* Makefile.am (STAGESTUFF): Remove variable.
[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;
98f699f6
JL
291
292 case 'O':
293 delta = (l >> 6) & 0x7fff;
294 delta <<= 3;
295 (*info->print_address_func) (delta, info);
296 break;
297
ffee80df
JL
298 /* end-sanitize-r5900 */
299
d0ba1cea 300 case 'T':
fde326fb 301 case 'W':
5d0734a7
JK
302 (*info->fprintf_func) (info->stream, "$f%d",
303 (l >> OP_SH_FT) & OP_MASK_FT);
d0ba1cea
ILT
304 break;
305
306 case 'D':
5d0734a7
JK
307 (*info->fprintf_func) (info->stream, "$f%d",
308 (l >> OP_SH_FD) & OP_MASK_FD);
d0ba1cea
ILT
309 break;
310
30b1724c
ILT
311 case 'R':
312 (*info->fprintf_func) (info->stream, "$f%d",
313 (l >> OP_SH_FR) & OP_MASK_FR);
314 break;
315
fde326fb
ILT
316 case 'E':
317 (*info->fprintf_func) (info->stream, "$%d",
318 (l >> OP_SH_RT) & OP_MASK_RT);
319 break;
320
321 case 'G':
322 (*info->fprintf_func) (info->stream, "$%d",
323 (l >> OP_SH_RD) & OP_MASK_RD);
324 break;
325
30b1724c
ILT
326 case 'N':
327 (*info->fprintf_func) (info->stream, "$fcc%d",
328 (l >> OP_SH_BCC) & OP_MASK_BCC);
329 break;
330
331 case 'M':
332 (*info->fprintf_func) (info->stream, "$fcc%d",
333 (l >> OP_SH_CCC) & OP_MASK_CCC);
334 break;
335
83af2335 336 case 'P':
fb1a826b 337 (*info->fprintf_func) (info->stream, "%d",
83af2335
JL
338 (l >> OP_SH_PERFREG) & OP_MASK_PERFREG);
339 break;
340
341 /* start-sanitize-vr5400 */
342 case 'e':
343 (*info->fprintf_func) (info->stream, "%d",
344 (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE);
345 break;
346
347 case '%':
348 (*info->fprintf_func) (info->stream, "%d",
349 (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN);
350 break;
351 /* end-sanitize-vr5400 */
352
d0ba1cea 353 default:
5d0734a7
JK
354 (*info->fprintf_func) (info->stream,
355 "# internal error, undefined modifier(%c)", *d);
d0ba1cea
ILT
356 break;
357 }
358}
359\f
360/* Print the mips instruction at address MEMADDR in debugged memory,
5d0734a7 361 on using INFO. Returns length of the instruction, in bytes, which is
d0ba1cea
ILT
362 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
363 this is little-endian code. */
364
30b1724c 365static int
5d0734a7 366_print_insn_mips (memaddr, word, info)
d0ba1cea 367 bfd_vma memaddr;
5d0734a7 368 unsigned long int word;
8d67dc30 369 struct disassemble_info *info;
d0ba1cea 370{
30b1724c 371 register const struct mips_opcode *op;
83af2335 372 int target_processor, mips_isa;
30b1724c
ILT
373 static boolean init = 0;
374 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
d0ba1cea 375
30b1724c
ILT
376 /* Build a hash table to shorten the search time. */
377 if (! init)
d0ba1cea 378 {
30b1724c
ILT
379 unsigned int i;
380
381 for (i = 0; i <= OP_MASK_OP; i++)
fde326fb 382 {
30b1724c
ILT
383 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
384 {
385 if (op->pinfo == INSN_MACRO)
386 continue;
387 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
388 {
389 mips_hash[i] = op;
390 break;
391 }
392 }
393 }
394
395 init = 1;
d0ba1cea
ILT
396 }
397
83af2335
JL
398 switch (info->mach)
399 {
400 /* start-sanitize-tx19 */
401 case bfd_mach_mips1900:
402 target_processor = 1900;
403 mips_isa = 1;
404 break;
405 /* end-sanitize-tx19 */
406 case bfd_mach_mips3000:
407 target_processor = 3000;
408 mips_isa = 1;
409 break;
410 case bfd_mach_mips3900:
411 target_processor = 3900;
412 mips_isa = 1;
413 break;
414 case bfd_mach_mips4000:
415 target_processor = 4000;
416 mips_isa = 3;
417 break;
418 case bfd_mach_mips4010:
419 target_processor = 4010;
420 mips_isa = 2;
421 break;
422 case bfd_mach_mips4100:
423 target_processor = 4100;
424 mips_isa = 3;
425 break;
426 case bfd_mach_mips4300:
427 target_processor = 4300;
428 mips_isa = 3;
429 break;
ffee80df
JL
430 /* start-sanitize-vr4320 */
431 case bfd_mach_mips4320:
432 target_processor = 4320;
433 mips_isa = 3;
434 break;
435 /* end-sanitize-vr4320 */
83af2335
JL
436 case bfd_mach_mips4400:
437 target_processor = 4400;
438 mips_isa = 3;
439 break;
440 case bfd_mach_mips4600:
441 target_processor = 4600;
442 mips_isa = 3;
443 break;
444 case bfd_mach_mips4650:
445 target_processor = 4650;
446 mips_isa = 3;
447 break;
448 /* start-sanitize-tx49 */
449 case bfd_mach_mips4900:
450 target_processor = 4900;
451 mips_isa = 3;
452 break;
453 /* end-sanitize-tx49 */
454 case bfd_mach_mips5000:
455 target_processor = 5000;
456 mips_isa = 4;
457 break;
458 /* start-sanitize-vr5400 */
459 case bfd_mach_mips5400:
460 target_processor = 5400;
461 mips_isa = 3;
462 break;
463 /* end-sanitize-vr5400 */
464 /* start-sanitize-r5900 */
465 case bfd_mach_mips5900:
466 target_processor = 5900;
467 mips_isa = 3;
468 break;
469 /* end-sanitize-r5900 */
470 case bfd_mach_mips6000:
471 target_processor = 6000;
472 mips_isa = 2;
473 break;
474 case bfd_mach_mips8000:
475 target_processor = 8000;
476 mips_isa = 4;
477 break;
478 case bfd_mach_mips10000:
479 target_processor = 10000;
480 mips_isa = 4;
481 break;
482 case bfd_mach_mips16:
483 target_processor = 16;
484 mips_isa = 3;
485 break;
486 default:
487 target_processor = 3000;
488 mips_isa = 3;
489 break;
490
491 }
492
2ea116f4
ILT
493 info->bytes_per_chunk = 4;
494 info->display_endian = info->endian;
495
30b1724c
ILT
496 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
497 if (op != NULL)
d0ba1cea 498 {
30b1724c
ILT
499 for (; op < &mips_opcodes[NUMOPCODES]; op++)
500 {
501 if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
502 {
503 register const char *d;
83af2335
JL
504 int insn_isa;
505
506 if ((op->membership & INSN_ISA) == INSN_ISA1)
507 insn_isa = 1;
508 else if ((op->membership & INSN_ISA) == INSN_ISA2)
509 insn_isa = 2;
510 else if ((op->membership & INSN_ISA) == INSN_ISA3)
511 insn_isa = 3;
512 else if ((op->membership & INSN_ISA) == INSN_ISA4)
513 insn_isa = 4;
514 else
515 insn_isa = 15;
516
517 if (insn_isa > mips_isa
518 && (target_processor == 4650
519 && op->membership & INSN_4650) == 0
520 && (target_processor == 4010
521 && op->membership & INSN_4010) == 0
522 && (target_processor == 4100
523 && op->membership & INSN_4100) == 0
ffee80df
JL
524 /* start-sanitize-vr4320 */
525 && (target_processor == 4320
526 && op->membership & INSN_4320) == 0
527 /* end-sanitize-vr4320 */
83af2335
JL
528 /* start-sanitize-vr5400 */
529 && (target_processor == 5400
530 && op->membership & INSN_5400) == 0
fb1a826b 531 /* end-sanitize-vr5400 */
83af2335
JL
532 /* start-sanitize-r5900 */
533 && (target_processor == 5900
534 && op->membership & INSN_5900) == 0
535 /* end-sanitize-r5900 */
536 /* start-sanitize-tx49 */
537 && (target_processor == 4900
538 && op->membership & INSN_4900) == 0
539 /* end-sanitize-tx49 */
540 && (target_processor == 3900
541 && op->membership & INSN_3900) == 0)
542 continue;
30b1724c
ILT
543
544 (*info->fprintf_func) (info->stream, "%s", op->name);
545
546 d = op->args;
8d67dc30 547 if (d != NULL && *d != '\0')
30b1724c 548 {
ffee80df
JL
549 /* start-sanitize-r5900 */
550 /* If this is an opcode completer, then do not emit
551 a tab after the opcode. */
552 if (*d != '&')
553 /* end-sanitize-r5900 */
554 (*info->fprintf_func) (info->stream, "\t");
30b1724c 555 for (; *d != '\0'; d++)
ffee80df
JL
556 /* start-sanitize-r5900 */
557 /* If this is an escape character, go ahead and print the
558 next character in the arg string verbatim. */
98f699f6 559 if (*d == '#')
ffee80df
JL
560 {
561 d++;
562 (*info->fprintf_func) (info->stream, "%c", *d);
563 }
564 else
565 /* end-sanitize-r5900 */
566 print_insn_arg (d, word, memaddr, info);
30b1724c
ILT
567 }
568
569 return 4;
570 }
571 }
d0ba1cea
ILT
572 }
573
30b1724c
ILT
574 /* Handle undefined instructions. */
575 (*info->fprintf_func) (info->stream, "0x%x", word);
d0ba1cea
ILT
576 return 4;
577}
5d0734a7
JK
578
579int
580print_insn_big_mips (memaddr, info)
581 bfd_vma memaddr;
582 struct disassemble_info *info;
583{
584 bfd_byte buffer[4];
8d67dc30
ILT
585 int status;
586
587 if (info->mach == 16
588 || (info->flavour == bfd_target_elf_flavour
88b38f0c
DE
589 && info->symbols != NULL
590 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
8d67dc30
ILT
591 == STO_MIPS16)))
592 return print_insn_mips16 (memaddr, info);
593
594 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 595 if (status == 0)
8d67dc30
ILT
596 return _print_insn_mips (memaddr, (unsigned long) bfd_getb32 (buffer),
597 info);
5d0734a7
JK
598 else
599 {
600 (*info->memory_error_func) (status, memaddr, info);
601 return -1;
602 }
603}
604
605int
606print_insn_little_mips (memaddr, info)
607 bfd_vma memaddr;
608 struct disassemble_info *info;
609{
610 bfd_byte buffer[4];
8d67dc30
ILT
611 int status;
612
37130f11
DE
613 /* start-sanitize-sky */
614#ifdef ARCH_dvp
88b38f0c
DE
615 {
616 /* bfd_mach_dvp_p is a macro which may evaluate its arguments more than
617 once. Since dvp_mach_type is a function, ensure it's only called
618 once. */
619 int mach = dvp_info_mach_type (info);
620
621 if (bfd_mach_dvp_p (info->mach)
622 || bfd_mach_dvp_p (mach))
623 return print_insn_dvp (memaddr, info);
624 }
37130f11
DE
625#endif
626 /* end-sanitize-sky */
627
8d67dc30
ILT
628 if (info->mach == 16
629 || (info->flavour == bfd_target_elf_flavour
88b38f0c
DE
630 && info->symbols != NULL
631 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
8d67dc30
ILT
632 == STO_MIPS16)))
633 return print_insn_mips16 (memaddr, info);
634
635 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 636 if (status == 0)
8d67dc30
ILT
637 return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer),
638 info);
5d0734a7
JK
639 else
640 {
641 (*info->memory_error_func) (status, memaddr, info);
642 return -1;
643 }
644}
8d67dc30
ILT
645\f
646/* Disassemble mips16 instructions. */
647
648static int
649print_insn_mips16 (memaddr, info)
650 bfd_vma memaddr;
651 struct disassemble_info *info;
652{
653 int status;
654 bfd_byte buffer[2];
655 int length;
656 int insn;
657 boolean use_extend;
658 int extend;
659 const struct mips_opcode *op, *opend;
660
2ea116f4
ILT
661 info->bytes_per_chunk = 2;
662 info->display_endian = info->endian;
663
20d43018
ILT
664 info->insn_info_valid = 1;
665 info->branch_delay_insns = 0;
666 info->data_size = 0;
667 info->insn_type = dis_nonbranch;
668 info->target = 0;
669 info->target2 = 0;
670
8d67dc30
ILT
671 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
672 if (status != 0)
673 {
674 (*info->memory_error_func) (status, memaddr, info);
675 return -1;
676 }
677
678 length = 2;
679
680 if (info->endian == BFD_ENDIAN_BIG)
681 insn = bfd_getb16 (buffer);
682 else
683 insn = bfd_getl16 (buffer);
684
685 /* Handle the extend opcode specially. */
686 use_extend = false;
687 if ((insn & 0xf800) == 0xf000)
688 {
689 use_extend = true;
690 extend = insn & 0x7ff;
691
692 memaddr += 2;
693
694 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
695 if (status != 0)
696 {
697 (*info->fprintf_func) (info->stream, "extend 0x%x",
698 (unsigned int) extend);
699 (*info->memory_error_func) (status, memaddr, info);
700 return -1;
701 }
702
8d67dc30
ILT
703 if (info->endian == BFD_ENDIAN_BIG)
704 insn = bfd_getb16 (buffer);
705 else
706 insn = bfd_getl16 (buffer);
c4f19df2
ILT
707
708 /* Check for an extend opcode followed by an extend opcode. */
709 if ((insn & 0xf800) == 0xf000)
710 {
711 (*info->fprintf_func) (info->stream, "extend 0x%x",
712 (unsigned int) extend);
20d43018 713 info->insn_type = dis_noninsn;
c4f19df2
ILT
714 return length;
715 }
716
717 length += 2;
8d67dc30
ILT
718 }
719
720 /* FIXME: Should probably use a hash table on the major opcode here. */
721
722 opend = mips16_opcodes + bfd_mips16_num_opcodes;
723 for (op = mips16_opcodes; op < opend; op++)
724 {
725 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
726 {
727 const char *s;
728
729 if (strchr (op->args, 'a') != NULL)
730 {
731 if (use_extend)
c4f19df2
ILT
732 {
733 (*info->fprintf_func) (info->stream, "extend 0x%x",
734 (unsigned int) extend);
20d43018 735 info->insn_type = dis_noninsn;
c4f19df2
ILT
736 return length - 2;
737 }
738
8d67dc30
ILT
739 use_extend = false;
740
741 memaddr += 2;
742
743 status = (*info->read_memory_func) (memaddr, buffer, 2,
744 info);
745 if (status == 0)
746 {
747 use_extend = true;
748 if (info->endian == BFD_ENDIAN_BIG)
749 extend = bfd_getb16 (buffer);
750 else
751 extend = bfd_getl16 (buffer);
752 length += 2;
753 }
754 }
755
c4f19df2
ILT
756 (*info->fprintf_func) (info->stream, "%s", op->name);
757 if (op->args[0] != '\0')
758 (*info->fprintf_func) (info->stream, "\t");
8d67dc30
ILT
759
760 for (s = op->args; *s != '\0'; s++)
761 {
762 if (*s == ','
763 && s[1] == 'w'
764 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
765 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
766 {
767 /* Skip the register and the comma. */
768 ++s;
769 continue;
770 }
771 if (*s == ','
772 && s[1] == 'v'
773 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
774 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
775 {
776 /* Skip the register and the comma. */
777 ++s;
778 continue;
779 }
780 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
781 info);
782 }
783
20d43018
ILT
784 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
785 {
786 info->branch_delay_insns = 1;
787 if (info->insn_type != dis_jsr)
788 info->insn_type = dis_branch;
789 }
790
8d67dc30
ILT
791 return length;
792 }
793 }
794
795 if (use_extend)
796 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
797 (*info->fprintf_func) (info->stream, "0x%x", insn);
20d43018 798 info->insn_type = dis_noninsn;
8d67dc30
ILT
799
800 return length;
801}
802
803/* Disassemble an operand for a mips16 instruction. */
804
805static void
806print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
807 int type;
808 const struct mips_opcode *op;
809 int l;
810 boolean use_extend;
811 int extend;
812 bfd_vma memaddr;
813 struct disassemble_info *info;
814{
815 switch (type)
816 {
817 case ',':
818 case '(':
819 case ')':
820 (*info->fprintf_func) (info->stream, "%c", type);
821 break;
822
823 case 'y':
824 case 'w':
825 (*info->fprintf_func) (info->stream, "$%s",
826 mips16_reg_names[((l >> MIPS16OP_SH_RY)
827 & MIPS16OP_MASK_RY)]);
828 break;
829
830 case 'x':
831 case 'v':
832 (*info->fprintf_func) (info->stream, "$%s",
833 mips16_reg_names[((l >> MIPS16OP_SH_RX)
834 & MIPS16OP_MASK_RX)]);
835 break;
836
837 case 'z':
838 (*info->fprintf_func) (info->stream, "$%s",
839 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
840 & MIPS16OP_MASK_RZ)]);
841 break;
842
843 case 'Z':
844 (*info->fprintf_func) (info->stream, "$%s",
845 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
846 & MIPS16OP_MASK_MOVE32Z)]);
847 break;
848
849 case '0':
850 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
851 break;
852
853 case 'S':
854 (*info->fprintf_func) (info->stream, "$%s", reg_names[29]);
855 break;
856
857 case 'P':
858 (*info->fprintf_func) (info->stream, "$pc");
859 break;
860
861 case 'R':
862 (*info->fprintf_func) (info->stream, "$%s", reg_names[31]);
863 break;
864
865 case 'X':
866 (*info->fprintf_func) (info->stream, "$%s",
867 reg_names[((l >> MIPS16OP_SH_REGR32)
868 & MIPS16OP_MASK_REGR32)]);
869 break;
870
871 case 'Y':
872 (*info->fprintf_func) (info->stream, "$%s",
873 reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
874 break;
875
876 case '<':
877 case '>':
878 case '[':
879 case ']':
880 case '4':
881 case '5':
882 case 'H':
883 case 'W':
884 case 'D':
885 case 'j':
886 case '6':
887 case '8':
888 case 'V':
889 case 'C':
890 case 'U':
891 case 'k':
892 case 'K':
893 case 'p':
894 case 'q':
895 case 'A':
896 case 'B':
897 case 'E':
898 {
899 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
900
901 shift = 0;
902 signedp = 0;
903 extbits = 16;
904 pcrel = 0;
905 extu = 0;
906 branch = 0;
907 switch (type)
908 {
909 case '<':
910 nbits = 3;
911 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
912 extbits = 5;
913 extu = 1;
914 break;
915 case '>':
916 nbits = 3;
917 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
918 extbits = 5;
919 extu = 1;
920 break;
921 case '[':
922 nbits = 3;
923 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
924 extbits = 6;
925 extu = 1;
926 break;
927 case ']':
928 nbits = 3;
929 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
930 extbits = 6;
931 extu = 1;
932 break;
933 case '4':
934 nbits = 4;
935 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
936 signedp = 1;
937 extbits = 15;
938 break;
939 case '5':
940 nbits = 5;
941 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
942 info->insn_type = dis_dref;
943 info->data_size = 1;
8d67dc30
ILT
944 break;
945 case 'H':
946 nbits = 5;
947 shift = 1;
948 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
949 info->insn_type = dis_dref;
950 info->data_size = 2;
8d67dc30
ILT
951 break;
952 case 'W':
953 nbits = 5;
954 shift = 2;
955 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
956 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
957 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
958 {
959 info->insn_type = dis_dref;
960 info->data_size = 4;
961 }
8d67dc30
ILT
962 break;
963 case 'D':
964 nbits = 5;
965 shift = 3;
966 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
967 info->insn_type = dis_dref;
968 info->data_size = 8;
8d67dc30
ILT
969 break;
970 case 'j':
971 nbits = 5;
972 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
973 signedp = 1;
974 break;
975 case '6':
976 nbits = 6;
977 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
978 break;
979 case '8':
980 nbits = 8;
981 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
982 break;
983 case 'V':
984 nbits = 8;
985 shift = 2;
986 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
987 /* FIXME: This might be lw, or it might be addiu to $sp or
988 $pc. We assume it's load. */
989 info->insn_type = dis_dref;
990 info->data_size = 4;
8d67dc30
ILT
991 break;
992 case 'C':
993 nbits = 8;
994 shift = 3;
995 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
996 info->insn_type = dis_dref;
997 info->data_size = 8;
8d67dc30
ILT
998 break;
999 case 'U':
1000 nbits = 8;
1001 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1002 extu = 1;
1003 break;
1004 case 'k':
1005 nbits = 8;
1006 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1007 signedp = 1;
1008 break;
1009 case 'K':
1010 nbits = 8;
1011 shift = 3;
1012 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1013 signedp = 1;
1014 break;
1015 case 'p':
1016 nbits = 8;
1017 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1018 signedp = 1;
1019 pcrel = 1;
1020 branch = 1;
20d43018 1021 info->insn_type = dis_condbranch;
8d67dc30
ILT
1022 break;
1023 case 'q':
1024 nbits = 11;
1025 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
1026 signedp = 1;
1027 pcrel = 1;
1028 branch = 1;
20d43018 1029 info->insn_type = dis_branch;
8d67dc30
ILT
1030 break;
1031 case 'A':
1032 nbits = 8;
1033 shift = 2;
1034 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1035 pcrel = 1;
20d43018
ILT
1036 /* FIXME: This can be lw or la. We assume it is lw. */
1037 info->insn_type = dis_dref;
1038 info->data_size = 4;
8d67dc30
ILT
1039 break;
1040 case 'B':
1041 nbits = 5;
1042 shift = 3;
1043 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1044 pcrel = 1;
20d43018
ILT
1045 info->insn_type = dis_dref;
1046 info->data_size = 8;
8d67dc30
ILT
1047 break;
1048 case 'E':
1049 nbits = 5;
1050 shift = 2;
1051 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1052 pcrel = 1;
1053 break;
1054 default:
1055 abort ();
1056 }
1057
1058 if (! use_extend)
1059 {
1060 if (signedp && immed >= (1 << (nbits - 1)))
1061 immed -= 1 << nbits;
1062 immed <<= shift;
1063 if ((type == '<' || type == '>' || type == '[' || type == '[')
1064 && immed == 0)
1065 immed = 8;
1066 }
1067 else
1068 {
1069 if (extbits == 16)
1070 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
1071 else if (extbits == 15)
1072 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
1073 else
1074 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
1075 immed &= (1 << extbits) - 1;
1076 if (! extu && immed >= (1 << (extbits - 1)))
1077 immed -= 1 << extbits;
1078 }
1079
1080 if (! pcrel)
1081 (*info->fprintf_func) (info->stream, "%d", immed);
1082 else
1083 {
c4f19df2 1084 bfd_vma baseaddr;
8d67dc30
ILT
1085 bfd_vma val;
1086
1087 if (branch)
c4f19df2
ILT
1088 {
1089 immed *= 2;
1090 baseaddr = memaddr + 2;
1091 }
1092 else if (use_extend)
83af2335 1093 baseaddr = memaddr - 2;
c4f19df2
ILT
1094 else
1095 {
1096 int status;
1097 bfd_byte buffer[2];
1098
1099 baseaddr = memaddr;
1100
1101 /* If this instruction is in the delay slot of a jr
1102 instruction, the base address is the address of the
1103 jr instruction. If it is in the delay slot of jalr
1104 instruction, the base address is the address of the
1105 jalr instruction. This test is unreliable: we have
1106 no way of knowing whether the previous word is
1107 instruction or data. */
1108 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
1109 info);
1110 if (status == 0
1111 && (((info->endian == BFD_ENDIAN_BIG
1112 ? bfd_getb16 (buffer)
1113 : bfd_getl16 (buffer))
1114 & 0xf800) == 0x1800))
1115 baseaddr = memaddr - 4;
1116 else
1117 {
1118 status = (*info->read_memory_func) (memaddr - 2, buffer,
1119 2, info);
1120 if (status == 0
1121 && (((info->endian == BFD_ENDIAN_BIG
1122 ? bfd_getb16 (buffer)
1123 : bfd_getl16 (buffer))
1124 & 0xf81f) == 0xe800))
1125 baseaddr = memaddr - 2;
1126 }
1127 }
1128 val = (baseaddr & ~ ((1 << shift) - 1)) + immed;
8d67dc30 1129 (*info->print_address_func) (val, info);
20d43018 1130 info->target = val;
8d67dc30
ILT
1131 }
1132 }
1133 break;
1134
1135 case 'a':
1136 if (! use_extend)
1137 extend = 0;
1138 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
1139 (*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
20d43018
ILT
1140 info->insn_type = dis_jsr;
1141 info->target = (memaddr & 0xf0000000) | l;
1142 info->branch_delay_insns = 1;
8d67dc30
ILT
1143 break;
1144
1145 case 'l':
1146 case 'L':
1147 {
1148 int need_comma, amask, smask;
1149
1150 need_comma = 0;
1151
1152 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1153
1154 amask = (l >> 3) & 7;
0d52464c
ILT
1155
1156 if (amask > 0 && amask < 5)
8d67dc30 1157 {
0d52464c 1158 (*info->fprintf_func) (info->stream, "$%s", reg_names[4]);
8d67dc30 1159 if (amask > 1)
0d52464c 1160 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
1161 reg_names[amask + 3]);
1162 need_comma = 1;
1163 }
1164
1165 smask = (l >> 1) & 3;
1166 if (smask == 3)
1167 {
1168 (*info->fprintf_func) (info->stream, "%s??",
1169 need_comma ? "," : "");
1170 need_comma = 1;
1171 }
1172 else if (smask > 0)
1173 {
0d52464c 1174 (*info->fprintf_func) (info->stream, "%s$%s",
8d67dc30
ILT
1175 need_comma ? "," : "",
1176 reg_names[16]);
1177 if (smask > 1)
0d52464c 1178 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
1179 reg_names[smask + 15]);
1180 need_comma = 1;
1181 }
1182
1183 if (l & 1)
0d52464c
ILT
1184 {
1185 (*info->fprintf_func) (info->stream, "%s$%s",
1186 need_comma ? "," : "",
1187 reg_names[31]);
1188 need_comma = 1;
1189 }
1190
1191 if (amask == 5 || amask == 6)
1192 {
1193 (*info->fprintf_func) (info->stream, "%s$f0",
1194 need_comma ? "," : "");
1195 if (amask == 6)
1196 (*info->fprintf_func) (info->stream, "-$f1");
1197 }
8d67dc30
ILT
1198 }
1199 break;
1200
1201 default:
1202 abort ();
1203 }
1204}
This page took 0.43483 seconds and 4 git commands to generate.