745b6bfb61e4dfc4d8aa16ffa89198fd5bf266a3
[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 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
355 if (status != 0)
356 {
357 (*info->memory_error_func) (status, memaddr, info);
358 return -1;
359 }
360
361 length = 2;
362
363 if (info->endian == BFD_ENDIAN_BIG)
364 insn = bfd_getb16 (buffer);
365 else
366 insn = bfd_getl16 (buffer);
367
368 /* Handle the extend opcode specially. */
369 use_extend = false;
370 if ((insn & 0xf800) == 0xf000)
371 {
372 use_extend = true;
373 extend = insn & 0x7ff;
374
375 memaddr += 2;
376
377 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
378 if (status != 0)
379 {
380 (*info->fprintf_func) (info->stream, "extend 0x%x",
381 (unsigned int) extend);
382 (*info->memory_error_func) (status, memaddr, info);
383 return -1;
384 }
385
386 if (info->endian == BFD_ENDIAN_BIG)
387 insn = bfd_getb16 (buffer);
388 else
389 insn = bfd_getl16 (buffer);
390
391 /* Check for an extend opcode followed by an extend opcode. */
392 if ((insn & 0xf800) == 0xf000)
393 {
394 (*info->fprintf_func) (info->stream, "extend 0x%x",
395 (unsigned int) extend);
396 return length;
397 }
398
399 length += 2;
400 }
401
402 /* FIXME: Should probably use a hash table on the major opcode here. */
403
404 opend = mips16_opcodes + bfd_mips16_num_opcodes;
405 for (op = mips16_opcodes; op < opend; op++)
406 {
407 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
408 {
409 const char *s;
410
411 if (strchr (op->args, 'a') != NULL)
412 {
413 if (use_extend)
414 {
415 (*info->fprintf_func) (info->stream, "extend 0x%x",
416 (unsigned int) extend);
417 return length - 2;
418 }
419
420 use_extend = false;
421
422 memaddr += 2;
423
424 status = (*info->read_memory_func) (memaddr, buffer, 2,
425 info);
426 if (status == 0)
427 {
428 use_extend = true;
429 if (info->endian == BFD_ENDIAN_BIG)
430 extend = bfd_getb16 (buffer);
431 else
432 extend = bfd_getl16 (buffer);
433 length += 2;
434 }
435 }
436
437 (*info->fprintf_func) (info->stream, "%s", op->name);
438 if (op->args[0] != '\0')
439 (*info->fprintf_func) (info->stream, "\t");
440
441 for (s = op->args; *s != '\0'; s++)
442 {
443 if (*s == ','
444 && s[1] == 'w'
445 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
446 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
447 {
448 /* Skip the register and the comma. */
449 ++s;
450 continue;
451 }
452 if (*s == ','
453 && s[1] == 'v'
454 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
455 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
456 {
457 /* Skip the register and the comma. */
458 ++s;
459 continue;
460 }
461 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
462 info);
463 }
464
465 return length;
466 }
467 }
468
469 if (use_extend)
470 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
471 (*info->fprintf_func) (info->stream, "0x%x", insn);
472
473 return length;
474 }
475
476 /* Disassemble an operand for a mips16 instruction. */
477
478 static void
479 print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
480 int type;
481 const struct mips_opcode *op;
482 int l;
483 boolean use_extend;
484 int extend;
485 bfd_vma memaddr;
486 struct disassemble_info *info;
487 {
488 switch (type)
489 {
490 case ',':
491 case '(':
492 case ')':
493 (*info->fprintf_func) (info->stream, "%c", type);
494 break;
495
496 case 'y':
497 case 'w':
498 (*info->fprintf_func) (info->stream, "$%s",
499 mips16_reg_names[((l >> MIPS16OP_SH_RY)
500 & MIPS16OP_MASK_RY)]);
501 break;
502
503 case 'x':
504 case 'v':
505 (*info->fprintf_func) (info->stream, "$%s",
506 mips16_reg_names[((l >> MIPS16OP_SH_RX)
507 & MIPS16OP_MASK_RX)]);
508 break;
509
510 case 'z':
511 (*info->fprintf_func) (info->stream, "$%s",
512 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
513 & MIPS16OP_MASK_RZ)]);
514 break;
515
516 case 'Z':
517 (*info->fprintf_func) (info->stream, "$%s",
518 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
519 & MIPS16OP_MASK_MOVE32Z)]);
520 break;
521
522 case '0':
523 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
524 break;
525
526 case 'S':
527 (*info->fprintf_func) (info->stream, "$%s", reg_names[29]);
528 break;
529
530 case 'P':
531 (*info->fprintf_func) (info->stream, "$pc");
532 break;
533
534 case 'R':
535 (*info->fprintf_func) (info->stream, "$%s", reg_names[31]);
536 break;
537
538 case 'X':
539 (*info->fprintf_func) (info->stream, "$%s",
540 reg_names[((l >> MIPS16OP_SH_REGR32)
541 & MIPS16OP_MASK_REGR32)]);
542 break;
543
544 case 'Y':
545 (*info->fprintf_func) (info->stream, "$%s",
546 reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
547 break;
548
549 case '<':
550 case '>':
551 case '[':
552 case ']':
553 case '4':
554 case '5':
555 case 'H':
556 case 'W':
557 case 'D':
558 case 'j':
559 case '6':
560 case '8':
561 case 'V':
562 case 'C':
563 case 'U':
564 case 'k':
565 case 'K':
566 case 'p':
567 case 'q':
568 case 'A':
569 case 'B':
570 case 'E':
571 {
572 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
573
574 shift = 0;
575 signedp = 0;
576 extbits = 16;
577 pcrel = 0;
578 extu = 0;
579 branch = 0;
580 switch (type)
581 {
582 case '<':
583 nbits = 3;
584 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
585 extbits = 5;
586 extu = 1;
587 break;
588 case '>':
589 nbits = 3;
590 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
591 extbits = 5;
592 extu = 1;
593 break;
594 case '[':
595 nbits = 3;
596 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
597 extbits = 6;
598 extu = 1;
599 break;
600 case ']':
601 nbits = 3;
602 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
603 extbits = 6;
604 extu = 1;
605 break;
606 case '4':
607 nbits = 4;
608 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
609 signedp = 1;
610 extbits = 15;
611 break;
612 case '5':
613 nbits = 5;
614 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
615 break;
616 case 'H':
617 nbits = 5;
618 shift = 1;
619 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
620 break;
621 case 'W':
622 nbits = 5;
623 shift = 2;
624 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
625 break;
626 case 'D':
627 nbits = 5;
628 shift = 3;
629 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
630 break;
631 case 'j':
632 nbits = 5;
633 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
634 signedp = 1;
635 break;
636 case '6':
637 nbits = 6;
638 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
639 break;
640 case '8':
641 nbits = 8;
642 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
643 break;
644 case 'V':
645 nbits = 8;
646 shift = 2;
647 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
648 break;
649 case 'C':
650 nbits = 8;
651 shift = 3;
652 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
653 break;
654 case 'U':
655 nbits = 8;
656 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
657 extu = 1;
658 break;
659 case 'k':
660 nbits = 8;
661 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
662 signedp = 1;
663 break;
664 case 'K':
665 nbits = 8;
666 shift = 3;
667 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
668 signedp = 1;
669 break;
670 case 'p':
671 nbits = 8;
672 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
673 signedp = 1;
674 pcrel = 1;
675 branch = 1;
676 break;
677 case 'q':
678 nbits = 11;
679 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
680 signedp = 1;
681 pcrel = 1;
682 branch = 1;
683 break;
684 case 'A':
685 nbits = 8;
686 shift = 2;
687 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
688 pcrel = 1;
689 break;
690 case 'B':
691 nbits = 5;
692 shift = 3;
693 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
694 pcrel = 1;
695 break;
696 case 'E':
697 nbits = 5;
698 shift = 2;
699 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
700 pcrel = 1;
701 break;
702 default:
703 abort ();
704 }
705
706 if (! use_extend)
707 {
708 if (signedp && immed >= (1 << (nbits - 1)))
709 immed -= 1 << nbits;
710 immed <<= shift;
711 if ((type == '<' || type == '>' || type == '[' || type == '[')
712 && immed == 0)
713 immed = 8;
714 }
715 else
716 {
717 if (extbits == 16)
718 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
719 else if (extbits == 15)
720 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
721 else
722 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
723 immed &= (1 << extbits) - 1;
724 if (! extu && immed >= (1 << (extbits - 1)))
725 immed -= 1 << extbits;
726 }
727
728 if (! pcrel)
729 (*info->fprintf_func) (info->stream, "%d", immed);
730 else
731 {
732 bfd_vma baseaddr;
733 bfd_vma val;
734
735 if (branch)
736 {
737 immed *= 2;
738 baseaddr = memaddr + 2;
739 }
740 else if (use_extend)
741 baseaddr = memaddr;
742 else
743 {
744 int status;
745 bfd_byte buffer[2];
746
747 baseaddr = memaddr;
748
749 /* If this instruction is in the delay slot of a jr
750 instruction, the base address is the address of the
751 jr instruction. If it is in the delay slot of jalr
752 instruction, the base address is the address of the
753 jalr instruction. This test is unreliable: we have
754 no way of knowing whether the previous word is
755 instruction or data. */
756 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
757 info);
758 if (status == 0
759 && (((info->endian == BFD_ENDIAN_BIG
760 ? bfd_getb16 (buffer)
761 : bfd_getl16 (buffer))
762 & 0xf800) == 0x1800))
763 baseaddr = memaddr - 4;
764 else
765 {
766 status = (*info->read_memory_func) (memaddr - 2, buffer,
767 2, info);
768 if (status == 0
769 && (((info->endian == BFD_ENDIAN_BIG
770 ? bfd_getb16 (buffer)
771 : bfd_getl16 (buffer))
772 & 0xf81f) == 0xe800))
773 baseaddr = memaddr - 2;
774 }
775 }
776 val = (baseaddr & ~ ((1 << shift) - 1)) + immed;
777 (*info->print_address_func) (val, info);
778 }
779 }
780 break;
781
782 case 'a':
783 if (! use_extend)
784 extend = 0;
785 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
786 (*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
787 break;
788
789 case 'l':
790 case 'L':
791 {
792 int need_comma, amask, smask;
793
794 need_comma = 0;
795
796 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
797
798 amask = (l >> 3) & 7;
799 if (amask == 5 || amask == 6)
800 {
801 (*info->fprintf_func) (info->stream, "??");
802 need_comma = 1;
803 }
804 else if (amask > 0 && amask < 7)
805 {
806 (*info->fprintf_func) (info->stream, "%s", reg_names[4]);
807 if (amask > 1)
808 (*info->fprintf_func) (info->stream, "-%s",
809 reg_names[amask + 3]);
810 need_comma = 1;
811 }
812
813 smask = (l >> 1) & 3;
814 if (smask == 3)
815 {
816 (*info->fprintf_func) (info->stream, "%s??",
817 need_comma ? "," : "");
818 need_comma = 1;
819 }
820 else if (smask > 0)
821 {
822 (*info->fprintf_func) (info->stream, "%s%s",
823 need_comma ? "," : "",
824 reg_names[16]);
825 if (smask > 1)
826 (*info->fprintf_func) (info->stream, "-%s",
827 reg_names[smask + 15]);
828 need_comma = 1;
829 }
830
831 if (l & 1)
832 (*info->fprintf_func) (info->stream, "%s%s",
833 need_comma ? "," : "",
834 reg_names[31]);
835 }
836 break;
837
838 default:
839 abort ();
840 }
841 }
This page took 0.087551 seconds and 4 git commands to generate.