Fix typos: Setting trace in wrong function, ME vs HW.
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
d0ba1cea 1/* Print mips instructions for GDB, the GNU debugger, or for objdump.
3536b6a3 2 Copyright 1989, 91-97, 1998 Free Software Foundation, Inc.
d0ba1cea
ILT
3 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
4
8d67dc30 5This file is part of GDB, GAS, and the GNU binutils.
d0ba1cea
ILT
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
30b1724c 19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
d0ba1cea 20
5d0734a7 21#include <ansidecl.h>
d0ba1cea 22#include "sysdep.h"
5d0734a7 23#include "dis-asm.h"
d0ba1cea
ILT
24#include "opcode/mips.h"
25
8d67dc30
ILT
26/* FIXME: These are needed to figure out if this is a mips16 symbol or
27 not. It would be better to think of a cleaner way to do this. */
28#include "elf-bfd.h"
29#include "elf/mips.h"
30
31static int print_insn_mips16 PARAMS ((bfd_vma, struct disassemble_info *));
32static void print_mips16_insn_arg
33 PARAMS ((int, const struct mips_opcode *, int, boolean, int, bfd_vma,
34 struct disassemble_info *));
35
d0ba1cea
ILT
36/* Mips instructions are never longer than this many bytes. */
37#define MAXLEN 4
8d67dc30
ILT
38
39static void print_insn_arg PARAMS ((const char *, unsigned long, bfd_vma,
40 struct disassemble_info *));
41static int _print_insn_mips PARAMS ((bfd_vma, unsigned long int,
42 struct disassemble_info *));
43
d0ba1cea
ILT
44\f
45/* FIXME: This should be shared with gdb somehow. */
46#define REGISTER_NAMES \
47 { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
48 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
49 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
50 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
51 "sr", "lo", "hi", "bad", "cause","pc", \
52 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
53 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
54 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
55 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
56 "fsr", "fir", "fp", "inx", "rand", "tlblo","ctxt", "tlbhi",\
57 "epc", "prid"\
58 }
59
60static CONST char * CONST reg_names[] = REGISTER_NAMES;
8d67dc30
ILT
61
62/* The mips16 register names. */
63static const char * const mips16_reg_names[] =
64{
65 "s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3"
66};
d0ba1cea
ILT
67\f
68/* subroutine */
5d0734a7
JK
69static void
70print_insn_arg (d, l, pc, info)
547998d2 71 const char *d;
5d0734a7 72 register unsigned long int l;
d0ba1cea 73 bfd_vma pc;
5d0734a7 74 struct disassemble_info *info;
d0ba1cea 75{
fde326fb
ILT
76 int delta;
77
d0ba1cea
ILT
78 switch (*d)
79 {
80 case ',':
81 case '(':
82 case ')':
83af2335
JL
83 /* start-sanitize-vr5400 */
84 case '[':
85 case ']':
86 /* end-sanitize-vr5400 */
ffee80df
JL
87 /* start-sanitize-r5900 */
88 case '+':
89 case '-':
90 /* end-santiize-r5900 */
5d0734a7 91 (*info->fprintf_func) (info->stream, "%c", *d);
d0ba1cea
ILT
92 break;
93
94 case 's':
fde326fb
ILT
95 case 'b':
96 case 'r':
97 case 'v':
5d0734a7
JK
98 (*info->fprintf_func) (info->stream, "$%s",
99 reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
d0ba1cea
ILT
100 break;
101
102 case 't':
fde326fb 103 case 'w':
5d0734a7
JK
104 (*info->fprintf_func) (info->stream, "$%s",
105 reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
d0ba1cea
ILT
106 break;
107
108 case 'i':
fde326fb 109 case 'u':
30b1724c 110 (*info->fprintf_func) (info->stream, "0x%x",
5d0734a7 111 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
d0ba1cea
ILT
112 break;
113
114 case 'j': /* same as i, but sign-extended */
fde326fb
ILT
115 case 'o':
116 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
117 if (delta & 0x8000)
118 delta |= ~0xffff;
5d0734a7 119 (*info->fprintf_func) (info->stream, "%d",
fde326fb 120 delta);
d0ba1cea
ILT
121 break;
122
30b1724c
ILT
123 case 'h':
124 (*info->fprintf_func) (info->stream, "0x%x",
125 (unsigned int) ((l >> OP_SH_PREFX)
126 & OP_MASK_PREFX));
127 break;
128
129 case 'k':
130 (*info->fprintf_func) (info->stream, "0x%x",
131 (unsigned int) ((l >> OP_SH_CACHE)
132 & OP_MASK_CACHE));
133 break;
134
d0ba1cea 135 case 'a':
fde326fb
ILT
136 (*info->print_address_func)
137 (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
138 info);
d0ba1cea
ILT
139 break;
140
fde326fb
ILT
141 case 'p':
142 /* sign extend the displacement */
143 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
144 if (delta & 0x8000)
145 delta |= ~0xffff;
146 (*info->print_address_func)
147 ((delta << 2) + pc + 4,
148 info);
d0ba1cea
ILT
149 break;
150
151 case 'd':
5d0734a7
JK
152 (*info->fprintf_func) (info->stream, "$%s",
153 reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
d0ba1cea
ILT
154 break;
155
547998d2
ILT
156 case 'z':
157 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
158 break;
159
fde326fb 160 case '<':
5d0734a7
JK
161 (*info->fprintf_func) (info->stream, "0x%x",
162 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
d0ba1cea
ILT
163 break;
164
fde326fb 165 case 'c':
5d0734a7
JK
166 (*info->fprintf_func) (info->stream, "0x%x",
167 (l >> OP_SH_CODE) & OP_MASK_CODE);
d0ba1cea
ILT
168 break;
169
fde326fb
ILT
170 case 'C':
171 (*info->fprintf_func) (info->stream, "0x%x",
172 (l >> OP_SH_COPZ) & OP_MASK_COPZ);
173 break;
174
175 case 'B':
176 (*info->fprintf_func) (info->stream, "0x%x",
177 (l >> OP_SH_SYSCALL) & OP_MASK_SYSCALL);
178 break;
179
d0ba1cea 180 case 'S':
fde326fb 181 case 'V':
5d0734a7
JK
182 (*info->fprintf_func) (info->stream, "$f%d",
183 (l >> OP_SH_FS) & OP_MASK_FS);
d0ba1cea
ILT
184 break;
185
ffee80df
JL
186 /* start-sanitize-r5900
187 case '0':
188 (*info->fprintf_func) (info->stream, "0x%x",
189 (l >> 6) & 0x1f);
190 break;
191
192 case '9':
193 (*info->fprintf_func) (info->stream, "vi19");
194 break;
195
196 case '1':
197 (*info->fprintf_func) (info->stream, "vf%d",
198 (l >> OP_SH_FT) & OP_MASK_FT);
199 break;
200 case '2':
201 (*info->fprintf_func) (info->stream, "vf%d",
202 (l >> OP_SH_FS) & OP_MASK_FS);
203 break;
204 case '3':
205 (*info->fprintf_func) (info->stream, "vf%d",
206 (l >> OP_SH_FD) & OP_MASK_FD);
207 break;
208
209 case '4':
210 (*info->fprintf_func) (info->stream, "vi%d",
211 (l >> OP_SH_FT) & OP_MASK_FT);
212 break;
213 case '5':
214 (*info->fprintf_func) (info->stream, "vi%d",
215 (l >> OP_SH_FS) & OP_MASK_FS);
216 break;
217 case '6':
218 (*info->fprintf_func) (info->stream, "vi%d",
219 (l >> OP_SH_FD) & OP_MASK_FD);
220 break;
221
222 case '7':
223 (*info->fprintf_func) (info->stream, "vf%d",
224 (l >> OP_SH_FT) & OP_MASK_FT);
225 switch ((l >> 23) & 0x3)
226 {
227 case 0:
228 (*info->fprintf_func) (info->stream, "x");
229 break;
230 case 1:
231 (*info->fprintf_func) (info->stream, "y");
232 break;
233 case 2:
234 (*info->fprintf_func) (info->stream, "z");
235 break;
236 case 3:
237 (*info->fprintf_func) (info->stream, "w");
238 break;
239 }
240 break;
241 case 'K':
242 break;
243
244 case '&':
245 (*info->fprintf_func) (info->stream, ".");
246 if (l & (1 << 21))
247 (*info->fprintf_func) (info->stream, "w");
248 if (l & (1 << 24))
249 (*info->fprintf_func) (info->stream, "x");
250 if (l & (1 << 23))
251 (*info->fprintf_func) (info->stream, "y");
252 if (l & (1 << 22))
253 (*info->fprintf_func) (info->stream, "z");
254 (*info->fprintf_func) (info->stream, "\t");
255 break;
256
257 case '8':
258 (*info->fprintf_func) (info->stream, "vf%d",
259 (l >> OP_SH_FS) & OP_MASK_FS);
260 switch ((l >> 21) & 0x3)
261 {
262 case 0:
263 (*info->fprintf_func) (info->stream, "x");
264 break;
265 case 1:
266 (*info->fprintf_func) (info->stream, "y");
267 break;
268 case 2:
269 (*info->fprintf_func) (info->stream, "z");
270 break;
271 case 3:
272 (*info->fprintf_func) (info->stream, "w");
273 break;
274 }
275 break;
276 case 'J':
277 (*info->fprintf_func) (info->stream, "I");
278 break;
279
280 case 'Q':
281 (*info->fprintf_func) (info->stream, "Q");
282 break;
283
284 case 'X':
285 (*info->fprintf_func) (info->stream, "R");
286 break;
287
288 case 'U':
289 (*info->fprintf_func) (info->stream, "ACC");
290 break;
291 /* end-sanitize-r5900 */
292
d0ba1cea 293 case 'T':
fde326fb 294 case 'W':
5d0734a7
JK
295 (*info->fprintf_func) (info->stream, "$f%d",
296 (l >> OP_SH_FT) & OP_MASK_FT);
d0ba1cea
ILT
297 break;
298
299 case 'D':
5d0734a7
JK
300 (*info->fprintf_func) (info->stream, "$f%d",
301 (l >> OP_SH_FD) & OP_MASK_FD);
d0ba1cea
ILT
302 break;
303
30b1724c
ILT
304 case 'R':
305 (*info->fprintf_func) (info->stream, "$f%d",
306 (l >> OP_SH_FR) & OP_MASK_FR);
307 break;
308
fde326fb
ILT
309 case 'E':
310 (*info->fprintf_func) (info->stream, "$%d",
311 (l >> OP_SH_RT) & OP_MASK_RT);
312 break;
313
314 case 'G':
315 (*info->fprintf_func) (info->stream, "$%d",
316 (l >> OP_SH_RD) & OP_MASK_RD);
317 break;
318
30b1724c
ILT
319 case 'N':
320 (*info->fprintf_func) (info->stream, "$fcc%d",
321 (l >> OP_SH_BCC) & OP_MASK_BCC);
322 break;
323
324 case 'M':
325 (*info->fprintf_func) (info->stream, "$fcc%d",
326 (l >> OP_SH_CCC) & OP_MASK_CCC);
327 break;
328
83af2335 329 case 'P':
fb1a826b 330 (*info->fprintf_func) (info->stream, "%d",
83af2335
JL
331 (l >> OP_SH_PERFREG) & OP_MASK_PERFREG);
332 break;
333
334 /* start-sanitize-vr5400 */
335 case 'e':
336 (*info->fprintf_func) (info->stream, "%d",
337 (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE);
338 break;
339
340 case '%':
341 (*info->fprintf_func) (info->stream, "%d",
342 (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN);
343 break;
344 /* end-sanitize-vr5400 */
345
d0ba1cea 346 default:
5d0734a7
JK
347 (*info->fprintf_func) (info->stream,
348 "# internal error, undefined modifier(%c)", *d);
d0ba1cea
ILT
349 break;
350 }
351}
352\f
353/* Print the mips instruction at address MEMADDR in debugged memory,
5d0734a7 354 on using INFO. Returns length of the instruction, in bytes, which is
d0ba1cea
ILT
355 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
356 this is little-endian code. */
357
30b1724c 358static int
5d0734a7 359_print_insn_mips (memaddr, word, info)
d0ba1cea 360 bfd_vma memaddr;
5d0734a7 361 unsigned long int word;
8d67dc30 362 struct disassemble_info *info;
d0ba1cea 363{
30b1724c 364 register const struct mips_opcode *op;
83af2335 365 int target_processor, mips_isa;
30b1724c
ILT
366 static boolean init = 0;
367 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
d0ba1cea 368
30b1724c
ILT
369 /* Build a hash table to shorten the search time. */
370 if (! init)
d0ba1cea 371 {
30b1724c
ILT
372 unsigned int i;
373
374 for (i = 0; i <= OP_MASK_OP; i++)
fde326fb 375 {
30b1724c
ILT
376 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
377 {
378 if (op->pinfo == INSN_MACRO)
379 continue;
380 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
381 {
382 mips_hash[i] = op;
383 break;
384 }
385 }
386 }
387
388 init = 1;
d0ba1cea
ILT
389 }
390
83af2335
JL
391 switch (info->mach)
392 {
393 /* start-sanitize-tx19 */
394 case bfd_mach_mips1900:
395 target_processor = 1900;
396 mips_isa = 1;
397 break;
398 /* end-sanitize-tx19 */
399 case bfd_mach_mips3000:
400 target_processor = 3000;
401 mips_isa = 1;
402 break;
403 case bfd_mach_mips3900:
404 target_processor = 3900;
405 mips_isa = 1;
406 break;
407 case bfd_mach_mips4000:
408 target_processor = 4000;
409 mips_isa = 3;
410 break;
411 case bfd_mach_mips4010:
412 target_processor = 4010;
413 mips_isa = 2;
414 break;
415 case bfd_mach_mips4100:
416 target_processor = 4100;
417 mips_isa = 3;
418 break;
419 case bfd_mach_mips4300:
420 target_processor = 4300;
421 mips_isa = 3;
422 break;
ffee80df
JL
423 /* start-sanitize-vr4320 */
424 case bfd_mach_mips4320:
425 target_processor = 4320;
426 mips_isa = 3;
427 break;
428 /* end-sanitize-vr4320 */
83af2335
JL
429 case bfd_mach_mips4400:
430 target_processor = 4400;
431 mips_isa = 3;
432 break;
433 case bfd_mach_mips4600:
434 target_processor = 4600;
435 mips_isa = 3;
436 break;
437 case bfd_mach_mips4650:
438 target_processor = 4650;
439 mips_isa = 3;
440 break;
441 /* start-sanitize-tx49 */
442 case bfd_mach_mips4900:
443 target_processor = 4900;
444 mips_isa = 3;
445 break;
446 /* end-sanitize-tx49 */
447 case bfd_mach_mips5000:
448 target_processor = 5000;
449 mips_isa = 4;
450 break;
451 /* start-sanitize-vr5400 */
452 case bfd_mach_mips5400:
453 target_processor = 5400;
454 mips_isa = 3;
455 break;
456 /* end-sanitize-vr5400 */
457 /* start-sanitize-r5900 */
458 case bfd_mach_mips5900:
459 target_processor = 5900;
460 mips_isa = 3;
461 break;
462 /* end-sanitize-r5900 */
463 case bfd_mach_mips6000:
464 target_processor = 6000;
465 mips_isa = 2;
466 break;
467 case bfd_mach_mips8000:
468 target_processor = 8000;
469 mips_isa = 4;
470 break;
471 case bfd_mach_mips10000:
472 target_processor = 10000;
473 mips_isa = 4;
474 break;
475 case bfd_mach_mips16:
476 target_processor = 16;
477 mips_isa = 3;
478 break;
479 default:
480 target_processor = 3000;
481 mips_isa = 3;
482 break;
483
484 }
485
2ea116f4
ILT
486 info->bytes_per_chunk = 4;
487 info->display_endian = info->endian;
488
30b1724c
ILT
489 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
490 if (op != NULL)
d0ba1cea 491 {
30b1724c
ILT
492 for (; op < &mips_opcodes[NUMOPCODES]; op++)
493 {
494 if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
495 {
496 register const char *d;
83af2335
JL
497 int insn_isa;
498
499 if ((op->membership & INSN_ISA) == INSN_ISA1)
500 insn_isa = 1;
501 else if ((op->membership & INSN_ISA) == INSN_ISA2)
502 insn_isa = 2;
503 else if ((op->membership & INSN_ISA) == INSN_ISA3)
504 insn_isa = 3;
505 else if ((op->membership & INSN_ISA) == INSN_ISA4)
506 insn_isa = 4;
507 else
508 insn_isa = 15;
509
510 if (insn_isa > mips_isa
511 && (target_processor == 4650
512 && op->membership & INSN_4650) == 0
513 && (target_processor == 4010
514 && op->membership & INSN_4010) == 0
515 && (target_processor == 4100
516 && op->membership & INSN_4100) == 0
ffee80df
JL
517 /* start-sanitize-vr4320 */
518 && (target_processor == 4320
519 && op->membership & INSN_4320) == 0
520 /* end-sanitize-vr4320 */
83af2335
JL
521 /* start-sanitize-vr5400 */
522 && (target_processor == 5400
523 && op->membership & INSN_5400) == 0
fb1a826b 524 /* end-sanitize-vr5400 */
83af2335
JL
525 /* start-sanitize-r5900 */
526 && (target_processor == 5900
527 && op->membership & INSN_5900) == 0
528 /* end-sanitize-r5900 */
529 /* start-sanitize-tx49 */
530 && (target_processor == 4900
531 && op->membership & INSN_4900) == 0
532 /* end-sanitize-tx49 */
533 && (target_processor == 3900
534 && op->membership & INSN_3900) == 0)
535 continue;
30b1724c
ILT
536
537 (*info->fprintf_func) (info->stream, "%s", op->name);
538
539 d = op->args;
8d67dc30 540 if (d != NULL && *d != '\0')
30b1724c 541 {
ffee80df
JL
542 /* start-sanitize-r5900 */
543 /* If this is an opcode completer, then do not emit
544 a tab after the opcode. */
545 if (*d != '&')
546 /* end-sanitize-r5900 */
547 (*info->fprintf_func) (info->stream, "\t");
30b1724c 548 for (; *d != '\0'; d++)
ffee80df
JL
549 /* start-sanitize-r5900 */
550 /* If this is an escape character, go ahead and print the
551 next character in the arg string verbatim. */
552 if (*d == '%')
553 {
554 d++;
555 (*info->fprintf_func) (info->stream, "%c", *d);
556 }
557 else
558 /* end-sanitize-r5900 */
559 print_insn_arg (d, word, memaddr, info);
30b1724c
ILT
560 }
561
562 return 4;
563 }
564 }
d0ba1cea
ILT
565 }
566
30b1724c
ILT
567 /* Handle undefined instructions. */
568 (*info->fprintf_func) (info->stream, "0x%x", word);
d0ba1cea
ILT
569 return 4;
570}
5d0734a7
JK
571
572int
573print_insn_big_mips (memaddr, info)
574 bfd_vma memaddr;
575 struct disassemble_info *info;
576{
577 bfd_byte buffer[4];
8d67dc30
ILT
578 int status;
579
580 if (info->mach == 16
581 || (info->flavour == bfd_target_elf_flavour
88b38f0c
DE
582 && info->symbols != NULL
583 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
8d67dc30
ILT
584 == STO_MIPS16)))
585 return print_insn_mips16 (memaddr, info);
586
587 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 588 if (status == 0)
8d67dc30
ILT
589 return _print_insn_mips (memaddr, (unsigned long) bfd_getb32 (buffer),
590 info);
5d0734a7
JK
591 else
592 {
593 (*info->memory_error_func) (status, memaddr, info);
594 return -1;
595 }
596}
597
598int
599print_insn_little_mips (memaddr, info)
600 bfd_vma memaddr;
601 struct disassemble_info *info;
602{
603 bfd_byte buffer[4];
8d67dc30
ILT
604 int status;
605
37130f11
DE
606 /* start-sanitize-sky */
607#ifdef ARCH_dvp
88b38f0c
DE
608 {
609 /* bfd_mach_dvp_p is a macro which may evaluate its arguments more than
610 once. Since dvp_mach_type is a function, ensure it's only called
611 once. */
612 int mach = dvp_info_mach_type (info);
613
614 if (bfd_mach_dvp_p (info->mach)
615 || bfd_mach_dvp_p (mach))
616 return print_insn_dvp (memaddr, info);
617 }
37130f11
DE
618#endif
619 /* end-sanitize-sky */
620
8d67dc30
ILT
621 if (info->mach == 16
622 || (info->flavour == bfd_target_elf_flavour
88b38f0c
DE
623 && info->symbols != NULL
624 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
8d67dc30
ILT
625 == STO_MIPS16)))
626 return print_insn_mips16 (memaddr, info);
627
628 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 629 if (status == 0)
8d67dc30
ILT
630 return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer),
631 info);
5d0734a7
JK
632 else
633 {
634 (*info->memory_error_func) (status, memaddr, info);
635 return -1;
636 }
637}
8d67dc30
ILT
638\f
639/* Disassemble mips16 instructions. */
640
641static int
642print_insn_mips16 (memaddr, info)
643 bfd_vma memaddr;
644 struct disassemble_info *info;
645{
646 int status;
647 bfd_byte buffer[2];
648 int length;
649 int insn;
650 boolean use_extend;
651 int extend;
652 const struct mips_opcode *op, *opend;
653
2ea116f4
ILT
654 info->bytes_per_chunk = 2;
655 info->display_endian = info->endian;
656
20d43018
ILT
657 info->insn_info_valid = 1;
658 info->branch_delay_insns = 0;
659 info->data_size = 0;
660 info->insn_type = dis_nonbranch;
661 info->target = 0;
662 info->target2 = 0;
663
8d67dc30
ILT
664 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
665 if (status != 0)
666 {
667 (*info->memory_error_func) (status, memaddr, info);
668 return -1;
669 }
670
671 length = 2;
672
673 if (info->endian == BFD_ENDIAN_BIG)
674 insn = bfd_getb16 (buffer);
675 else
676 insn = bfd_getl16 (buffer);
677
678 /* Handle the extend opcode specially. */
679 use_extend = false;
680 if ((insn & 0xf800) == 0xf000)
681 {
682 use_extend = true;
683 extend = insn & 0x7ff;
684
685 memaddr += 2;
686
687 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
688 if (status != 0)
689 {
690 (*info->fprintf_func) (info->stream, "extend 0x%x",
691 (unsigned int) extend);
692 (*info->memory_error_func) (status, memaddr, info);
693 return -1;
694 }
695
8d67dc30
ILT
696 if (info->endian == BFD_ENDIAN_BIG)
697 insn = bfd_getb16 (buffer);
698 else
699 insn = bfd_getl16 (buffer);
c4f19df2
ILT
700
701 /* Check for an extend opcode followed by an extend opcode. */
702 if ((insn & 0xf800) == 0xf000)
703 {
704 (*info->fprintf_func) (info->stream, "extend 0x%x",
705 (unsigned int) extend);
20d43018 706 info->insn_type = dis_noninsn;
c4f19df2
ILT
707 return length;
708 }
709
710 length += 2;
8d67dc30
ILT
711 }
712
713 /* FIXME: Should probably use a hash table on the major opcode here. */
714
715 opend = mips16_opcodes + bfd_mips16_num_opcodes;
716 for (op = mips16_opcodes; op < opend; op++)
717 {
718 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
719 {
720 const char *s;
721
722 if (strchr (op->args, 'a') != NULL)
723 {
724 if (use_extend)
c4f19df2
ILT
725 {
726 (*info->fprintf_func) (info->stream, "extend 0x%x",
727 (unsigned int) extend);
20d43018 728 info->insn_type = dis_noninsn;
c4f19df2
ILT
729 return length - 2;
730 }
731
8d67dc30
ILT
732 use_extend = false;
733
734 memaddr += 2;
735
736 status = (*info->read_memory_func) (memaddr, buffer, 2,
737 info);
738 if (status == 0)
739 {
740 use_extend = true;
741 if (info->endian == BFD_ENDIAN_BIG)
742 extend = bfd_getb16 (buffer);
743 else
744 extend = bfd_getl16 (buffer);
745 length += 2;
746 }
747 }
748
c4f19df2
ILT
749 (*info->fprintf_func) (info->stream, "%s", op->name);
750 if (op->args[0] != '\0')
751 (*info->fprintf_func) (info->stream, "\t");
8d67dc30
ILT
752
753 for (s = op->args; *s != '\0'; s++)
754 {
755 if (*s == ','
756 && s[1] == 'w'
757 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
758 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
759 {
760 /* Skip the register and the comma. */
761 ++s;
762 continue;
763 }
764 if (*s == ','
765 && s[1] == 'v'
766 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
767 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
768 {
769 /* Skip the register and the comma. */
770 ++s;
771 continue;
772 }
773 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
774 info);
775 }
776
20d43018
ILT
777 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
778 {
779 info->branch_delay_insns = 1;
780 if (info->insn_type != dis_jsr)
781 info->insn_type = dis_branch;
782 }
783
8d67dc30
ILT
784 return length;
785 }
786 }
787
788 if (use_extend)
789 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
790 (*info->fprintf_func) (info->stream, "0x%x", insn);
20d43018 791 info->insn_type = dis_noninsn;
8d67dc30
ILT
792
793 return length;
794}
795
796/* Disassemble an operand for a mips16 instruction. */
797
798static void
799print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
800 int type;
801 const struct mips_opcode *op;
802 int l;
803 boolean use_extend;
804 int extend;
805 bfd_vma memaddr;
806 struct disassemble_info *info;
807{
808 switch (type)
809 {
810 case ',':
811 case '(':
812 case ')':
813 (*info->fprintf_func) (info->stream, "%c", type);
814 break;
815
816 case 'y':
817 case 'w':
818 (*info->fprintf_func) (info->stream, "$%s",
819 mips16_reg_names[((l >> MIPS16OP_SH_RY)
820 & MIPS16OP_MASK_RY)]);
821 break;
822
823 case 'x':
824 case 'v':
825 (*info->fprintf_func) (info->stream, "$%s",
826 mips16_reg_names[((l >> MIPS16OP_SH_RX)
827 & MIPS16OP_MASK_RX)]);
828 break;
829
830 case 'z':
831 (*info->fprintf_func) (info->stream, "$%s",
832 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
833 & MIPS16OP_MASK_RZ)]);
834 break;
835
836 case 'Z':
837 (*info->fprintf_func) (info->stream, "$%s",
838 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
839 & MIPS16OP_MASK_MOVE32Z)]);
840 break;
841
842 case '0':
843 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
844 break;
845
846 case 'S':
847 (*info->fprintf_func) (info->stream, "$%s", reg_names[29]);
848 break;
849
850 case 'P':
851 (*info->fprintf_func) (info->stream, "$pc");
852 break;
853
854 case 'R':
855 (*info->fprintf_func) (info->stream, "$%s", reg_names[31]);
856 break;
857
858 case 'X':
859 (*info->fprintf_func) (info->stream, "$%s",
860 reg_names[((l >> MIPS16OP_SH_REGR32)
861 & MIPS16OP_MASK_REGR32)]);
862 break;
863
864 case 'Y':
865 (*info->fprintf_func) (info->stream, "$%s",
866 reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
867 break;
868
869 case '<':
870 case '>':
871 case '[':
872 case ']':
873 case '4':
874 case '5':
875 case 'H':
876 case 'W':
877 case 'D':
878 case 'j':
879 case '6':
880 case '8':
881 case 'V':
882 case 'C':
883 case 'U':
884 case 'k':
885 case 'K':
886 case 'p':
887 case 'q':
888 case 'A':
889 case 'B':
890 case 'E':
891 {
892 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
893
894 shift = 0;
895 signedp = 0;
896 extbits = 16;
897 pcrel = 0;
898 extu = 0;
899 branch = 0;
900 switch (type)
901 {
902 case '<':
903 nbits = 3;
904 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
905 extbits = 5;
906 extu = 1;
907 break;
908 case '>':
909 nbits = 3;
910 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
911 extbits = 5;
912 extu = 1;
913 break;
914 case '[':
915 nbits = 3;
916 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
917 extbits = 6;
918 extu = 1;
919 break;
920 case ']':
921 nbits = 3;
922 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
923 extbits = 6;
924 extu = 1;
925 break;
926 case '4':
927 nbits = 4;
928 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
929 signedp = 1;
930 extbits = 15;
931 break;
932 case '5':
933 nbits = 5;
934 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
935 info->insn_type = dis_dref;
936 info->data_size = 1;
8d67dc30
ILT
937 break;
938 case 'H':
939 nbits = 5;
940 shift = 1;
941 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
942 info->insn_type = dis_dref;
943 info->data_size = 2;
8d67dc30
ILT
944 break;
945 case 'W':
946 nbits = 5;
947 shift = 2;
948 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
949 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
950 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
951 {
952 info->insn_type = dis_dref;
953 info->data_size = 4;
954 }
8d67dc30
ILT
955 break;
956 case 'D':
957 nbits = 5;
958 shift = 3;
959 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
960 info->insn_type = dis_dref;
961 info->data_size = 8;
8d67dc30
ILT
962 break;
963 case 'j':
964 nbits = 5;
965 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
966 signedp = 1;
967 break;
968 case '6':
969 nbits = 6;
970 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
971 break;
972 case '8':
973 nbits = 8;
974 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
975 break;
976 case 'V':
977 nbits = 8;
978 shift = 2;
979 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
980 /* FIXME: This might be lw, or it might be addiu to $sp or
981 $pc. We assume it's load. */
982 info->insn_type = dis_dref;
983 info->data_size = 4;
8d67dc30
ILT
984 break;
985 case 'C':
986 nbits = 8;
987 shift = 3;
988 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
989 info->insn_type = dis_dref;
990 info->data_size = 8;
8d67dc30
ILT
991 break;
992 case 'U':
993 nbits = 8;
994 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
995 extu = 1;
996 break;
997 case 'k':
998 nbits = 8;
999 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1000 signedp = 1;
1001 break;
1002 case 'K':
1003 nbits = 8;
1004 shift = 3;
1005 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1006 signedp = 1;
1007 break;
1008 case 'p':
1009 nbits = 8;
1010 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1011 signedp = 1;
1012 pcrel = 1;
1013 branch = 1;
20d43018 1014 info->insn_type = dis_condbranch;
8d67dc30
ILT
1015 break;
1016 case 'q':
1017 nbits = 11;
1018 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
1019 signedp = 1;
1020 pcrel = 1;
1021 branch = 1;
20d43018 1022 info->insn_type = dis_branch;
8d67dc30
ILT
1023 break;
1024 case 'A':
1025 nbits = 8;
1026 shift = 2;
1027 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1028 pcrel = 1;
20d43018
ILT
1029 /* FIXME: This can be lw or la. We assume it is lw. */
1030 info->insn_type = dis_dref;
1031 info->data_size = 4;
8d67dc30
ILT
1032 break;
1033 case 'B':
1034 nbits = 5;
1035 shift = 3;
1036 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1037 pcrel = 1;
20d43018
ILT
1038 info->insn_type = dis_dref;
1039 info->data_size = 8;
8d67dc30
ILT
1040 break;
1041 case 'E':
1042 nbits = 5;
1043 shift = 2;
1044 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1045 pcrel = 1;
1046 break;
1047 default:
1048 abort ();
1049 }
1050
1051 if (! use_extend)
1052 {
1053 if (signedp && immed >= (1 << (nbits - 1)))
1054 immed -= 1 << nbits;
1055 immed <<= shift;
1056 if ((type == '<' || type == '>' || type == '[' || type == '[')
1057 && immed == 0)
1058 immed = 8;
1059 }
1060 else
1061 {
1062 if (extbits == 16)
1063 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
1064 else if (extbits == 15)
1065 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
1066 else
1067 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
1068 immed &= (1 << extbits) - 1;
1069 if (! extu && immed >= (1 << (extbits - 1)))
1070 immed -= 1 << extbits;
1071 }
1072
1073 if (! pcrel)
1074 (*info->fprintf_func) (info->stream, "%d", immed);
1075 else
1076 {
c4f19df2 1077 bfd_vma baseaddr;
8d67dc30
ILT
1078 bfd_vma val;
1079
1080 if (branch)
c4f19df2
ILT
1081 {
1082 immed *= 2;
1083 baseaddr = memaddr + 2;
1084 }
1085 else if (use_extend)
83af2335 1086 baseaddr = memaddr - 2;
c4f19df2
ILT
1087 else
1088 {
1089 int status;
1090 bfd_byte buffer[2];
1091
1092 baseaddr = memaddr;
1093
1094 /* If this instruction is in the delay slot of a jr
1095 instruction, the base address is the address of the
1096 jr instruction. If it is in the delay slot of jalr
1097 instruction, the base address is the address of the
1098 jalr instruction. This test is unreliable: we have
1099 no way of knowing whether the previous word is
1100 instruction or data. */
1101 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
1102 info);
1103 if (status == 0
1104 && (((info->endian == BFD_ENDIAN_BIG
1105 ? bfd_getb16 (buffer)
1106 : bfd_getl16 (buffer))
1107 & 0xf800) == 0x1800))
1108 baseaddr = memaddr - 4;
1109 else
1110 {
1111 status = (*info->read_memory_func) (memaddr - 2, buffer,
1112 2, info);
1113 if (status == 0
1114 && (((info->endian == BFD_ENDIAN_BIG
1115 ? bfd_getb16 (buffer)
1116 : bfd_getl16 (buffer))
1117 & 0xf81f) == 0xe800))
1118 baseaddr = memaddr - 2;
1119 }
1120 }
1121 val = (baseaddr & ~ ((1 << shift) - 1)) + immed;
8d67dc30 1122 (*info->print_address_func) (val, info);
20d43018 1123 info->target = val;
8d67dc30
ILT
1124 }
1125 }
1126 break;
1127
1128 case 'a':
1129 if (! use_extend)
1130 extend = 0;
1131 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
1132 (*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
20d43018
ILT
1133 info->insn_type = dis_jsr;
1134 info->target = (memaddr & 0xf0000000) | l;
1135 info->branch_delay_insns = 1;
8d67dc30
ILT
1136 break;
1137
1138 case 'l':
1139 case 'L':
1140 {
1141 int need_comma, amask, smask;
1142
1143 need_comma = 0;
1144
1145 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1146
1147 amask = (l >> 3) & 7;
0d52464c
ILT
1148
1149 if (amask > 0 && amask < 5)
8d67dc30 1150 {
0d52464c 1151 (*info->fprintf_func) (info->stream, "$%s", reg_names[4]);
8d67dc30 1152 if (amask > 1)
0d52464c 1153 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
1154 reg_names[amask + 3]);
1155 need_comma = 1;
1156 }
1157
1158 smask = (l >> 1) & 3;
1159 if (smask == 3)
1160 {
1161 (*info->fprintf_func) (info->stream, "%s??",
1162 need_comma ? "," : "");
1163 need_comma = 1;
1164 }
1165 else if (smask > 0)
1166 {
0d52464c 1167 (*info->fprintf_func) (info->stream, "%s$%s",
8d67dc30
ILT
1168 need_comma ? "," : "",
1169 reg_names[16]);
1170 if (smask > 1)
0d52464c 1171 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
1172 reg_names[smask + 15]);
1173 need_comma = 1;
1174 }
1175
1176 if (l & 1)
0d52464c
ILT
1177 {
1178 (*info->fprintf_func) (info->stream, "%s$%s",
1179 need_comma ? "," : "",
1180 reg_names[31]);
1181 need_comma = 1;
1182 }
1183
1184 if (amask == 5 || amask == 6)
1185 {
1186 (*info->fprintf_func) (info->stream, "%s$f0",
1187 need_comma ? "," : "");
1188 if (amask == 6)
1189 (*info->fprintf_func) (info->stream, "-$f1");
1190 }
8d67dc30
ILT
1191 }
1192 break;
1193
1194 default:
1195 abort ();
1196 }
1197}
This page took 0.228405 seconds and 4 git commands to generate.