print_insn_sh cleanup:
[platform/upstream/binutils.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 }