2002-10-02 Nathanael Nerode <neroden@gcc.gnu.org>
[binutils.git] / opcodes / sh-dis.c
blob24d4b41eaff5b69b425bc76910fe11d643764502
1 /* Disassemble SH instructions.
2 Copyright 1993, 1994, 1995, 1997, 1998, 2000, 2001
3 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 #include <stdio.h>
20 #include "sysdep.h"
21 #define STATIC_TABLE
22 #define DEFINE_TABLE
24 #include "sh-opc.h"
25 #include "dis-asm.h"
27 static void print_movxy
28 PARAMS ((sh_opcode_info *, int, int, fprintf_ftype, void *));
29 static void print_insn_ddt PARAMS ((int, struct disassemble_info *));
30 static void print_dsp_reg PARAMS ((int, fprintf_ftype, void *));
31 static void print_insn_ppi PARAMS ((int, struct disassemble_info *));
33 static void
34 print_movxy (op, rn, rm, fprintf_fn, stream)
35 sh_opcode_info *op;
36 int rn, rm;
37 fprintf_ftype fprintf_fn;
38 void *stream;
40 int n;
42 fprintf_fn (stream, "%s\t", op->name);
43 for (n = 0; n < 2; n++)
45 switch (op->arg[n])
47 case A_IND_N:
48 fprintf_fn (stream, "@r%d", rn);
49 break;
50 case A_INC_N:
51 fprintf_fn (stream, "@r%d+", rn);
52 break;
53 case A_PMOD_N:
54 fprintf_fn (stream, "@r%d+r8", rn);
55 break;
56 case A_PMODY_N:
57 fprintf_fn (stream, "@r%d+r9", rn);
58 break;
59 case DSP_REG_M:
60 fprintf_fn (stream, "a%c", '0' + rm);
61 break;
62 case DSP_REG_X:
63 fprintf_fn (stream, "x%c", '0' + rm);
64 break;
65 case DSP_REG_Y:
66 fprintf_fn (stream, "y%c", '0' + rm);
67 break;
68 default:
69 abort ();
71 if (n == 0)
72 fprintf_fn (stream, ",");
76 /* Print a double data transfer insn. INSN is just the lower three
77 nibbles of the insn, i.e. field a and the bit that indicates if
78 a parallel processing insn follows.
79 Return nonzero if a field b of a parallel processing insns follows. */
81 static void
82 print_insn_ddt (insn, info)
83 int insn;
84 struct disassemble_info *info;
86 fprintf_ftype fprintf_fn = info->fprintf_func;
87 void *stream = info->stream;
89 /* If this is just a nop, make sure to emit something. */
90 if (insn == 0x000)
91 fprintf_fn (stream, "nopx\tnopy");
93 /* If a parallel processing insn was printed before,
94 and we got a non-nop, emit a tab. */
95 if ((insn & 0x800) && (insn & 0x3ff))
96 fprintf_fn (stream, "\t");
98 /* Check if either the x or y part is invalid. */
99 if (((insn & 0xc) == 0 && (insn & 0x2a0))
100 || ((insn & 3) == 0 && (insn & 0x150)))
101 fprintf_fn (stream, ".word 0x%x", insn);
102 else
104 static sh_opcode_info *first_movx, *first_movy;
105 sh_opcode_info *opx, *opy;
106 unsigned int insn_x, insn_y;
108 if (! first_movx)
110 for (first_movx = sh_table; first_movx->nibbles[1] != MOVX;)
111 first_movx++;
112 for (first_movy = first_movx; first_movy->nibbles[1] != MOVY;)
113 first_movy++;
115 insn_x = (insn >> 2) & 0xb;
116 if (insn_x)
118 for (opx = first_movx; opx->nibbles[2] != insn_x;)
119 opx++;
120 print_movxy (opx, ((insn >> 9) & 1) + 4, (insn >> 7) & 1,
121 fprintf_fn, stream);
123 insn_y = (insn & 3) | ((insn >> 1) & 8);
124 if (insn_y)
126 if (insn_x)
127 fprintf_fn (stream, "\t");
128 for (opy = first_movy; opy->nibbles[2] != insn_y;)
129 opy++;
130 print_movxy (opy, ((insn >> 8) & 1) + 6, (insn >> 6) & 1,
131 fprintf_fn, stream);
136 static void
137 print_dsp_reg (rm, fprintf_fn, stream)
138 int rm;
139 fprintf_ftype fprintf_fn;
140 void *stream;
142 switch (rm)
144 case A_A1_NUM:
145 fprintf_fn (stream, "a1");
146 break;
147 case A_A0_NUM:
148 fprintf_fn (stream, "a0");
149 break;
150 case A_X0_NUM:
151 fprintf_fn (stream, "x0");
152 break;
153 case A_X1_NUM:
154 fprintf_fn (stream, "x1");
155 break;
156 case A_Y0_NUM:
157 fprintf_fn (stream, "y0");
158 break;
159 case A_Y1_NUM:
160 fprintf_fn (stream, "y1");
161 break;
162 case A_M0_NUM:
163 fprintf_fn (stream, "m0");
164 break;
165 case A_A1G_NUM:
166 fprintf_fn (stream, "a1g");
167 break;
168 case A_M1_NUM:
169 fprintf_fn (stream, "m1");
170 break;
171 case A_A0G_NUM:
172 fprintf_fn (stream, "a0g");
173 break;
174 default:
175 fprintf_fn (stream, "0x%x", rm);
176 break;
180 static void
181 print_insn_ppi (field_b, info)
182 int field_b;
183 struct disassemble_info *info;
185 static char *sx_tab[] = { "x0", "x1", "a0", "a1" };
186 static char *sy_tab[] = { "y0", "y1", "m0", "m1" };
187 fprintf_ftype fprintf_fn = info->fprintf_func;
188 void *stream = info->stream;
189 unsigned int nib1, nib2, nib3;
190 char *dc = NULL;
191 sh_opcode_info *op;
193 if ((field_b & 0xe800) == 0)
195 fprintf_fn (stream, "psh%c\t#%d,",
196 field_b & 0x1000 ? 'a' : 'l',
197 (field_b >> 4) & 127);
198 print_dsp_reg (field_b & 0xf, fprintf_fn, stream);
199 return;
201 if ((field_b & 0xc000) == 0x4000 && (field_b & 0x3000) != 0x1000)
203 static char *du_tab[] = { "x0", "y0", "a0", "a1" };
204 static char *se_tab[] = { "x0", "x1", "y0", "a1" };
205 static char *sf_tab[] = { "y0", "y1", "x0", "a1" };
206 static char *sg_tab[] = { "m0", "m1", "a0", "a1" };
208 if (field_b & 0x2000)
210 fprintf_fn (stream, "p%s %s,%s,%s\t",
211 (field_b & 0x1000) ? "add" : "sub",
212 sx_tab[(field_b >> 6) & 3],
213 sy_tab[(field_b >> 4) & 3],
214 du_tab[(field_b >> 0) & 3]);
216 fprintf_fn (stream, "pmuls%c%s,%s,%s",
217 field_b & 0x2000 ? ' ' : '\t',
218 se_tab[(field_b >> 10) & 3],
219 sf_tab[(field_b >> 8) & 3],
220 sg_tab[(field_b >> 2) & 3]);
221 return;
224 nib1 = PPIC;
225 nib2 = field_b >> 12 & 0xf;
226 nib3 = field_b >> 8 & 0xf;
227 switch (nib3 & 0x3)
229 case 0:
230 dc = "";
231 nib1 = PPI3;
232 break;
233 case 1:
234 dc = "";
235 break;
236 case 2:
237 dc = "dct ";
238 nib3 -= 1;
239 break;
240 case 3:
241 dc = "dcf ";
242 nib3 -= 2;
243 break;
245 for (op = sh_table; op->name; op++)
247 if (op->nibbles[1] == nib1
248 && op->nibbles[2] == nib2
249 && op->nibbles[3] == nib3)
251 int n;
253 fprintf_fn (stream, "%s%s\t", dc, op->name);
254 for (n = 0; n < 3 && op->arg[n] != A_END; n++)
256 if (n && op->arg[1] != A_END)
257 fprintf_fn (stream, ",");
258 switch (op->arg[n])
260 case DSP_REG_N:
261 print_dsp_reg (field_b & 0xf, fprintf_fn, stream);
262 break;
263 case DSP_REG_X:
264 fprintf_fn (stream, sx_tab[(field_b >> 6) & 3]);
265 break;
266 case DSP_REG_Y:
267 fprintf_fn (stream, sy_tab[(field_b >> 4) & 3]);
268 break;
269 case A_MACH:
270 fprintf_fn (stream, "mach");
271 break;
272 case A_MACL:
273 fprintf_fn (stream, "macl");
274 break;
275 default:
276 abort ();
279 return;
282 /* Not found. */
283 fprintf_fn (stream, ".word 0x%x", field_b);
287 print_insn_sh (memaddr, info)
288 bfd_vma memaddr;
289 struct disassemble_info *info;
291 fprintf_ftype fprintf_fn = info->fprintf_func;
292 void *stream = info->stream;
293 unsigned char insn[2];
294 unsigned char nibs[4];
295 int status;
296 bfd_vma relmask = ~(bfd_vma) 0;
297 sh_opcode_info *op;
298 int target_arch;
300 switch (info->mach)
302 case bfd_mach_sh:
303 target_arch = arch_sh1;
304 /* SH coff object files lack information about the machine type, so
305 we end up with bfd_mach_sh unless it was set explicitly (which
306 could have happended if this is a call from gdb or the simulator.) */
307 if (info->symbols
308 && bfd_asymbol_flavour(*info->symbols) == bfd_target_coff_flavour)
309 target_arch = arch_sh4;
310 break;
311 case bfd_mach_sh2:
312 target_arch = arch_sh2;
313 break;
314 case bfd_mach_sh_dsp:
315 target_arch = arch_sh_dsp;
316 break;
317 case bfd_mach_sh3:
318 target_arch = arch_sh3;
319 break;
320 case bfd_mach_sh3_dsp:
321 target_arch = arch_sh3_dsp;
322 break;
323 case bfd_mach_sh3e:
324 target_arch = arch_sh3e;
325 break;
326 case bfd_mach_sh4:
327 target_arch = arch_sh4;
328 break;
329 case bfd_mach_sh5:
330 #ifdef INCLUDE_SHMEDIA
331 status = print_insn_sh64 (memaddr, info);
332 if (status != -2)
333 return status;
334 #endif
335 /* When we get here for sh64, it's because we want to disassemble
336 SHcompact, i.e. arch_sh4. */
337 target_arch = arch_sh4;
338 break;
339 default:
340 abort ();
343 status = info->read_memory_func (memaddr, insn, 2, info);
345 if (status != 0)
347 info->memory_error_func (status, memaddr, info);
348 return -1;
351 if (info->endian == BFD_ENDIAN_LITTLE)
353 nibs[0] = (insn[1] >> 4) & 0xf;
354 nibs[1] = insn[1] & 0xf;
356 nibs[2] = (insn[0] >> 4) & 0xf;
357 nibs[3] = insn[0] & 0xf;
359 else
361 nibs[0] = (insn[0] >> 4) & 0xf;
362 nibs[1] = insn[0] & 0xf;
364 nibs[2] = (insn[1] >> 4) & 0xf;
365 nibs[3] = insn[1] & 0xf;
368 if (nibs[0] == 0xf && (nibs[1] & 4) == 0 && target_arch & arch_sh_dsp_up)
370 if (nibs[1] & 8)
372 int field_b;
374 status = info->read_memory_func (memaddr + 2, insn, 2, info);
376 if (status != 0)
378 info->memory_error_func (status, memaddr + 2, info);
379 return -1;
382 if (info->endian == BFD_ENDIAN_LITTLE)
383 field_b = insn[1] << 8 | insn[0];
384 else
385 field_b = insn[0] << 8 | insn[1];
387 print_insn_ppi (field_b, info);
388 print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info);
389 return 4;
391 print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info);
392 return 2;
394 for (op = sh_table; op->name; op++)
396 int n;
397 int imm = 0;
398 int rn = 0;
399 int rm = 0;
400 int rb = 0;
401 int disp_pc;
402 bfd_vma disp_pc_addr = 0;
404 if ((op->arch & target_arch) == 0)
405 goto fail;
406 for (n = 0; n < 4; n++)
408 int i = op->nibbles[n];
410 if (i < 16)
412 if (nibs[n] == i)
413 continue;
414 goto fail;
416 switch (i)
418 case BRANCH_8:
419 imm = (nibs[2] << 4) | (nibs[3]);
420 if (imm & 0x80)
421 imm |= ~0xff;
422 imm = ((char) imm) * 2 + 4;
423 goto ok;
424 case BRANCH_12:
425 imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]);
426 if (imm & 0x800)
427 imm |= ~0xfff;
428 imm = imm * 2 + 4;
429 goto ok;
430 case IMM0_4:
431 case IMM1_4:
432 imm = nibs[3];
433 goto ok;
434 case IMM0_4BY2:
435 case IMM1_4BY2:
436 imm = nibs[3] << 1;
437 goto ok;
438 case IMM0_4BY4:
439 case IMM1_4BY4:
440 imm = nibs[3] << 2;
441 goto ok;
442 case IMM0_8:
443 case IMM1_8:
444 imm = (nibs[2] << 4) | nibs[3];
445 goto ok;
446 case PCRELIMM_8BY2:
447 imm = ((nibs[2] << 4) | nibs[3]) << 1;
448 relmask = ~(bfd_vma) 1;
449 goto ok;
450 case PCRELIMM_8BY4:
451 imm = ((nibs[2] << 4) | nibs[3]) << 2;
452 relmask = ~(bfd_vma) 3;
453 goto ok;
454 case IMM0_8BY2:
455 case IMM1_8BY2:
456 imm = ((nibs[2] << 4) | nibs[3]) << 1;
457 goto ok;
458 case IMM0_8BY4:
459 case IMM1_8BY4:
460 imm = ((nibs[2] << 4) | nibs[3]) << 2;
461 goto ok;
462 case REG_N:
463 rn = nibs[n];
464 break;
465 case REG_M:
466 rm = nibs[n];
467 break;
468 case REG_NM:
469 rn = (nibs[n] & 0xc) >> 2;
470 rm = (nibs[n] & 0x3);
471 break;
472 case REG_B:
473 rb = nibs[n] & 0x07;
474 break;
475 case SDT_REG_N:
476 /* sh-dsp: single data transfer. */
477 rn = nibs[n];
478 if ((rn & 0xc) != 4)
479 goto fail;
480 rn = rn & 0x3;
481 rn |= (!(rn & 2)) << 2;
482 break;
483 case PPI:
484 case REPEAT:
485 goto fail;
486 default:
487 abort ();
492 fprintf_fn (stream, "%s\t", op->name);
493 disp_pc = 0;
494 for (n = 0; n < 3 && op->arg[n] != A_END; n++)
496 if (n && op->arg[1] != A_END)
497 fprintf_fn (stream, ",");
498 switch (op->arg[n])
500 case A_IMM:
501 fprintf_fn (stream, "#%d", (char) (imm));
502 break;
503 case A_R0:
504 fprintf_fn (stream, "r0");
505 break;
506 case A_REG_N:
507 fprintf_fn (stream, "r%d", rn);
508 break;
509 case A_INC_N:
510 fprintf_fn (stream, "@r%d+", rn);
511 break;
512 case A_DEC_N:
513 fprintf_fn (stream, "@-r%d", rn);
514 break;
515 case A_IND_N:
516 fprintf_fn (stream, "@r%d", rn);
517 break;
518 case A_DISP_REG_N:
519 fprintf_fn (stream, "@(%d,r%d)", imm, rn);
520 break;
521 case A_PMOD_N:
522 fprintf_fn (stream, "@r%d+r8", rn);
523 break;
524 case A_REG_M:
525 fprintf_fn (stream, "r%d", rm);
526 break;
527 case A_INC_M:
528 fprintf_fn (stream, "@r%d+", rm);
529 break;
530 case A_DEC_M:
531 fprintf_fn (stream, "@-r%d", rm);
532 break;
533 case A_IND_M:
534 fprintf_fn (stream, "@r%d", rm);
535 break;
536 case A_DISP_REG_M:
537 fprintf_fn (stream, "@(%d,r%d)", imm, rm);
538 break;
539 case A_REG_B:
540 fprintf_fn (stream, "r%d_bank", rb);
541 break;
542 case A_DISP_PC:
543 disp_pc = 1;
544 disp_pc_addr = imm + 4 + (memaddr & relmask);
545 (*info->print_address_func) (disp_pc_addr, info);
546 break;
547 case A_IND_R0_REG_N:
548 fprintf_fn (stream, "@(r0,r%d)", rn);
549 break;
550 case A_IND_R0_REG_M:
551 fprintf_fn (stream, "@(r0,r%d)", rm);
552 break;
553 case A_DISP_GBR:
554 fprintf_fn (stream, "@(%d,gbr)", imm);
555 break;
556 case A_R0_GBR:
557 fprintf_fn (stream, "@(r0,gbr)");
558 break;
559 case A_BDISP12:
560 case A_BDISP8:
561 (*info->print_address_func) (imm + memaddr, info);
562 break;
563 case A_SR:
564 fprintf_fn (stream, "sr");
565 break;
566 case A_GBR:
567 fprintf_fn (stream, "gbr");
568 break;
569 case A_VBR:
570 fprintf_fn (stream, "vbr");
571 break;
572 case A_DSR:
573 fprintf_fn (stream, "dsr");
574 break;
575 case A_MOD:
576 fprintf_fn (stream, "mod");
577 break;
578 case A_RE:
579 fprintf_fn (stream, "re");
580 break;
581 case A_RS:
582 fprintf_fn (stream, "rs");
583 break;
584 case A_A0:
585 fprintf_fn (stream, "a0");
586 break;
587 case A_X0:
588 fprintf_fn (stream, "x0");
589 break;
590 case A_X1:
591 fprintf_fn (stream, "x1");
592 break;
593 case A_Y0:
594 fprintf_fn (stream, "y0");
595 break;
596 case A_Y1:
597 fprintf_fn (stream, "y1");
598 break;
599 case DSP_REG_M:
600 print_dsp_reg (rm, fprintf_fn, stream);
601 break;
602 case A_SSR:
603 fprintf_fn (stream, "ssr");
604 break;
605 case A_SPC:
606 fprintf_fn (stream, "spc");
607 break;
608 case A_MACH:
609 fprintf_fn (stream, "mach");
610 break;
611 case A_MACL:
612 fprintf_fn (stream, "macl");
613 break;
614 case A_PR:
615 fprintf_fn (stream, "pr");
616 break;
617 case A_SGR:
618 fprintf_fn (stream, "sgr");
619 break;
620 case A_DBR:
621 fprintf_fn (stream, "dbr");
622 break;
623 case F_REG_N:
624 fprintf_fn (stream, "fr%d", rn);
625 break;
626 case F_REG_M:
627 fprintf_fn (stream, "fr%d", rm);
628 break;
629 case DX_REG_N:
630 if (rn & 1)
632 fprintf_fn (stream, "xd%d", rn & ~1);
633 break;
635 case D_REG_N:
636 fprintf_fn (stream, "dr%d", rn);
637 break;
638 case DX_REG_M:
639 if (rm & 1)
641 fprintf_fn (stream, "xd%d", rm & ~1);
642 break;
644 case D_REG_M:
645 fprintf_fn (stream, "dr%d", rm);
646 break;
647 case FPSCR_M:
648 case FPSCR_N:
649 fprintf_fn (stream, "fpscr");
650 break;
651 case FPUL_M:
652 case FPUL_N:
653 fprintf_fn (stream, "fpul");
654 break;
655 case F_FR0:
656 fprintf_fn (stream, "fr0");
657 break;
658 case V_REG_N:
659 fprintf_fn (stream, "fv%d", rn * 4);
660 break;
661 case V_REG_M:
662 fprintf_fn (stream, "fv%d", rm * 4);
663 break;
664 case XMTRX_M4:
665 fprintf_fn (stream, "xmtrx");
666 break;
667 default:
668 abort ();
672 #if 0
673 /* This code prints instructions in delay slots on the same line
674 as the instruction which needs the delay slots. This can be
675 confusing, since other disassembler don't work this way, and
676 it means that the instructions are not all in a line. So I
677 disabled it. Ian. */
678 if (!(info->flags & 1)
679 && (op->name[0] == 'j'
680 || (op->name[0] == 'b'
681 && (op->name[1] == 'r'
682 || op->name[1] == 's'))
683 || (op->name[0] == 'r' && op->name[1] == 't')
684 || (op->name[0] == 'b' && op->name[2] == '.')))
686 info->flags |= 1;
687 fprintf_fn (stream, "\t(slot ");
688 print_insn_sh (memaddr + 2, info);
689 info->flags &= ~1;
690 fprintf_fn (stream, ")");
691 return 4;
693 #endif
695 if (disp_pc && strcmp (op->name, "mova") != 0)
697 int size;
698 bfd_byte bytes[4];
700 if (relmask == ~(bfd_vma) 1)
701 size = 2;
702 else
703 size = 4;
704 status = info->read_memory_func (disp_pc_addr, bytes, size, info);
705 if (status == 0)
707 unsigned int val;
709 if (size == 2)
711 if (info->endian == BFD_ENDIAN_LITTLE)
712 val = bfd_getl16 (bytes);
713 else
714 val = bfd_getb16 (bytes);
716 else
718 if (info->endian == BFD_ENDIAN_LITTLE)
719 val = bfd_getl32 (bytes);
720 else
721 val = bfd_getb32 (bytes);
723 fprintf_fn (stream, "\t! 0x%x", val);
727 return 2;
728 fail:
732 fprintf_fn (stream, ".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]);
733 return 2;