2000-08-08 Jason Eckhardt <jle@cygnus.com>
[external/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 #include "sysdep.h"
20 #define STATIC_TABLE
21 #define DEFINE_TABLE
22
23 #include "sh-opc.h"
24 #include "dis-asm.h"
25
26 #define LITTLE_BIT 2
27
28 static void
29 print_movxy (op, rn, rm, fprintf_fn, stream)
30      sh_opcode_info *op;
31      int rn, rm;
32      fprintf_ftype fprintf_fn;
33      void *stream;
34 {
35   int n;
36
37   fprintf_fn (stream,"%s\t", op->name);
38   for (n = 0; n < 2; n++)
39     {
40       switch (op->arg[n])
41         {
42         case A_IND_N:
43           fprintf_fn (stream, "@r%d", rn);      
44           break;
45         case A_INC_N:
46           fprintf_fn (stream, "@r%d+", rn);     
47           break;
48         case A_PMOD_N:
49           fprintf_fn (stream, "@r%d+r8", rn);   
50           break;
51         case A_PMODY_N:
52           fprintf_fn (stream, "@r%d+r9", rn);   
53           break;
54         case DSP_REG_M:
55           fprintf_fn (stream, "a%c", '0' + rm);
56           break;
57         case DSP_REG_X:
58           fprintf_fn (stream, "x%c", '0' + rm);
59           break;
60         case DSP_REG_Y:
61           fprintf_fn (stream, "y%c", '0' + rm);
62           break;
63         default:
64           abort ();
65         }
66       if (n == 0)
67         fprintf_fn (stream, ",");       
68     }
69 }
70
71 /* Print a double data transfer insn.  INSN is just the lower three
72    nibbles of the insn, i.e. field a and the bit that indicates if
73    a parallel processing insn follows.
74    Return nonzero if a field b of a parallel processing insns follows.  */
75 static void
76 print_insn_ddt (insn, info)
77      int insn;
78      struct disassemble_info *info;
79 {
80   fprintf_ftype fprintf_fn = info->fprintf_func;
81   void *stream = info->stream;
82
83   /* If this is just a nop, make sure to emit something.  */
84   if (insn == 0x000)
85     fprintf_fn (stream, "nopx\tnopy");
86
87   /* If a parallel processing insn was printed before,
88      and we got a non-nop, emit a tab.  */
89   if ((insn & 0x800) && (insn & 0x3ff))
90     fprintf_fn (stream, "\t");
91
92   /* Check if either the x or y part is invalid.  */
93   if (((insn & 0xc) == 0 && (insn & 0x2a0))
94       || ((insn & 3) == 0 && (insn & 0x150)))
95     fprintf_fn (stream, ".word 0x%x", insn);
96   else
97     {
98       static sh_opcode_info *first_movx, *first_movy;
99       sh_opcode_info *opx, *opy;
100       int insn_x, insn_y;
101
102       if (! first_movx)
103         {
104           for (first_movx = sh_table; first_movx->nibbles[1] != MOVX; )
105             first_movx++;
106           for (first_movy = first_movx; first_movy->nibbles[1] != MOVY; )
107             first_movy++;
108         }
109       insn_x = (insn >> 2) & 0xb;
110       if (insn_x)
111         {
112           for (opx = first_movx; opx->nibbles[2] != insn_x; ) opx++;
113           print_movxy (opx, ((insn >> 9) & 1) + 4, (insn >> 7) & 1,
114                        fprintf_fn, stream);
115         }
116       insn_y = (insn & 3) | ((insn >> 1) & 8);
117       if (insn_y)
118         {
119           if (insn_x)
120             fprintf_fn (stream, "\t");
121           for (opy = first_movy; opy->nibbles[2] != insn_y; ) opy++;
122           print_movxy (opy, ((insn >> 8) & 1) + 6, (insn >> 6) & 1,
123                        fprintf_fn, stream);
124         }
125     }
126 }
127
128 static void
129 print_dsp_reg (rm, fprintf_fn, stream)
130      int rm;
131      fprintf_ftype fprintf_fn;
132      void *stream;
133 {
134   switch (rm)
135     {
136     case A_A1_NUM:
137       fprintf_fn (stream, "a1");
138       break;
139     case A_A0_NUM:
140       fprintf_fn (stream, "a0");
141       break;
142     case A_X0_NUM:
143       fprintf_fn (stream, "x0");
144       break;
145     case A_X1_NUM:
146       fprintf_fn (stream, "x1");
147       break;
148     case A_Y0_NUM:
149       fprintf_fn (stream, "y0");
150       break;
151     case A_Y1_NUM:
152       fprintf_fn (stream, "y1");
153       break;
154     case A_M0_NUM:
155       fprintf_fn (stream, "m0");
156       break;
157     case A_A1G_NUM:
158       fprintf_fn (stream, "a1g");
159       break;
160     case A_M1_NUM:
161       fprintf_fn (stream, "m1");
162       break;
163     case A_A0G_NUM:
164       fprintf_fn (stream, "a0g");
165       break;
166     default:
167       fprintf_fn (stream, "0x%x", rm);
168       break;
169     }
170 }
171
172 static void
173 print_insn_ppi (field_b, info)
174      int field_b;
175      struct disassemble_info *info;
176 {
177   static char *sx_tab[] = {"x0","x1","a0","a1"};
178   static char *sy_tab[] = {"y0","y1","m0","m1"};
179   fprintf_ftype fprintf_fn = info->fprintf_func;
180   void *stream = info->stream;
181   int nib1, nib2, nib3;
182   char *dc;
183   sh_opcode_info *op;
184
185   if ((field_b & 0xe800) == 0)
186     {
187       fprintf_fn (stream, "psh%c\t#%d,",
188                   field_b & 0x1000 ? 'a' : 'l',
189                   (field_b >> 4) & 127);
190       print_dsp_reg (field_b & 0xf, fprintf_fn, stream);
191       return;
192     }
193   if ((field_b & 0xc000) == 0x4000 && (field_b & 0x3000) != 0x1000)
194     {
195       static char *du_tab[] = {"x0","y0","a0","a1"};
196       static char *se_tab[] = {"x0","x1","y0","a1"};
197       static char *sf_tab[] = {"y0","y1","x0","a1"};
198       static char *sg_tab[] = {"m0","m1","a0","a1"};
199
200       if (field_b & 0x2000)
201         {
202           fprintf_fn (stream, "p%s %s,%s,%s\t",
203                       (field_b & 0x1000) ? "add" : "sub",
204                       sx_tab[(field_b >> 6) & 3],
205                       sy_tab[(field_b >> 4) & 3],
206                       du_tab[(field_b >> 0) & 3]);
207         }
208       fprintf_fn (stream, "pmuls%c%s,%s,%s",
209                   field_b & 0x2000 ? ' ' : '\t',
210                   se_tab[(field_b >> 10) & 3],
211                   sf_tab[(field_b >>  8) & 3],
212                   sg_tab[(field_b >>  2) & 3]);
213       return;
214     }
215
216   nib1 = PPIC;
217   nib2 = field_b >> 12 & 0xf;
218   nib3 = field_b >> 8 & 0xf;
219   switch (nib3 & 0x3)
220     {
221     case 0:
222       dc = "";
223       nib1 = PPI3;
224       break;
225     case 1:
226       dc = "";
227       break;
228     case 2:
229       dc = "dct ";
230       nib3 -= 1;
231       break;
232     case 3:
233       dc = "dcf ";
234       nib3 -= 2;
235       break;
236     }
237   for (op = sh_table; op->name; op++)
238     {
239       if (op->nibbles[1] == nib1
240           && op->nibbles[2] == nib2
241           && op->nibbles[3] == nib3)
242         {
243           int n;
244
245           fprintf_fn (stream, "%s%s\t", dc, op->name);
246           for (n = 0; n < 3 && op->arg[n] != A_END; n++) 
247             {
248               if (n && op->arg[1] != A_END)
249                 fprintf_fn (stream, ",");
250               switch (op->arg[n]) 
251                 {
252                 case DSP_REG_N:
253                   print_dsp_reg (field_b & 0xf, fprintf_fn, stream);
254                   break;
255                 case DSP_REG_X:
256                   fprintf_fn (stream, sx_tab[(field_b >> 6) & 3]);
257                   break;
258                 case DSP_REG_Y:
259                   fprintf_fn (stream, sy_tab[(field_b >> 4) & 3]);
260                   break;
261                 case A_MACH:
262                   fprintf_fn (stream, "mach");
263                   break;
264                 case A_MACL:
265                   fprintf_fn (stream ,"macl");
266                   break;
267                 default:
268                   abort ();
269                 }
270             }
271           return;
272         }
273     }
274   /* Not found.  */
275   fprintf_fn (stream, ".word 0x%x", field_b);
276 }
277
278 static int 
279 print_insn_shx (memaddr, info)
280      bfd_vma memaddr;
281      struct disassemble_info *info;
282 {
283   fprintf_ftype fprintf_fn = info->fprintf_func;
284   void *stream = info->stream;
285   unsigned char insn[2];
286   unsigned char nibs[4];
287   int status;
288   bfd_vma relmask = ~ (bfd_vma) 0;
289   sh_opcode_info *op;
290   int target_arch;
291
292   switch (info->mach)
293     {
294     case bfd_mach_sh:
295       target_arch = arch_sh1;
296       break;
297     case bfd_mach_sh2:
298       target_arch = arch_sh2;
299       break;
300     case bfd_mach_sh_dsp:
301       target_arch = arch_sh_dsp;
302       break;
303     case bfd_mach_sh3:
304       target_arch = arch_sh3;
305       break;
306     case bfd_mach_sh3_dsp:
307       target_arch = arch_sh3_dsp;
308       break;
309     case bfd_mach_sh3e:
310       target_arch = arch_sh3e;
311       break;
312     case bfd_mach_sh4:
313       target_arch = arch_sh4;
314       break;
315     default:
316       abort ();
317     }
318
319   status = info->read_memory_func (memaddr, insn, 2, info);
320
321   if (status != 0) 
322     {
323       info->memory_error_func (status, memaddr, info);
324       return -1;
325     }
326
327   if (info->flags & LITTLE_BIT) 
328     {
329       nibs[0] = (insn[1] >> 4) & 0xf;
330       nibs[1] = insn[1] & 0xf;
331
332       nibs[2] = (insn[0] >> 4) & 0xf;
333       nibs[3] = insn[0] & 0xf;
334     }
335   else 
336     {
337       nibs[0] = (insn[0] >> 4) & 0xf;
338       nibs[1] = insn[0] & 0xf;
339
340       nibs[2] = (insn[1] >> 4) & 0xf;
341       nibs[3] = insn[1] & 0xf;
342     }
343
344   if (nibs[0] == 0xf && (nibs[1] & 4) == 0 && target_arch & arch_sh_dsp_up)
345     {
346       if (nibs[1] & 8)
347         {
348           int field_b;
349
350           status = info->read_memory_func (memaddr + 2, insn, 2, info);
351
352           if (status != 0) 
353             {
354               info->memory_error_func (status, memaddr + 2, info);
355               return -1;
356             }
357
358           if (info->flags & LITTLE_BIT) 
359             field_b = insn[1] << 8 | insn[0];
360           else
361             field_b = insn[0] << 8 | insn[1];
362
363           print_insn_ppi (field_b, info);
364           print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info);
365           return 4;
366         }
367       print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info);
368       return 2;
369     }
370   for (op = sh_table; op->name; op++) 
371     {
372       int n;
373       int imm = 0;
374       int rn = 0;
375       int rm = 0;
376       int rb = 0;
377       int disp_pc;
378       bfd_vma disp_pc_addr = 0;
379
380       if ((op->arch & target_arch) == 0)
381         goto fail;
382       for (n = 0; n < 4; n++)
383         {
384           int i = op->nibbles[n];
385
386           if (i < 16) 
387             {
388               if (nibs[n] == i)
389                 continue;
390               goto fail;
391             }
392           switch (i)
393             {
394             case BRANCH_8:
395               imm = (nibs[2] << 4) | (nibs[3]);   
396               if (imm & 0x80)
397                 imm |= ~0xff;
398               imm = ((char)imm) * 2 + 4 ;
399               goto ok;
400             case BRANCH_12:
401               imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]);
402               if (imm & 0x800)
403                 imm |= ~0xfff;
404               imm = imm * 2 + 4;
405               goto ok;
406             case IMM0_4:
407             case IMM1_4:
408               imm = nibs[3];
409               goto ok;
410             case IMM0_4BY2:
411             case IMM1_4BY2:
412               imm = nibs[3] <<1;
413               goto ok;
414             case IMM0_4BY4:
415             case IMM1_4BY4:
416               imm = nibs[3] <<2;
417               goto ok;
418             case IMM0_8:
419             case IMM1_8:
420               imm = (nibs[2] << 4) | nibs[3];
421               goto ok;
422             case PCRELIMM_8BY2:
423               imm = ((nibs[2] << 4) | nibs[3]) <<1;
424               relmask = ~ (bfd_vma) 1;
425               goto ok;
426             case PCRELIMM_8BY4:
427               imm = ((nibs[2] << 4) | nibs[3]) <<2;
428               relmask = ~ (bfd_vma) 3;
429               goto ok;
430             case IMM0_8BY2:
431             case IMM1_8BY2:
432               imm = ((nibs[2] << 4) | nibs[3]) <<1;
433               goto ok;
434             case IMM0_8BY4:
435             case IMM1_8BY4:
436               imm = ((nibs[2] << 4) | nibs[3]) <<2;
437               goto ok;
438             case REG_N:
439               rn = nibs[n];
440               break;
441             case REG_M:
442               rm = nibs[n];
443               break;
444             case REG_NM:
445               rn = (nibs[n] & 0xc) >> 2;
446               rm = (nibs[n] & 0x3);
447               break;
448             case REG_B:
449               rb = nibs[n] & 0x07;
450               break;    
451             case SDT_REG_N:
452               /* sh-dsp: single data transfer.  */
453               rn = nibs[n];
454               if ((rn & 0xc) != 4)
455                 goto fail;
456               rn = rn & 0x3;
457               rn |= (rn & 2) << 1;
458               break;
459             case PPI:
460             case REPEAT:
461               goto fail;
462             default:
463               abort();
464             }
465         }
466
467     ok:
468       fprintf_fn (stream,"%s\t", op->name);
469       disp_pc = 0;
470       for (n = 0; n < 3 && op->arg[n] != A_END; n++) 
471         {
472           if (n && op->arg[1] != A_END)
473             fprintf_fn (stream, ",");
474           switch (op->arg[n]) 
475             {
476             case A_IMM:
477               fprintf_fn (stream, "#%d", (char)(imm));
478               break;
479             case A_R0:
480               fprintf_fn (stream, "r0");
481               break;
482             case A_REG_N:
483               fprintf_fn (stream, "r%d", rn);
484               break;
485             case A_INC_N:
486               fprintf_fn (stream, "@r%d+", rn); 
487               break;
488             case A_DEC_N:
489               fprintf_fn (stream, "@-r%d", rn); 
490               break;
491             case A_IND_N:
492               fprintf_fn (stream, "@r%d", rn);  
493               break;
494             case A_DISP_REG_N:
495               fprintf_fn (stream, "@(%d,r%d)", imm, rn);        
496               break;
497             case A_PMOD_N:
498               fprintf_fn (stream, "@r%d+r8", rn);       
499               break;
500             case A_REG_M:
501               fprintf_fn (stream, "r%d", rm);
502               break;
503             case A_INC_M:
504               fprintf_fn (stream, "@r%d+", rm); 
505               break;
506             case A_DEC_M:
507               fprintf_fn (stream, "@-r%d", rm); 
508               break;
509             case A_IND_M:
510               fprintf_fn (stream, "@r%d", rm);  
511               break;
512             case A_DISP_REG_M:
513               fprintf_fn (stream, "@(%d,r%d)", imm, rm);        
514               break;
515             case A_REG_B:
516               fprintf_fn (stream, "r%d_bank", rb);
517               break;
518             case A_DISP_PC:
519               disp_pc = 1;
520               disp_pc_addr = imm + 4 + (memaddr & relmask);
521               (*info->print_address_func) (disp_pc_addr, info);
522               break;
523             case A_IND_R0_REG_N:
524               fprintf_fn (stream, "@(r0,r%d)", rn);
525               break; 
526             case A_IND_R0_REG_M:
527               fprintf_fn (stream, "@(r0,r%d)", rm);
528               break; 
529             case A_DISP_GBR:
530               fprintf_fn (stream, "@(%d,gbr)",imm);
531               break;
532             case A_R0_GBR:
533               fprintf_fn (stream, "@(r0,gbr)");
534               break;
535             case A_BDISP12:
536             case A_BDISP8:
537               (*info->print_address_func) (imm + memaddr, info);
538               break;
539             case A_SR:
540               fprintf_fn (stream, "sr");
541               break;
542             case A_GBR:
543               fprintf_fn (stream, "gbr");
544               break;
545             case A_VBR:
546               fprintf_fn (stream, "vbr");
547               break;
548             case A_DSR:
549               fprintf_fn (stream, "dsr");
550               break;
551             case A_MOD:
552               fprintf_fn (stream, "mod");
553               break;
554             case A_RE:
555               fprintf_fn (stream, "re");
556               break;
557             case A_RS:
558               fprintf_fn (stream, "rs");
559               break;
560             case A_A0:
561               fprintf_fn (stream, "a0");
562               break;
563             case A_X0:
564               fprintf_fn (stream, "x0");
565               break;
566             case A_X1:
567               fprintf_fn (stream, "x1");
568               break;
569             case A_Y0:
570               fprintf_fn (stream, "y0");
571               break;
572             case A_Y1:
573               fprintf_fn (stream, "y1");
574               break;
575             case DSP_REG_M:
576               print_dsp_reg (rm, fprintf_fn, stream);
577               break;
578             case A_SSR:
579               fprintf_fn (stream, "ssr");
580               break;
581             case A_SPC:
582               fprintf_fn (stream, "spc");
583               break;
584             case A_MACH:
585               fprintf_fn (stream, "mach");
586               break;
587             case A_MACL:
588               fprintf_fn (stream ,"macl");
589               break;
590             case A_PR:
591               fprintf_fn (stream, "pr");
592               break;
593             case A_SGR:
594               fprintf_fn (stream, "sgr");
595               break;
596             case A_DBR:
597               fprintf_fn (stream, "dbr");
598               break;
599             case F_REG_N:
600               fprintf_fn (stream, "fr%d", rn);
601               break;
602             case F_REG_M:
603               fprintf_fn (stream, "fr%d", rm);
604               break;
605             case DX_REG_N:
606               if (rn & 1)
607                 {
608                   fprintf_fn (stream, "xd%d", rn & ~1);
609                   break;
610                 }
611             d_reg_n:
612             case D_REG_N:
613               fprintf_fn (stream, "dr%d", rn);
614               break;
615             case DX_REG_M:
616               if (rm & 1)
617                 {
618                   fprintf_fn (stream, "xd%d", rm & ~1);
619                   break;
620                 }
621             case D_REG_M:
622               fprintf_fn (stream, "dr%d", rm);
623               break;
624             case FPSCR_M:
625             case FPSCR_N:
626               fprintf_fn (stream, "fpscr");
627               break;
628             case FPUL_M:
629             case FPUL_N:
630               fprintf_fn (stream, "fpul");
631               break;
632             case F_FR0:
633               fprintf_fn (stream, "fr0");
634               break;
635             case V_REG_N:
636               fprintf_fn (stream, "fv%d", rn*4);
637               break;
638             case V_REG_M:
639               fprintf_fn (stream, "fv%d", rm*4);
640               break;
641             case XMTRX_M4:
642               fprintf_fn (stream, "xmtrx");
643               break;
644             default:
645               abort();
646             }
647         }
648
649 #if 0
650       /* This code prints instructions in delay slots on the same line
651          as the instruction which needs the delay slots.  This can be
652          confusing, since other disassembler don't work this way, and
653          it means that the instructions are not all in a line.  So I
654          disabled it.  Ian.  */
655       if (!(info->flags & 1)
656           && (op->name[0] == 'j'
657               || (op->name[0] == 'b'
658                   && (op->name[1] == 'r' 
659                       || op->name[1] == 's'))
660               || (op->name[0] == 'r' && op->name[1] == 't')
661               || (op->name[0] == 'b' && op->name[2] == '.')))
662         {
663           info->flags |= 1;
664           fprintf_fn (stream, "\t(slot ");
665           print_insn_shx (memaddr + 2, info);
666           info->flags &= ~1;
667           fprintf_fn (stream, ")");
668           return 4;
669         }
670 #endif
671
672       if (disp_pc && strcmp (op->name, "mova") != 0)
673         {
674           int size;
675           bfd_byte bytes[4];
676
677           if (relmask == ~ (bfd_vma) 1)
678             size = 2;
679           else
680             size = 4;
681           status = info->read_memory_func (disp_pc_addr, bytes, size, info);
682           if (status == 0)
683             {
684               unsigned int val;
685
686               if (size == 2)
687                 {
688                   if ((info->flags & LITTLE_BIT) != 0)
689                     val = bfd_getl16 (bytes);
690                   else
691                     val = bfd_getb16 (bytes);
692                 }
693               else
694                 {
695                   if ((info->flags & LITTLE_BIT) != 0)
696                     val = bfd_getl32 (bytes);
697                   else
698                     val = bfd_getb32 (bytes);
699                 }
700               fprintf_fn (stream, "\t! 0x%x", val);
701             }
702         }
703
704       return 2;
705     fail:
706       ;
707
708     }
709   fprintf_fn (stream, ".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]);
710   return 2;
711 }
712
713 int 
714 print_insn_shl (memaddr, info)
715      bfd_vma memaddr;
716      struct disassemble_info *info;
717 {
718   int r;
719
720   info->flags = LITTLE_BIT;
721   r = print_insn_shx (memaddr, info);
722   return r;
723 }
724
725 int 
726 print_insn_sh (memaddr, info)
727      bfd_vma memaddr;
728      struct disassemble_info *info;
729 {
730   int r;
731
732   info->flags = 0;
733   r = print_insn_shx (memaddr, info);
734   return r;
735 }