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