Wed Jan 28 16:41:19 1998 J.J. van der Heijden <J.J.vanderHeijden@student.utwente.nl>
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
d0ba1cea 1/* Print mips instructions for GDB, the GNU debugger, or for objdump.
0d52464c 2 Copyright 1989, 91, 92, 93, 94, 95, 96, 1997 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 ')':
83af2335
JL
83 /* start-sanitize-vr5400 */
84 case '[':
85 case ']':
86 /* end-sanitize-vr5400 */
5d0734a7 87 (*info->fprintf_func) (info->stream, "%c", *d);
d0ba1cea
ILT
88 break;
89
90 case 's':
fde326fb
ILT
91 case 'b':
92 case 'r':
93 case 'v':
5d0734a7
JK
94 (*info->fprintf_func) (info->stream, "$%s",
95 reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
d0ba1cea
ILT
96 break;
97
98 case 't':
fde326fb 99 case 'w':
5d0734a7
JK
100 (*info->fprintf_func) (info->stream, "$%s",
101 reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
d0ba1cea
ILT
102 break;
103
104 case 'i':
fde326fb 105 case 'u':
30b1724c 106 (*info->fprintf_func) (info->stream, "0x%x",
5d0734a7 107 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
d0ba1cea
ILT
108 break;
109
110 case 'j': /* same as i, but sign-extended */
fde326fb
ILT
111 case 'o':
112 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
113 if (delta & 0x8000)
114 delta |= ~0xffff;
5d0734a7 115 (*info->fprintf_func) (info->stream, "%d",
fde326fb 116 delta);
d0ba1cea
ILT
117 break;
118
30b1724c
ILT
119 case 'h':
120 (*info->fprintf_func) (info->stream, "0x%x",
121 (unsigned int) ((l >> OP_SH_PREFX)
122 & OP_MASK_PREFX));
123 break;
124
125 case 'k':
126 (*info->fprintf_func) (info->stream, "0x%x",
127 (unsigned int) ((l >> OP_SH_CACHE)
128 & OP_MASK_CACHE));
129 break;
130
d0ba1cea 131 case 'a':
fde326fb
ILT
132 (*info->print_address_func)
133 (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
134 info);
d0ba1cea
ILT
135 break;
136
fde326fb
ILT
137 case 'p':
138 /* sign extend the displacement */
139 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
140 if (delta & 0x8000)
141 delta |= ~0xffff;
142 (*info->print_address_func)
143 ((delta << 2) + pc + 4,
144 info);
d0ba1cea
ILT
145 break;
146
147 case 'd':
5d0734a7
JK
148 (*info->fprintf_func) (info->stream, "$%s",
149 reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
d0ba1cea
ILT
150 break;
151
547998d2
ILT
152 case 'z':
153 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
154 break;
155
fde326fb 156 case '<':
5d0734a7
JK
157 (*info->fprintf_func) (info->stream, "0x%x",
158 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
d0ba1cea
ILT
159 break;
160
fde326fb 161 case 'c':
5d0734a7
JK
162 (*info->fprintf_func) (info->stream, "0x%x",
163 (l >> OP_SH_CODE) & OP_MASK_CODE);
d0ba1cea
ILT
164 break;
165
fde326fb
ILT
166 case 'C':
167 (*info->fprintf_func) (info->stream, "0x%x",
168 (l >> OP_SH_COPZ) & OP_MASK_COPZ);
169 break;
170
171 case 'B':
172 (*info->fprintf_func) (info->stream, "0x%x",
173 (l >> OP_SH_SYSCALL) & OP_MASK_SYSCALL);
174 break;
175
d0ba1cea 176 case 'S':
fde326fb 177 case 'V':
5d0734a7
JK
178 (*info->fprintf_func) (info->stream, "$f%d",
179 (l >> OP_SH_FS) & OP_MASK_FS);
d0ba1cea
ILT
180 break;
181
182 case 'T':
fde326fb 183 case 'W':
5d0734a7
JK
184 (*info->fprintf_func) (info->stream, "$f%d",
185 (l >> OP_SH_FT) & OP_MASK_FT);
d0ba1cea
ILT
186 break;
187
188 case 'D':
5d0734a7
JK
189 (*info->fprintf_func) (info->stream, "$f%d",
190 (l >> OP_SH_FD) & OP_MASK_FD);
d0ba1cea
ILT
191 break;
192
30b1724c
ILT
193 case 'R':
194 (*info->fprintf_func) (info->stream, "$f%d",
195 (l >> OP_SH_FR) & OP_MASK_FR);
196 break;
197
fde326fb
ILT
198 case 'E':
199 (*info->fprintf_func) (info->stream, "$%d",
200 (l >> OP_SH_RT) & OP_MASK_RT);
201 break;
202
203 case 'G':
204 (*info->fprintf_func) (info->stream, "$%d",
205 (l >> OP_SH_RD) & OP_MASK_RD);
206 break;
207
30b1724c
ILT
208 case 'N':
209 (*info->fprintf_func) (info->stream, "$fcc%d",
210 (l >> OP_SH_BCC) & OP_MASK_BCC);
211 break;
212
213 case 'M':
214 (*info->fprintf_func) (info->stream, "$fcc%d",
215 (l >> OP_SH_CCC) & OP_MASK_CCC);
216 break;
217
83af2335
JL
218 case 'P':
219 (*info->fprintf_func) (info->stream, "$%d",
220 (l >> OP_SH_PERFREG) & OP_MASK_PERFREG);
221 break;
222
223 /* start-sanitize-vr5400 */
224 case 'e':
225 (*info->fprintf_func) (info->stream, "%d",
226 (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE);
227 break;
228
229 case '%':
230 (*info->fprintf_func) (info->stream, "%d",
231 (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN);
232 break;
233 /* end-sanitize-vr5400 */
234
d0ba1cea 235 default:
5d0734a7
JK
236 (*info->fprintf_func) (info->stream,
237 "# internal error, undefined modifier(%c)", *d);
d0ba1cea
ILT
238 break;
239 }
240}
241\f
242/* Print the mips instruction at address MEMADDR in debugged memory,
5d0734a7 243 on using INFO. Returns length of the instruction, in bytes, which is
d0ba1cea
ILT
244 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
245 this is little-endian code. */
246
30b1724c 247static int
5d0734a7 248_print_insn_mips (memaddr, word, info)
d0ba1cea 249 bfd_vma memaddr;
5d0734a7 250 unsigned long int word;
8d67dc30 251 struct disassemble_info *info;
d0ba1cea 252{
30b1724c 253 register const struct mips_opcode *op;
83af2335 254 int target_processor, mips_isa;
30b1724c
ILT
255 static boolean init = 0;
256 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
d0ba1cea 257
30b1724c
ILT
258 /* Build a hash table to shorten the search time. */
259 if (! init)
d0ba1cea 260 {
30b1724c
ILT
261 unsigned int i;
262
263 for (i = 0; i <= OP_MASK_OP; i++)
fde326fb 264 {
30b1724c
ILT
265 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
266 {
267 if (op->pinfo == INSN_MACRO)
268 continue;
269 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
270 {
271 mips_hash[i] = op;
272 break;
273 }
274 }
275 }
276
277 init = 1;
d0ba1cea
ILT
278 }
279
83af2335
JL
280 switch (info->mach)
281 {
282 /* start-sanitize-tx19 */
283 case bfd_mach_mips1900:
284 target_processor = 1900;
285 mips_isa = 1;
286 break;
287 /* end-sanitize-tx19 */
288 case bfd_mach_mips3000:
289 target_processor = 3000;
290 mips_isa = 1;
291 break;
292 case bfd_mach_mips3900:
293 target_processor = 3900;
294 mips_isa = 1;
295 break;
296 case bfd_mach_mips4000:
297 target_processor = 4000;
298 mips_isa = 3;
299 break;
300 case bfd_mach_mips4010:
301 target_processor = 4010;
302 mips_isa = 2;
303 break;
304 case bfd_mach_mips4100:
305 target_processor = 4100;
306 mips_isa = 3;
307 break;
308 case bfd_mach_mips4300:
309 target_processor = 4300;
310 mips_isa = 3;
311 break;
312 case bfd_mach_mips4400:
313 target_processor = 4400;
314 mips_isa = 3;
315 break;
316 case bfd_mach_mips4600:
317 target_processor = 4600;
318 mips_isa = 3;
319 break;
320 case bfd_mach_mips4650:
321 target_processor = 4650;
322 mips_isa = 3;
323 break;
324 /* start-sanitize-tx49 */
325 case bfd_mach_mips4900:
326 target_processor = 4900;
327 mips_isa = 3;
328 break;
329 /* end-sanitize-tx49 */
330 case bfd_mach_mips5000:
331 target_processor = 5000;
332 mips_isa = 4;
333 break;
334 /* start-sanitize-vr5400 */
335 case bfd_mach_mips5400:
336 target_processor = 5400;
337 mips_isa = 3;
338 break;
339 /* end-sanitize-vr5400 */
340 /* start-sanitize-r5900 */
341 case bfd_mach_mips5900:
342 target_processor = 5900;
343 mips_isa = 3;
344 break;
345 /* end-sanitize-r5900 */
346 case bfd_mach_mips6000:
347 target_processor = 6000;
348 mips_isa = 2;
349 break;
350 case bfd_mach_mips8000:
351 target_processor = 8000;
352 mips_isa = 4;
353 break;
354 case bfd_mach_mips10000:
355 target_processor = 10000;
356 mips_isa = 4;
357 break;
358 case bfd_mach_mips16:
359 target_processor = 16;
360 mips_isa = 3;
361 break;
362 default:
363 target_processor = 3000;
364 mips_isa = 3;
365 break;
366
367 }
368
2ea116f4
ILT
369 info->bytes_per_chunk = 4;
370 info->display_endian = info->endian;
371
30b1724c
ILT
372 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
373 if (op != NULL)
d0ba1cea 374 {
30b1724c
ILT
375 for (; op < &mips_opcodes[NUMOPCODES]; op++)
376 {
377 if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
378 {
379 register const char *d;
83af2335
JL
380 int insn_isa;
381
382 if ((op->membership & INSN_ISA) == INSN_ISA1)
383 insn_isa = 1;
384 else if ((op->membership & INSN_ISA) == INSN_ISA2)
385 insn_isa = 2;
386 else if ((op->membership & INSN_ISA) == INSN_ISA3)
387 insn_isa = 3;
388 else if ((op->membership & INSN_ISA) == INSN_ISA4)
389 insn_isa = 4;
390 else
391 insn_isa = 15;
392
393 if (insn_isa > mips_isa
394 && (target_processor == 4650
395 && op->membership & INSN_4650) == 0
396 && (target_processor == 4010
397 && op->membership & INSN_4010) == 0
398 && (target_processor == 4100
399 && op->membership & INSN_4100) == 0
400 /* start-sanitize-vr5400 */
401 && (target_processor == 5400
402 && op->membership & INSN_5400) == 0
403 /* end-santiize-vr5400 */
404 /* start-sanitize-r5900 */
405 && (target_processor == 5900
406 && op->membership & INSN_5900) == 0
407 /* end-sanitize-r5900 */
408 /* start-sanitize-tx49 */
409 && (target_processor == 4900
410 && op->membership & INSN_4900) == 0
411 /* end-sanitize-tx49 */
412 && (target_processor == 3900
413 && op->membership & INSN_3900) == 0)
414 continue;
30b1724c
ILT
415
416 (*info->fprintf_func) (info->stream, "%s", op->name);
417
418 d = op->args;
8d67dc30 419 if (d != NULL && *d != '\0')
30b1724c 420 {
8d67dc30 421 (*info->fprintf_func) (info->stream, "\t");
30b1724c
ILT
422 for (; *d != '\0'; d++)
423 print_insn_arg (d, word, memaddr, info);
424 }
425
426 return 4;
427 }
428 }
d0ba1cea
ILT
429 }
430
30b1724c
ILT
431 /* Handle undefined instructions. */
432 (*info->fprintf_func) (info->stream, "0x%x", word);
d0ba1cea
ILT
433 return 4;
434}
5d0734a7
JK
435
436int
437print_insn_big_mips (memaddr, info)
438 bfd_vma memaddr;
439 struct disassemble_info *info;
440{
441 bfd_byte buffer[4];
8d67dc30
ILT
442 int status;
443
444 if (info->mach == 16
445 || (info->flavour == bfd_target_elf_flavour
446 && info->symbol != NULL
447 && (((elf_symbol_type *) info->symbol)->internal_elf_sym.st_other
448 == STO_MIPS16)))
449 return print_insn_mips16 (memaddr, info);
450
451 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 452 if (status == 0)
8d67dc30
ILT
453 return _print_insn_mips (memaddr, (unsigned long) bfd_getb32 (buffer),
454 info);
5d0734a7
JK
455 else
456 {
457 (*info->memory_error_func) (status, memaddr, info);
458 return -1;
459 }
460}
461
462int
463print_insn_little_mips (memaddr, info)
464 bfd_vma memaddr;
465 struct disassemble_info *info;
466{
467 bfd_byte buffer[4];
8d67dc30
ILT
468 int status;
469
470 if (info->mach == 16
471 || (info->flavour == bfd_target_elf_flavour
472 && info->symbol != NULL
473 && (((elf_symbol_type *) info->symbol)->internal_elf_sym.st_other
474 == STO_MIPS16)))
475 return print_insn_mips16 (memaddr, info);
476
477 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 478 if (status == 0)
8d67dc30
ILT
479 return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer),
480 info);
5d0734a7
JK
481 else
482 {
483 (*info->memory_error_func) (status, memaddr, info);
484 return -1;
485 }
486}
8d67dc30
ILT
487\f
488/* Disassemble mips16 instructions. */
489
490static int
491print_insn_mips16 (memaddr, info)
492 bfd_vma memaddr;
493 struct disassemble_info *info;
494{
495 int status;
496 bfd_byte buffer[2];
497 int length;
498 int insn;
499 boolean use_extend;
500 int extend;
501 const struct mips_opcode *op, *opend;
502
2ea116f4
ILT
503 info->bytes_per_chunk = 2;
504 info->display_endian = info->endian;
505
20d43018
ILT
506 info->insn_info_valid = 1;
507 info->branch_delay_insns = 0;
508 info->data_size = 0;
509 info->insn_type = dis_nonbranch;
510 info->target = 0;
511 info->target2 = 0;
512
8d67dc30
ILT
513 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
514 if (status != 0)
515 {
516 (*info->memory_error_func) (status, memaddr, info);
517 return -1;
518 }
519
520 length = 2;
521
522 if (info->endian == BFD_ENDIAN_BIG)
523 insn = bfd_getb16 (buffer);
524 else
525 insn = bfd_getl16 (buffer);
526
527 /* Handle the extend opcode specially. */
528 use_extend = false;
529 if ((insn & 0xf800) == 0xf000)
530 {
531 use_extend = true;
532 extend = insn & 0x7ff;
533
534 memaddr += 2;
535
536 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
537 if (status != 0)
538 {
539 (*info->fprintf_func) (info->stream, "extend 0x%x",
540 (unsigned int) extend);
541 (*info->memory_error_func) (status, memaddr, info);
542 return -1;
543 }
544
8d67dc30
ILT
545 if (info->endian == BFD_ENDIAN_BIG)
546 insn = bfd_getb16 (buffer);
547 else
548 insn = bfd_getl16 (buffer);
c4f19df2
ILT
549
550 /* Check for an extend opcode followed by an extend opcode. */
551 if ((insn & 0xf800) == 0xf000)
552 {
553 (*info->fprintf_func) (info->stream, "extend 0x%x",
554 (unsigned int) extend);
20d43018 555 info->insn_type = dis_noninsn;
c4f19df2
ILT
556 return length;
557 }
558
559 length += 2;
8d67dc30
ILT
560 }
561
562 /* FIXME: Should probably use a hash table on the major opcode here. */
563
564 opend = mips16_opcodes + bfd_mips16_num_opcodes;
565 for (op = mips16_opcodes; op < opend; op++)
566 {
567 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
568 {
569 const char *s;
570
571 if (strchr (op->args, 'a') != NULL)
572 {
573 if (use_extend)
c4f19df2
ILT
574 {
575 (*info->fprintf_func) (info->stream, "extend 0x%x",
576 (unsigned int) extend);
20d43018 577 info->insn_type = dis_noninsn;
c4f19df2
ILT
578 return length - 2;
579 }
580
8d67dc30
ILT
581 use_extend = false;
582
583 memaddr += 2;
584
585 status = (*info->read_memory_func) (memaddr, buffer, 2,
586 info);
587 if (status == 0)
588 {
589 use_extend = true;
590 if (info->endian == BFD_ENDIAN_BIG)
591 extend = bfd_getb16 (buffer);
592 else
593 extend = bfd_getl16 (buffer);
594 length += 2;
595 }
596 }
597
c4f19df2
ILT
598 (*info->fprintf_func) (info->stream, "%s", op->name);
599 if (op->args[0] != '\0')
600 (*info->fprintf_func) (info->stream, "\t");
8d67dc30
ILT
601
602 for (s = op->args; *s != '\0'; s++)
603 {
604 if (*s == ','
605 && s[1] == 'w'
606 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
607 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
608 {
609 /* Skip the register and the comma. */
610 ++s;
611 continue;
612 }
613 if (*s == ','
614 && s[1] == 'v'
615 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
616 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
617 {
618 /* Skip the register and the comma. */
619 ++s;
620 continue;
621 }
622 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
623 info);
624 }
625
20d43018
ILT
626 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
627 {
628 info->branch_delay_insns = 1;
629 if (info->insn_type != dis_jsr)
630 info->insn_type = dis_branch;
631 }
632
8d67dc30
ILT
633 return length;
634 }
635 }
636
637 if (use_extend)
638 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
639 (*info->fprintf_func) (info->stream, "0x%x", insn);
20d43018 640 info->insn_type = dis_noninsn;
8d67dc30
ILT
641
642 return length;
643}
644
645/* Disassemble an operand for a mips16 instruction. */
646
647static void
648print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
649 int type;
650 const struct mips_opcode *op;
651 int l;
652 boolean use_extend;
653 int extend;
654 bfd_vma memaddr;
655 struct disassemble_info *info;
656{
657 switch (type)
658 {
659 case ',':
660 case '(':
661 case ')':
662 (*info->fprintf_func) (info->stream, "%c", type);
663 break;
664
665 case 'y':
666 case 'w':
667 (*info->fprintf_func) (info->stream, "$%s",
668 mips16_reg_names[((l >> MIPS16OP_SH_RY)
669 & MIPS16OP_MASK_RY)]);
670 break;
671
672 case 'x':
673 case 'v':
674 (*info->fprintf_func) (info->stream, "$%s",
675 mips16_reg_names[((l >> MIPS16OP_SH_RX)
676 & MIPS16OP_MASK_RX)]);
677 break;
678
679 case 'z':
680 (*info->fprintf_func) (info->stream, "$%s",
681 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
682 & MIPS16OP_MASK_RZ)]);
683 break;
684
685 case 'Z':
686 (*info->fprintf_func) (info->stream, "$%s",
687 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
688 & MIPS16OP_MASK_MOVE32Z)]);
689 break;
690
691 case '0':
692 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
693 break;
694
695 case 'S':
696 (*info->fprintf_func) (info->stream, "$%s", reg_names[29]);
697 break;
698
699 case 'P':
700 (*info->fprintf_func) (info->stream, "$pc");
701 break;
702
703 case 'R':
704 (*info->fprintf_func) (info->stream, "$%s", reg_names[31]);
705 break;
706
707 case 'X':
708 (*info->fprintf_func) (info->stream, "$%s",
709 reg_names[((l >> MIPS16OP_SH_REGR32)
710 & MIPS16OP_MASK_REGR32)]);
711 break;
712
713 case 'Y':
714 (*info->fprintf_func) (info->stream, "$%s",
715 reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
716 break;
717
718 case '<':
719 case '>':
720 case '[':
721 case ']':
722 case '4':
723 case '5':
724 case 'H':
725 case 'W':
726 case 'D':
727 case 'j':
728 case '6':
729 case '8':
730 case 'V':
731 case 'C':
732 case 'U':
733 case 'k':
734 case 'K':
735 case 'p':
736 case 'q':
737 case 'A':
738 case 'B':
739 case 'E':
740 {
741 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
742
743 shift = 0;
744 signedp = 0;
745 extbits = 16;
746 pcrel = 0;
747 extu = 0;
748 branch = 0;
749 switch (type)
750 {
751 case '<':
752 nbits = 3;
753 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
754 extbits = 5;
755 extu = 1;
756 break;
757 case '>':
758 nbits = 3;
759 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
760 extbits = 5;
761 extu = 1;
762 break;
763 case '[':
764 nbits = 3;
765 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
766 extbits = 6;
767 extu = 1;
768 break;
769 case ']':
770 nbits = 3;
771 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
772 extbits = 6;
773 extu = 1;
774 break;
775 case '4':
776 nbits = 4;
777 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
778 signedp = 1;
779 extbits = 15;
780 break;
781 case '5':
782 nbits = 5;
783 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
784 info->insn_type = dis_dref;
785 info->data_size = 1;
8d67dc30
ILT
786 break;
787 case 'H':
788 nbits = 5;
789 shift = 1;
790 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
791 info->insn_type = dis_dref;
792 info->data_size = 2;
8d67dc30
ILT
793 break;
794 case 'W':
795 nbits = 5;
796 shift = 2;
797 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
798 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
799 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
800 {
801 info->insn_type = dis_dref;
802 info->data_size = 4;
803 }
8d67dc30
ILT
804 break;
805 case 'D':
806 nbits = 5;
807 shift = 3;
808 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
809 info->insn_type = dis_dref;
810 info->data_size = 8;
8d67dc30
ILT
811 break;
812 case 'j':
813 nbits = 5;
814 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
815 signedp = 1;
816 break;
817 case '6':
818 nbits = 6;
819 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
820 break;
821 case '8':
822 nbits = 8;
823 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
824 break;
825 case 'V':
826 nbits = 8;
827 shift = 2;
828 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
829 /* FIXME: This might be lw, or it might be addiu to $sp or
830 $pc. We assume it's load. */
831 info->insn_type = dis_dref;
832 info->data_size = 4;
8d67dc30
ILT
833 break;
834 case 'C':
835 nbits = 8;
836 shift = 3;
837 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
838 info->insn_type = dis_dref;
839 info->data_size = 8;
8d67dc30
ILT
840 break;
841 case 'U':
842 nbits = 8;
843 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
844 extu = 1;
845 break;
846 case 'k':
847 nbits = 8;
848 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
849 signedp = 1;
850 break;
851 case 'K':
852 nbits = 8;
853 shift = 3;
854 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
855 signedp = 1;
856 break;
857 case 'p':
858 nbits = 8;
859 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
860 signedp = 1;
861 pcrel = 1;
862 branch = 1;
20d43018 863 info->insn_type = dis_condbranch;
8d67dc30
ILT
864 break;
865 case 'q':
866 nbits = 11;
867 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
868 signedp = 1;
869 pcrel = 1;
870 branch = 1;
20d43018 871 info->insn_type = dis_branch;
8d67dc30
ILT
872 break;
873 case 'A':
874 nbits = 8;
875 shift = 2;
876 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
877 pcrel = 1;
20d43018
ILT
878 /* FIXME: This can be lw or la. We assume it is lw. */
879 info->insn_type = dis_dref;
880 info->data_size = 4;
8d67dc30
ILT
881 break;
882 case 'B':
883 nbits = 5;
884 shift = 3;
885 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
886 pcrel = 1;
20d43018
ILT
887 info->insn_type = dis_dref;
888 info->data_size = 8;
8d67dc30
ILT
889 break;
890 case 'E':
891 nbits = 5;
892 shift = 2;
893 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
894 pcrel = 1;
895 break;
896 default:
897 abort ();
898 }
899
900 if (! use_extend)
901 {
902 if (signedp && immed >= (1 << (nbits - 1)))
903 immed -= 1 << nbits;
904 immed <<= shift;
905 if ((type == '<' || type == '>' || type == '[' || type == '[')
906 && immed == 0)
907 immed = 8;
908 }
909 else
910 {
911 if (extbits == 16)
912 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
913 else if (extbits == 15)
914 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
915 else
916 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
917 immed &= (1 << extbits) - 1;
918 if (! extu && immed >= (1 << (extbits - 1)))
919 immed -= 1 << extbits;
920 }
921
922 if (! pcrel)
923 (*info->fprintf_func) (info->stream, "%d", immed);
924 else
925 {
c4f19df2 926 bfd_vma baseaddr;
8d67dc30
ILT
927 bfd_vma val;
928
929 if (branch)
c4f19df2
ILT
930 {
931 immed *= 2;
932 baseaddr = memaddr + 2;
933 }
934 else if (use_extend)
83af2335 935 baseaddr = memaddr - 2;
c4f19df2
ILT
936 else
937 {
938 int status;
939 bfd_byte buffer[2];
940
941 baseaddr = memaddr;
942
943 /* If this instruction is in the delay slot of a jr
944 instruction, the base address is the address of the
945 jr instruction. If it is in the delay slot of jalr
946 instruction, the base address is the address of the
947 jalr instruction. This test is unreliable: we have
948 no way of knowing whether the previous word is
949 instruction or data. */
950 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
951 info);
952 if (status == 0
953 && (((info->endian == BFD_ENDIAN_BIG
954 ? bfd_getb16 (buffer)
955 : bfd_getl16 (buffer))
956 & 0xf800) == 0x1800))
957 baseaddr = memaddr - 4;
958 else
959 {
960 status = (*info->read_memory_func) (memaddr - 2, buffer,
961 2, info);
962 if (status == 0
963 && (((info->endian == BFD_ENDIAN_BIG
964 ? bfd_getb16 (buffer)
965 : bfd_getl16 (buffer))
966 & 0xf81f) == 0xe800))
967 baseaddr = memaddr - 2;
968 }
969 }
970 val = (baseaddr & ~ ((1 << shift) - 1)) + immed;
8d67dc30 971 (*info->print_address_func) (val, info);
20d43018 972 info->target = val;
8d67dc30
ILT
973 }
974 }
975 break;
976
977 case 'a':
978 if (! use_extend)
979 extend = 0;
980 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
981 (*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
20d43018
ILT
982 info->insn_type = dis_jsr;
983 info->target = (memaddr & 0xf0000000) | l;
984 info->branch_delay_insns = 1;
8d67dc30
ILT
985 break;
986
987 case 'l':
988 case 'L':
989 {
990 int need_comma, amask, smask;
991
992 need_comma = 0;
993
994 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
995
996 amask = (l >> 3) & 7;
0d52464c
ILT
997
998 if (amask > 0 && amask < 5)
8d67dc30 999 {
0d52464c 1000 (*info->fprintf_func) (info->stream, "$%s", reg_names[4]);
8d67dc30 1001 if (amask > 1)
0d52464c 1002 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
1003 reg_names[amask + 3]);
1004 need_comma = 1;
1005 }
1006
1007 smask = (l >> 1) & 3;
1008 if (smask == 3)
1009 {
1010 (*info->fprintf_func) (info->stream, "%s??",
1011 need_comma ? "," : "");
1012 need_comma = 1;
1013 }
1014 else if (smask > 0)
1015 {
0d52464c 1016 (*info->fprintf_func) (info->stream, "%s$%s",
8d67dc30
ILT
1017 need_comma ? "," : "",
1018 reg_names[16]);
1019 if (smask > 1)
0d52464c 1020 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
1021 reg_names[smask + 15]);
1022 need_comma = 1;
1023 }
1024
1025 if (l & 1)
0d52464c
ILT
1026 {
1027 (*info->fprintf_func) (info->stream, "%s$%s",
1028 need_comma ? "," : "",
1029 reg_names[31]);
1030 need_comma = 1;
1031 }
1032
1033 if (amask == 5 || amask == 6)
1034 {
1035 (*info->fprintf_func) (info->stream, "%s$f0",
1036 need_comma ? "," : "");
1037 if (amask == 6)
1038 (*info->fprintf_func) (info->stream, "-$f1");
1039 }
8d67dc30
ILT
1040 }
1041 break;
1042
1043 default:
1044 abort ();
1045 }
1046}
This page took 0.218333 seconds and 4 git commands to generate.