TCG README fixes (Stuart Brady)
[qemu/malc.git] / target-sh4 / translate.c
blobb7c5f8d0a4c0eaa0290dc7c2fe4585543bd2479b
1 /*
2 * SH4 translation
4 * Copyright (c) 2005 Samuel Tardieu
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <assert.h>
27 #define DEBUG_DISAS
28 #define SH4_DEBUG_DISAS
29 //#define SH4_SINGLE_STEP
31 #include "cpu.h"
32 #include "exec-all.h"
33 #include "disas.h"
34 #include "tcg-op.h"
36 typedef struct DisasContext {
37 struct TranslationBlock *tb;
38 target_ulong pc;
39 uint32_t sr;
40 uint32_t fpscr;
41 uint16_t opcode;
42 uint32_t flags;
43 int bstate;
44 int memidx;
45 uint32_t delayed_pc;
46 int singlestep_enabled;
47 } DisasContext;
49 enum {
50 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
51 * exception condition
53 BS_STOP = 1, /* We want to stop translation for any reason */
54 BS_BRANCH = 2, /* We reached a branch condition */
55 BS_EXCP = 3, /* We reached an exception condition */
58 #ifdef CONFIG_USER_ONLY
60 #define GEN_OP_LD(width, reg) \
61 void gen_op_ld##width##_T0_##reg (DisasContext *ctx) { \
62 gen_op_ld##width##_T0_##reg##_raw(); \
64 #define GEN_OP_ST(width, reg) \
65 void gen_op_st##width##_##reg##_T1 (DisasContext *ctx) { \
66 gen_op_st##width##_##reg##_T1_raw(); \
69 #else
71 #define GEN_OP_LD(width, reg) \
72 void gen_op_ld##width##_T0_##reg (DisasContext *ctx) { \
73 if (ctx->memidx) gen_op_ld##width##_T0_##reg##_kernel(); \
74 else gen_op_ld##width##_T0_##reg##_user();\
76 #define GEN_OP_ST(width, reg) \
77 void gen_op_st##width##_##reg##_T1 (DisasContext *ctx) { \
78 if (ctx->memidx) gen_op_st##width##_##reg##_T1_kernel(); \
79 else gen_op_st##width##_##reg##_T1_user();\
82 #endif
84 GEN_OP_LD(ub, T0)
85 GEN_OP_LD(b, T0)
86 GEN_OP_ST(b, T0)
87 GEN_OP_LD(uw, T0)
88 GEN_OP_LD(w, T0)
89 GEN_OP_ST(w, T0)
90 GEN_OP_LD(l, T0)
91 GEN_OP_ST(l, T0)
92 GEN_OP_LD(fl, FT0)
93 GEN_OP_ST(fl, FT0)
94 GEN_OP_LD(fq, DT0)
95 GEN_OP_ST(fq, DT0)
97 void cpu_dump_state(CPUState * env, FILE * f,
98 int (*cpu_fprintf) (FILE * f, const char *fmt, ...),
99 int flags)
101 int i;
102 cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
103 env->pc, env->sr, env->pr, env->fpscr);
104 for (i = 0; i < 24; i += 4) {
105 cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
106 i, env->gregs[i], i + 1, env->gregs[i + 1],
107 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
109 if (env->flags & DELAY_SLOT) {
110 cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
111 env->delayed_pc);
112 } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
113 cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
114 env->delayed_pc);
118 void cpu_sh4_reset(CPUSH4State * env)
120 #if defined(CONFIG_USER_ONLY)
121 env->sr = SR_FD; /* FD - kernel does lazy fpu context switch */
122 #else
123 env->sr = 0x700000F0; /* MD, RB, BL, I3-I0 */
124 #endif
125 env->vbr = 0;
126 env->pc = 0xA0000000;
127 #if defined(CONFIG_USER_ONLY)
128 env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
129 set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
130 #else
131 env->fpscr = 0x00040001; /* CPU reset value according to SH4 manual */
132 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
133 #endif
134 env->mmucr = 0;
137 CPUSH4State *cpu_sh4_init(const char *cpu_model)
139 CPUSH4State *env;
141 env = qemu_mallocz(sizeof(CPUSH4State));
142 if (!env)
143 return NULL;
144 cpu_exec_init(env);
145 cpu_sh4_reset(env);
146 tlb_flush(env, 1);
147 return env;
150 static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
152 TranslationBlock *tb;
153 tb = ctx->tb;
155 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
156 !ctx->singlestep_enabled) {
157 /* Use a direct jump if in same page and singlestep not enabled */
158 tcg_gen_goto_tb(n);
159 gen_op_movl_imm_PC(dest);
160 tcg_gen_exit_tb((long) tb + n);
161 } else {
162 gen_op_movl_imm_PC(dest);
163 if (ctx->singlestep_enabled)
164 gen_op_debug();
165 tcg_gen_exit_tb(0);
169 static void gen_jump(DisasContext * ctx)
171 if (ctx->delayed_pc == (uint32_t) - 1) {
172 /* Target is not statically known, it comes necessarily from a
173 delayed jump as immediate jump are conditinal jumps */
174 gen_op_movl_delayed_pc_PC();
175 if (ctx->singlestep_enabled)
176 gen_op_debug();
177 tcg_gen_exit_tb(0);
178 } else {
179 gen_goto_tb(ctx, 0, ctx->delayed_pc);
183 /* Immediate conditional jump (bt or bf) */
184 static void gen_conditional_jump(DisasContext * ctx,
185 target_ulong ift, target_ulong ifnott)
187 int l1;
189 l1 = gen_new_label();
190 gen_op_jT(l1);
191 gen_goto_tb(ctx, 0, ifnott);
192 gen_set_label(l1);
193 gen_goto_tb(ctx, 1, ift);
196 /* Delayed conditional jump (bt or bf) */
197 static void gen_delayed_conditional_jump(DisasContext * ctx)
199 int l1;
201 l1 = gen_new_label();
202 gen_op_jdelayed(l1);
203 gen_goto_tb(ctx, 1, ctx->pc + 2);
204 gen_set_label(l1);
205 gen_jump(ctx);
208 #define B3_0 (ctx->opcode & 0xf)
209 #define B6_4 ((ctx->opcode >> 4) & 0x7)
210 #define B7_4 ((ctx->opcode >> 4) & 0xf)
211 #define B7_0 (ctx->opcode & 0xff)
212 #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
213 #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
214 (ctx->opcode & 0xfff))
215 #define B11_8 ((ctx->opcode >> 8) & 0xf)
216 #define B15_12 ((ctx->opcode >> 12) & 0xf)
218 #define REG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB) ? \
219 (x) + 16 : (x))
221 #define ALTREG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) != (SR_MD | SR_RB) \
222 ? (x) + 16 : (x))
224 #define FREG(x) (ctx->fpscr & FPSCR_FR ? (x) ^ 0x10 : (x))
225 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
226 #define XREG(x) (ctx->fpscr & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x))
227 #define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */
229 #define CHECK_NOT_DELAY_SLOT \
230 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
231 {gen_op_raise_slot_illegal_instruction (); ctx->bstate = BS_EXCP; \
232 return;}
234 void _decode_opc(DisasContext * ctx)
236 #if 0
237 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
238 #endif
239 switch (ctx->opcode) {
240 case 0x0019: /* div0u */
241 gen_op_div0u();
242 return;
243 case 0x000b: /* rts */
244 CHECK_NOT_DELAY_SLOT gen_op_rts();
245 ctx->flags |= DELAY_SLOT;
246 ctx->delayed_pc = (uint32_t) - 1;
247 return;
248 case 0x0028: /* clrmac */
249 gen_op_clrmac();
250 return;
251 case 0x0048: /* clrs */
252 gen_op_clrs();
253 return;
254 case 0x0008: /* clrt */
255 gen_op_clrt();
256 return;
257 case 0x0038: /* ldtlb */
258 assert(0); /* XXXXX */
259 return;
260 case 0x002b: /* rte */
261 CHECK_NOT_DELAY_SLOT gen_op_rte();
262 ctx->flags |= DELAY_SLOT;
263 ctx->delayed_pc = (uint32_t) - 1;
264 return;
265 case 0x0058: /* sets */
266 gen_op_sets();
267 return;
268 case 0x0018: /* sett */
269 gen_op_sett();
270 return;
271 case 0xfbfd: /* frchg */
272 gen_op_frchg();
273 ctx->bstate = BS_STOP;
274 return;
275 case 0xf3fd: /* fschg */
276 gen_op_fschg();
277 ctx->bstate = BS_STOP;
278 return;
279 case 0x0009: /* nop */
280 return;
281 case 0x001b: /* sleep */
282 assert(0); /* XXXXX */
283 return;
286 switch (ctx->opcode & 0xf000) {
287 case 0x1000: /* mov.l Rm,@(disp,Rn) */
288 gen_op_movl_rN_T0(REG(B7_4));
289 gen_op_movl_rN_T1(REG(B11_8));
290 gen_op_addl_imm_T1(B3_0 * 4);
291 gen_op_stl_T0_T1(ctx);
292 return;
293 case 0x5000: /* mov.l @(disp,Rm),Rn */
294 gen_op_movl_rN_T0(REG(B7_4));
295 gen_op_addl_imm_T0(B3_0 * 4);
296 gen_op_ldl_T0_T0(ctx);
297 gen_op_movl_T0_rN(REG(B11_8));
298 return;
299 case 0xe000: /* mov #imm,Rn */
300 gen_op_movl_imm_rN(B7_0s, REG(B11_8));
301 return;
302 case 0x9000: /* mov.w @(disp,PC),Rn */
303 gen_op_movl_imm_T0(ctx->pc + 4 + B7_0 * 2);
304 gen_op_ldw_T0_T0(ctx);
305 gen_op_movl_T0_rN(REG(B11_8));
306 return;
307 case 0xd000: /* mov.l @(disp,PC),Rn */
308 gen_op_movl_imm_T0((ctx->pc + 4 + B7_0 * 4) & ~3);
309 gen_op_ldl_T0_T0(ctx);
310 gen_op_movl_T0_rN(REG(B11_8));
311 return;
312 case 0x7000: /* add #imm,Rn */
313 gen_op_add_imm_rN(B7_0s, REG(B11_8));
314 return;
315 case 0xa000: /* bra disp */
316 CHECK_NOT_DELAY_SLOT
317 gen_op_bra(ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2);
318 ctx->flags |= DELAY_SLOT;
319 return;
320 case 0xb000: /* bsr disp */
321 CHECK_NOT_DELAY_SLOT
322 gen_op_bsr(ctx->pc + 4, ctx->delayed_pc =
323 ctx->pc + 4 + B11_0s * 2);
324 ctx->flags |= DELAY_SLOT;
325 return;
328 switch (ctx->opcode & 0xf00f) {
329 case 0x6003: /* mov Rm,Rn */
330 gen_op_movl_rN_T0(REG(B7_4));
331 gen_op_movl_T0_rN(REG(B11_8));
332 return;
333 case 0x2000: /* mov.b Rm,@Rn */
334 gen_op_movl_rN_T0(REG(B7_4));
335 gen_op_movl_rN_T1(REG(B11_8));
336 gen_op_stb_T0_T1(ctx);
337 return;
338 case 0x2001: /* mov.w Rm,@Rn */
339 gen_op_movl_rN_T0(REG(B7_4));
340 gen_op_movl_rN_T1(REG(B11_8));
341 gen_op_stw_T0_T1(ctx);
342 return;
343 case 0x2002: /* mov.l Rm,@Rn */
344 gen_op_movl_rN_T0(REG(B7_4));
345 gen_op_movl_rN_T1(REG(B11_8));
346 gen_op_stl_T0_T1(ctx);
347 return;
348 case 0x6000: /* mov.b @Rm,Rn */
349 gen_op_movl_rN_T0(REG(B7_4));
350 gen_op_ldb_T0_T0(ctx);
351 gen_op_movl_T0_rN(REG(B11_8));
352 return;
353 case 0x6001: /* mov.w @Rm,Rn */
354 gen_op_movl_rN_T0(REG(B7_4));
355 gen_op_ldw_T0_T0(ctx);
356 gen_op_movl_T0_rN(REG(B11_8));
357 return;
358 case 0x6002: /* mov.l @Rm,Rn */
359 gen_op_movl_rN_T0(REG(B7_4));
360 gen_op_ldl_T0_T0(ctx);
361 gen_op_movl_T0_rN(REG(B11_8));
362 return;
363 case 0x2004: /* mov.b Rm,@-Rn */
364 gen_op_movl_rN_T0(REG(B7_4));
365 gen_op_dec1_rN(REG(B11_8));
366 gen_op_movl_rN_T1(REG(B11_8));
367 gen_op_stb_T0_T1(ctx);
368 return;
369 case 0x2005: /* mov.w Rm,@-Rn */
370 gen_op_movl_rN_T0(REG(B7_4));
371 gen_op_dec2_rN(REG(B11_8));
372 gen_op_movl_rN_T1(REG(B11_8));
373 gen_op_stw_T0_T1(ctx);
374 return;
375 case 0x2006: /* mov.l Rm,@-Rn */
376 gen_op_movl_rN_T0(REG(B7_4));
377 gen_op_dec4_rN(REG(B11_8));
378 gen_op_movl_rN_T1(REG(B11_8));
379 gen_op_stl_T0_T1(ctx);
380 return;
381 case 0x6004: /* mov.b @Rm+,Rn */
382 gen_op_movl_rN_T0(REG(B7_4));
383 gen_op_ldb_T0_T0(ctx);
384 gen_op_movl_T0_rN(REG(B11_8));
385 if ( B11_8 != B7_4 )
386 gen_op_inc1_rN(REG(B7_4));
387 return;
388 case 0x6005: /* mov.w @Rm+,Rn */
389 gen_op_movl_rN_T0(REG(B7_4));
390 gen_op_ldw_T0_T0(ctx);
391 gen_op_movl_T0_rN(REG(B11_8));
392 if ( B11_8 != B7_4 )
393 gen_op_inc2_rN(REG(B7_4));
394 return;
395 case 0x6006: /* mov.l @Rm+,Rn */
396 gen_op_movl_rN_T0(REG(B7_4));
397 gen_op_ldl_T0_T0(ctx);
398 gen_op_movl_T0_rN(REG(B11_8));
399 if ( B11_8 != B7_4 )
400 gen_op_inc4_rN(REG(B7_4));
401 return;
402 case 0x0004: /* mov.b Rm,@(R0,Rn) */
403 gen_op_movl_rN_T0(REG(B7_4));
404 gen_op_movl_rN_T1(REG(B11_8));
405 gen_op_add_rN_T1(REG(0));
406 gen_op_stb_T0_T1(ctx);
407 return;
408 case 0x0005: /* mov.w Rm,@(R0,Rn) */
409 gen_op_movl_rN_T0(REG(B7_4));
410 gen_op_movl_rN_T1(REG(B11_8));
411 gen_op_add_rN_T1(REG(0));
412 gen_op_stw_T0_T1(ctx);
413 return;
414 case 0x0006: /* mov.l Rm,@(R0,Rn) */
415 gen_op_movl_rN_T0(REG(B7_4));
416 gen_op_movl_rN_T1(REG(B11_8));
417 gen_op_add_rN_T1(REG(0));
418 gen_op_stl_T0_T1(ctx);
419 return;
420 case 0x000c: /* mov.b @(R0,Rm),Rn */
421 gen_op_movl_rN_T0(REG(B7_4));
422 gen_op_add_rN_T0(REG(0));
423 gen_op_ldb_T0_T0(ctx);
424 gen_op_movl_T0_rN(REG(B11_8));
425 return;
426 case 0x000d: /* mov.w @(R0,Rm),Rn */
427 gen_op_movl_rN_T0(REG(B7_4));
428 gen_op_add_rN_T0(REG(0));
429 gen_op_ldw_T0_T0(ctx);
430 gen_op_movl_T0_rN(REG(B11_8));
431 return;
432 case 0x000e: /* mov.l @(R0,Rm),Rn */
433 gen_op_movl_rN_T0(REG(B7_4));
434 gen_op_add_rN_T0(REG(0));
435 gen_op_ldl_T0_T0(ctx);
436 gen_op_movl_T0_rN(REG(B11_8));
437 return;
438 case 0x6008: /* swap.b Rm,Rn */
439 gen_op_movl_rN_T0(REG(B7_4));
440 gen_op_swapb_T0();
441 gen_op_movl_T0_rN(REG(B11_8));
442 return;
443 case 0x6009: /* swap.w Rm,Rn */
444 gen_op_movl_rN_T0(REG(B7_4));
445 gen_op_swapw_T0();
446 gen_op_movl_T0_rN(REG(B11_8));
447 return;
448 case 0x200d: /* xtrct Rm,Rn */
449 gen_op_movl_rN_T0(REG(B7_4));
450 gen_op_movl_rN_T1(REG(B11_8));
451 gen_op_xtrct_T0_T1();
452 gen_op_movl_T1_rN(REG(B11_8));
453 return;
454 case 0x300c: /* add Rm,Rn */
455 gen_op_movl_rN_T0(REG(B7_4));
456 gen_op_add_T0_rN(REG(B11_8));
457 return;
458 case 0x300e: /* addc Rm,Rn */
459 gen_op_movl_rN_T0(REG(B7_4));
460 gen_op_movl_rN_T1(REG(B11_8));
461 gen_op_addc_T0_T1();
462 gen_op_movl_T1_rN(REG(B11_8));
463 return;
464 case 0x300f: /* addv Rm,Rn */
465 gen_op_movl_rN_T0(REG(B7_4));
466 gen_op_movl_rN_T1(REG(B11_8));
467 gen_op_addv_T0_T1();
468 gen_op_movl_T1_rN(REG(B11_8));
469 return;
470 case 0x2009: /* and Rm,Rn */
471 gen_op_movl_rN_T0(REG(B7_4));
472 gen_op_and_T0_rN(REG(B11_8));
473 return;
474 case 0x3000: /* cmp/eq Rm,Rn */
475 gen_op_movl_rN_T0(REG(B7_4));
476 gen_op_movl_rN_T1(REG(B11_8));
477 gen_op_cmp_eq_T0_T1();
478 return;
479 case 0x3003: /* cmp/ge Rm,Rn */
480 gen_op_movl_rN_T0(REG(B7_4));
481 gen_op_movl_rN_T1(REG(B11_8));
482 gen_op_cmp_ge_T0_T1();
483 return;
484 case 0x3007: /* cmp/gt Rm,Rn */
485 gen_op_movl_rN_T0(REG(B7_4));
486 gen_op_movl_rN_T1(REG(B11_8));
487 gen_op_cmp_gt_T0_T1();
488 return;
489 case 0x3006: /* cmp/hi Rm,Rn */
490 gen_op_movl_rN_T0(REG(B7_4));
491 gen_op_movl_rN_T1(REG(B11_8));
492 gen_op_cmp_hi_T0_T1();
493 return;
494 case 0x3002: /* cmp/hs Rm,Rn */
495 gen_op_movl_rN_T0(REG(B7_4));
496 gen_op_movl_rN_T1(REG(B11_8));
497 gen_op_cmp_hs_T0_T1();
498 return;
499 case 0x200c: /* cmp/str Rm,Rn */
500 gen_op_movl_rN_T0(REG(B7_4));
501 gen_op_movl_rN_T1(REG(B11_8));
502 gen_op_cmp_str_T0_T1();
503 return;
504 case 0x2007: /* div0s Rm,Rn */
505 gen_op_movl_rN_T0(REG(B7_4));
506 gen_op_movl_rN_T1(REG(B11_8));
507 gen_op_div0s_T0_T1();
508 return;
509 case 0x3004: /* div1 Rm,Rn */
510 gen_op_movl_rN_T0(REG(B7_4));
511 gen_op_movl_rN_T1(REG(B11_8));
512 gen_op_div1_T0_T1();
513 gen_op_movl_T1_rN(REG(B11_8));
514 return;
515 case 0x300d: /* dmuls.l Rm,Rn */
516 gen_op_movl_rN_T0(REG(B7_4));
517 gen_op_movl_rN_T1(REG(B11_8));
518 gen_op_dmulsl_T0_T1();
519 return;
520 case 0x3005: /* dmulu.l Rm,Rn */
521 gen_op_movl_rN_T0(REG(B7_4));
522 gen_op_movl_rN_T1(REG(B11_8));
523 gen_op_dmulul_T0_T1();
524 return;
525 case 0x600e: /* exts.b Rm,Rn */
526 gen_op_movb_rN_T0(REG(B7_4));
527 gen_op_movl_T0_rN(REG(B11_8));
528 return;
529 case 0x600f: /* exts.w Rm,Rn */
530 gen_op_movw_rN_T0(REG(B7_4));
531 gen_op_movl_T0_rN(REG(B11_8));
532 return;
533 case 0x600c: /* extu.b Rm,Rn */
534 gen_op_movub_rN_T0(REG(B7_4));
535 gen_op_movl_T0_rN(REG(B11_8));
536 return;
537 case 0x600d: /* extu.w Rm,Rn */
538 gen_op_movuw_rN_T0(REG(B7_4));
539 gen_op_movl_T0_rN(REG(B11_8));
540 return;
541 case 0x000f: /* mac.l @Rm+,@Rn+ */
542 gen_op_movl_rN_T0(REG(B11_8));
543 gen_op_ldl_T0_T0(ctx);
544 gen_op_movl_T0_T1();
545 gen_op_inc4_rN(REG(B11_8));
546 gen_op_movl_rN_T0(REG(B7_4));
547 gen_op_ldl_T0_T0(ctx);
548 gen_op_macl_T0_T1();
549 gen_op_inc4_rN(REG(B7_4));
550 return;
551 case 0x400f: /* mac.w @Rm+,@Rn+ */
552 gen_op_movl_rN_T0(REG(B11_8));
553 gen_op_ldl_T0_T0(ctx);
554 gen_op_movl_T0_T1();
555 gen_op_inc2_rN(REG(B11_8));
556 gen_op_movl_rN_T0(REG(B7_4));
557 gen_op_ldl_T0_T0(ctx);
558 gen_op_macw_T0_T1();
559 gen_op_inc2_rN(REG(B7_4));
560 return;
561 case 0x0007: /* mul.l Rm,Rn */
562 gen_op_movl_rN_T0(REG(B7_4));
563 gen_op_movl_rN_T1(REG(B11_8));
564 gen_op_mull_T0_T1();
565 return;
566 case 0x200f: /* muls.w Rm,Rn */
567 gen_op_movw_rN_T0(REG(B7_4));
568 gen_op_movw_rN_T1(REG(B11_8));
569 gen_op_mulsw_T0_T1();
570 return;
571 case 0x200e: /* mulu.w Rm,Rn */
572 gen_op_movuw_rN_T0(REG(B7_4));
573 gen_op_movuw_rN_T1(REG(B11_8));
574 gen_op_muluw_T0_T1();
575 return;
576 case 0x600b: /* neg Rm,Rn */
577 gen_op_movl_rN_T0(REG(B7_4));
578 gen_op_neg_T0();
579 gen_op_movl_T0_rN(REG(B11_8));
580 return;
581 case 0x600a: /* negc Rm,Rn */
582 gen_op_movl_rN_T0(REG(B7_4));
583 gen_op_negc_T0();
584 gen_op_movl_T0_rN(REG(B11_8));
585 return;
586 case 0x6007: /* not Rm,Rn */
587 gen_op_movl_rN_T0(REG(B7_4));
588 gen_op_not_T0();
589 gen_op_movl_T0_rN(REG(B11_8));
590 return;
591 case 0x200b: /* or Rm,Rn */
592 gen_op_movl_rN_T0(REG(B7_4));
593 gen_op_or_T0_rN(REG(B11_8));
594 return;
595 case 0x400c: /* shad Rm,Rn */
596 gen_op_movl_rN_T0(REG(B7_4));
597 gen_op_movl_rN_T1(REG(B11_8));
598 gen_op_shad_T0_T1();
599 gen_op_movl_T1_rN(REG(B11_8));
600 return;
601 case 0x400d: /* shld Rm,Rn */
602 gen_op_movl_rN_T0(REG(B7_4));
603 gen_op_movl_rN_T1(REG(B11_8));
604 gen_op_shld_T0_T1();
605 gen_op_movl_T1_rN(REG(B11_8));
606 return;
607 case 0x3008: /* sub Rm,Rn */
608 gen_op_movl_rN_T0(REG(B7_4));
609 gen_op_sub_T0_rN(REG(B11_8));
610 return;
611 case 0x300a: /* subc Rm,Rn */
612 gen_op_movl_rN_T0(REG(B7_4));
613 gen_op_movl_rN_T1(REG(B11_8));
614 gen_op_subc_T0_T1();
615 gen_op_movl_T1_rN(REG(B11_8));
616 return;
617 case 0x300b: /* subv Rm,Rn */
618 gen_op_movl_rN_T0(REG(B7_4));
619 gen_op_movl_rN_T1(REG(B11_8));
620 gen_op_subv_T0_T1();
621 gen_op_movl_T1_rN(REG(B11_8));
622 return;
623 case 0x2008: /* tst Rm,Rn */
624 gen_op_movl_rN_T0(REG(B7_4));
625 gen_op_movl_rN_T1(REG(B11_8));
626 gen_op_tst_T0_T1();
627 return;
628 case 0x200a: /* xor Rm,Rn */
629 gen_op_movl_rN_T0(REG(B7_4));
630 gen_op_xor_T0_rN(REG(B11_8));
631 return;
632 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
633 if (ctx->fpscr & FPSCR_SZ) {
634 gen_op_fmov_drN_DT0(XREG(B7_4));
635 gen_op_fmov_DT0_drN(XREG(B11_8));
636 } else {
637 gen_op_fmov_frN_FT0(FREG(B7_4));
638 gen_op_fmov_FT0_frN(FREG(B11_8));
640 return;
641 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
642 if (ctx->fpscr & FPSCR_SZ) {
643 gen_op_fmov_drN_DT0(XREG(B7_4));
644 gen_op_movl_rN_T1(REG(B11_8));
645 gen_op_stfq_DT0_T1(ctx);
646 } else {
647 gen_op_fmov_frN_FT0(FREG(B7_4));
648 gen_op_movl_rN_T1(REG(B11_8));
649 gen_op_stfl_FT0_T1(ctx);
651 return;
652 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
653 if (ctx->fpscr & FPSCR_SZ) {
654 gen_op_movl_rN_T0(REG(B7_4));
655 gen_op_ldfq_T0_DT0(ctx);
656 gen_op_fmov_DT0_drN(XREG(B11_8));
657 } else {
658 gen_op_movl_rN_T0(REG(B7_4));
659 gen_op_ldfl_T0_FT0(ctx);
660 gen_op_fmov_FT0_frN(FREG(B11_8));
662 return;
663 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
664 if (ctx->fpscr & FPSCR_SZ) {
665 gen_op_movl_rN_T0(REG(B7_4));
666 gen_op_ldfq_T0_DT0(ctx);
667 gen_op_fmov_DT0_drN(XREG(B11_8));
668 gen_op_inc8_rN(REG(B7_4));
669 } else {
670 gen_op_movl_rN_T0(REG(B7_4));
671 gen_op_ldfl_T0_FT0(ctx);
672 gen_op_fmov_FT0_frN(FREG(B11_8));
673 gen_op_inc4_rN(REG(B7_4));
675 return;
676 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
677 if (ctx->fpscr & FPSCR_SZ) {
678 gen_op_dec8_rN(REG(B11_8));
679 gen_op_fmov_drN_DT0(XREG(B7_4));
680 gen_op_movl_rN_T1(REG(B11_8));
681 gen_op_stfq_DT0_T1(ctx);
682 } else {
683 gen_op_dec4_rN(REG(B11_8));
684 gen_op_fmov_frN_FT0(FREG(B7_4));
685 gen_op_movl_rN_T1(REG(B11_8));
686 gen_op_stfl_FT0_T1(ctx);
688 return;
689 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
690 if (ctx->fpscr & FPSCR_SZ) {
691 gen_op_movl_rN_T0(REG(B7_4));
692 gen_op_add_rN_T0(REG(0));
693 gen_op_ldfq_T0_DT0(ctx);
694 gen_op_fmov_DT0_drN(XREG(B11_8));
695 } else {
696 gen_op_movl_rN_T0(REG(B7_4));
697 gen_op_add_rN_T0(REG(0));
698 gen_op_ldfl_T0_FT0(ctx);
699 gen_op_fmov_FT0_frN(FREG(B11_8));
701 return;
702 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
703 if (ctx->fpscr & FPSCR_SZ) {
704 gen_op_fmov_drN_DT0(XREG(B7_4));
705 gen_op_movl_rN_T1(REG(B11_8));
706 gen_op_add_rN_T1(REG(0));
707 gen_op_stfq_DT0_T1(ctx);
708 } else {
709 gen_op_fmov_frN_FT0(FREG(B7_4));
710 gen_op_movl_rN_T1(REG(B11_8));
711 gen_op_add_rN_T1(REG(0));
712 gen_op_stfl_FT0_T1(ctx);
714 return;
715 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
716 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
717 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
718 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
719 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
720 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
721 if (ctx->fpscr & FPSCR_PR) {
722 if (ctx->opcode & 0x0110)
723 break; /* illegal instruction */
724 gen_op_fmov_drN_DT1(DREG(B7_4));
725 gen_op_fmov_drN_DT0(DREG(B11_8));
727 else {
728 gen_op_fmov_frN_FT1(FREG(B7_4));
729 gen_op_fmov_frN_FT0(FREG(B11_8));
732 switch (ctx->opcode & 0xf00f) {
733 case 0xf000: /* fadd Rm,Rn */
734 ctx->fpscr & FPSCR_PR ? gen_op_fadd_DT() : gen_op_fadd_FT();
735 break;
736 case 0xf001: /* fsub Rm,Rn */
737 ctx->fpscr & FPSCR_PR ? gen_op_fsub_DT() : gen_op_fsub_FT();
738 break;
739 case 0xf002: /* fmul Rm,Rn */
740 ctx->fpscr & FPSCR_PR ? gen_op_fmul_DT() : gen_op_fmul_FT();
741 break;
742 case 0xf003: /* fdiv Rm,Rn */
743 ctx->fpscr & FPSCR_PR ? gen_op_fdiv_DT() : gen_op_fdiv_FT();
744 break;
745 case 0xf004: /* fcmp/eq Rm,Rn */
746 ctx->fpscr & FPSCR_PR ? gen_op_fcmp_eq_DT() : gen_op_fcmp_eq_FT();
747 return;
748 case 0xf005: /* fcmp/gt Rm,Rn */
749 ctx->fpscr & FPSCR_PR ? gen_op_fcmp_gt_DT() : gen_op_fcmp_gt_FT();
750 return;
753 if (ctx->fpscr & FPSCR_PR) {
754 gen_op_fmov_DT0_drN(DREG(B11_8));
756 else {
757 gen_op_fmov_FT0_frN(FREG(B11_8));
759 return;
762 switch (ctx->opcode & 0xff00) {
763 case 0xc900: /* and #imm,R0 */
764 gen_op_and_imm_rN(B7_0, REG(0));
765 return;
766 case 0xcd00: /* and.b #imm,@(R0,GBR) */
767 gen_op_movl_rN_T0(REG(0));
768 gen_op_addl_GBR_T0();
769 gen_op_movl_T0_T1();
770 gen_op_ldub_T0_T0(ctx);
771 gen_op_and_imm_T0(B7_0);
772 gen_op_stb_T0_T1(ctx);
773 return;
774 case 0x8b00: /* bf label */
775 CHECK_NOT_DELAY_SLOT
776 gen_conditional_jump(ctx, ctx->pc + 2,
777 ctx->pc + 4 + B7_0s * 2);
778 ctx->bstate = BS_BRANCH;
779 return;
780 case 0x8f00: /* bf/s label */
781 CHECK_NOT_DELAY_SLOT
782 gen_op_bf_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
783 ctx->flags |= DELAY_SLOT_CONDITIONAL;
784 return;
785 case 0x8900: /* bt label */
786 CHECK_NOT_DELAY_SLOT
787 gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2,
788 ctx->pc + 2);
789 ctx->bstate = BS_BRANCH;
790 return;
791 case 0x8d00: /* bt/s label */
792 CHECK_NOT_DELAY_SLOT
793 gen_op_bt_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
794 ctx->flags |= DELAY_SLOT_CONDITIONAL;
795 return;
796 case 0x8800: /* cmp/eq #imm,R0 */
797 gen_op_movl_rN_T0(REG(0));
798 gen_op_cmp_eq_imm_T0(B7_0s);
799 return;
800 case 0xc400: /* mov.b @(disp,GBR),R0 */
801 gen_op_stc_gbr_T0();
802 gen_op_addl_imm_T0(B7_0);
803 gen_op_ldb_T0_T0(ctx);
804 gen_op_movl_T0_rN(REG(0));
805 return;
806 case 0xc500: /* mov.w @(disp,GBR),R0 */
807 gen_op_stc_gbr_T0();
808 gen_op_addl_imm_T0(B7_0 * 2);
809 gen_op_ldw_T0_T0(ctx);
810 gen_op_movl_T0_rN(REG(0));
811 return;
812 case 0xc600: /* mov.l @(disp,GBR),R0 */
813 gen_op_stc_gbr_T0();
814 gen_op_addl_imm_T0(B7_0 * 4);
815 gen_op_ldl_T0_T0(ctx);
816 gen_op_movl_T0_rN(REG(0));
817 return;
818 case 0xc000: /* mov.b R0,@(disp,GBR) */
819 gen_op_stc_gbr_T0();
820 gen_op_addl_imm_T0(B7_0);
821 gen_op_movl_T0_T1();
822 gen_op_movl_rN_T0(REG(0));
823 gen_op_stb_T0_T1(ctx);
824 return;
825 case 0xc100: /* mov.w R0,@(disp,GBR) */
826 gen_op_stc_gbr_T0();
827 gen_op_addl_imm_T0(B7_0 * 2);
828 gen_op_movl_T0_T1();
829 gen_op_movl_rN_T0(REG(0));
830 gen_op_stw_T0_T1(ctx);
831 return;
832 case 0xc200: /* mov.l R0,@(disp,GBR) */
833 gen_op_stc_gbr_T0();
834 gen_op_addl_imm_T0(B7_0 * 4);
835 gen_op_movl_T0_T1();
836 gen_op_movl_rN_T0(REG(0));
837 gen_op_stl_T0_T1(ctx);
838 return;
839 case 0x8000: /* mov.b R0,@(disp,Rn) */
840 gen_op_movl_rN_T0(REG(0));
841 gen_op_movl_rN_T1(REG(B7_4));
842 gen_op_addl_imm_T1(B3_0);
843 gen_op_stb_T0_T1(ctx);
844 return;
845 case 0x8100: /* mov.w R0,@(disp,Rn) */
846 gen_op_movl_rN_T0(REG(0));
847 gen_op_movl_rN_T1(REG(B7_4));
848 gen_op_addl_imm_T1(B3_0 * 2);
849 gen_op_stw_T0_T1(ctx);
850 return;
851 case 0x8400: /* mov.b @(disp,Rn),R0 */
852 gen_op_movl_rN_T0(REG(B7_4));
853 gen_op_addl_imm_T0(B3_0);
854 gen_op_ldb_T0_T0(ctx);
855 gen_op_movl_T0_rN(REG(0));
856 return;
857 case 0x8500: /* mov.w @(disp,Rn),R0 */
858 gen_op_movl_rN_T0(REG(B7_4));
859 gen_op_addl_imm_T0(B3_0 * 2);
860 gen_op_ldw_T0_T0(ctx);
861 gen_op_movl_T0_rN(REG(0));
862 return;
863 case 0xc700: /* mova @(disp,PC),R0 */
864 gen_op_movl_imm_rN(((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3,
865 REG(0));
866 return;
867 case 0xcb00: /* or #imm,R0 */
868 gen_op_or_imm_rN(B7_0, REG(0));
869 return;
870 case 0xcf00: /* or.b #imm,@(R0,GBR) */
871 gen_op_movl_rN_T0(REG(0));
872 gen_op_addl_GBR_T0();
873 gen_op_movl_T0_T1();
874 gen_op_ldub_T0_T0(ctx);
875 gen_op_or_imm_T0(B7_0);
876 gen_op_stb_T0_T1(ctx);
877 return;
878 case 0xc300: /* trapa #imm */
879 CHECK_NOT_DELAY_SLOT gen_op_movl_imm_PC(ctx->pc);
880 gen_op_trapa(B7_0);
881 ctx->bstate = BS_BRANCH;
882 return;
883 case 0xc800: /* tst #imm,R0 */
884 gen_op_tst_imm_rN(B7_0, REG(0));
885 return;
886 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
887 gen_op_movl_rN_T0(REG(0));
888 gen_op_addl_GBR_T0();
889 gen_op_ldub_T0_T0(ctx);
890 gen_op_tst_imm_T0(B7_0);
891 return;
892 case 0xca00: /* xor #imm,R0 */
893 gen_op_xor_imm_rN(B7_0, REG(0));
894 return;
895 case 0xce00: /* xor.b #imm,@(R0,GBR) */
896 gen_op_movl_rN_T0(REG(0));
897 gen_op_addl_GBR_T0();
898 gen_op_movl_T0_T1();
899 gen_op_ldub_T0_T0(ctx);
900 gen_op_xor_imm_T0(B7_0);
901 gen_op_stb_T0_T1(ctx);
902 return;
905 switch (ctx->opcode & 0xf08f) {
906 case 0x408e: /* ldc Rm,Rn_BANK */
907 gen_op_movl_rN_rN(REG(B11_8), ALTREG(B6_4));
908 return;
909 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
910 gen_op_movl_rN_T0(REG(B11_8));
911 gen_op_ldl_T0_T0(ctx);
912 gen_op_movl_T0_rN(ALTREG(B6_4));
913 gen_op_inc4_rN(REG(B11_8));
914 return;
915 case 0x0082: /* stc Rm_BANK,Rn */
916 gen_op_movl_rN_rN(ALTREG(B6_4), REG(B11_8));
917 return;
918 case 0x4083: /* stc.l Rm_BANK,@-Rn */
919 gen_op_dec4_rN(REG(B11_8));
920 gen_op_movl_rN_T1(REG(B11_8));
921 gen_op_movl_rN_T0(ALTREG(B6_4));
922 gen_op_stl_T0_T1(ctx);
923 return;
926 switch (ctx->opcode & 0xf0ff) {
927 case 0x0023: /* braf Rn */
928 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
929 gen_op_braf_T0(ctx->pc + 4);
930 ctx->flags |= DELAY_SLOT;
931 ctx->delayed_pc = (uint32_t) - 1;
932 return;
933 case 0x0003: /* bsrf Rn */
934 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
935 gen_op_bsrf_T0(ctx->pc + 4);
936 ctx->flags |= DELAY_SLOT;
937 ctx->delayed_pc = (uint32_t) - 1;
938 return;
939 case 0x4015: /* cmp/pl Rn */
940 gen_op_movl_rN_T0(REG(B11_8));
941 gen_op_cmp_pl_T0();
942 return;
943 case 0x4011: /* cmp/pz Rn */
944 gen_op_movl_rN_T0(REG(B11_8));
945 gen_op_cmp_pz_T0();
946 return;
947 case 0x4010: /* dt Rn */
948 gen_op_dt_rN(REG(B11_8));
949 return;
950 case 0x402b: /* jmp @Rn */
951 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
952 gen_op_jmp_T0();
953 ctx->flags |= DELAY_SLOT;
954 ctx->delayed_pc = (uint32_t) - 1;
955 return;
956 case 0x400b: /* jsr @Rn */
957 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
958 gen_op_jsr_T0(ctx->pc + 4);
959 ctx->flags |= DELAY_SLOT;
960 ctx->delayed_pc = (uint32_t) - 1;
961 return;
962 #define LDST(reg,ldnum,ldpnum,ldop,stnum,stpnum,stop,extrald) \
963 case ldnum: \
964 gen_op_movl_rN_T0 (REG(B11_8)); \
965 gen_op_##ldop##_T0_##reg (); \
966 extrald \
967 return; \
968 case ldpnum: \
969 gen_op_movl_rN_T0 (REG(B11_8)); \
970 gen_op_ldl_T0_T0 (ctx); \
971 gen_op_inc4_rN (REG(B11_8)); \
972 gen_op_##ldop##_T0_##reg (); \
973 extrald \
974 return; \
975 case stnum: \
976 gen_op_##stop##_##reg##_T0 (); \
977 gen_op_movl_T0_rN (REG(B11_8)); \
978 return; \
979 case stpnum: \
980 gen_op_##stop##_##reg##_T0 (); \
981 gen_op_dec4_rN (REG(B11_8)); \
982 gen_op_movl_rN_T1 (REG(B11_8)); \
983 gen_op_stl_T0_T1 (ctx); \
984 return;
985 LDST(sr, 0x400e, 0x4007, ldc, 0x0002, 0x4003, stc, ctx->bstate =
986 BS_STOP;)
987 LDST(gbr, 0x401e, 0x4017, ldc, 0x0012, 0x4013, stc,)
988 LDST(vbr, 0x402e, 0x4027, ldc, 0x0022, 0x4023, stc,)
989 LDST(ssr, 0x403e, 0x4037, ldc, 0x0032, 0x4033, stc,)
990 LDST(spc, 0x404e, 0x4047, ldc, 0x0042, 0x4043, stc,)
991 LDST(dbr, 0x40fa, 0x40f6, ldc, 0x00fa, 0x40f2, stc,)
992 LDST(mach, 0x400a, 0x4006, lds, 0x000a, 0x4002, sts,)
993 LDST(macl, 0x401a, 0x4016, lds, 0x001a, 0x4012, sts,)
994 LDST(pr, 0x402a, 0x4026, lds, 0x002a, 0x4022, sts,)
995 LDST(fpul, 0x405a, 0x4056, lds, 0x005a, 0x4052, sts,)
996 LDST(fpscr, 0x406a, 0x4066, lds, 0x006a, 0x4062, sts, ctx->bstate =
997 BS_STOP;)
998 case 0x00c3: /* movca.l R0,@Rm */
999 gen_op_movl_rN_T0(REG(0));
1000 gen_op_movl_rN_T1(REG(B11_8));
1001 gen_op_stl_T0_T1(ctx);
1002 return;
1003 case 0x0029: /* movt Rn */
1004 gen_op_movt_rN(REG(B11_8));
1005 return;
1006 case 0x0093: /* ocbi @Rn */
1007 gen_op_movl_rN_T0(REG(B11_8));
1008 gen_op_ldl_T0_T0(ctx);
1009 return;
1010 case 0x00a3: /* ocbp @Rn */
1011 gen_op_movl_rN_T0(REG(B11_8));
1012 gen_op_ldl_T0_T0(ctx);
1013 return;
1014 case 0x00b3: /* ocbwb @Rn */
1015 gen_op_movl_rN_T0(REG(B11_8));
1016 gen_op_ldl_T0_T0(ctx);
1017 return;
1018 case 0x0083: /* pref @Rn */
1019 return;
1020 case 0x4024: /* rotcl Rn */
1021 gen_op_rotcl_Rn(REG(B11_8));
1022 return;
1023 case 0x4025: /* rotcr Rn */
1024 gen_op_rotcr_Rn(REG(B11_8));
1025 return;
1026 case 0x4004: /* rotl Rn */
1027 gen_op_rotl_Rn(REG(B11_8));
1028 return;
1029 case 0x4005: /* rotr Rn */
1030 gen_op_rotr_Rn(REG(B11_8));
1031 return;
1032 case 0x4000: /* shll Rn */
1033 case 0x4020: /* shal Rn */
1034 gen_op_shal_Rn(REG(B11_8));
1035 return;
1036 case 0x4021: /* shar Rn */
1037 gen_op_shar_Rn(REG(B11_8));
1038 return;
1039 case 0x4001: /* shlr Rn */
1040 gen_op_shlr_Rn(REG(B11_8));
1041 return;
1042 case 0x4008: /* shll2 Rn */
1043 gen_op_shll2_Rn(REG(B11_8));
1044 return;
1045 case 0x4018: /* shll8 Rn */
1046 gen_op_shll8_Rn(REG(B11_8));
1047 return;
1048 case 0x4028: /* shll16 Rn */
1049 gen_op_shll16_Rn(REG(B11_8));
1050 return;
1051 case 0x4009: /* shlr2 Rn */
1052 gen_op_shlr2_Rn(REG(B11_8));
1053 return;
1054 case 0x4019: /* shlr8 Rn */
1055 gen_op_shlr8_Rn(REG(B11_8));
1056 return;
1057 case 0x4029: /* shlr16 Rn */
1058 gen_op_shlr16_Rn(REG(B11_8));
1059 return;
1060 case 0x401b: /* tas.b @Rn */
1061 gen_op_tasb_rN(REG(B11_8));
1062 return;
1063 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1064 gen_op_movl_fpul_FT0();
1065 gen_op_fmov_FT0_frN(FREG(B11_8));
1066 return;
1067 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1068 gen_op_fmov_frN_FT0(FREG(B11_8));
1069 gen_op_movl_FT0_fpul();
1070 return;
1071 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
1072 if (ctx->fpscr & FPSCR_PR) {
1073 if (ctx->opcode & 0x0100)
1074 break; /* illegal instruction */
1075 gen_op_float_DT();
1076 gen_op_fmov_DT0_drN(DREG(B11_8));
1078 else {
1079 gen_op_float_FT();
1080 gen_op_fmov_FT0_frN(FREG(B11_8));
1082 return;
1083 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1084 if (ctx->fpscr & FPSCR_PR) {
1085 if (ctx->opcode & 0x0100)
1086 break; /* illegal instruction */
1087 gen_op_fmov_drN_DT0(DREG(B11_8));
1088 gen_op_ftrc_DT();
1090 else {
1091 gen_op_fmov_frN_FT0(FREG(B11_8));
1092 gen_op_ftrc_FT();
1094 return;
1095 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
1096 gen_op_fneg_frN(FREG(B11_8));
1097 return;
1098 case 0xf05d: /* fabs FRn/DRn */
1099 if (ctx->fpscr & FPSCR_PR) {
1100 if (ctx->opcode & 0x0100)
1101 break; /* illegal instruction */
1102 gen_op_fmov_drN_DT0(DREG(B11_8));
1103 gen_op_fabs_DT();
1104 gen_op_fmov_DT0_drN(DREG(B11_8));
1105 } else {
1106 gen_op_fmov_frN_FT0(FREG(B11_8));
1107 gen_op_fabs_FT();
1108 gen_op_fmov_FT0_frN(FREG(B11_8));
1110 return;
1111 case 0xf06d: /* fsqrt FRn */
1112 if (ctx->fpscr & FPSCR_PR) {
1113 if (ctx->opcode & 0x0100)
1114 break; /* illegal instruction */
1115 gen_op_fmov_drN_DT0(FREG(B11_8));
1116 gen_op_fsqrt_DT();
1117 gen_op_fmov_DT0_drN(FREG(B11_8));
1118 } else {
1119 gen_op_fmov_frN_FT0(FREG(B11_8));
1120 gen_op_fsqrt_FT();
1121 gen_op_fmov_FT0_frN(FREG(B11_8));
1123 return;
1124 case 0xf07d: /* fsrra FRn */
1125 break;
1126 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
1127 if (!(ctx->fpscr & FPSCR_PR)) {
1128 gen_op_movl_imm_T0(0);
1129 gen_op_fmov_T0_frN(FREG(B11_8));
1130 return;
1132 break;
1133 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
1134 if (!(ctx->fpscr & FPSCR_PR)) {
1135 gen_op_movl_imm_T0(0x3f800000);
1136 gen_op_fmov_T0_frN(FREG(B11_8));
1137 return;
1139 break;
1140 case 0xf0ad: /* fcnvsd FPUL,DRn */
1141 gen_op_movl_fpul_FT0();
1142 gen_op_fcnvsd_FT_DT();
1143 gen_op_fmov_DT0_drN(DREG(B11_8));
1144 return;
1145 case 0xf0bd: /* fcnvds DRn,FPUL */
1146 gen_op_fmov_drN_DT0(DREG(B11_8));
1147 gen_op_fcnvds_DT_FT();
1148 gen_op_movl_FT0_fpul();
1149 return;
1152 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1153 ctx->opcode, ctx->pc);
1154 gen_op_raise_illegal_instruction();
1155 ctx->bstate = BS_EXCP;
1158 void decode_opc(DisasContext * ctx)
1160 uint32_t old_flags = ctx->flags;
1162 _decode_opc(ctx);
1164 if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
1165 if (ctx->flags & DELAY_SLOT_CLEARME) {
1166 gen_op_store_flags(0);
1168 ctx->flags = 0;
1169 ctx->bstate = BS_BRANCH;
1170 if (old_flags & DELAY_SLOT_CONDITIONAL) {
1171 gen_delayed_conditional_jump(ctx);
1172 } else if (old_flags & DELAY_SLOT) {
1173 gen_jump(ctx);
1179 static inline int
1180 gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
1181 int search_pc)
1183 DisasContext ctx;
1184 target_ulong pc_start;
1185 static uint16_t *gen_opc_end;
1186 int i, ii;
1188 pc_start = tb->pc;
1189 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1190 ctx.pc = pc_start;
1191 ctx.flags = (uint32_t)tb->flags;
1192 ctx.bstate = BS_NONE;
1193 ctx.sr = env->sr;
1194 ctx.fpscr = env->fpscr;
1195 ctx.memidx = (env->sr & SR_MD) ? 1 : 0;
1196 /* We don't know if the delayed pc came from a dynamic or static branch,
1197 so assume it is a dynamic branch. */
1198 ctx.delayed_pc = -1; /* use delayed pc from env pointer */
1199 ctx.tb = tb;
1200 ctx.singlestep_enabled = env->singlestep_enabled;
1202 #ifdef DEBUG_DISAS
1203 if (loglevel & CPU_LOG_TB_CPU) {
1204 fprintf(logfile,
1205 "------------------------------------------------\n");
1206 cpu_dump_state(env, logfile, fprintf, 0);
1208 #endif
1210 ii = -1;
1211 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1212 if (env->nb_breakpoints > 0) {
1213 for (i = 0; i < env->nb_breakpoints; i++) {
1214 if (ctx.pc == env->breakpoints[i]) {
1215 /* We have hit a breakpoint - make sure PC is up-to-date */
1216 gen_op_movl_imm_PC(ctx.pc);
1217 gen_op_debug();
1218 ctx.bstate = BS_EXCP;
1219 break;
1223 if (search_pc) {
1224 i = gen_opc_ptr - gen_opc_buf;
1225 if (ii < i) {
1226 ii++;
1227 while (ii < i)
1228 gen_opc_instr_start[ii++] = 0;
1230 gen_opc_pc[ii] = ctx.pc;
1231 gen_opc_hflags[ii] = ctx.flags;
1232 gen_opc_instr_start[ii] = 1;
1234 #if 0
1235 fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
1236 fflush(stderr);
1237 #endif
1238 ctx.opcode = lduw_code(ctx.pc);
1239 decode_opc(&ctx);
1240 ctx.pc += 2;
1241 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1242 break;
1243 if (env->singlestep_enabled)
1244 break;
1245 #ifdef SH4_SINGLE_STEP
1246 break;
1247 #endif
1249 if (env->singlestep_enabled) {
1250 gen_op_debug();
1251 } else {
1252 switch (ctx.bstate) {
1253 case BS_STOP:
1254 /* gen_op_interrupt_restart(); */
1255 /* fall through */
1256 case BS_NONE:
1257 if (ctx.flags) {
1258 gen_op_store_flags(ctx.flags | DELAY_SLOT_CLEARME);
1260 gen_goto_tb(&ctx, 0, ctx.pc);
1261 break;
1262 case BS_EXCP:
1263 /* gen_op_interrupt_restart(); */
1264 tcg_gen_exit_tb(0);
1265 break;
1266 case BS_BRANCH:
1267 default:
1268 break;
1272 *gen_opc_ptr = INDEX_op_end;
1273 if (search_pc) {
1274 i = gen_opc_ptr - gen_opc_buf;
1275 ii++;
1276 while (ii <= i)
1277 gen_opc_instr_start[ii++] = 0;
1278 } else {
1279 tb->size = ctx.pc - pc_start;
1282 #ifdef DEBUG_DISAS
1283 #ifdef SH4_DEBUG_DISAS
1284 if (loglevel & CPU_LOG_TB_IN_ASM)
1285 fprintf(logfile, "\n");
1286 #endif
1287 if (loglevel & CPU_LOG_TB_IN_ASM) {
1288 fprintf(logfile, "IN:\n"); /* , lookup_symbol(pc_start)); */
1289 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1290 fprintf(logfile, "\n");
1292 #endif
1293 return 0;
1296 int gen_intermediate_code(CPUState * env, struct TranslationBlock *tb)
1298 return gen_intermediate_code_internal(env, tb, 0);
1301 int gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
1303 return gen_intermediate_code_internal(env, tb, 1);