]>
Commit | Line | Data |
---|---|---|
66f6448d | 1 | /* Disassemble SH instructions. |
54a93a72 | 2 | Copyright (C) 1993, 94, 95, 96, 1997 Free Software Foundation, Inc. |
66f6448d JW |
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 int | |
54a93a72 | 28 | print_insn_shx (memaddr, info) |
66f6448d JW |
29 | bfd_vma memaddr; |
30 | struct disassemble_info *info; | |
31 | { | |
54a93a72 | 32 | fprintf_ftype fprintf_fn = info->fprintf_func; |
66f6448d | 33 | void *stream = info->stream; |
54a93a72 ILT |
34 | unsigned char insn[2]; |
35 | unsigned char nibs[4]; | |
66f6448d JW |
36 | int status; |
37 | int relmask = ~0; | |
38 | sh_opcode_info *op; | |
54a93a72 ILT |
39 | |
40 | status = info->read_memory_func (memaddr, insn, 2, info); | |
66f6448d JW |
41 | |
42 | if (status != 0) | |
43 | { | |
54a93a72 | 44 | info->memory_error_func (status, memaddr, info); |
66f6448d JW |
45 | return -1; |
46 | } | |
47 | ||
66f6448d JW |
48 | if (info->flags & LITTLE_BIT) |
49 | { | |
50 | nibs[0] = (insn[1] >> 4) & 0xf; | |
51 | nibs[1] = insn[1] & 0xf; | |
52 | ||
53 | nibs[2] = (insn[0] >> 4) & 0xf; | |
54 | nibs[3] = insn[0] & 0xf; | |
55 | } | |
56 | else | |
57 | { | |
58 | nibs[0] = (insn[0] >> 4) & 0xf; | |
59 | nibs[1] = insn[0] & 0xf; | |
60 | ||
61 | nibs[2] = (insn[1] >> 4) & 0xf; | |
62 | nibs[3] = insn[1] & 0xf; | |
63 | } | |
64 | ||
65 | for (op = sh_table; op->name; op++) | |
66 | { | |
67 | int n; | |
68 | int imm; | |
69 | int rn; | |
70 | int rm; | |
54a93a72 | 71 | int rb; |
66f6448d | 72 | |
54a93a72 ILT |
73 | for (n = 0; n < 4; n++) |
74 | { | |
75 | int i = op->nibbles[n]; | |
66f6448d | 76 | |
54a93a72 ILT |
77 | if (i < 16) |
78 | { | |
79 | if (nibs[n] == i) | |
80 | continue; | |
81 | goto fail; | |
82 | } | |
83 | switch (i) | |
84 | { | |
85 | case BRANCH_8: | |
86 | imm = (nibs[2] << 4) | (nibs[3]); | |
87 | if (imm & 0x80) | |
88 | imm |= ~0xff; | |
89 | imm = ((char)imm) * 2 + 4 ; | |
90 | goto ok; | |
91 | case BRANCH_12: | |
92 | imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]); | |
93 | if (imm & 0x800) | |
94 | imm |= ~0xfff; | |
95 | imm = imm * 2 + 4; | |
96 | goto ok; | |
97 | case IMM_4: | |
98 | imm = nibs[3]; | |
99 | goto ok; | |
100 | case IMM_4BY2: | |
101 | imm = nibs[3] <<1; | |
102 | goto ok; | |
103 | case IMM_4BY4: | |
104 | imm = nibs[3] <<2; | |
105 | goto ok; | |
106 | case IMM_8: | |
107 | imm = (nibs[2] << 4) | nibs[3]; | |
108 | goto ok; | |
109 | case PCRELIMM_8BY2: | |
110 | imm = ((nibs[2] << 4) | nibs[3]) <<1; | |
111 | relmask = ~1; | |
112 | goto ok; | |
113 | case PCRELIMM_8BY4: | |
114 | imm = ((nibs[2] << 4) | nibs[3]) <<2; | |
115 | relmask = ~3; | |
116 | goto ok; | |
117 | case IMM_8BY2: | |
118 | imm = ((nibs[2] << 4) | nibs[3]) <<1; | |
119 | goto ok; | |
120 | case IMM_8BY4: | |
121 | imm = ((nibs[2] << 4) | nibs[3]) <<2; | |
122 | goto ok; | |
123 | case DISP_8: | |
124 | imm = (nibs[2] << 4) | (nibs[3]); | |
125 | goto ok; | |
126 | case DISP_4: | |
127 | imm = nibs[3]; | |
128 | goto ok; | |
129 | case REG_N: | |
130 | rn = nibs[n]; | |
131 | break; | |
132 | case REG_M: | |
133 | rm = nibs[n]; | |
134 | break; | |
135 | case REG_B: | |
136 | rb = nibs[n] & 0x07; | |
137 | break; | |
138 | default: | |
139 | abort(); | |
140 | } | |
141 | } | |
66f6448d | 142 | |
66f6448d | 143 | ok: |
54a93a72 | 144 | fprintf_fn (stream,"%s\t", op->name); |
60da0079 | 145 | for (n = 0; n < 3 && op->arg[n] != A_END; n++) |
66f6448d JW |
146 | { |
147 | if (n && op->arg[1] != A_END) | |
54a93a72 | 148 | fprintf_fn (stream, ","); |
66f6448d JW |
149 | switch (op->arg[n]) |
150 | { | |
151 | case A_IMM: | |
54a93a72 | 152 | fprintf_fn (stream, "#%d", (char)(imm)); |
66f6448d JW |
153 | break; |
154 | case A_R0: | |
54a93a72 | 155 | fprintf_fn (stream, "r0"); |
66f6448d JW |
156 | break; |
157 | case A_REG_N: | |
54a93a72 | 158 | fprintf_fn (stream, "r%d", rn); |
66f6448d JW |
159 | break; |
160 | case A_INC_N: | |
54a93a72 | 161 | fprintf_fn (stream, "@r%d+", rn); |
66f6448d JW |
162 | break; |
163 | case A_DEC_N: | |
54a93a72 | 164 | fprintf_fn (stream, "@-r%d", rn); |
66f6448d JW |
165 | break; |
166 | case A_IND_N: | |
54a93a72 | 167 | fprintf_fn (stream, "@r%d", rn); |
66f6448d JW |
168 | break; |
169 | case A_DISP_REG_N: | |
54a93a72 | 170 | fprintf_fn (stream, "@(%d,r%d)", imm, rn); |
66f6448d JW |
171 | break; |
172 | case A_REG_M: | |
54a93a72 | 173 | fprintf_fn (stream, "r%d", rm); |
66f6448d JW |
174 | break; |
175 | case A_INC_M: | |
54a93a72 | 176 | fprintf_fn (stream, "@r%d+", rm); |
66f6448d JW |
177 | break; |
178 | case A_DEC_M: | |
54a93a72 | 179 | fprintf_fn (stream, "@-r%d", rm); |
66f6448d JW |
180 | break; |
181 | case A_IND_M: | |
54a93a72 | 182 | fprintf_fn (stream, "@r%d", rm); |
66f6448d JW |
183 | break; |
184 | case A_DISP_REG_M: | |
54a93a72 ILT |
185 | fprintf_fn (stream, "@(%d,r%d)", imm, rm); |
186 | break; | |
187 | case A_REG_B: | |
188 | fprintf_fn (stream, "r%d_bank", rb); | |
66f6448d JW |
189 | break; |
190 | case A_DISP_PC: | |
54a93a72 | 191 | fprintf_fn (stream, "0x%0x", imm + 4 + (memaddr & relmask)); |
66f6448d JW |
192 | break; |
193 | case A_IND_R0_REG_N: | |
54a93a72 | 194 | fprintf_fn (stream, "@(r0,r%d)", rn); |
66f6448d JW |
195 | break; |
196 | case A_IND_R0_REG_M: | |
54a93a72 | 197 | fprintf_fn (stream, "@(r0,r%d)", rm); |
66f6448d JW |
198 | break; |
199 | case A_DISP_GBR: | |
54a93a72 | 200 | fprintf_fn (stream, "@(%d,gbr)",imm); |
66f6448d JW |
201 | break; |
202 | case A_R0_GBR: | |
54a93a72 | 203 | fprintf_fn (stream, "@(r0,gbr)"); |
66f6448d JW |
204 | break; |
205 | case A_BDISP12: | |
206 | case A_BDISP8: | |
207 | (*info->print_address_func) (imm + memaddr, info); | |
208 | break; | |
209 | case A_SR: | |
54a93a72 | 210 | fprintf_fn (stream, "sr"); |
66f6448d JW |
211 | break; |
212 | case A_GBR: | |
54a93a72 | 213 | fprintf_fn (stream, "gbr"); |
66f6448d JW |
214 | break; |
215 | case A_VBR: | |
54a93a72 | 216 | fprintf_fn (stream, "vbr"); |
66f6448d | 217 | break; |
60da0079 | 218 | case A_SSR: |
54a93a72 | 219 | fprintf_fn (stream, "ssr"); |
60da0079 C |
220 | break; |
221 | case A_SPC: | |
54a93a72 | 222 | fprintf_fn (stream, "spc"); |
60da0079 | 223 | break; |
66f6448d | 224 | case A_MACH: |
54a93a72 | 225 | fprintf_fn (stream, "mach"); |
66f6448d JW |
226 | break; |
227 | case A_MACL: | |
54a93a72 | 228 | fprintf_fn (stream ,"macl"); |
66f6448d JW |
229 | break; |
230 | case A_PR: | |
54a93a72 | 231 | fprintf_fn (stream, "pr"); |
66f6448d | 232 | break; |
66f6448d | 233 | case F_REG_N: |
54a93a72 | 234 | fprintf_fn (stream, "fr%d", rn); |
66f6448d JW |
235 | break; |
236 | case F_REG_M: | |
54a93a72 | 237 | fprintf_fn (stream, "fr%d", rm); |
66f6448d JW |
238 | break; |
239 | case FPSCR_M: | |
240 | case FPSCR_N: | |
54a93a72 | 241 | fprintf_fn (stream, "fpscr"); |
66f6448d JW |
242 | break; |
243 | case FPUL_M: | |
244 | case FPUL_N: | |
54a93a72 | 245 | fprintf_fn (stream, "fpul"); |
66f6448d | 246 | break; |
60da0079 | 247 | case F_FR0: |
54a93a72 | 248 | fprintf_fn (stream, "fr0"); |
60da0079 | 249 | break; |
66f6448d JW |
250 | default: |
251 | abort(); | |
252 | } | |
253 | ||
254 | } | |
54a93a72 | 255 | |
66f6448d JW |
256 | if (!(info->flags & 1) |
257 | && (op->name[0] == 'j' | |
258 | || (op->name[0] == 'b' | |
259 | && (op->name[1] == 'r' | |
260 | || op->name[1] == 's')) | |
261 | || (op->name[0] == 'r' && op->name[1] == 't') | |
262 | || (op->name[0] == 'b' && op->name[2] == '.'))) | |
263 | { | |
264 | info->flags |= 1; | |
54a93a72 ILT |
265 | fprintf_fn (stream, "\t(slot "); |
266 | print_insn_shx (memaddr + 2, info); | |
66f6448d | 267 | info->flags &= ~1; |
54a93a72 | 268 | fprintf_fn (stream, ")"); |
66f6448d JW |
269 | return 4; |
270 | } | |
54a93a72 | 271 | |
66f6448d JW |
272 | return 2; |
273 | fail: | |
274 | ; | |
275 | ||
276 | } | |
54a93a72 | 277 | fprintf_fn (stream, ".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]); |
66f6448d JW |
278 | return 2; |
279 | } | |
280 | ||
66f6448d | 281 | int |
54a93a72 | 282 | print_insn_shl (memaddr, info) |
66f6448d JW |
283 | bfd_vma memaddr; |
284 | struct disassemble_info *info; | |
285 | { | |
286 | int r; | |
54a93a72 | 287 | |
66f6448d | 288 | info->flags = LITTLE_BIT; |
54a93a72 | 289 | r = print_insn_shx (memaddr, info); |
66f6448d JW |
290 | return r; |
291 | } | |
292 | ||
293 | int | |
54a93a72 | 294 | print_insn_sh (memaddr, info) |
66f6448d JW |
295 | bfd_vma memaddr; |
296 | struct disassemble_info *info; | |
297 | { | |
298 | int r; | |
54a93a72 | 299 | |
66f6448d | 300 | info->flags = 0; |
54a93a72 | 301 | r = print_insn_shx (memaddr, info); |
66f6448d JW |
302 | return r; |
303 | } |