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