This commit was generated by cvs2svn to track changes on a CVS vendor
[platform/upstream/binutils.git] / opcodes / sh-dis.c
1 /* Disassemble SH instructions.
2    Copyright (C) 1993, 94, 95, 96, 97, 1998 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 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;    
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;
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;
495             case A_PMOD_N:
496               fprintf_fn (stream, "@r%d+r8", rn);       
497               break;
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;
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;
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;
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
711 int 
712 print_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
723 int 
724 print_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 }