]> Git Repo - binutils.git/blob - opcodes/mips-dis.c
* mips-dis.c (print_insn_mips16): Set insn_info information.
[binutils.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([email protected]).
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.074308 seconds and 4 git commands to generate.