print_insn_sh cleanup:
[deliverable/binutils-gdb.git] / opcodes / sh-dis.c
1 /* Disassemble SH instructions.
2 Copyright 1993, 1994, 1995, 1997, 1998, 2000, 2001
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 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 *));
32
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;
39 {
40 int n;
41
42 fprintf_fn (stream, "%s\t", op->name);
43 for (n = 0; n < 2; n++)
44 {
45 switch (op->arg[n])
46 {
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 ();
70 }
71 if (n == 0)
72 fprintf_fn (stream, ",");
73 }
74 }
75
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. */
80
81 static void
82 print_insn_ddt (insn, info)
83 int insn;
84 struct disassemble_info *info;
85 {
86 fprintf_ftype fprintf_fn = info->fprintf_func;
87 void *stream = info->stream;
88
89 /* If this is just a nop, make sure to emit something. */
90 if (insn == 0x000)
91 fprintf_fn (stream, "nopx\tnopy");
92
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");
97
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
103 {
104 static sh_opcode_info *first_movx, *first_movy;
105 sh_opcode_info *opx, *opy;
106 unsigned int insn_x, insn_y;
107
108 if (! first_movx)
109 {
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++;
114 }
115 insn_x = (insn >> 2) & 0xb;
116 if (insn_x)
117 {
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);
122 }
123 insn_y = (insn & 3) | ((insn >> 1) & 8);
124 if (insn_y)
125 {
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);
132 }
133 }
134 }
135
136 static void
137 print_dsp_reg (rm, fprintf_fn, stream)
138 int rm;
139 fprintf_ftype fprintf_fn;
140 void *stream;
141 {
142 switch (rm)
143 {
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;
177 }
178 }
179
180 static void
181 print_insn_ppi (field_b, info)
182 int field_b;
183 struct disassemble_info *info;
184 {
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;
192
193 if ((field_b & 0xe800) == 0)
194 {
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;
200 }
201 if ((field_b & 0xc000) == 0x4000 && (field_b & 0x3000) != 0x1000)
202 {
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" };
207
208 if (field_b & 0x2000)
209 {
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]);
215 }
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;
222 }
223
224 nib1 = PPIC;
225 nib2 = field_b >> 12 & 0xf;
226 nib3 = field_b >> 8 & 0xf;
227 switch (nib3 & 0x3)
228 {
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;
244 }
245 for (op = sh_table; op->name; op++)
246 {
247 if (op->nibbles[1] == nib1
248 && op->nibbles[2] == nib2
249 && op->nibbles[3] == nib3)
250 {
251 int n;
252
253 fprintf_fn (stream, "%s%s\t", dc, op->name);
254 for (n = 0; n < 3 && op->arg[n] != A_END; n++)
255 {
256 if (n && op->arg[1] != A_END)
257 fprintf_fn (stream, ",");
258 switch (op->arg[n])
259 {
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 ();
277 }
278 }
279 return;
280 }
281 }
282 /* Not found. */
283 fprintf_fn (stream, ".word 0x%x", field_b);
284 }
285
286 int
287 print_insn_sh (memaddr, info)
288 bfd_vma memaddr;
289 struct disassemble_info *info;
290 {
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;
299
300 switch (info->mach)
301 {
302 case bfd_mach_sh:
303 target_arch = arch_sh1;
304 break;
305 case bfd_mach_sh2:
306 target_arch = arch_sh2;
307 break;
308 case bfd_mach_sh_dsp:
309 target_arch = arch_sh_dsp;
310 break;
311 case bfd_mach_sh3:
312 target_arch = arch_sh3;
313 break;
314 case bfd_mach_sh3_dsp:
315 target_arch = arch_sh3_dsp;
316 break;
317 case bfd_mach_sh3e:
318 target_arch = arch_sh3e;
319 break;
320 case bfd_mach_sh4:
321 target_arch = arch_sh4;
322 break;
323 case bfd_mach_sh5:
324 #ifdef INCLUDE_SHMEDIA
325 status = print_insn_sh64 (memaddr, info);
326 if (status != -2)
327 return status;
328 #endif
329 /* When we get here for sh64, it's because we want to disassemble
330 SHcompact, i.e. arch_sh4. */
331 target_arch = arch_sh4;
332 break;
333 default:
334 abort ();
335 }
336
337 status = info->read_memory_func (memaddr, insn, 2, info);
338
339 if (status != 0)
340 {
341 info->memory_error_func (status, memaddr, info);
342 return -1;
343 }
344
345 if (info->endian == BFD_ENDIAN_LITTLE)
346 {
347 nibs[0] = (insn[1] >> 4) & 0xf;
348 nibs[1] = insn[1] & 0xf;
349
350 nibs[2] = (insn[0] >> 4) & 0xf;
351 nibs[3] = insn[0] & 0xf;
352 }
353 else
354 {
355 nibs[0] = (insn[0] >> 4) & 0xf;
356 nibs[1] = insn[0] & 0xf;
357
358 nibs[2] = (insn[1] >> 4) & 0xf;
359 nibs[3] = insn[1] & 0xf;
360 }
361
362 if (nibs[0] == 0xf && (nibs[1] & 4) == 0 && target_arch & arch_sh_dsp_up)
363 {
364 if (nibs[1] & 8)
365 {
366 int field_b;
367
368 status = info->read_memory_func (memaddr + 2, insn, 2, info);
369
370 if (status != 0)
371 {
372 info->memory_error_func (status, memaddr + 2, info);
373 return -1;
374 }
375
376 if (info->endian == BFD_ENDIAN_LITTLE)
377 field_b = insn[1] << 8 | insn[0];
378 else
379 field_b = insn[0] << 8 | insn[1];
380
381 print_insn_ppi (field_b, info);
382 print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info);
383 return 4;
384 }
385 print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info);
386 return 2;
387 }
388 for (op = sh_table; op->name; op++)
389 {
390 int n;
391 int imm = 0;
392 int rn = 0;
393 int rm = 0;
394 int rb = 0;
395 int disp_pc;
396 bfd_vma disp_pc_addr = 0;
397
398 if ((op->arch & target_arch) == 0)
399 goto fail;
400 for (n = 0; n < 4; n++)
401 {
402 int i = op->nibbles[n];
403
404 if (i < 16)
405 {
406 if (nibs[n] == i)
407 continue;
408 goto fail;
409 }
410 switch (i)
411 {
412 case BRANCH_8:
413 imm = (nibs[2] << 4) | (nibs[3]);
414 if (imm & 0x80)
415 imm |= ~0xff;
416 imm = ((char) imm) * 2 + 4;
417 goto ok;
418 case BRANCH_12:
419 imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]);
420 if (imm & 0x800)
421 imm |= ~0xfff;
422 imm = imm * 2 + 4;
423 goto ok;
424 case IMM0_4:
425 case IMM1_4:
426 imm = nibs[3];
427 goto ok;
428 case IMM0_4BY2:
429 case IMM1_4BY2:
430 imm = nibs[3] << 1;
431 goto ok;
432 case IMM0_4BY4:
433 case IMM1_4BY4:
434 imm = nibs[3] << 2;
435 goto ok;
436 case IMM0_8:
437 case IMM1_8:
438 imm = (nibs[2] << 4) | nibs[3];
439 goto ok;
440 case PCRELIMM_8BY2:
441 imm = ((nibs[2] << 4) | nibs[3]) << 1;
442 relmask = ~(bfd_vma) 1;
443 goto ok;
444 case PCRELIMM_8BY4:
445 imm = ((nibs[2] << 4) | nibs[3]) << 2;
446 relmask = ~(bfd_vma) 3;
447 goto ok;
448 case IMM0_8BY2:
449 case IMM1_8BY2:
450 imm = ((nibs[2] << 4) | nibs[3]) << 1;
451 goto ok;
452 case IMM0_8BY4:
453 case IMM1_8BY4:
454 imm = ((nibs[2] << 4) | nibs[3]) << 2;
455 goto ok;
456 case REG_N:
457 rn = nibs[n];
458 break;
459 case REG_M:
460 rm = nibs[n];
461 break;
462 case REG_NM:
463 rn = (nibs[n] & 0xc) >> 2;
464 rm = (nibs[n] & 0x3);
465 break;
466 case REG_B:
467 rb = nibs[n] & 0x07;
468 break;
469 case SDT_REG_N:
470 /* sh-dsp: single data transfer. */
471 rn = nibs[n];
472 if ((rn & 0xc) != 4)
473 goto fail;
474 rn = rn & 0x3;
475 rn |= (!(rn & 2)) << 2;
476 break;
477 case PPI:
478 case REPEAT:
479 goto fail;
480 default:
481 abort ();
482 }
483 }
484
485 ok:
486 fprintf_fn (stream, "%s\t", op->name);
487 disp_pc = 0;
488 for (n = 0; n < 3 && op->arg[n] != A_END; n++)
489 {
490 if (n && op->arg[1] != A_END)
491 fprintf_fn (stream, ",");
492 switch (op->arg[n])
493 {
494 case A_IMM:
495 fprintf_fn (stream, "#%d", (char) (imm));
496 break;
497 case A_R0:
498 fprintf_fn (stream, "r0");
499 break;
500 case A_REG_N:
501 fprintf_fn (stream, "r%d", rn);
502 break;
503 case A_INC_N:
504 fprintf_fn (stream, "@r%d+", rn);
505 break;
506 case A_DEC_N:
507 fprintf_fn (stream, "@-r%d", rn);
508 break;
509 case A_IND_N:
510 fprintf_fn (stream, "@r%d", rn);
511 break;
512 case A_DISP_REG_N:
513 fprintf_fn (stream, "@(%d,r%d)", imm, rn);
514 break;
515 case A_PMOD_N:
516 fprintf_fn (stream, "@r%d+r8", rn);
517 break;
518 case A_REG_M:
519 fprintf_fn (stream, "r%d", rm);
520 break;
521 case A_INC_M:
522 fprintf_fn (stream, "@r%d+", rm);
523 break;
524 case A_DEC_M:
525 fprintf_fn (stream, "@-r%d", rm);
526 break;
527 case A_IND_M:
528 fprintf_fn (stream, "@r%d", rm);
529 break;
530 case A_DISP_REG_M:
531 fprintf_fn (stream, "@(%d,r%d)", imm, rm);
532 break;
533 case A_REG_B:
534 fprintf_fn (stream, "r%d_bank", rb);
535 break;
536 case A_DISP_PC:
537 disp_pc = 1;
538 disp_pc_addr = imm + 4 + (memaddr & relmask);
539 (*info->print_address_func) (disp_pc_addr, info);
540 break;
541 case A_IND_R0_REG_N:
542 fprintf_fn (stream, "@(r0,r%d)", rn);
543 break;
544 case A_IND_R0_REG_M:
545 fprintf_fn (stream, "@(r0,r%d)", rm);
546 break;
547 case A_DISP_GBR:
548 fprintf_fn (stream, "@(%d,gbr)", imm);
549 break;
550 case A_R0_GBR:
551 fprintf_fn (stream, "@(r0,gbr)");
552 break;
553 case A_BDISP12:
554 case A_BDISP8:
555 (*info->print_address_func) (imm + memaddr, info);
556 break;
557 case A_SR:
558 fprintf_fn (stream, "sr");
559 break;
560 case A_GBR:
561 fprintf_fn (stream, "gbr");
562 break;
563 case A_VBR:
564 fprintf_fn (stream, "vbr");
565 break;
566 case A_DSR:
567 fprintf_fn (stream, "dsr");
568 break;
569 case A_MOD:
570 fprintf_fn (stream, "mod");
571 break;
572 case A_RE:
573 fprintf_fn (stream, "re");
574 break;
575 case A_RS:
576 fprintf_fn (stream, "rs");
577 break;
578 case A_A0:
579 fprintf_fn (stream, "a0");
580 break;
581 case A_X0:
582 fprintf_fn (stream, "x0");
583 break;
584 case A_X1:
585 fprintf_fn (stream, "x1");
586 break;
587 case A_Y0:
588 fprintf_fn (stream, "y0");
589 break;
590 case A_Y1:
591 fprintf_fn (stream, "y1");
592 break;
593 case DSP_REG_M:
594 print_dsp_reg (rm, fprintf_fn, stream);
595 break;
596 case A_SSR:
597 fprintf_fn (stream, "ssr");
598 break;
599 case A_SPC:
600 fprintf_fn (stream, "spc");
601 break;
602 case A_MACH:
603 fprintf_fn (stream, "mach");
604 break;
605 case A_MACL:
606 fprintf_fn (stream, "macl");
607 break;
608 case A_PR:
609 fprintf_fn (stream, "pr");
610 break;
611 case A_SGR:
612 fprintf_fn (stream, "sgr");
613 break;
614 case A_DBR:
615 fprintf_fn (stream, "dbr");
616 break;
617 case F_REG_N:
618 fprintf_fn (stream, "fr%d", rn);
619 break;
620 case F_REG_M:
621 fprintf_fn (stream, "fr%d", rm);
622 break;
623 case DX_REG_N:
624 if (rn & 1)
625 {
626 fprintf_fn (stream, "xd%d", rn & ~1);
627 break;
628 }
629 case D_REG_N:
630 fprintf_fn (stream, "dr%d", rn);
631 break;
632 case DX_REG_M:
633 if (rm & 1)
634 {
635 fprintf_fn (stream, "xd%d", rm & ~1);
636 break;
637 }
638 case D_REG_M:
639 fprintf_fn (stream, "dr%d", rm);
640 break;
641 case FPSCR_M:
642 case FPSCR_N:
643 fprintf_fn (stream, "fpscr");
644 break;
645 case FPUL_M:
646 case FPUL_N:
647 fprintf_fn (stream, "fpul");
648 break;
649 case F_FR0:
650 fprintf_fn (stream, "fr0");
651 break;
652 case V_REG_N:
653 fprintf_fn (stream, "fv%d", rn * 4);
654 break;
655 case V_REG_M:
656 fprintf_fn (stream, "fv%d", rm * 4);
657 break;
658 case XMTRX_M4:
659 fprintf_fn (stream, "xmtrx");
660 break;
661 default:
662 abort ();
663 }
664 }
665
666 #if 0
667 /* This code prints instructions in delay slots on the same line
668 as the instruction which needs the delay slots. This can be
669 confusing, since other disassembler don't work this way, and
670 it means that the instructions are not all in a line. So I
671 disabled it. Ian. */
672 if (!(info->flags & 1)
673 && (op->name[0] == 'j'
674 || (op->name[0] == 'b'
675 && (op->name[1] == 'r'
676 || op->name[1] == 's'))
677 || (op->name[0] == 'r' && op->name[1] == 't')
678 || (op->name[0] == 'b' && op->name[2] == '.')))
679 {
680 info->flags |= 1;
681 fprintf_fn (stream, "\t(slot ");
682 print_insn_sh (memaddr + 2, info);
683 info->flags &= ~1;
684 fprintf_fn (stream, ")");
685 return 4;
686 }
687 #endif
688
689 if (disp_pc && strcmp (op->name, "mova") != 0)
690 {
691 int size;
692 bfd_byte bytes[4];
693
694 if (relmask == ~(bfd_vma) 1)
695 size = 2;
696 else
697 size = 4;
698 status = info->read_memory_func (disp_pc_addr, bytes, size, info);
699 if (status == 0)
700 {
701 unsigned int val;
702
703 if (size == 2)
704 {
705 if (info->endian == BFD_ENDIAN_LITTLE)
706 val = bfd_getl16 (bytes);
707 else
708 val = bfd_getb16 (bytes);
709 }
710 else
711 {
712 if (info->endian == BFD_ENDIAN_LITTLE)
713 val = bfd_getl32 (bytes);
714 else
715 val = bfd_getb32 (bytes);
716 }
717 fprintf_fn (stream, "\t! 0x%x", val);
718 }
719 }
720
721 return 2;
722 fail:
723 ;
724
725 }
726 fprintf_fn (stream, ".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]);
727 return 2;
728 }
This page took 0.127544 seconds and 5 git commands to generate.