* NOTES.config (Implementation): as.h #define's "GAS" not "gas",
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
d0ba1cea 1/* Print mips instructions for GDB, the GNU debugger, or for objdump.
8d67dc30 2 Copyright 1989, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
d0ba1cea
ILT
3 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
4
8d67dc30 5This file is part of GDB, GAS, and the GNU binutils.
d0ba1cea
ILT
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
30b1724c 19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
d0ba1cea 20
5d0734a7 21#include <ansidecl.h>
d0ba1cea 22#include "sysdep.h"
5d0734a7 23#include "dis-asm.h"
d0ba1cea
ILT
24#include "opcode/mips.h"
25
8d67dc30
ILT
26/* FIXME: These are needed to figure out if this is a mips16 symbol or
27 not. It would be better to think of a cleaner way to do this. */
28#include "elf-bfd.h"
29#include "elf/mips.h"
30
31static int print_insn_mips16 PARAMS ((bfd_vma, struct disassemble_info *));
32static void print_mips16_insn_arg
33 PARAMS ((int, const struct mips_opcode *, int, boolean, int, bfd_vma,
34 struct disassemble_info *));
35
d0ba1cea
ILT
36/* Mips instructions are never longer than this many bytes. */
37#define MAXLEN 4
8d67dc30
ILT
38
39static void print_insn_arg PARAMS ((const char *, unsigned long, bfd_vma,
40 struct disassemble_info *));
41static int _print_insn_mips PARAMS ((bfd_vma, unsigned long int,
42 struct disassemble_info *));
43
d0ba1cea
ILT
44\f
45/* FIXME: This should be shared with gdb somehow. */
46#define REGISTER_NAMES \
47 { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
48 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
49 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
50 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
51 "sr", "lo", "hi", "bad", "cause","pc", \
52 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
53 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
54 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
55 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
56 "fsr", "fir", "fp", "inx", "rand", "tlblo","ctxt", "tlbhi",\
57 "epc", "prid"\
58 }
59
60static CONST char * CONST reg_names[] = REGISTER_NAMES;
8d67dc30
ILT
61
62/* The mips16 register names. */
63static const char * const mips16_reg_names[] =
64{
65 "s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3"
66};
d0ba1cea
ILT
67\f
68/* subroutine */
5d0734a7
JK
69static void
70print_insn_arg (d, l, pc, info)
547998d2 71 const char *d;
5d0734a7 72 register unsigned long int l;
d0ba1cea 73 bfd_vma pc;
5d0734a7 74 struct disassemble_info *info;
d0ba1cea 75{
fde326fb
ILT
76 int delta;
77
d0ba1cea
ILT
78 switch (*d)
79 {
80 case ',':
81 case '(':
82 case ')':
5d0734a7 83 (*info->fprintf_func) (info->stream, "%c", *d);
d0ba1cea
ILT
84 break;
85
86 case 's':
fde326fb
ILT
87 case 'b':
88 case 'r':
89 case 'v':
5d0734a7
JK
90 (*info->fprintf_func) (info->stream, "$%s",
91 reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
d0ba1cea
ILT
92 break;
93
94 case 't':
fde326fb 95 case 'w':
5d0734a7
JK
96 (*info->fprintf_func) (info->stream, "$%s",
97 reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
d0ba1cea
ILT
98 break;
99
100 case 'i':
fde326fb 101 case 'u':
30b1724c 102 (*info->fprintf_func) (info->stream, "0x%x",
5d0734a7 103 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
d0ba1cea
ILT
104 break;
105
106 case 'j': /* same as i, but sign-extended */
fde326fb
ILT
107 case 'o':
108 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
109 if (delta & 0x8000)
110 delta |= ~0xffff;
5d0734a7 111 (*info->fprintf_func) (info->stream, "%d",
fde326fb 112 delta);
d0ba1cea
ILT
113 break;
114
30b1724c
ILT
115 case 'h':
116 (*info->fprintf_func) (info->stream, "0x%x",
117 (unsigned int) ((l >> OP_SH_PREFX)
118 & OP_MASK_PREFX));
119 break;
120
121 case 'k':
122 (*info->fprintf_func) (info->stream, "0x%x",
123 (unsigned int) ((l >> OP_SH_CACHE)
124 & OP_MASK_CACHE));
125 break;
126
d0ba1cea 127 case 'a':
fde326fb
ILT
128 (*info->print_address_func)
129 (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
130 info);
d0ba1cea
ILT
131 break;
132
fde326fb
ILT
133 case 'p':
134 /* sign extend the displacement */
135 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
136 if (delta & 0x8000)
137 delta |= ~0xffff;
138 (*info->print_address_func)
139 ((delta << 2) + pc + 4,
140 info);
d0ba1cea
ILT
141 break;
142
143 case 'd':
5d0734a7
JK
144 (*info->fprintf_func) (info->stream, "$%s",
145 reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
d0ba1cea
ILT
146 break;
147
547998d2
ILT
148 case 'z':
149 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
150 break;
151
fde326fb 152 case '<':
5d0734a7
JK
153 (*info->fprintf_func) (info->stream, "0x%x",
154 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
d0ba1cea
ILT
155 break;
156
fde326fb 157 case 'c':
5d0734a7
JK
158 (*info->fprintf_func) (info->stream, "0x%x",
159 (l >> OP_SH_CODE) & OP_MASK_CODE);
d0ba1cea
ILT
160 break;
161
fde326fb
ILT
162 case 'C':
163 (*info->fprintf_func) (info->stream, "0x%x",
164 (l >> OP_SH_COPZ) & OP_MASK_COPZ);
165 break;
166
167 case 'B':
168 (*info->fprintf_func) (info->stream, "0x%x",
169 (l >> OP_SH_SYSCALL) & OP_MASK_SYSCALL);
170 break;
171
d0ba1cea 172 case 'S':
fde326fb 173 case 'V':
5d0734a7
JK
174 (*info->fprintf_func) (info->stream, "$f%d",
175 (l >> OP_SH_FS) & OP_MASK_FS);
d0ba1cea
ILT
176 break;
177
178 case 'T':
fde326fb 179 case 'W':
5d0734a7
JK
180 (*info->fprintf_func) (info->stream, "$f%d",
181 (l >> OP_SH_FT) & OP_MASK_FT);
d0ba1cea
ILT
182 break;
183
184 case 'D':
5d0734a7
JK
185 (*info->fprintf_func) (info->stream, "$f%d",
186 (l >> OP_SH_FD) & OP_MASK_FD);
d0ba1cea
ILT
187 break;
188
30b1724c
ILT
189 case 'R':
190 (*info->fprintf_func) (info->stream, "$f%d",
191 (l >> OP_SH_FR) & OP_MASK_FR);
192 break;
193
fde326fb
ILT
194 case 'E':
195 (*info->fprintf_func) (info->stream, "$%d",
196 (l >> OP_SH_RT) & OP_MASK_RT);
197 break;
198
199 case 'G':
200 (*info->fprintf_func) (info->stream, "$%d",
201 (l >> OP_SH_RD) & OP_MASK_RD);
202 break;
203
30b1724c
ILT
204 case 'N':
205 (*info->fprintf_func) (info->stream, "$fcc%d",
206 (l >> OP_SH_BCC) & OP_MASK_BCC);
207 break;
208
209 case 'M':
210 (*info->fprintf_func) (info->stream, "$fcc%d",
211 (l >> OP_SH_CCC) & OP_MASK_CCC);
212 break;
213
d0ba1cea 214 default:
5d0734a7
JK
215 (*info->fprintf_func) (info->stream,
216 "# internal error, undefined modifier(%c)", *d);
d0ba1cea
ILT
217 break;
218 }
219}
220\f
221/* Print the mips instruction at address MEMADDR in debugged memory,
5d0734a7 222 on using INFO. Returns length of the instruction, in bytes, which is
d0ba1cea
ILT
223 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
224 this is little-endian code. */
225
30b1724c 226static int
5d0734a7 227_print_insn_mips (memaddr, word, info)
d0ba1cea 228 bfd_vma memaddr;
5d0734a7 229 unsigned long int word;
8d67dc30 230 struct disassemble_info *info;
d0ba1cea 231{
30b1724c
ILT
232 register const struct mips_opcode *op;
233 static boolean init = 0;
234 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
d0ba1cea 235
30b1724c
ILT
236 /* Build a hash table to shorten the search time. */
237 if (! init)
d0ba1cea 238 {
30b1724c
ILT
239 unsigned int i;
240
241 for (i = 0; i <= OP_MASK_OP; i++)
fde326fb 242 {
30b1724c
ILT
243 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
244 {
245 if (op->pinfo == INSN_MACRO)
246 continue;
247 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
248 {
249 mips_hash[i] = op;
250 break;
251 }
252 }
253 }
254
255 init = 1;
d0ba1cea
ILT
256 }
257
30b1724c
ILT
258 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
259 if (op != NULL)
d0ba1cea 260 {
30b1724c
ILT
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;
8d67dc30 270 if (d != NULL && *d != '\0')
30b1724c 271 {
8d67dc30 272 (*info->fprintf_func) (info->stream, "\t");
30b1724c
ILT
273 for (; *d != '\0'; d++)
274 print_insn_arg (d, word, memaddr, info);
275 }
276
277 return 4;
278 }
279 }
d0ba1cea
ILT
280 }
281
30b1724c
ILT
282 /* Handle undefined instructions. */
283 (*info->fprintf_func) (info->stream, "0x%x", word);
d0ba1cea
ILT
284 return 4;
285}
5d0734a7
JK
286
287int
288print_insn_big_mips (memaddr, info)
289 bfd_vma memaddr;
290 struct disassemble_info *info;
291{
292 bfd_byte buffer[4];
8d67dc30
ILT
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);
5d0734a7 303 if (status == 0)
8d67dc30
ILT
304 return _print_insn_mips (memaddr, (unsigned long) bfd_getb32 (buffer),
305 info);
5d0734a7
JK
306 else
307 {
308 (*info->memory_error_func) (status, memaddr, info);
309 return -1;
310 }
311}
312
313int
314print_insn_little_mips (memaddr, info)
315 bfd_vma memaddr;
316 struct disassemble_info *info;
317{
318 bfd_byte buffer[4];
8d67dc30
ILT
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);
5d0734a7 329 if (status == 0)
8d67dc30
ILT
330 return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer),
331 info);
5d0734a7
JK
332 else
333 {
334 (*info->memory_error_func) (status, memaddr, info);
335 return -1;
336 }
337}
8d67dc30
ILT
338\f
339/* Disassemble mips16 instructions. */
340
341static int
342print_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 length += 2;
387
388 if (info->endian == BFD_ENDIAN_BIG)
389 insn = bfd_getb16 (buffer);
390 else
391 insn = bfd_getl16 (buffer);
392 }
393
394 /* FIXME: Should probably use a hash table on the major opcode here. */
395
396 opend = mips16_opcodes + bfd_mips16_num_opcodes;
397 for (op = mips16_opcodes; op < opend; op++)
398 {
399 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
400 {
401 const char *s;
402
403 if (strchr (op->args, 'a') != NULL)
404 {
405 if (use_extend)
406 (*info->fprintf_func) (info->stream, "extend 0x%x",
407 (unsigned int) extend);
408 use_extend = false;
409
410 memaddr += 2;
411
412 status = (*info->read_memory_func) (memaddr, buffer, 2,
413 info);
414 if (status == 0)
415 {
416 use_extend = true;
417 if (info->endian == BFD_ENDIAN_BIG)
418 extend = bfd_getb16 (buffer);
419 else
420 extend = bfd_getl16 (buffer);
421 length += 2;
422 }
423 }
424
425 (*info->fprintf_func) (info->stream, "%s ", op->name);
426
427 for (s = op->args; *s != '\0'; s++)
428 {
429 if (*s == ','
430 && s[1] == 'w'
431 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
432 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
433 {
434 /* Skip the register and the comma. */
435 ++s;
436 continue;
437 }
438 if (*s == ','
439 && s[1] == 'v'
440 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
441 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
442 {
443 /* Skip the register and the comma. */
444 ++s;
445 continue;
446 }
447 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
448 info);
449 }
450
451 return length;
452 }
453 }
454
455 if (use_extend)
456 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
457 (*info->fprintf_func) (info->stream, "0x%x", insn);
458
459 return length;
460}
461
462/* Disassemble an operand for a mips16 instruction. */
463
464static void
465print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
466 int type;
467 const struct mips_opcode *op;
468 int l;
469 boolean use_extend;
470 int extend;
471 bfd_vma memaddr;
472 struct disassemble_info *info;
473{
474 switch (type)
475 {
476 case ',':
477 case '(':
478 case ')':
479 (*info->fprintf_func) (info->stream, "%c", type);
480 break;
481
482 case 'y':
483 case 'w':
484 (*info->fprintf_func) (info->stream, "$%s",
485 mips16_reg_names[((l >> MIPS16OP_SH_RY)
486 & MIPS16OP_MASK_RY)]);
487 break;
488
489 case 'x':
490 case 'v':
491 (*info->fprintf_func) (info->stream, "$%s",
492 mips16_reg_names[((l >> MIPS16OP_SH_RX)
493 & MIPS16OP_MASK_RX)]);
494 break;
495
496 case 'z':
497 (*info->fprintf_func) (info->stream, "$%s",
498 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
499 & MIPS16OP_MASK_RZ)]);
500 break;
501
502 case 'Z':
503 (*info->fprintf_func) (info->stream, "$%s",
504 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
505 & MIPS16OP_MASK_MOVE32Z)]);
506 break;
507
508 case '0':
509 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
510 break;
511
512 case 'S':
513 (*info->fprintf_func) (info->stream, "$%s", reg_names[29]);
514 break;
515
516 case 'P':
517 (*info->fprintf_func) (info->stream, "$pc");
518 break;
519
520 case 'R':
521 (*info->fprintf_func) (info->stream, "$%s", reg_names[31]);
522 break;
523
524 case 'X':
525 (*info->fprintf_func) (info->stream, "$%s",
526 reg_names[((l >> MIPS16OP_SH_REGR32)
527 & MIPS16OP_MASK_REGR32)]);
528 break;
529
530 case 'Y':
531 (*info->fprintf_func) (info->stream, "$%s",
532 reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
533 break;
534
535 case '<':
536 case '>':
537 case '[':
538 case ']':
539 case '4':
540 case '5':
541 case 'H':
542 case 'W':
543 case 'D':
544 case 'j':
545 case '6':
546 case '8':
547 case 'V':
548 case 'C':
549 case 'U':
550 case 'k':
551 case 'K':
552 case 'p':
553 case 'q':
554 case 'A':
555 case 'B':
556 case 'E':
557 {
558 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
559
560 shift = 0;
561 signedp = 0;
562 extbits = 16;
563 pcrel = 0;
564 extu = 0;
565 branch = 0;
566 switch (type)
567 {
568 case '<':
569 nbits = 3;
570 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
571 extbits = 5;
572 extu = 1;
573 break;
574 case '>':
575 nbits = 3;
576 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
577 extbits = 5;
578 extu = 1;
579 break;
580 case '[':
581 nbits = 3;
582 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
583 extbits = 6;
584 extu = 1;
585 break;
586 case ']':
587 nbits = 3;
588 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
589 extbits = 6;
590 extu = 1;
591 break;
592 case '4':
593 nbits = 4;
594 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
595 signedp = 1;
596 extbits = 15;
597 break;
598 case '5':
599 nbits = 5;
600 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
601 break;
602 case 'H':
603 nbits = 5;
604 shift = 1;
605 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
606 break;
607 case 'W':
608 nbits = 5;
609 shift = 2;
610 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
611 break;
612 case 'D':
613 nbits = 5;
614 shift = 3;
615 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
616 break;
617 case 'j':
618 nbits = 5;
619 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
620 signedp = 1;
621 break;
622 case '6':
623 nbits = 6;
624 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
625 break;
626 case '8':
627 nbits = 8;
628 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
629 break;
630 case 'V':
631 nbits = 8;
632 shift = 2;
633 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
634 break;
635 case 'C':
636 nbits = 8;
637 shift = 3;
638 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
639 break;
640 case 'U':
641 nbits = 8;
642 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
643 extu = 1;
644 break;
645 case 'k':
646 nbits = 8;
647 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
648 signedp = 1;
649 break;
650 case 'K':
651 nbits = 8;
652 shift = 3;
653 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
654 signedp = 1;
655 break;
656 case 'p':
657 nbits = 8;
658 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
659 signedp = 1;
660 pcrel = 1;
661 branch = 1;
662 break;
663 case 'q':
664 nbits = 11;
665 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
666 signedp = 1;
667 pcrel = 1;
668 branch = 1;
669 break;
670 case 'A':
671 nbits = 8;
672 shift = 2;
673 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
674 pcrel = 1;
675 break;
676 case 'B':
677 nbits = 5;
678 shift = 3;
679 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
680 pcrel = 1;
681 break;
682 case 'E':
683 nbits = 5;
684 shift = 2;
685 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
686 pcrel = 1;
687 break;
688 default:
689 abort ();
690 }
691
692 if (! use_extend)
693 {
694 if (signedp && immed >= (1 << (nbits - 1)))
695 immed -= 1 << nbits;
696 immed <<= shift;
697 if ((type == '<' || type == '>' || type == '[' || type == '[')
698 && immed == 0)
699 immed = 8;
700 }
701 else
702 {
703 if (extbits == 16)
704 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
705 else if (extbits == 15)
706 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
707 else
708 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
709 immed &= (1 << extbits) - 1;
710 if (! extu && immed >= (1 << (extbits - 1)))
711 immed -= 1 << extbits;
712 }
713
714 if (! pcrel)
715 (*info->fprintf_func) (info->stream, "%d", immed);
716 else
717 {
718 bfd_vma val;
719
720 if (branch)
721 immed *= 2;
722 val = ((memaddr + 2) & ~ ((1 << shift) - 1)) + immed;
723 (*info->print_address_func) (val, info);
724 }
725 }
726 break;
727
728 case 'a':
729 if (! use_extend)
730 extend = 0;
731 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
732 (*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
733 break;
734
735 case 'l':
736 case 'L':
737 {
738 int need_comma, amask, smask;
739
740 need_comma = 0;
741
742 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
743
744 amask = (l >> 3) & 7;
745 if (amask == 5 || amask == 6)
746 {
747 (*info->fprintf_func) (info->stream, "??");
748 need_comma = 1;
749 }
750 else if (amask > 0 && amask < 7)
751 {
752 (*info->fprintf_func) (info->stream, "%s", reg_names[4]);
753 if (amask > 1)
754 (*info->fprintf_func) (info->stream, "-%s",
755 reg_names[amask + 3]);
756 need_comma = 1;
757 }
758
759 smask = (l >> 1) & 3;
760 if (smask == 3)
761 {
762 (*info->fprintf_func) (info->stream, "%s??",
763 need_comma ? "," : "");
764 need_comma = 1;
765 }
766 else if (smask > 0)
767 {
768 (*info->fprintf_func) (info->stream, "%s%s",
769 need_comma ? "," : "",
770 reg_names[16]);
771 if (smask > 1)
772 (*info->fprintf_func) (info->stream, "-%s",
773 reg_names[smask + 15]);
774 need_comma = 1;
775 }
776
777 if (l & 1)
778 (*info->fprintf_func) (info->stream, "%s%s",
779 need_comma ? "," : "",
780 reg_names[31]);
781 }
782 break;
783
784 default:
785 abort ();
786 }
787}
This page took 0.174816 seconds and 4 git commands to generate.