Add r5900
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
d0ba1cea 1/* Print mips instructions for GDB, the GNU debugger, or for objdump.
0d52464c 2 Copyright 1989, 91, 92, 93, 94, 95, 96, 1997 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 ')':
5d0734a7 83 (*info->fprintf_func) (info->stream, "%c", *d);
d0ba1cea
ILT
84 break;
85
86 case 's':
fde326fb
ILT
87 case 'b':
88 case 'r':
89 case 'v':
5d0734a7
JK
90 (*info->fprintf_func) (info->stream, "$%s",
91 reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
d0ba1cea
ILT
92 break;
93
94 case 't':
fde326fb 95 case 'w':
5d0734a7
JK
96 (*info->fprintf_func) (info->stream, "$%s",
97 reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
d0ba1cea
ILT
98 break;
99
100 case 'i':
fde326fb 101 case 'u':
30b1724c 102 (*info->fprintf_func) (info->stream, "0x%x",
5d0734a7 103 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
d0ba1cea
ILT
104 break;
105
106 case 'j': /* same as i, but sign-extended */
fde326fb
ILT
107 case 'o':
108 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
109 if (delta & 0x8000)
110 delta |= ~0xffff;
5d0734a7 111 (*info->fprintf_func) (info->stream, "%d",
fde326fb 112 delta);
d0ba1cea
ILT
113 break;
114
30b1724c
ILT
115 case 'h':
116 (*info->fprintf_func) (info->stream, "0x%x",
117 (unsigned int) ((l >> OP_SH_PREFX)
118 & OP_MASK_PREFX));
119 break;
120
121 case 'k':
122 (*info->fprintf_func) (info->stream, "0x%x",
123 (unsigned int) ((l >> OP_SH_CACHE)
124 & OP_MASK_CACHE));
125 break;
126
d0ba1cea 127 case 'a':
fde326fb
ILT
128 (*info->print_address_func)
129 (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
130 info);
d0ba1cea
ILT
131 break;
132
fde326fb
ILT
133 case 'p':
134 /* sign extend the displacement */
135 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
136 if (delta & 0x8000)
137 delta |= ~0xffff;
138 (*info->print_address_func)
139 ((delta << 2) + pc + 4,
140 info);
d0ba1cea
ILT
141 break;
142
143 case 'd':
5d0734a7
JK
144 (*info->fprintf_func) (info->stream, "$%s",
145 reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
d0ba1cea
ILT
146 break;
147
547998d2
ILT
148 case 'z':
149 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
150 break;
151
fde326fb 152 case '<':
5d0734a7
JK
153 (*info->fprintf_func) (info->stream, "0x%x",
154 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
d0ba1cea
ILT
155 break;
156
fde326fb 157 case 'c':
5d0734a7
JK
158 (*info->fprintf_func) (info->stream, "0x%x",
159 (l >> OP_SH_CODE) & OP_MASK_CODE);
d0ba1cea
ILT
160 break;
161
fde326fb
ILT
162 case 'C':
163 (*info->fprintf_func) (info->stream, "0x%x",
164 (l >> OP_SH_COPZ) & OP_MASK_COPZ);
165 break;
166
167 case 'B':
168 (*info->fprintf_func) (info->stream, "0x%x",
169 (l >> OP_SH_SYSCALL) & OP_MASK_SYSCALL);
170 break;
171
d0ba1cea 172 case 'S':
fde326fb 173 case 'V':
5d0734a7
JK
174 (*info->fprintf_func) (info->stream, "$f%d",
175 (l >> OP_SH_FS) & OP_MASK_FS);
d0ba1cea
ILT
176 break;
177
178 case 'T':
fde326fb 179 case 'W':
5d0734a7
JK
180 (*info->fprintf_func) (info->stream, "$f%d",
181 (l >> OP_SH_FT) & OP_MASK_FT);
d0ba1cea
ILT
182 break;
183
184 case 'D':
5d0734a7
JK
185 (*info->fprintf_func) (info->stream, "$f%d",
186 (l >> OP_SH_FD) & OP_MASK_FD);
d0ba1cea
ILT
187 break;
188
30b1724c
ILT
189 case 'R':
190 (*info->fprintf_func) (info->stream, "$f%d",
191 (l >> OP_SH_FR) & OP_MASK_FR);
192 break;
193
fde326fb
ILT
194 case 'E':
195 (*info->fprintf_func) (info->stream, "$%d",
196 (l >> OP_SH_RT) & OP_MASK_RT);
197 break;
198
199 case 'G':
200 (*info->fprintf_func) (info->stream, "$%d",
201 (l >> OP_SH_RD) & OP_MASK_RD);
202 break;
203
30b1724c
ILT
204 case 'N':
205 (*info->fprintf_func) (info->stream, "$fcc%d",
206 (l >> OP_SH_BCC) & OP_MASK_BCC);
207 break;
208
209 case 'M':
210 (*info->fprintf_func) (info->stream, "$fcc%d",
211 (l >> OP_SH_CCC) & OP_MASK_CCC);
212 break;
213
d0ba1cea 214 default:
5d0734a7
JK
215 (*info->fprintf_func) (info->stream,
216 "# internal error, undefined modifier(%c)", *d);
d0ba1cea
ILT
217 break;
218 }
219}
220\f
221/* Print the mips instruction at address MEMADDR in debugged memory,
5d0734a7 222 on using INFO. Returns length of the instruction, in bytes, which is
d0ba1cea
ILT
223 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
224 this is little-endian code. */
225
30b1724c 226static int
5d0734a7 227_print_insn_mips (memaddr, word, info)
d0ba1cea 228 bfd_vma memaddr;
5d0734a7 229 unsigned long int word;
8d67dc30 230 struct disassemble_info *info;
d0ba1cea 231{
30b1724c
ILT
232 register const struct mips_opcode *op;
233 static boolean init = 0;
234 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
d0ba1cea 235
30b1724c
ILT
236 /* Build a hash table to shorten the search time. */
237 if (! init)
d0ba1cea 238 {
30b1724c
ILT
239 unsigned int i;
240
241 for (i = 0; i <= OP_MASK_OP; i++)
fde326fb 242 {
30b1724c
ILT
243 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
244 {
245 if (op->pinfo == INSN_MACRO)
246 continue;
247 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
248 {
249 mips_hash[i] = op;
250 break;
251 }
252 }
253 }
254
255 init = 1;
d0ba1cea
ILT
256 }
257
30b1724c
ILT
258 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
259 if (op != NULL)
d0ba1cea 260 {
30b1724c
ILT
261 for (; op < &mips_opcodes[NUMOPCODES]; op++)
262 {
263 if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
264 {
265 register const char *d;
266
267 (*info->fprintf_func) (info->stream, "%s", op->name);
268
269 d = op->args;
8d67dc30 270 if (d != NULL && *d != '\0')
30b1724c 271 {
8d67dc30 272 (*info->fprintf_func) (info->stream, "\t");
30b1724c
ILT
273 for (; *d != '\0'; d++)
274 print_insn_arg (d, word, memaddr, info);
275 }
276
277 return 4;
278 }
279 }
d0ba1cea
ILT
280 }
281
30b1724c
ILT
282 /* Handle undefined instructions. */
283 (*info->fprintf_func) (info->stream, "0x%x", word);
d0ba1cea
ILT
284 return 4;
285}
5d0734a7
JK
286
287int
288print_insn_big_mips (memaddr, info)
289 bfd_vma memaddr;
290 struct disassemble_info *info;
291{
292 bfd_byte buffer[4];
8d67dc30
ILT
293 int status;
294
295 if (info->mach == 16
296 || (info->flavour == bfd_target_elf_flavour
297 && info->symbol != NULL
298 && (((elf_symbol_type *) info->symbol)->internal_elf_sym.st_other
299 == STO_MIPS16)))
300 return print_insn_mips16 (memaddr, info);
301
302 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 303 if (status == 0)
8d67dc30
ILT
304 return _print_insn_mips (memaddr, (unsigned long) bfd_getb32 (buffer),
305 info);
5d0734a7
JK
306 else
307 {
308 (*info->memory_error_func) (status, memaddr, info);
309 return -1;
310 }
311}
312
313int
314print_insn_little_mips (memaddr, info)
315 bfd_vma memaddr;
316 struct disassemble_info *info;
317{
318 bfd_byte buffer[4];
8d67dc30
ILT
319 int status;
320
321 if (info->mach == 16
322 || (info->flavour == bfd_target_elf_flavour
323 && info->symbol != NULL
324 && (((elf_symbol_type *) info->symbol)->internal_elf_sym.st_other
325 == STO_MIPS16)))
326 return print_insn_mips16 (memaddr, info);
327
328 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 329 if (status == 0)
8d67dc30
ILT
330 return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer),
331 info);
5d0734a7
JK
332 else
333 {
334 (*info->memory_error_func) (status, memaddr, info);
335 return -1;
336 }
337}
8d67dc30
ILT
338\f
339/* Disassemble mips16 instructions. */
340
341static int
342print_insn_mips16 (memaddr, info)
343 bfd_vma memaddr;
344 struct disassemble_info *info;
345{
346 int status;
347 bfd_byte buffer[2];
348 int length;
349 int insn;
350 boolean use_extend;
351 int extend;
352 const struct mips_opcode *op, *opend;
353
20d43018
ILT
354 info->insn_info_valid = 1;
355 info->branch_delay_insns = 0;
356 info->data_size = 0;
357 info->insn_type = dis_nonbranch;
358 info->target = 0;
359 info->target2 = 0;
360
8d67dc30
ILT
361 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
362 if (status != 0)
363 {
364 (*info->memory_error_func) (status, memaddr, info);
365 return -1;
366 }
367
368 length = 2;
369
370 if (info->endian == BFD_ENDIAN_BIG)
371 insn = bfd_getb16 (buffer);
372 else
373 insn = bfd_getl16 (buffer);
374
375 /* Handle the extend opcode specially. */
376 use_extend = false;
377 if ((insn & 0xf800) == 0xf000)
378 {
379 use_extend = true;
380 extend = insn & 0x7ff;
381
382 memaddr += 2;
383
384 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
385 if (status != 0)
386 {
387 (*info->fprintf_func) (info->stream, "extend 0x%x",
388 (unsigned int) extend);
389 (*info->memory_error_func) (status, memaddr, info);
390 return -1;
391 }
392
8d67dc30
ILT
393 if (info->endian == BFD_ENDIAN_BIG)
394 insn = bfd_getb16 (buffer);
395 else
396 insn = bfd_getl16 (buffer);
c4f19df2
ILT
397
398 /* Check for an extend opcode followed by an extend opcode. */
399 if ((insn & 0xf800) == 0xf000)
400 {
401 (*info->fprintf_func) (info->stream, "extend 0x%x",
402 (unsigned int) extend);
20d43018 403 info->insn_type = dis_noninsn;
c4f19df2
ILT
404 return length;
405 }
406
407 length += 2;
8d67dc30
ILT
408 }
409
410 /* FIXME: Should probably use a hash table on the major opcode here. */
411
412 opend = mips16_opcodes + bfd_mips16_num_opcodes;
413 for (op = mips16_opcodes; op < opend; op++)
414 {
415 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
416 {
417 const char *s;
418
419 if (strchr (op->args, 'a') != NULL)
420 {
421 if (use_extend)
c4f19df2
ILT
422 {
423 (*info->fprintf_func) (info->stream, "extend 0x%x",
424 (unsigned int) extend);
20d43018 425 info->insn_type = dis_noninsn;
c4f19df2
ILT
426 return length - 2;
427 }
428
8d67dc30
ILT
429 use_extend = false;
430
431 memaddr += 2;
432
433 status = (*info->read_memory_func) (memaddr, buffer, 2,
434 info);
435 if (status == 0)
436 {
437 use_extend = true;
438 if (info->endian == BFD_ENDIAN_BIG)
439 extend = bfd_getb16 (buffer);
440 else
441 extend = bfd_getl16 (buffer);
442 length += 2;
443 }
444 }
445
c4f19df2
ILT
446 (*info->fprintf_func) (info->stream, "%s", op->name);
447 if (op->args[0] != '\0')
448 (*info->fprintf_func) (info->stream, "\t");
8d67dc30
ILT
449
450 for (s = op->args; *s != '\0'; s++)
451 {
452 if (*s == ','
453 && s[1] == 'w'
454 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
455 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
456 {
457 /* Skip the register and the comma. */
458 ++s;
459 continue;
460 }
461 if (*s == ','
462 && s[1] == 'v'
463 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
464 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
465 {
466 /* Skip the register and the comma. */
467 ++s;
468 continue;
469 }
470 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
471 info);
472 }
473
20d43018
ILT
474 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
475 {
476 info->branch_delay_insns = 1;
477 if (info->insn_type != dis_jsr)
478 info->insn_type = dis_branch;
479 }
480
8d67dc30
ILT
481 return length;
482 }
483 }
484
485 if (use_extend)
486 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
487 (*info->fprintf_func) (info->stream, "0x%x", insn);
20d43018 488 info->insn_type = dis_noninsn;
8d67dc30
ILT
489
490 return length;
491}
492
493/* Disassemble an operand for a mips16 instruction. */
494
495static void
496print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
497 int type;
498 const struct mips_opcode *op;
499 int l;
500 boolean use_extend;
501 int extend;
502 bfd_vma memaddr;
503 struct disassemble_info *info;
504{
505 switch (type)
506 {
507 case ',':
508 case '(':
509 case ')':
510 (*info->fprintf_func) (info->stream, "%c", type);
511 break;
512
513 case 'y':
514 case 'w':
515 (*info->fprintf_func) (info->stream, "$%s",
516 mips16_reg_names[((l >> MIPS16OP_SH_RY)
517 & MIPS16OP_MASK_RY)]);
518 break;
519
520 case 'x':
521 case 'v':
522 (*info->fprintf_func) (info->stream, "$%s",
523 mips16_reg_names[((l >> MIPS16OP_SH_RX)
524 & MIPS16OP_MASK_RX)]);
525 break;
526
527 case 'z':
528 (*info->fprintf_func) (info->stream, "$%s",
529 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
530 & MIPS16OP_MASK_RZ)]);
531 break;
532
533 case 'Z':
534 (*info->fprintf_func) (info->stream, "$%s",
535 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
536 & MIPS16OP_MASK_MOVE32Z)]);
537 break;
538
539 case '0':
540 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
541 break;
542
543 case 'S':
544 (*info->fprintf_func) (info->stream, "$%s", reg_names[29]);
545 break;
546
547 case 'P':
548 (*info->fprintf_func) (info->stream, "$pc");
549 break;
550
551 case 'R':
552 (*info->fprintf_func) (info->stream, "$%s", reg_names[31]);
553 break;
554
555 case 'X':
556 (*info->fprintf_func) (info->stream, "$%s",
557 reg_names[((l >> MIPS16OP_SH_REGR32)
558 & MIPS16OP_MASK_REGR32)]);
559 break;
560
561 case 'Y':
562 (*info->fprintf_func) (info->stream, "$%s",
563 reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
564 break;
565
566 case '<':
567 case '>':
568 case '[':
569 case ']':
570 case '4':
571 case '5':
572 case 'H':
573 case 'W':
574 case 'D':
575 case 'j':
576 case '6':
577 case '8':
578 case 'V':
579 case 'C':
580 case 'U':
581 case 'k':
582 case 'K':
583 case 'p':
584 case 'q':
585 case 'A':
586 case 'B':
587 case 'E':
588 {
589 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
590
591 shift = 0;
592 signedp = 0;
593 extbits = 16;
594 pcrel = 0;
595 extu = 0;
596 branch = 0;
597 switch (type)
598 {
599 case '<':
600 nbits = 3;
601 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
602 extbits = 5;
603 extu = 1;
604 break;
605 case '>':
606 nbits = 3;
607 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
608 extbits = 5;
609 extu = 1;
610 break;
611 case '[':
612 nbits = 3;
613 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
614 extbits = 6;
615 extu = 1;
616 break;
617 case ']':
618 nbits = 3;
619 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
620 extbits = 6;
621 extu = 1;
622 break;
623 case '4':
624 nbits = 4;
625 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
626 signedp = 1;
627 extbits = 15;
628 break;
629 case '5':
630 nbits = 5;
631 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
632 info->insn_type = dis_dref;
633 info->data_size = 1;
8d67dc30
ILT
634 break;
635 case 'H':
636 nbits = 5;
637 shift = 1;
638 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
639 info->insn_type = dis_dref;
640 info->data_size = 2;
8d67dc30
ILT
641 break;
642 case 'W':
643 nbits = 5;
644 shift = 2;
645 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
646 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
647 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
648 {
649 info->insn_type = dis_dref;
650 info->data_size = 4;
651 }
8d67dc30
ILT
652 break;
653 case 'D':
654 nbits = 5;
655 shift = 3;
656 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
657 info->insn_type = dis_dref;
658 info->data_size = 8;
8d67dc30
ILT
659 break;
660 case 'j':
661 nbits = 5;
662 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
663 signedp = 1;
664 break;
665 case '6':
666 nbits = 6;
667 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
668 break;
669 case '8':
670 nbits = 8;
671 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
672 break;
673 case 'V':
674 nbits = 8;
675 shift = 2;
676 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
677 /* FIXME: This might be lw, or it might be addiu to $sp or
678 $pc. We assume it's load. */
679 info->insn_type = dis_dref;
680 info->data_size = 4;
8d67dc30
ILT
681 break;
682 case 'C':
683 nbits = 8;
684 shift = 3;
685 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
686 info->insn_type = dis_dref;
687 info->data_size = 8;
8d67dc30
ILT
688 break;
689 case 'U':
690 nbits = 8;
691 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
692 extu = 1;
693 break;
694 case 'k':
695 nbits = 8;
696 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
697 signedp = 1;
698 break;
699 case 'K':
700 nbits = 8;
701 shift = 3;
702 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
703 signedp = 1;
704 break;
705 case 'p':
706 nbits = 8;
707 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
708 signedp = 1;
709 pcrel = 1;
710 branch = 1;
20d43018 711 info->insn_type = dis_condbranch;
8d67dc30
ILT
712 break;
713 case 'q':
714 nbits = 11;
715 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
716 signedp = 1;
717 pcrel = 1;
718 branch = 1;
20d43018 719 info->insn_type = dis_branch;
8d67dc30
ILT
720 break;
721 case 'A':
722 nbits = 8;
723 shift = 2;
724 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
725 pcrel = 1;
20d43018
ILT
726 /* FIXME: This can be lw or la. We assume it is lw. */
727 info->insn_type = dis_dref;
728 info->data_size = 4;
8d67dc30
ILT
729 break;
730 case 'B':
731 nbits = 5;
732 shift = 3;
733 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
734 pcrel = 1;
20d43018
ILT
735 info->insn_type = dis_dref;
736 info->data_size = 8;
8d67dc30
ILT
737 break;
738 case 'E':
739 nbits = 5;
740 shift = 2;
741 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
742 pcrel = 1;
743 break;
744 default:
745 abort ();
746 }
747
748 if (! use_extend)
749 {
750 if (signedp && immed >= (1 << (nbits - 1)))
751 immed -= 1 << nbits;
752 immed <<= shift;
753 if ((type == '<' || type == '>' || type == '[' || type == '[')
754 && immed == 0)
755 immed = 8;
756 }
757 else
758 {
759 if (extbits == 16)
760 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
761 else if (extbits == 15)
762 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
763 else
764 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
765 immed &= (1 << extbits) - 1;
766 if (! extu && immed >= (1 << (extbits - 1)))
767 immed -= 1 << extbits;
768 }
769
770 if (! pcrel)
771 (*info->fprintf_func) (info->stream, "%d", immed);
772 else
773 {
c4f19df2 774 bfd_vma baseaddr;
8d67dc30
ILT
775 bfd_vma val;
776
777 if (branch)
c4f19df2
ILT
778 {
779 immed *= 2;
780 baseaddr = memaddr + 2;
781 }
782 else if (use_extend)
783 baseaddr = memaddr;
784 else
785 {
786 int status;
787 bfd_byte buffer[2];
788
789 baseaddr = memaddr;
790
791 /* If this instruction is in the delay slot of a jr
792 instruction, the base address is the address of the
793 jr instruction. If it is in the delay slot of jalr
794 instruction, the base address is the address of the
795 jalr instruction. This test is unreliable: we have
796 no way of knowing whether the previous word is
797 instruction or data. */
798 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
799 info);
800 if (status == 0
801 && (((info->endian == BFD_ENDIAN_BIG
802 ? bfd_getb16 (buffer)
803 : bfd_getl16 (buffer))
804 & 0xf800) == 0x1800))
805 baseaddr = memaddr - 4;
806 else
807 {
808 status = (*info->read_memory_func) (memaddr - 2, buffer,
809 2, info);
810 if (status == 0
811 && (((info->endian == BFD_ENDIAN_BIG
812 ? bfd_getb16 (buffer)
813 : bfd_getl16 (buffer))
814 & 0xf81f) == 0xe800))
815 baseaddr = memaddr - 2;
816 }
817 }
818 val = (baseaddr & ~ ((1 << shift) - 1)) + immed;
8d67dc30 819 (*info->print_address_func) (val, info);
20d43018 820 info->target = val;
8d67dc30
ILT
821 }
822 }
823 break;
824
825 case 'a':
826 if (! use_extend)
827 extend = 0;
828 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
829 (*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
20d43018
ILT
830 info->insn_type = dis_jsr;
831 info->target = (memaddr & 0xf0000000) | l;
832 info->branch_delay_insns = 1;
8d67dc30
ILT
833 break;
834
835 case 'l':
836 case 'L':
837 {
838 int need_comma, amask, smask;
839
840 need_comma = 0;
841
842 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
843
844 amask = (l >> 3) & 7;
0d52464c
ILT
845
846 if (amask > 0 && amask < 5)
8d67dc30 847 {
0d52464c 848 (*info->fprintf_func) (info->stream, "$%s", reg_names[4]);
8d67dc30 849 if (amask > 1)
0d52464c 850 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
851 reg_names[amask + 3]);
852 need_comma = 1;
853 }
854
855 smask = (l >> 1) & 3;
856 if (smask == 3)
857 {
858 (*info->fprintf_func) (info->stream, "%s??",
859 need_comma ? "," : "");
860 need_comma = 1;
861 }
862 else if (smask > 0)
863 {
0d52464c 864 (*info->fprintf_func) (info->stream, "%s$%s",
8d67dc30
ILT
865 need_comma ? "," : "",
866 reg_names[16]);
867 if (smask > 1)
0d52464c 868 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
869 reg_names[smask + 15]);
870 need_comma = 1;
871 }
872
873 if (l & 1)
0d52464c
ILT
874 {
875 (*info->fprintf_func) (info->stream, "%s$%s",
876 need_comma ? "," : "",
877 reg_names[31]);
878 need_comma = 1;
879 }
880
881 if (amask == 5 || amask == 6)
882 {
883 (*info->fprintf_func) (info->stream, "%s$f0",
884 need_comma ? "," : "");
885 if (amask == 6)
886 (*info->fprintf_func) (info->stream, "-$f1");
887 }
8d67dc30
ILT
888 }
889 break;
890
891 default:
892 abort ();
893 }
894}
This page took 0.198695 seconds and 4 git commands to generate.