* i960-dis.c: Add parameters for 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 *));
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
NC
371 break;
372 case bfd_mach_mips32:
aa5f19f2
NC
373 *cputype = CPU_MIPS32;
374 *isa = ISA_MIPS32;
e7af610e
NC
375 break;
376 case bfd_mach_mips32_4k:
aa5f19f2
NC
377 *cputype = CPU_MIPS32_4K;
378 *isa = ISA_MIPS32;
156c2f8b 379 break;
84ea6cf2 380 case bfd_mach_mips5:
aa5f19f2
NC
381 *cputype = CPU_MIPS5;
382 *isa = ISA_MIPS5;
84ea6cf2
NC
383 break;
384 case bfd_mach_mips64:
aa5f19f2
NC
385 *cputype = CPU_MIPS64;
386 *isa = ISA_MIPS64;
84ea6cf2 387 break;
c6c98b38 388 case bfd_mach_mips_sb1:
aa5f19f2
NC
389 *cputype = CPU_SB1;
390 *isa = ISA_MIPS64;
c6c98b38 391 break;
156c2f8b 392 default:
aa5f19f2
NC
393 *cputype = CPU_R3000;
394 *isa = ISA_MIPS3;
156c2f8b 395 break;
252b5132 396 }
252b5132
RH
397}
398
21d34b1c 399/* Check if the object uses NewABI conventions. */
aa5f19f2
NC
400
401static int
7f6621cd 402is_newabi (header)
21d34b1c 403 Elf_Internal_Ehdr *header;
aa5f19f2 404{
21d34b1c
TS
405 if ((header->e_flags
406 & (E_MIPS_ABI_EABI32 | E_MIPS_ABI_EABI64 | EF_MIPS_ABI2)) != 0
407 || (header->e_ident[EI_CLASS] == ELFCLASS64
408 && (header->e_flags & E_MIPS_ABI_O64) == 0))
409 return 1;
252b5132 410
21d34b1c 411 return 0;
aa5f19f2
NC
412}
413\f
252b5132
RH
414/* Print the mips instruction at address MEMADDR in debugged memory,
415 on using INFO. Returns length of the instruction, in bytes, which is
aa5f19f2 416 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
252b5132
RH
417 this is little-endian code. */
418
419static int
aa5f19f2 420print_insn_mips (memaddr, word, info)
252b5132
RH
421 bfd_vma memaddr;
422 unsigned long int word;
423 struct disassemble_info *info;
424{
425 register const struct mips_opcode *op;
426 int target_processor, mips_isa;
427 static boolean init = 0;
428 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
429
430 /* Build a hash table to shorten the search time. */
431 if (! init)
432 {
433 unsigned int i;
434
435 for (i = 0; i <= OP_MASK_OP; i++)
436 {
437 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
438 {
439 if (op->pinfo == INSN_MACRO)
440 continue;
441 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
442 {
443 mips_hash[i] = op;
444 break;
445 }
446 }
7f6621cd 447 }
252b5132
RH
448
449 init = 1;
450 }
451
452#if ! SYMTAB_AVAILABLE
453 /* This is running out on a target machine, not in a host tool.
454 FIXME: Where does mips_target_info come from? */
455 target_processor = mips_target_info.processor;
456 mips_isa = mips_target_info.isa;
e93d7199 457#else
aa5f19f2 458 mips_isa_type (info->mach, &mips_isa, &target_processor);
e93d7199 459#endif
252b5132 460
aa5f19f2 461 info->bytes_per_chunk = INSNLEN;
252b5132
RH
462 info->display_endian = info->endian;
463
464 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
465 if (op != NULL)
466 {
467 for (; op < &mips_opcodes[NUMOPCODES]; op++)
468 {
469 if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
470 {
471 register const char *d;
2bd7f1f3 472
d98bb281 473 if (! OPCODE_IS_MEMBER (op, mips_isa, target_processor))
252b5132
RH
474 continue;
475
476 (*info->fprintf_func) (info->stream, "%s", op->name);
477
478 d = op->args;
479 if (d != NULL && *d != '\0')
480 {
7f6621cd 481 (*info->fprintf_func) (info->stream, "\t");
252b5132 482 for (; *d != '\0'; d++)
7f6621cd 483 print_insn_arg (d, word, memaddr, info);
252b5132
RH
484 }
485
aa5f19f2 486 return INSNLEN;
252b5132
RH
487 }
488 }
489 }
490
491 /* Handle undefined instructions. */
492 (*info->fprintf_func) (info->stream, "0x%x", word);
aa5f19f2 493 return INSNLEN;
252b5132 494}
aa5f19f2 495\f
252b5132
RH
496/* In an environment where we do not know the symbol type of the
497 instruction we are forced to assume that the low order bit of the
498 instructions' address may mark it as a mips16 instruction. If we
499 are single stepping, or the pc is within the disassembled function,
500 this works. Otherwise, we need a clue. Sometimes. */
501
aa5f19f2
NC
502static int
503_print_insn_mips (memaddr, info, endianness)
252b5132
RH
504 bfd_vma memaddr;
505 struct disassemble_info *info;
aa5f19f2 506 enum bfd_endian endianness;
252b5132 507{
aa5f19f2 508 bfd_byte buffer[INSNLEN];
252b5132
RH
509 int status;
510
511#if 1
512 /* FIXME: If odd address, this is CLEARLY a mips 16 instruction. */
513 /* Only a few tools will work this way. */
514 if (memaddr & 0x01)
515 return print_insn_mips16 (memaddr, info);
e93d7199 516#endif
252b5132
RH
517
518#if SYMTAB_AVAILABLE
519 if (info->mach == 16
520 || (info->flavour == bfd_target_elf_flavour
521 && info->symbols != NULL
522 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
523 == STO_MIPS16)))
524 return print_insn_mips16 (memaddr, info);
e93d7199 525#endif
252b5132 526
aa5f19f2 527 /* Use mips64_reg_names for new ABI. */
21d34b1c
TS
528 reg_names = mips32_reg_names;
529
530 if (info->flavour == bfd_target_elf_flavour && info->symbols != NULL)
531 {
532 Elf_Internal_Ehdr *header;
533
7f6621cd
KH
534 header = elf_elfheader (bfd_asymbol_bfd (*(info->symbols)));
535 if (is_newabi (header))
21d34b1c
TS
536 reg_names = mips64_reg_names;
537 }
aa5f19f2
NC
538
539 status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
252b5132 540 if (status == 0)
aa5f19f2
NC
541 {
542 unsigned long insn;
543
544 if (endianness == BFD_ENDIAN_BIG)
7f6621cd 545 insn = (unsigned long) bfd_getb32 (buffer);
aa5f19f2
NC
546 else
547 insn = (unsigned long) bfd_getl32 (buffer);
548
549 return print_insn_mips (memaddr, insn, info);
550 }
252b5132
RH
551 else
552 {
553 (*info->memory_error_func) (status, memaddr, info);
554 return -1;
555 }
556}
557
558int
aa5f19f2 559print_insn_big_mips (memaddr, info)
252b5132
RH
560 bfd_vma memaddr;
561 struct disassemble_info *info;
562{
aa5f19f2
NC
563 return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
564}
252b5132 565
aa5f19f2
NC
566int
567print_insn_little_mips (memaddr, info)
568 bfd_vma memaddr;
569 struct disassemble_info *info;
570{
571 return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
252b5132
RH
572}
573\f
574/* Disassemble mips16 instructions. */
575
576static int
577print_insn_mips16 (memaddr, info)
578 bfd_vma memaddr;
579 struct disassemble_info *info;
580{
581 int status;
582 bfd_byte buffer[2];
583 int length;
584 int insn;
585 boolean use_extend;
586 int extend = 0;
587 const struct mips_opcode *op, *opend;
588
589 info->bytes_per_chunk = 2;
590 info->display_endian = info->endian;
252b5132
RH
591 info->insn_info_valid = 1;
592 info->branch_delay_insns = 0;
593 info->data_size = 0;
594 info->insn_type = dis_nonbranch;
595 info->target = 0;
596 info->target2 = 0;
597
598 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
599 if (status != 0)
600 {
601 (*info->memory_error_func) (status, memaddr, info);
602 return -1;
603 }
604
605 length = 2;
606
607 if (info->endian == BFD_ENDIAN_BIG)
608 insn = bfd_getb16 (buffer);
609 else
610 insn = bfd_getl16 (buffer);
611
612 /* Handle the extend opcode specially. */
613 use_extend = false;
614 if ((insn & 0xf800) == 0xf000)
615 {
616 use_extend = true;
617 extend = insn & 0x7ff;
618
619 memaddr += 2;
620
621 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
622 if (status != 0)
623 {
624 (*info->fprintf_func) (info->stream, "extend 0x%x",
625 (unsigned int) extend);
626 (*info->memory_error_func) (status, memaddr, info);
627 return -1;
628 }
629
630 if (info->endian == BFD_ENDIAN_BIG)
631 insn = bfd_getb16 (buffer);
632 else
633 insn = bfd_getl16 (buffer);
634
635 /* Check for an extend opcode followed by an extend opcode. */
636 if ((insn & 0xf800) == 0xf000)
637 {
638 (*info->fprintf_func) (info->stream, "extend 0x%x",
639 (unsigned int) extend);
640 info->insn_type = dis_noninsn;
641 return length;
642 }
643
644 length += 2;
645 }
646
647 /* FIXME: Should probably use a hash table on the major opcode here. */
648
649 opend = mips16_opcodes + bfd_mips16_num_opcodes;
650 for (op = mips16_opcodes; op < opend; op++)
651 {
652 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
653 {
654 const char *s;
655
656 if (strchr (op->args, 'a') != NULL)
657 {
658 if (use_extend)
659 {
660 (*info->fprintf_func) (info->stream, "extend 0x%x",
661 (unsigned int) extend);
662 info->insn_type = dis_noninsn;
663 return length - 2;
664 }
665
666 use_extend = false;
667
668 memaddr += 2;
669
670 status = (*info->read_memory_func) (memaddr, buffer, 2,
671 info);
672 if (status == 0)
673 {
674 use_extend = true;
675 if (info->endian == BFD_ENDIAN_BIG)
676 extend = bfd_getb16 (buffer);
677 else
678 extend = bfd_getl16 (buffer);
679 length += 2;
680 }
681 }
682
683 (*info->fprintf_func) (info->stream, "%s", op->name);
684 if (op->args[0] != '\0')
685 (*info->fprintf_func) (info->stream, "\t");
686
687 for (s = op->args; *s != '\0'; s++)
688 {
689 if (*s == ','
690 && s[1] == 'w'
691 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
692 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
693 {
694 /* Skip the register and the comma. */
695 ++s;
696 continue;
697 }
698 if (*s == ','
699 && s[1] == 'v'
700 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
701 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
702 {
703 /* Skip the register and the comma. */
704 ++s;
705 continue;
706 }
707 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
708 info);
709 }
710
711 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
712 {
713 info->branch_delay_insns = 1;
714 if (info->insn_type != dis_jsr)
715 info->insn_type = dis_branch;
716 }
717
718 return length;
719 }
720 }
721
722 if (use_extend)
723 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
724 (*info->fprintf_func) (info->stream, "0x%x", insn);
725 info->insn_type = dis_noninsn;
726
727 return length;
728}
729
730/* Disassemble an operand for a mips16 instruction. */
731
732static void
733print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
aa5f19f2 734 char type;
252b5132
RH
735 const struct mips_opcode *op;
736 int l;
737 boolean use_extend;
738 int extend;
739 bfd_vma memaddr;
740 struct disassemble_info *info;
741{
742 switch (type)
743 {
744 case ',':
745 case '(':
746 case ')':
747 (*info->fprintf_func) (info->stream, "%c", type);
748 break;
749
750 case 'y':
751 case 'w':
aa5f19f2 752 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
753 mips16_reg_names[((l >> MIPS16OP_SH_RY)
754 & MIPS16OP_MASK_RY)]);
755 break;
756
757 case 'x':
758 case 'v':
aa5f19f2 759 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
760 mips16_reg_names[((l >> MIPS16OP_SH_RX)
761 & MIPS16OP_MASK_RX)]);
762 break;
763
764 case 'z':
aa5f19f2 765 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
766 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
767 & MIPS16OP_MASK_RZ)]);
768 break;
769
770 case 'Z':
aa5f19f2 771 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
772 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
773 & MIPS16OP_MASK_MOVE32Z)]);
774 break;
775
776 case '0':
aa5f19f2 777 (*info->fprintf_func) (info->stream, "%s", mips32_reg_names[0]);
252b5132
RH
778 break;
779
780 case 'S':
aa5f19f2 781 (*info->fprintf_func) (info->stream, "%s", mips32_reg_names[29]);
252b5132
RH
782 break;
783
784 case 'P':
785 (*info->fprintf_func) (info->stream, "$pc");
786 break;
787
788 case 'R':
aa5f19f2 789 (*info->fprintf_func) (info->stream, "%s", mips32_reg_names[31]);
252b5132
RH
790 break;
791
792 case 'X':
aa5f19f2
NC
793 (*info->fprintf_func) (info->stream, "%s",
794 mips32_reg_names[((l >> MIPS16OP_SH_REGR32)
7f6621cd 795 & MIPS16OP_MASK_REGR32)]);
252b5132
RH
796 break;
797
798 case 'Y':
aa5f19f2
NC
799 (*info->fprintf_func) (info->stream, "%s",
800 mips32_reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
252b5132
RH
801 break;
802
803 case '<':
804 case '>':
805 case '[':
806 case ']':
807 case '4':
808 case '5':
809 case 'H':
810 case 'W':
811 case 'D':
812 case 'j':
813 case '6':
814 case '8':
815 case 'V':
816 case 'C':
817 case 'U':
818 case 'k':
819 case 'K':
820 case 'p':
821 case 'q':
822 case 'A':
823 case 'B':
824 case 'E':
825 {
826 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
827
828 shift = 0;
829 signedp = 0;
830 extbits = 16;
831 pcrel = 0;
832 extu = 0;
833 branch = 0;
834 switch (type)
835 {
836 case '<':
837 nbits = 3;
838 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
839 extbits = 5;
840 extu = 1;
841 break;
842 case '>':
843 nbits = 3;
844 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
845 extbits = 5;
846 extu = 1;
847 break;
848 case '[':
849 nbits = 3;
850 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
851 extbits = 6;
852 extu = 1;
853 break;
854 case ']':
855 nbits = 3;
856 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
857 extbits = 6;
858 extu = 1;
859 break;
860 case '4':
861 nbits = 4;
862 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
863 signedp = 1;
864 extbits = 15;
865 break;
866 case '5':
867 nbits = 5;
868 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
869 info->insn_type = dis_dref;
870 info->data_size = 1;
871 break;
872 case 'H':
873 nbits = 5;
874 shift = 1;
875 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
876 info->insn_type = dis_dref;
877 info->data_size = 2;
878 break;
879 case 'W':
880 nbits = 5;
881 shift = 2;
882 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
883 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
884 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
885 {
886 info->insn_type = dis_dref;
887 info->data_size = 4;
888 }
889 break;
890 case 'D':
891 nbits = 5;
892 shift = 3;
893 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
894 info->insn_type = dis_dref;
895 info->data_size = 8;
896 break;
897 case 'j':
898 nbits = 5;
899 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
900 signedp = 1;
901 break;
902 case '6':
903 nbits = 6;
904 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
905 break;
906 case '8':
907 nbits = 8;
908 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
909 break;
910 case 'V':
911 nbits = 8;
912 shift = 2;
913 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
914 /* FIXME: This might be lw, or it might be addiu to $sp or
915 $pc. We assume it's load. */
916 info->insn_type = dis_dref;
917 info->data_size = 4;
918 break;
919 case 'C':
920 nbits = 8;
921 shift = 3;
922 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
923 info->insn_type = dis_dref;
924 info->data_size = 8;
925 break;
926 case 'U':
927 nbits = 8;
928 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
929 extu = 1;
930 break;
931 case 'k':
932 nbits = 8;
933 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
934 signedp = 1;
935 break;
936 case 'K':
937 nbits = 8;
938 shift = 3;
939 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
940 signedp = 1;
941 break;
942 case 'p':
943 nbits = 8;
944 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
945 signedp = 1;
946 pcrel = 1;
947 branch = 1;
948 info->insn_type = dis_condbranch;
949 break;
950 case 'q':
951 nbits = 11;
952 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
953 signedp = 1;
954 pcrel = 1;
955 branch = 1;
956 info->insn_type = dis_branch;
957 break;
958 case 'A':
959 nbits = 8;
960 shift = 2;
961 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
962 pcrel = 1;
963 /* FIXME: This can be lw or la. We assume it is lw. */
964 info->insn_type = dis_dref;
965 info->data_size = 4;
966 break;
967 case 'B':
968 nbits = 5;
969 shift = 3;
970 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
971 pcrel = 1;
972 info->insn_type = dis_dref;
973 info->data_size = 8;
974 break;
975 case 'E':
976 nbits = 5;
977 shift = 2;
978 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
979 pcrel = 1;
980 break;
981 default:
982 abort ();
983 }
984
985 if (! use_extend)
986 {
987 if (signedp && immed >= (1 << (nbits - 1)))
988 immed -= 1 << nbits;
989 immed <<= shift;
990 if ((type == '<' || type == '>' || type == '[' || type == ']')
991 && immed == 0)
992 immed = 8;
993 }
994 else
995 {
996 if (extbits == 16)
997 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
998 else if (extbits == 15)
999 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
1000 else
1001 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
1002 immed &= (1 << extbits) - 1;
1003 if (! extu && immed >= (1 << (extbits - 1)))
1004 immed -= 1 << extbits;
1005 }
1006
1007 if (! pcrel)
1008 (*info->fprintf_func) (info->stream, "%d", immed);
1009 else
1010 {
1011 bfd_vma baseaddr;
1012 bfd_vma val;
1013
1014 if (branch)
1015 {
1016 immed *= 2;
1017 baseaddr = memaddr + 2;
1018 }
1019 else if (use_extend)
1020 baseaddr = memaddr - 2;
1021 else
1022 {
1023 int status;
1024 bfd_byte buffer[2];
1025
1026 baseaddr = memaddr;
1027
1028 /* If this instruction is in the delay slot of a jr
1029 instruction, the base address is the address of the
1030 jr instruction. If it is in the delay slot of jalr
1031 instruction, the base address is the address of the
1032 jalr instruction. This test is unreliable: we have
1033 no way of knowing whether the previous word is
1034 instruction or data. */
1035 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
1036 info);
1037 if (status == 0
1038 && (((info->endian == BFD_ENDIAN_BIG
1039 ? bfd_getb16 (buffer)
1040 : bfd_getl16 (buffer))
1041 & 0xf800) == 0x1800))
1042 baseaddr = memaddr - 4;
1043 else
1044 {
1045 status = (*info->read_memory_func) (memaddr - 2, buffer,
1046 2, info);
1047 if (status == 0
1048 && (((info->endian == BFD_ENDIAN_BIG
1049 ? bfd_getb16 (buffer)
1050 : bfd_getl16 (buffer))
1051 & 0xf81f) == 0xe800))
1052 baseaddr = memaddr - 2;
1053 }
1054 }
7f6621cd 1055 val = (baseaddr & ~((1 << shift) - 1)) + immed;
252b5132
RH
1056 (*info->print_address_func) (val, info);
1057 info->target = val;
1058 }
1059 }
1060 break;
1061
1062 case 'a':
1063 if (! use_extend)
1064 extend = 0;
1065 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
9117d219 1066 (*info->print_address_func) (((memaddr + 4) & 0xf0000000) | l, info);
252b5132 1067 info->insn_type = dis_jsr;
9117d219 1068 info->target = ((memaddr + 4) & 0xf0000000) | l;
252b5132
RH
1069 info->branch_delay_insns = 1;
1070 break;
1071
1072 case 'l':
1073 case 'L':
1074 {
1075 int need_comma, amask, smask;
1076
1077 need_comma = 0;
1078
1079 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1080
1081 amask = (l >> 3) & 7;
1082
1083 if (amask > 0 && amask < 5)
1084 {
aa5f19f2 1085 (*info->fprintf_func) (info->stream, "%s", mips32_reg_names[4]);
252b5132 1086 if (amask > 1)
aa5f19f2
NC
1087 (*info->fprintf_func) (info->stream, "-%s",
1088 mips32_reg_names[amask + 3]);
252b5132
RH
1089 need_comma = 1;
1090 }
1091
1092 smask = (l >> 1) & 3;
1093 if (smask == 3)
1094 {
1095 (*info->fprintf_func) (info->stream, "%s??",
1096 need_comma ? "," : "");
1097 need_comma = 1;
1098 }
1099 else if (smask > 0)
1100 {
aa5f19f2 1101 (*info->fprintf_func) (info->stream, "%s%s",
252b5132 1102 need_comma ? "," : "",
aa5f19f2 1103 mips32_reg_names[16]);
252b5132 1104 if (smask > 1)
aa5f19f2
NC
1105 (*info->fprintf_func) (info->stream, "-%s",
1106 mips32_reg_names[smask + 15]);
252b5132
RH
1107 need_comma = 1;
1108 }
1109
1110 if (l & 1)
1111 {
aa5f19f2 1112 (*info->fprintf_func) (info->stream, "%s%s",
252b5132 1113 need_comma ? "," : "",
aa5f19f2 1114 mips32_reg_names[31]);
252b5132
RH
1115 need_comma = 1;
1116 }
1117
1118 if (amask == 5 || amask == 6)
1119 {
1120 (*info->fprintf_func) (info->stream, "%s$f0",
1121 need_comma ? "," : "");
1122 if (amask == 6)
1123 (*info->fprintf_func) (info->stream, "-$f1");
1124 }
1125 }
1126 break;
1127
1128 default:
aa5f19f2
NC
1129 /* xgettext:c-format */
1130 (*info->fprintf_func)
1131 (info->stream,
1132 _("# internal disassembler error, unrecognised modifier (%c)"),
1133 type);
252b5132
RH
1134 abort ();
1135 }
1136}
This page took 0.265314 seconds and 4 git commands to generate.