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