2001-11-04 Chris Demetriou <cgd@broadcom.com>
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
252b5132 1/* Print mips instructions for GDB, the GNU debugger, or for objdump.
060d22b0
NC
2 Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2000, 2001
73da6b6b 4 Free Software Foundation, Inc.
252b5132
RH
5 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
6
7This file is part of GDB, GAS, and the GNU binutils.
8
9This program is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2 of the License, or
12(at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22
252b5132
RH
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
7f6621cd 31 system as when it is used for disassembler support in a monitor. */
252b5132
RH
32
33#if !defined(EMBEDDED_ENV)
34#define SYMTAB_AVAILABLE 1
35#include "elf-bfd.h"
36#include "elf/mips.h"
37#endif
38
aa5f19f2
NC
39/* Mips instructions are at maximum this many bytes long. */
40#define INSNLEN 4
41
42static int _print_insn_mips
43 PARAMS ((bfd_vma, struct disassemble_info *, enum bfd_endian));
44static int print_insn_mips
45 PARAMS ((bfd_vma, unsigned long int, struct disassemble_info *));
46static void print_insn_arg
47 PARAMS ((const char *, unsigned long, bfd_vma, struct disassemble_info *));
7fa108a4
AJ
48static void mips_isa_type
49 PARAMS ((int, int *, int *));
aa5f19f2
NC
50static int print_insn_mips16
51 PARAMS ((bfd_vma, struct disassemble_info *));
7fa108a4
AJ
52static int is_newabi
53 PARAMS ((Elf_Internal_Ehdr *));
252b5132
RH
54static void print_mips16_insn_arg
55 PARAMS ((int, const struct mips_opcode *, int, boolean, int, bfd_vma,
56 struct disassemble_info *));
252b5132 57\f
aa5f19f2 58/* FIXME: These should be shared with gdb somehow. */
252b5132
RH
59
60/* The mips16 register names. */
7f6621cd 61static const char * const mips16_reg_names[] = {
252b5132
RH
62 "s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3"
63};
fb48caed 64
7f6621cd 65static const char * const mips32_reg_names[] = {
aa5f19f2
NC
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
7f6621cd 79static const char * const mips64_reg_names[] = {
aa5f19f2
NC
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
fb48caed 94 table to use. */
aa5f19f2 95static const char * const *reg_names = NULL;
252b5132 96\f
7f6621cd 97/* Print insn arguments for 32/64-bit code. */
aa5f19f2 98
252b5132
RH
99static void
100print_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':
aa5f19f2 120 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
121 reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
122 break;
123
124 case 't':
125 case 'w':
aa5f19f2 126 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
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",
7f6621cd 133 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
252b5132
RH
134 break;
135
7f6621cd 136 case 'j': /* Same as i, but sign-extended. */
252b5132
RH
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':
9bb28706
CD
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);
252b5132
RH
161 break;
162
163 case 'p':
7f6621cd 164 /* Sign extend the displacement. */
252b5132
RH
165 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
166 if (delta & 0x8000)
167 delta |= ~0xffff;
9bb28706
CD
168 info->target = (delta << 2) + pc + INSNLEN;
169 (*info->print_address_func) (info->target, info);
252b5132
RH
170 break;
171
172 case 'd':
aa5f19f2 173 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
174 reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
175 break;
176
4372b673
NC
177 case 'U':
178 {
7f6621cd
KH
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 }
4372b673
NC
198 }
199 break;
200
252b5132 201 case 'z':
aa5f19f2 202 (*info->fprintf_func) (info->stream, "%s", reg_names[0]);
252b5132
RH
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
252b5132
RH
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",
4372b673
NC
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);
252b5132
RH
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
252b5132
RH
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':
21d34b1c
TS
258 (*info->fprintf_func) (info->stream, "$%d",
259 (l >> OP_SH_RT) & OP_MASK_RT);
252b5132
RH
260 break;
261
262 case 'G':
21d34b1c
TS
263 (*info->fprintf_func) (info->stream, "$%d",
264 (l >> OP_SH_RD) & OP_MASK_RD);
252b5132
RH
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
156c2f8b 282 case 'H':
e93d7199 283 (*info->fprintf_func) (info->stream, "%d",
156c2f8b
NC
284 (l >> OP_SH_SEL) & OP_MASK_SEL);
285 break;
252b5132
RH
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
7f6621cd 296/* Figure out the MIPS ISA and CPU based on the machine number. */
252b5132
RH
297
298static void
aa5f19f2 299mips_isa_type (mach, isa, cputype)
252b5132
RH
300 int mach;
301 int *isa;
302 int *cputype;
303{
252b5132
RH
304 switch (mach)
305 {
156c2f8b 306 case bfd_mach_mips3000:
aa5f19f2
NC
307 *cputype = CPU_R3000;
308 *isa = ISA_MIPS1;
156c2f8b
NC
309 break;
310 case bfd_mach_mips3900:
aa5f19f2
NC
311 *cputype = CPU_R3900;
312 *isa = ISA_MIPS1;
156c2f8b
NC
313 break;
314 case bfd_mach_mips4000:
aa5f19f2
NC
315 *cputype = CPU_R4000;
316 *isa = ISA_MIPS3;
156c2f8b
NC
317 break;
318 case bfd_mach_mips4010:
aa5f19f2
NC
319 *cputype = CPU_R4010;
320 *isa = ISA_MIPS2;
156c2f8b
NC
321 break;
322 case bfd_mach_mips4100:
aa5f19f2
NC
323 *cputype = CPU_VR4100;
324 *isa = ISA_MIPS3;
156c2f8b
NC
325 break;
326 case bfd_mach_mips4111:
aa5f19f2
NC
327 *cputype = CPU_R4111;
328 *isa = ISA_MIPS3;
156c2f8b
NC
329 break;
330 case bfd_mach_mips4300:
aa5f19f2
NC
331 *cputype = CPU_R4300;
332 *isa = ISA_MIPS3;
156c2f8b
NC
333 break;
334 case bfd_mach_mips4400:
aa5f19f2
NC
335 *cputype = CPU_R4400;
336 *isa = ISA_MIPS3;
156c2f8b
NC
337 break;
338 case bfd_mach_mips4600:
aa5f19f2
NC
339 *cputype = CPU_R4600;
340 *isa = ISA_MIPS3;
156c2f8b
NC
341 break;
342 case bfd_mach_mips4650:
aa5f19f2
NC
343 *cputype = CPU_R4650;
344 *isa = ISA_MIPS3;
156c2f8b
NC
345 break;
346 case bfd_mach_mips5000:
aa5f19f2
NC
347 *cputype = CPU_R5000;
348 *isa = ISA_MIPS4;
156c2f8b
NC
349 break;
350 case bfd_mach_mips6000:
aa5f19f2
NC
351 *cputype = CPU_R6000;
352 *isa = ISA_MIPS2;
156c2f8b
NC
353 break;
354 case bfd_mach_mips8000:
aa5f19f2
NC
355 *cputype = CPU_R8000;
356 *isa = ISA_MIPS4;
156c2f8b
NC
357 break;
358 case bfd_mach_mips10000:
aa5f19f2
NC
359 *cputype = CPU_R10000;
360 *isa = ISA_MIPS4;
156c2f8b 361 break;
d1cf510e
NC
362 case bfd_mach_mips12000:
363 *cputype = CPU_R12000;
364 *isa = ISA_MIPS4;
365 break;
156c2f8b 366 case bfd_mach_mips16:
aa5f19f2
NC
367 *cputype = CPU_MIPS16;
368 *isa = ISA_MIPS3;
e7af610e 369 break;
84ea6cf2 370 case bfd_mach_mips5:
aa5f19f2
NC
371 *cputype = CPU_MIPS5;
372 *isa = ISA_MIPS5;
84ea6cf2 373 break;
c6c98b38 374 case bfd_mach_mips_sb1:
aa5f19f2 375 *cputype = CPU_SB1;
2228315b 376 *isa = ISA_MIPS64 | INSN_SB1;
c6c98b38 377 break;
0823fbca
EC
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
156c2f8b 387 default:
aa5f19f2
NC
388 *cputype = CPU_R3000;
389 *isa = ISA_MIPS3;
156c2f8b 390 break;
252b5132 391 }
252b5132
RH
392}
393
21d34b1c 394/* Check if the object uses NewABI conventions. */
aa5f19f2
NC
395
396static int
7f6621cd 397is_newabi (header)
21d34b1c 398 Elf_Internal_Ehdr *header;
aa5f19f2 399{
21d34b1c
TS
400 if ((header->e_flags
401 & (E_MIPS_ABI_EABI32 | E_MIPS_ABI_EABI64 | EF_MIPS_ABI2)) != 0
402 || (header->e_ident[EI_CLASS] == ELFCLASS64
403 && (header->e_flags & E_MIPS_ABI_O64) == 0))
404 return 1;
252b5132 405
21d34b1c 406 return 0;
aa5f19f2
NC
407}
408\f
252b5132
RH
409/* Print the mips instruction at address MEMADDR in debugged memory,
410 on using INFO. Returns length of the instruction, in bytes, which is
aa5f19f2 411 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
252b5132
RH
412 this is little-endian code. */
413
414static int
aa5f19f2 415print_insn_mips (memaddr, word, info)
252b5132
RH
416 bfd_vma memaddr;
417 unsigned long int word;
418 struct disassemble_info *info;
419{
420 register const struct mips_opcode *op;
421 int target_processor, mips_isa;
422 static boolean init = 0;
423 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
424
425 /* Build a hash table to shorten the search time. */
426 if (! init)
427 {
428 unsigned int i;
429
430 for (i = 0; i <= OP_MASK_OP; i++)
431 {
432 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
433 {
434 if (op->pinfo == INSN_MACRO)
435 continue;
436 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
437 {
438 mips_hash[i] = op;
439 break;
440 }
441 }
7f6621cd 442 }
252b5132
RH
443
444 init = 1;
445 }
446
447#if ! SYMTAB_AVAILABLE
448 /* This is running out on a target machine, not in a host tool.
449 FIXME: Where does mips_target_info come from? */
450 target_processor = mips_target_info.processor;
451 mips_isa = mips_target_info.isa;
e93d7199 452#else
aa5f19f2 453 mips_isa_type (info->mach, &mips_isa, &target_processor);
e93d7199 454#endif
252b5132 455
aa5f19f2 456 info->bytes_per_chunk = INSNLEN;
252b5132 457 info->display_endian = info->endian;
9bb28706
CD
458 info->insn_info_valid = 1;
459 info->branch_delay_insns = 0;
460 info->data_size = 0;
461 info->insn_type = dis_nonbranch;
462 info->target = 0;
463 info->target2 = 0;
252b5132
RH
464
465 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
466 if (op != NULL)
467 {
468 for (; op < &mips_opcodes[NUMOPCODES]; op++)
469 {
470 if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
471 {
472 register const char *d;
2bd7f1f3 473
d98bb281 474 if (! OPCODE_IS_MEMBER (op, mips_isa, target_processor))
252b5132
RH
475 continue;
476
9bb28706
CD
477 /* Figure out instruction type and branch delay information. */
478 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
479 {
480 if ((info->insn_type & INSN_WRITE_GPR_31) != 0)
481 info->insn_type = dis_jsr;
482 else
483 info->insn_type = dis_branch;
484 info->branch_delay_insns = 1;
485 }
486 else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
487 | INSN_COND_BRANCH_LIKELY)) != 0)
488 {
489 if ((info->insn_type & INSN_WRITE_GPR_31) != 0)
490 info->insn_type = dis_condjsr;
491 else
492 info->insn_type = dis_condbranch;
493 info->branch_delay_insns = 1;
494 }
495 else if ((op->pinfo & (INSN_STORE_MEMORY
496 | INSN_LOAD_MEMORY_DELAY)) != 0)
497 info->insn_type = dis_dref;
498
252b5132
RH
499 (*info->fprintf_func) (info->stream, "%s", op->name);
500
501 d = op->args;
502 if (d != NULL && *d != '\0')
503 {
7f6621cd 504 (*info->fprintf_func) (info->stream, "\t");
252b5132 505 for (; *d != '\0'; d++)
7f6621cd 506 print_insn_arg (d, word, memaddr, info);
252b5132
RH
507 }
508
aa5f19f2 509 return INSNLEN;
252b5132
RH
510 }
511 }
512 }
513
514 /* Handle undefined instructions. */
9bb28706 515 info->insn_type = dis_noninsn;
252b5132 516 (*info->fprintf_func) (info->stream, "0x%x", word);
aa5f19f2 517 return INSNLEN;
252b5132 518}
aa5f19f2 519\f
252b5132
RH
520/* In an environment where we do not know the symbol type of the
521 instruction we are forced to assume that the low order bit of the
522 instructions' address may mark it as a mips16 instruction. If we
523 are single stepping, or the pc is within the disassembled function,
524 this works. Otherwise, we need a clue. Sometimes. */
525
aa5f19f2
NC
526static int
527_print_insn_mips (memaddr, info, endianness)
252b5132
RH
528 bfd_vma memaddr;
529 struct disassemble_info *info;
aa5f19f2 530 enum bfd_endian endianness;
252b5132 531{
aa5f19f2 532 bfd_byte buffer[INSNLEN];
252b5132
RH
533 int status;
534
535#if 1
536 /* FIXME: If odd address, this is CLEARLY a mips 16 instruction. */
537 /* Only a few tools will work this way. */
538 if (memaddr & 0x01)
539 return print_insn_mips16 (memaddr, info);
e93d7199 540#endif
252b5132
RH
541
542#if SYMTAB_AVAILABLE
543 if (info->mach == 16
544 || (info->flavour == bfd_target_elf_flavour
545 && info->symbols != NULL
546 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
547 == STO_MIPS16)))
548 return print_insn_mips16 (memaddr, info);
e93d7199 549#endif
252b5132 550
aa5f19f2 551 /* Use mips64_reg_names for new ABI. */
21d34b1c
TS
552 reg_names = mips32_reg_names;
553
554 if (info->flavour == bfd_target_elf_flavour && info->symbols != NULL)
555 {
556 Elf_Internal_Ehdr *header;
557
7f6621cd
KH
558 header = elf_elfheader (bfd_asymbol_bfd (*(info->symbols)));
559 if (is_newabi (header))
21d34b1c
TS
560 reg_names = mips64_reg_names;
561 }
aa5f19f2
NC
562
563 status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
252b5132 564 if (status == 0)
aa5f19f2
NC
565 {
566 unsigned long insn;
567
568 if (endianness == BFD_ENDIAN_BIG)
7f6621cd 569 insn = (unsigned long) bfd_getb32 (buffer);
aa5f19f2
NC
570 else
571 insn = (unsigned long) bfd_getl32 (buffer);
572
573 return print_insn_mips (memaddr, insn, info);
574 }
252b5132
RH
575 else
576 {
577 (*info->memory_error_func) (status, memaddr, info);
578 return -1;
579 }
580}
581
582int
aa5f19f2 583print_insn_big_mips (memaddr, info)
252b5132
RH
584 bfd_vma memaddr;
585 struct disassemble_info *info;
586{
aa5f19f2
NC
587 return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
588}
252b5132 589
aa5f19f2
NC
590int
591print_insn_little_mips (memaddr, info)
592 bfd_vma memaddr;
593 struct disassemble_info *info;
594{
595 return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
252b5132
RH
596}
597\f
598/* Disassemble mips16 instructions. */
599
600static int
601print_insn_mips16 (memaddr, info)
602 bfd_vma memaddr;
603 struct disassemble_info *info;
604{
605 int status;
606 bfd_byte buffer[2];
607 int length;
608 int insn;
609 boolean use_extend;
610 int extend = 0;
611 const struct mips_opcode *op, *opend;
612
613 info->bytes_per_chunk = 2;
614 info->display_endian = info->endian;
252b5132
RH
615 info->insn_info_valid = 1;
616 info->branch_delay_insns = 0;
617 info->data_size = 0;
618 info->insn_type = dis_nonbranch;
619 info->target = 0;
620 info->target2 = 0;
621
622 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
623 if (status != 0)
624 {
625 (*info->memory_error_func) (status, memaddr, info);
626 return -1;
627 }
628
629 length = 2;
630
631 if (info->endian == BFD_ENDIAN_BIG)
632 insn = bfd_getb16 (buffer);
633 else
634 insn = bfd_getl16 (buffer);
635
636 /* Handle the extend opcode specially. */
637 use_extend = false;
638 if ((insn & 0xf800) == 0xf000)
639 {
640 use_extend = true;
641 extend = insn & 0x7ff;
642
643 memaddr += 2;
644
645 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
646 if (status != 0)
647 {
648 (*info->fprintf_func) (info->stream, "extend 0x%x",
649 (unsigned int) extend);
650 (*info->memory_error_func) (status, memaddr, info);
651 return -1;
652 }
653
654 if (info->endian == BFD_ENDIAN_BIG)
655 insn = bfd_getb16 (buffer);
656 else
657 insn = bfd_getl16 (buffer);
658
659 /* Check for an extend opcode followed by an extend opcode. */
660 if ((insn & 0xf800) == 0xf000)
661 {
662 (*info->fprintf_func) (info->stream, "extend 0x%x",
663 (unsigned int) extend);
664 info->insn_type = dis_noninsn;
665 return length;
666 }
667
668 length += 2;
669 }
670
671 /* FIXME: Should probably use a hash table on the major opcode here. */
672
673 opend = mips16_opcodes + bfd_mips16_num_opcodes;
674 for (op = mips16_opcodes; op < opend; op++)
675 {
676 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
677 {
678 const char *s;
679
680 if (strchr (op->args, 'a') != NULL)
681 {
682 if (use_extend)
683 {
684 (*info->fprintf_func) (info->stream, "extend 0x%x",
685 (unsigned int) extend);
686 info->insn_type = dis_noninsn;
687 return length - 2;
688 }
689
690 use_extend = false;
691
692 memaddr += 2;
693
694 status = (*info->read_memory_func) (memaddr, buffer, 2,
695 info);
696 if (status == 0)
697 {
698 use_extend = true;
699 if (info->endian == BFD_ENDIAN_BIG)
700 extend = bfd_getb16 (buffer);
701 else
702 extend = bfd_getl16 (buffer);
703 length += 2;
704 }
705 }
706
707 (*info->fprintf_func) (info->stream, "%s", op->name);
708 if (op->args[0] != '\0')
709 (*info->fprintf_func) (info->stream, "\t");
710
711 for (s = op->args; *s != '\0'; s++)
712 {
713 if (*s == ','
714 && s[1] == 'w'
715 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
716 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
717 {
718 /* Skip the register and the comma. */
719 ++s;
720 continue;
721 }
722 if (*s == ','
723 && s[1] == 'v'
724 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
725 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
726 {
727 /* Skip the register and the comma. */
728 ++s;
729 continue;
730 }
731 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
732 info);
733 }
734
735 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
736 {
737 info->branch_delay_insns = 1;
738 if (info->insn_type != dis_jsr)
739 info->insn_type = dis_branch;
740 }
741
742 return length;
743 }
744 }
745
746 if (use_extend)
747 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
748 (*info->fprintf_func) (info->stream, "0x%x", insn);
749 info->insn_type = dis_noninsn;
750
751 return length;
752}
753
754/* Disassemble an operand for a mips16 instruction. */
755
756static void
757print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
aa5f19f2 758 char type;
252b5132
RH
759 const struct mips_opcode *op;
760 int l;
761 boolean use_extend;
762 int extend;
763 bfd_vma memaddr;
764 struct disassemble_info *info;
765{
766 switch (type)
767 {
768 case ',':
769 case '(':
770 case ')':
771 (*info->fprintf_func) (info->stream, "%c", type);
772 break;
773
774 case 'y':
775 case 'w':
aa5f19f2 776 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
777 mips16_reg_names[((l >> MIPS16OP_SH_RY)
778 & MIPS16OP_MASK_RY)]);
779 break;
780
781 case 'x':
782 case 'v':
aa5f19f2 783 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
784 mips16_reg_names[((l >> MIPS16OP_SH_RX)
785 & MIPS16OP_MASK_RX)]);
786 break;
787
788 case 'z':
aa5f19f2 789 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
790 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
791 & MIPS16OP_MASK_RZ)]);
792 break;
793
794 case 'Z':
aa5f19f2 795 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
796 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
797 & MIPS16OP_MASK_MOVE32Z)]);
798 break;
799
800 case '0':
aa5f19f2 801 (*info->fprintf_func) (info->stream, "%s", mips32_reg_names[0]);
252b5132
RH
802 break;
803
804 case 'S':
aa5f19f2 805 (*info->fprintf_func) (info->stream, "%s", mips32_reg_names[29]);
252b5132
RH
806 break;
807
808 case 'P':
809 (*info->fprintf_func) (info->stream, "$pc");
810 break;
811
812 case 'R':
aa5f19f2 813 (*info->fprintf_func) (info->stream, "%s", mips32_reg_names[31]);
252b5132
RH
814 break;
815
816 case 'X':
aa5f19f2
NC
817 (*info->fprintf_func) (info->stream, "%s",
818 mips32_reg_names[((l >> MIPS16OP_SH_REGR32)
7f6621cd 819 & MIPS16OP_MASK_REGR32)]);
252b5132
RH
820 break;
821
822 case 'Y':
aa5f19f2
NC
823 (*info->fprintf_func) (info->stream, "%s",
824 mips32_reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
252b5132
RH
825 break;
826
827 case '<':
828 case '>':
829 case '[':
830 case ']':
831 case '4':
832 case '5':
833 case 'H':
834 case 'W':
835 case 'D':
836 case 'j':
837 case '6':
838 case '8':
839 case 'V':
840 case 'C':
841 case 'U':
842 case 'k':
843 case 'K':
844 case 'p':
845 case 'q':
846 case 'A':
847 case 'B':
848 case 'E':
849 {
850 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
851
852 shift = 0;
853 signedp = 0;
854 extbits = 16;
855 pcrel = 0;
856 extu = 0;
857 branch = 0;
858 switch (type)
859 {
860 case '<':
861 nbits = 3;
862 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
863 extbits = 5;
864 extu = 1;
865 break;
866 case '>':
867 nbits = 3;
868 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
869 extbits = 5;
870 extu = 1;
871 break;
872 case '[':
873 nbits = 3;
874 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
875 extbits = 6;
876 extu = 1;
877 break;
878 case ']':
879 nbits = 3;
880 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
881 extbits = 6;
882 extu = 1;
883 break;
884 case '4':
885 nbits = 4;
886 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
887 signedp = 1;
888 extbits = 15;
889 break;
890 case '5':
891 nbits = 5;
892 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
893 info->insn_type = dis_dref;
894 info->data_size = 1;
895 break;
896 case 'H':
897 nbits = 5;
898 shift = 1;
899 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
900 info->insn_type = dis_dref;
901 info->data_size = 2;
902 break;
903 case 'W':
904 nbits = 5;
905 shift = 2;
906 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
907 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
908 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
909 {
910 info->insn_type = dis_dref;
911 info->data_size = 4;
912 }
913 break;
914 case 'D':
915 nbits = 5;
916 shift = 3;
917 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
918 info->insn_type = dis_dref;
919 info->data_size = 8;
920 break;
921 case 'j':
922 nbits = 5;
923 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
924 signedp = 1;
925 break;
926 case '6':
927 nbits = 6;
928 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
929 break;
930 case '8':
931 nbits = 8;
932 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
933 break;
934 case 'V':
935 nbits = 8;
936 shift = 2;
937 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
938 /* FIXME: This might be lw, or it might be addiu to $sp or
939 $pc. We assume it's load. */
940 info->insn_type = dis_dref;
941 info->data_size = 4;
942 break;
943 case 'C':
944 nbits = 8;
945 shift = 3;
946 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
947 info->insn_type = dis_dref;
948 info->data_size = 8;
949 break;
950 case 'U':
951 nbits = 8;
952 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
953 extu = 1;
954 break;
955 case 'k':
956 nbits = 8;
957 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
958 signedp = 1;
959 break;
960 case 'K':
961 nbits = 8;
962 shift = 3;
963 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
964 signedp = 1;
965 break;
966 case 'p':
967 nbits = 8;
968 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
969 signedp = 1;
970 pcrel = 1;
971 branch = 1;
972 info->insn_type = dis_condbranch;
973 break;
974 case 'q':
975 nbits = 11;
976 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
977 signedp = 1;
978 pcrel = 1;
979 branch = 1;
980 info->insn_type = dis_branch;
981 break;
982 case 'A':
983 nbits = 8;
984 shift = 2;
985 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
986 pcrel = 1;
987 /* FIXME: This can be lw or la. We assume it is lw. */
988 info->insn_type = dis_dref;
989 info->data_size = 4;
990 break;
991 case 'B':
992 nbits = 5;
993 shift = 3;
994 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
995 pcrel = 1;
996 info->insn_type = dis_dref;
997 info->data_size = 8;
998 break;
999 case 'E':
1000 nbits = 5;
1001 shift = 2;
1002 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1003 pcrel = 1;
1004 break;
1005 default:
1006 abort ();
1007 }
1008
1009 if (! use_extend)
1010 {
1011 if (signedp && immed >= (1 << (nbits - 1)))
1012 immed -= 1 << nbits;
1013 immed <<= shift;
1014 if ((type == '<' || type == '>' || type == '[' || type == ']')
1015 && immed == 0)
1016 immed = 8;
1017 }
1018 else
1019 {
1020 if (extbits == 16)
1021 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
1022 else if (extbits == 15)
1023 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
1024 else
1025 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
1026 immed &= (1 << extbits) - 1;
1027 if (! extu && immed >= (1 << (extbits - 1)))
1028 immed -= 1 << extbits;
1029 }
1030
1031 if (! pcrel)
1032 (*info->fprintf_func) (info->stream, "%d", immed);
1033 else
1034 {
1035 bfd_vma baseaddr;
252b5132
RH
1036
1037 if (branch)
1038 {
1039 immed *= 2;
1040 baseaddr = memaddr + 2;
1041 }
1042 else if (use_extend)
1043 baseaddr = memaddr - 2;
1044 else
1045 {
1046 int status;
1047 bfd_byte buffer[2];
1048
1049 baseaddr = memaddr;
1050
1051 /* If this instruction is in the delay slot of a jr
1052 instruction, the base address is the address of the
1053 jr instruction. If it is in the delay slot of jalr
1054 instruction, the base address is the address of the
1055 jalr instruction. This test is unreliable: we have
1056 no way of knowing whether the previous word is
1057 instruction or data. */
1058 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
1059 info);
1060 if (status == 0
1061 && (((info->endian == BFD_ENDIAN_BIG
1062 ? bfd_getb16 (buffer)
1063 : bfd_getl16 (buffer))
1064 & 0xf800) == 0x1800))
1065 baseaddr = memaddr - 4;
1066 else
1067 {
1068 status = (*info->read_memory_func) (memaddr - 2, buffer,
1069 2, info);
1070 if (status == 0
1071 && (((info->endian == BFD_ENDIAN_BIG
1072 ? bfd_getb16 (buffer)
1073 : bfd_getl16 (buffer))
1074 & 0xf81f) == 0xe800))
1075 baseaddr = memaddr - 2;
1076 }
1077 }
9bb28706
CD
1078 info->target = (baseaddr & ~((1 << shift) - 1)) + immed;
1079 (*info->print_address_func) (info->target, info);
252b5132
RH
1080 }
1081 }
1082 break;
1083
1084 case 'a':
1085 if (! use_extend)
1086 extend = 0;
1087 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
9bb28706
CD
1088 info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
1089 (*info->print_address_func) (info->target, info);
252b5132 1090 info->insn_type = dis_jsr;
252b5132
RH
1091 info->branch_delay_insns = 1;
1092 break;
1093
1094 case 'l':
1095 case 'L':
1096 {
1097 int need_comma, amask, smask;
1098
1099 need_comma = 0;
1100
1101 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1102
1103 amask = (l >> 3) & 7;
1104
1105 if (amask > 0 && amask < 5)
1106 {
aa5f19f2 1107 (*info->fprintf_func) (info->stream, "%s", mips32_reg_names[4]);
252b5132 1108 if (amask > 1)
aa5f19f2
NC
1109 (*info->fprintf_func) (info->stream, "-%s",
1110 mips32_reg_names[amask + 3]);
252b5132
RH
1111 need_comma = 1;
1112 }
1113
1114 smask = (l >> 1) & 3;
1115 if (smask == 3)
1116 {
1117 (*info->fprintf_func) (info->stream, "%s??",
1118 need_comma ? "," : "");
1119 need_comma = 1;
1120 }
1121 else if (smask > 0)
1122 {
aa5f19f2 1123 (*info->fprintf_func) (info->stream, "%s%s",
252b5132 1124 need_comma ? "," : "",
aa5f19f2 1125 mips32_reg_names[16]);
252b5132 1126 if (smask > 1)
aa5f19f2
NC
1127 (*info->fprintf_func) (info->stream, "-%s",
1128 mips32_reg_names[smask + 15]);
252b5132
RH
1129 need_comma = 1;
1130 }
1131
1132 if (l & 1)
1133 {
aa5f19f2 1134 (*info->fprintf_func) (info->stream, "%s%s",
252b5132 1135 need_comma ? "," : "",
aa5f19f2 1136 mips32_reg_names[31]);
252b5132
RH
1137 need_comma = 1;
1138 }
1139
1140 if (amask == 5 || amask == 6)
1141 {
1142 (*info->fprintf_func) (info->stream, "%s$f0",
1143 need_comma ? "," : "");
1144 if (amask == 6)
1145 (*info->fprintf_func) (info->stream, "-$f1");
1146 }
1147 }
1148 break;
1149
1150 default:
aa5f19f2
NC
1151 /* xgettext:c-format */
1152 (*info->fprintf_func)
1153 (info->stream,
1154 _("# internal disassembler error, unrecognised modifier (%c)"),
1155 type);
252b5132
RH
1156 abort ();
1157 }
1158}
This page took 0.150407 seconds and 4 git commands to generate.