Revision | 7b1a81e593f07f99548fb0888b62f1b4d953cb74 (tree) |
---|---|
Time | 2019-07-05 00:48:22 |
Author | Yoshinori Sato <ysato@user...> |
Commiter | Yoshinori Sato |
target/rx: RX disassembler
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190607091116.49044-5-ysato@users.sourceforge.jp>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
@@ -226,6 +226,10 @@ enum bfd_architecture | ||
226 | 226 | #define bfd_mach_nios2r2 2 |
227 | 227 | bfd_arch_lm32, /* Lattice Mico32 */ |
228 | 228 | #define bfd_mach_lm32 1 |
229 | + bfd_arch_rx, /* Renesas RX */ | |
230 | +#define bfd_mach_rx 0x75 | |
231 | +#define bfd_mach_rx_v2 0x76 | |
232 | +#define bfd_mach_rx_v3 0x77 | |
229 | 233 | bfd_arch_last |
230 | 234 | }; |
231 | 235 | #define bfd_mach_s390_31 31 |
@@ -433,6 +437,7 @@ int print_insn_little_nios2 (bfd_vma, disassemble_info*); | ||
433 | 437 | int print_insn_xtensa (bfd_vma, disassemble_info*); |
434 | 438 | int print_insn_riscv32 (bfd_vma, disassemble_info*); |
435 | 439 | int print_insn_riscv64 (bfd_vma, disassemble_info*); |
440 | +int print_insn_rx(bfd_vma, disassemble_info *); | |
436 | 441 | |
437 | 442 | #if 0 |
438 | 443 | /* Fetch the disassembler for a given BFD, if that support is available. */ |
@@ -0,0 +1,1480 @@ | ||
1 | +/* | |
2 | + * Renesas RX Disassembler | |
3 | + * | |
4 | + * Copyright (c) 2019 Yoshinori Sato <ysato@users.sourceforge.jp> | |
5 | + * | |
6 | + * This program is free software; you can redistribute it and/or modify it | |
7 | + * under the terms and conditions of the GNU General Public License, | |
8 | + * version 2 or later, as published by the Free Software Foundation. | |
9 | + * | |
10 | + * This program is distributed in the hope it will be useful, but WITHOUT | |
11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
13 | + * more details. | |
14 | + * | |
15 | + * You should have received a copy of the GNU General Public License along with | |
16 | + * this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | + */ | |
18 | + | |
19 | +#include "qemu/osdep.h" | |
20 | +#include "disas/dis-asm.h" | |
21 | +#include "qemu/bitops.h" | |
22 | +#include "cpu.h" | |
23 | + | |
24 | +typedef struct DisasContext { | |
25 | + disassemble_info *dis; | |
26 | + uint32_t addr; | |
27 | + uint32_t pc; | |
28 | +} DisasContext; | |
29 | + | |
30 | + | |
31 | +static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn, | |
32 | + int i, int n) | |
33 | +{ | |
34 | + bfd_byte buf; | |
35 | + while (++i <= n) { | |
36 | + ctx->dis->read_memory_func(ctx->addr++, &buf, 1, ctx->dis); | |
37 | + insn |= buf << (32 - i * 8); | |
38 | + } | |
39 | + return insn; | |
40 | +} | |
41 | + | |
42 | +static int32_t li(DisasContext *ctx, int sz) | |
43 | +{ | |
44 | + int32_t addr; | |
45 | + bfd_byte buf[4]; | |
46 | + addr = ctx->addr; | |
47 | + | |
48 | + switch (sz) { | |
49 | + case 1: | |
50 | + ctx->addr += 1; | |
51 | + ctx->dis->read_memory_func(addr, buf, 1, ctx->dis); | |
52 | + return (int8_t)buf[0]; | |
53 | + case 2: | |
54 | + ctx->addr += 2; | |
55 | + ctx->dis->read_memory_func(addr, buf, 2, ctx->dis); | |
56 | + return ldsw_le_p(buf); | |
57 | + case 3: | |
58 | + ctx->addr += 3; | |
59 | + ctx->dis->read_memory_func(addr, buf, 3, ctx->dis); | |
60 | + return (int8_t)buf[2] << 16 | lduw_le_p(buf); | |
61 | + case 0: | |
62 | + ctx->addr += 4; | |
63 | + ctx->dis->read_memory_func(addr, buf, 4, ctx->dis); | |
64 | + return ldl_le_p(buf); | |
65 | + default: | |
66 | + g_assert_not_reached(); | |
67 | + } | |
68 | +} | |
69 | + | |
70 | +static int bdsp_s(DisasContext *ctx, int d) | |
71 | +{ | |
72 | + /* | |
73 | + * 0 -> 8 | |
74 | + * 1 -> 9 | |
75 | + * 2 -> 10 | |
76 | + * 3 -> 3 | |
77 | + * : | |
78 | + * 7 -> 7 | |
79 | + */ | |
80 | + if (d < 3) { | |
81 | + d += 8; | |
82 | + } | |
83 | + return d; | |
84 | +} | |
85 | + | |
86 | +/* Include the auto-generated decoder. */ | |
87 | +#include "decode.inc.c" | |
88 | + | |
89 | +#define prt(...) (ctx->dis->fprintf_func)((ctx->dis->stream), __VA_ARGS__) | |
90 | + | |
91 | +#define RX_MEMORY_BYTE 0 | |
92 | +#define RX_MEMORY_WORD 1 | |
93 | +#define RX_MEMORY_LONG 2 | |
94 | + | |
95 | +#define RX_IM_BYTE 0 | |
96 | +#define RX_IM_WORD 1 | |
97 | +#define RX_IM_LONG 2 | |
98 | +#define RX_IM_UWORD 3 | |
99 | + | |
100 | +static const char size[] = {'b', 'w', 'l'}; | |
101 | +static const char cond[][4] = { | |
102 | + "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n", | |
103 | + "ge", "lt", "gt", "le", "o", "no", "ra", "f" | |
104 | +}; | |
105 | +static const char psw[] = { | |
106 | + 'c', 'z', 's', 'o', 0, 0, 0, 0, | |
107 | + 'i', 'u', 0, 0, 0, 0, 0, 0, | |
108 | +}; | |
109 | + | |
110 | +static uint32_t rx_index_addr(int ld, int size, DisasContext *ctx) | |
111 | +{ | |
112 | + bfd_byte buf[2]; | |
113 | + switch (ld) { | |
114 | + case 0: | |
115 | + return 0; | |
116 | + case 1: | |
117 | + ctx->dis->read_memory_func(ctx->addr, buf, 1, ctx->dis); | |
118 | + ctx->addr += 1; | |
119 | + return ((uint8_t)buf[0]) << size; | |
120 | + case 2: | |
121 | + ctx->dis->read_memory_func(ctx->addr, buf, 2, ctx->dis); | |
122 | + ctx->addr += 2; | |
123 | + return lduw_le_p(buf) << size; | |
124 | + } | |
125 | + g_assert_not_reached(); | |
126 | +} | |
127 | + | |
128 | +static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd) | |
129 | +{ | |
130 | + int dsp; | |
131 | + static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"}; | |
132 | + if (ld < 3) { | |
133 | + switch (mi) { | |
134 | + case 4: | |
135 | + /* dsp[rs].ub */ | |
136 | + dsp = rx_index_addr(ld, RX_MEMORY_BYTE, ctx); | |
137 | + break; | |
138 | + case 3: | |
139 | + /* dsp[rs].uw */ | |
140 | + dsp = rx_index_addr(ld, RX_MEMORY_WORD, ctx); | |
141 | + break; | |
142 | + default: | |
143 | + /* dsp[rs].b */ | |
144 | + /* dsp[rs].w */ | |
145 | + /* dsp[rs].l */ | |
146 | + dsp = rx_index_addr(ld, mi, ctx); | |
147 | + break; | |
148 | + } | |
149 | + if (dsp > 0) { | |
150 | + prt("%d", dsp); | |
151 | + } | |
152 | + prt("[r%d]%s", rs, sizes[mi]); | |
153 | + } else { | |
154 | + prt("r%d", rs); | |
155 | + } | |
156 | + prt(", r%d", rd); | |
157 | +} | |
158 | + | |
159 | +static void prt_ir(DisasContext *ctx, const char *insn, int imm, int rd) | |
160 | +{ | |
161 | + if (imm < 0x100) { | |
162 | + prt("%s\t#%d, r%d", insn, imm, rd); | |
163 | + } else { | |
164 | + prt("%s\t#0x%08x, r%d", insn, imm, rd); | |
165 | + } | |
166 | +} | |
167 | + | |
168 | +/* mov.[bwl] rs,dsp:[rd] */ | |
169 | +static bool trans_MOV_rm(DisasContext *ctx, arg_MOV_rm *a) | |
170 | +{ | |
171 | + if (a->dsp > 0) { | |
172 | + prt("mov.%c\tr%d,%d[r%d]", | |
173 | + size[a->sz], a->rs, a->dsp << a->sz, a->rd); | |
174 | + } else { | |
175 | + prt("mov.%c\tr%d,[r%d]", | |
176 | + size[a->sz], a->rs, a->rd); | |
177 | + } | |
178 | + return true; | |
179 | +} | |
180 | + | |
181 | +/* mov.[bwl] dsp:[rs],rd */ | |
182 | +static bool trans_MOV_mr(DisasContext *ctx, arg_MOV_mr *a) | |
183 | +{ | |
184 | + if (a->dsp > 0) { | |
185 | + prt("mov.%c\t%d[r%d], r%d", | |
186 | + size[a->sz], a->dsp << a->sz, a->rs, a->rd); | |
187 | + } else { | |
188 | + prt("mov.%c\t[r%d], r%d", | |
189 | + size[a->sz], a->rs, a->rd); | |
190 | + } | |
191 | + return true; | |
192 | +} | |
193 | + | |
194 | +/* mov.l #uimm4,rd */ | |
195 | +/* mov.l #uimm8,rd */ | |
196 | +/* mov.l #imm,rd */ | |
197 | +static bool trans_MOV_ir(DisasContext *ctx, arg_MOV_ir *a) | |
198 | +{ | |
199 | + prt_ir(ctx, "mov.l", a->imm, a->rd); | |
200 | + return true; | |
201 | +} | |
202 | + | |
203 | +/* mov.[bwl] #uimm8,dsp:[rd] */ | |
204 | +/* mov #imm, dsp:[rd] */ | |
205 | +static bool trans_MOV_im(DisasContext *ctx, arg_MOV_im *a) | |
206 | +{ | |
207 | + if (a->dsp > 0) { | |
208 | + prt("mov.%c\t#%d,%d[r%d]", | |
209 | + size[a->sz], a->imm, a->dsp << a->sz, a->rd); | |
210 | + } else { | |
211 | + prt("mov.%c\t#%d,[r%d]", | |
212 | + size[a->sz], a->imm, a->rd); | |
213 | + } | |
214 | + return true; | |
215 | +} | |
216 | + | |
217 | +/* mov.[bwl] [ri,rb],rd */ | |
218 | +static bool trans_MOV_ar(DisasContext *ctx, arg_MOV_ar *a) | |
219 | +{ | |
220 | + prt("mov.%c\t[r%d,r%d], r%d", size[a->sz], a->ri, a->rb, a->rd); | |
221 | + return true; | |
222 | +} | |
223 | + | |
224 | +/* mov.[bwl] rd,[ri,rb] */ | |
225 | +static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a) | |
226 | +{ | |
227 | + prt("mov.%c\tr%d, [r%d, r%d]", size[a->sz], a->rs, a->ri, a->rb); | |
228 | + return true; | |
229 | +} | |
230 | + | |
231 | + | |
232 | +/* mov.[bwl] dsp:[rs],dsp:[rd] */ | |
233 | +/* mov.[bwl] rs,dsp:[rd] */ | |
234 | +/* mov.[bwl] dsp:[rs],rd */ | |
235 | +/* mov.[bwl] rs,rd */ | |
236 | +static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a) | |
237 | +{ | |
238 | + int dsp; | |
239 | + | |
240 | + prt("mov.%c\t", size[a->sz]); | |
241 | + if (a->lds == 3 && a->ldd == 3) { | |
242 | + /* mov.[bwl] rs,rd */ | |
243 | + prt("r%d, r%d", a->rs, a->rd); | |
244 | + return true; | |
245 | + } | |
246 | + if (a->lds == 3) { | |
247 | + prt("r%d, ", a->rd); | |
248 | + dsp = rx_index_addr(a->ldd, a->sz, ctx); | |
249 | + if (dsp > 0) { | |
250 | + prt("%d", dsp); | |
251 | + } | |
252 | + prt("[r%d]", a->rs); | |
253 | + } else if (a->ldd == 3) { | |
254 | + dsp = rx_index_addr(a->lds, a->sz, ctx); | |
255 | + if (dsp > 0) { | |
256 | + prt("%d", dsp); | |
257 | + } | |
258 | + prt("[r%d], r%d", a->rs, a->rd); | |
259 | + } else { | |
260 | + dsp = rx_index_addr(a->lds, a->sz, ctx); | |
261 | + if (dsp > 0) { | |
262 | + prt("%d", dsp); | |
263 | + } | |
264 | + prt("[r%d], ", a->rs); | |
265 | + dsp = rx_index_addr(a->ldd, a->sz, ctx); | |
266 | + if (dsp > 0) { | |
267 | + prt("%d", dsp); | |
268 | + } | |
269 | + prt("[r%d]", a->rd); | |
270 | + } | |
271 | + return true; | |
272 | +} | |
273 | + | |
274 | +/* mov.[bwl] rs,[rd+] */ | |
275 | +/* mov.[bwl] rs,[-rd] */ | |
276 | +static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a) | |
277 | +{ | |
278 | + prt("mov.%c\tr%d, ", size[a->sz], a->rs); | |
279 | + prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd); | |
280 | + return true; | |
281 | +} | |
282 | + | |
283 | +/* mov.[bwl] [rd+],rs */ | |
284 | +/* mov.[bwl] [-rd],rs */ | |
285 | +static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a) | |
286 | +{ | |
287 | + prt("mov.%c\t", size[a->sz]); | |
288 | + prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd); | |
289 | + prt(", r%d", a->rs); | |
290 | + return true; | |
291 | +} | |
292 | + | |
293 | +/* movu.[bw] dsp5:[rs],rd */ | |
294 | +static bool trans_MOVU_mr(DisasContext *ctx, arg_MOVU_mr *a) | |
295 | +{ | |
296 | + if (a->dsp > 0) { | |
297 | + prt("movu.%c\t%d[r%d], r%d", size[a->sz], | |
298 | + a->dsp << a->sz, a->rs, a->rd); | |
299 | + } else { | |
300 | + prt("movu.%c\t[r%d], r%d", size[a->sz], a->rs, a->rd); | |
301 | + } | |
302 | + return true; | |
303 | +} | |
304 | + | |
305 | +/* movu.[bw] rs,rd */ | |
306 | +static bool trans_MOVU_rr(DisasContext *ctx, arg_MOVU_rr *a) | |
307 | +{ | |
308 | + prt("movu.%c\tr%d, r%d", size[a->sz], a->rs, a->rd); | |
309 | + return true; | |
310 | +} | |
311 | + | |
312 | +/* movu.[bw] [ri,rb],rd */ | |
313 | +static bool trans_MOVU_ar(DisasContext *ctx, arg_MOVU_ar *a) | |
314 | +{ | |
315 | + prt("mov.%c\t[r%d,r%d], r%d", size[a->sz], a->ri, a->rb, a->rd); | |
316 | + return true; | |
317 | +} | |
318 | + | |
319 | +/* movu.[bw] [rs+],rd */ | |
320 | +/* movu.[bw] [-rs],rd */ | |
321 | +static bool trans_MOVU_pr(DisasContext *ctx, arg_MOVU_pr *a) | |
322 | +{ | |
323 | + prt("movu.%c\t", size[a->sz]); | |
324 | + prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd); | |
325 | + prt(", r%d", a->rs); | |
326 | + return true; | |
327 | +} | |
328 | + | |
329 | +/* pop rd */ | |
330 | +static bool trans_POP(DisasContext *ctx, arg_POP *a) | |
331 | +{ | |
332 | + prt("pop\tr%d", a->rd); | |
333 | + return true; | |
334 | +} | |
335 | + | |
336 | +/* popc rx */ | |
337 | +static bool trans_POPC(DisasContext *ctx, arg_POPC *a) | |
338 | +{ | |
339 | + prt("pop\tr%s", rx_crname[a->cr]); | |
340 | + return true; | |
341 | +} | |
342 | + | |
343 | +/* popm rd-rd2 */ | |
344 | +static bool trans_POPM(DisasContext *ctx, arg_POPM *a) | |
345 | +{ | |
346 | + prt("popm\tr%d-r%d", a->rd, a->rd2); | |
347 | + return true; | |
348 | +} | |
349 | + | |
350 | +/* push rs */ | |
351 | +static bool trans_PUSH_r(DisasContext *ctx, arg_PUSH_r *a) | |
352 | +{ | |
353 | + prt("push\tr%d", a->rs); | |
354 | + return true; | |
355 | +} | |
356 | + | |
357 | +/* push dsp[rs] */ | |
358 | +static bool trans_PUSH_m(DisasContext *ctx, arg_PUSH_m *a) | |
359 | +{ | |
360 | + prt("push\t"); | |
361 | + int dsp = rx_index_addr(a->ld, a->sz, ctx); | |
362 | + if (dsp > 0) { | |
363 | + prt("%d", dsp); | |
364 | + } | |
365 | + prt("[r%d]", a->rs); | |
366 | + return true; | |
367 | +} | |
368 | + | |
369 | +/* pushc rx */ | |
370 | +static bool trans_PUSHC(DisasContext *ctx, arg_PUSHC *a) | |
371 | +{ | |
372 | + prt("push\t%s", rx_crname[a->cr]); | |
373 | + return true; | |
374 | +} | |
375 | + | |
376 | +/* pushm rs-rs2*/ | |
377 | +static bool trans_PUSHM(DisasContext *ctx, arg_PUSHM *a) | |
378 | +{ | |
379 | + prt("pushm\tr%d-r%d", a->rs, a->rs2); | |
380 | + return true; | |
381 | +} | |
382 | + | |
383 | +/* xchg rs,rd */ | |
384 | +static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a) | |
385 | +{ | |
386 | + prt("xchg\tr%d, r%d", a->rs, a->rd); | |
387 | + return true; | |
388 | +} | |
389 | +/* xchg dsp[rs].<mi>,rd */ | |
390 | +static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a) | |
391 | +{ | |
392 | + int dsp; | |
393 | + static const char msize[][4] = { | |
394 | + "b", "w", "l", "ub", "uw", | |
395 | + }; | |
396 | + | |
397 | + prt("xchg\t"); | |
398 | + dsp = rx_index_addr(a->ld, a->mi, ctx); | |
399 | + if (dsp > 0) { | |
400 | + prt("%d", dsp); | |
401 | + } | |
402 | + prt("[r%d].%s, r%d", a->rs, msize[a->mi], a->rd); | |
403 | + return true; | |
404 | +} | |
405 | + | |
406 | +/* stz #imm,rd */ | |
407 | +static bool trans_STZ(DisasContext *ctx, arg_STZ *a) | |
408 | +{ | |
409 | + prt_ir(ctx, "stz", a->imm, a->rd); | |
410 | + return true; | |
411 | +} | |
412 | + | |
413 | +/* stnz #imm,rd */ | |
414 | +static bool trans_STNZ(DisasContext *ctx, arg_STNZ *a) | |
415 | +{ | |
416 | + prt_ir(ctx, "stnz", a->imm, a->rd); | |
417 | + return true; | |
418 | +} | |
419 | + | |
420 | +/* rtsd #imm */ | |
421 | +static bool trans_RTSD_i(DisasContext *ctx, arg_RTSD_i *a) | |
422 | +{ | |
423 | + prt("rtsd\t#%d", a->imm << 2); | |
424 | + return true; | |
425 | +} | |
426 | + | |
427 | +/* rtsd #imm, rd-rd2 */ | |
428 | +static bool trans_RTSD_irr(DisasContext *ctx, arg_RTSD_irr *a) | |
429 | +{ | |
430 | + prt("rtsd\t#%d, r%d - r%d", a->imm << 2, a->rd, a->rd2); | |
431 | + return true; | |
432 | +} | |
433 | + | |
434 | +/* and #uimm:4, rd */ | |
435 | +/* and #imm, rd */ | |
436 | +static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a) | |
437 | +{ | |
438 | + prt_ir(ctx, "and", a->imm, a->rd); | |
439 | + return true; | |
440 | +} | |
441 | + | |
442 | +/* and dsp[rs], rd */ | |
443 | +/* and rs,rd */ | |
444 | +static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *a) | |
445 | +{ | |
446 | + prt("and\t"); | |
447 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
448 | + return true; | |
449 | +} | |
450 | + | |
451 | +/* and rs,rs2,rd */ | |
452 | +static bool trans_AND_rrr(DisasContext *ctx, arg_AND_rrr *a) | |
453 | +{ | |
454 | + prt("and\tr%d,r%d, r%d", a->rs, a->rs2, a->rd); | |
455 | + return true; | |
456 | +} | |
457 | + | |
458 | +/* or #uimm:4, rd */ | |
459 | +/* or #imm, rd */ | |
460 | +static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a) | |
461 | +{ | |
462 | + prt_ir(ctx, "or", a->imm, a->rd); | |
463 | + return true; | |
464 | +} | |
465 | + | |
466 | +/* or dsp[rs], rd */ | |
467 | +/* or rs,rd */ | |
468 | +static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *a) | |
469 | +{ | |
470 | + prt("or\t"); | |
471 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
472 | + return true; | |
473 | +} | |
474 | + | |
475 | +/* or rs,rs2,rd */ | |
476 | +static bool trans_OR_rrr(DisasContext *ctx, arg_OR_rrr *a) | |
477 | +{ | |
478 | + prt("or\tr%d, r%d, r%d", a->rs, a->rs2, a->rd); | |
479 | + return true; | |
480 | +} | |
481 | + | |
482 | +/* xor #imm, rd */ | |
483 | +static bool trans_XOR_ir(DisasContext *ctx, arg_XOR_ir *a) | |
484 | +{ | |
485 | + prt_ir(ctx, "xor", a->imm, a->rd); | |
486 | + return true; | |
487 | +} | |
488 | + | |
489 | +/* xor dsp[rs], rd */ | |
490 | +/* xor rs,rd */ | |
491 | +static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a) | |
492 | +{ | |
493 | + prt("xor\t"); | |
494 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
495 | + return true; | |
496 | +} | |
497 | + | |
498 | +/* tst #imm, rd */ | |
499 | +static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a) | |
500 | +{ | |
501 | + prt_ir(ctx, "tst", a->imm, a->rd); | |
502 | + return true; | |
503 | +} | |
504 | + | |
505 | +/* tst dsp[rs], rd */ | |
506 | +/* tst rs, rd */ | |
507 | +static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a) | |
508 | +{ | |
509 | + prt("tst\t"); | |
510 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
511 | + return true; | |
512 | +} | |
513 | + | |
514 | +/* not rd */ | |
515 | +/* not rs, rd */ | |
516 | +static bool trans_NOT_rr(DisasContext *ctx, arg_NOT_rr *a) | |
517 | +{ | |
518 | + prt("not\t"); | |
519 | + if (a->rs != a->rd) { | |
520 | + prt("r%d, ", a->rs); | |
521 | + } | |
522 | + prt("r%d", a->rd); | |
523 | + return true; | |
524 | +} | |
525 | + | |
526 | +/* neg rd */ | |
527 | +/* neg rs, rd */ | |
528 | +static bool trans_NEG_rr(DisasContext *ctx, arg_NEG_rr *a) | |
529 | +{ | |
530 | + prt("neg\t"); | |
531 | + if (a->rs != a->rd) { | |
532 | + prt("r%d, ", a->rs); | |
533 | + } | |
534 | + prt("r%d", a->rd); | |
535 | + return true; | |
536 | +} | |
537 | + | |
538 | +/* adc #imm, rd */ | |
539 | +static bool trans_ADC_ir(DisasContext *ctx, arg_ADC_ir *a) | |
540 | +{ | |
541 | + prt_ir(ctx, "adc", a->imm, a->rd); | |
542 | + return true; | |
543 | +} | |
544 | + | |
545 | +/* adc rs, rd */ | |
546 | +static bool trans_ADC_rr(DisasContext *ctx, arg_ADC_rr *a) | |
547 | +{ | |
548 | + prt("adc\tr%d, r%d", a->rs, a->rd); | |
549 | + return true; | |
550 | +} | |
551 | + | |
552 | +/* adc dsp[rs], rd */ | |
553 | +static bool trans_ADC_mr(DisasContext *ctx, arg_ADC_mr *a) | |
554 | +{ | |
555 | + int dsp; | |
556 | + prt("adc\t"); | |
557 | + dsp = rx_index_addr(a->ld, 2, ctx); | |
558 | + if (dsp > 0) { | |
559 | + prt("%d", dsp); | |
560 | + } | |
561 | + prt("[r%d], r%d", a->rs, a->rd); | |
562 | + return true; | |
563 | +} | |
564 | + | |
565 | +/* add #uimm4, rd */ | |
566 | +/* add #imm, rs, rd */ | |
567 | +static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a) | |
568 | +{ | |
569 | + if (a->imm < 0x10 && a->rs2 == a->rd) { | |
570 | + prt("add\t#%d, r%d", a->imm, a->rd); | |
571 | + } else { | |
572 | + prt("add\t#0x%08x, r%d, r%d", a->imm, a->rs2, a->rd); | |
573 | + } | |
574 | + return true; | |
575 | +} | |
576 | + | |
577 | +/* add rs, rd */ | |
578 | +/* add dsp[rs], rd */ | |
579 | +static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a) | |
580 | +{ | |
581 | + prt("add\t"); | |
582 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
583 | + return true; | |
584 | +} | |
585 | + | |
586 | +/* add rs, rs2, rd */ | |
587 | +static bool trans_ADD_rrr(DisasContext *ctx, arg_ADD_rrr *a) | |
588 | +{ | |
589 | + prt("add\tr%d, r%d, r%d", a->rs, a->rs2, a->rd); | |
590 | + return true; | |
591 | +} | |
592 | + | |
593 | +/* cmp #imm4, rd */ | |
594 | +/* cmp #imm8, rd */ | |
595 | +/* cmp #imm, rs2 */ | |
596 | +static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a) | |
597 | +{ | |
598 | + prt_ir(ctx, "cmp", a->imm, a->rs2); | |
599 | + return true; | |
600 | +} | |
601 | + | |
602 | +/* cmp rs, rs2 */ | |
603 | +/* cmp dsp[rs], rs2 */ | |
604 | +static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a) | |
605 | +{ | |
606 | + prt("cmp\t"); | |
607 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
608 | + return true; | |
609 | +} | |
610 | + | |
611 | +/* sub #imm4, rd */ | |
612 | +static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a) | |
613 | +{ | |
614 | + prt("sub\t#%d, r%d", a->imm, a->rd); | |
615 | + return true; | |
616 | +} | |
617 | + | |
618 | +/* sub rs, rd */ | |
619 | +/* sub dsp[rs], rd */ | |
620 | +static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *a) | |
621 | +{ | |
622 | + prt("sub\t"); | |
623 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
624 | + return true; | |
625 | +} | |
626 | + | |
627 | +/* sub rs, rs2, rd */ | |
628 | +static bool trans_SUB_rrr(DisasContext *ctx, arg_SUB_rrr *a) | |
629 | +{ | |
630 | + prt("sub\tr%d, r%d, r%d", a->rs, a->rs2, a->rd); | |
631 | + return true; | |
632 | +} | |
633 | + | |
634 | +/* sbb rs, rd */ | |
635 | +static bool trans_SBB_rr(DisasContext *ctx, arg_SBB_rr *a) | |
636 | +{ | |
637 | + prt("sbb\tr%d, r%d", a->rs, a->rd); | |
638 | + return true; | |
639 | +} | |
640 | + | |
641 | +/* sbb dsp[rs], rd */ | |
642 | +static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a) | |
643 | +{ | |
644 | + prt("sbb\t"); | |
645 | + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); | |
646 | + return true; | |
647 | +} | |
648 | + | |
649 | +/* abs rd */ | |
650 | +/* abs rs, rd */ | |
651 | +static bool trans_ABS_rr(DisasContext *ctx, arg_ABS_rr *a) | |
652 | +{ | |
653 | + prt("abs\t"); | |
654 | + if (a->rs == a->rd) { | |
655 | + prt("r%d", a->rd); | |
656 | + } else { | |
657 | + prt("r%d, r%d", a->rs, a->rd); | |
658 | + } | |
659 | + return true; | |
660 | +} | |
661 | + | |
662 | +/* max #imm, rd */ | |
663 | +static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a) | |
664 | +{ | |
665 | + prt_ir(ctx, "max", a->imm, a->rd); | |
666 | + return true; | |
667 | +} | |
668 | + | |
669 | +/* max rs, rd */ | |
670 | +/* max dsp[rs], rd */ | |
671 | +static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a) | |
672 | +{ | |
673 | + prt("max\t"); | |
674 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
675 | + return true; | |
676 | +} | |
677 | + | |
678 | +/* min #imm, rd */ | |
679 | +static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a) | |
680 | +{ | |
681 | + prt_ir(ctx, "min", a->imm, a->rd); | |
682 | + return true; | |
683 | +} | |
684 | + | |
685 | +/* min rs, rd */ | |
686 | +/* min dsp[rs], rd */ | |
687 | +static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a) | |
688 | +{ | |
689 | + prt("max\t"); | |
690 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
691 | + return true; | |
692 | +} | |
693 | + | |
694 | +/* mul #uimm4, rd */ | |
695 | +/* mul #imm, rd */ | |
696 | +static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a) | |
697 | +{ | |
698 | + prt_ir(ctx, "mul", a->imm, a->rd); | |
699 | + return true; | |
700 | +} | |
701 | + | |
702 | +/* mul rs, rd */ | |
703 | +/* mul dsp[rs], rd */ | |
704 | +static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *a) | |
705 | +{ | |
706 | + prt("mul\t"); | |
707 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
708 | + return true; | |
709 | +} | |
710 | + | |
711 | +/* mul rs, rs2, rd */ | |
712 | +static bool trans_MUL_rrr(DisasContext *ctx, arg_MUL_rrr *a) | |
713 | +{ | |
714 | + prt("mul\tr%d,r%d,r%d", a->rs, a->rs2, a->rd); | |
715 | + return true; | |
716 | +} | |
717 | + | |
718 | +/* emul #imm, rd */ | |
719 | +static bool trans_EMUL_ir(DisasContext *ctx, arg_EMUL_ir *a) | |
720 | +{ | |
721 | + prt_ir(ctx, "emul", a->imm, a->rd); | |
722 | + return true; | |
723 | +} | |
724 | + | |
725 | +/* emul rs, rd */ | |
726 | +/* emul dsp[rs], rd */ | |
727 | +static bool trans_EMUL_mr(DisasContext *ctx, arg_EMUL_mr *a) | |
728 | +{ | |
729 | + prt("emul\t"); | |
730 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
731 | + return true; | |
732 | +} | |
733 | + | |
734 | +/* emulu #imm, rd */ | |
735 | +static bool trans_EMULU_ir(DisasContext *ctx, arg_EMULU_ir *a) | |
736 | +{ | |
737 | + prt_ir(ctx, "emulu", a->imm, a->rd); | |
738 | + return true; | |
739 | +} | |
740 | + | |
741 | +/* emulu rs, rd */ | |
742 | +/* emulu dsp[rs], rd */ | |
743 | +static bool trans_EMULU_mr(DisasContext *ctx, arg_EMULU_mr *a) | |
744 | +{ | |
745 | + prt("emulu\t"); | |
746 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
747 | + return true; | |
748 | +} | |
749 | + | |
750 | +/* div #imm, rd */ | |
751 | +static bool trans_DIV_ir(DisasContext *ctx, arg_DIV_ir *a) | |
752 | +{ | |
753 | + prt_ir(ctx, "div", a->imm, a->rd); | |
754 | + return true; | |
755 | +} | |
756 | + | |
757 | +/* div rs, rd */ | |
758 | +/* div dsp[rs], rd */ | |
759 | +static bool trans_DIV_mr(DisasContext *ctx, arg_DIV_mr *a) | |
760 | +{ | |
761 | + prt("div\t"); | |
762 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
763 | + return true; | |
764 | +} | |
765 | + | |
766 | +/* divu #imm, rd */ | |
767 | +static bool trans_DIVU_ir(DisasContext *ctx, arg_DIVU_ir *a) | |
768 | +{ | |
769 | + prt_ir(ctx, "divu", a->imm, a->rd); | |
770 | + return true; | |
771 | +} | |
772 | + | |
773 | +/* divu rs, rd */ | |
774 | +/* divu dsp[rs], rd */ | |
775 | +static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a) | |
776 | +{ | |
777 | + prt("divu\t"); | |
778 | + operand(ctx, a->ld, a->mi, a->rs, a->rd); | |
779 | + return true; | |
780 | +} | |
781 | + | |
782 | + | |
783 | +/* shll #imm:5, rd */ | |
784 | +/* shll #imm:5, rs, rd */ | |
785 | +static bool trans_SHLL_irr(DisasContext *ctx, arg_SHLL_irr *a) | |
786 | +{ | |
787 | + prt("shll\t#%d, ", a->imm); | |
788 | + if (a->rs2 != a->rd) { | |
789 | + prt("r%d, ", a->rs2); | |
790 | + } | |
791 | + prt("r%d", a->rd); | |
792 | + return true; | |
793 | +} | |
794 | + | |
795 | +/* shll rs, rd */ | |
796 | +static bool trans_SHLL_rr(DisasContext *ctx, arg_SHLL_rr *a) | |
797 | +{ | |
798 | + prt("shll\tr%d, r%d", a->rs, a->rd); | |
799 | + return true; | |
800 | +} | |
801 | + | |
802 | +/* shar #imm:5, rd */ | |
803 | +/* shar #imm:5, rs, rd */ | |
804 | +static bool trans_SHAR_irr(DisasContext *ctx, arg_SHAR_irr *a) | |
805 | +{ | |
806 | + prt("shar\t#%d,", a->imm); | |
807 | + if (a->rs2 != a->rd) { | |
808 | + prt("r%d, ", a->rs2); | |
809 | + } | |
810 | + prt("r%d", a->rd); | |
811 | + return true; | |
812 | +} | |
813 | + | |
814 | +/* shar rs, rd */ | |
815 | +static bool trans_SHAR_rr(DisasContext *ctx, arg_SHAR_rr *a) | |
816 | +{ | |
817 | + prt("shar\tr%d, r%d", a->rs, a->rd); | |
818 | + return true; | |
819 | +} | |
820 | + | |
821 | +/* shlr #imm:5, rd */ | |
822 | +/* shlr #imm:5, rs, rd */ | |
823 | +static bool trans_SHLR_irr(DisasContext *ctx, arg_SHLR_irr *a) | |
824 | +{ | |
825 | + prt("shlr\t#%d, ", a->imm); | |
826 | + if (a->rs2 != a->rd) { | |
827 | + prt("r%d, ", a->rs2); | |
828 | + } | |
829 | + prt("r%d", a->rd); | |
830 | + return true; | |
831 | +} | |
832 | + | |
833 | +/* shlr rs, rd */ | |
834 | +static bool trans_SHLR_rr(DisasContext *ctx, arg_SHLR_rr *a) | |
835 | +{ | |
836 | + prt("shlr\tr%d, r%d", a->rs, a->rd); | |
837 | + return true; | |
838 | +} | |
839 | + | |
840 | +/* rolc rd */ | |
841 | +static bool trans_ROLC(DisasContext *ctx, arg_ROLC *a) | |
842 | +{ | |
843 | + prt("rorc\tr%d", a->rd); | |
844 | + return true; | |
845 | +} | |
846 | + | |
847 | +/* rorc rd */ | |
848 | +static bool trans_RORC(DisasContext *ctx, arg_RORC *a) | |
849 | +{ | |
850 | + prt("rorc\tr%d", a->rd); | |
851 | + return true; | |
852 | +} | |
853 | + | |
854 | +/* rotl #imm, rd */ | |
855 | +static bool trans_ROTL_ir(DisasContext *ctx, arg_ROTL_ir *a) | |
856 | +{ | |
857 | + prt("rotl\t#%d, r%d", a->imm, a->rd); | |
858 | + return true; | |
859 | +} | |
860 | + | |
861 | +/* rotl rs, rd */ | |
862 | +static bool trans_ROTL_rr(DisasContext *ctx, arg_ROTL_rr *a) | |
863 | +{ | |
864 | + prt("rotl\tr%d, r%d", a->rs, a->rd); | |
865 | + return true; | |
866 | +} | |
867 | + | |
868 | +/* rotr #imm, rd */ | |
869 | +static bool trans_ROTR_ir(DisasContext *ctx, arg_ROTR_ir *a) | |
870 | +{ | |
871 | + prt("rotr\t#%d, r%d", a->imm, a->rd); | |
872 | + return true; | |
873 | +} | |
874 | + | |
875 | +/* rotr rs, rd */ | |
876 | +static bool trans_ROTR_rr(DisasContext *ctx, arg_ROTR_rr *a) | |
877 | +{ | |
878 | + prt("rotr\tr%d, r%d", a->rs, a->rd); | |
879 | + return true; | |
880 | +} | |
881 | + | |
882 | +/* revl rs, rd */ | |
883 | +static bool trans_REVL(DisasContext *ctx, arg_REVL *a) | |
884 | +{ | |
885 | + prt("revl\tr%d, r%d", a->rs, a->rd); | |
886 | + return true; | |
887 | +} | |
888 | + | |
889 | +/* revw rs, rd */ | |
890 | +static bool trans_REVW(DisasContext *ctx, arg_REVW *a) | |
891 | +{ | |
892 | + prt("revw\tr%d, r%d", a->rs, a->rd); | |
893 | + return true; | |
894 | +} | |
895 | + | |
896 | +/* conditional branch helper */ | |
897 | +static void rx_bcnd_main(DisasContext *ctx, int cd, int len, int dst) | |
898 | +{ | |
899 | + static const char sz[] = {'s', 'b', 'w', 'a'}; | |
900 | + prt("b%s.%c\t%08x", cond[cd], sz[len - 1], ctx->pc + dst); | |
901 | +} | |
902 | + | |
903 | +/* beq dsp:3 / bne dsp:3 */ | |
904 | +/* beq dsp:8 / bne dsp:8 */ | |
905 | +/* bc dsp:8 / bnc dsp:8 */ | |
906 | +/* bgtu dsp:8 / bleu dsp:8 */ | |
907 | +/* bpz dsp:8 / bn dsp:8 */ | |
908 | +/* bge dsp:8 / blt dsp:8 */ | |
909 | +/* bgt dsp:8 / ble dsp:8 */ | |
910 | +/* bo dsp:8 / bno dsp:8 */ | |
911 | +/* beq dsp:16 / bne dsp:16 */ | |
912 | +static bool trans_BCnd(DisasContext *ctx, arg_BCnd *a) | |
913 | +{ | |
914 | + rx_bcnd_main(ctx, a->cd, a->sz, a->dsp); | |
915 | + return true; | |
916 | +} | |
917 | + | |
918 | +/* bra dsp:3 */ | |
919 | +/* bra dsp:8 */ | |
920 | +/* bra dsp:16 */ | |
921 | +/* bra dsp:24 */ | |
922 | +static bool trans_BRA(DisasContext *ctx, arg_BRA *a) | |
923 | +{ | |
924 | + rx_bcnd_main(ctx, 14, a->sz, a->dsp); | |
925 | + return true; | |
926 | +} | |
927 | + | |
928 | +/* bra rs */ | |
929 | +static bool trans_BRA_l(DisasContext *ctx, arg_BRA_l *a) | |
930 | +{ | |
931 | + prt("bra.l\tr%d", a->rd); | |
932 | + return true; | |
933 | +} | |
934 | + | |
935 | +/* jmp rs */ | |
936 | +static bool trans_JMP(DisasContext *ctx, arg_JMP *a) | |
937 | +{ | |
938 | + prt("jmp\tr%d", a->rs); | |
939 | + return true; | |
940 | +} | |
941 | + | |
942 | +/* jsr rs */ | |
943 | +static bool trans_JSR(DisasContext *ctx, arg_JSR *a) | |
944 | +{ | |
945 | + prt("jsr\tr%d", a->rs); | |
946 | + return true; | |
947 | +} | |
948 | + | |
949 | +/* bsr dsp:16 */ | |
950 | +/* bsr dsp:24 */ | |
951 | +static bool trans_BSR(DisasContext *ctx, arg_BSR *a) | |
952 | +{ | |
953 | + static const char sz[] = {'w', 'a'}; | |
954 | + prt("bsr.%c\t%08x", sz[a->sz - 3], ctx->pc + a->dsp); | |
955 | + return true; | |
956 | +} | |
957 | + | |
958 | +/* bsr rs */ | |
959 | +static bool trans_BSR_l(DisasContext *ctx, arg_BSR_l *a) | |
960 | +{ | |
961 | + prt("bsr.l\tr%d", a->rd); | |
962 | + return true; | |
963 | +} | |
964 | + | |
965 | +/* rts */ | |
966 | +static bool trans_RTS(DisasContext *ctx, arg_RTS *a) | |
967 | +{ | |
968 | + prt("rts"); | |
969 | + return true; | |
970 | +} | |
971 | + | |
972 | +/* nop */ | |
973 | +static bool trans_NOP(DisasContext *ctx, arg_NOP *a) | |
974 | +{ | |
975 | + prt("nop"); | |
976 | + return true; | |
977 | +} | |
978 | + | |
979 | +/* scmpu */ | |
980 | +static bool trans_SCMPU(DisasContext *ctx, arg_SCMPU *a) | |
981 | +{ | |
982 | + prt("scmpu"); | |
983 | + return true; | |
984 | +} | |
985 | + | |
986 | +/* smovu */ | |
987 | +static bool trans_SMOVU(DisasContext *ctx, arg_SMOVU *a) | |
988 | +{ | |
989 | + prt("smovu"); | |
990 | + return true; | |
991 | +} | |
992 | + | |
993 | +/* smovf */ | |
994 | +static bool trans_SMOVF(DisasContext *ctx, arg_SMOVF *a) | |
995 | +{ | |
996 | + prt("smovf"); | |
997 | + return true; | |
998 | +} | |
999 | + | |
1000 | +/* smovb */ | |
1001 | +static bool trans_SMOVB(DisasContext *ctx, arg_SMOVB *a) | |
1002 | +{ | |
1003 | + prt("smovb"); | |
1004 | + return true; | |
1005 | +} | |
1006 | + | |
1007 | +/* suntile */ | |
1008 | +static bool trans_SUNTIL(DisasContext *ctx, arg_SUNTIL *a) | |
1009 | +{ | |
1010 | + prt("suntil.%c", size[a->sz]); | |
1011 | + return true; | |
1012 | +} | |
1013 | + | |
1014 | +/* swhile */ | |
1015 | +static bool trans_SWHILE(DisasContext *ctx, arg_SWHILE *a) | |
1016 | +{ | |
1017 | + prt("swhile.%c", size[a->sz]); | |
1018 | + return true; | |
1019 | +} | |
1020 | +/* sstr */ | |
1021 | +static bool trans_SSTR(DisasContext *ctx, arg_SSTR *a) | |
1022 | +{ | |
1023 | + prt("sstr.%c", size[a->sz]); | |
1024 | + return true; | |
1025 | +} | |
1026 | + | |
1027 | +/* rmpa */ | |
1028 | +static bool trans_RMPA(DisasContext *ctx, arg_RMPA *a) | |
1029 | +{ | |
1030 | + prt("rmpa.%c", size[a->sz]); | |
1031 | + return true; | |
1032 | +} | |
1033 | + | |
1034 | +/* mulhi rs,rs2 */ | |
1035 | +static bool trans_MULHI(DisasContext *ctx, arg_MULHI *a) | |
1036 | +{ | |
1037 | + prt("mulhi\tr%d,r%d", a->rs, a->rs2); | |
1038 | + return true; | |
1039 | +} | |
1040 | + | |
1041 | +/* mullo rs,rs2 */ | |
1042 | +static bool trans_MULLO(DisasContext *ctx, arg_MULLO *a) | |
1043 | +{ | |
1044 | + prt("mullo\tr%d, r%d", a->rs, a->rs2); | |
1045 | + return true; | |
1046 | +} | |
1047 | + | |
1048 | +/* machi rs,rs2 */ | |
1049 | +static bool trans_MACHI(DisasContext *ctx, arg_MACHI *a) | |
1050 | +{ | |
1051 | + prt("machi\tr%d, r%d", a->rs, a->rs2); | |
1052 | + return true; | |
1053 | +} | |
1054 | + | |
1055 | +/* maclo rs,rs2 */ | |
1056 | +static bool trans_MACLO(DisasContext *ctx, arg_MACLO *a) | |
1057 | +{ | |
1058 | + prt("maclo\tr%d, r%d", a->rs, a->rs2); | |
1059 | + return true; | |
1060 | +} | |
1061 | + | |
1062 | +/* mvfachi rd */ | |
1063 | +static bool trans_MVFACHI(DisasContext *ctx, arg_MVFACHI *a) | |
1064 | +{ | |
1065 | + prt("mvfachi\tr%d", a->rd); | |
1066 | + return true; | |
1067 | +} | |
1068 | + | |
1069 | +/* mvfacmi rd */ | |
1070 | +static bool trans_MVFACMI(DisasContext *ctx, arg_MVFACMI *a) | |
1071 | +{ | |
1072 | + prt("mvfacmi\tr%d", a->rd); | |
1073 | + return true; | |
1074 | +} | |
1075 | + | |
1076 | +/* mvtachi rs */ | |
1077 | +static bool trans_MVTACHI(DisasContext *ctx, arg_MVTACHI *a) | |
1078 | +{ | |
1079 | + prt("mvtachi\tr%d", a->rs); | |
1080 | + return true; | |
1081 | +} | |
1082 | + | |
1083 | +/* mvtaclo rs */ | |
1084 | +static bool trans_MVTACLO(DisasContext *ctx, arg_MVTACLO *a) | |
1085 | +{ | |
1086 | + prt("mvtaclo\tr%d", a->rs); | |
1087 | + return true; | |
1088 | +} | |
1089 | + | |
1090 | +/* racw #imm */ | |
1091 | +static bool trans_RACW(DisasContext *ctx, arg_RACW *a) | |
1092 | +{ | |
1093 | + prt("racw\t#%d", a->imm + 1); | |
1094 | + return true; | |
1095 | +} | |
1096 | + | |
1097 | +/* sat rd */ | |
1098 | +static bool trans_SAT(DisasContext *ctx, arg_SAT *a) | |
1099 | +{ | |
1100 | + prt("sat\tr%d", a->rd); | |
1101 | + return true; | |
1102 | +} | |
1103 | + | |
1104 | +/* satr */ | |
1105 | +static bool trans_SATR(DisasContext *ctx, arg_SATR *a) | |
1106 | +{ | |
1107 | + prt("satr"); | |
1108 | + return true; | |
1109 | +} | |
1110 | + | |
1111 | +/* fadd #imm, rd */ | |
1112 | +static bool trans_FADD_ir(DisasContext *ctx, arg_FADD_ir *a) | |
1113 | +{ | |
1114 | + prt("fadd\t#%d,r%d", li(ctx, 0), a->rd); | |
1115 | + return true; | |
1116 | +} | |
1117 | + | |
1118 | +/* fadd dsp[rs], rd */ | |
1119 | +/* fadd rs, rd */ | |
1120 | +static bool trans_FADD_mr(DisasContext *ctx, arg_FADD_mr *a) | |
1121 | +{ | |
1122 | + prt("fadd\t"); | |
1123 | + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); | |
1124 | + return true; | |
1125 | +} | |
1126 | + | |
1127 | +/* fcmp #imm, rd */ | |
1128 | +static bool trans_FCMP_ir(DisasContext *ctx, arg_FCMP_ir *a) | |
1129 | +{ | |
1130 | + prt("fadd\t#%d,r%d", li(ctx, 0), a->rd); | |
1131 | + return true; | |
1132 | +} | |
1133 | + | |
1134 | +/* fcmp dsp[rs], rd */ | |
1135 | +/* fcmp rs, rd */ | |
1136 | +static bool trans_FCMP_mr(DisasContext *ctx, arg_FCMP_mr *a) | |
1137 | +{ | |
1138 | + prt("fcmp\t"); | |
1139 | + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); | |
1140 | + return true; | |
1141 | +} | |
1142 | + | |
1143 | +/* fsub #imm, rd */ | |
1144 | +static bool trans_FSUB_ir(DisasContext *ctx, arg_FSUB_ir *a) | |
1145 | +{ | |
1146 | + prt("fsub\t#%d,r%d", li(ctx, 0), a->rd); | |
1147 | + return true; | |
1148 | +} | |
1149 | + | |
1150 | +/* fsub dsp[rs], rd */ | |
1151 | +/* fsub rs, rd */ | |
1152 | +static bool trans_FSUB_mr(DisasContext *ctx, arg_FSUB_mr *a) | |
1153 | +{ | |
1154 | + prt("fsub\t"); | |
1155 | + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); | |
1156 | + return true; | |
1157 | +} | |
1158 | + | |
1159 | +/* ftoi dsp[rs], rd */ | |
1160 | +/* ftoi rs, rd */ | |
1161 | +static bool trans_FTOI(DisasContext *ctx, arg_FTOI *a) | |
1162 | +{ | |
1163 | + prt("ftoi\t"); | |
1164 | + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); | |
1165 | + return true; | |
1166 | +} | |
1167 | + | |
1168 | +/* fmul #imm, rd */ | |
1169 | +static bool trans_FMUL_ir(DisasContext *ctx, arg_FMUL_ir *a) | |
1170 | +{ | |
1171 | + prt("fmul\t#%d,r%d", li(ctx, 0), a->rd); | |
1172 | + return true; | |
1173 | +} | |
1174 | + | |
1175 | +/* fmul dsp[rs], rd */ | |
1176 | +/* fmul rs, rd */ | |
1177 | +static bool trans_FMUL_mr(DisasContext *ctx, arg_FMUL_mr *a) | |
1178 | +{ | |
1179 | + prt("fmul\t"); | |
1180 | + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); | |
1181 | + return true; | |
1182 | +} | |
1183 | + | |
1184 | +/* fdiv #imm, rd */ | |
1185 | +static bool trans_FDIV_ir(DisasContext *ctx, arg_FDIV_ir *a) | |
1186 | +{ | |
1187 | + prt("fdiv\t#%d,r%d", li(ctx, 0), a->rd); | |
1188 | + return true; | |
1189 | +} | |
1190 | + | |
1191 | +/* fdiv dsp[rs], rd */ | |
1192 | +/* fdiv rs, rd */ | |
1193 | +static bool trans_FDIV_mr(DisasContext *ctx, arg_FDIV_mr *a) | |
1194 | +{ | |
1195 | + prt("fdiv\t"); | |
1196 | + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); | |
1197 | + return true; | |
1198 | +} | |
1199 | + | |
1200 | +/* round dsp[rs], rd */ | |
1201 | +/* round rs, rd */ | |
1202 | +static bool trans_ROUND(DisasContext *ctx, arg_ROUND *a) | |
1203 | +{ | |
1204 | + prt("round\t"); | |
1205 | + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); | |
1206 | + return true; | |
1207 | +} | |
1208 | + | |
1209 | +/* itof rs, rd */ | |
1210 | +/* itof dsp[rs], rd */ | |
1211 | +static bool trans_ITOF(DisasContext *ctx, arg_ITOF *a) | |
1212 | +{ | |
1213 | + prt("itof\t"); | |
1214 | + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); | |
1215 | + return true; | |
1216 | +} | |
1217 | + | |
1218 | +#define BOP_IM(name, reg) \ | |
1219 | + do { \ | |
1220 | + int dsp; \ | |
1221 | + prt("b%s\t#%d, ", #name, a->imm); \ | |
1222 | + dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); \ | |
1223 | + if (dsp > 0) { \ | |
1224 | + prt("%d", dsp); \ | |
1225 | + } \ | |
1226 | + prt("[r%d]", reg); \ | |
1227 | + return true; \ | |
1228 | + } while (0) | |
1229 | + | |
1230 | +#define BOP_RM(name) \ | |
1231 | + do { \ | |
1232 | + int dsp; \ | |
1233 | + prt("b%s\tr%d, ", #name, a->rd); \ | |
1234 | + dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); \ | |
1235 | + if (dsp > 0) { \ | |
1236 | + prt("%d", dsp); \ | |
1237 | + } \ | |
1238 | + prt("[r%d]", a->rs); \ | |
1239 | + return true; \ | |
1240 | + } while (0) | |
1241 | + | |
1242 | +/* bset #imm, dsp[rd] */ | |
1243 | +static bool trans_BSET_im(DisasContext *ctx, arg_BSET_im *a) | |
1244 | +{ | |
1245 | + BOP_IM(bset, a->rs); | |
1246 | +} | |
1247 | + | |
1248 | +/* bset rs, dsp[rd] */ | |
1249 | +static bool trans_BSET_rm(DisasContext *ctx, arg_BSET_rm *a) | |
1250 | +{ | |
1251 | + BOP_RM(set); | |
1252 | +} | |
1253 | + | |
1254 | +/* bset rs, rd */ | |
1255 | +static bool trans_BSET_rr(DisasContext *ctx, arg_BSET_rr *a) | |
1256 | +{ | |
1257 | + prt("bset\tr%d,r%d", a->rs, a->rd); | |
1258 | + return true; | |
1259 | +} | |
1260 | + | |
1261 | +/* bset #imm, rd */ | |
1262 | +static bool trans_BSET_ir(DisasContext *ctx, arg_BSET_ir *a) | |
1263 | +{ | |
1264 | + prt("bset\t#%d, r%d", a->imm, a->rd); | |
1265 | + return true; | |
1266 | +} | |
1267 | + | |
1268 | +/* bclr #imm, dsp[rd] */ | |
1269 | +static bool trans_BCLR_im(DisasContext *ctx, arg_BCLR_im *a) | |
1270 | +{ | |
1271 | + BOP_IM(clr, a->rs); | |
1272 | +} | |
1273 | + | |
1274 | +/* bclr rs, dsp[rd] */ | |
1275 | +static bool trans_BCLR_rm(DisasContext *ctx, arg_BCLR_rm *a) | |
1276 | +{ | |
1277 | + BOP_RM(clr); | |
1278 | +} | |
1279 | + | |
1280 | +/* bclr rs, rd */ | |
1281 | +static bool trans_BCLR_rr(DisasContext *ctx, arg_BCLR_rr *a) | |
1282 | +{ | |
1283 | + prt("bclr\tr%d, r%d", a->rs, a->rd); | |
1284 | + return true; | |
1285 | +} | |
1286 | + | |
1287 | +/* bclr #imm, rd */ | |
1288 | +static bool trans_BCLR_ir(DisasContext *ctx, arg_BCLR_ir *a) | |
1289 | +{ | |
1290 | + prt("bclr\t#%d,r%d", a->imm, a->rd); | |
1291 | + return true; | |
1292 | +} | |
1293 | + | |
1294 | +/* btst #imm, dsp[rd] */ | |
1295 | +static bool trans_BTST_im(DisasContext *ctx, arg_BTST_im *a) | |
1296 | +{ | |
1297 | + BOP_IM(tst, a->rs); | |
1298 | +} | |
1299 | + | |
1300 | +/* btst rs, dsp[rd] */ | |
1301 | +static bool trans_BTST_rm(DisasContext *ctx, arg_BTST_rm *a) | |
1302 | +{ | |
1303 | + BOP_RM(tst); | |
1304 | +} | |
1305 | + | |
1306 | +/* btst rs, rd */ | |
1307 | +static bool trans_BTST_rr(DisasContext *ctx, arg_BTST_rr *a) | |
1308 | +{ | |
1309 | + prt("btst\tr%d, r%d", a->rs, a->rd); | |
1310 | + return true; | |
1311 | +} | |
1312 | + | |
1313 | +/* btst #imm, rd */ | |
1314 | +static bool trans_BTST_ir(DisasContext *ctx, arg_BTST_ir *a) | |
1315 | +{ | |
1316 | + prt("btst\t#%d, r%d", a->imm, a->rd); | |
1317 | + return true; | |
1318 | +} | |
1319 | + | |
1320 | +/* bnot rs, dsp[rd] */ | |
1321 | +static bool trans_BNOT_rm(DisasContext *ctx, arg_BNOT_rm *a) | |
1322 | +{ | |
1323 | + BOP_RM(not); | |
1324 | +} | |
1325 | + | |
1326 | +/* bnot rs, rd */ | |
1327 | +static bool trans_BNOT_rr(DisasContext *ctx, arg_BNOT_rr *a) | |
1328 | +{ | |
1329 | + prt("bnot\tr%d, r%d", a->rs, a->rd); | |
1330 | + return true; | |
1331 | +} | |
1332 | + | |
1333 | +/* bnot #imm, dsp[rd] */ | |
1334 | +static bool trans_BNOT_im(DisasContext *ctx, arg_BNOT_im *a) | |
1335 | +{ | |
1336 | + BOP_IM(not, a->rs); | |
1337 | +} | |
1338 | + | |
1339 | +/* bnot #imm, rd */ | |
1340 | +static bool trans_BNOT_ir(DisasContext *ctx, arg_BNOT_ir *a) | |
1341 | +{ | |
1342 | + prt("bnot\t#%d, r%d", a->imm, a->rd); | |
1343 | + return true; | |
1344 | +} | |
1345 | + | |
1346 | +/* bmcond #imm, dsp[rd] */ | |
1347 | +static bool trans_BMCnd_im(DisasContext *ctx, arg_BMCnd_im *a) | |
1348 | +{ | |
1349 | + int dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); | |
1350 | + prt("bm%s\t#%d, ", cond[a->cd], a->imm); | |
1351 | + if (dsp > 0) { | |
1352 | + prt("%d", dsp); | |
1353 | + } | |
1354 | + prt("[%d]", a->rd); | |
1355 | + return true; | |
1356 | +} | |
1357 | + | |
1358 | +/* bmcond #imm, rd */ | |
1359 | +static bool trans_BMCnd_ir(DisasContext *ctx, arg_BMCnd_ir *a) | |
1360 | +{ | |
1361 | + prt("bm%s\t#%d, r%d", cond[a->cd], a->imm, a->rd); | |
1362 | + return true; | |
1363 | +} | |
1364 | + | |
1365 | +/* clrpsw psw */ | |
1366 | +static bool trans_CLRPSW(DisasContext *ctx, arg_CLRPSW *a) | |
1367 | +{ | |
1368 | + prt("clrpsw\t%c", psw[a->cb]); | |
1369 | + return true; | |
1370 | +} | |
1371 | + | |
1372 | +/* setpsw psw */ | |
1373 | +static bool trans_SETPSW(DisasContext *ctx, arg_SETPSW *a) | |
1374 | +{ | |
1375 | + prt("setpsw\t%c", psw[a->cb]); | |
1376 | + return true; | |
1377 | +} | |
1378 | + | |
1379 | +/* mvtipl #imm */ | |
1380 | +static bool trans_MVTIPL(DisasContext *ctx, arg_MVTIPL *a) | |
1381 | +{ | |
1382 | + prt("movtipl\t#%d", a->imm); | |
1383 | + return true; | |
1384 | +} | |
1385 | + | |
1386 | +/* mvtc #imm, rd */ | |
1387 | +static bool trans_MVTC_i(DisasContext *ctx, arg_MVTC_i *a) | |
1388 | +{ | |
1389 | + prt("mvtc\t#0x%08x, %s", a->imm, rx_crname[a->cr]); | |
1390 | + return true; | |
1391 | +} | |
1392 | + | |
1393 | +/* mvtc rs, rd */ | |
1394 | +static bool trans_MVTC_r(DisasContext *ctx, arg_MVTC_r *a) | |
1395 | +{ | |
1396 | + prt("mvtc\tr%d, %s", a->rs, rx_crname[a->cr]); | |
1397 | + return true; | |
1398 | +} | |
1399 | + | |
1400 | +/* mvfc rs, rd */ | |
1401 | +static bool trans_MVFC(DisasContext *ctx, arg_MVFC *a) | |
1402 | +{ | |
1403 | + prt("mvfc\t%s, r%d", rx_crname[a->cr], a->rd); | |
1404 | + return true; | |
1405 | +} | |
1406 | + | |
1407 | +/* rtfi */ | |
1408 | +static bool trans_RTFI(DisasContext *ctx, arg_RTFI *a) | |
1409 | +{ | |
1410 | + prt("rtfi"); | |
1411 | + return true; | |
1412 | +} | |
1413 | + | |
1414 | +/* rte */ | |
1415 | +static bool trans_RTE(DisasContext *ctx, arg_RTE *a) | |
1416 | +{ | |
1417 | + prt("rte"); | |
1418 | + return true; | |
1419 | +} | |
1420 | + | |
1421 | +/* brk */ | |
1422 | +static bool trans_BRK(DisasContext *ctx, arg_BRK *a) | |
1423 | +{ | |
1424 | + prt("brk"); | |
1425 | + return true; | |
1426 | +} | |
1427 | + | |
1428 | +/* int #imm */ | |
1429 | +static bool trans_INT(DisasContext *ctx, arg_INT *a) | |
1430 | +{ | |
1431 | + prt("int\t#%d", a->imm); | |
1432 | + return true; | |
1433 | +} | |
1434 | + | |
1435 | +/* wait */ | |
1436 | +static bool trans_WAIT(DisasContext *ctx, arg_WAIT *a) | |
1437 | +{ | |
1438 | + prt("wait"); | |
1439 | + return true; | |
1440 | +} | |
1441 | + | |
1442 | +/* sccnd.[bwl] rd */ | |
1443 | +/* sccnd.[bwl] dsp:[rd] */ | |
1444 | +static bool trans_SCCnd(DisasContext *ctx, arg_SCCnd *a) | |
1445 | +{ | |
1446 | + int dsp; | |
1447 | + prt("sc%s.%c\t", cond[a->cd], size[a->sz]); | |
1448 | + if (a->ld < 3) { | |
1449 | + dsp = rx_index_addr(a->sz, a->ld, ctx); | |
1450 | + if (dsp > 0) { | |
1451 | + prt("%d", dsp); | |
1452 | + } | |
1453 | + prt("[r%d]", a->rd); | |
1454 | + } else { | |
1455 | + prt("r%d", a->rd); | |
1456 | + } | |
1457 | + return true; | |
1458 | +} | |
1459 | + | |
1460 | +int print_insn_rx(bfd_vma addr, disassemble_info *dis) | |
1461 | +{ | |
1462 | + DisasContext ctx; | |
1463 | + uint32_t insn; | |
1464 | + int i; | |
1465 | + ctx.dis = dis; | |
1466 | + ctx.pc = ctx.addr = addr; | |
1467 | + | |
1468 | + insn = decode_load(&ctx); | |
1469 | + if (!decode(&ctx, insn)) { | |
1470 | + ctx.dis->fprintf_func(ctx.dis->stream, ".byte\t"); | |
1471 | + for (i = 0; i < ctx.addr - addr; i++) { | |
1472 | + if (i > 0) { | |
1473 | + ctx.dis->fprintf_func(ctx.dis->stream, ","); | |
1474 | + } | |
1475 | + ctx.dis->fprintf_func(ctx.dis->stream, "0x%02x", insn >> 24); | |
1476 | + insn <<= 8; | |
1477 | + } | |
1478 | + } | |
1479 | + return ctx.addr - addr; | |
1480 | +} |