* dvp-opc.c (vif_opcodes): Add stcycl.
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
d0ba1cea 1/* Print mips instructions for GDB, the GNU debugger, or for objdump.
3536b6a3 2 Copyright 1989, 91-97, 1998 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 218 case 'P':
fb1a826b 219 (*info->fprintf_func) (info->stream, "%d",
83af2335
JL
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
fb1a826b 403 /* end-sanitize-vr5400 */
83af2335
JL
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
88b38f0c
DE
446 && info->symbols != NULL
447 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
8d67dc30
ILT
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
37130f11
DE
470 /* start-sanitize-sky */
471#ifdef ARCH_dvp
88b38f0c
DE
472 {
473 /* bfd_mach_dvp_p is a macro which may evaluate its arguments more than
474 once. Since dvp_mach_type is a function, ensure it's only called
475 once. */
476 int mach = dvp_info_mach_type (info);
477
478 if (bfd_mach_dvp_p (info->mach)
479 || bfd_mach_dvp_p (mach))
480 return print_insn_dvp (memaddr, info);
481 }
37130f11
DE
482#endif
483 /* end-sanitize-sky */
484
8d67dc30
ILT
485 if (info->mach == 16
486 || (info->flavour == bfd_target_elf_flavour
88b38f0c
DE
487 && info->symbols != NULL
488 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
8d67dc30
ILT
489 == STO_MIPS16)))
490 return print_insn_mips16 (memaddr, info);
491
492 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
5d0734a7 493 if (status == 0)
8d67dc30
ILT
494 return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer),
495 info);
5d0734a7
JK
496 else
497 {
498 (*info->memory_error_func) (status, memaddr, info);
499 return -1;
500 }
501}
8d67dc30
ILT
502\f
503/* Disassemble mips16 instructions. */
504
505static int
506print_insn_mips16 (memaddr, info)
507 bfd_vma memaddr;
508 struct disassemble_info *info;
509{
510 int status;
511 bfd_byte buffer[2];
512 int length;
513 int insn;
514 boolean use_extend;
515 int extend;
516 const struct mips_opcode *op, *opend;
517
2ea116f4
ILT
518 info->bytes_per_chunk = 2;
519 info->display_endian = info->endian;
520
20d43018
ILT
521 info->insn_info_valid = 1;
522 info->branch_delay_insns = 0;
523 info->data_size = 0;
524 info->insn_type = dis_nonbranch;
525 info->target = 0;
526 info->target2 = 0;
527
8d67dc30
ILT
528 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
529 if (status != 0)
530 {
531 (*info->memory_error_func) (status, memaddr, info);
532 return -1;
533 }
534
535 length = 2;
536
537 if (info->endian == BFD_ENDIAN_BIG)
538 insn = bfd_getb16 (buffer);
539 else
540 insn = bfd_getl16 (buffer);
541
542 /* Handle the extend opcode specially. */
543 use_extend = false;
544 if ((insn & 0xf800) == 0xf000)
545 {
546 use_extend = true;
547 extend = insn & 0x7ff;
548
549 memaddr += 2;
550
551 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
552 if (status != 0)
553 {
554 (*info->fprintf_func) (info->stream, "extend 0x%x",
555 (unsigned int) extend);
556 (*info->memory_error_func) (status, memaddr, info);
557 return -1;
558 }
559
8d67dc30
ILT
560 if (info->endian == BFD_ENDIAN_BIG)
561 insn = bfd_getb16 (buffer);
562 else
563 insn = bfd_getl16 (buffer);
c4f19df2
ILT
564
565 /* Check for an extend opcode followed by an extend opcode. */
566 if ((insn & 0xf800) == 0xf000)
567 {
568 (*info->fprintf_func) (info->stream, "extend 0x%x",
569 (unsigned int) extend);
20d43018 570 info->insn_type = dis_noninsn;
c4f19df2
ILT
571 return length;
572 }
573
574 length += 2;
8d67dc30
ILT
575 }
576
577 /* FIXME: Should probably use a hash table on the major opcode here. */
578
579 opend = mips16_opcodes + bfd_mips16_num_opcodes;
580 for (op = mips16_opcodes; op < opend; op++)
581 {
582 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
583 {
584 const char *s;
585
586 if (strchr (op->args, 'a') != NULL)
587 {
588 if (use_extend)
c4f19df2
ILT
589 {
590 (*info->fprintf_func) (info->stream, "extend 0x%x",
591 (unsigned int) extend);
20d43018 592 info->insn_type = dis_noninsn;
c4f19df2
ILT
593 return length - 2;
594 }
595
8d67dc30
ILT
596 use_extend = false;
597
598 memaddr += 2;
599
600 status = (*info->read_memory_func) (memaddr, buffer, 2,
601 info);
602 if (status == 0)
603 {
604 use_extend = true;
605 if (info->endian == BFD_ENDIAN_BIG)
606 extend = bfd_getb16 (buffer);
607 else
608 extend = bfd_getl16 (buffer);
609 length += 2;
610 }
611 }
612
c4f19df2
ILT
613 (*info->fprintf_func) (info->stream, "%s", op->name);
614 if (op->args[0] != '\0')
615 (*info->fprintf_func) (info->stream, "\t");
8d67dc30
ILT
616
617 for (s = op->args; *s != '\0'; s++)
618 {
619 if (*s == ','
620 && s[1] == 'w'
621 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
622 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
623 {
624 /* Skip the register and the comma. */
625 ++s;
626 continue;
627 }
628 if (*s == ','
629 && s[1] == 'v'
630 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
631 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
632 {
633 /* Skip the register and the comma. */
634 ++s;
635 continue;
636 }
637 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
638 info);
639 }
640
20d43018
ILT
641 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
642 {
643 info->branch_delay_insns = 1;
644 if (info->insn_type != dis_jsr)
645 info->insn_type = dis_branch;
646 }
647
8d67dc30
ILT
648 return length;
649 }
650 }
651
652 if (use_extend)
653 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
654 (*info->fprintf_func) (info->stream, "0x%x", insn);
20d43018 655 info->insn_type = dis_noninsn;
8d67dc30
ILT
656
657 return length;
658}
659
660/* Disassemble an operand for a mips16 instruction. */
661
662static void
663print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
664 int type;
665 const struct mips_opcode *op;
666 int l;
667 boolean use_extend;
668 int extend;
669 bfd_vma memaddr;
670 struct disassemble_info *info;
671{
672 switch (type)
673 {
674 case ',':
675 case '(':
676 case ')':
677 (*info->fprintf_func) (info->stream, "%c", type);
678 break;
679
680 case 'y':
681 case 'w':
682 (*info->fprintf_func) (info->stream, "$%s",
683 mips16_reg_names[((l >> MIPS16OP_SH_RY)
684 & MIPS16OP_MASK_RY)]);
685 break;
686
687 case 'x':
688 case 'v':
689 (*info->fprintf_func) (info->stream, "$%s",
690 mips16_reg_names[((l >> MIPS16OP_SH_RX)
691 & MIPS16OP_MASK_RX)]);
692 break;
693
694 case 'z':
695 (*info->fprintf_func) (info->stream, "$%s",
696 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
697 & MIPS16OP_MASK_RZ)]);
698 break;
699
700 case 'Z':
701 (*info->fprintf_func) (info->stream, "$%s",
702 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
703 & MIPS16OP_MASK_MOVE32Z)]);
704 break;
705
706 case '0':
707 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
708 break;
709
710 case 'S':
711 (*info->fprintf_func) (info->stream, "$%s", reg_names[29]);
712 break;
713
714 case 'P':
715 (*info->fprintf_func) (info->stream, "$pc");
716 break;
717
718 case 'R':
719 (*info->fprintf_func) (info->stream, "$%s", reg_names[31]);
720 break;
721
722 case 'X':
723 (*info->fprintf_func) (info->stream, "$%s",
724 reg_names[((l >> MIPS16OP_SH_REGR32)
725 & MIPS16OP_MASK_REGR32)]);
726 break;
727
728 case 'Y':
729 (*info->fprintf_func) (info->stream, "$%s",
730 reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
731 break;
732
733 case '<':
734 case '>':
735 case '[':
736 case ']':
737 case '4':
738 case '5':
739 case 'H':
740 case 'W':
741 case 'D':
742 case 'j':
743 case '6':
744 case '8':
745 case 'V':
746 case 'C':
747 case 'U':
748 case 'k':
749 case 'K':
750 case 'p':
751 case 'q':
752 case 'A':
753 case 'B':
754 case 'E':
755 {
756 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
757
758 shift = 0;
759 signedp = 0;
760 extbits = 16;
761 pcrel = 0;
762 extu = 0;
763 branch = 0;
764 switch (type)
765 {
766 case '<':
767 nbits = 3;
768 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
769 extbits = 5;
770 extu = 1;
771 break;
772 case '>':
773 nbits = 3;
774 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
775 extbits = 5;
776 extu = 1;
777 break;
778 case '[':
779 nbits = 3;
780 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
781 extbits = 6;
782 extu = 1;
783 break;
784 case ']':
785 nbits = 3;
786 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
787 extbits = 6;
788 extu = 1;
789 break;
790 case '4':
791 nbits = 4;
792 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
793 signedp = 1;
794 extbits = 15;
795 break;
796 case '5':
797 nbits = 5;
798 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
799 info->insn_type = dis_dref;
800 info->data_size = 1;
8d67dc30
ILT
801 break;
802 case 'H':
803 nbits = 5;
804 shift = 1;
805 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
806 info->insn_type = dis_dref;
807 info->data_size = 2;
8d67dc30
ILT
808 break;
809 case 'W':
810 nbits = 5;
811 shift = 2;
812 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
813 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
814 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
815 {
816 info->insn_type = dis_dref;
817 info->data_size = 4;
818 }
8d67dc30
ILT
819 break;
820 case 'D':
821 nbits = 5;
822 shift = 3;
823 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
20d43018
ILT
824 info->insn_type = dis_dref;
825 info->data_size = 8;
8d67dc30
ILT
826 break;
827 case 'j':
828 nbits = 5;
829 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
830 signedp = 1;
831 break;
832 case '6':
833 nbits = 6;
834 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
835 break;
836 case '8':
837 nbits = 8;
838 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
839 break;
840 case 'V':
841 nbits = 8;
842 shift = 2;
843 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
844 /* FIXME: This might be lw, or it might be addiu to $sp or
845 $pc. We assume it's load. */
846 info->insn_type = dis_dref;
847 info->data_size = 4;
8d67dc30
ILT
848 break;
849 case 'C':
850 nbits = 8;
851 shift = 3;
852 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
20d43018
ILT
853 info->insn_type = dis_dref;
854 info->data_size = 8;
8d67dc30
ILT
855 break;
856 case 'U':
857 nbits = 8;
858 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
859 extu = 1;
860 break;
861 case 'k':
862 nbits = 8;
863 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
864 signedp = 1;
865 break;
866 case 'K':
867 nbits = 8;
868 shift = 3;
869 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
870 signedp = 1;
871 break;
872 case 'p':
873 nbits = 8;
874 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
875 signedp = 1;
876 pcrel = 1;
877 branch = 1;
20d43018 878 info->insn_type = dis_condbranch;
8d67dc30
ILT
879 break;
880 case 'q':
881 nbits = 11;
882 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
883 signedp = 1;
884 pcrel = 1;
885 branch = 1;
20d43018 886 info->insn_type = dis_branch;
8d67dc30
ILT
887 break;
888 case 'A':
889 nbits = 8;
890 shift = 2;
891 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
892 pcrel = 1;
20d43018
ILT
893 /* FIXME: This can be lw or la. We assume it is lw. */
894 info->insn_type = dis_dref;
895 info->data_size = 4;
8d67dc30
ILT
896 break;
897 case 'B':
898 nbits = 5;
899 shift = 3;
900 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
901 pcrel = 1;
20d43018
ILT
902 info->insn_type = dis_dref;
903 info->data_size = 8;
8d67dc30
ILT
904 break;
905 case 'E':
906 nbits = 5;
907 shift = 2;
908 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
909 pcrel = 1;
910 break;
911 default:
912 abort ();
913 }
914
915 if (! use_extend)
916 {
917 if (signedp && immed >= (1 << (nbits - 1)))
918 immed -= 1 << nbits;
919 immed <<= shift;
920 if ((type == '<' || type == '>' || type == '[' || type == '[')
921 && immed == 0)
922 immed = 8;
923 }
924 else
925 {
926 if (extbits == 16)
927 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
928 else if (extbits == 15)
929 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
930 else
931 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
932 immed &= (1 << extbits) - 1;
933 if (! extu && immed >= (1 << (extbits - 1)))
934 immed -= 1 << extbits;
935 }
936
937 if (! pcrel)
938 (*info->fprintf_func) (info->stream, "%d", immed);
939 else
940 {
c4f19df2 941 bfd_vma baseaddr;
8d67dc30
ILT
942 bfd_vma val;
943
944 if (branch)
c4f19df2
ILT
945 {
946 immed *= 2;
947 baseaddr = memaddr + 2;
948 }
949 else if (use_extend)
83af2335 950 baseaddr = memaddr - 2;
c4f19df2
ILT
951 else
952 {
953 int status;
954 bfd_byte buffer[2];
955
956 baseaddr = memaddr;
957
958 /* If this instruction is in the delay slot of a jr
959 instruction, the base address is the address of the
960 jr instruction. If it is in the delay slot of jalr
961 instruction, the base address is the address of the
962 jalr instruction. This test is unreliable: we have
963 no way of knowing whether the previous word is
964 instruction or data. */
965 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
966 info);
967 if (status == 0
968 && (((info->endian == BFD_ENDIAN_BIG
969 ? bfd_getb16 (buffer)
970 : bfd_getl16 (buffer))
971 & 0xf800) == 0x1800))
972 baseaddr = memaddr - 4;
973 else
974 {
975 status = (*info->read_memory_func) (memaddr - 2, buffer,
976 2, info);
977 if (status == 0
978 && (((info->endian == BFD_ENDIAN_BIG
979 ? bfd_getb16 (buffer)
980 : bfd_getl16 (buffer))
981 & 0xf81f) == 0xe800))
982 baseaddr = memaddr - 2;
983 }
984 }
985 val = (baseaddr & ~ ((1 << shift) - 1)) + immed;
8d67dc30 986 (*info->print_address_func) (val, info);
20d43018 987 info->target = val;
8d67dc30
ILT
988 }
989 }
990 break;
991
992 case 'a':
993 if (! use_extend)
994 extend = 0;
995 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
996 (*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
20d43018
ILT
997 info->insn_type = dis_jsr;
998 info->target = (memaddr & 0xf0000000) | l;
999 info->branch_delay_insns = 1;
8d67dc30
ILT
1000 break;
1001
1002 case 'l':
1003 case 'L':
1004 {
1005 int need_comma, amask, smask;
1006
1007 need_comma = 0;
1008
1009 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1010
1011 amask = (l >> 3) & 7;
0d52464c
ILT
1012
1013 if (amask > 0 && amask < 5)
8d67dc30 1014 {
0d52464c 1015 (*info->fprintf_func) (info->stream, "$%s", reg_names[4]);
8d67dc30 1016 if (amask > 1)
0d52464c 1017 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
1018 reg_names[amask + 3]);
1019 need_comma = 1;
1020 }
1021
1022 smask = (l >> 1) & 3;
1023 if (smask == 3)
1024 {
1025 (*info->fprintf_func) (info->stream, "%s??",
1026 need_comma ? "," : "");
1027 need_comma = 1;
1028 }
1029 else if (smask > 0)
1030 {
0d52464c 1031 (*info->fprintf_func) (info->stream, "%s$%s",
8d67dc30
ILT
1032 need_comma ? "," : "",
1033 reg_names[16]);
1034 if (smask > 1)
0d52464c 1035 (*info->fprintf_func) (info->stream, "-$%s",
8d67dc30
ILT
1036 reg_names[smask + 15]);
1037 need_comma = 1;
1038 }
1039
1040 if (l & 1)
0d52464c
ILT
1041 {
1042 (*info->fprintf_func) (info->stream, "%s$%s",
1043 need_comma ? "," : "",
1044 reg_names[31]);
1045 need_comma = 1;
1046 }
1047
1048 if (amask == 5 || amask == 6)
1049 {
1050 (*info->fprintf_func) (info->stream, "%s$f0",
1051 need_comma ? "," : "");
1052 if (amask == 6)
1053 (*info->fprintf_func) (info->stream, "-$f1");
1054 }
8d67dc30
ILT
1055 }
1056 break;
1057
1058 default:
1059 abort ();
1060 }
1061}
This page took 0.228854 seconds and 4 git commands to generate.