Fix MTSA opcode encoding.
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
1 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2 Copyright 1989, 91, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
3 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
4
5 This file is part of GDB, GAS, and the GNU binutils.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 #include <ansidecl.h>
22 #include "sysdep.h"
23 #include "dis-asm.h"
24 #include "opcode/mips.h"
25
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
31 static int print_insn_mips16 PARAMS ((bfd_vma, struct disassemble_info *));
32 static void print_mips16_insn_arg
33 PARAMS ((int, const struct mips_opcode *, int, boolean, int, bfd_vma,
34 struct disassemble_info *));
35
36 /* Mips instructions are never longer than this many bytes. */
37 #define MAXLEN 4
38
39 static void print_insn_arg PARAMS ((const char *, unsigned long, bfd_vma,
40 struct disassemble_info *));
41 static int _print_insn_mips PARAMS ((bfd_vma, unsigned long int,
42 struct disassemble_info *));
43
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
60 static CONST char * CONST reg_names[] = REGISTER_NAMES;
61
62 /* The mips16 register names. */
63 static const char * const mips16_reg_names[] =
64 {
65 "s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3"
66 };
67 \f
68 /* subroutine */
69 static void
70 print_insn_arg (d, l, pc, info)
71 const char *d;
72 register unsigned long int l;
73 bfd_vma pc;
74 struct disassemble_info *info;
75 {
76 int delta;
77
78 switch (*d)
79 {
80 case ',':
81 case '(':
82 case ')':
83 (*info->fprintf_func) (info->stream, "%c", *d);
84 break;
85
86 case 's':
87 case 'b':
88 case 'r':
89 case 'v':
90 (*info->fprintf_func) (info->stream, "$%s",
91 reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
92 break;
93
94 case 't':
95 case 'w':
96 (*info->fprintf_func) (info->stream, "$%s",
97 reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
98 break;
99
100 case 'i':
101 case 'u':
102 (*info->fprintf_func) (info->stream, "0x%x",
103 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
104 break;
105
106 case 'j': /* same as i, but sign-extended */
107 case 'o':
108 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
109 if (delta & 0x8000)
110 delta |= ~0xffff;
111 (*info->fprintf_func) (info->stream, "%d",
112 delta);
113 break;
114
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
127 case 'a':
128 (*info->print_address_func)
129 (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
130 info);
131 break;
132
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);
141 break;
142
143 case 'd':
144 (*info->fprintf_func) (info->stream, "$%s",
145 reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
146 break;
147
148 case 'z':
149 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
150 break;
151
152 case '<':
153 (*info->fprintf_func) (info->stream, "0x%x",
154 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
155 break;
156
157 case 'c':
158 (*info->fprintf_func) (info->stream, "0x%x",
159 (l >> OP_SH_CODE) & OP_MASK_CODE);
160 break;
161
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
172 case 'S':
173 case 'V':
174 (*info->fprintf_func) (info->stream, "$f%d",
175 (l >> OP_SH_FS) & OP_MASK_FS);
176 break;
177
178 case 'T':
179 case 'W':
180 (*info->fprintf_func) (info->stream, "$f%d",
181 (l >> OP_SH_FT) & OP_MASK_FT);
182 break;
183
184 case 'D':
185 (*info->fprintf_func) (info->stream, "$f%d",
186 (l >> OP_SH_FD) & OP_MASK_FD);
187 break;
188
189 case 'R':
190 (*info->fprintf_func) (info->stream, "$f%d",
191 (l >> OP_SH_FR) & OP_MASK_FR);
192 break;
193
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
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
214 default:
215 (*info->fprintf_func) (info->stream,
216 "# internal error, undefined modifier(%c)", *d);
217 break;
218 }
219 }
220 \f
221 /* Print the mips instruction at address MEMADDR in debugged memory,
222 on using INFO. Returns length of the instruction, in bytes, which is
223 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
224 this is little-endian code. */
225
226 static int
227 _print_insn_mips (memaddr, word, info)
228 bfd_vma memaddr;
229 unsigned long int word;
230 struct disassemble_info *info;
231 {
232 register const struct mips_opcode *op;
233 static boolean init = 0;
234 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
235
236 /* Build a hash table to shorten the search time. */
237 if (! init)
238 {
239 unsigned int i;
240
241 for (i = 0; i <= OP_MASK_OP; i++)
242 {
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;
256 }
257
258 info->bytes_per_chunk = 4;
259 info->display_endian = info->endian;
260
261 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
262 if (op != NULL)
263 {
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;
273 if (d != NULL && *d != '\0')
274 {
275 (*info->fprintf_func) (info->stream, "\t");
276 for (; *d != '\0'; d++)
277 print_insn_arg (d, word, memaddr, info);
278 }
279
280 return 4;
281 }
282 }
283 }
284
285 /* Handle undefined instructions. */
286 (*info->fprintf_func) (info->stream, "0x%x", word);
287 return 4;
288 }
289
290 int
291 print_insn_big_mips (memaddr, info)
292 bfd_vma memaddr;
293 struct disassemble_info *info;
294 {
295 bfd_byte buffer[4];
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);
306 if (status == 0)
307 return _print_insn_mips (memaddr, (unsigned long) bfd_getb32 (buffer),
308 info);
309 else
310 {
311 (*info->memory_error_func) (status, memaddr, info);
312 return -1;
313 }
314 }
315
316 int
317 print_insn_little_mips (memaddr, info)
318 bfd_vma memaddr;
319 struct disassemble_info *info;
320 {
321 bfd_byte buffer[4];
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);
332 if (status == 0)
333 return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer),
334 info);
335 else
336 {
337 (*info->memory_error_func) (status, memaddr, info);
338 return -1;
339 }
340 }
341 \f
342 /* Disassemble mips16 instructions. */
343
344 static int
345 print_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
357 info->bytes_per_chunk = 2;
358 info->display_endian = info->endian;
359
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
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
399 if (info->endian == BFD_ENDIAN_BIG)
400 insn = bfd_getb16 (buffer);
401 else
402 insn = bfd_getl16 (buffer);
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);
409 info->insn_type = dis_noninsn;
410 return length;
411 }
412
413 length += 2;
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)
428 {
429 (*info->fprintf_func) (info->stream, "extend 0x%x",
430 (unsigned int) extend);
431 info->insn_type = dis_noninsn;
432 return length - 2;
433 }
434
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
452 (*info->fprintf_func) (info->stream, "%s", op->name);
453 if (op->args[0] != '\0')
454 (*info->fprintf_func) (info->stream, "\t");
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
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
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);
494 info->insn_type = dis_noninsn;
495
496 return length;
497 }
498
499 /* Disassemble an operand for a mips16 instruction. */
500
501 static void
502 print_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;
638 info->insn_type = dis_dref;
639 info->data_size = 1;
640 break;
641 case 'H':
642 nbits = 5;
643 shift = 1;
644 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
645 info->insn_type = dis_dref;
646 info->data_size = 2;
647 break;
648 case 'W':
649 nbits = 5;
650 shift = 2;
651 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
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 }
658 break;
659 case 'D':
660 nbits = 5;
661 shift = 3;
662 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
663 info->insn_type = dis_dref;
664 info->data_size = 8;
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;
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;
687 break;
688 case 'C':
689 nbits = 8;
690 shift = 3;
691 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
692 info->insn_type = dis_dref;
693 info->data_size = 8;
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;
717 info->insn_type = dis_condbranch;
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;
725 info->insn_type = dis_branch;
726 break;
727 case 'A':
728 nbits = 8;
729 shift = 2;
730 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
731 pcrel = 1;
732 /* FIXME: This can be lw or la. We assume it is lw. */
733 info->insn_type = dis_dref;
734 info->data_size = 4;
735 break;
736 case 'B':
737 nbits = 5;
738 shift = 3;
739 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
740 pcrel = 1;
741 info->insn_type = dis_dref;
742 info->data_size = 8;
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 {
780 bfd_vma baseaddr;
781 bfd_vma val;
782
783 if (branch)
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;
825 (*info->print_address_func) (val, info);
826 info->target = val;
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);
836 info->insn_type = dis_jsr;
837 info->target = (memaddr & 0xf0000000) | l;
838 info->branch_delay_insns = 1;
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;
851
852 if (amask > 0 && amask < 5)
853 {
854 (*info->fprintf_func) (info->stream, "$%s", reg_names[4]);
855 if (amask > 1)
856 (*info->fprintf_func) (info->stream, "-$%s",
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 {
870 (*info->fprintf_func) (info->stream, "%s$%s",
871 need_comma ? "," : "",
872 reg_names[16]);
873 if (smask > 1)
874 (*info->fprintf_func) (info->stream, "-$%s",
875 reg_names[smask + 15]);
876 need_comma = 1;
877 }
878
879 if (l & 1)
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 }
894 }
895 break;
896
897 default:
898 abort ();
899 }
900 }
This page took 0.062266 seconds and 4 git commands to generate.