1 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2 Copyright (c) 1989, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
3 Free Software Foundation, Inc.
4 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
6 This file is part of GDB, GAS, and the GNU binutils.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 #include "opcode/mips.h"
27 /* FIXME: These are needed to figure out if the code is mips16 or
28 not. The low bit of the address is often a good indicator. No
29 symbol table is available when this code runs out in an embedded
30 system as when it is used for disassembler support in a monitor. */
32 #if !defined(EMBEDDED_ENV)
33 #define SYMTAB_AVAILABLE 1
38 static int print_insn_mips16
PARAMS ((bfd_vma
, struct disassemble_info
*));
39 static void print_mips16_insn_arg
40 PARAMS ((int, const struct mips_opcode
*, int, boolean
, int, bfd_vma
,
41 struct disassemble_info
*));
43 /* Mips instructions are never longer than this many bytes. */
46 static void print_insn_arg
PARAMS ((const char *, unsigned long, bfd_vma
,
47 struct disassemble_info
*));
48 static int _print_insn_mips
PARAMS ((bfd_vma
, unsigned long int,
49 struct disassemble_info
*));
52 /* FIXME: This should be shared with gdb somehow. */
53 #define STD_REGISTER_NAMES \
54 { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
55 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
56 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
57 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
58 "sr", "lo", "hi", "bad", "cause","pc", \
59 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
60 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
61 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
62 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
63 "fsr", "fir", "fp", "inx", "rand", "tlblo","ctxt", "tlbhi",\
67 static CONST
char * CONST std_reg_names
[] = STD_REGISTER_NAMES
;
69 /* The mips16 register names. */
70 static const char * const mips16_reg_names
[] =
72 "s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3"
75 /* Scalar register names. set_mips_isa_type() decides which register name
77 static CONST
char * CONST
*reg_names
= NULL
;
81 print_insn_arg (d
, l
, pc
, info
)
83 register unsigned long int l
;
85 struct disassemble_info
*info
;
94 (*info
->fprintf_func
) (info
->stream
, "%c", *d
);
101 (*info
->fprintf_func
) (info
->stream
, "$%s",
102 reg_names
[(l
>> OP_SH_RS
) & OP_MASK_RS
]);
107 (*info
->fprintf_func
) (info
->stream
, "$%s",
108 reg_names
[(l
>> OP_SH_RT
) & OP_MASK_RT
]);
113 (*info
->fprintf_func
) (info
->stream
, "0x%x",
114 (l
>> OP_SH_IMMEDIATE
) & OP_MASK_IMMEDIATE
);
117 case 'j': /* same as i, but sign-extended */
119 delta
= (l
>> OP_SH_DELTA
) & OP_MASK_DELTA
;
122 (*info
->fprintf_func
) (info
->stream
, "%d",
127 (*info
->fprintf_func
) (info
->stream
, "0x%x",
128 (unsigned int) ((l
>> OP_SH_PREFX
)
133 (*info
->fprintf_func
) (info
->stream
, "0x%x",
134 (unsigned int) ((l
>> OP_SH_CACHE
)
139 (*info
->print_address_func
)
140 (((pc
& ~ (bfd_vma
) 0x0fffffff)
141 | (((l
>> OP_SH_TARGET
) & OP_MASK_TARGET
) << 2)),
146 /* sign extend the displacement */
147 delta
= (l
>> OP_SH_DELTA
) & OP_MASK_DELTA
;
150 (*info
->print_address_func
)
151 ((delta
<< 2) + pc
+ 4,
156 (*info
->fprintf_func
) (info
->stream
, "$%s",
157 reg_names
[(l
>> OP_SH_RD
) & OP_MASK_RD
]);
162 /* First check for both rd and rt being equal. */
163 int reg
= (l
>> OP_SH_RD
) & OP_MASK_RD
;
164 if (reg
== ((l
>> OP_SH_RT
) & OP_MASK_RT
))
165 (*info
->fprintf_func
) (info
->stream
, "$%s",
169 /* If one is zero use the other. */
171 (*info
->fprintf_func
) (info
->stream
, "$%s",
172 reg_names
[(l
>> OP_SH_RT
) & OP_MASK_RT
]);
173 else if (((l
>> OP_SH_RT
) & OP_MASK_RT
) == 0)
174 (*info
->fprintf_func
) (info
->stream
, "$%s",
176 else /* Bogus, result depends on processor. */
177 (*info
->fprintf_func
) (info
->stream
, "$%s or $%s",
179 reg_names
[(l
>> OP_SH_RT
) & OP_MASK_RT
]);
185 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[0]);
189 (*info
->fprintf_func
) (info
->stream
, "0x%x",
190 (l
>> OP_SH_SHAMT
) & OP_MASK_SHAMT
);
194 (*info
->fprintf_func
) (info
->stream
, "0x%x",
195 (l
>> OP_SH_CODE
) & OP_MASK_CODE
);
199 (*info
->fprintf_func
) (info
->stream
, "0x%x",
200 (l
>> OP_SH_CODE2
) & OP_MASK_CODE2
);
204 (*info
->fprintf_func
) (info
->stream
, "0x%x",
205 (l
>> OP_SH_COPZ
) & OP_MASK_COPZ
);
209 (*info
->fprintf_func
) (info
->stream
, "0x%x",
210 (l
>> OP_SH_CODE20
) & OP_MASK_CODE20
);
214 (*info
->fprintf_func
) (info
->stream
, "0x%x",
215 (l
>> OP_SH_CODE19
) & OP_MASK_CODE19
);
220 (*info
->fprintf_func
) (info
->stream
, "$f%d",
221 (l
>> OP_SH_FS
) & OP_MASK_FS
);
226 (*info
->fprintf_func
) (info
->stream
, "$f%d",
227 (l
>> OP_SH_FT
) & OP_MASK_FT
);
231 (*info
->fprintf_func
) (info
->stream
, "$f%d",
232 (l
>> OP_SH_FD
) & OP_MASK_FD
);
236 (*info
->fprintf_func
) (info
->stream
, "$f%d",
237 (l
>> OP_SH_FR
) & OP_MASK_FR
);
241 (*info
->fprintf_func
) (info
->stream
, "$%d",
242 (l
>> OP_SH_RT
) & OP_MASK_RT
);
246 (*info
->fprintf_func
) (info
->stream
, "$%d",
247 (l
>> OP_SH_RD
) & OP_MASK_RD
);
251 (*info
->fprintf_func
) (info
->stream
, "$fcc%d",
252 (l
>> OP_SH_BCC
) & OP_MASK_BCC
);
256 (*info
->fprintf_func
) (info
->stream
, "$fcc%d",
257 (l
>> OP_SH_CCC
) & OP_MASK_CCC
);
261 (*info
->fprintf_func
) (info
->stream
, "%d",
262 (l
>> OP_SH_PERFREG
) & OP_MASK_PERFREG
);
266 (*info
->fprintf_func
) (info
->stream
, "%d",
267 (l
>> OP_SH_SEL
) & OP_MASK_SEL
);
271 /* xgettext:c-format */
272 (*info
->fprintf_func
) (info
->stream
,
273 _("# internal error, undefined modifier(%c)"),
281 /* Figure out the MIPS ISA and CPU based on the machine number.
282 FIXME: What does this have to do with SYMTAB_AVAILABLE? */
285 set_mips_isa_type (mach
, isa
, cputype
)
290 int target_processor
= CPU_UNKNOWN
;
291 int mips_isa
= ISA_UNKNOWN
;
293 /* Use standard MIPS register names by default. */
294 reg_names
= std_reg_names
;
298 case bfd_mach_mips3000
:
299 target_processor
= CPU_R3000
;
300 mips_isa
= ISA_MIPS1
;
302 case bfd_mach_mips3900
:
303 target_processor
= CPU_R3900
;
304 mips_isa
= ISA_MIPS1
;
306 case bfd_mach_mips4000
:
307 target_processor
= CPU_R4000
;
308 mips_isa
= ISA_MIPS3
;
310 case bfd_mach_mips4010
:
311 target_processor
= CPU_R4010
;
312 mips_isa
= ISA_MIPS2
;
314 case bfd_mach_mips4100
:
315 target_processor
= CPU_VR4100
;
316 mips_isa
= ISA_MIPS3
;
318 case bfd_mach_mips4111
:
319 target_processor
= CPU_VR4100
; /* FIXME: Shouldn't this be CPU_R4111 ??? */
320 mips_isa
= ISA_MIPS3
;
322 case bfd_mach_mips4300
:
323 target_processor
= CPU_R4300
;
324 mips_isa
= ISA_MIPS3
;
326 case bfd_mach_mips4400
:
327 target_processor
= CPU_R4400
;
328 mips_isa
= ISA_MIPS3
;
330 case bfd_mach_mips4600
:
331 target_processor
= CPU_R4600
;
332 mips_isa
= ISA_MIPS3
;
334 case bfd_mach_mips4650
:
335 target_processor
= CPU_R4650
;
336 mips_isa
= ISA_MIPS3
;
338 case bfd_mach_mips5000
:
339 target_processor
= CPU_R5000
;
340 mips_isa
= ISA_MIPS4
;
342 case bfd_mach_mips6000
:
343 target_processor
= CPU_R6000
;
344 mips_isa
= ISA_MIPS2
;
346 case bfd_mach_mips8000
:
347 target_processor
= CPU_R8000
;
348 mips_isa
= ISA_MIPS4
;
350 case bfd_mach_mips10000
:
351 target_processor
= CPU_R10000
;
352 mips_isa
= ISA_MIPS4
;
354 case bfd_mach_mips16
:
355 target_processor
= CPU_MIPS16
;
356 mips_isa
= ISA_MIPS3
;
358 case bfd_mach_mips32
:
359 target_processor
= CPU_MIPS32
;
360 mips_isa
= ISA_MIPS32
;
362 case bfd_mach_mips32_4k
:
363 target_processor
= CPU_MIPS32_4K
;
364 mips_isa
= ISA_MIPS32
;
367 target_processor
= CPU_MIPS5
;
368 mips_isa
= ISA_MIPS5
;
370 case bfd_mach_mips64
:
371 target_processor
= CPU_MIPS64
;
372 mips_isa
= ISA_MIPS64
;
374 case bfd_mach_mips_sb1
:
375 target_processor
= CPU_SB1
;
376 mips_isa
= ISA_MIPS64
;
379 target_processor
= CPU_R3000
;
380 mips_isa
= ISA_MIPS3
;
385 *cputype
= target_processor
;
388 #endif /* SYMTAB_AVAILABLE */
390 /* Print the mips instruction at address MEMADDR in debugged memory,
391 on using INFO. Returns length of the instruction, in bytes, which is
392 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
393 this is little-endian code. */
396 _print_insn_mips (memaddr
, word
, info
)
398 unsigned long int word
;
399 struct disassemble_info
*info
;
401 register const struct mips_opcode
*op
;
402 int target_processor
, mips_isa
;
403 static boolean init
= 0;
404 static const struct mips_opcode
*mips_hash
[OP_MASK_OP
+ 1];
406 /* Build a hash table to shorten the search time. */
411 for (i
= 0; i
<= OP_MASK_OP
; i
++)
413 for (op
= mips_opcodes
; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
415 if (op
->pinfo
== INSN_MACRO
)
417 if (i
== ((op
->match
>> OP_SH_OP
) & OP_MASK_OP
))
428 #if ! SYMTAB_AVAILABLE
429 /* This is running out on a target machine, not in a host tool.
430 FIXME: Where does mips_target_info come from? */
431 target_processor
= mips_target_info
.processor
;
432 mips_isa
= mips_target_info
.isa
;
434 set_mips_isa_type (info
->mach
, &mips_isa
, &target_processor
);
437 info
->bytes_per_chunk
= 4;
438 info
->display_endian
= info
->endian
;
440 op
= mips_hash
[(word
>> OP_SH_OP
) & OP_MASK_OP
];
443 for (; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
445 if (op
->pinfo
!= INSN_MACRO
&& (word
& op
->mask
) == op
->match
)
447 register const char *d
;
449 if (! OPCODE_IS_MEMBER (op
, mips_isa
, target_processor
, 0))
452 (*info
->fprintf_func
) (info
->stream
, "%s", op
->name
);
455 if (d
!= NULL
&& *d
!= '\0')
457 (*info
->fprintf_func
) (info
->stream
, "\t");
458 for (; *d
!= '\0'; d
++)
459 print_insn_arg (d
, word
, memaddr
, info
);
467 /* Handle undefined instructions. */
468 (*info
->fprintf_func
) (info
->stream
, "0x%x", word
);
473 /* In an environment where we do not know the symbol type of the
474 instruction we are forced to assume that the low order bit of the
475 instructions' address may mark it as a mips16 instruction. If we
476 are single stepping, or the pc is within the disassembled function,
477 this works. Otherwise, we need a clue. Sometimes. */
480 print_insn_big_mips (memaddr
, info
)
482 struct disassemble_info
*info
;
488 /* FIXME: If odd address, this is CLEARLY a mips 16 instruction. */
489 /* Only a few tools will work this way. */
491 return print_insn_mips16 (memaddr
, info
);
496 || (info
->flavour
== bfd_target_elf_flavour
497 && info
->symbols
!= NULL
498 && ((*(elf_symbol_type
**) info
->symbols
)->internal_elf_sym
.st_other
500 return print_insn_mips16 (memaddr
, info
);
503 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
505 return _print_insn_mips (memaddr
, (unsigned long) bfd_getb32 (buffer
),
509 (*info
->memory_error_func
) (status
, memaddr
, info
);
515 print_insn_little_mips (memaddr
, info
)
517 struct disassemble_info
*info
;
525 return print_insn_mips16 (memaddr
, info
);
530 || (info
->flavour
== bfd_target_elf_flavour
531 && info
->symbols
!= NULL
532 && ((*(elf_symbol_type
**) info
->symbols
)->internal_elf_sym
.st_other
534 return print_insn_mips16 (memaddr
, info
);
537 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
539 return _print_insn_mips (memaddr
, (unsigned long) bfd_getl32 (buffer
),
543 (*info
->memory_error_func
) (status
, memaddr
, info
);
548 /* Disassemble mips16 instructions. */
551 print_insn_mips16 (memaddr
, info
)
553 struct disassemble_info
*info
;
561 const struct mips_opcode
*op
, *opend
;
563 info
->bytes_per_chunk
= 2;
564 info
->display_endian
= info
->endian
;
566 info
->insn_info_valid
= 1;
567 info
->branch_delay_insns
= 0;
569 info
->insn_type
= dis_nonbranch
;
573 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
576 (*info
->memory_error_func
) (status
, memaddr
, info
);
582 if (info
->endian
== BFD_ENDIAN_BIG
)
583 insn
= bfd_getb16 (buffer
);
585 insn
= bfd_getl16 (buffer
);
587 /* Handle the extend opcode specially. */
589 if ((insn
& 0xf800) == 0xf000)
592 extend
= insn
& 0x7ff;
596 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
599 (*info
->fprintf_func
) (info
->stream
, "extend 0x%x",
600 (unsigned int) extend
);
601 (*info
->memory_error_func
) (status
, memaddr
, info
);
605 if (info
->endian
== BFD_ENDIAN_BIG
)
606 insn
= bfd_getb16 (buffer
);
608 insn
= bfd_getl16 (buffer
);
610 /* Check for an extend opcode followed by an extend opcode. */
611 if ((insn
& 0xf800) == 0xf000)
613 (*info
->fprintf_func
) (info
->stream
, "extend 0x%x",
614 (unsigned int) extend
);
615 info
->insn_type
= dis_noninsn
;
622 /* FIXME: Should probably use a hash table on the major opcode here. */
624 opend
= mips16_opcodes
+ bfd_mips16_num_opcodes
;
625 for (op
= mips16_opcodes
; op
< opend
; op
++)
627 if (op
->pinfo
!= INSN_MACRO
&& (insn
& op
->mask
) == op
->match
)
631 if (strchr (op
->args
, 'a') != NULL
)
635 (*info
->fprintf_func
) (info
->stream
, "extend 0x%x",
636 (unsigned int) extend
);
637 info
->insn_type
= dis_noninsn
;
645 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2,
650 if (info
->endian
== BFD_ENDIAN_BIG
)
651 extend
= bfd_getb16 (buffer
);
653 extend
= bfd_getl16 (buffer
);
658 (*info
->fprintf_func
) (info
->stream
, "%s", op
->name
);
659 if (op
->args
[0] != '\0')
660 (*info
->fprintf_func
) (info
->stream
, "\t");
662 for (s
= op
->args
; *s
!= '\0'; s
++)
666 && (((insn
>> MIPS16OP_SH_RX
) & MIPS16OP_MASK_RX
)
667 == ((insn
>> MIPS16OP_SH_RY
) & MIPS16OP_MASK_RY
)))
669 /* Skip the register and the comma. */
675 && (((insn
>> MIPS16OP_SH_RZ
) & MIPS16OP_MASK_RZ
)
676 == ((insn
>> MIPS16OP_SH_RX
) & MIPS16OP_MASK_RX
)))
678 /* Skip the register and the comma. */
682 print_mips16_insn_arg (*s
, op
, insn
, use_extend
, extend
, memaddr
,
686 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
688 info
->branch_delay_insns
= 1;
689 if (info
->insn_type
!= dis_jsr
)
690 info
->insn_type
= dis_branch
;
698 (*info
->fprintf_func
) (info
->stream
, "0x%x", extend
| 0xf000);
699 (*info
->fprintf_func
) (info
->stream
, "0x%x", insn
);
700 info
->insn_type
= dis_noninsn
;
705 /* Disassemble an operand for a mips16 instruction. */
708 print_mips16_insn_arg (type
, op
, l
, use_extend
, extend
, memaddr
, info
)
710 const struct mips_opcode
*op
;
715 struct disassemble_info
*info
;
722 (*info
->fprintf_func
) (info
->stream
, "%c", type
);
727 (*info
->fprintf_func
) (info
->stream
, "$%s",
728 mips16_reg_names
[((l
>> MIPS16OP_SH_RY
)
729 & MIPS16OP_MASK_RY
)]);
734 (*info
->fprintf_func
) (info
->stream
, "$%s",
735 mips16_reg_names
[((l
>> MIPS16OP_SH_RX
)
736 & MIPS16OP_MASK_RX
)]);
740 (*info
->fprintf_func
) (info
->stream
, "$%s",
741 mips16_reg_names
[((l
>> MIPS16OP_SH_RZ
)
742 & MIPS16OP_MASK_RZ
)]);
746 (*info
->fprintf_func
) (info
->stream
, "$%s",
747 mips16_reg_names
[((l
>> MIPS16OP_SH_MOVE32Z
)
748 & MIPS16OP_MASK_MOVE32Z
)]);
752 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[0]);
756 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[29]);
760 (*info
->fprintf_func
) (info
->stream
, "$pc");
764 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[31]);
768 (*info
->fprintf_func
) (info
->stream
, "$%s",
769 reg_names
[((l
>> MIPS16OP_SH_REGR32
)
770 & MIPS16OP_MASK_REGR32
)]);
774 (*info
->fprintf_func
) (info
->stream
, "$%s",
775 reg_names
[MIPS16OP_EXTRACT_REG32R (l
)]);
801 int immed
, nbits
, shift
, signedp
, extbits
, pcrel
, extu
, branch
;
813 immed
= (l
>> MIPS16OP_SH_RZ
) & MIPS16OP_MASK_RZ
;
819 immed
= (l
>> MIPS16OP_SH_RX
) & MIPS16OP_MASK_RX
;
825 immed
= (l
>> MIPS16OP_SH_RZ
) & MIPS16OP_MASK_RZ
;
831 immed
= (l
>> MIPS16OP_SH_RX
) & MIPS16OP_MASK_RX
;
837 immed
= (l
>> MIPS16OP_SH_IMM4
) & MIPS16OP_MASK_IMM4
;
843 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
844 info
->insn_type
= dis_dref
;
850 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
851 info
->insn_type
= dis_dref
;
857 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
858 if ((op
->pinfo
& MIPS16_INSN_READ_PC
) == 0
859 && (op
->pinfo
& MIPS16_INSN_READ_SP
) == 0)
861 info
->insn_type
= dis_dref
;
868 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
869 info
->insn_type
= dis_dref
;
874 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
879 immed
= (l
>> MIPS16OP_SH_IMM6
) & MIPS16OP_MASK_IMM6
;
883 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
888 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
889 /* FIXME: This might be lw, or it might be addiu to $sp or
890 $pc. We assume it's load. */
891 info
->insn_type
= dis_dref
;
897 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
898 info
->insn_type
= dis_dref
;
903 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
908 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
914 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
919 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
923 info
->insn_type
= dis_condbranch
;
927 immed
= (l
>> MIPS16OP_SH_IMM11
) & MIPS16OP_MASK_IMM11
;
931 info
->insn_type
= dis_branch
;
936 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
938 /* FIXME: This can be lw or la. We assume it is lw. */
939 info
->insn_type
= dis_dref
;
945 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
947 info
->insn_type
= dis_dref
;
953 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
962 if (signedp
&& immed
>= (1 << (nbits
- 1)))
965 if ((type
== '<' || type
== '>' || type
== '[' || type
== ']')
972 immed
|= ((extend
& 0x1f) << 11) | (extend
& 0x7e0);
973 else if (extbits
== 15)
974 immed
|= ((extend
& 0xf) << 11) | (extend
& 0x7f0);
976 immed
= ((extend
>> 6) & 0x1f) | (extend
& 0x20);
977 immed
&= (1 << extbits
) - 1;
978 if (! extu
&& immed
>= (1 << (extbits
- 1)))
979 immed
-= 1 << extbits
;
983 (*info
->fprintf_func
) (info
->stream
, "%d", immed
);
992 baseaddr
= memaddr
+ 2;
995 baseaddr
= memaddr
- 2;
1003 /* If this instruction is in the delay slot of a jr
1004 instruction, the base address is the address of the
1005 jr instruction. If it is in the delay slot of jalr
1006 instruction, the base address is the address of the
1007 jalr instruction. This test is unreliable: we have
1008 no way of knowing whether the previous word is
1009 instruction or data. */
1010 status
= (*info
->read_memory_func
) (memaddr
- 4, buffer
, 2,
1013 && (((info
->endian
== BFD_ENDIAN_BIG
1014 ? bfd_getb16 (buffer
)
1015 : bfd_getl16 (buffer
))
1016 & 0xf800) == 0x1800))
1017 baseaddr
= memaddr
- 4;
1020 status
= (*info
->read_memory_func
) (memaddr
- 2, buffer
,
1023 && (((info
->endian
== BFD_ENDIAN_BIG
1024 ? bfd_getb16 (buffer
)
1025 : bfd_getl16 (buffer
))
1026 & 0xf81f) == 0xe800))
1027 baseaddr
= memaddr
- 2;
1030 val
= (baseaddr
& ~ ((1 << shift
) - 1)) + immed
;
1031 (*info
->print_address_func
) (val
, info
);
1040 l
= ((l
& 0x1f) << 23) | ((l
& 0x3e0) << 13) | (extend
<< 2);
1041 (*info
->print_address_func
) ((memaddr
& 0xf0000000) | l
, info
);
1042 info
->insn_type
= dis_jsr
;
1043 info
->target
= (memaddr
& 0xf0000000) | l
;
1044 info
->branch_delay_insns
= 1;
1050 int need_comma
, amask
, smask
;
1054 l
= (l
>> MIPS16OP_SH_IMM6
) & MIPS16OP_MASK_IMM6
;
1056 amask
= (l
>> 3) & 7;
1058 if (amask
> 0 && amask
< 5)
1060 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[4]);
1062 (*info
->fprintf_func
) (info
->stream
, "-$%s",
1063 reg_names
[amask
+ 3]);
1067 smask
= (l
>> 1) & 3;
1070 (*info
->fprintf_func
) (info
->stream
, "%s??",
1071 need_comma
? "," : "");
1076 (*info
->fprintf_func
) (info
->stream
, "%s$%s",
1077 need_comma
? "," : "",
1080 (*info
->fprintf_func
) (info
->stream
, "-$%s",
1081 reg_names
[smask
+ 15]);
1087 (*info
->fprintf_func
) (info
->stream
, "%s$%s",
1088 need_comma
? "," : "",
1093 if (amask
== 5 || amask
== 6)
1095 (*info
->fprintf_func
) (info
->stream
, "%s$f0",
1096 need_comma
? "," : "");
1098 (*info
->fprintf_func
) (info
->stream
, "-$f1");