bfd:
[deliverable/binutils-gdb.git] / opcodes / sh-dis.c
CommitLineData
252b5132
RH
1/* Disassemble SH instructions.
2 Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
3
4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, 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
d4845d57
JR
27static void
28print_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. */
74static void
75print_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
127static void
128print_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
171static void
172print_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
252b5132
RH
277static int
278print_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;
d4845d57
JR
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 }
252b5132
RH
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
d4845d57
JR
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 }
252b5132
RH
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
d4845d57
JR
379 if ((op->arch & target_arch) == 0)
380 goto fail;
252b5132
RH
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 IMM_4:
406 imm = nibs[3];
407 goto ok;
408 case IMM_4BY2:
409 imm = nibs[3] <<1;
410 goto ok;
411 case IMM_4BY4:
412 imm = nibs[3] <<2;
413 goto ok;
414 case IMM_8:
415 imm = (nibs[2] << 4) | nibs[3];
416 goto ok;
417 case PCRELIMM_8BY2:
418 imm = ((nibs[2] << 4) | nibs[3]) <<1;
419 relmask = ~ (bfd_vma) 1;
420 goto ok;
421 case PCRELIMM_8BY4:
422 imm = ((nibs[2] << 4) | nibs[3]) <<2;
423 relmask = ~ (bfd_vma) 3;
424 goto ok;
425 case IMM_8BY2:
426 imm = ((nibs[2] << 4) | nibs[3]) <<1;
427 goto ok;
428 case IMM_8BY4:
429 imm = ((nibs[2] << 4) | nibs[3]) <<2;
430 goto ok;
431 case DISP_8:
432 imm = (nibs[2] << 4) | (nibs[3]);
433 goto ok;
434 case DISP_4:
435 imm = nibs[3];
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;
d4845d57
JR
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 goto fail;
252b5132
RH
460 default:
461 abort();
462 }
463 }
464
465 ok:
466 fprintf_fn (stream,"%s\t", op->name);
467 disp_pc = 0;
468 for (n = 0; n < 3 && op->arg[n] != A_END; n++)
469 {
470 if (n && op->arg[1] != A_END)
471 fprintf_fn (stream, ",");
472 switch (op->arg[n])
473 {
474 case A_IMM:
475 fprintf_fn (stream, "#%d", (char)(imm));
476 break;
477 case A_R0:
478 fprintf_fn (stream, "r0");
479 break;
480 case A_REG_N:
481 fprintf_fn (stream, "r%d", rn);
482 break;
483 case A_INC_N:
484 fprintf_fn (stream, "@r%d+", rn);
485 break;
486 case A_DEC_N:
487 fprintf_fn (stream, "@-r%d", rn);
488 break;
489 case A_IND_N:
490 fprintf_fn (stream, "@r%d", rn);
491 break;
492 case A_DISP_REG_N:
493 fprintf_fn (stream, "@(%d,r%d)", imm, rn);
494 break;
d4845d57
JR
495 case A_PMOD_N:
496 fprintf_fn (stream, "@r%d+r8", rn);
497 break;
252b5132
RH
498 case A_REG_M:
499 fprintf_fn (stream, "r%d", rm);
500 break;
501 case A_INC_M:
502 fprintf_fn (stream, "@r%d+", rm);
503 break;
504 case A_DEC_M:
505 fprintf_fn (stream, "@-r%d", rm);
506 break;
507 case A_IND_M:
508 fprintf_fn (stream, "@r%d", rm);
509 break;
510 case A_DISP_REG_M:
511 fprintf_fn (stream, "@(%d,r%d)", imm, rm);
512 break;
513 case A_REG_B:
514 fprintf_fn (stream, "r%d_bank", rb);
515 break;
516 case A_DISP_PC:
517 disp_pc = 1;
518 disp_pc_addr = imm + 4 + (memaddr & relmask);
519 (*info->print_address_func) (disp_pc_addr, info);
520 break;
521 case A_IND_R0_REG_N:
522 fprintf_fn (stream, "@(r0,r%d)", rn);
523 break;
524 case A_IND_R0_REG_M:
525 fprintf_fn (stream, "@(r0,r%d)", rm);
526 break;
527 case A_DISP_GBR:
528 fprintf_fn (stream, "@(%d,gbr)",imm);
529 break;
530 case A_R0_GBR:
531 fprintf_fn (stream, "@(r0,gbr)");
532 break;
533 case A_BDISP12:
534 case A_BDISP8:
535 (*info->print_address_func) (imm + memaddr, info);
536 break;
537 case A_SR:
538 fprintf_fn (stream, "sr");
539 break;
540 case A_GBR:
541 fprintf_fn (stream, "gbr");
542 break;
543 case A_VBR:
544 fprintf_fn (stream, "vbr");
545 break;
d4845d57
JR
546 case A_DSR:
547 fprintf_fn (stream, "dsr");
548 break;
549 case A_MOD:
550 fprintf_fn (stream, "mod");
551 break;
552 case A_RE:
553 fprintf_fn (stream, "re");
554 break;
555 case A_RS:
556 fprintf_fn (stream, "rs");
557 break;
558 case A_A0:
559 fprintf_fn (stream, "a0");
560 break;
561 case A_X0:
562 fprintf_fn (stream, "x0");
563 break;
564 case A_X1:
565 fprintf_fn (stream, "x1");
566 break;
567 case A_Y0:
568 fprintf_fn (stream, "y0");
569 break;
570 case A_Y1:
571 fprintf_fn (stream, "y1");
572 break;
573 case DSP_REG_M:
574 print_dsp_reg (rm, fprintf_fn, stream);
575 break;
252b5132
RH
576 case A_SSR:
577 fprintf_fn (stream, "ssr");
578 break;
579 case A_SPC:
580 fprintf_fn (stream, "spc");
581 break;
582 case A_MACH:
583 fprintf_fn (stream, "mach");
584 break;
585 case A_MACL:
586 fprintf_fn (stream ,"macl");
587 break;
588 case A_PR:
589 fprintf_fn (stream, "pr");
590 break;
591 case A_SGR:
592 fprintf_fn (stream, "sgr");
593 break;
594 case A_DBR:
595 fprintf_fn (stream, "dbr");
596 break;
252b5132
RH
597 case F_REG_N:
598 fprintf_fn (stream, "fr%d", rn);
599 break;
600 case F_REG_M:
601 fprintf_fn (stream, "fr%d", rm);
602 break;
603 case DX_REG_N:
604 if (rn & 1)
605 {
606 fprintf_fn (stream, "xd%d", rn & ~1);
607 break;
608 }
609 d_reg_n:
610 case D_REG_N:
611 fprintf_fn (stream, "dr%d", rn);
612 break;
613 case DX_REG_M:
614 if (rm & 1)
615 {
616 fprintf_fn (stream, "xd%d", rm & ~1);
617 break;
618 }
619 case D_REG_M:
620 fprintf_fn (stream, "dr%d", rm);
621 break;
622 case FPSCR_M:
623 case FPSCR_N:
624 fprintf_fn (stream, "fpscr");
625 break;
626 case FPUL_M:
627 case FPUL_N:
628 fprintf_fn (stream, "fpul");
629 break;
630 case F_FR0:
631 fprintf_fn (stream, "fr0");
632 break;
633 case V_REG_N:
634 fprintf_fn (stream, "fv%d", rn*4);
635 break;
636 case V_REG_M:
637 fprintf_fn (stream, "fv%d", rm*4);
638 break;
639 case XMTRX_M4:
640 fprintf_fn (stream, "xmtrx");
641 break;
642 default:
643 abort();
644 }
645 }
646
647#if 0
648 /* This code prints instructions in delay slots on the same line
649 as the instruction which needs the delay slots. This can be
650 confusing, since other disassembler don't work this way, and
651 it means that the instructions are not all in a line. So I
652 disabled it. Ian. */
653 if (!(info->flags & 1)
654 && (op->name[0] == 'j'
655 || (op->name[0] == 'b'
656 && (op->name[1] == 'r'
657 || op->name[1] == 's'))
658 || (op->name[0] == 'r' && op->name[1] == 't')
659 || (op->name[0] == 'b' && op->name[2] == '.')))
660 {
661 info->flags |= 1;
662 fprintf_fn (stream, "\t(slot ");
663 print_insn_shx (memaddr + 2, info);
664 info->flags &= ~1;
665 fprintf_fn (stream, ")");
666 return 4;
667 }
668#endif
669
670 if (disp_pc && strcmp (op->name, "mova") != 0)
671 {
672 int size;
673 bfd_byte bytes[4];
674
675 if (relmask == ~ (bfd_vma) 1)
676 size = 2;
677 else
678 size = 4;
679 status = info->read_memory_func (disp_pc_addr, bytes, size, info);
680 if (status == 0)
681 {
682 unsigned int val;
683
684 if (size == 2)
685 {
686 if ((info->flags & LITTLE_BIT) != 0)
687 val = bfd_getl16 (bytes);
688 else
689 val = bfd_getb16 (bytes);
690 }
691 else
692 {
693 if ((info->flags & LITTLE_BIT) != 0)
694 val = bfd_getl32 (bytes);
695 else
696 val = bfd_getb32 (bytes);
697 }
698 fprintf_fn (stream, "\t! 0x%x", val);
699 }
700 }
701
702 return 2;
703 fail:
704 ;
705
706 }
707 fprintf_fn (stream, ".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]);
708 return 2;
709}
710
711int
712print_insn_shl (memaddr, info)
713 bfd_vma memaddr;
714 struct disassemble_info *info;
715{
716 int r;
717
718 info->flags = LITTLE_BIT;
719 r = print_insn_shx (memaddr, info);
720 return r;
721}
722
723int
724print_insn_sh (memaddr, info)
725 bfd_vma memaddr;
726 struct disassemble_info *info;
727{
728 int r;
729
730 info->flags = 0;
731 r = print_insn_shx (memaddr, info);
732 return r;
733}
This page took 0.0820419999999999 seconds and 4 git commands to generate.