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