1 /* Disassemble SH instructions.
2    Copyright (C) 1993-2024 Free Software Foundation, Inc.
3 
4    This file is part of the GNU opcodes library.
5 
6    This library is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    It is distributed in the hope that it will be useful, but WITHOUT
12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14    License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this file; see the file COPYING.  If not, write to the
18    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20 
21 #include "sysdep.h"
22 #include <stdio.h>
23 
24 #define STATIC_TABLE
25 #define DEFINE_TABLE
26 
27 #include "sh-opc.h"
28 #include "disassemble.h"
29 
30 static void
print_movxy(const sh_opcode_info * op,int rn,int rm,fprintf_ftype fprintf_fn,void * stream)31 print_movxy (const sh_opcode_info *op,
32                int rn,
33                int rm,
34                fprintf_ftype fprintf_fn,
35                void *stream)
36 {
37   int n;
38 
39   fprintf_fn (stream, "%s\t", op->name);
40   for (n = 0; n < 2; n++)
41     {
42       switch (op->arg[n])
43           {
44           case A_IND_N:
45           case AX_IND_N:
46           case AXY_IND_N:
47           case AY_IND_N:
48           case AYX_IND_N:
49             fprintf_fn (stream, "@r%d", rn);
50             break;
51           case A_INC_N:
52           case AX_INC_N:
53           case AXY_INC_N:
54           case AY_INC_N:
55           case AYX_INC_N:
56             fprintf_fn (stream, "@r%d+", rn);
57             break;
58           case AX_PMOD_N:
59           case AXY_PMOD_N:
60             fprintf_fn (stream, "@r%d+r8", rn);
61             break;
62           case AY_PMOD_N:
63           case AYX_PMOD_N:
64             fprintf_fn (stream, "@r%d+r9", rn);
65             break;
66           case DSP_REG_A_M:
67             fprintf_fn (stream, "a%c", '0' + rm);
68             break;
69           case DSP_REG_X:
70             fprintf_fn (stream, "x%c", '0' + rm);
71             break;
72           case DSP_REG_Y:
73             fprintf_fn (stream, "y%c", '0' + rm);
74             break;
75           case DSP_REG_AX:
76             fprintf_fn (stream, "%c%c",
77                           (rm & 1) ? 'x' : 'a',
78                           (rm & 2) ? '1' : '0');
79             break;
80           case DSP_REG_XY:
81             fprintf_fn (stream, "%c%c",
82                           (rm & 1) ? 'y' : 'x',
83                           (rm & 2) ? '1' : '0');
84             break;
85           case DSP_REG_AY:
86             fprintf_fn (stream, "%c%c",
87                           (rm & 2) ? 'y' : 'a',
88                           (rm & 1) ? '1' : '0');
89             break;
90           case DSP_REG_YX:
91             fprintf_fn (stream, "%c%c",
92                           (rm & 2) ? 'x' : 'y',
93                           (rm & 1) ? '1' : '0');
94             break;
95           default:
96             abort ();
97           }
98       if (n == 0)
99           fprintf_fn (stream, ",");
100     }
101 }
102 
103 /* Print a double data transfer insn.  INSN is just the lower three
104    nibbles of the insn, i.e. field a and the bit that indicates if
105    a parallel processing insn follows.  */
106 
107 static void
print_insn_ddt(int insn,struct disassemble_info * info)108 print_insn_ddt (int insn, struct disassemble_info *info)
109 {
110   fprintf_ftype fprintf_fn = info->fprintf_func;
111   void *stream = info->stream;
112 
113   /* If this is just a nop, make sure to emit something.  */
114   if (insn == 0x000)
115     {
116       fprintf_fn (stream, "nopx\tnopy");
117       return;
118     }
119 
120   /* If a parallel processing insn was printed before,
121      and we got a non-nop, emit a tab.  */
122   if ((insn & 0x800) && (insn & 0x3ff))
123     fprintf_fn (stream, "\t");
124 
125   /* Check if either the x or y part is invalid.  */
126   if (((insn & 3) != 0 && (insn & 0xc) == 0 && (insn & 0x2a0))
127       || ((insn & 3) == 0 && (insn & 0xc) != 0 && (insn & 0x150)))
128     if (info->mach != bfd_mach_sh_dsp
129         && info->mach != bfd_mach_sh3_dsp)
130       {
131           static const sh_opcode_info *first_movx, *first_movy;
132           const sh_opcode_info *op;
133           int is_movy;
134 
135           if (! first_movx)
136             {
137               for (first_movx = sh_table; first_movx->nibbles[1] != MOVX_NOPY;)
138                 first_movx++;
139               for (first_movy = first_movx; first_movy->nibbles[1] != MOVY_NOPX;)
140                 first_movy++;
141             }
142 
143           is_movy = ((insn & 3) != 0);
144 
145           if (is_movy)
146             op = first_movy;
147           else
148             op = first_movx;
149 
150           while (op->nibbles[2] != (unsigned) ((insn >> 4) & 3)
151                  || op->nibbles[3] != (unsigned) (insn & 0xf))
152             op++;
153 
154           print_movxy (op,
155                          (4 * ((insn & (is_movy ? 0x200 : 0x100)) == 0)
156                           + 2 * is_movy
157                           + 1 * ((insn & (is_movy ? 0x100 : 0x200)) != 0)),
158                          (insn >> 6) & 3,
159                          fprintf_fn, stream);
160       }
161     else
162       fprintf_fn (stream, ".word 0x%x", insn | 0xf000);
163   else
164     {
165       static const sh_opcode_info *first_movx, *first_movy;
166       const sh_opcode_info *opx, *opy;
167       unsigned int insn_x, insn_y;
168 
169       if (! first_movx)
170           {
171             for (first_movx = sh_table; first_movx->nibbles[1] != MOVX;)
172               first_movx++;
173             for (first_movy = first_movx; first_movy->nibbles[1] != MOVY;)
174               first_movy++;
175           }
176       insn_x = (insn >> 2) & 0xb;
177       if (insn_x)
178           {
179             for (opx = first_movx; opx->nibbles[2] != insn_x;)
180               opx++;
181             print_movxy (opx, ((insn >> 9) & 1) + 4, (insn >> 7) & 1,
182                            fprintf_fn, stream);
183           }
184       insn_y = (insn & 3) | ((insn >> 1) & 8);
185       if (insn_y)
186           {
187             if (insn_x)
188               fprintf_fn (stream, "\t");
189             for (opy = first_movy; opy->nibbles[2] != insn_y;)
190               opy++;
191             print_movxy (opy, ((insn >> 8) & 1) + 6, (insn >> 6) & 1,
192                            fprintf_fn, stream);
193           }
194       if (!insn_x && !insn_y && ((insn & 0x3ff) != 0 || (insn & 0x800) == 0))
195           fprintf_fn (stream, ".word 0x%x", insn | 0xf000);
196     }
197 }
198 
199 static void
print_dsp_reg(int rm,fprintf_ftype fprintf_fn,void * stream)200 print_dsp_reg (int rm, fprintf_ftype fprintf_fn, void *stream)
201 {
202   switch (rm)
203     {
204     case A_A1_NUM:
205       fprintf_fn (stream, "a1");
206       break;
207     case A_A0_NUM:
208       fprintf_fn (stream, "a0");
209       break;
210     case A_X0_NUM:
211       fprintf_fn (stream, "x0");
212       break;
213     case A_X1_NUM:
214       fprintf_fn (stream, "x1");
215       break;
216     case A_Y0_NUM:
217       fprintf_fn (stream, "y0");
218       break;
219     case A_Y1_NUM:
220       fprintf_fn (stream, "y1");
221       break;
222     case A_M0_NUM:
223       fprintf_fn (stream, "m0");
224       break;
225     case A_A1G_NUM:
226       fprintf_fn (stream, "a1g");
227       break;
228     case A_M1_NUM:
229       fprintf_fn (stream, "m1");
230       break;
231     case A_A0G_NUM:
232       fprintf_fn (stream, "a0g");
233       break;
234     default:
235       fprintf_fn (stream, "0x%x", rm);
236       break;
237     }
238 }
239 
240 static void
print_insn_ppi(int field_b,struct disassemble_info * info)241 print_insn_ppi (int field_b, struct disassemble_info *info)
242 {
243   static char *sx_tab[] = { "x0", "x1", "a0", "a1" };
244   static char *sy_tab[] = { "y0", "y1", "m0", "m1" };
245   fprintf_ftype fprintf_fn = info->fprintf_func;
246   void *stream = info->stream;
247   unsigned int nib1, nib2, nib3;
248   unsigned int altnib1, nib4;
249   char *dc = NULL;
250   const sh_opcode_info *op;
251 
252   if ((field_b & 0xe800) == 0)
253     {
254       fprintf_fn (stream, "psh%c\t#%d,",
255                       field_b & 0x1000 ? 'a' : 'l',
256                       (field_b >> 4) & 127);
257       print_dsp_reg (field_b & 0xf, fprintf_fn, stream);
258       return;
259     }
260   if ((field_b & 0xc000) == 0x4000 && (field_b & 0x3000) != 0x1000)
261     {
262       static char *du_tab[] = { "x0", "y0", "a0", "a1" };
263       static char *se_tab[] = { "x0", "x1", "y0", "a1" };
264       static char *sf_tab[] = { "y0", "y1", "x0", "a1" };
265       static char *sg_tab[] = { "m0", "m1", "a0", "a1" };
266 
267       if (field_b & 0x2000)
268           fprintf_fn (stream, "p%s %s,%s,%s\t",
269                         (field_b & 0x1000) ? "add" : "sub",
270                         sx_tab[(field_b >> 6) & 3],
271                         sy_tab[(field_b >> 4) & 3],
272                         du_tab[(field_b >> 0) & 3]);
273 
274       else if ((field_b & 0xf0) == 0x10
275                  && info->mach != bfd_mach_sh_dsp
276                  && info->mach != bfd_mach_sh3_dsp)
277           fprintf_fn (stream, "pclr %s \t", du_tab[(field_b >> 0) & 3]);
278 
279       else if ((field_b & 0xf3) != 0)
280           fprintf_fn (stream, ".word 0x%x\t", field_b);
281 
282       fprintf_fn (stream, "pmuls%c%s,%s,%s",
283                       field_b & 0x2000 ? ' ' : '\t',
284                       se_tab[(field_b >> 10) & 3],
285                       sf_tab[(field_b >>  8) & 3],
286                       sg_tab[(field_b >>  2) & 3]);
287       return;
288     }
289 
290   nib1 = PPIC;
291   nib2 = field_b >> 12 & 0xf;
292   nib3 = field_b >> 8 & 0xf;
293   nib4 = field_b >> 4 & 0xf;
294   switch (nib3 & 0x3)
295     {
296     case 0:
297       dc = "";
298       nib1 = PPI3;
299       break;
300     case 1:
301       dc = "";
302       break;
303     case 2:
304       dc = "dct ";
305       nib3 -= 1;
306       break;
307     case 3:
308       dc = "dcf ";
309       nib3 -= 2;
310       break;
311     }
312   if (nib1 == PPI3)
313     altnib1 = PPI3NC;
314   else
315     altnib1 = nib1;
316   for (op = sh_table; op->name; op++)
317     {
318       if ((op->nibbles[1] == nib1 || op->nibbles[1] == altnib1)
319             && op->nibbles[2] == nib2
320             && op->nibbles[3] == nib3)
321           {
322             int n;
323 
324             switch (op->nibbles[4])
325               {
326               case HEX_0:
327                 break;
328               case HEX_XX00:
329                 if ((nib4 & 3) != 0)
330                     continue;
331                 break;
332               case HEX_1:
333                 if ((nib4 & 3) != 1)
334                     continue;
335                 break;
336               case HEX_00YY:
337                 if ((nib4 & 0xc) != 0)
338                     continue;
339                 break;
340               case HEX_4:
341                 if ((nib4 & 0xc) != 4)
342                     continue;
343                 break;
344               default:
345                 abort ();
346               }
347             fprintf_fn (stream, "%s%s\t", dc, op->name);
348             for (n = 0; n < 3 && op->arg[n] != A_END; n++)
349               {
350                 if (n && op->arg[1] != A_END)
351                     fprintf_fn (stream, ",");
352                 switch (op->arg[n])
353                     {
354                     case DSP_REG_N:
355                       print_dsp_reg (field_b & 0xf, fprintf_fn, stream);
356                       break;
357                     case DSP_REG_X:
358                       fprintf_fn (stream, "%s", sx_tab[(field_b >> 6) & 3]);
359                       break;
360                     case DSP_REG_Y:
361                       fprintf_fn (stream, "%s", sy_tab[(field_b >> 4) & 3]);
362                       break;
363                     case A_MACH:
364                       fprintf_fn (stream, "mach");
365                       break;
366                     case A_MACL:
367                       fprintf_fn (stream, "macl");
368                       break;
369                     default:
370                       abort ();
371                     }
372               }
373             return;
374           }
375     }
376   /* Not found.  */
377   fprintf_fn (stream, ".word 0x%x", field_b);
378 }
379 
380 /* FIXME mvs: movx insns print as ".word 0x%03x", insn & 0xfff
381    (ie. the upper nibble is missing).  */
382 
383 int
print_insn_sh(bfd_vma memaddr,struct disassemble_info * info)384 print_insn_sh (bfd_vma memaddr, struct disassemble_info *info)
385 {
386   fprintf_ftype fprintf_fn = info->fprintf_func;
387   void *stream = info->stream;
388   unsigned char insn[4];
389   unsigned char nibs[8];
390   int status;
391   bfd_vma relmask = ~(bfd_vma) 0;
392   const sh_opcode_info *op;
393   unsigned int target_arch;
394   int allow_op32;
395 
396   switch (info->mach)
397     {
398     case bfd_mach_sh:
399       target_arch = arch_sh1;
400       /* SH coff object files lack information about the machine type, so
401          we end up with bfd_mach_sh unless it was set explicitly (which
402            could have happended if this is a call from gdb or the simulator.)  */
403       if (info->symbols
404             && bfd_asymbol_flavour(*info->symbols) == bfd_target_coff_flavour)
405           target_arch = arch_sh4;
406       break;
407     default:
408       target_arch = sh_get_arch_from_bfd_mach (info->mach);
409     }
410 
411   status = info->read_memory_func (memaddr, insn, 2, info);
412 
413   if (status != 0)
414     {
415       info->memory_error_func (status, memaddr, info);
416       return -1;
417     }
418 
419   if (info->endian == BFD_ENDIAN_LITTLE)
420     {
421       nibs[0] = (insn[1] >> 4) & 0xf;
422       nibs[1] = insn[1] & 0xf;
423 
424       nibs[2] = (insn[0] >> 4) & 0xf;
425       nibs[3] = insn[0] & 0xf;
426     }
427   else
428     {
429       nibs[0] = (insn[0] >> 4) & 0xf;
430       nibs[1] = insn[0] & 0xf;
431 
432       nibs[2] = (insn[1] >> 4) & 0xf;
433       nibs[3] = insn[1] & 0xf;
434     }
435   status = info->read_memory_func (memaddr + 2, insn + 2, 2, info);
436   if (status != 0)
437     allow_op32 = 0;
438   else
439     {
440       allow_op32 = 1;
441 
442       if (info->endian == BFD_ENDIAN_LITTLE)
443           {
444             nibs[4] = (insn[3] >> 4) & 0xf;
445             nibs[5] = insn[3] & 0xf;
446 
447             nibs[6] = (insn[2] >> 4) & 0xf;
448             nibs[7] = insn[2] & 0xf;
449           }
450       else
451           {
452             nibs[4] = (insn[2] >> 4) & 0xf;
453             nibs[5] = insn[2] & 0xf;
454 
455             nibs[6] = (insn[3] >> 4) & 0xf;
456             nibs[7] = insn[3] & 0xf;
457           }
458     }
459 
460   if (nibs[0] == 0xf && (nibs[1] & 4) == 0
461       && SH_MERGE_ARCH_SET_VALID (target_arch, arch_sh_dsp_up))
462     {
463       if (nibs[1] & 8)
464           {
465             int field_b;
466 
467             status = info->read_memory_func (memaddr + 2, insn, 2, info);
468 
469             if (status != 0)
470               {
471                 info->memory_error_func (status, memaddr + 2, info);
472                 return -1;
473               }
474 
475             if (info->endian == BFD_ENDIAN_LITTLE)
476               field_b = insn[1] << 8 | insn[0];
477             else
478               field_b = insn[0] << 8 | insn[1];
479 
480             print_insn_ppi (field_b, info);
481             print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info);
482             return 4;
483           }
484       print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info);
485       return 2;
486     }
487   for (op = sh_table; op->name; op++)
488     {
489       int n;
490       int imm = 0;
491       int rn = 0;
492       int rm = 0;
493       int rb = 0;
494       int disp_pc;
495       bfd_vma disp_pc_addr = 0;
496       int disp = 0;
497       int has_disp = 0;
498       int max_n = SH_MERGE_ARCH_SET (op->arch, arch_op32) ? 8 : 4;
499 
500       if (!allow_op32
501             && SH_MERGE_ARCH_SET (op->arch, arch_op32))
502           goto fail;
503 
504       if (!SH_MERGE_ARCH_SET_VALID (op->arch, target_arch))
505           goto fail;
506       for (n = 0; n < max_n; n++)
507           {
508             int i = op->nibbles[n];
509 
510             if (i < 16)
511               {
512                 if (nibs[n] == i)
513                     continue;
514                 goto fail;
515               }
516             switch (i)
517               {
518               case BRANCH_8:
519                 imm = (nibs[2] << 4) | (nibs[3]);
520                 if (imm & 0x80)
521                     imm |= ~0xff;
522                 imm = ((char) imm) * 2 + 4;
523                 goto ok;
524               case BRANCH_12:
525                 imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]);
526                 if (imm & 0x800)
527                     imm |= ~0xfff;
528                 imm = imm * 2 + 4;
529                 goto ok;
530               case IMM0_3c:
531                 if (nibs[3] & 0x8)
532                     goto fail;
533                 imm = nibs[3] & 0x7;
534                 break;
535               case IMM0_3s:
536                 if (!(nibs[3] & 0x8))
537                     goto fail;
538                 imm = nibs[3] & 0x7;
539                 break;
540               case IMM0_3Uc:
541                 if (nibs[2] & 0x8)
542                     goto fail;
543                 imm = nibs[2] & 0x7;
544                 break;
545               case IMM0_3Us:
546                 if (!(nibs[2] & 0x8))
547                     goto fail;
548                 imm = nibs[2] & 0x7;
549                 break;
550               case DISP0_12:
551               case DISP1_12:
552                 disp = (nibs[5] << 8) | (nibs[6] << 4) | nibs[7];
553                 has_disp = 1;
554                 goto ok;
555               case DISP0_12BY2:
556               case DISP1_12BY2:
557                 disp = ((nibs[5] << 8) | (nibs[6] << 4) | nibs[7]) << 1;
558                 relmask = ~(bfd_vma) 1;
559                 has_disp = 1;
560                 goto ok;
561               case DISP0_12BY4:
562               case DISP1_12BY4:
563                 disp = ((nibs[5] << 8) | (nibs[6] << 4) | nibs[7]) << 2;
564                 relmask = ~(bfd_vma) 3;
565                 has_disp = 1;
566                 goto ok;
567               case DISP0_12BY8:
568               case DISP1_12BY8:
569                 disp = ((nibs[5] << 8) | (nibs[6] << 4) | nibs[7]) << 3;
570                 relmask = ~(bfd_vma) 7;
571                 has_disp = 1;
572                 goto ok;
573               case IMM0_20_4:
574                 break;
575               case IMM0_20:
576                 imm = ((nibs[2] << 16) | (nibs[4] << 12) | (nibs[5] << 8)
577                          | (nibs[6] << 4) | nibs[7]);
578                 if (imm & 0x80000)
579                     imm -= 0x100000;
580                 goto ok;
581               case IMM0_20BY8:
582                 imm = ((nibs[2] << 16) | (nibs[4] << 12) | (nibs[5] << 8)
583                          | (nibs[6] << 4) | nibs[7]);
584                 imm <<= 8;
585                 if (imm & 0x8000000)
586                     imm -= 0x10000000;
587                 goto ok;
588               case IMM0_4:
589               case IMM1_4:
590                 imm = nibs[3];
591                 goto ok;
592               case IMM0_4BY2:
593               case IMM1_4BY2:
594                 imm = nibs[3] << 1;
595                 goto ok;
596               case IMM0_4BY4:
597               case IMM1_4BY4:
598                 imm = nibs[3] << 2;
599                 goto ok;
600               case IMM0_8S:
601               case IMM1_8:
602                 imm = (nibs[2] << 4) | nibs[3];
603                 disp = imm;
604                 has_disp = 1;
605                 if (imm & 0x80)
606                     imm -= 0x100;
607                 goto ok;
608               case IMM0_8U:
609                 disp = imm = (nibs[2] << 4) | nibs[3];
610                 has_disp = 1;
611                 goto ok;
612               case PCRELIMM_8BY2:
613                 imm = ((nibs[2] << 4) | nibs[3]) << 1;
614                 relmask = ~(bfd_vma) 1;
615                 goto ok;
616               case PCRELIMM_8BY4:
617                 imm = ((nibs[2] << 4) | nibs[3]) << 2;
618                 relmask = ~(bfd_vma) 3;
619                 goto ok;
620               case IMM0_8BY2:
621               case IMM1_8BY2:
622                 imm = ((nibs[2] << 4) | nibs[3]) << 1;
623                 goto ok;
624               case IMM0_8BY4:
625               case IMM1_8BY4:
626                 imm = ((nibs[2] << 4) | nibs[3]) << 2;
627                 goto ok;
628               case REG_N_D:
629                 if ((nibs[n] & 1) != 0)
630                     goto fail;
631                 /* Fall through.  */
632               case REG_N:
633                 rn = nibs[n];
634                 break;
635               case REG_M:
636                 rm = nibs[n];
637                 break;
638               case REG_N_B01:
639                 if ((nibs[n] & 0x3) != 1 /* binary 01 */)
640                     goto fail;
641                 rn = (nibs[n] & 0xc) >> 2;
642                 break;
643               case REG_NM:
644                 rn = (nibs[n] & 0xc) >> 2;
645                 rm = (nibs[n] & 0x3);
646                 break;
647               case REG_B:
648                 if (!(nibs[n] & 0x08)) /* Must always be 1.  */
649                     goto fail;
650                 rb = nibs[n] & 0x07;
651                 break;
652               case SDT_REG_N:
653                 /* sh-dsp: single data transfer.  */
654                 rn = nibs[n];
655                 if ((rn & 0xc) != 4)
656                     goto fail;
657                 rn = rn & 0x3;
658                 rn |= (!(rn & 2)) << 2;
659                 break;
660               case PPI:
661               case REPEAT:
662                 goto fail;
663               default:
664                 abort ();
665               }
666           }
667 
668     ok:
669       /* sh2a has D_REG but not X_REG.  We don't know the pattern
670            doesn't match unless we check the output args to see if they
671            make sense.  */
672       if (target_arch == arch_sh2a
673             && ((op->arg[0] == DX_REG_M && (rm & 1) != 0)
674                 || (op->arg[1] == DX_REG_N && (rn & 1) != 0)))
675           goto fail;
676 
677       fprintf_fn (stream, "%s\t", op->name);
678       disp_pc = 0;
679       for (n = 0; n < 3 && op->arg[n] != A_END; n++)
680           {
681             if (n && op->arg[1] != A_END)
682               fprintf_fn (stream, ",");
683             switch (op->arg[n])
684               {
685               case A_IMM:
686                 fprintf_fn (stream, "#%d", imm);
687                 break;
688               case A_R0:
689                 fprintf_fn (stream, "r0");
690                 break;
691               case A_REG_N:
692                 fprintf_fn (stream, "r%d", rn);
693                 break;
694               case A_INC_N:
695               case AS_INC_N:
696                 fprintf_fn (stream, "@r%d+", rn);
697                 break;
698               case A_DEC_N:
699               case AS_DEC_N:
700                 fprintf_fn (stream, "@-r%d", rn);
701                 break;
702               case A_IND_N:
703               case AS_IND_N:
704                 fprintf_fn (stream, "@r%d", rn);
705                 break;
706               case A_DISP_REG_N:
707                 fprintf_fn (stream, "@(%d,r%d)", has_disp?disp:imm, rn);
708                 break;
709               case AS_PMOD_N:
710                 fprintf_fn (stream, "@r%d+r8", rn);
711                 break;
712               case A_REG_M:
713                 fprintf_fn (stream, "r%d", rm);
714                 break;
715               case A_INC_M:
716                 fprintf_fn (stream, "@r%d+", rm);
717                 break;
718               case A_DEC_M:
719                 fprintf_fn (stream, "@-r%d", rm);
720                 break;
721               case A_IND_M:
722                 fprintf_fn (stream, "@r%d", rm);
723                 break;
724               case A_DISP_REG_M:
725                 fprintf_fn (stream, "@(%d,r%d)", has_disp?disp:imm, rm);
726                 break;
727               case A_REG_B:
728                 fprintf_fn (stream, "r%d_bank", rb);
729                 break;
730               case A_DISP_PC:
731                 disp_pc = 1;
732                 disp_pc_addr = imm + 4 + (memaddr & relmask);
733                 (*info->print_address_func) (disp_pc_addr, info);
734                 break;
735               case A_IND_R0_REG_N:
736                 fprintf_fn (stream, "@(r0,r%d)", rn);
737                 break;
738               case A_IND_R0_REG_M:
739                 fprintf_fn (stream, "@(r0,r%d)", rm);
740                 break;
741               case A_DISP_GBR:
742                 fprintf_fn (stream, "@(%d,gbr)", has_disp?disp:imm);
743                 break;
744               case A_TBR:
745                 fprintf_fn (stream, "tbr");
746                 break;
747               case A_DISP2_TBR:
748                 fprintf_fn (stream, "@@(%d,tbr)", has_disp?disp:imm);
749                 break;
750               case A_INC_R15:
751                 fprintf_fn (stream, "@r15+");
752                 break;
753               case A_DEC_R15:
754                 fprintf_fn (stream, "@-r15");
755                 break;
756               case A_R0_GBR:
757                 fprintf_fn (stream, "@(r0,gbr)");
758                 break;
759               case A_BDISP12:
760               case A_BDISP8:
761                 (*info->print_address_func) (imm + memaddr, info);
762                 break;
763               case A_SR:
764                 fprintf_fn (stream, "sr");
765                 break;
766               case A_GBR:
767                 fprintf_fn (stream, "gbr");
768                 break;
769               case A_VBR:
770                 fprintf_fn (stream, "vbr");
771                 break;
772               case A_DSR:
773                 fprintf_fn (stream, "dsr");
774                 break;
775               case A_MOD:
776                 fprintf_fn (stream, "mod");
777                 break;
778               case A_RE:
779                 fprintf_fn (stream, "re");
780                 break;
781               case A_RS:
782                 fprintf_fn (stream, "rs");
783                 break;
784               case A_A0:
785                 fprintf_fn (stream, "a0");
786                 break;
787               case A_X0:
788                 fprintf_fn (stream, "x0");
789                 break;
790               case A_X1:
791                 fprintf_fn (stream, "x1");
792                 break;
793               case A_Y0:
794                 fprintf_fn (stream, "y0");
795                 break;
796               case A_Y1:
797                 fprintf_fn (stream, "y1");
798                 break;
799               case DSP_REG_M:
800                 print_dsp_reg (rm, fprintf_fn, stream);
801                 break;
802               case A_SSR:
803                 fprintf_fn (stream, "ssr");
804                 break;
805               case A_SPC:
806                 fprintf_fn (stream, "spc");
807                 break;
808               case A_MACH:
809                 fprintf_fn (stream, "mach");
810                 break;
811               case A_MACL:
812                 fprintf_fn (stream, "macl");
813                 break;
814               case A_PR:
815                 fprintf_fn (stream, "pr");
816                 break;
817               case A_SGR:
818                 fprintf_fn (stream, "sgr");
819                 break;
820               case A_DBR:
821                 fprintf_fn (stream, "dbr");
822                 break;
823               case F_REG_N:
824                 fprintf_fn (stream, "fr%d", rn);
825                 break;
826               case F_REG_M:
827                 fprintf_fn (stream, "fr%d", rm);
828                 break;
829               case DX_REG_N:
830                 if (rn & 1)
831                     {
832                       fprintf_fn (stream, "xd%d", rn & ~1);
833                       break;
834                     }
835                 /* Fall through.  */
836               case D_REG_N:
837                 fprintf_fn (stream, "dr%d", rn);
838                 break;
839               case DX_REG_M:
840                 if (rm & 1)
841                     {
842                       fprintf_fn (stream, "xd%d", rm & ~1);
843                       break;
844                     }
845                 /* Fall through.  */
846               case D_REG_M:
847                 fprintf_fn (stream, "dr%d", rm);
848                 break;
849               case FPSCR_M:
850               case FPSCR_N:
851                 fprintf_fn (stream, "fpscr");
852                 break;
853               case FPUL_M:
854               case FPUL_N:
855                 fprintf_fn (stream, "fpul");
856                 break;
857               case F_FR0:
858                 fprintf_fn (stream, "fr0");
859                 break;
860               case V_REG_N:
861                 fprintf_fn (stream, "fv%d", rn * 4);
862                 break;
863               case V_REG_M:
864                 fprintf_fn (stream, "fv%d", rm * 4);
865                 break;
866               case XMTRX_M4:
867                 fprintf_fn (stream, "xmtrx");
868                 break;
869               default:
870                 abort ();
871               }
872           }
873 
874 #if 0
875       /* This code prints instructions in delay slots on the same line
876          as the instruction which needs the delay slots.  This can be
877          confusing, since other disassembler don't work this way, and
878          it means that the instructions are not all in a line.  So I
879          disabled it.  Ian.  */
880       if (!(info->flags & 1)
881             && (op->name[0] == 'j'
882                 || (op->name[0] == 'b'
883                       && (op->name[1] == 'r'
884                           || op->name[1] == 's'))
885                 || (op->name[0] == 'r' && op->name[1] == 't')
886                 || (op->name[0] == 'b' && op->name[2] == '.')))
887           {
888             info->flags |= 1;
889             fprintf_fn (stream, "\t(slot ");
890             print_insn_sh (memaddr + 2, info);
891             info->flags &= ~1;
892             fprintf_fn (stream, ")");
893             return 4;
894           }
895 #endif
896 
897       if (disp_pc && strcmp (op->name, "mova") != 0)
898           {
899             int size;
900             bfd_byte bytes[4];
901 
902             if (relmask == ~(bfd_vma) 1)
903               size = 2;
904             else
905               size = 4;
906             /* Not reading an instruction - disable stop_vma.  */
907             info->stop_vma = 0;
908             status = info->read_memory_func (disp_pc_addr, bytes, size, info);
909             if (status == 0)
910               {
911                 unsigned int val;
912 
913                 if (size == 2)
914                     {
915                       if (info->endian == BFD_ENDIAN_LITTLE)
916                         val = bfd_getl16 (bytes);
917                       else
918                         val = bfd_getb16 (bytes);
919                     }
920                 else
921                     {
922                       if (info->endian == BFD_ENDIAN_LITTLE)
923                         val = bfd_getl32 (bytes);
924                       else
925                         val = bfd_getb32 (bytes);
926                     }
927                 if ((*info->symbol_at_address_func) (val, info))
928                     {
929                       fprintf_fn (stream, "\t! ");
930                       (*info->print_address_func) (val, info);
931                     }
932                 else
933                     fprintf_fn (stream, "\t! %x", val);
934               }
935           }
936 
937       return SH_MERGE_ARCH_SET (op->arch, arch_op32) ? 4 : 2;
938     fail:
939       ;
940 
941     }
942   fprintf_fn (stream, ".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]);
943   return 2;
944 }
945