Fri Jun 5 19:15:04 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
d0ba1cea 1/* Print mips instructions for GDB, the GNU debugger, or for objdump.
1124a4a7 2 Copyright (c) 1989, 91-97, 1998 Free Software Foundation, Inc.
d0ba1cea
ILT
3 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
4
8d67dc30 5This file is part of GDB, GAS, and the GNU binutils.
d0ba1cea
ILT
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
30b1724c 19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
d0ba1cea 20
5d0734a7 21#include <ansidecl.h>
d0ba1cea 22#include "sysdep.h"
5d0734a7 23#include "dis-asm.h"
d0ba1cea 24#include "opcode/mips.h"
1124a4a7 25#include "opintl.h"
d0ba1cea 26
8d67dc30
ILT
27/* FIXME: These are needed to figure out if this is a mips16 symbol or
28 not. It would be better to think of a cleaner way to do this. */
29#include "elf-bfd.h"
30#include "elf/mips.h"
31
32static int print_insn_mips16 PARAMS ((bfd_vma, struct disassemble_info *));
33static void print_mips16_insn_arg
34 PARAMS ((int, const struct mips_opcode *, int, boolean, int, bfd_vma,
35 struct disassemble_info *));
36
d0ba1cea
ILT
37/* Mips instructions are never longer than this many bytes. */
38#define MAXLEN 4
8d67dc30
ILT
39
40static void print_insn_arg PARAMS ((const char *, unsigned long, bfd_vma,
41 struct disassemble_info *));
42static int _print_insn_mips PARAMS ((bfd_vma, unsigned long int,
43 struct disassemble_info *));
44
d0ba1cea
ILT
45\f
46/* FIXME: This should be shared with gdb somehow. */
47#define REGISTER_NAMES \
48 { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
49 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
50 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
51 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
52 "sr", "lo", "hi", "bad", "cause","pc", \
53 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
54 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
55 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
56 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
57 "fsr", "fir", "fp", "inx", "rand", "tlblo","ctxt", "tlbhi",\
58 "epc", "prid"\
59 }
60
61static CONST char * CONST reg_names[] = REGISTER_NAMES;
8d67dc30
ILT
62
63/* The mips16 register names. */
64static const char * const mips16_reg_names[] =
65{
66 "s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3"
67};
d0ba1cea
ILT
68\f
69/* subroutine */
5d0734a7
JK
70static void
71print_insn_arg (d, l, pc, info)
547998d2 72 const char *d;
5d0734a7 73 register unsigned long int l;
d0ba1cea 74 bfd_vma pc;
5d0734a7 75 struct disassemble_info *info;
d0ba1cea 76{
fde326fb
ILT
77 int delta;
78
d0ba1cea
ILT
79 switch (*d)
80 {
81 case ',':
82 case '(':
83 case ')':
83af2335
JL
84 /* start-sanitize-vr5400 */
85 case '[':
86 case ']':
87 /* end-sanitize-vr5400 */
ffee80df
JL
88 /* start-sanitize-r5900 */
89 case '+':
90 case '-':
1124a4a7 91 /* end-sanitize-r5900 */
5d0734a7 92 (*info->fprintf_func) (info->stream, "%c", *d);
d0ba1cea
ILT
93 break;
94
95 case 's':
fde326fb
ILT
96 case 'b':
97 case 'r':
98 case 'v':
5d0734a7
JK
99 (*info->fprintf_func) (info->stream, "$%s",
100 reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
d0ba1cea
ILT
101 break;
102
103 case 't':
fde326fb 104 case 'w':
5d0734a7
JK
105 (*info->fprintf_func) (info->stream, "$%s",
106 reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
d0ba1cea
ILT
107 break;
108
109 case 'i':
fde326fb 110 case 'u':
30b1724c 111 (*info->fprintf_func) (info->stream, "0x%x",
5d0734a7 112 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
d0ba1cea
ILT
113 break;
114
115 case 'j': /* same as i, but sign-extended */
fde326fb
ILT
116 case 'o':
117 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
118 if (delta & 0x8000)
119 delta |= ~0xffff;
5d0734a7 120 (*info->fprintf_func) (info->stream, "%d",
fde326fb 121 delta);
d0ba1cea
ILT
122 break;
123
30b1724c
ILT
124 case 'h':
125 (*info->fprintf_func) (info->stream, "0x%x",
126 (unsigned int) ((l >> OP_SH_PREFX)
127 & OP_MASK_PREFX));
128 break;
129
130 case 'k':
131 (*info->fprintf_func) (info->stream, "0x%x",
132 (unsigned int) ((l >> OP_SH_CACHE)
133 & OP_MASK_CACHE));
134 break;
135
d0ba1cea 136 case 'a':
fde326fb
ILT
137 (*info->print_address_func)
138 (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
139 info);
d0ba1cea
ILT
140 break;
141
fde326fb
ILT
142 case 'p':
143 /* sign extend the displacement */
144 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
145 if (delta & 0x8000)
146 delta |= ~0xffff;
147 (*info->print_address_func)
148 ((delta << 2) + pc + 4,
149 info);
d0ba1cea
ILT
150 break;
151
152 case 'd':
5d0734a7
JK
153 (*info->fprintf_func) (info->stream, "$%s",
154 reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
d0ba1cea
ILT
155 break;
156
547998d2
ILT
157 case 'z':
158 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
159 break;
160
fde326fb 161 case '<':
5d0734a7
JK
162 (*info->fprintf_func) (info->stream, "0x%x",
163 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
d0ba1cea
ILT
164 break;
165
fde326fb 166 case 'c':
5d0734a7
JK
167 (*info->fprintf_func) (info->stream, "0x%x",
168 (l >> OP_SH_CODE) & OP_MASK_CODE);
d0ba1cea
ILT
169 break;
170
1124a4a7
JL
171
172 case 'q':
173 (*info->fprintf_func) (info->stream, "0x%x",
174 (l >> OP_SH_CODE2) & OP_MASK_CODE2);
175 break;
176
fde326fb
ILT
177 case 'C':
178 (*info->fprintf_func) (info->stream, "0x%x",
179 (l >> OP_SH_COPZ) & OP_MASK_COPZ);
180 break;
181
182 case 'B':
183 (*info->fprintf_func) (info->stream, "0x%x",
184 (l >> OP_SH_SYSCALL) & OP_MASK_SYSCALL);
185 break;
186
d0ba1cea 187 case 'S':
fde326fb 188 case 'V':
5d0734a7
JK
189 (*info->fprintf_func) (info->stream, "$f%d",
190 (l >> OP_SH_FS) & OP_MASK_FS);
d0ba1cea
ILT
191 break;
192
92976c09 193 /* start-sanitize-r5900 */
ffee80df
JL
194 case '0':
195 (*info->fprintf_func) (info->stream, "0x%x",
196 (l >> 6) & 0x1f);
197 break;
198
199 case '9':
92976c09 200 (*info->fprintf_func) (info->stream, "vi27");
ffee80df
JL
201 break;
202
203 case '1':
204 (*info->fprintf_func) (info->stream, "vf%d",
205 (l >> OP_SH_FT) & OP_MASK_FT);
206 break;
207 case '2':
208 (*info->fprintf_func) (info->stream, "vf%d",
209 (l >> OP_SH_FS) & OP_MASK_FS);
210 break;
211 case '3':
212 (*info->fprintf_func) (info->stream, "vf%d",
213 (l >> OP_SH_FD) & OP_MASK_FD);
214 break;
215
216 case '4':
217 (*info->fprintf_func) (info->stream, "vi%d",
218 (l >> OP_SH_FT) & OP_MASK_FT);
219 break;
220 case '5':
221 (*info->fprintf_func) (info->stream, "vi%d",
222 (l >> OP_SH_FS) & OP_MASK_FS);
223 break;
224 case '6':
225 (*info->fprintf_func) (info->stream, "vi%d",
226 (l >> OP_SH_FD) & OP_MASK_FD);
227 break;
228
229 case '7':
230 (*info->fprintf_func) (info->stream, "vf%d",
231 (l >> OP_SH_FT) & OP_MASK_FT);
232 switch ((l >> 23) & 0x3)
233 {
234 case 0:
235 (*info->fprintf_func) (info->stream, "x");
236 break;
237 case 1:
238 (*info->fprintf_func) (info->stream, "y");
239 break;
240 case 2:
241 (*info->fprintf_func) (info->stream, "z");
242 break;
243 case 3:
244 (*info->fprintf_func) (info->stream, "w");
245 break;
246 }
247 break;
248 case 'K':
249 break;
250
1124a4a7
JL
251 case ';':
252 (*info->fprintf_func) (info->stream, ".xyz\t");
253 break;
254
ffee80df
JL
255 case '&':
256 (*info->fprintf_func) (info->stream, ".");
257 if (l & (1 << 21))
258 (*info->fprintf_func) (info->stream, "w");
259 if (l & (1 << 24))
260 (*info->fprintf_func) (info->stream, "x");
261 if (l & (1 << 23))
262 (*info->fprintf_func) (info->stream, "y");
263 if (l & (1 << 22))
264 (*info->fprintf_func) (info->stream, "z");
265 (*info->fprintf_func) (info->stream, "\t");
266 break;
267
268 case '8':
269 (*info->fprintf_func) (info->stream, "vf%d",
270 (l >> OP_SH_FS) & OP_MASK_FS);
271 switch ((l >> 21) & 0x3)
272 {
273 case 0:
274 (*info->fprintf_func) (info->stream, "x");
275 break;
276 case 1:
277 (*info->fprintf_func) (info->stream, "y");
278 break;
279 case 2:
280 (*info->fprintf_func) (info->stream, "z");
281 break;
282 case 3:
283 (*info->fprintf_func) (info->stream, "w");
284 break;
285 }
286 break;
287 case 'J':
288 (*info->fprintf_func) (info->stream, "I");
289 break;
290
291 case 'Q':
292 (*info->fprintf_func) (info->stream, "Q");
293 break;
294
295 case 'X':
296 (*info->fprintf_func) (info->stream, "R");
297 break;
298
299 case 'U':
300 (*info->fprintf_func) (info->stream, "ACC");
301 break;
98f699f6
JL
302
303 case 'O':
304 delta = (l >> 6) & 0x7fff;
305 delta <<= 3;
306 (*info->print_address_func) (delta, info);
307 break;
308
ffee80df
JL
309 /* end-sanitize-r5900 */
310
d0ba1cea 311 case 'T':
fde326fb 312 case 'W':
5d0734a7
JK
313 (*info->fprintf_func) (info->stream, "$f%d",
314 (l >> OP_SH_FT) & OP_MASK_FT);
d0ba1cea
ILT
315 break;
316
317 case 'D':
5d0734a7
JK
318 (*info->fprintf_func) (info->stream, "$f%d",
319 (l >> OP_SH_FD) & OP_MASK_FD);
d0ba1cea
ILT
320 break;
321
30b1724c
ILT
322 case 'R':
323 (*info->fprintf_func) (info->stream, "$f%d",
324 (l >> OP_SH_FR) & OP_MASK_FR);
325 break;
326
fde326fb
ILT
327 case 'E':
328 (*info->fprintf_func) (info->stream, "$%d",
329 (l >> OP_SH_RT) & OP_MASK_RT);
330 break;
331
332 case 'G':
333 (*info->fprintf_func) (info->stream, "$%d",
334 (l >> OP_SH_RD) & OP_MASK_RD);
335 break;
336
30b1724c
ILT
337 case 'N':
338 (*info->fprintf_func) (info->stream, "$fcc%d",
339 (l >> OP_SH_BCC) & OP_MASK_BCC);
340 break;
341
342 case 'M':
343 (*info->fprintf_func) (info->stream, "$fcc%d",
344 (l >> OP_SH_CCC) & OP_MASK_CCC);
345 break;
346
83af2335 347 case 'P':
fb1a826b 348 (*info->fprintf_func) (info->stream, "%d",
83af2335
JL
349 (l >> OP_SH_PERFREG) & OP_MASK_PERFREG);
350 break;
351
352 /* start-sanitize-vr5400 */
353 case 'e':
354 (*info->fprintf_func) (info->stream, "%d",
355 (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE);
356 break;
357
358 case '%':
359 (*info->fprintf_func) (info->stream, "%d",
360 (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN);
361 break;
362 /* end-sanitize-vr5400 */
363
d0ba1cea 364 default:
1124a4a7 365 /* xgettext:c-format */
5d0734a7 366 (*info->fprintf_func) (info->stream,
1124a4a7
JL
367 _("# internal error, undefined modifier(%c)"),
368 *d);
d0ba1cea
ILT
369 break;
370 }
371}
372\f
373/* Print the mips instruction at address MEMADDR in debugged memory,
5d0734a7 374 on using INFO. Returns length of the instruction, in bytes, which is
d0ba1cea
ILT
375 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
376 this is little-endian code. */
377
30b1724c 378static int
5d0734a7 379_print_insn_mips (memaddr, word, info)
d0ba1cea 380 bfd_vma memaddr;
5d0734a7 381 unsigned long int word;
8d67dc30 382 struct disassemble_info *info;
d0ba1cea 383{
30b1724c 384 register const struct mips_opcode *op;
83af2335 385 int target_processor, mips_isa;
30b1724c
ILT
386 static boolean init = 0;
387 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
d0ba1cea 388
30b1724c
ILT
389 /* Build a hash table to shorten the search time. */
390 if (! init)
d0ba1cea 391 {
30b1724c
ILT
392 unsigned int i;
393
394 for (i = 0; i <= OP_MASK_OP; i++)
fde326fb 395 {
30b1724c
ILT
396 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
397 {
398 if (op->pinfo == INSN_MACRO)
399 continue;
400 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
401 {
402 mips_hash[i] = op;
403 break;
404 }
405 }
406 }
407
408 init = 1;
d0ba1cea
ILT
409 }
410
83af2335
JL
411 switch (info->mach)
412 {
413 /* start-sanitize-tx19 */
414 case bfd_mach_mips1900:
415 target_processor = 1900;
416 mips_isa = 1;
417 break;
418 /* end-sanitize-tx19 */
419 case bfd_mach_mips3000:
420 target_processor = 3000;
421 mips_isa = 1;
422 break;
423 case bfd_mach_mips3900:
424 target_processor = 3900;
425 mips_isa = 1;
426 break;
427 case bfd_mach_mips4000:
428 target_processor = 4000;
429 mips_isa = 3;
430 break;
431 case bfd_mach_mips4010:
432 target_processor = 4010;
433 mips_isa = 2;
434 break;
435 case bfd_mach_mips4100:
436 target_processor = 4100;
437 mips_isa = 3;
438 break;
439 case bfd_mach_mips4300:
440 target_processor = 4300;
441 mips_isa = 3;
442 break;
ffee80df
JL
443 /* start-sanitize-vr4320 */
444 case bfd_mach_mips4320:
445 target_processor = 4320;
446 mips_isa = 3;
447 break;
448 /* end-sanitize-vr4320 */
83af2335
JL
449 case bfd_mach_mips4400:
450 target_processor = 4400;
451 mips_isa = 3;
452 break;
453 case bfd_mach_mips4600:
454 target_processor = 4600;
455 mips_isa = 3;
456 break;
457 case bfd_mach_mips4650:
458 target_processor = 4650;
459 mips_isa = 3;
460 break;
461 /* start-sanitize-tx49 */
462 case bfd_mach_mips4900:
463 target_processor = 4900;
464 mips_isa = 3;
465 break;
466 /* end-sanitize-tx49 */
467 case bfd_mach_mips5000:
468 target_processor = 5000;
469 mips_isa = 4;
470 break;
471 /* start-sanitize-vr5400 */
472 case bfd_mach_mips5400:
473 target_processor = 5400;
474 mips_isa = 3;
475 break;
476 /* end-sanitize-vr5400 */
477 /* start-sanitize-r5900 */
478 case bfd_mach_mips5900:
479 target_processor = 5900;
480 mips_isa = 3;
481 break;
482 /* end-sanitize-r5900 */
483 case bfd_mach_mips6000:
484 target_processor = 6000;
485 mips_isa = 2;
486 break;
487 case bfd_mach_mips8000:
488 target_processor = 8000;
489 mips_isa = 4;
490 break;
491 case bfd_mach_mips10000:
492 target_processor = 10000;
493 mips_isa = 4;
494 break;
495 case bfd_mach_mips16:
496 target_processor = 16;
497 mips_isa = 3;
498 break;
499 default:
500 target_processor = 3000;
501 mips_isa = 3;
502 break;
503
504 }
505
2ea116f4
ILT
506 info->bytes_per_chunk = 4;
507 info->display_endian = info->endian;
508
30b1724c
ILT
509 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
510 if (op != NULL)
d0ba1cea 511 {
30b1724c
ILT
512 for (; op < &mips_opcodes[NUMOPCODES]; op++)
513 {
514 if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
515 {
516 register const char *d;
83af2335
JL
517 int insn_isa;
518
519 if ((op->membership & INSN_ISA) == INSN_ISA1)
520 insn_isa = 1;
521 else if ((op->membership & INSN_ISA) == INSN_ISA2)
522 insn_isa = 2;
523 else if ((op->membership & INSN_ISA) == INSN_ISA3)
524 insn_isa = 3;
525 else if ((op->membership & INSN_ISA) == INSN_ISA4)
526 insn_isa = 4;
527 else
528 insn_isa = 15;
529
530 if (insn_isa > mips_isa
531 && (target_processor == 4650
532 && op->membership & INSN_4650) == 0
533 && (target_processor == 4010
534 && op->membership & INSN_4010) == 0
535 && (target_processor == 4100
536 && op->membership & INSN_4100) == 0
ffee80df
JL
537 /* start-sanitize-vr4320 */
538 && (target_processor == 4320
539 && op->membership & INSN_4320) == 0
540 /* end-sanitize-vr4320 */
83af2335
JL
541 /* start-sanitize-vr5400 */
542 && (target_processor == 5400
543 && op->membership & INSN_5400) == 0
fb1a826b 544 /* end-sanitize-vr5400 */
83af2335
JL
545 /* start-sanitize-r5900 */
546 && (target_processor == 5900
547 && op->membership & INSN_5900) == 0
548 /* end-sanitize-r5900 */
549 /* start-sanitize-tx49 */
550 && (target_processor == 4900
551 && op->membership & INSN_4900) == 0
552 /* end-sanitize-tx49 */
553 && (target_processor == 3900
554 && op->membership & INSN_3900) == 0)
555 continue;
30b1724c
ILT
556
557 (*info->fprintf_func) (info->stream, "%s", op->name);
558
559 d = op->args;
8d67dc30 560 if (d != NULL && *d != '\0')
30b1724c 561 {
ffee80df
JL
562 /* start-sanitize-r5900 */
563 /* If this is an opcode completer, then do not emit
564 a tab after the opcode. */
1124a4a7 565 if (*d != '&' && *d != ';')
ffee80df
JL
566 /* end-sanitize-r5900 */
567 (*info->fprintf_func) (info->stream, "\t");
30b1724c 568 for (; *d != '\0'; d++)
ffee80df
JL
569 /* start-sanitize-r5900 */
570 /* If this is an escape character, go ahead and print the
571 next character in the arg string verbatim. */
98f699f6 572 if (*d == '#')
ffee80df
JL
573 {
574 d++;
575 (*info->fprintf_func) (info->stream, "%c", *d);
576 }
577 else
578 /* end-sanitize-r5900 */
579 print_insn_arg (d, word, memaddr, info);
30b1724c
ILT
580 }
581
582 return 4;
583 }
584 }
d0ba1cea
ILT
585 }
586
30b1724c
ILT
587 /* Handle undefined instructions. */
588 (*info->fprintf_func) (info->stream, "0x%x", word);
d0ba1cea
ILT
589 return 4;
590}
5d0734a7
JK
591
592int
593print_insn_big_mips (memaddr, info)
594 bfd_vma memaddr;
595 struct disassemble_info *info;
596{
597 bfd_byte buffer[4];
8d67dc30
ILT
598 int status;
599
600 if (info->mach == 16
601 || (info->flavour == bfd_target_elf_flavour
88b38f0c
DE
602 && info->symbols != NULL
603 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
8d67dc30
ILT
604 == STO_MIPS16)))
605 return print_insn_mips16 (memaddr, info);
606
607 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 608 if (status == 0)
8d67dc30
ILT
609 return _print_insn_mips (memaddr, (unsigned long) bfd_getb32 (buffer),
610 info);
5d0734a7
JK
611 else
612 {
613 (*info->memory_error_func) (status, memaddr, info);
614 return -1;
615 }
616}
617
618int
619print_insn_little_mips (memaddr, info)
620 bfd_vma memaddr;
621 struct disassemble_info *info;
622{
623 bfd_byte buffer[4];
8d67dc30
ILT
624 int status;
625
37130f11
DE
626 /* start-sanitize-sky */
627#ifdef ARCH_dvp
88b38f0c
DE
628 {
629 /* bfd_mach_dvp_p is a macro which may evaluate its arguments more than
630 once. Since dvp_mach_type is a function, ensure it's only called
631 once. */
632 int mach = dvp_info_mach_type (info);
633
634 if (bfd_mach_dvp_p (info->mach)
635 || bfd_mach_dvp_p (mach))
636 return print_insn_dvp (memaddr, info);
637 }
37130f11
DE
638#endif
639 /* end-sanitize-sky */
640
8d67dc30
ILT
641 if (info->mach == 16
642 || (info->flavour == bfd_target_elf_flavour
88b38f0c
DE
643 && info->symbols != NULL
644 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
8d67dc30
ILT
645 == STO_MIPS16)))
646 return print_insn_mips16 (memaddr, info);
647
648 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 649 if (status == 0)
8d67dc30
ILT
650 return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer),
651 info);
5d0734a7
JK
652 else
653 {
654 (*info->memory_error_func) (status, memaddr, info);
655 return -1;
656 }
657}
8d67dc30
ILT
658\f
659/* Disassemble mips16 instructions. */
660
661static int
662print_insn_mips16 (memaddr, info)
663 bfd_vma memaddr;
664 struct disassemble_info *info;
665{
666 int status;
667 bfd_byte buffer[2];
668 int length;
669 int insn;
670 boolean use_extend;
92976c09 671 int extend = 0;
8d67dc30
ILT
672 const struct mips_opcode *op, *opend;
673
2ea116f4
ILT
674 info->bytes_per_chunk = 2;
675 info->display_endian = info->endian;
676
20d43018
ILT
677 info->insn_info_valid = 1;
678 info->branch_delay_insns = 0;
679 info->data_size = 0;
680 info->insn_type = dis_nonbranch;
681 info->target = 0;
682 info->target2 = 0;
683
8d67dc30
ILT
684 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
685 if (status != 0)
686 {
687 (*info->memory_error_func) (status, memaddr, info);
688 return -1;
689 }
690
691 length = 2;
692
693 if (info->endian == BFD_ENDIAN_BIG)
694 insn = bfd_getb16 (buffer);
695 else
696 insn = bfd_getl16 (buffer);
697
698 /* Handle the extend opcode specially. */
699 use_extend = false;
700 if ((insn & 0xf800) == 0xf000)
701 {
702 use_extend = true;
703 extend = insn & 0x7ff;
704
705 memaddr += 2;
706
707 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
708 if (status != 0)
709 {
710 (*info->fprintf_func) (info->stream, "extend 0x%x",
711 (unsigned int) extend);
712 (*info->memory_error_func) (status, memaddr, info);
713 return -1;
714 }
715
8d67dc30
ILT
716 if (info->endian == BFD_ENDIAN_BIG)
717 insn = bfd_getb16 (buffer);
718 else
719 insn = bfd_getl16 (buffer);
c4f19df2
ILT
720
721 /* Check for an extend opcode followed by an extend opcode. */
722 if ((insn & 0xf800) == 0xf000)
723 {
724 (*info->fprintf_func) (info->stream, "extend 0x%x",
725 (unsigned int) extend);
20d43018 726 info->insn_type = dis_noninsn;
c4f19df2
ILT
727 return length;
728 }
729
730 length += 2;
8d67dc30
ILT
731 }
732
733 /* FIXME: Should probably use a hash table on the major opcode here. */
734
735 opend = mips16_opcodes + bfd_mips16_num_opcodes;
736 for (op = mips16_opcodes; op < opend; op++)
737 {
738 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
739 {
740 const char *s;
741
742 if (strchr (op->args, 'a') != NULL)
743 {
744 if (use_extend)
c4f19df2
ILT
745 {
746 (*info->fprintf_func) (info->stream, "extend 0x%x",
747 (unsigned int) extend);
20d43018 748 info->insn_type = dis_noninsn;
c4f19df2
ILT
749 return length - 2;
750 }
751
8d67dc30
ILT
752 use_extend = false;
753
754 memaddr += 2;
755
756 status = (*info->read_memory_func) (memaddr, buffer, 2,
757 info);
758 if (status == 0)
759 {
760 use_extend = true;
761 if (info->endian == BFD_ENDIAN_BIG)
762 extend = bfd_getb16 (buffer);
763 else
764 extend = bfd_getl16 (buffer);
765 length += 2;
766 }
767 }
768
c4f19df2
ILT
769 (*info->fprintf_func) (info->stream, "%s", op->name);
770 if (op->args[0] != '\0')
771 (*info->fprintf_func) (info->stream, "\t");
8d67dc30
ILT
772
773 for (s = op->args; *s != '\0'; s++)
774 {
775 if (*s == ','
776 && s[1] == 'w'
777 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
778 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
779 {
780 /* Skip the register and the comma. */
781 ++s;
782 continue;
783 }
784 if (*s == ','
785 && s[1] == 'v'
786 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
787 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
788 {
789 /* Skip the register and the comma. */
790 ++s;
791 continue;
792 }
793 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
794 info);
795 }
796
20d43018
ILT
797 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
798 {
799 info->branch_delay_insns = 1;
800 if (info->insn_type != dis_jsr)
801 info->insn_type = dis_branch;
802 }
803
8d67dc30
ILT
804 return length;
805 }
806 }
807
808 if (use_extend)
809 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
810 (*info->fprintf_func) (info->stream, "0x%x", insn);
20d43018 811 info->insn_type = dis_noninsn;
8d67dc30
ILT
812
813 return length;
814}
815
816/* Disassemble an operand for a mips16 instruction. */
817
818static void
819print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
820 int type;
821 const struct mips_opcode *op;
822 int l;
823 boolean use_extend;
824 int extend;
825 bfd_vma memaddr;
826 struct disassemble_info *info;
827{
828 switch (type)
829 {
830 case ',':
831 case '(':
832 case ')':
833 (*info->fprintf_func) (info->stream, "%c", type);
834 break;
835
836 case 'y':
837 case 'w':
838 (*info->fprintf_func) (info->stream, "$%s",
839 mips16_reg_names[((l >> MIPS16OP_SH_RY)
840 & MIPS16OP_MASK_RY)]);
841 break;
842
843 case 'x':
844 case 'v':
845 (*info->fprintf_func) (info->stream, "$%s",
846 mips16_reg_names[((l >> MIPS16OP_SH_RX)
847 & MIPS16OP_MASK_RX)]);
848 break;
849
850 case 'z':
851 (*info->fprintf_func) (info->stream, "$%s",
852 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
853 & MIPS16OP_MASK_RZ)]);
854 break;
855
856 case 'Z':
857 (*info->fprintf_func) (info->stream, "$%s",
858 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
859 & MIPS16OP_MASK_MOVE32Z)]);
860 break;
861
862 case '0':
863 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
864 break;
865
866 case 'S':
867 (*info->fprintf_func) (info->stream, "$%s", reg_names[29]);
868 break;
869
870 case 'P':
871 (*info->fprintf_func) (info->stream, "$pc");
872 break;
873
874 case 'R':
875 (*info->fprintf_func) (info->stream, "$%s", reg_names[31]);
876 break;
877
878 case 'X':
879 (*info->fprintf_func) (info->stream, "$%s",
880 reg_names[((l >> MIPS16OP_SH_REGR32)
881 & MIPS16OP_MASK_REGR32)]);
882 break;
883
884 case 'Y':
885 (*info->fprintf_func) (info->stream, "$%s",
886 reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
887 break;
888
889 case '<':
890 case '>':
891 case '[':
892 case ']':
893 case '4':
894 case '5':
895 case 'H':
896 case 'W':
897 case 'D':
898 case 'j':
899 case '6':
900 case '8':
901 case 'V':
902 case 'C':
903 case 'U':
904 case 'k':
905 case 'K':
906 case 'p':
907 case 'q':
908 case 'A':
909 case 'B':
910 case 'E':
911 {
912 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
913
914 shift = 0;
915 signedp = 0;
916 extbits = 16;
917 pcrel = 0;
918 extu = 0;
919 branch = 0;
920 switch (type)
921 {
922 case '<':
923 nbits = 3;
924 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
925 extbits = 5;
926 extu = 1;
927 break;
928 case '>':
929 nbits = 3;
930 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
931 extbits = 5;
932 extu = 1;
933 break;
934 case '[':
935 nbits = 3;
936 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
937 extbits = 6;
938 extu = 1;
939 break;
940 case ']':
941 nbits = 3;
942 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
943 extbits = 6;
944 extu = 1;
945 break;
946 case '4':
947 nbits = 4;
948 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
949 signedp = 1;
950 extbits = 15;
951 break;
952 case '5':
953 nbits = 5;
954 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
955 info->insn_type = dis_dref;
956 info->data_size = 1;
8d67dc30
ILT
957 break;
958 case 'H':
959 nbits = 5;
960 shift = 1;
961 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
962 info->insn_type = dis_dref;
963 info->data_size = 2;
8d67dc30
ILT
964 break;
965 case 'W':
966 nbits = 5;
967 shift = 2;
968 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
969 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
970 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
971 {
972 info->insn_type = dis_dref;
973 info->data_size = 4;
974 }
8d67dc30
ILT
975 break;
976 case 'D':
977 nbits = 5;
978 shift = 3;
979 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
980 info->insn_type = dis_dref;
981 info->data_size = 8;
8d67dc30
ILT
982 break;
983 case 'j':
984 nbits = 5;
985 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
986 signedp = 1;
987 break;
988 case '6':
989 nbits = 6;
990 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
991 break;
992 case '8':
993 nbits = 8;
994 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
995 break;
996 case 'V':
997 nbits = 8;
998 shift = 2;
999 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
1000 /* FIXME: This might be lw, or it might be addiu to $sp or
1001 $pc. We assume it's load. */
1002 info->insn_type = dis_dref;
1003 info->data_size = 4;
8d67dc30
ILT
1004 break;
1005 case 'C':
1006 nbits = 8;
1007 shift = 3;
1008 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
1009 info->insn_type = dis_dref;
1010 info->data_size = 8;
8d67dc30
ILT
1011 break;
1012 case 'U':
1013 nbits = 8;
1014 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1015 extu = 1;
1016 break;
1017 case 'k':
1018 nbits = 8;
1019 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1020 signedp = 1;
1021 break;
1022 case 'K':
1023 nbits = 8;
1024 shift = 3;
1025 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1026 signedp = 1;
1027 break;
1028 case 'p':
1029 nbits = 8;
1030 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1031 signedp = 1;
1032 pcrel = 1;
1033 branch = 1;
20d43018 1034 info->insn_type = dis_condbranch;
8d67dc30
ILT
1035 break;
1036 case 'q':
1037 nbits = 11;
1038 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
1039 signedp = 1;
1040 pcrel = 1;
1041 branch = 1;
20d43018 1042 info->insn_type = dis_branch;
8d67dc30
ILT
1043 break;
1044 case 'A':
1045 nbits = 8;
1046 shift = 2;
1047 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1048 pcrel = 1;
20d43018
ILT
1049 /* FIXME: This can be lw or la. We assume it is lw. */
1050 info->insn_type = dis_dref;
1051 info->data_size = 4;
8d67dc30
ILT
1052 break;
1053 case 'B':
1054 nbits = 5;
1055 shift = 3;
1056 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1057 pcrel = 1;
20d43018
ILT
1058 info->insn_type = dis_dref;
1059 info->data_size = 8;
8d67dc30
ILT
1060 break;
1061 case 'E':
1062 nbits = 5;
1063 shift = 2;
1064 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1065 pcrel = 1;
1066 break;
1067 default:
1068 abort ();
1069 }
1070
1071 if (! use_extend)
1072 {
1073 if (signedp && immed >= (1 << (nbits - 1)))
1074 immed -= 1 << nbits;
1075 immed <<= shift;
1076 if ((type == '<' || type == '>' || type == '[' || type == '[')
1077 && immed == 0)
1078 immed = 8;
1079 }
1080 else
1081 {
1082 if (extbits == 16)
1083 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
1084 else if (extbits == 15)
1085 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
1086 else
1087 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
1088 immed &= (1 << extbits) - 1;
1089 if (! extu && immed >= (1 << (extbits - 1)))
1090 immed -= 1 << extbits;
1091 }
1092
1093 if (! pcrel)
1094 (*info->fprintf_func) (info->stream, "%d", immed);
1095 else
1096 {
c4f19df2 1097 bfd_vma baseaddr;
8d67dc30
ILT
1098 bfd_vma val;
1099
1100 if (branch)
c4f19df2
ILT
1101 {
1102 immed *= 2;
1103 baseaddr = memaddr + 2;
1104 }
1105 else if (use_extend)
83af2335 1106 baseaddr = memaddr - 2;
c4f19df2
ILT
1107 else
1108 {
1109 int status;
1110 bfd_byte buffer[2];
1111
1112 baseaddr = memaddr;
1113
1114 /* If this instruction is in the delay slot of a jr
1115 instruction, the base address is the address of the
1116 jr instruction. If it is in the delay slot of jalr
1117 instruction, the base address is the address of the
1118 jalr instruction. This test is unreliable: we have
1119 no way of knowing whether the previous word is
1120 instruction or data. */
1121 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
1122 info);
1123 if (status == 0
1124 && (((info->endian == BFD_ENDIAN_BIG
1125 ? bfd_getb16 (buffer)
1126 : bfd_getl16 (buffer))
1127 & 0xf800) == 0x1800))
1128 baseaddr = memaddr - 4;
1129 else
1130 {
1131 status = (*info->read_memory_func) (memaddr - 2, buffer,
1132 2, info);
1133 if (status == 0
1134 && (((info->endian == BFD_ENDIAN_BIG
1135 ? bfd_getb16 (buffer)
1136 : bfd_getl16 (buffer))
1137 & 0xf81f) == 0xe800))
1138 baseaddr = memaddr - 2;
1139 }
1140 }
1141 val = (baseaddr & ~ ((1 << shift) - 1)) + immed;
8d67dc30 1142 (*info->print_address_func) (val, info);
20d43018 1143 info->target = val;
8d67dc30
ILT
1144 }
1145 }
1146 break;
1147
1148 case 'a':
1149 if (! use_extend)
1150 extend = 0;
1151 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
1152 (*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
20d43018
ILT
1153 info->insn_type = dis_jsr;
1154 info->target = (memaddr & 0xf0000000) | l;
1155 info->branch_delay_insns = 1;
8d67dc30
ILT
1156 break;
1157
1158 case 'l':
1159 case 'L':
1160 {
1161 int need_comma, amask, smask;
1162
1163 need_comma = 0;
1164
1165 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1166
1167 amask = (l >> 3) & 7;
0d52464c
ILT
1168
1169 if (amask > 0 && amask < 5)
8d67dc30 1170 {
0d52464c 1171 (*info->fprintf_func) (info->stream, "$%s", reg_names[4]);
8d67dc30 1172 if (amask > 1)
0d52464c 1173 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
1174 reg_names[amask + 3]);
1175 need_comma = 1;
1176 }
1177
1178 smask = (l >> 1) & 3;
1179 if (smask == 3)
1180 {
1181 (*info->fprintf_func) (info->stream, "%s??",
1182 need_comma ? "," : "");
1183 need_comma = 1;
1184 }
1185 else if (smask > 0)
1186 {
0d52464c 1187 (*info->fprintf_func) (info->stream, "%s$%s",
8d67dc30
ILT
1188 need_comma ? "," : "",
1189 reg_names[16]);
1190 if (smask > 1)
0d52464c 1191 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
1192 reg_names[smask + 15]);
1193 need_comma = 1;
1194 }
1195
1196 if (l & 1)
0d52464c
ILT
1197 {
1198 (*info->fprintf_func) (info->stream, "%s$%s",
1199 need_comma ? "," : "",
1200 reg_names[31]);
1201 need_comma = 1;
1202 }
1203
1204 if (amask == 5 || amask == 6)
1205 {
1206 (*info->fprintf_func) (info->stream, "%s$f0",
1207 need_comma ? "," : "");
1208 if (amask == 6)
1209 (*info->fprintf_func) (info->stream, "-$f1");
1210 }
8d67dc30
ILT
1211 }
1212 break;
1213
1214 default:
1215 abort ();
1216 }
1217}
This page took 0.250671 seconds and 4 git commands to generate.