* mips-dis.c (print_insn_mips16): Set insn_info information.
[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, 1996 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 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
259 if (op != NULL)
260 {
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;
270 if (d != NULL && *d != '\0')
271 {
272 (*info->fprintf_func) (info->stream, "\t");
273 for (; *d != '\0'; d++)
274 print_insn_arg (d, word, memaddr, info);
275 }
276
277 return 4;
278 }
279 }
280 }
281
282 /* Handle undefined instructions. */
283 (*info->fprintf_func) (info->stream, "0x%x", word);
284 return 4;
285 }
286
287 int
288 print_insn_big_mips (memaddr, info)
289 bfd_vma memaddr;
290 struct disassemble_info *info;
291 {
292 bfd_byte buffer[4];
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);
303 if (status == 0)
304 return _print_insn_mips (memaddr, (unsigned long) bfd_getb32 (buffer),
305 info);
306 else
307 {
308 (*info->memory_error_func) (status, memaddr, info);
309 return -1;
310 }
311 }
312
313 int
314 print_insn_little_mips (memaddr, info)
315 bfd_vma memaddr;
316 struct disassemble_info *info;
317 {
318 bfd_byte buffer[4];
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);
329 if (status == 0)
330 return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer),
331 info);
332 else
333 {
334 (*info->memory_error_func) (status, memaddr, info);
335 return -1;
336 }
337 }
338 \f
339 /* Disassemble mips16 instructions. */
340
341 static int
342 print_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
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
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
393 if (info->endian == BFD_ENDIAN_BIG)
394 insn = bfd_getb16 (buffer);
395 else
396 insn = bfd_getl16 (buffer);
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);
403 info->insn_type = dis_noninsn;
404 return length;
405 }
406
407 length += 2;
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)
422 {
423 (*info->fprintf_func) (info->stream, "extend 0x%x",
424 (unsigned int) extend);
425 info->insn_type = dis_noninsn;
426 return length - 2;
427 }
428
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
446 (*info->fprintf_func) (info->stream, "%s", op->name);
447 if (op->args[0] != '\0')
448 (*info->fprintf_func) (info->stream, "\t");
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
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
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);
488 info->insn_type = dis_noninsn;
489
490 return length;
491 }
492
493 /* Disassemble an operand for a mips16 instruction. */
494
495 static void
496 print_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;
632 info->insn_type = dis_dref;
633 info->data_size = 1;
634 break;
635 case 'H':
636 nbits = 5;
637 shift = 1;
638 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
639 info->insn_type = dis_dref;
640 info->data_size = 2;
641 break;
642 case 'W':
643 nbits = 5;
644 shift = 2;
645 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
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 }
652 break;
653 case 'D':
654 nbits = 5;
655 shift = 3;
656 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
657 info->insn_type = dis_dref;
658 info->data_size = 8;
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;
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;
681 break;
682 case 'C':
683 nbits = 8;
684 shift = 3;
685 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
686 info->insn_type = dis_dref;
687 info->data_size = 8;
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;
711 info->insn_type = dis_condbranch;
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;
719 info->insn_type = dis_branch;
720 break;
721 case 'A':
722 nbits = 8;
723 shift = 2;
724 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
725 pcrel = 1;
726 /* FIXME: This can be lw or la. We assume it is lw. */
727 info->insn_type = dis_dref;
728 info->data_size = 4;
729 break;
730 case 'B':
731 nbits = 5;
732 shift = 3;
733 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
734 pcrel = 1;
735 info->insn_type = dis_dref;
736 info->data_size = 8;
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 {
774 bfd_vma baseaddr;
775 bfd_vma val;
776
777 if (branch)
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;
819 (*info->print_address_func) (val, info);
820 info->target = val;
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);
830 info->insn_type = dis_jsr;
831 info->target = (memaddr & 0xf0000000) | l;
832 info->branch_delay_insns = 1;
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;
845 if (amask == 5 || amask == 6)
846 {
847 (*info->fprintf_func) (info->stream, "??");
848 need_comma = 1;
849 }
850 else if (amask > 0 && amask < 7)
851 {
852 (*info->fprintf_func) (info->stream, "%s", reg_names[4]);
853 if (amask > 1)
854 (*info->fprintf_func) (info->stream, "-%s",
855 reg_names[amask + 3]);
856 need_comma = 1;
857 }
858
859 smask = (l >> 1) & 3;
860 if (smask == 3)
861 {
862 (*info->fprintf_func) (info->stream, "%s??",
863 need_comma ? "," : "");
864 need_comma = 1;
865 }
866 else if (smask > 0)
867 {
868 (*info->fprintf_func) (info->stream, "%s%s",
869 need_comma ? "," : "",
870 reg_names[16]);
871 if (smask > 1)
872 (*info->fprintf_func) (info->stream, "-%s",
873 reg_names[smask + 15]);
874 need_comma = 1;
875 }
876
877 if (l & 1)
878 (*info->fprintf_func) (info->stream, "%s%s",
879 need_comma ? "," : "",
880 reg_names[31]);
881 }
882 break;
883
884 default:
885 abort ();
886 }
887 }
This page took 0.059926 seconds and 5 git commands to generate.