1 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2 Copyright 1989, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
3 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
5 This file is part of GDB, GAS, and the GNU binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 #include "opcode/mips.h"
26 /* FIXME: These are needed to figure out if this is a mips16 symbol or
27 not. It would be better to think of a cleaner way to do this. */
31 static int print_insn_mips16
PARAMS ((bfd_vma
, struct disassemble_info
*));
32 static void print_mips16_insn_arg
33 PARAMS ((int, const struct mips_opcode
*, int, boolean
, int, bfd_vma
,
34 struct disassemble_info
*));
36 /* Mips instructions are never longer than this many bytes. */
39 static void print_insn_arg
PARAMS ((const char *, unsigned long, bfd_vma
,
40 struct disassemble_info
*));
41 static int _print_insn_mips
PARAMS ((bfd_vma
, unsigned long int,
42 struct disassemble_info
*));
45 /* FIXME: This should be shared with gdb somehow. */
46 #define REGISTER_NAMES \
47 { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
48 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
49 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
50 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
51 "sr", "lo", "hi", "bad", "cause","pc", \
52 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
53 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
54 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
55 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
56 "fsr", "fir", "fp", "inx", "rand", "tlblo","ctxt", "tlbhi",\
60 static CONST
char * CONST reg_names
[] = REGISTER_NAMES
;
62 /* The mips16 register names. */
63 static const char * const mips16_reg_names
[] =
65 "s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3"
70 print_insn_arg (d
, l
, pc
, info
)
72 register unsigned long int l
;
74 struct disassemble_info
*info
;
83 (*info
->fprintf_func
) (info
->stream
, "%c", *d
);
90 (*info
->fprintf_func
) (info
->stream
, "$%s",
91 reg_names
[(l
>> OP_SH_RS
) & OP_MASK_RS
]);
96 (*info
->fprintf_func
) (info
->stream
, "$%s",
97 reg_names
[(l
>> OP_SH_RT
) & OP_MASK_RT
]);
102 (*info
->fprintf_func
) (info
->stream
, "0x%x",
103 (l
>> OP_SH_IMMEDIATE
) & OP_MASK_IMMEDIATE
);
106 case 'j': /* same as i, but sign-extended */
108 delta
= (l
>> OP_SH_DELTA
) & OP_MASK_DELTA
;
111 (*info
->fprintf_func
) (info
->stream
, "%d",
116 (*info
->fprintf_func
) (info
->stream
, "0x%x",
117 (unsigned int) ((l
>> OP_SH_PREFX
)
122 (*info
->fprintf_func
) (info
->stream
, "0x%x",
123 (unsigned int) ((l
>> OP_SH_CACHE
)
128 (*info
->print_address_func
)
129 (((pc
& 0xF0000000) | (((l
>> OP_SH_TARGET
) & OP_MASK_TARGET
) << 2)),
134 /* sign extend the displacement */
135 delta
= (l
>> OP_SH_DELTA
) & OP_MASK_DELTA
;
138 (*info
->print_address_func
)
139 ((delta
<< 2) + pc
+ 4,
144 (*info
->fprintf_func
) (info
->stream
, "$%s",
145 reg_names
[(l
>> OP_SH_RD
) & OP_MASK_RD
]);
149 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[0]);
153 (*info
->fprintf_func
) (info
->stream
, "0x%x",
154 (l
>> OP_SH_SHAMT
) & OP_MASK_SHAMT
);
158 (*info
->fprintf_func
) (info
->stream
, "0x%x",
159 (l
>> OP_SH_CODE
) & OP_MASK_CODE
);
163 (*info
->fprintf_func
) (info
->stream
, "0x%x",
164 (l
>> OP_SH_COPZ
) & OP_MASK_COPZ
);
168 (*info
->fprintf_func
) (info
->stream
, "0x%x",
169 (l
>> OP_SH_SYSCALL
) & OP_MASK_SYSCALL
);
174 (*info
->fprintf_func
) (info
->stream
, "$f%d",
175 (l
>> OP_SH_FS
) & OP_MASK_FS
);
180 (*info
->fprintf_func
) (info
->stream
, "$f%d",
181 (l
>> OP_SH_FT
) & OP_MASK_FT
);
185 (*info
->fprintf_func
) (info
->stream
, "$f%d",
186 (l
>> OP_SH_FD
) & OP_MASK_FD
);
190 (*info
->fprintf_func
) (info
->stream
, "$f%d",
191 (l
>> OP_SH_FR
) & OP_MASK_FR
);
195 (*info
->fprintf_func
) (info
->stream
, "$%d",
196 (l
>> OP_SH_RT
) & OP_MASK_RT
);
200 (*info
->fprintf_func
) (info
->stream
, "$%d",
201 (l
>> OP_SH_RD
) & OP_MASK_RD
);
205 (*info
->fprintf_func
) (info
->stream
, "$fcc%d",
206 (l
>> OP_SH_BCC
) & OP_MASK_BCC
);
210 (*info
->fprintf_func
) (info
->stream
, "$fcc%d",
211 (l
>> OP_SH_CCC
) & OP_MASK_CCC
);
215 (*info
->fprintf_func
) (info
->stream
,
216 "# internal error, undefined modifier(%c)", *d
);
221 /* Print the mips instruction at address MEMADDR in debugged memory,
222 on using INFO. Returns length of the instruction, in bytes, which is
223 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
224 this is little-endian code. */
227 _print_insn_mips (memaddr
, word
, info
)
229 unsigned long int word
;
230 struct disassemble_info
*info
;
232 register const struct mips_opcode
*op
;
233 static boolean init
= 0;
234 static const struct mips_opcode
*mips_hash
[OP_MASK_OP
+ 1];
236 /* Build a hash table to shorten the search time. */
241 for (i
= 0; i
<= OP_MASK_OP
; i
++)
243 for (op
= mips_opcodes
; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
245 if (op
->pinfo
== INSN_MACRO
)
247 if (i
== ((op
->match
>> OP_SH_OP
) & OP_MASK_OP
))
258 op
= mips_hash
[(word
>> OP_SH_OP
) & OP_MASK_OP
];
261 for (; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
263 if (op
->pinfo
!= INSN_MACRO
&& (word
& op
->mask
) == op
->match
)
265 register const char *d
;
267 (*info
->fprintf_func
) (info
->stream
, "%s", op
->name
);
270 if (d
!= NULL
&& *d
!= '\0')
272 (*info
->fprintf_func
) (info
->stream
, "\t");
273 for (; *d
!= '\0'; d
++)
274 print_insn_arg (d
, word
, memaddr
, info
);
282 /* Handle undefined instructions. */
283 (*info
->fprintf_func
) (info
->stream
, "0x%x", word
);
288 print_insn_big_mips (memaddr
, info
)
290 struct disassemble_info
*info
;
296 || (info
->flavour
== bfd_target_elf_flavour
297 && info
->symbol
!= NULL
298 && (((elf_symbol_type
*) info
->symbol
)->internal_elf_sym
.st_other
300 return print_insn_mips16 (memaddr
, info
);
302 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
304 return _print_insn_mips (memaddr
, (unsigned long) bfd_getb32 (buffer
),
308 (*info
->memory_error_func
) (status
, memaddr
, info
);
314 print_insn_little_mips (memaddr
, info
)
316 struct disassemble_info
*info
;
322 || (info
->flavour
== bfd_target_elf_flavour
323 && info
->symbol
!= NULL
324 && (((elf_symbol_type
*) info
->symbol
)->internal_elf_sym
.st_other
326 return print_insn_mips16 (memaddr
, info
);
328 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
330 return _print_insn_mips (memaddr
, (unsigned long) bfd_getl32 (buffer
),
334 (*info
->memory_error_func
) (status
, memaddr
, info
);
339 /* Disassemble mips16 instructions. */
342 print_insn_mips16 (memaddr
, info
)
344 struct disassemble_info
*info
;
352 const struct mips_opcode
*op
, *opend
;
354 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
357 (*info
->memory_error_func
) (status
, memaddr
, info
);
363 if (info
->endian
== BFD_ENDIAN_BIG
)
364 insn
= bfd_getb16 (buffer
);
366 insn
= bfd_getl16 (buffer
);
368 /* Handle the extend opcode specially. */
370 if ((insn
& 0xf800) == 0xf000)
373 extend
= insn
& 0x7ff;
377 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
380 (*info
->fprintf_func
) (info
->stream
, "extend 0x%x",
381 (unsigned int) extend
);
382 (*info
->memory_error_func
) (status
, memaddr
, info
);
388 if (info
->endian
== BFD_ENDIAN_BIG
)
389 insn
= bfd_getb16 (buffer
);
391 insn
= bfd_getl16 (buffer
);
394 /* FIXME: Should probably use a hash table on the major opcode here. */
396 opend
= mips16_opcodes
+ bfd_mips16_num_opcodes
;
397 for (op
= mips16_opcodes
; op
< opend
; op
++)
399 if (op
->pinfo
!= INSN_MACRO
&& (insn
& op
->mask
) == op
->match
)
403 if (strchr (op
->args
, 'a') != NULL
)
406 (*info
->fprintf_func
) (info
->stream
, "extend 0x%x",
407 (unsigned int) extend
);
412 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2,
417 if (info
->endian
== BFD_ENDIAN_BIG
)
418 extend
= bfd_getb16 (buffer
);
420 extend
= bfd_getl16 (buffer
);
425 (*info
->fprintf_func
) (info
->stream
, "%s ", op
->name
);
427 for (s
= op
->args
; *s
!= '\0'; s
++)
431 && (((insn
>> MIPS16OP_SH_RX
) & MIPS16OP_MASK_RX
)
432 == ((insn
>> MIPS16OP_SH_RY
) & MIPS16OP_MASK_RY
)))
434 /* Skip the register and the comma. */
440 && (((insn
>> MIPS16OP_SH_RZ
) & MIPS16OP_MASK_RZ
)
441 == ((insn
>> MIPS16OP_SH_RX
) & MIPS16OP_MASK_RX
)))
443 /* Skip the register and the comma. */
447 print_mips16_insn_arg (*s
, op
, insn
, use_extend
, extend
, memaddr
,
456 (*info
->fprintf_func
) (info
->stream
, "0x%x", extend
| 0xf000);
457 (*info
->fprintf_func
) (info
->stream
, "0x%x", insn
);
462 /* Disassemble an operand for a mips16 instruction. */
465 print_mips16_insn_arg (type
, op
, l
, use_extend
, extend
, memaddr
, info
)
467 const struct mips_opcode
*op
;
472 struct disassemble_info
*info
;
479 (*info
->fprintf_func
) (info
->stream
, "%c", type
);
484 (*info
->fprintf_func
) (info
->stream
, "$%s",
485 mips16_reg_names
[((l
>> MIPS16OP_SH_RY
)
486 & MIPS16OP_MASK_RY
)]);
491 (*info
->fprintf_func
) (info
->stream
, "$%s",
492 mips16_reg_names
[((l
>> MIPS16OP_SH_RX
)
493 & MIPS16OP_MASK_RX
)]);
497 (*info
->fprintf_func
) (info
->stream
, "$%s",
498 mips16_reg_names
[((l
>> MIPS16OP_SH_RZ
)
499 & MIPS16OP_MASK_RZ
)]);
503 (*info
->fprintf_func
) (info
->stream
, "$%s",
504 mips16_reg_names
[((l
>> MIPS16OP_SH_MOVE32Z
)
505 & MIPS16OP_MASK_MOVE32Z
)]);
509 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[0]);
513 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[29]);
517 (*info
->fprintf_func
) (info
->stream
, "$pc");
521 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[31]);
525 (*info
->fprintf_func
) (info
->stream
, "$%s",
526 reg_names
[((l
>> MIPS16OP_SH_REGR32
)
527 & MIPS16OP_MASK_REGR32
)]);
531 (*info
->fprintf_func
) (info
->stream
, "$%s",
532 reg_names
[MIPS16OP_EXTRACT_REG32R (l
)]);
558 int immed
, nbits
, shift
, signedp
, extbits
, pcrel
, extu
, branch
;
570 immed
= (l
>> MIPS16OP_SH_RZ
) & MIPS16OP_MASK_RZ
;
576 immed
= (l
>> MIPS16OP_SH_RX
) & MIPS16OP_MASK_RX
;
582 immed
= (l
>> MIPS16OP_SH_RZ
) & MIPS16OP_MASK_RZ
;
588 immed
= (l
>> MIPS16OP_SH_RX
) & MIPS16OP_MASK_RX
;
594 immed
= (l
>> MIPS16OP_SH_IMM4
) & MIPS16OP_MASK_IMM4
;
600 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
605 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
610 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
615 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
619 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
624 immed
= (l
>> MIPS16OP_SH_IMM6
) & MIPS16OP_MASK_IMM6
;
628 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
633 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
638 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
642 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
647 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
653 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
658 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
665 immed
= (l
>> MIPS16OP_SH_IMM11
) & MIPS16OP_MASK_IMM11
;
673 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
679 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
685 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
694 if (signedp
&& immed
>= (1 << (nbits
- 1)))
697 if ((type
== '<' || type
== '>' || type
== '[' || type
== '[')
704 immed
|= ((extend
& 0x1f) << 11) | (extend
& 0x7e0);
705 else if (extbits
== 15)
706 immed
|= ((extend
& 0xf) << 11) | (extend
& 0x7f0);
708 immed
= ((extend
>> 6) & 0x1f) | (extend
& 0x20);
709 immed
&= (1 << extbits
) - 1;
710 if (! extu
&& immed
>= (1 << (extbits
- 1)))
711 immed
-= 1 << extbits
;
715 (*info
->fprintf_func
) (info
->stream
, "%d", immed
);
722 val
= ((memaddr
+ 2) & ~ ((1 << shift
) - 1)) + immed
;
723 (*info
->print_address_func
) (val
, info
);
731 l
= ((l
& 0x1f) << 23) | ((l
& 0x3e0) << 13) | (extend
<< 2);
732 (*info
->print_address_func
) ((memaddr
& 0xf0000000) | l
, info
);
738 int need_comma
, amask
, smask
;
742 l
= (l
>> MIPS16OP_SH_IMM6
) & MIPS16OP_MASK_IMM6
;
744 amask
= (l
>> 3) & 7;
745 if (amask
== 5 || amask
== 6)
747 (*info
->fprintf_func
) (info
->stream
, "??");
750 else if (amask
> 0 && amask
< 7)
752 (*info
->fprintf_func
) (info
->stream
, "%s", reg_names
[4]);
754 (*info
->fprintf_func
) (info
->stream
, "-%s",
755 reg_names
[amask
+ 3]);
759 smask
= (l
>> 1) & 3;
762 (*info
->fprintf_func
) (info
->stream
, "%s??",
763 need_comma
? "," : "");
768 (*info
->fprintf_func
) (info
->stream
, "%s%s",
769 need_comma
? "," : "",
772 (*info
->fprintf_func
) (info
->stream
, "-%s",
773 reg_names
[smask
+ 15]);
778 (*info
->fprintf_func
) (info
->stream
, "%s%s",
779 need_comma
? "," : "",
This page took 0.046102 seconds and 4 git commands to generate.