1 /* Disassemble SH instructions.
2 Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
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.
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.
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. */
28 print_movxy (op
, rn
, rm
, fprintf_fn
, stream
)
31 fprintf_ftype fprintf_fn
;
36 fprintf_fn (stream
,"%s\t", op
->name
);
37 for (n
= 0; n
< 2; n
++)
42 fprintf_fn (stream
, "@r%d", rn
);
45 fprintf_fn (stream
, "@r%d+", rn
);
48 fprintf_fn (stream
, "@r%d+r8", rn
);
51 fprintf_fn (stream
, "@r%d+r9", rn
);
54 fprintf_fn (stream
, "a%c", '0' + rm
);
57 fprintf_fn (stream
, "x%c", '0' + rm
);
60 fprintf_fn (stream
, "y%c", '0' + rm
);
66 fprintf_fn (stream
, ",");
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. */
75 print_insn_ddt (insn
, info
)
77 struct disassemble_info
*info
;
79 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
80 void *stream
= info
->stream
;
82 /* If this is just a nop, make sure to emit something. */
84 fprintf_fn (stream
, "nopx\tnopy");
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");
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
);
97 static sh_opcode_info
*first_movx
, *first_movy
;
98 sh_opcode_info
*opx
, *opy
;
103 for (first_movx
= sh_table
; first_movx
->nibbles
[1] != MOVX
; )
105 for (first_movy
= first_movx
; first_movy
->nibbles
[1] != MOVY
; )
108 insn_x
= (insn
>> 2) & 0xb;
111 for (opx
= first_movx
; opx
->nibbles
[2] != insn_x
; ) opx
++;
112 print_movxy (opx
, ((insn
>> 9) & 1) + 4, (insn
>> 7) & 1,
115 insn_y
= (insn
& 3) | ((insn
>> 1) & 8);
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,
128 print_dsp_reg (rm
, fprintf_fn
, stream
)
130 fprintf_ftype fprintf_fn
;
136 fprintf_fn (stream
, "a1");
139 fprintf_fn (stream
, "a0");
142 fprintf_fn (stream
, "x0");
145 fprintf_fn (stream
, "x1");
148 fprintf_fn (stream
, "y0");
151 fprintf_fn (stream
, "y1");
154 fprintf_fn (stream
, "m0");
157 fprintf_fn (stream
, "a1g");
160 fprintf_fn (stream
, "m1");
163 fprintf_fn (stream
, "a0g");
166 fprintf_fn (stream
, "0x%x", rm
);
172 print_insn_ppi (field_b
, info
)
174 struct disassemble_info
*info
;
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
;
184 if ((field_b
& 0xe800) == 0)
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
);
192 if ((field_b
& 0xc000) == 0x4000 && (field_b
& 0x3000) != 0x1000)
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"};
199 if (field_b
& 0x2000)
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]);
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]);
216 nib2
= field_b
>> 12 & 0xf;
217 nib3
= field_b
>> 8 & 0xf;
236 for (op
= sh_table
; op
->name
; op
++)
238 if (op
->nibbles
[1] == nib1
239 && op
->nibbles
[2] == nib2
240 && op
->nibbles
[3] == nib3
)
244 fprintf_fn (stream
, "%s%s\t", dc
, op
->name
);
245 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
247 if (n
&& op
->arg
[1] != A_END
)
248 fprintf_fn (stream
, ",");
252 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
255 fprintf_fn (stream
, sx_tab
[(field_b
>> 6) & 3]);
258 fprintf_fn (stream
, sy_tab
[(field_b
>> 4) & 3]);
261 fprintf_fn (stream
, "mach");
264 fprintf_fn (stream
,"macl");
274 fprintf_fn (stream
, ".word 0x%x", field_b
);
278 print_insn_shx (memaddr
, info
)
280 struct disassemble_info
*info
;
282 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
283 void *stream
= info
->stream
;
284 unsigned char insn
[2];
285 unsigned char nibs
[4];
287 bfd_vma relmask
= ~ (bfd_vma
) 0;
294 target_arch
= arch_sh1
;
297 target_arch
= arch_sh2
;
299 case bfd_mach_sh_dsp
:
300 target_arch
= arch_sh_dsp
;
303 target_arch
= arch_sh3
;
305 case bfd_mach_sh3_dsp
:
306 target_arch
= arch_sh3_dsp
;
309 target_arch
= arch_sh3e
;
312 target_arch
= arch_sh4
;
318 status
= info
->read_memory_func (memaddr
, insn
, 2, info
);
322 info
->memory_error_func (status
, memaddr
, info
);
326 if (info
->flags
& LITTLE_BIT
)
328 nibs
[0] = (insn
[1] >> 4) & 0xf;
329 nibs
[1] = insn
[1] & 0xf;
331 nibs
[2] = (insn
[0] >> 4) & 0xf;
332 nibs
[3] = insn
[0] & 0xf;
336 nibs
[0] = (insn
[0] >> 4) & 0xf;
337 nibs
[1] = insn
[0] & 0xf;
339 nibs
[2] = (insn
[1] >> 4) & 0xf;
340 nibs
[3] = insn
[1] & 0xf;
343 if (nibs
[0] == 0xf && (nibs
[1] & 4) == 0 && target_arch
& arch_sh_dsp_up
)
349 status
= info
->read_memory_func (memaddr
+ 2, insn
, 2, info
);
353 info
->memory_error_func (status
, memaddr
+ 2, info
);
357 if (info
->flags
& LITTLE_BIT
)
358 field_b
= insn
[1] << 8 | insn
[0];
360 field_b
= insn
[0] << 8 | insn
[1];
362 print_insn_ppi (field_b
, info
);
363 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
366 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
369 for (op
= sh_table
; op
->name
; op
++)
377 bfd_vma disp_pc_addr
= 0;
379 if ((op
->arch
& target_arch
) == 0)
381 for (n
= 0; n
< 4; n
++)
383 int i
= op
->nibbles
[n
];
394 imm
= (nibs
[2] << 4) | (nibs
[3]);
397 imm
= ((char)imm
) * 2 + 4 ;
400 imm
= ((nibs
[1]) << 8) | (nibs
[2] << 4) | (nibs
[3]);
415 imm
= (nibs
[2] << 4) | nibs
[3];
418 imm
= ((nibs
[2] << 4) | nibs
[3]) <<1;
419 relmask
= ~ (bfd_vma
) 1;
422 imm
= ((nibs
[2] << 4) | nibs
[3]) <<2;
423 relmask
= ~ (bfd_vma
) 3;
426 imm
= ((nibs
[2] << 4) | nibs
[3]) <<1;
429 imm
= ((nibs
[2] << 4) | nibs
[3]) <<2;
432 imm
= (nibs
[2] << 4) | (nibs
[3]);
444 rn
= (nibs
[n
] & 0xc) >> 2;
445 rm
= (nibs
[n
] & 0x3);
451 /* sh-dsp: single data transfer. */
466 fprintf_fn (stream
,"%s\t", op
->name
);
468 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
470 if (n
&& op
->arg
[1] != A_END
)
471 fprintf_fn (stream
, ",");
475 fprintf_fn (stream
, "#%d", (char)(imm
));
478 fprintf_fn (stream
, "r0");
481 fprintf_fn (stream
, "r%d", rn
);
484 fprintf_fn (stream
, "@r%d+", rn
);
487 fprintf_fn (stream
, "@-r%d", rn
);
490 fprintf_fn (stream
, "@r%d", rn
);
493 fprintf_fn (stream
, "@(%d,r%d)", imm
, rn
);
496 fprintf_fn (stream
, "@r%d+r8", rn
);
499 fprintf_fn (stream
, "r%d", rm
);
502 fprintf_fn (stream
, "@r%d+", rm
);
505 fprintf_fn (stream
, "@-r%d", rm
);
508 fprintf_fn (stream
, "@r%d", rm
);
511 fprintf_fn (stream
, "@(%d,r%d)", imm
, rm
);
514 fprintf_fn (stream
, "r%d_bank", rb
);
518 disp_pc_addr
= imm
+ 4 + (memaddr
& relmask
);
519 (*info
->print_address_func
) (disp_pc_addr
, info
);
522 fprintf_fn (stream
, "@(r0,r%d)", rn
);
525 fprintf_fn (stream
, "@(r0,r%d)", rm
);
528 fprintf_fn (stream
, "@(%d,gbr)",imm
);
531 fprintf_fn (stream
, "@(r0,gbr)");
535 (*info
->print_address_func
) (imm
+ memaddr
, info
);
538 fprintf_fn (stream
, "sr");
541 fprintf_fn (stream
, "gbr");
544 fprintf_fn (stream
, "vbr");
547 fprintf_fn (stream
, "dsr");
550 fprintf_fn (stream
, "mod");
553 fprintf_fn (stream
, "re");
556 fprintf_fn (stream
, "rs");
559 fprintf_fn (stream
, "a0");
562 fprintf_fn (stream
, "x0");
565 fprintf_fn (stream
, "x1");
568 fprintf_fn (stream
, "y0");
571 fprintf_fn (stream
, "y1");
574 print_dsp_reg (rm
, fprintf_fn
, stream
);
577 fprintf_fn (stream
, "ssr");
580 fprintf_fn (stream
, "spc");
583 fprintf_fn (stream
, "mach");
586 fprintf_fn (stream
,"macl");
589 fprintf_fn (stream
, "pr");
592 fprintf_fn (stream
, "sgr");
595 fprintf_fn (stream
, "dbr");
598 fprintf_fn (stream
, "fr%d", rn
);
601 fprintf_fn (stream
, "fr%d", rm
);
606 fprintf_fn (stream
, "xd%d", rn
& ~1);
611 fprintf_fn (stream
, "dr%d", rn
);
616 fprintf_fn (stream
, "xd%d", rm
& ~1);
620 fprintf_fn (stream
, "dr%d", rm
);
624 fprintf_fn (stream
, "fpscr");
628 fprintf_fn (stream
, "fpul");
631 fprintf_fn (stream
, "fr0");
634 fprintf_fn (stream
, "fv%d", rn
*4);
637 fprintf_fn (stream
, "fv%d", rm
*4);
640 fprintf_fn (stream
, "xmtrx");
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
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] == '.')))
662 fprintf_fn (stream
, "\t(slot ");
663 print_insn_shx (memaddr
+ 2, info
);
665 fprintf_fn (stream
, ")");
670 if (disp_pc
&& strcmp (op
->name
, "mova") != 0)
675 if (relmask
== ~ (bfd_vma
) 1)
679 status
= info
->read_memory_func (disp_pc_addr
, bytes
, size
, info
);
686 if ((info
->flags
& LITTLE_BIT
) != 0)
687 val
= bfd_getl16 (bytes
);
689 val
= bfd_getb16 (bytes
);
693 if ((info
->flags
& LITTLE_BIT
) != 0)
694 val
= bfd_getl32 (bytes
);
696 val
= bfd_getb32 (bytes
);
698 fprintf_fn (stream
, "\t! 0x%x", val
);
707 fprintf_fn (stream
, ".word 0x%x%x%x%x", nibs
[0], nibs
[1], nibs
[2], nibs
[3]);
712 print_insn_shl (memaddr
, info
)
714 struct disassemble_info
*info
;
718 info
->flags
= LITTLE_BIT
;
719 r
= print_insn_shx (memaddr
, info
);
724 print_insn_sh (memaddr
, info
)
726 struct disassemble_info
*info
;
731 r
= print_insn_shx (memaddr
, info
);
This page took 0.047954 seconds and 4 git commands to generate.