]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - opcodes/sh-dis.c
1 /* Disassemble SH instructions.
2 Copyright 1993, 1994, 1995, 1997, 1998, 2000, 2001
3 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
27 static void print_movxy
28 PARAMS ((sh_opcode_info
*, int, int, fprintf_ftype
, void *));
29 static void print_insn_ddt
PARAMS ((int, struct disassemble_info
*));
30 static void print_dsp_reg
PARAMS ((int, fprintf_ftype
, void *));
31 static void print_insn_ppi
PARAMS ((int, struct disassemble_info
*));
34 print_movxy (op
, rn
, rm
, fprintf_fn
, stream
)
37 fprintf_ftype fprintf_fn
;
42 fprintf_fn (stream
, "%s\t", op
->name
);
43 for (n
= 0; n
< 2; n
++)
48 fprintf_fn (stream
, "@r%d", rn
);
51 fprintf_fn (stream
, "@r%d+", rn
);
54 fprintf_fn (stream
, "@r%d+r8", rn
);
57 fprintf_fn (stream
, "@r%d+r9", rn
);
60 fprintf_fn (stream
, "a%c", '0' + rm
);
63 fprintf_fn (stream
, "x%c", '0' + rm
);
66 fprintf_fn (stream
, "y%c", '0' + rm
);
72 fprintf_fn (stream
, ",");
76 /* Print a double data transfer insn. INSN is just the lower three
77 nibbles of the insn, i.e. field a and the bit that indicates if
78 a parallel processing insn follows.
79 Return nonzero if a field b of a parallel processing insns follows. */
82 print_insn_ddt (insn
, info
)
84 struct disassemble_info
*info
;
86 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
87 void *stream
= info
->stream
;
89 /* If this is just a nop, make sure to emit something. */
91 fprintf_fn (stream
, "nopx\tnopy");
93 /* If a parallel processing insn was printed before,
94 and we got a non-nop, emit a tab. */
95 if ((insn
& 0x800) && (insn
& 0x3ff))
96 fprintf_fn (stream
, "\t");
98 /* Check if either the x or y part is invalid. */
99 if (((insn
& 0xc) == 0 && (insn
& 0x2a0))
100 || ((insn
& 3) == 0 && (insn
& 0x150)))
101 fprintf_fn (stream
, ".word 0x%x", insn
);
104 static sh_opcode_info
*first_movx
, *first_movy
;
105 sh_opcode_info
*opx
, *opy
;
106 unsigned int insn_x
, insn_y
;
110 for (first_movx
= sh_table
; first_movx
->nibbles
[1] != MOVX
;)
112 for (first_movy
= first_movx
; first_movy
->nibbles
[1] != MOVY
;)
115 insn_x
= (insn
>> 2) & 0xb;
118 for (opx
= first_movx
; opx
->nibbles
[2] != insn_x
;)
120 print_movxy (opx
, ((insn
>> 9) & 1) + 4, (insn
>> 7) & 1,
123 insn_y
= (insn
& 3) | ((insn
>> 1) & 8);
127 fprintf_fn (stream
, "\t");
128 for (opy
= first_movy
; opy
->nibbles
[2] != insn_y
;)
130 print_movxy (opy
, ((insn
>> 8) & 1) + 6, (insn
>> 6) & 1,
137 print_dsp_reg (rm
, fprintf_fn
, stream
)
139 fprintf_ftype fprintf_fn
;
145 fprintf_fn (stream
, "a1");
148 fprintf_fn (stream
, "a0");
151 fprintf_fn (stream
, "x0");
154 fprintf_fn (stream
, "x1");
157 fprintf_fn (stream
, "y0");
160 fprintf_fn (stream
, "y1");
163 fprintf_fn (stream
, "m0");
166 fprintf_fn (stream
, "a1g");
169 fprintf_fn (stream
, "m1");
172 fprintf_fn (stream
, "a0g");
175 fprintf_fn (stream
, "0x%x", rm
);
181 print_insn_ppi (field_b
, info
)
183 struct disassemble_info
*info
;
185 static char *sx_tab
[] = { "x0", "x1", "a0", "a1" };
186 static char *sy_tab
[] = { "y0", "y1", "m0", "m1" };
187 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
188 void *stream
= info
->stream
;
189 unsigned int nib1
, nib2
, nib3
;
193 if ((field_b
& 0xe800) == 0)
195 fprintf_fn (stream
, "psh%c\t#%d,",
196 field_b
& 0x1000 ? 'a' : 'l',
197 (field_b
>> 4) & 127);
198 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
201 if ((field_b
& 0xc000) == 0x4000 && (field_b
& 0x3000) != 0x1000)
203 static char *du_tab
[] = { "x0", "y0", "a0", "a1" };
204 static char *se_tab
[] = { "x0", "x1", "y0", "a1" };
205 static char *sf_tab
[] = { "y0", "y1", "x0", "a1" };
206 static char *sg_tab
[] = { "m0", "m1", "a0", "a1" };
208 if (field_b
& 0x2000)
210 fprintf_fn (stream
, "p%s %s,%s,%s\t",
211 (field_b
& 0x1000) ? "add" : "sub",
212 sx_tab
[(field_b
>> 6) & 3],
213 sy_tab
[(field_b
>> 4) & 3],
214 du_tab
[(field_b
>> 0) & 3]);
216 fprintf_fn (stream
, "pmuls%c%s,%s,%s",
217 field_b
& 0x2000 ? ' ' : '\t',
218 se_tab
[(field_b
>> 10) & 3],
219 sf_tab
[(field_b
>> 8) & 3],
220 sg_tab
[(field_b
>> 2) & 3]);
225 nib2
= field_b
>> 12 & 0xf;
226 nib3
= field_b
>> 8 & 0xf;
245 for (op
= sh_table
; op
->name
; op
++)
247 if (op
->nibbles
[1] == nib1
248 && op
->nibbles
[2] == nib2
249 && op
->nibbles
[3] == nib3
)
253 fprintf_fn (stream
, "%s%s\t", dc
, op
->name
);
254 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
256 if (n
&& op
->arg
[1] != A_END
)
257 fprintf_fn (stream
, ",");
261 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
264 fprintf_fn (stream
, sx_tab
[(field_b
>> 6) & 3]);
267 fprintf_fn (stream
, sy_tab
[(field_b
>> 4) & 3]);
270 fprintf_fn (stream
, "mach");
273 fprintf_fn (stream
, "macl");
283 fprintf_fn (stream
, ".word 0x%x", field_b
);
287 print_insn_sh (memaddr
, info
)
289 struct disassemble_info
*info
;
291 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
292 void *stream
= info
->stream
;
293 unsigned char insn
[2];
294 unsigned char nibs
[4];
296 bfd_vma relmask
= ~(bfd_vma
) 0;
303 target_arch
= arch_sh1
;
306 target_arch
= arch_sh2
;
308 case bfd_mach_sh_dsp
:
309 target_arch
= arch_sh_dsp
;
312 target_arch
= arch_sh3
;
314 case bfd_mach_sh3_dsp
:
315 target_arch
= arch_sh3_dsp
;
318 target_arch
= arch_sh3e
;
321 target_arch
= arch_sh4
;
324 #ifdef INCLUDE_SHMEDIA
325 status
= print_insn_sh64 (memaddr
, info
);
329 /* When we get here for sh64, it's because we want to disassemble
330 SHcompact, i.e. arch_sh4. */
331 target_arch
= arch_sh4
;
337 status
= info
->read_memory_func (memaddr
, insn
, 2, info
);
341 info
->memory_error_func (status
, memaddr
, info
);
345 if (info
->endian
== BFD_ENDIAN_LITTLE
)
347 nibs
[0] = (insn
[1] >> 4) & 0xf;
348 nibs
[1] = insn
[1] & 0xf;
350 nibs
[2] = (insn
[0] >> 4) & 0xf;
351 nibs
[3] = insn
[0] & 0xf;
355 nibs
[0] = (insn
[0] >> 4) & 0xf;
356 nibs
[1] = insn
[0] & 0xf;
358 nibs
[2] = (insn
[1] >> 4) & 0xf;
359 nibs
[3] = insn
[1] & 0xf;
362 if (nibs
[0] == 0xf && (nibs
[1] & 4) == 0 && target_arch
& arch_sh_dsp_up
)
368 status
= info
->read_memory_func (memaddr
+ 2, insn
, 2, info
);
372 info
->memory_error_func (status
, memaddr
+ 2, info
);
376 if (info
->endian
== BFD_ENDIAN_LITTLE
)
377 field_b
= insn
[1] << 8 | insn
[0];
379 field_b
= insn
[0] << 8 | insn
[1];
381 print_insn_ppi (field_b
, info
);
382 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
385 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
388 for (op
= sh_table
; op
->name
; op
++)
396 bfd_vma disp_pc_addr
= 0;
398 if ((op
->arch
& target_arch
) == 0)
400 for (n
= 0; n
< 4; n
++)
402 int i
= op
->nibbles
[n
];
413 imm
= (nibs
[2] << 4) | (nibs
[3]);
416 imm
= ((char) imm
) * 2 + 4;
419 imm
= ((nibs
[1]) << 8) | (nibs
[2] << 4) | (nibs
[3]);
438 imm
= (nibs
[2] << 4) | nibs
[3];
441 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
442 relmask
= ~(bfd_vma
) 1;
445 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
446 relmask
= ~(bfd_vma
) 3;
450 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
454 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
463 rn
= (nibs
[n
] & 0xc) >> 2;
464 rm
= (nibs
[n
] & 0x3);
470 /* sh-dsp: single data transfer. */
475 rn
|= (!(rn
& 2)) << 2;
486 fprintf_fn (stream
, "%s\t", op
->name
);
488 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
490 if (n
&& op
->arg
[1] != A_END
)
491 fprintf_fn (stream
, ",");
495 fprintf_fn (stream
, "#%d", (char) (imm
));
498 fprintf_fn (stream
, "r0");
501 fprintf_fn (stream
, "r%d", rn
);
504 fprintf_fn (stream
, "@r%d+", rn
);
507 fprintf_fn (stream
, "@-r%d", rn
);
510 fprintf_fn (stream
, "@r%d", rn
);
513 fprintf_fn (stream
, "@(%d,r%d)", imm
, rn
);
516 fprintf_fn (stream
, "@r%d+r8", rn
);
519 fprintf_fn (stream
, "r%d", rm
);
522 fprintf_fn (stream
, "@r%d+", rm
);
525 fprintf_fn (stream
, "@-r%d", rm
);
528 fprintf_fn (stream
, "@r%d", rm
);
531 fprintf_fn (stream
, "@(%d,r%d)", imm
, rm
);
534 fprintf_fn (stream
, "r%d_bank", rb
);
538 disp_pc_addr
= imm
+ 4 + (memaddr
& relmask
);
539 (*info
->print_address_func
) (disp_pc_addr
, info
);
542 fprintf_fn (stream
, "@(r0,r%d)", rn
);
545 fprintf_fn (stream
, "@(r0,r%d)", rm
);
548 fprintf_fn (stream
, "@(%d,gbr)", imm
);
551 fprintf_fn (stream
, "@(r0,gbr)");
555 (*info
->print_address_func
) (imm
+ memaddr
, info
);
558 fprintf_fn (stream
, "sr");
561 fprintf_fn (stream
, "gbr");
564 fprintf_fn (stream
, "vbr");
567 fprintf_fn (stream
, "dsr");
570 fprintf_fn (stream
, "mod");
573 fprintf_fn (stream
, "re");
576 fprintf_fn (stream
, "rs");
579 fprintf_fn (stream
, "a0");
582 fprintf_fn (stream
, "x0");
585 fprintf_fn (stream
, "x1");
588 fprintf_fn (stream
, "y0");
591 fprintf_fn (stream
, "y1");
594 print_dsp_reg (rm
, fprintf_fn
, stream
);
597 fprintf_fn (stream
, "ssr");
600 fprintf_fn (stream
, "spc");
603 fprintf_fn (stream
, "mach");
606 fprintf_fn (stream
, "macl");
609 fprintf_fn (stream
, "pr");
612 fprintf_fn (stream
, "sgr");
615 fprintf_fn (stream
, "dbr");
618 fprintf_fn (stream
, "fr%d", rn
);
621 fprintf_fn (stream
, "fr%d", rm
);
626 fprintf_fn (stream
, "xd%d", rn
& ~1);
630 fprintf_fn (stream
, "dr%d", rn
);
635 fprintf_fn (stream
, "xd%d", rm
& ~1);
639 fprintf_fn (stream
, "dr%d", rm
);
643 fprintf_fn (stream
, "fpscr");
647 fprintf_fn (stream
, "fpul");
650 fprintf_fn (stream
, "fr0");
653 fprintf_fn (stream
, "fv%d", rn
* 4);
656 fprintf_fn (stream
, "fv%d", rm
* 4);
659 fprintf_fn (stream
, "xmtrx");
667 /* This code prints instructions in delay slots on the same line
668 as the instruction which needs the delay slots. This can be
669 confusing, since other disassembler don't work this way, and
670 it means that the instructions are not all in a line. So I
672 if (!(info
->flags
& 1)
673 && (op
->name
[0] == 'j'
674 || (op
->name
[0] == 'b'
675 && (op
->name
[1] == 'r'
676 || op
->name
[1] == 's'))
677 || (op
->name
[0] == 'r' && op
->name
[1] == 't')
678 || (op
->name
[0] == 'b' && op
->name
[2] == '.')))
681 fprintf_fn (stream
, "\t(slot ");
682 print_insn_sh (memaddr
+ 2, info
);
684 fprintf_fn (stream
, ")");
689 if (disp_pc
&& strcmp (op
->name
, "mova") != 0)
694 if (relmask
== ~(bfd_vma
) 1)
698 status
= info
->read_memory_func (disp_pc_addr
, bytes
, size
, info
);
705 if (info
->endian
== BFD_ENDIAN_LITTLE
)
706 val
= bfd_getl16 (bytes
);
708 val
= bfd_getb16 (bytes
);
712 if (info
->endian
== BFD_ENDIAN_LITTLE
)
713 val
= bfd_getl32 (bytes
);
715 val
= bfd_getb32 (bytes
);
717 fprintf_fn (stream
, "\t! 0x%x", val
);
726 fprintf_fn (stream
, ".word 0x%x%x%x%x", nibs
[0], nibs
[1], nibs
[2], nibs
[3]);