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