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