daily update
[binutils.git] / opcodes / sh-dis.c
blobed472dc3045bc64eb56a7d919d2447dadff9003e
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 #define LITTLE_BIT 2
29 static void print_movxy
30 PARAMS ((sh_opcode_info *, int, int, fprintf_ftype, void *));
31 static void print_insn_ddt PARAMS ((int, struct disassemble_info *));
32 static void print_dsp_reg PARAMS ((int, fprintf_ftype, void *));
33 static void print_insn_ppi PARAMS ((int, struct disassemble_info *));
34 static int print_insn_shx PARAMS ((bfd_vma, struct disassemble_info *));
36 static void
37 print_movxy (op, rn, rm, fprintf_fn, stream)
38 sh_opcode_info *op;
39 int rn, rm;
40 fprintf_ftype fprintf_fn;
41 void *stream;
43 int n;
45 fprintf_fn (stream, "%s\t", op->name);
46 for (n = 0; n < 2; n++)
48 switch (op->arg[n])
50 case A_IND_N:
51 fprintf_fn (stream, "@r%d", rn);
52 break;
53 case A_INC_N:
54 fprintf_fn (stream, "@r%d+", rn);
55 break;
56 case A_PMOD_N:
57 fprintf_fn (stream, "@r%d+r8", rn);
58 break;
59 case A_PMODY_N:
60 fprintf_fn (stream, "@r%d+r9", rn);
61 break;
62 case DSP_REG_M:
63 fprintf_fn (stream, "a%c", '0' + rm);
64 break;
65 case DSP_REG_X:
66 fprintf_fn (stream, "x%c", '0' + rm);
67 break;
68 case DSP_REG_Y:
69 fprintf_fn (stream, "y%c", '0' + rm);
70 break;
71 default:
72 abort ();
74 if (n == 0)
75 fprintf_fn (stream, ",");
79 /* Print a double data transfer insn. INSN is just the lower three
80 nibbles of the insn, i.e. field a and the bit that indicates if
81 a parallel processing insn follows.
82 Return nonzero if a field b of a parallel processing insns follows. */
84 static void
85 print_insn_ddt (insn, info)
86 int insn;
87 struct disassemble_info *info;
89 fprintf_ftype fprintf_fn = info->fprintf_func;
90 void *stream = info->stream;
92 /* If this is just a nop, make sure to emit something. */
93 if (insn == 0x000)
94 fprintf_fn (stream, "nopx\tnopy");
96 /* If a parallel processing insn was printed before,
97 and we got a non-nop, emit a tab. */
98 if ((insn & 0x800) && (insn & 0x3ff))
99 fprintf_fn (stream, "\t");
101 /* Check if either the x or y part is invalid. */
102 if (((insn & 0xc) == 0 && (insn & 0x2a0))
103 || ((insn & 3) == 0 && (insn & 0x150)))
104 fprintf_fn (stream, ".word 0x%x", insn);
105 else
107 static sh_opcode_info *first_movx, *first_movy;
108 sh_opcode_info *opx, *opy;
109 unsigned int insn_x, insn_y;
111 if (! first_movx)
113 for (first_movx = sh_table; first_movx->nibbles[1] != MOVX;)
114 first_movx++;
115 for (first_movy = first_movx; first_movy->nibbles[1] != MOVY;)
116 first_movy++;
118 insn_x = (insn >> 2) & 0xb;
119 if (insn_x)
121 for (opx = first_movx; opx->nibbles[2] != insn_x;)
122 opx++;
123 print_movxy (opx, ((insn >> 9) & 1) + 4, (insn >> 7) & 1,
124 fprintf_fn, stream);
126 insn_y = (insn & 3) | ((insn >> 1) & 8);
127 if (insn_y)
129 if (insn_x)
130 fprintf_fn (stream, "\t");
131 for (opy = first_movy; opy->nibbles[2] != insn_y;)
132 opy++;
133 print_movxy (opy, ((insn >> 8) & 1) + 6, (insn >> 6) & 1,
134 fprintf_fn, stream);
139 static void
140 print_dsp_reg (rm, fprintf_fn, stream)
141 int rm;
142 fprintf_ftype fprintf_fn;
143 void *stream;
145 switch (rm)
147 case A_A1_NUM:
148 fprintf_fn (stream, "a1");
149 break;
150 case A_A0_NUM:
151 fprintf_fn (stream, "a0");
152 break;
153 case A_X0_NUM:
154 fprintf_fn (stream, "x0");
155 break;
156 case A_X1_NUM:
157 fprintf_fn (stream, "x1");
158 break;
159 case A_Y0_NUM:
160 fprintf_fn (stream, "y0");
161 break;
162 case A_Y1_NUM:
163 fprintf_fn (stream, "y1");
164 break;
165 case A_M0_NUM:
166 fprintf_fn (stream, "m0");
167 break;
168 case A_A1G_NUM:
169 fprintf_fn (stream, "a1g");
170 break;
171 case A_M1_NUM:
172 fprintf_fn (stream, "m1");
173 break;
174 case A_A0G_NUM:
175 fprintf_fn (stream, "a0g");
176 break;
177 default:
178 fprintf_fn (stream, "0x%x", rm);
179 break;
183 static void
184 print_insn_ppi (field_b, info)
185 int field_b;
186 struct disassemble_info *info;
188 static char *sx_tab[] = { "x0", "x1", "a0", "a1" };
189 static char *sy_tab[] = { "y0", "y1", "m0", "m1" };
190 fprintf_ftype fprintf_fn = info->fprintf_func;
191 void *stream = info->stream;
192 unsigned int nib1, nib2, nib3;
193 char *dc = NULL;
194 sh_opcode_info *op;
196 if ((field_b & 0xe800) == 0)
198 fprintf_fn (stream, "psh%c\t#%d,",
199 field_b & 0x1000 ? 'a' : 'l',
200 (field_b >> 4) & 127);
201 print_dsp_reg (field_b & 0xf, fprintf_fn, stream);
202 return;
204 if ((field_b & 0xc000) == 0x4000 && (field_b & 0x3000) != 0x1000)
206 static char *du_tab[] = { "x0", "y0", "a0", "a1" };
207 static char *se_tab[] = { "x0", "x1", "y0", "a1" };
208 static char *sf_tab[] = { "y0", "y1", "x0", "a1" };
209 static char *sg_tab[] = { "m0", "m1", "a0", "a1" };
211 if (field_b & 0x2000)
213 fprintf_fn (stream, "p%s %s,%s,%s\t",
214 (field_b & 0x1000) ? "add" : "sub",
215 sx_tab[(field_b >> 6) & 3],
216 sy_tab[(field_b >> 4) & 3],
217 du_tab[(field_b >> 0) & 3]);
219 fprintf_fn (stream, "pmuls%c%s,%s,%s",
220 field_b & 0x2000 ? ' ' : '\t',
221 se_tab[(field_b >> 10) & 3],
222 sf_tab[(field_b >> 8) & 3],
223 sg_tab[(field_b >> 2) & 3]);
224 return;
227 nib1 = PPIC;
228 nib2 = field_b >> 12 & 0xf;
229 nib3 = field_b >> 8 & 0xf;
230 switch (nib3 & 0x3)
232 case 0:
233 dc = "";
234 nib1 = PPI3;
235 break;
236 case 1:
237 dc = "";
238 break;
239 case 2:
240 dc = "dct ";
241 nib3 -= 1;
242 break;
243 case 3:
244 dc = "dcf ";
245 nib3 -= 2;
246 break;
248 for (op = sh_table; op->name; op++)
250 if (op->nibbles[1] == nib1
251 && op->nibbles[2] == nib2
252 && op->nibbles[3] == nib3)
254 int n;
256 fprintf_fn (stream, "%s%s\t", dc, op->name);
257 for (n = 0; n < 3 && op->arg[n] != A_END; n++)
259 if (n && op->arg[1] != A_END)
260 fprintf_fn (stream, ",");
261 switch (op->arg[n])
263 case DSP_REG_N:
264 print_dsp_reg (field_b & 0xf, fprintf_fn, stream);
265 break;
266 case DSP_REG_X:
267 fprintf_fn (stream, sx_tab[(field_b >> 6) & 3]);
268 break;
269 case DSP_REG_Y:
270 fprintf_fn (stream, sy_tab[(field_b >> 4) & 3]);
271 break;
272 case A_MACH:
273 fprintf_fn (stream, "mach");
274 break;
275 case A_MACL:
276 fprintf_fn (stream, "macl");
277 break;
278 default:
279 abort ();
282 return;
285 /* Not found. */
286 fprintf_fn (stream, ".word 0x%x", field_b);
289 static int
290 print_insn_shx (memaddr, info)
291 bfd_vma memaddr;
292 struct disassemble_info *info;
294 fprintf_ftype fprintf_fn = info->fprintf_func;
295 void *stream = info->stream;
296 unsigned char insn[2];
297 unsigned char nibs[4];
298 int status;
299 bfd_vma relmask = ~(bfd_vma) 0;
300 sh_opcode_info *op;
301 int target_arch;
303 switch (info->mach)
305 case bfd_mach_sh:
306 target_arch = arch_sh1;
307 break;
308 case bfd_mach_sh2:
309 target_arch = arch_sh2;
310 break;
311 case bfd_mach_sh_dsp:
312 target_arch = arch_sh_dsp;
313 break;
314 case bfd_mach_sh3:
315 target_arch = arch_sh3;
316 break;
317 case bfd_mach_sh3_dsp:
318 target_arch = arch_sh3_dsp;
319 break;
320 case bfd_mach_sh3e:
321 target_arch = arch_sh3e;
322 break;
323 case bfd_mach_sh4:
324 target_arch = arch_sh4;
325 break;
326 default:
327 abort ();
330 status = info->read_memory_func (memaddr, insn, 2, info);
332 if (status != 0)
334 info->memory_error_func (status, memaddr, info);
335 return -1;
338 if (info->flags & LITTLE_BIT)
340 nibs[0] = (insn[1] >> 4) & 0xf;
341 nibs[1] = insn[1] & 0xf;
343 nibs[2] = (insn[0] >> 4) & 0xf;
344 nibs[3] = insn[0] & 0xf;
346 else
348 nibs[0] = (insn[0] >> 4) & 0xf;
349 nibs[1] = insn[0] & 0xf;
351 nibs[2] = (insn[1] >> 4) & 0xf;
352 nibs[3] = insn[1] & 0xf;
355 if (nibs[0] == 0xf && (nibs[1] & 4) == 0 && target_arch & arch_sh_dsp_up)
357 if (nibs[1] & 8)
359 int field_b;
361 status = info->read_memory_func (memaddr + 2, insn, 2, info);
363 if (status != 0)
365 info->memory_error_func (status, memaddr + 2, info);
366 return -1;
369 if (info->flags & LITTLE_BIT)
370 field_b = insn[1] << 8 | insn[0];
371 else
372 field_b = insn[0] << 8 | insn[1];
374 print_insn_ppi (field_b, info);
375 print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info);
376 return 4;
378 print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info);
379 return 2;
381 for (op = sh_table; op->name; op++)
383 int n;
384 int imm = 0;
385 int rn = 0;
386 int rm = 0;
387 int rb = 0;
388 int disp_pc;
389 bfd_vma disp_pc_addr = 0;
391 if ((op->arch & target_arch) == 0)
392 goto fail;
393 for (n = 0; n < 4; n++)
395 int i = op->nibbles[n];
397 if (i < 16)
399 if (nibs[n] == i)
400 continue;
401 goto fail;
403 switch (i)
405 case BRANCH_8:
406 imm = (nibs[2] << 4) | (nibs[3]);
407 if (imm & 0x80)
408 imm |= ~0xff;
409 imm = ((char) imm) * 2 + 4;
410 goto ok;
411 case BRANCH_12:
412 imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]);
413 if (imm & 0x800)
414 imm |= ~0xfff;
415 imm = imm * 2 + 4;
416 goto ok;
417 case IMM0_4:
418 case IMM1_4:
419 imm = nibs[3];
420 goto ok;
421 case IMM0_4BY2:
422 case IMM1_4BY2:
423 imm = nibs[3] << 1;
424 goto ok;
425 case IMM0_4BY4:
426 case IMM1_4BY4:
427 imm = nibs[3] << 2;
428 goto ok;
429 case IMM0_8:
430 case IMM1_8:
431 imm = (nibs[2] << 4) | nibs[3];
432 goto ok;
433 case PCRELIMM_8BY2:
434 imm = ((nibs[2] << 4) | nibs[3]) << 1;
435 relmask = ~(bfd_vma) 1;
436 goto ok;
437 case PCRELIMM_8BY4:
438 imm = ((nibs[2] << 4) | nibs[3]) << 2;
439 relmask = ~(bfd_vma) 3;
440 goto ok;
441 case IMM0_8BY2:
442 case IMM1_8BY2:
443 imm = ((nibs[2] << 4) | nibs[3]) << 1;
444 goto ok;
445 case IMM0_8BY4:
446 case IMM1_8BY4:
447 imm = ((nibs[2] << 4) | nibs[3]) << 2;
448 goto ok;
449 case REG_N:
450 rn = nibs[n];
451 break;
452 case REG_M:
453 rm = nibs[n];
454 break;
455 case REG_NM:
456 rn = (nibs[n] & 0xc) >> 2;
457 rm = (nibs[n] & 0x3);
458 break;
459 case REG_B:
460 rb = nibs[n] & 0x07;
461 break;
462 case SDT_REG_N:
463 /* sh-dsp: single data transfer. */
464 rn = nibs[n];
465 if ((rn & 0xc) != 4)
466 goto fail;
467 rn = rn & 0x3;
468 rn |= (!(rn & 2)) << 2;
469 break;
470 case PPI:
471 case REPEAT:
472 goto fail;
473 default:
474 abort ();
479 fprintf_fn (stream, "%s\t", op->name);
480 disp_pc = 0;
481 for (n = 0; n < 3 && op->arg[n] != A_END; n++)
483 if (n && op->arg[1] != A_END)
484 fprintf_fn (stream, ",");
485 switch (op->arg[n])
487 case A_IMM:
488 fprintf_fn (stream, "#%d", (char) (imm));
489 break;
490 case A_R0:
491 fprintf_fn (stream, "r0");
492 break;
493 case A_REG_N:
494 fprintf_fn (stream, "r%d", rn);
495 break;
496 case A_INC_N:
497 fprintf_fn (stream, "@r%d+", rn);
498 break;
499 case A_DEC_N:
500 fprintf_fn (stream, "@-r%d", rn);
501 break;
502 case A_IND_N:
503 fprintf_fn (stream, "@r%d", rn);
504 break;
505 case A_DISP_REG_N:
506 fprintf_fn (stream, "@(%d,r%d)", imm, rn);
507 break;
508 case A_PMOD_N:
509 fprintf_fn (stream, "@r%d+r8", rn);
510 break;
511 case A_REG_M:
512 fprintf_fn (stream, "r%d", rm);
513 break;
514 case A_INC_M:
515 fprintf_fn (stream, "@r%d+", rm);
516 break;
517 case A_DEC_M:
518 fprintf_fn (stream, "@-r%d", rm);
519 break;
520 case A_IND_M:
521 fprintf_fn (stream, "@r%d", rm);
522 break;
523 case A_DISP_REG_M:
524 fprintf_fn (stream, "@(%d,r%d)", imm, rm);
525 break;
526 case A_REG_B:
527 fprintf_fn (stream, "r%d_bank", rb);
528 break;
529 case A_DISP_PC:
530 disp_pc = 1;
531 disp_pc_addr = imm + 4 + (memaddr & relmask);
532 (*info->print_address_func) (disp_pc_addr, info);
533 break;
534 case A_IND_R0_REG_N:
535 fprintf_fn (stream, "@(r0,r%d)", rn);
536 break;
537 case A_IND_R0_REG_M:
538 fprintf_fn (stream, "@(r0,r%d)", rm);
539 break;
540 case A_DISP_GBR:
541 fprintf_fn (stream, "@(%d,gbr)", imm);
542 break;
543 case A_R0_GBR:
544 fprintf_fn (stream, "@(r0,gbr)");
545 break;
546 case A_BDISP12:
547 case A_BDISP8:
548 (*info->print_address_func) (imm + memaddr, info);
549 break;
550 case A_SR:
551 fprintf_fn (stream, "sr");
552 break;
553 case A_GBR:
554 fprintf_fn (stream, "gbr");
555 break;
556 case A_VBR:
557 fprintf_fn (stream, "vbr");
558 break;
559 case A_DSR:
560 fprintf_fn (stream, "dsr");
561 break;
562 case A_MOD:
563 fprintf_fn (stream, "mod");
564 break;
565 case A_RE:
566 fprintf_fn (stream, "re");
567 break;
568 case A_RS:
569 fprintf_fn (stream, "rs");
570 break;
571 case A_A0:
572 fprintf_fn (stream, "a0");
573 break;
574 case A_X0:
575 fprintf_fn (stream, "x0");
576 break;
577 case A_X1:
578 fprintf_fn (stream, "x1");
579 break;
580 case A_Y0:
581 fprintf_fn (stream, "y0");
582 break;
583 case A_Y1:
584 fprintf_fn (stream, "y1");
585 break;
586 case DSP_REG_M:
587 print_dsp_reg (rm, fprintf_fn, stream);
588 break;
589 case A_SSR:
590 fprintf_fn (stream, "ssr");
591 break;
592 case A_SPC:
593 fprintf_fn (stream, "spc");
594 break;
595 case A_MACH:
596 fprintf_fn (stream, "mach");
597 break;
598 case A_MACL:
599 fprintf_fn (stream, "macl");
600 break;
601 case A_PR:
602 fprintf_fn (stream, "pr");
603 break;
604 case A_SGR:
605 fprintf_fn (stream, "sgr");
606 break;
607 case A_DBR:
608 fprintf_fn (stream, "dbr");
609 break;
610 case F_REG_N:
611 fprintf_fn (stream, "fr%d", rn);
612 break;
613 case F_REG_M:
614 fprintf_fn (stream, "fr%d", rm);
615 break;
616 case DX_REG_N:
617 if (rn & 1)
619 fprintf_fn (stream, "xd%d", rn & ~1);
620 break;
622 case D_REG_N:
623 fprintf_fn (stream, "dr%d", rn);
624 break;
625 case DX_REG_M:
626 if (rm & 1)
628 fprintf_fn (stream, "xd%d", rm & ~1);
629 break;
631 case D_REG_M:
632 fprintf_fn (stream, "dr%d", rm);
633 break;
634 case FPSCR_M:
635 case FPSCR_N:
636 fprintf_fn (stream, "fpscr");
637 break;
638 case FPUL_M:
639 case FPUL_N:
640 fprintf_fn (stream, "fpul");
641 break;
642 case F_FR0:
643 fprintf_fn (stream, "fr0");
644 break;
645 case V_REG_N:
646 fprintf_fn (stream, "fv%d", rn * 4);
647 break;
648 case V_REG_M:
649 fprintf_fn (stream, "fv%d", rm * 4);
650 break;
651 case XMTRX_M4:
652 fprintf_fn (stream, "xmtrx");
653 break;
654 default:
655 abort ();
659 #if 0
660 /* This code prints instructions in delay slots on the same line
661 as the instruction which needs the delay slots. This can be
662 confusing, since other disassembler don't work this way, and
663 it means that the instructions are not all in a line. So I
664 disabled it. Ian. */
665 if (!(info->flags & 1)
666 && (op->name[0] == 'j'
667 || (op->name[0] == 'b'
668 && (op->name[1] == 'r'
669 || op->name[1] == 's'))
670 || (op->name[0] == 'r' && op->name[1] == 't')
671 || (op->name[0] == 'b' && op->name[2] == '.')))
673 info->flags |= 1;
674 fprintf_fn (stream, "\t(slot ");
675 print_insn_shx (memaddr + 2, info);
676 info->flags &= ~1;
677 fprintf_fn (stream, ")");
678 return 4;
680 #endif
682 if (disp_pc && strcmp (op->name, "mova") != 0)
684 int size;
685 bfd_byte bytes[4];
687 if (relmask == ~(bfd_vma) 1)
688 size = 2;
689 else
690 size = 4;
691 status = info->read_memory_func (disp_pc_addr, bytes, size, info);
692 if (status == 0)
694 unsigned int val;
696 if (size == 2)
698 if ((info->flags & LITTLE_BIT) != 0)
699 val = bfd_getl16 (bytes);
700 else
701 val = bfd_getb16 (bytes);
703 else
705 if ((info->flags & LITTLE_BIT) != 0)
706 val = bfd_getl32 (bytes);
707 else
708 val = bfd_getb32 (bytes);
710 fprintf_fn (stream, "\t! 0x%x", val);
714 return 2;
715 fail:
719 fprintf_fn (stream, ".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]);
720 return 2;
724 print_insn_shl (memaddr, info)
725 bfd_vma memaddr;
726 struct disassemble_info *info;
728 int r;
730 info->flags = LITTLE_BIT;
731 r = print_insn_shx (memaddr, info);
732 return r;
736 print_insn_sh (memaddr, info)
737 bfd_vma memaddr;
738 struct disassemble_info *info;
740 int r;
742 info->flags = 0;
743 r = print_insn_shx (memaddr, info);
744 return r;