1 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2 Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4 Free Software Foundation, Inc.
5 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
7 This file is part of GDB, GAS, and the GNU binutils.
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.
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.
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. */
25 #include "opcode/mips.h"
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. */
33 #if !defined(EMBEDDED_ENV)
34 #define SYMTAB_AVAILABLE 1
39 static int print_insn_mips16
PARAMS ((bfd_vma
, struct disassemble_info
*));
40 static void print_mips16_insn_arg
41 PARAMS ((int, const struct mips_opcode
*, int, boolean
, int, bfd_vma
,
42 struct disassemble_info
*));
44 /* Mips instructions are never longer than this many bytes. */
47 static void print_insn_arg
PARAMS ((const char *, unsigned long, bfd_vma
,
48 struct disassemble_info
*));
49 static int _print_insn_mips
PARAMS ((bfd_vma
, unsigned long int,
50 struct disassemble_info
*));
53 /* FIXME: This should be shared with gdb somehow. */
54 #define STD_REGISTER_NAMES \
55 { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
56 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
57 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
58 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
59 "sr", "lo", "hi", "bad", "cause","pc", \
60 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
61 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
62 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
63 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
64 "fsr", "fir", "fp", "inx", "rand", "tlblo","ctxt", "tlbhi",\
68 static CONST
char * CONST std_reg_names
[] = STD_REGISTER_NAMES
;
70 /* The mips16 register names. */
71 static const char * const mips16_reg_names
[] =
73 "s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3"
76 /* Scalar register names. set_mips_isa_type() decides which register name
78 static CONST
char * CONST
*reg_names
= NULL
;
82 print_insn_arg (d
, l
, pc
, info
)
84 register unsigned long int l
;
86 struct disassemble_info
*info
;
95 (*info
->fprintf_func
) (info
->stream
, "%c", *d
);
102 (*info
->fprintf_func
) (info
->stream
, "$%s",
103 reg_names
[(l
>> OP_SH_RS
) & OP_MASK_RS
]);
108 (*info
->fprintf_func
) (info
->stream
, "$%s",
109 reg_names
[(l
>> OP_SH_RT
) & OP_MASK_RT
]);
114 (*info
->fprintf_func
) (info
->stream
, "0x%x",
115 (l
>> OP_SH_IMMEDIATE
) & OP_MASK_IMMEDIATE
);
118 case 'j': /* same as i, but sign-extended */
120 delta
= (l
>> OP_SH_DELTA
) & OP_MASK_DELTA
;
123 (*info
->fprintf_func
) (info
->stream
, "%d",
128 (*info
->fprintf_func
) (info
->stream
, "0x%x",
129 (unsigned int) ((l
>> OP_SH_PREFX
)
134 (*info
->fprintf_func
) (info
->stream
, "0x%x",
135 (unsigned int) ((l
>> OP_SH_CACHE
)
140 (*info
->print_address_func
)
141 ((((pc
+ 4) & ~ (bfd_vma
) 0x0fffffff)
142 | (((l
>> OP_SH_TARGET
) & OP_MASK_TARGET
) << 2)),
147 /* sign extend the displacement */
148 delta
= (l
>> OP_SH_DELTA
) & OP_MASK_DELTA
;
151 (*info
->print_address_func
)
152 ((delta
<< 2) + pc
+ 4,
157 (*info
->fprintf_func
) (info
->stream
, "$%s",
158 reg_names
[(l
>> OP_SH_RD
) & OP_MASK_RD
]);
163 /* First check for both rd and rt being equal. */
164 int reg
= (l
>> OP_SH_RD
) & OP_MASK_RD
;
165 if (reg
== ((l
>> OP_SH_RT
) & OP_MASK_RT
))
166 (*info
->fprintf_func
) (info
->stream
, "$%s",
170 /* If one is zero use the other. */
172 (*info
->fprintf_func
) (info
->stream
, "$%s",
173 reg_names
[(l
>> OP_SH_RT
) & OP_MASK_RT
]);
174 else if (((l
>> OP_SH_RT
) & OP_MASK_RT
) == 0)
175 (*info
->fprintf_func
) (info
->stream
, "$%s",
177 else /* Bogus, result depends on processor. */
178 (*info
->fprintf_func
) (info
->stream
, "$%s or $%s",
180 reg_names
[(l
>> OP_SH_RT
) & OP_MASK_RT
]);
186 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[0]);
190 (*info
->fprintf_func
) (info
->stream
, "0x%x",
191 (l
>> OP_SH_SHAMT
) & OP_MASK_SHAMT
);
195 (*info
->fprintf_func
) (info
->stream
, "0x%x",
196 (l
>> OP_SH_CODE
) & OP_MASK_CODE
);
200 (*info
->fprintf_func
) (info
->stream
, "0x%x",
201 (l
>> OP_SH_CODE2
) & OP_MASK_CODE2
);
205 (*info
->fprintf_func
) (info
->stream
, "0x%x",
206 (l
>> OP_SH_COPZ
) & OP_MASK_COPZ
);
210 (*info
->fprintf_func
) (info
->stream
, "0x%x",
211 (l
>> OP_SH_CODE20
) & OP_MASK_CODE20
);
215 (*info
->fprintf_func
) (info
->stream
, "0x%x",
216 (l
>> OP_SH_CODE19
) & OP_MASK_CODE19
);
221 (*info
->fprintf_func
) (info
->stream
, "$f%d",
222 (l
>> OP_SH_FS
) & OP_MASK_FS
);
227 (*info
->fprintf_func
) (info
->stream
, "$f%d",
228 (l
>> OP_SH_FT
) & OP_MASK_FT
);
232 (*info
->fprintf_func
) (info
->stream
, "$f%d",
233 (l
>> OP_SH_FD
) & OP_MASK_FD
);
237 (*info
->fprintf_func
) (info
->stream
, "$f%d",
238 (l
>> OP_SH_FR
) & OP_MASK_FR
);
242 (*info
->fprintf_func
) (info
->stream
, "$%d",
243 (l
>> OP_SH_RT
) & OP_MASK_RT
);
247 (*info
->fprintf_func
) (info
->stream
, "$%d",
248 (l
>> OP_SH_RD
) & OP_MASK_RD
);
252 (*info
->fprintf_func
) (info
->stream
, "$fcc%d",
253 (l
>> OP_SH_BCC
) & OP_MASK_BCC
);
257 (*info
->fprintf_func
) (info
->stream
, "$fcc%d",
258 (l
>> OP_SH_CCC
) & OP_MASK_CCC
);
262 (*info
->fprintf_func
) (info
->stream
, "%d",
263 (l
>> OP_SH_PERFREG
) & OP_MASK_PERFREG
);
267 (*info
->fprintf_func
) (info
->stream
, "%d",
268 (l
>> OP_SH_SEL
) & OP_MASK_SEL
);
272 /* xgettext:c-format */
273 (*info
->fprintf_func
) (info
->stream
,
274 _("# internal error, undefined modifier(%c)"),
282 /* Figure out the MIPS ISA and CPU based on the machine number.
283 FIXME: What does this have to do with SYMTAB_AVAILABLE? */
286 set_mips_isa_type (mach
, isa
, cputype
)
291 int target_processor
= CPU_UNKNOWN
;
292 int mips_isa
= ISA_UNKNOWN
;
294 /* Use standard MIPS register names by default. */
295 reg_names
= std_reg_names
;
299 case bfd_mach_mips3000
:
300 target_processor
= CPU_R3000
;
301 mips_isa
= ISA_MIPS1
;
303 case bfd_mach_mips3900
:
304 target_processor
= CPU_R3900
;
305 mips_isa
= ISA_MIPS1
;
307 case bfd_mach_mips4000
:
308 target_processor
= CPU_R4000
;
309 mips_isa
= ISA_MIPS3
;
311 case bfd_mach_mips4010
:
312 target_processor
= CPU_R4010
;
313 mips_isa
= ISA_MIPS2
;
315 case bfd_mach_mips4100
:
316 target_processor
= CPU_VR4100
;
317 mips_isa
= ISA_MIPS3
;
319 case bfd_mach_mips4111
:
320 target_processor
= CPU_VR4100
; /* FIXME: Shouldn't this be CPU_R4111 ??? */
321 mips_isa
= ISA_MIPS3
;
323 case bfd_mach_mips4300
:
324 target_processor
= CPU_R4300
;
325 mips_isa
= ISA_MIPS3
;
327 case bfd_mach_mips4400
:
328 target_processor
= CPU_R4400
;
329 mips_isa
= ISA_MIPS3
;
331 case bfd_mach_mips4600
:
332 target_processor
= CPU_R4600
;
333 mips_isa
= ISA_MIPS3
;
335 case bfd_mach_mips4650
:
336 target_processor
= CPU_R4650
;
337 mips_isa
= ISA_MIPS3
;
339 case bfd_mach_mips5000
:
340 target_processor
= CPU_R5000
;
341 mips_isa
= ISA_MIPS4
;
343 case bfd_mach_mips6000
:
344 target_processor
= CPU_R6000
;
345 mips_isa
= ISA_MIPS2
;
347 case bfd_mach_mips8000
:
348 target_processor
= CPU_R8000
;
349 mips_isa
= ISA_MIPS4
;
351 case bfd_mach_mips10000
:
352 target_processor
= CPU_R10000
;
353 mips_isa
= ISA_MIPS4
;
355 case bfd_mach_mips16
:
356 target_processor
= CPU_MIPS16
;
357 mips_isa
= ISA_MIPS3
;
359 case bfd_mach_mips32
:
360 target_processor
= CPU_MIPS32
;
361 mips_isa
= ISA_MIPS32
;
363 case bfd_mach_mips32_4k
:
364 target_processor
= CPU_MIPS32_4K
;
365 mips_isa
= ISA_MIPS32
;
368 target_processor
= CPU_MIPS5
;
369 mips_isa
= ISA_MIPS5
;
371 case bfd_mach_mips64
:
372 target_processor
= CPU_MIPS64
;
373 mips_isa
= ISA_MIPS64
;
375 case bfd_mach_mips_sb1
:
376 target_processor
= CPU_SB1
;
377 mips_isa
= ISA_MIPS64
;
380 target_processor
= CPU_R3000
;
381 mips_isa
= ISA_MIPS3
;
386 *cputype
= target_processor
;
389 #endif /* SYMTAB_AVAILABLE */
391 /* Print the mips instruction at address MEMADDR in debugged memory,
392 on using INFO. Returns length of the instruction, in bytes, which is
393 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
394 this is little-endian code. */
397 _print_insn_mips (memaddr
, word
, info
)
399 unsigned long int word
;
400 struct disassemble_info
*info
;
402 register const struct mips_opcode
*op
;
403 int target_processor
, mips_isa
;
404 static boolean init
= 0;
405 static const struct mips_opcode
*mips_hash
[OP_MASK_OP
+ 1];
407 /* Build a hash table to shorten the search time. */
412 for (i
= 0; i
<= OP_MASK_OP
; i
++)
414 for (op
= mips_opcodes
; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
416 if (op
->pinfo
== INSN_MACRO
)
418 if (i
== ((op
->match
>> OP_SH_OP
) & OP_MASK_OP
))
429 #if ! SYMTAB_AVAILABLE
430 /* This is running out on a target machine, not in a host tool.
431 FIXME: Where does mips_target_info come from? */
432 target_processor
= mips_target_info
.processor
;
433 mips_isa
= mips_target_info
.isa
;
435 set_mips_isa_type (info
->mach
, &mips_isa
, &target_processor
);
438 info
->bytes_per_chunk
= 4;
439 info
->display_endian
= info
->endian
;
441 op
= mips_hash
[(word
>> OP_SH_OP
) & OP_MASK_OP
];
444 for (; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
446 if (op
->pinfo
!= INSN_MACRO
&& (word
& op
->mask
) == op
->match
)
448 register const char *d
;
450 if (! OPCODE_IS_MEMBER (op
, mips_isa
, target_processor
, 0))
453 (*info
->fprintf_func
) (info
->stream
, "%s", op
->name
);
456 if (d
!= NULL
&& *d
!= '\0')
458 (*info
->fprintf_func
) (info
->stream
, "\t");
459 for (; *d
!= '\0'; d
++)
460 print_insn_arg (d
, word
, memaddr
, info
);
468 /* Handle undefined instructions. */
469 (*info
->fprintf_func
) (info
->stream
, "0x%x", word
);
474 /* In an environment where we do not know the symbol type of the
475 instruction we are forced to assume that the low order bit of the
476 instructions' address may mark it as a mips16 instruction. If we
477 are single stepping, or the pc is within the disassembled function,
478 this works. Otherwise, we need a clue. Sometimes. */
481 print_insn_big_mips (memaddr
, info
)
483 struct disassemble_info
*info
;
489 /* FIXME: If odd address, this is CLEARLY a mips 16 instruction. */
490 /* Only a few tools will work this way. */
492 return print_insn_mips16 (memaddr
, info
);
497 || (info
->flavour
== bfd_target_elf_flavour
498 && info
->symbols
!= NULL
499 && ((*(elf_symbol_type
**) info
->symbols
)->internal_elf_sym
.st_other
501 return print_insn_mips16 (memaddr
, info
);
504 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
506 return _print_insn_mips (memaddr
, (unsigned long) bfd_getb32 (buffer
),
510 (*info
->memory_error_func
) (status
, memaddr
, info
);
516 print_insn_little_mips (memaddr
, info
)
518 struct disassemble_info
*info
;
526 return print_insn_mips16 (memaddr
, info
);
531 || (info
->flavour
== bfd_target_elf_flavour
532 && info
->symbols
!= NULL
533 && ((*(elf_symbol_type
**) info
->symbols
)->internal_elf_sym
.st_other
535 return print_insn_mips16 (memaddr
, info
);
538 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
540 return _print_insn_mips (memaddr
, (unsigned long) bfd_getl32 (buffer
),
544 (*info
->memory_error_func
) (status
, memaddr
, info
);
549 /* Disassemble mips16 instructions. */
552 print_insn_mips16 (memaddr
, info
)
554 struct disassemble_info
*info
;
562 const struct mips_opcode
*op
, *opend
;
564 info
->bytes_per_chunk
= 2;
565 info
->display_endian
= info
->endian
;
567 info
->insn_info_valid
= 1;
568 info
->branch_delay_insns
= 0;
570 info
->insn_type
= dis_nonbranch
;
574 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
577 (*info
->memory_error_func
) (status
, memaddr
, info
);
583 if (info
->endian
== BFD_ENDIAN_BIG
)
584 insn
= bfd_getb16 (buffer
);
586 insn
= bfd_getl16 (buffer
);
588 /* Handle the extend opcode specially. */
590 if ((insn
& 0xf800) == 0xf000)
593 extend
= insn
& 0x7ff;
597 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
600 (*info
->fprintf_func
) (info
->stream
, "extend 0x%x",
601 (unsigned int) extend
);
602 (*info
->memory_error_func
) (status
, memaddr
, info
);
606 if (info
->endian
== BFD_ENDIAN_BIG
)
607 insn
= bfd_getb16 (buffer
);
609 insn
= bfd_getl16 (buffer
);
611 /* Check for an extend opcode followed by an extend opcode. */
612 if ((insn
& 0xf800) == 0xf000)
614 (*info
->fprintf_func
) (info
->stream
, "extend 0x%x",
615 (unsigned int) extend
);
616 info
->insn_type
= dis_noninsn
;
623 /* FIXME: Should probably use a hash table on the major opcode here. */
625 opend
= mips16_opcodes
+ bfd_mips16_num_opcodes
;
626 for (op
= mips16_opcodes
; op
< opend
; op
++)
628 if (op
->pinfo
!= INSN_MACRO
&& (insn
& op
->mask
) == op
->match
)
632 if (strchr (op
->args
, 'a') != NULL
)
636 (*info
->fprintf_func
) (info
->stream
, "extend 0x%x",
637 (unsigned int) extend
);
638 info
->insn_type
= dis_noninsn
;
646 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2,
651 if (info
->endian
== BFD_ENDIAN_BIG
)
652 extend
= bfd_getb16 (buffer
);
654 extend
= bfd_getl16 (buffer
);
659 (*info
->fprintf_func
) (info
->stream
, "%s", op
->name
);
660 if (op
->args
[0] != '\0')
661 (*info
->fprintf_func
) (info
->stream
, "\t");
663 for (s
= op
->args
; *s
!= '\0'; s
++)
667 && (((insn
>> MIPS16OP_SH_RX
) & MIPS16OP_MASK_RX
)
668 == ((insn
>> MIPS16OP_SH_RY
) & MIPS16OP_MASK_RY
)))
670 /* Skip the register and the comma. */
676 && (((insn
>> MIPS16OP_SH_RZ
) & MIPS16OP_MASK_RZ
)
677 == ((insn
>> MIPS16OP_SH_RX
) & MIPS16OP_MASK_RX
)))
679 /* Skip the register and the comma. */
683 print_mips16_insn_arg (*s
, op
, insn
, use_extend
, extend
, memaddr
,
687 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
689 info
->branch_delay_insns
= 1;
690 if (info
->insn_type
!= dis_jsr
)
691 info
->insn_type
= dis_branch
;
699 (*info
->fprintf_func
) (info
->stream
, "0x%x", extend
| 0xf000);
700 (*info
->fprintf_func
) (info
->stream
, "0x%x", insn
);
701 info
->insn_type
= dis_noninsn
;
706 /* Disassemble an operand for a mips16 instruction. */
709 print_mips16_insn_arg (type
, op
, l
, use_extend
, extend
, memaddr
, info
)
711 const struct mips_opcode
*op
;
716 struct disassemble_info
*info
;
723 (*info
->fprintf_func
) (info
->stream
, "%c", type
);
728 (*info
->fprintf_func
) (info
->stream
, "$%s",
729 mips16_reg_names
[((l
>> MIPS16OP_SH_RY
)
730 & MIPS16OP_MASK_RY
)]);
735 (*info
->fprintf_func
) (info
->stream
, "$%s",
736 mips16_reg_names
[((l
>> MIPS16OP_SH_RX
)
737 & MIPS16OP_MASK_RX
)]);
741 (*info
->fprintf_func
) (info
->stream
, "$%s",
742 mips16_reg_names
[((l
>> MIPS16OP_SH_RZ
)
743 & MIPS16OP_MASK_RZ
)]);
747 (*info
->fprintf_func
) (info
->stream
, "$%s",
748 mips16_reg_names
[((l
>> MIPS16OP_SH_MOVE32Z
)
749 & MIPS16OP_MASK_MOVE32Z
)]);
753 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[0]);
757 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[29]);
761 (*info
->fprintf_func
) (info
->stream
, "$pc");
765 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[31]);
769 (*info
->fprintf_func
) (info
->stream
, "$%s",
770 reg_names
[((l
>> MIPS16OP_SH_REGR32
)
771 & MIPS16OP_MASK_REGR32
)]);
775 (*info
->fprintf_func
) (info
->stream
, "$%s",
776 reg_names
[MIPS16OP_EXTRACT_REG32R (l
)]);
802 int immed
, nbits
, shift
, signedp
, extbits
, pcrel
, extu
, branch
;
814 immed
= (l
>> MIPS16OP_SH_RZ
) & MIPS16OP_MASK_RZ
;
820 immed
= (l
>> MIPS16OP_SH_RX
) & MIPS16OP_MASK_RX
;
826 immed
= (l
>> MIPS16OP_SH_RZ
) & MIPS16OP_MASK_RZ
;
832 immed
= (l
>> MIPS16OP_SH_RX
) & MIPS16OP_MASK_RX
;
838 immed
= (l
>> MIPS16OP_SH_IMM4
) & MIPS16OP_MASK_IMM4
;
844 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
845 info
->insn_type
= dis_dref
;
851 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
852 info
->insn_type
= dis_dref
;
858 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
859 if ((op
->pinfo
& MIPS16_INSN_READ_PC
) == 0
860 && (op
->pinfo
& MIPS16_INSN_READ_SP
) == 0)
862 info
->insn_type
= dis_dref
;
869 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
870 info
->insn_type
= dis_dref
;
875 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
880 immed
= (l
>> MIPS16OP_SH_IMM6
) & MIPS16OP_MASK_IMM6
;
884 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
889 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
890 /* FIXME: This might be lw, or it might be addiu to $sp or
891 $pc. We assume it's load. */
892 info
->insn_type
= dis_dref
;
898 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
899 info
->insn_type
= dis_dref
;
904 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
909 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
915 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
920 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
924 info
->insn_type
= dis_condbranch
;
928 immed
= (l
>> MIPS16OP_SH_IMM11
) & MIPS16OP_MASK_IMM11
;
932 info
->insn_type
= dis_branch
;
937 immed
= (l
>> MIPS16OP_SH_IMM8
) & MIPS16OP_MASK_IMM8
;
939 /* FIXME: This can be lw or la. We assume it is lw. */
940 info
->insn_type
= dis_dref
;
946 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
948 info
->insn_type
= dis_dref
;
954 immed
= (l
>> MIPS16OP_SH_IMM5
) & MIPS16OP_MASK_IMM5
;
963 if (signedp
&& immed
>= (1 << (nbits
- 1)))
966 if ((type
== '<' || type
== '>' || type
== '[' || type
== ']')
973 immed
|= ((extend
& 0x1f) << 11) | (extend
& 0x7e0);
974 else if (extbits
== 15)
975 immed
|= ((extend
& 0xf) << 11) | (extend
& 0x7f0);
977 immed
= ((extend
>> 6) & 0x1f) | (extend
& 0x20);
978 immed
&= (1 << extbits
) - 1;
979 if (! extu
&& immed
>= (1 << (extbits
- 1)))
980 immed
-= 1 << extbits
;
984 (*info
->fprintf_func
) (info
->stream
, "%d", immed
);
993 baseaddr
= memaddr
+ 2;
996 baseaddr
= memaddr
- 2;
1004 /* If this instruction is in the delay slot of a jr
1005 instruction, the base address is the address of the
1006 jr instruction. If it is in the delay slot of jalr
1007 instruction, the base address is the address of the
1008 jalr instruction. This test is unreliable: we have
1009 no way of knowing whether the previous word is
1010 instruction or data. */
1011 status
= (*info
->read_memory_func
) (memaddr
- 4, buffer
, 2,
1014 && (((info
->endian
== BFD_ENDIAN_BIG
1015 ? bfd_getb16 (buffer
)
1016 : bfd_getl16 (buffer
))
1017 & 0xf800) == 0x1800))
1018 baseaddr
= memaddr
- 4;
1021 status
= (*info
->read_memory_func
) (memaddr
- 2, buffer
,
1024 && (((info
->endian
== BFD_ENDIAN_BIG
1025 ? bfd_getb16 (buffer
)
1026 : bfd_getl16 (buffer
))
1027 & 0xf81f) == 0xe800))
1028 baseaddr
= memaddr
- 2;
1031 val
= (baseaddr
& ~ ((1 << shift
) - 1)) + immed
;
1032 (*info
->print_address_func
) (val
, info
);
1041 l
= ((l
& 0x1f) << 23) | ((l
& 0x3e0) << 13) | (extend
<< 2);
1042 (*info
->print_address_func
) (((memaddr
+ 4) & 0xf0000000) | l
, info
);
1043 info
->insn_type
= dis_jsr
;
1044 info
->target
= ((memaddr
+ 4) & 0xf0000000) | l
;
1045 info
->branch_delay_insns
= 1;
1051 int need_comma
, amask
, smask
;
1055 l
= (l
>> MIPS16OP_SH_IMM6
) & MIPS16OP_MASK_IMM6
;
1057 amask
= (l
>> 3) & 7;
1059 if (amask
> 0 && amask
< 5)
1061 (*info
->fprintf_func
) (info
->stream
, "$%s", reg_names
[4]);
1063 (*info
->fprintf_func
) (info
->stream
, "-$%s",
1064 reg_names
[amask
+ 3]);
1068 smask
= (l
>> 1) & 3;
1071 (*info
->fprintf_func
) (info
->stream
, "%s??",
1072 need_comma
? "," : "");
1077 (*info
->fprintf_func
) (info
->stream
, "%s$%s",
1078 need_comma
? "," : "",
1081 (*info
->fprintf_func
) (info
->stream
, "-$%s",
1082 reg_names
[smask
+ 15]);
1088 (*info
->fprintf_func
) (info
->stream
, "%s$%s",
1089 need_comma
? "," : "",
1094 if (amask
== 5 || amask
== 6)
1096 (*info
->fprintf_func
) (info
->stream
, "%s$f0",
1097 need_comma
? "," : "");
1099 (*info
->fprintf_func
) (info
->stream
, "-$f1");
This page took 0.052378 seconds and 4 git commands to generate.