Replace memory model with one from sim/common directory.
[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
2ea116f4
ILT
258 info->bytes_per_chunk = 4;
259 info->display_endian = info->endian;
260
30b1724c
ILT
261 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
262 if (op != NULL)
d0ba1cea 263 {
30b1724c
ILT
264 for (; op < &mips_opcodes[NUMOPCODES]; op++)
265 {
266 if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
267 {
268 register const char *d;
269
270 (*info->fprintf_func) (info->stream, "%s", op->name);
271
272 d = op->args;
8d67dc30 273 if (d != NULL && *d != '\0')
30b1724c 274 {
8d67dc30 275 (*info->fprintf_func) (info->stream, "\t");
30b1724c
ILT
276 for (; *d != '\0'; d++)
277 print_insn_arg (d, word, memaddr, info);
278 }
279
280 return 4;
281 }
282 }
d0ba1cea
ILT
283 }
284
30b1724c
ILT
285 /* Handle undefined instructions. */
286 (*info->fprintf_func) (info->stream, "0x%x", word);
d0ba1cea
ILT
287 return 4;
288}
5d0734a7
JK
289
290int
291print_insn_big_mips (memaddr, info)
292 bfd_vma memaddr;
293 struct disassemble_info *info;
294{
295 bfd_byte buffer[4];
8d67dc30
ILT
296 int status;
297
298 if (info->mach == 16
299 || (info->flavour == bfd_target_elf_flavour
300 && info->symbol != NULL
301 && (((elf_symbol_type *) info->symbol)->internal_elf_sym.st_other
302 == STO_MIPS16)))
303 return print_insn_mips16 (memaddr, info);
304
305 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 306 if (status == 0)
8d67dc30
ILT
307 return _print_insn_mips (memaddr, (unsigned long) bfd_getb32 (buffer),
308 info);
5d0734a7
JK
309 else
310 {
311 (*info->memory_error_func) (status, memaddr, info);
312 return -1;
313 }
314}
315
316int
317print_insn_little_mips (memaddr, info)
318 bfd_vma memaddr;
319 struct disassemble_info *info;
320{
321 bfd_byte buffer[4];
8d67dc30
ILT
322 int status;
323
324 if (info->mach == 16
325 || (info->flavour == bfd_target_elf_flavour
326 && info->symbol != NULL
327 && (((elf_symbol_type *) info->symbol)->internal_elf_sym.st_other
328 == STO_MIPS16)))
329 return print_insn_mips16 (memaddr, info);
330
331 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 332 if (status == 0)
8d67dc30
ILT
333 return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer),
334 info);
5d0734a7
JK
335 else
336 {
337 (*info->memory_error_func) (status, memaddr, info);
338 return -1;
339 }
340}
8d67dc30
ILT
341\f
342/* Disassemble mips16 instructions. */
343
344static int
345print_insn_mips16 (memaddr, info)
346 bfd_vma memaddr;
347 struct disassemble_info *info;
348{
349 int status;
350 bfd_byte buffer[2];
351 int length;
352 int insn;
353 boolean use_extend;
354 int extend;
355 const struct mips_opcode *op, *opend;
356
2ea116f4
ILT
357 info->bytes_per_chunk = 2;
358 info->display_endian = info->endian;
359
20d43018
ILT
360 info->insn_info_valid = 1;
361 info->branch_delay_insns = 0;
362 info->data_size = 0;
363 info->insn_type = dis_nonbranch;
364 info->target = 0;
365 info->target2 = 0;
366
8d67dc30
ILT
367 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
368 if (status != 0)
369 {
370 (*info->memory_error_func) (status, memaddr, info);
371 return -1;
372 }
373
374 length = 2;
375
376 if (info->endian == BFD_ENDIAN_BIG)
377 insn = bfd_getb16 (buffer);
378 else
379 insn = bfd_getl16 (buffer);
380
381 /* Handle the extend opcode specially. */
382 use_extend = false;
383 if ((insn & 0xf800) == 0xf000)
384 {
385 use_extend = true;
386 extend = insn & 0x7ff;
387
388 memaddr += 2;
389
390 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
391 if (status != 0)
392 {
393 (*info->fprintf_func) (info->stream, "extend 0x%x",
394 (unsigned int) extend);
395 (*info->memory_error_func) (status, memaddr, info);
396 return -1;
397 }
398
8d67dc30
ILT
399 if (info->endian == BFD_ENDIAN_BIG)
400 insn = bfd_getb16 (buffer);
401 else
402 insn = bfd_getl16 (buffer);
c4f19df2
ILT
403
404 /* Check for an extend opcode followed by an extend opcode. */
405 if ((insn & 0xf800) == 0xf000)
406 {
407 (*info->fprintf_func) (info->stream, "extend 0x%x",
408 (unsigned int) extend);
20d43018 409 info->insn_type = dis_noninsn;
c4f19df2
ILT
410 return length;
411 }
412
413 length += 2;
8d67dc30
ILT
414 }
415
416 /* FIXME: Should probably use a hash table on the major opcode here. */
417
418 opend = mips16_opcodes + bfd_mips16_num_opcodes;
419 for (op = mips16_opcodes; op < opend; op++)
420 {
421 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
422 {
423 const char *s;
424
425 if (strchr (op->args, 'a') != NULL)
426 {
427 if (use_extend)
c4f19df2
ILT
428 {
429 (*info->fprintf_func) (info->stream, "extend 0x%x",
430 (unsigned int) extend);
20d43018 431 info->insn_type = dis_noninsn;
c4f19df2
ILT
432 return length - 2;
433 }
434
8d67dc30
ILT
435 use_extend = false;
436
437 memaddr += 2;
438
439 status = (*info->read_memory_func) (memaddr, buffer, 2,
440 info);
441 if (status == 0)
442 {
443 use_extend = true;
444 if (info->endian == BFD_ENDIAN_BIG)
445 extend = bfd_getb16 (buffer);
446 else
447 extend = bfd_getl16 (buffer);
448 length += 2;
449 }
450 }
451
c4f19df2
ILT
452 (*info->fprintf_func) (info->stream, "%s", op->name);
453 if (op->args[0] != '\0')
454 (*info->fprintf_func) (info->stream, "\t");
8d67dc30
ILT
455
456 for (s = op->args; *s != '\0'; s++)
457 {
458 if (*s == ','
459 && s[1] == 'w'
460 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
461 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
462 {
463 /* Skip the register and the comma. */
464 ++s;
465 continue;
466 }
467 if (*s == ','
468 && s[1] == 'v'
469 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
470 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
471 {
472 /* Skip the register and the comma. */
473 ++s;
474 continue;
475 }
476 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
477 info);
478 }
479
20d43018
ILT
480 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
481 {
482 info->branch_delay_insns = 1;
483 if (info->insn_type != dis_jsr)
484 info->insn_type = dis_branch;
485 }
486
8d67dc30
ILT
487 return length;
488 }
489 }
490
491 if (use_extend)
492 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
493 (*info->fprintf_func) (info->stream, "0x%x", insn);
20d43018 494 info->insn_type = dis_noninsn;
8d67dc30
ILT
495
496 return length;
497}
498
499/* Disassemble an operand for a mips16 instruction. */
500
501static void
502print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
503 int type;
504 const struct mips_opcode *op;
505 int l;
506 boolean use_extend;
507 int extend;
508 bfd_vma memaddr;
509 struct disassemble_info *info;
510{
511 switch (type)
512 {
513 case ',':
514 case '(':
515 case ')':
516 (*info->fprintf_func) (info->stream, "%c", type);
517 break;
518
519 case 'y':
520 case 'w':
521 (*info->fprintf_func) (info->stream, "$%s",
522 mips16_reg_names[((l >> MIPS16OP_SH_RY)
523 & MIPS16OP_MASK_RY)]);
524 break;
525
526 case 'x':
527 case 'v':
528 (*info->fprintf_func) (info->stream, "$%s",
529 mips16_reg_names[((l >> MIPS16OP_SH_RX)
530 & MIPS16OP_MASK_RX)]);
531 break;
532
533 case 'z':
534 (*info->fprintf_func) (info->stream, "$%s",
535 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
536 & MIPS16OP_MASK_RZ)]);
537 break;
538
539 case 'Z':
540 (*info->fprintf_func) (info->stream, "$%s",
541 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
542 & MIPS16OP_MASK_MOVE32Z)]);
543 break;
544
545 case '0':
546 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
547 break;
548
549 case 'S':
550 (*info->fprintf_func) (info->stream, "$%s", reg_names[29]);
551 break;
552
553 case 'P':
554 (*info->fprintf_func) (info->stream, "$pc");
555 break;
556
557 case 'R':
558 (*info->fprintf_func) (info->stream, "$%s", reg_names[31]);
559 break;
560
561 case 'X':
562 (*info->fprintf_func) (info->stream, "$%s",
563 reg_names[((l >> MIPS16OP_SH_REGR32)
564 & MIPS16OP_MASK_REGR32)]);
565 break;
566
567 case 'Y':
568 (*info->fprintf_func) (info->stream, "$%s",
569 reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
570 break;
571
572 case '<':
573 case '>':
574 case '[':
575 case ']':
576 case '4':
577 case '5':
578 case 'H':
579 case 'W':
580 case 'D':
581 case 'j':
582 case '6':
583 case '8':
584 case 'V':
585 case 'C':
586 case 'U':
587 case 'k':
588 case 'K':
589 case 'p':
590 case 'q':
591 case 'A':
592 case 'B':
593 case 'E':
594 {
595 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
596
597 shift = 0;
598 signedp = 0;
599 extbits = 16;
600 pcrel = 0;
601 extu = 0;
602 branch = 0;
603 switch (type)
604 {
605 case '<':
606 nbits = 3;
607 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
608 extbits = 5;
609 extu = 1;
610 break;
611 case '>':
612 nbits = 3;
613 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
614 extbits = 5;
615 extu = 1;
616 break;
617 case '[':
618 nbits = 3;
619 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
620 extbits = 6;
621 extu = 1;
622 break;
623 case ']':
624 nbits = 3;
625 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
626 extbits = 6;
627 extu = 1;
628 break;
629 case '4':
630 nbits = 4;
631 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
632 signedp = 1;
633 extbits = 15;
634 break;
635 case '5':
636 nbits = 5;
637 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
638 info->insn_type = dis_dref;
639 info->data_size = 1;
8d67dc30
ILT
640 break;
641 case 'H':
642 nbits = 5;
643 shift = 1;
644 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
645 info->insn_type = dis_dref;
646 info->data_size = 2;
8d67dc30
ILT
647 break;
648 case 'W':
649 nbits = 5;
650 shift = 2;
651 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
652 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
653 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
654 {
655 info->insn_type = dis_dref;
656 info->data_size = 4;
657 }
8d67dc30
ILT
658 break;
659 case 'D':
660 nbits = 5;
661 shift = 3;
662 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
663 info->insn_type = dis_dref;
664 info->data_size = 8;
8d67dc30
ILT
665 break;
666 case 'j':
667 nbits = 5;
668 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
669 signedp = 1;
670 break;
671 case '6':
672 nbits = 6;
673 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
674 break;
675 case '8':
676 nbits = 8;
677 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
678 break;
679 case 'V':
680 nbits = 8;
681 shift = 2;
682 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
683 /* FIXME: This might be lw, or it might be addiu to $sp or
684 $pc. We assume it's load. */
685 info->insn_type = dis_dref;
686 info->data_size = 4;
8d67dc30
ILT
687 break;
688 case 'C':
689 nbits = 8;
690 shift = 3;
691 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
692 info->insn_type = dis_dref;
693 info->data_size = 8;
8d67dc30
ILT
694 break;
695 case 'U':
696 nbits = 8;
697 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
698 extu = 1;
699 break;
700 case 'k':
701 nbits = 8;
702 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
703 signedp = 1;
704 break;
705 case 'K':
706 nbits = 8;
707 shift = 3;
708 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
709 signedp = 1;
710 break;
711 case 'p':
712 nbits = 8;
713 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
714 signedp = 1;
715 pcrel = 1;
716 branch = 1;
20d43018 717 info->insn_type = dis_condbranch;
8d67dc30
ILT
718 break;
719 case 'q':
720 nbits = 11;
721 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
722 signedp = 1;
723 pcrel = 1;
724 branch = 1;
20d43018 725 info->insn_type = dis_branch;
8d67dc30
ILT
726 break;
727 case 'A':
728 nbits = 8;
729 shift = 2;
730 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
731 pcrel = 1;
20d43018
ILT
732 /* FIXME: This can be lw or la. We assume it is lw. */
733 info->insn_type = dis_dref;
734 info->data_size = 4;
8d67dc30
ILT
735 break;
736 case 'B':
737 nbits = 5;
738 shift = 3;
739 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
740 pcrel = 1;
20d43018
ILT
741 info->insn_type = dis_dref;
742 info->data_size = 8;
8d67dc30
ILT
743 break;
744 case 'E':
745 nbits = 5;
746 shift = 2;
747 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
748 pcrel = 1;
749 break;
750 default:
751 abort ();
752 }
753
754 if (! use_extend)
755 {
756 if (signedp && immed >= (1 << (nbits - 1)))
757 immed -= 1 << nbits;
758 immed <<= shift;
759 if ((type == '<' || type == '>' || type == '[' || type == '[')
760 && immed == 0)
761 immed = 8;
762 }
763 else
764 {
765 if (extbits == 16)
766 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
767 else if (extbits == 15)
768 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
769 else
770 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
771 immed &= (1 << extbits) - 1;
772 if (! extu && immed >= (1 << (extbits - 1)))
773 immed -= 1 << extbits;
774 }
775
776 if (! pcrel)
777 (*info->fprintf_func) (info->stream, "%d", immed);
778 else
779 {
c4f19df2 780 bfd_vma baseaddr;
8d67dc30
ILT
781 bfd_vma val;
782
783 if (branch)
c4f19df2
ILT
784 {
785 immed *= 2;
786 baseaddr = memaddr + 2;
787 }
788 else if (use_extend)
789 baseaddr = memaddr;
790 else
791 {
792 int status;
793 bfd_byte buffer[2];
794
795 baseaddr = memaddr;
796
797 /* If this instruction is in the delay slot of a jr
798 instruction, the base address is the address of the
799 jr instruction. If it is in the delay slot of jalr
800 instruction, the base address is the address of the
801 jalr instruction. This test is unreliable: we have
802 no way of knowing whether the previous word is
803 instruction or data. */
804 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
805 info);
806 if (status == 0
807 && (((info->endian == BFD_ENDIAN_BIG
808 ? bfd_getb16 (buffer)
809 : bfd_getl16 (buffer))
810 & 0xf800) == 0x1800))
811 baseaddr = memaddr - 4;
812 else
813 {
814 status = (*info->read_memory_func) (memaddr - 2, buffer,
815 2, info);
816 if (status == 0
817 && (((info->endian == BFD_ENDIAN_BIG
818 ? bfd_getb16 (buffer)
819 : bfd_getl16 (buffer))
820 & 0xf81f) == 0xe800))
821 baseaddr = memaddr - 2;
822 }
823 }
824 val = (baseaddr & ~ ((1 << shift) - 1)) + immed;
8d67dc30 825 (*info->print_address_func) (val, info);
20d43018 826 info->target = val;
8d67dc30
ILT
827 }
828 }
829 break;
830
831 case 'a':
832 if (! use_extend)
833 extend = 0;
834 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
835 (*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
20d43018
ILT
836 info->insn_type = dis_jsr;
837 info->target = (memaddr & 0xf0000000) | l;
838 info->branch_delay_insns = 1;
8d67dc30
ILT
839 break;
840
841 case 'l':
842 case 'L':
843 {
844 int need_comma, amask, smask;
845
846 need_comma = 0;
847
848 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
849
850 amask = (l >> 3) & 7;
0d52464c
ILT
851
852 if (amask > 0 && amask < 5)
8d67dc30 853 {
0d52464c 854 (*info->fprintf_func) (info->stream, "$%s", reg_names[4]);
8d67dc30 855 if (amask > 1)
0d52464c 856 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
857 reg_names[amask + 3]);
858 need_comma = 1;
859 }
860
861 smask = (l >> 1) & 3;
862 if (smask == 3)
863 {
864 (*info->fprintf_func) (info->stream, "%s??",
865 need_comma ? "," : "");
866 need_comma = 1;
867 }
868 else if (smask > 0)
869 {
0d52464c 870 (*info->fprintf_func) (info->stream, "%s$%s",
8d67dc30
ILT
871 need_comma ? "," : "",
872 reg_names[16]);
873 if (smask > 1)
0d52464c 874 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
875 reg_names[smask + 15]);
876 need_comma = 1;
877 }
878
879 if (l & 1)
0d52464c
ILT
880 {
881 (*info->fprintf_func) (info->stream, "%s$%s",
882 need_comma ? "," : "",
883 reg_names[31]);
884 need_comma = 1;
885 }
886
887 if (amask == 5 || amask == 6)
888 {
889 (*info->fprintf_func) (info->stream, "%s$f0",
890 need_comma ? "," : "");
891 if (amask == 6)
892 (*info->fprintf_func) (info->stream, "-$f1");
893 }
8d67dc30
ILT
894 }
895 break;
896
897 default:
898 abort ();
899 }
900}
This page took 0.203037 seconds and 4 git commands to generate.