2002-03-15 Chris Demetriou <cgd@broadcom.com>
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
1 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2 Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2000, 2001
4 Free Software Foundation, Inc.
5 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
6
7 This file is part of GDB, GAS, and the GNU binutils.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22
23 #include "sysdep.h"
24 #include "dis-asm.h"
25 #include "opcode/mips.h"
26 #include "opintl.h"
27
28 /* FIXME: These are needed to figure out if the code is mips16 or
29 not. The low bit of the address is often a good indicator. No
30 symbol table is available when this code runs out in an embedded
31 system as when it is used for disassembler support in a monitor. */
32
33 #if !defined(EMBEDDED_ENV)
34 #define SYMTAB_AVAILABLE 1
35 #include "elf-bfd.h"
36 #include "elf/mips.h"
37 #endif
38
39 /* Mips instructions are at maximum this many bytes long. */
40 #define INSNLEN 4
41
42 static int _print_insn_mips
43 PARAMS ((bfd_vma, struct disassemble_info *, enum bfd_endian));
44 static int print_insn_mips
45 PARAMS ((bfd_vma, unsigned long int, struct disassemble_info *));
46 static void print_insn_arg
47 PARAMS ((const char *, unsigned long, bfd_vma, struct disassemble_info *));
48 static void mips_isa_type
49 PARAMS ((int, int *, int *));
50 static int print_insn_mips16
51 PARAMS ((bfd_vma, struct disassemble_info *));
52 static int is_newabi
53 PARAMS ((Elf_Internal_Ehdr *));
54 static void print_mips16_insn_arg
55 PARAMS ((int, const struct mips_opcode *, int, boolean, int, bfd_vma,
56 struct disassemble_info *));
57 \f
58 /* FIXME: These should be shared with gdb somehow. */
59
60 /* The mips16 register names. */
61 static const char * const mips16_reg_names[] = {
62 "s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3"
63 };
64
65 static const char * const mips32_reg_names[] = {
66 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
67 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
68 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
69 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
70 "sr", "lo", "hi", "bad", "cause", "pc",
71 "fv0", "$f1", "fv1", "$f3", "ft0", "$f5", "ft1", "$f7",
72 "ft2", "$f9", "ft3", "$f11", "fa0", "$f13", "fa1", "$f15",
73 "ft4", "f17", "ft5", "f19", "fs0", "f21", "fs1", "f23",
74 "fs2", "$f25", "fs3", "$f27", "fs4", "$f29", "fs5", "$f31",
75 "fsr", "fir", "fp", "inx", "rand", "tlblo", "ctxt", "tlbhi",
76 "epc", "prid"
77 };
78
79 static const char * const mips64_reg_names[] = {
80 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
81 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
82 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
83 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
84 "sr", "lo", "hi", "bad", "cause", "pc",
85 "fv0", "$f1", "fv1", "$f3", "ft0", "ft1", "ft2", "ft3",
86 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
87 "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11",
88 "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
89 "fsr", "fir", "fp", "inx", "rand", "tlblo", "ctxt", "tlbhi",
90 "epc", "prid"
91 };
92
93 /* Scalar register names. _print_insn_mips() decides which register name
94 table to use. */
95 static const char * const *reg_names = NULL;
96 \f
97 /* Print insn arguments for 32/64-bit code. */
98
99 static void
100 print_insn_arg (d, l, pc, info)
101 const char *d;
102 register unsigned long int l;
103 bfd_vma pc;
104 struct disassemble_info *info;
105 {
106 int delta;
107
108 switch (*d)
109 {
110 case ',':
111 case '(':
112 case ')':
113 (*info->fprintf_func) (info->stream, "%c", *d);
114 break;
115
116 case 's':
117 case 'b':
118 case 'r':
119 case 'v':
120 (*info->fprintf_func) (info->stream, "%s",
121 reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
122 break;
123
124 case 't':
125 case 'w':
126 (*info->fprintf_func) (info->stream, "%s",
127 reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
128 break;
129
130 case 'i':
131 case 'u':
132 (*info->fprintf_func) (info->stream, "0x%x",
133 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
134 break;
135
136 case 'j': /* Same as i, but sign-extended. */
137 case 'o':
138 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
139 if (delta & 0x8000)
140 delta |= ~0xffff;
141 (*info->fprintf_func) (info->stream, "%d",
142 delta);
143 break;
144
145 case 'h':
146 (*info->fprintf_func) (info->stream, "0x%x",
147 (unsigned int) ((l >> OP_SH_PREFX)
148 & OP_MASK_PREFX));
149 break;
150
151 case 'k':
152 (*info->fprintf_func) (info->stream, "0x%x",
153 (unsigned int) ((l >> OP_SH_CACHE)
154 & OP_MASK_CACHE));
155 break;
156
157 case 'a':
158 info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
159 | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2));
160 (*info->print_address_func) (info->target, info);
161 break;
162
163 case 'p':
164 /* Sign extend the displacement. */
165 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
166 if (delta & 0x8000)
167 delta |= ~0xffff;
168 info->target = (delta << 2) + pc + INSNLEN;
169 (*info->print_address_func) (info->target, info);
170 break;
171
172 case 'd':
173 (*info->fprintf_func) (info->stream, "%s",
174 reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
175 break;
176
177 case 'U':
178 {
179 /* First check for both rd and rt being equal. */
180 unsigned int reg = (l >> OP_SH_RD) & OP_MASK_RD;
181 if (reg == ((l >> OP_SH_RT) & OP_MASK_RT))
182 (*info->fprintf_func) (info->stream, "%s",
183 reg_names[reg]);
184 else
185 {
186 /* If one is zero use the other. */
187 if (reg == 0)
188 (*info->fprintf_func) (info->stream, "%s",
189 reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
190 else if (((l >> OP_SH_RT) & OP_MASK_RT) == 0)
191 (*info->fprintf_func) (info->stream, "%s",
192 reg_names[reg]);
193 else /* Bogus, result depends on processor. */
194 (*info->fprintf_func) (info->stream, "%s or %s",
195 reg_names[reg],
196 reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
197 }
198 }
199 break;
200
201 case 'z':
202 (*info->fprintf_func) (info->stream, "%s", reg_names[0]);
203 break;
204
205 case '<':
206 (*info->fprintf_func) (info->stream, "0x%x",
207 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
208 break;
209
210 case 'c':
211 (*info->fprintf_func) (info->stream, "0x%x",
212 (l >> OP_SH_CODE) & OP_MASK_CODE);
213 break;
214
215 case 'q':
216 (*info->fprintf_func) (info->stream, "0x%x",
217 (l >> OP_SH_CODE2) & OP_MASK_CODE2);
218 break;
219
220 case 'C':
221 (*info->fprintf_func) (info->stream, "0x%x",
222 (l >> OP_SH_COPZ) & OP_MASK_COPZ);
223 break;
224
225 case 'B':
226 (*info->fprintf_func) (info->stream, "0x%x",
227 (l >> OP_SH_CODE20) & OP_MASK_CODE20);
228 break;
229
230 case 'J':
231 (*info->fprintf_func) (info->stream, "0x%x",
232 (l >> OP_SH_CODE19) & OP_MASK_CODE19);
233 break;
234
235 case 'S':
236 case 'V':
237 (*info->fprintf_func) (info->stream, "$f%d",
238 (l >> OP_SH_FS) & OP_MASK_FS);
239 break;
240
241 case 'T':
242 case 'W':
243 (*info->fprintf_func) (info->stream, "$f%d",
244 (l >> OP_SH_FT) & OP_MASK_FT);
245 break;
246
247 case 'D':
248 (*info->fprintf_func) (info->stream, "$f%d",
249 (l >> OP_SH_FD) & OP_MASK_FD);
250 break;
251
252 case 'R':
253 (*info->fprintf_func) (info->stream, "$f%d",
254 (l >> OP_SH_FR) & OP_MASK_FR);
255 break;
256
257 case 'E':
258 (*info->fprintf_func) (info->stream, "$%d",
259 (l >> OP_SH_RT) & OP_MASK_RT);
260 break;
261
262 case 'G':
263 (*info->fprintf_func) (info->stream, "$%d",
264 (l >> OP_SH_RD) & OP_MASK_RD);
265 break;
266
267 case 'N':
268 (*info->fprintf_func) (info->stream, "$fcc%d",
269 (l >> OP_SH_BCC) & OP_MASK_BCC);
270 break;
271
272 case 'M':
273 (*info->fprintf_func) (info->stream, "$fcc%d",
274 (l >> OP_SH_CCC) & OP_MASK_CCC);
275 break;
276
277 case 'P':
278 (*info->fprintf_func) (info->stream, "%d",
279 (l >> OP_SH_PERFREG) & OP_MASK_PERFREG);
280 break;
281
282 case 'H':
283 (*info->fprintf_func) (info->stream, "%d",
284 (l >> OP_SH_SEL) & OP_MASK_SEL);
285 break;
286
287 default:
288 /* xgettext:c-format */
289 (*info->fprintf_func) (info->stream,
290 _("# internal error, undefined modifier(%c)"),
291 *d);
292 break;
293 }
294 }
295 \f
296 /* Figure out the MIPS ISA and CPU based on the machine number. */
297
298 static void
299 mips_isa_type (mach, isa, cputype)
300 int mach;
301 int *isa;
302 int *cputype;
303 {
304 switch (mach)
305 {
306 case bfd_mach_mips3000:
307 *cputype = CPU_R3000;
308 *isa = ISA_MIPS1;
309 break;
310 case bfd_mach_mips3900:
311 *cputype = CPU_R3900;
312 *isa = ISA_MIPS1;
313 break;
314 case bfd_mach_mips4000:
315 *cputype = CPU_R4000;
316 *isa = ISA_MIPS3;
317 break;
318 case bfd_mach_mips4010:
319 *cputype = CPU_R4010;
320 *isa = ISA_MIPS2;
321 break;
322 case bfd_mach_mips4100:
323 *cputype = CPU_VR4100;
324 *isa = ISA_MIPS3;
325 break;
326 case bfd_mach_mips4111:
327 *cputype = CPU_R4111;
328 *isa = ISA_MIPS3;
329 break;
330 case bfd_mach_mips4300:
331 *cputype = CPU_R4300;
332 *isa = ISA_MIPS3;
333 break;
334 case bfd_mach_mips4400:
335 *cputype = CPU_R4400;
336 *isa = ISA_MIPS3;
337 break;
338 case bfd_mach_mips4600:
339 *cputype = CPU_R4600;
340 *isa = ISA_MIPS3;
341 break;
342 case bfd_mach_mips4650:
343 *cputype = CPU_R4650;
344 *isa = ISA_MIPS3;
345 break;
346 case bfd_mach_mips5000:
347 *cputype = CPU_R5000;
348 *isa = ISA_MIPS4;
349 break;
350 case bfd_mach_mips6000:
351 *cputype = CPU_R6000;
352 *isa = ISA_MIPS2;
353 break;
354 case bfd_mach_mips8000:
355 *cputype = CPU_R8000;
356 *isa = ISA_MIPS4;
357 break;
358 case bfd_mach_mips10000:
359 *cputype = CPU_R10000;
360 *isa = ISA_MIPS4;
361 break;
362 case bfd_mach_mips12000:
363 *cputype = CPU_R12000;
364 *isa = ISA_MIPS4;
365 break;
366 case bfd_mach_mips16:
367 *cputype = CPU_MIPS16;
368 *isa = ISA_MIPS3;
369 break;
370 case bfd_mach_mips5:
371 *cputype = CPU_MIPS5;
372 *isa = ISA_MIPS5;
373 break;
374 case bfd_mach_mips_sb1:
375 *cputype = CPU_SB1;
376 *isa = ISA_MIPS64 | INSN_SB1;
377 break;
378 case bfd_mach_mipsisa32:
379 *cputype = CPU_MIPS32;
380 *isa = ISA_MIPS32;
381 break;
382 case bfd_mach_mipsisa64:
383 *cputype = CPU_MIPS64;
384 *isa = ISA_MIPS64;
385 break;
386
387 default:
388 *cputype = CPU_R3000;
389 *isa = ISA_MIPS3;
390 break;
391 }
392 }
393
394 /* Check if the object uses NewABI conventions. */
395
396 static int
397 is_newabi (header)
398 Elf_Internal_Ehdr *header;
399 {
400 /* There are no old-style ABIs which use 64-bit ELF. */
401 if (header->e_ident[EI_CLASS] == ELFCLASS64)
402 return 1;
403
404 /* If a 32-bit ELF file, N32, EABI32, and EABI64 are new-style ABIs. */
405 if ((header->e_flags & EF_MIPS_ABI2) != 0
406 || (header->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI32
407 || (header->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI64)
408 return 1;
409
410 return 0;
411 }
412 \f
413 /* Print the mips instruction at address MEMADDR in debugged memory,
414 on using INFO. Returns length of the instruction, in bytes, which is
415 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
416 this is little-endian code. */
417
418 static int
419 print_insn_mips (memaddr, word, info)
420 bfd_vma memaddr;
421 unsigned long int word;
422 struct disassemble_info *info;
423 {
424 register const struct mips_opcode *op;
425 int target_processor, mips_isa;
426 static boolean init = 0;
427 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
428
429 /* Build a hash table to shorten the search time. */
430 if (! init)
431 {
432 unsigned int i;
433
434 for (i = 0; i <= OP_MASK_OP; i++)
435 {
436 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
437 {
438 if (op->pinfo == INSN_MACRO)
439 continue;
440 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
441 {
442 mips_hash[i] = op;
443 break;
444 }
445 }
446 }
447
448 init = 1;
449 }
450
451 #if ! SYMTAB_AVAILABLE
452 /* This is running out on a target machine, not in a host tool.
453 FIXME: Where does mips_target_info come from? */
454 target_processor = mips_target_info.processor;
455 mips_isa = mips_target_info.isa;
456 #else
457 mips_isa_type (info->mach, &mips_isa, &target_processor);
458 #endif
459
460 info->bytes_per_chunk = INSNLEN;
461 info->display_endian = info->endian;
462 info->insn_info_valid = 1;
463 info->branch_delay_insns = 0;
464 info->data_size = 0;
465 info->insn_type = dis_nonbranch;
466 info->target = 0;
467 info->target2 = 0;
468
469 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
470 if (op != NULL)
471 {
472 for (; op < &mips_opcodes[NUMOPCODES]; op++)
473 {
474 if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
475 {
476 register const char *d;
477
478 if (! OPCODE_IS_MEMBER (op, mips_isa, target_processor))
479 continue;
480
481 /* Figure out instruction type and branch delay information. */
482 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
483 {
484 if ((info->insn_type & INSN_WRITE_GPR_31) != 0)
485 info->insn_type = dis_jsr;
486 else
487 info->insn_type = dis_branch;
488 info->branch_delay_insns = 1;
489 }
490 else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
491 | INSN_COND_BRANCH_LIKELY)) != 0)
492 {
493 if ((info->insn_type & INSN_WRITE_GPR_31) != 0)
494 info->insn_type = dis_condjsr;
495 else
496 info->insn_type = dis_condbranch;
497 info->branch_delay_insns = 1;
498 }
499 else if ((op->pinfo & (INSN_STORE_MEMORY
500 | INSN_LOAD_MEMORY_DELAY)) != 0)
501 info->insn_type = dis_dref;
502
503 (*info->fprintf_func) (info->stream, "%s", op->name);
504
505 d = op->args;
506 if (d != NULL && *d != '\0')
507 {
508 (*info->fprintf_func) (info->stream, "\t");
509 for (; *d != '\0'; d++)
510 print_insn_arg (d, word, memaddr, info);
511 }
512
513 return INSNLEN;
514 }
515 }
516 }
517
518 /* Handle undefined instructions. */
519 info->insn_type = dis_noninsn;
520 (*info->fprintf_func) (info->stream, "0x%x", word);
521 return INSNLEN;
522 }
523 \f
524 /* In an environment where we do not know the symbol type of the
525 instruction we are forced to assume that the low order bit of the
526 instructions' address may mark it as a mips16 instruction. If we
527 are single stepping, or the pc is within the disassembled function,
528 this works. Otherwise, we need a clue. Sometimes. */
529
530 static int
531 _print_insn_mips (memaddr, info, endianness)
532 bfd_vma memaddr;
533 struct disassemble_info *info;
534 enum bfd_endian endianness;
535 {
536 bfd_byte buffer[INSNLEN];
537 int status;
538
539 #if 1
540 /* FIXME: If odd address, this is CLEARLY a mips 16 instruction. */
541 /* Only a few tools will work this way. */
542 if (memaddr & 0x01)
543 return print_insn_mips16 (memaddr, info);
544 #endif
545
546 #if SYMTAB_AVAILABLE
547 if (info->mach == 16
548 || (info->flavour == bfd_target_elf_flavour
549 && info->symbols != NULL
550 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
551 == STO_MIPS16)))
552 return print_insn_mips16 (memaddr, info);
553 #endif
554
555 /* Use mips64_reg_names for new ABI. */
556 reg_names = mips32_reg_names;
557
558 if (info->flavour == bfd_target_elf_flavour && info->symbols != NULL)
559 {
560 Elf_Internal_Ehdr *header;
561
562 header = elf_elfheader (bfd_asymbol_bfd (*(info->symbols)));
563 if (is_newabi (header))
564 reg_names = mips64_reg_names;
565 }
566
567 status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
568 if (status == 0)
569 {
570 unsigned long insn;
571
572 if (endianness == BFD_ENDIAN_BIG)
573 insn = (unsigned long) bfd_getb32 (buffer);
574 else
575 insn = (unsigned long) bfd_getl32 (buffer);
576
577 return print_insn_mips (memaddr, insn, info);
578 }
579 else
580 {
581 (*info->memory_error_func) (status, memaddr, info);
582 return -1;
583 }
584 }
585
586 int
587 print_insn_big_mips (memaddr, info)
588 bfd_vma memaddr;
589 struct disassemble_info *info;
590 {
591 return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
592 }
593
594 int
595 print_insn_little_mips (memaddr, info)
596 bfd_vma memaddr;
597 struct disassemble_info *info;
598 {
599 return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
600 }
601 \f
602 /* Disassemble mips16 instructions. */
603
604 static int
605 print_insn_mips16 (memaddr, info)
606 bfd_vma memaddr;
607 struct disassemble_info *info;
608 {
609 int status;
610 bfd_byte buffer[2];
611 int length;
612 int insn;
613 boolean use_extend;
614 int extend = 0;
615 const struct mips_opcode *op, *opend;
616
617 info->bytes_per_chunk = 2;
618 info->display_endian = info->endian;
619 info->insn_info_valid = 1;
620 info->branch_delay_insns = 0;
621 info->data_size = 0;
622 info->insn_type = dis_nonbranch;
623 info->target = 0;
624 info->target2 = 0;
625
626 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
627 if (status != 0)
628 {
629 (*info->memory_error_func) (status, memaddr, info);
630 return -1;
631 }
632
633 length = 2;
634
635 if (info->endian == BFD_ENDIAN_BIG)
636 insn = bfd_getb16 (buffer);
637 else
638 insn = bfd_getl16 (buffer);
639
640 /* Handle the extend opcode specially. */
641 use_extend = false;
642 if ((insn & 0xf800) == 0xf000)
643 {
644 use_extend = true;
645 extend = insn & 0x7ff;
646
647 memaddr += 2;
648
649 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
650 if (status != 0)
651 {
652 (*info->fprintf_func) (info->stream, "extend 0x%x",
653 (unsigned int) extend);
654 (*info->memory_error_func) (status, memaddr, info);
655 return -1;
656 }
657
658 if (info->endian == BFD_ENDIAN_BIG)
659 insn = bfd_getb16 (buffer);
660 else
661 insn = bfd_getl16 (buffer);
662
663 /* Check for an extend opcode followed by an extend opcode. */
664 if ((insn & 0xf800) == 0xf000)
665 {
666 (*info->fprintf_func) (info->stream, "extend 0x%x",
667 (unsigned int) extend);
668 info->insn_type = dis_noninsn;
669 return length;
670 }
671
672 length += 2;
673 }
674
675 /* FIXME: Should probably use a hash table on the major opcode here. */
676
677 opend = mips16_opcodes + bfd_mips16_num_opcodes;
678 for (op = mips16_opcodes; op < opend; op++)
679 {
680 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
681 {
682 const char *s;
683
684 if (strchr (op->args, 'a') != NULL)
685 {
686 if (use_extend)
687 {
688 (*info->fprintf_func) (info->stream, "extend 0x%x",
689 (unsigned int) extend);
690 info->insn_type = dis_noninsn;
691 return length - 2;
692 }
693
694 use_extend = false;
695
696 memaddr += 2;
697
698 status = (*info->read_memory_func) (memaddr, buffer, 2,
699 info);
700 if (status == 0)
701 {
702 use_extend = true;
703 if (info->endian == BFD_ENDIAN_BIG)
704 extend = bfd_getb16 (buffer);
705 else
706 extend = bfd_getl16 (buffer);
707 length += 2;
708 }
709 }
710
711 (*info->fprintf_func) (info->stream, "%s", op->name);
712 if (op->args[0] != '\0')
713 (*info->fprintf_func) (info->stream, "\t");
714
715 for (s = op->args; *s != '\0'; s++)
716 {
717 if (*s == ','
718 && s[1] == 'w'
719 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
720 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
721 {
722 /* Skip the register and the comma. */
723 ++s;
724 continue;
725 }
726 if (*s == ','
727 && s[1] == 'v'
728 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
729 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
730 {
731 /* Skip the register and the comma. */
732 ++s;
733 continue;
734 }
735 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
736 info);
737 }
738
739 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
740 {
741 info->branch_delay_insns = 1;
742 if (info->insn_type != dis_jsr)
743 info->insn_type = dis_branch;
744 }
745
746 return length;
747 }
748 }
749
750 if (use_extend)
751 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
752 (*info->fprintf_func) (info->stream, "0x%x", insn);
753 info->insn_type = dis_noninsn;
754
755 return length;
756 }
757
758 /* Disassemble an operand for a mips16 instruction. */
759
760 static void
761 print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
762 char type;
763 const struct mips_opcode *op;
764 int l;
765 boolean use_extend;
766 int extend;
767 bfd_vma memaddr;
768 struct disassemble_info *info;
769 {
770 switch (type)
771 {
772 case ',':
773 case '(':
774 case ')':
775 (*info->fprintf_func) (info->stream, "%c", type);
776 break;
777
778 case 'y':
779 case 'w':
780 (*info->fprintf_func) (info->stream, "%s",
781 mips16_reg_names[((l >> MIPS16OP_SH_RY)
782 & MIPS16OP_MASK_RY)]);
783 break;
784
785 case 'x':
786 case 'v':
787 (*info->fprintf_func) (info->stream, "%s",
788 mips16_reg_names[((l >> MIPS16OP_SH_RX)
789 & MIPS16OP_MASK_RX)]);
790 break;
791
792 case 'z':
793 (*info->fprintf_func) (info->stream, "%s",
794 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
795 & MIPS16OP_MASK_RZ)]);
796 break;
797
798 case 'Z':
799 (*info->fprintf_func) (info->stream, "%s",
800 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
801 & MIPS16OP_MASK_MOVE32Z)]);
802 break;
803
804 case '0':
805 (*info->fprintf_func) (info->stream, "%s", mips32_reg_names[0]);
806 break;
807
808 case 'S':
809 (*info->fprintf_func) (info->stream, "%s", mips32_reg_names[29]);
810 break;
811
812 case 'P':
813 (*info->fprintf_func) (info->stream, "$pc");
814 break;
815
816 case 'R':
817 (*info->fprintf_func) (info->stream, "%s", mips32_reg_names[31]);
818 break;
819
820 case 'X':
821 (*info->fprintf_func) (info->stream, "%s",
822 mips32_reg_names[((l >> MIPS16OP_SH_REGR32)
823 & MIPS16OP_MASK_REGR32)]);
824 break;
825
826 case 'Y':
827 (*info->fprintf_func) (info->stream, "%s",
828 mips32_reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
829 break;
830
831 case '<':
832 case '>':
833 case '[':
834 case ']':
835 case '4':
836 case '5':
837 case 'H':
838 case 'W':
839 case 'D':
840 case 'j':
841 case '6':
842 case '8':
843 case 'V':
844 case 'C':
845 case 'U':
846 case 'k':
847 case 'K':
848 case 'p':
849 case 'q':
850 case 'A':
851 case 'B':
852 case 'E':
853 {
854 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
855
856 shift = 0;
857 signedp = 0;
858 extbits = 16;
859 pcrel = 0;
860 extu = 0;
861 branch = 0;
862 switch (type)
863 {
864 case '<':
865 nbits = 3;
866 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
867 extbits = 5;
868 extu = 1;
869 break;
870 case '>':
871 nbits = 3;
872 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
873 extbits = 5;
874 extu = 1;
875 break;
876 case '[':
877 nbits = 3;
878 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
879 extbits = 6;
880 extu = 1;
881 break;
882 case ']':
883 nbits = 3;
884 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
885 extbits = 6;
886 extu = 1;
887 break;
888 case '4':
889 nbits = 4;
890 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
891 signedp = 1;
892 extbits = 15;
893 break;
894 case '5':
895 nbits = 5;
896 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
897 info->insn_type = dis_dref;
898 info->data_size = 1;
899 break;
900 case 'H':
901 nbits = 5;
902 shift = 1;
903 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
904 info->insn_type = dis_dref;
905 info->data_size = 2;
906 break;
907 case 'W':
908 nbits = 5;
909 shift = 2;
910 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
911 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
912 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
913 {
914 info->insn_type = dis_dref;
915 info->data_size = 4;
916 }
917 break;
918 case 'D':
919 nbits = 5;
920 shift = 3;
921 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
922 info->insn_type = dis_dref;
923 info->data_size = 8;
924 break;
925 case 'j':
926 nbits = 5;
927 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
928 signedp = 1;
929 break;
930 case '6':
931 nbits = 6;
932 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
933 break;
934 case '8':
935 nbits = 8;
936 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
937 break;
938 case 'V':
939 nbits = 8;
940 shift = 2;
941 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
942 /* FIXME: This might be lw, or it might be addiu to $sp or
943 $pc. We assume it's load. */
944 info->insn_type = dis_dref;
945 info->data_size = 4;
946 break;
947 case 'C':
948 nbits = 8;
949 shift = 3;
950 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
951 info->insn_type = dis_dref;
952 info->data_size = 8;
953 break;
954 case 'U':
955 nbits = 8;
956 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
957 extu = 1;
958 break;
959 case 'k':
960 nbits = 8;
961 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
962 signedp = 1;
963 break;
964 case 'K':
965 nbits = 8;
966 shift = 3;
967 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
968 signedp = 1;
969 break;
970 case 'p':
971 nbits = 8;
972 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
973 signedp = 1;
974 pcrel = 1;
975 branch = 1;
976 info->insn_type = dis_condbranch;
977 break;
978 case 'q':
979 nbits = 11;
980 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
981 signedp = 1;
982 pcrel = 1;
983 branch = 1;
984 info->insn_type = dis_branch;
985 break;
986 case 'A':
987 nbits = 8;
988 shift = 2;
989 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
990 pcrel = 1;
991 /* FIXME: This can be lw or la. We assume it is lw. */
992 info->insn_type = dis_dref;
993 info->data_size = 4;
994 break;
995 case 'B':
996 nbits = 5;
997 shift = 3;
998 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
999 pcrel = 1;
1000 info->insn_type = dis_dref;
1001 info->data_size = 8;
1002 break;
1003 case 'E':
1004 nbits = 5;
1005 shift = 2;
1006 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1007 pcrel = 1;
1008 break;
1009 default:
1010 abort ();
1011 }
1012
1013 if (! use_extend)
1014 {
1015 if (signedp && immed >= (1 << (nbits - 1)))
1016 immed -= 1 << nbits;
1017 immed <<= shift;
1018 if ((type == '<' || type == '>' || type == '[' || type == ']')
1019 && immed == 0)
1020 immed = 8;
1021 }
1022 else
1023 {
1024 if (extbits == 16)
1025 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
1026 else if (extbits == 15)
1027 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
1028 else
1029 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
1030 immed &= (1 << extbits) - 1;
1031 if (! extu && immed >= (1 << (extbits - 1)))
1032 immed -= 1 << extbits;
1033 }
1034
1035 if (! pcrel)
1036 (*info->fprintf_func) (info->stream, "%d", immed);
1037 else
1038 {
1039 bfd_vma baseaddr;
1040
1041 if (branch)
1042 {
1043 immed *= 2;
1044 baseaddr = memaddr + 2;
1045 }
1046 else if (use_extend)
1047 baseaddr = memaddr - 2;
1048 else
1049 {
1050 int status;
1051 bfd_byte buffer[2];
1052
1053 baseaddr = memaddr;
1054
1055 /* If this instruction is in the delay slot of a jr
1056 instruction, the base address is the address of the
1057 jr instruction. If it is in the delay slot of jalr
1058 instruction, the base address is the address of the
1059 jalr instruction. This test is unreliable: we have
1060 no way of knowing whether the previous word is
1061 instruction or data. */
1062 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
1063 info);
1064 if (status == 0
1065 && (((info->endian == BFD_ENDIAN_BIG
1066 ? bfd_getb16 (buffer)
1067 : bfd_getl16 (buffer))
1068 & 0xf800) == 0x1800))
1069 baseaddr = memaddr - 4;
1070 else
1071 {
1072 status = (*info->read_memory_func) (memaddr - 2, buffer,
1073 2, info);
1074 if (status == 0
1075 && (((info->endian == BFD_ENDIAN_BIG
1076 ? bfd_getb16 (buffer)
1077 : bfd_getl16 (buffer))
1078 & 0xf81f) == 0xe800))
1079 baseaddr = memaddr - 2;
1080 }
1081 }
1082 info->target = (baseaddr & ~((1 << shift) - 1)) + immed;
1083 (*info->print_address_func) (info->target, info);
1084 }
1085 }
1086 break;
1087
1088 case 'a':
1089 if (! use_extend)
1090 extend = 0;
1091 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
1092 info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
1093 (*info->print_address_func) (info->target, info);
1094 info->insn_type = dis_jsr;
1095 info->branch_delay_insns = 1;
1096 break;
1097
1098 case 'l':
1099 case 'L':
1100 {
1101 int need_comma, amask, smask;
1102
1103 need_comma = 0;
1104
1105 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1106
1107 amask = (l >> 3) & 7;
1108
1109 if (amask > 0 && amask < 5)
1110 {
1111 (*info->fprintf_func) (info->stream, "%s", mips32_reg_names[4]);
1112 if (amask > 1)
1113 (*info->fprintf_func) (info->stream, "-%s",
1114 mips32_reg_names[amask + 3]);
1115 need_comma = 1;
1116 }
1117
1118 smask = (l >> 1) & 3;
1119 if (smask == 3)
1120 {
1121 (*info->fprintf_func) (info->stream, "%s??",
1122 need_comma ? "," : "");
1123 need_comma = 1;
1124 }
1125 else if (smask > 0)
1126 {
1127 (*info->fprintf_func) (info->stream, "%s%s",
1128 need_comma ? "," : "",
1129 mips32_reg_names[16]);
1130 if (smask > 1)
1131 (*info->fprintf_func) (info->stream, "-%s",
1132 mips32_reg_names[smask + 15]);
1133 need_comma = 1;
1134 }
1135
1136 if (l & 1)
1137 {
1138 (*info->fprintf_func) (info->stream, "%s%s",
1139 need_comma ? "," : "",
1140 mips32_reg_names[31]);
1141 need_comma = 1;
1142 }
1143
1144 if (amask == 5 || amask == 6)
1145 {
1146 (*info->fprintf_func) (info->stream, "%s$f0",
1147 need_comma ? "," : "");
1148 if (amask == 6)
1149 (*info->fprintf_func) (info->stream, "-$f1");
1150 }
1151 }
1152 break;
1153
1154 default:
1155 /* xgettext:c-format */
1156 (*info->fprintf_func)
1157 (info->stream,
1158 _("# internal disassembler error, unrecognised modifier (%c)"),
1159 type);
1160 abort ();
1161 }
1162 }
This page took 0.053887 seconds and 4 git commands to generate.