[ gas/ChangeLog ]
[platform/upstream/binutils.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 }