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
28 #define SH4_DEBUG_DISAS
29 //#define SH4_SINGLE_STEP
36 #include "qemu-common.h"
38 typedef struct DisasContext {
39 struct TranslationBlock *tb;
48 int singlestep_enabled;
52 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
55 BS_STOP = 1, /* We want to stop translation for any reason */
56 BS_BRANCH = 2, /* We reached a branch condition */
57 BS_EXCP = 3, /* We reached an exception condition */
60 /* global register indexes */
62 static TCGv cpu_gregs[24];
63 static TCGv cpu_pc, cpu_sr, cpu_ssr, cpu_spc, cpu_gbr;
64 static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl;
65 static TCGv cpu_pr, cpu_fpscr, cpu_fpul, cpu_flags;
67 /* internal register indexes */
68 static TCGv cpu_flags, cpu_delayed_pc;
70 /* dyngen register indexes */
73 #include "gen-icount.h"
75 static void sh4_translate_init(void)
78 static int done_init = 0;
79 static const char * const gregnames[24] = {
80 "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
81 "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
82 "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
83 "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
84 "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
90 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
91 cpu_T[0] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG1, "T0");
92 cpu_T[1] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG2, "T1");
94 for (i = 0; i < 24; i++)
95 cpu_gregs[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
96 offsetof(CPUState, gregs[i]),
99 cpu_pc = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
100 offsetof(CPUState, pc), "PC");
101 cpu_sr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
102 offsetof(CPUState, sr), "SR");
103 cpu_ssr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
104 offsetof(CPUState, ssr), "SSR");
105 cpu_spc = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
106 offsetof(CPUState, spc), "SPC");
107 cpu_gbr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
108 offsetof(CPUState, gbr), "GBR");
109 cpu_vbr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
110 offsetof(CPUState, vbr), "VBR");
111 cpu_sgr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
112 offsetof(CPUState, sgr), "SGR");
113 cpu_dbr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
114 offsetof(CPUState, dbr), "DBR");
115 cpu_mach = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
116 offsetof(CPUState, mach), "MACH");
117 cpu_macl = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
118 offsetof(CPUState, macl), "MACL");
119 cpu_pr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
120 offsetof(CPUState, pr), "PR");
121 cpu_fpscr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
122 offsetof(CPUState, fpscr), "FPSCR");
123 cpu_fpul = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
124 offsetof(CPUState, fpul), "FPUL");
126 cpu_flags = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
127 offsetof(CPUState, flags), "_flags_");
128 cpu_delayed_pc = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
129 offsetof(CPUState, delayed_pc),
132 /* register helpers */
134 #define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
140 #ifdef CONFIG_USER_ONLY
142 #define GEN_OP_LD(width, reg) \
143 void gen_op_ld##width##_T0_##reg (DisasContext *ctx) { \
144 gen_op_ld##width##_T0_##reg##_raw(); \
146 #define GEN_OP_ST(width, reg) \
147 void gen_op_st##width##_##reg##_T1 (DisasContext *ctx) { \
148 gen_op_st##width##_##reg##_T1_raw(); \
153 #define GEN_OP_LD(width, reg) \
154 void gen_op_ld##width##_T0_##reg (DisasContext *ctx) { \
155 if (ctx->memidx) gen_op_ld##width##_T0_##reg##_kernel(); \
156 else gen_op_ld##width##_T0_##reg##_user();\
158 #define GEN_OP_ST(width, reg) \
159 void gen_op_st##width##_##reg##_T1 (DisasContext *ctx) { \
160 if (ctx->memidx) gen_op_st##width##_##reg##_T1_kernel(); \
161 else gen_op_st##width##_##reg##_T1_user();\
171 void cpu_dump_state(CPUState * env, FILE * f,
172 int (*cpu_fprintf) (FILE * f, const char *fmt, ...),
176 cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
177 env->pc, env->sr, env->pr, env->fpscr);
178 cpu_fprintf(f, "spc=0x%08x ssr=0x%08x gbr=0x%08x vbr=0x%08x\n",
179 env->spc, env->ssr, env->gbr, env->vbr);
180 cpu_fprintf(f, "sgr=0x%08x dbr=0x%08x delayed_pc=0x%08x fpul=0x%08x\n",
181 env->sgr, env->dbr, env->delayed_pc, env->fpul);
182 for (i = 0; i < 24; i += 4) {
183 cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
184 i, env->gregs[i], i + 1, env->gregs[i + 1],
185 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
187 if (env->flags & DELAY_SLOT) {
188 cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
190 } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
191 cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
196 void cpu_sh4_reset(CPUSH4State * env)
198 #if defined(CONFIG_USER_ONLY)
199 env->sr = SR_FD; /* FD - kernel does lazy fpu context switch */
201 env->sr = 0x700000F0; /* MD, RB, BL, I3-I0 */
204 env->pc = 0xA0000000;
205 #if defined(CONFIG_USER_ONLY)
206 env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
207 set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
209 env->fpscr = 0x00040001; /* CPU reset value according to SH4 manual */
210 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
215 CPUSH4State *cpu_sh4_init(const char *cpu_model)
219 env = qemu_mallocz(sizeof(CPUSH4State));
223 sh4_translate_init();
229 static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
231 TranslationBlock *tb;
234 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
235 !ctx->singlestep_enabled) {
236 /* Use a direct jump if in same page and singlestep not enabled */
238 tcg_gen_movi_i32(cpu_pc, dest);
239 tcg_gen_exit_tb((long) tb + n);
241 tcg_gen_movi_i32(cpu_pc, dest);
242 if (ctx->singlestep_enabled)
243 tcg_gen_helper_0_0(helper_debug);
248 static void gen_jump(DisasContext * ctx)
250 if (ctx->delayed_pc == (uint32_t) - 1) {
251 /* Target is not statically known, it comes necessarily from a
252 delayed jump as immediate jump are conditinal jumps */
253 tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc);
254 if (ctx->singlestep_enabled)
255 tcg_gen_helper_0_0(helper_debug);
258 gen_goto_tb(ctx, 0, ctx->delayed_pc);
262 static inline void gen_branch_slot(uint32_t delayed_pc, int t)
264 int label = gen_new_label();
265 tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc);
266 tcg_gen_andi_i32(cpu_T[0], cpu_sr, SR_T);
267 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], t ? SR_T : 0, label);
268 tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
269 gen_set_label(label);
272 /* Immediate conditional jump (bt or bf) */
273 static void gen_conditional_jump(DisasContext * ctx,
274 target_ulong ift, target_ulong ifnott)
278 l1 = gen_new_label();
279 tcg_gen_andi_i32(cpu_T[0], cpu_sr, SR_T);
280 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_T[0], SR_T, l1);
281 gen_goto_tb(ctx, 0, ifnott);
283 gen_goto_tb(ctx, 1, ift);
286 /* Delayed conditional jump (bt or bf) */
287 static void gen_delayed_conditional_jump(DisasContext * ctx)
291 l1 = gen_new_label();
292 tcg_gen_andi_i32(cpu_T[0], cpu_flags, DELAY_SLOT_TRUE);
293 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_T[0], DELAY_SLOT_TRUE, l1);
294 gen_goto_tb(ctx, 1, ctx->pc + 2);
296 tcg_gen_andi_i32(cpu_flags, cpu_flags, ~DELAY_SLOT_TRUE);
300 static inline void gen_set_t(void)
302 tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T);
305 static inline void gen_clr_t(void)
307 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
310 static inline void gen_cmp(int cond, TCGv t0, TCGv t1)
312 int label1 = gen_new_label();
313 int label2 = gen_new_label();
314 tcg_gen_brcond_i32(cond, t1, t0, label1);
317 gen_set_label(label1);
319 gen_set_label(label2);
322 static inline void gen_cmp_imm(int cond, TCGv t0, int32_t imm)
324 int label1 = gen_new_label();
325 int label2 = gen_new_label();
326 tcg_gen_brcondi_i32(cond, t0, imm, label1);
329 gen_set_label(label1);
331 gen_set_label(label2);
334 static inline void gen_store_flags(uint32_t flags)
336 tcg_gen_andi_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
337 tcg_gen_ori_i32(cpu_flags, cpu_flags, flags);
340 static inline void gen_copy_bit_i32(TCGv t0, int p0, TCGv t1, int p1)
342 TCGv tmp = tcg_temp_new(TCG_TYPE_I32);
347 tcg_gen_andi_i32(tmp, t1, (1 << p1));
348 tcg_gen_andi_i32(t0, t0, ~(1 << p0));
350 tcg_gen_shri_i32(tmp, tmp, p1 - p0);
352 tcg_gen_shli_i32(tmp, tmp, p0 - p1);
353 tcg_gen_or_i32(t0, t0, tmp);
358 #define B3_0 (ctx->opcode & 0xf)
359 #define B6_4 ((ctx->opcode >> 4) & 0x7)
360 #define B7_4 ((ctx->opcode >> 4) & 0xf)
361 #define B7_0 (ctx->opcode & 0xff)
362 #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
363 #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
364 (ctx->opcode & 0xfff))
365 #define B11_8 ((ctx->opcode >> 8) & 0xf)
366 #define B15_12 ((ctx->opcode >> 12) & 0xf)
368 #define REG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB) ? \
369 (cpu_gregs[x + 16]) : (cpu_gregs[x]))
371 #define ALTREG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) != (SR_MD | SR_RB) \
372 ? (cpu_gregs[x + 16]) : (cpu_gregs[x]))
374 #define FREG(x) (ctx->fpscr & FPSCR_FR ? (x) ^ 0x10 : (x))
375 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
376 #define XREG(x) (ctx->fpscr & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x))
377 #define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */
379 #define CHECK_NOT_DELAY_SLOT \
380 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
381 {tcg_gen_helper_0_0(helper_raise_slot_illegal_instruction); ctx->bstate = BS_EXCP; \
384 void _decode_opc(DisasContext * ctx)
387 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
389 switch (ctx->opcode) {
390 case 0x0019: /* div0u */
391 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(SR_M | SR_Q | SR_T));
393 case 0x000b: /* rts */
395 tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
396 ctx->flags |= DELAY_SLOT;
397 ctx->delayed_pc = (uint32_t) - 1;
399 case 0x0028: /* clrmac */
400 tcg_gen_movi_i32(cpu_mach, 0);
401 tcg_gen_movi_i32(cpu_macl, 0);
403 case 0x0048: /* clrs */
404 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_S);
406 case 0x0008: /* clrt */
409 case 0x0038: /* ldtlb */
410 #if defined(CONFIG_USER_ONLY)
411 assert(0); /* XXXXX */
413 tcg_gen_helper_0_0(helper_ldtlb);
416 case 0x002b: /* rte */
418 tcg_gen_mov_i32(cpu_sr, cpu_ssr);
419 tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
420 ctx->flags |= DELAY_SLOT;
421 ctx->delayed_pc = (uint32_t) - 1;
423 case 0x0058: /* sets */
424 tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_S);
426 case 0x0018: /* sett */
429 case 0xfbfd: /* frchg */
430 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
431 ctx->bstate = BS_STOP;
433 case 0xf3fd: /* fschg */
434 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ);
435 ctx->bstate = BS_STOP;
437 case 0x0009: /* nop */
439 case 0x001b: /* sleep */
441 tcg_gen_helper_0_0(helper_sleep);
443 tcg_gen_helper_0_0(helper_raise_illegal_instruction);
444 ctx->bstate = BS_EXCP;
449 switch (ctx->opcode & 0xf000) {
450 case 0x1000: /* mov.l Rm,@(disp,Rn) */
451 tcg_gen_addi_i32(cpu_T[0], REG(B11_8), B3_0 * 4);
452 tcg_gen_qemu_st32(REG(B7_4), cpu_T[0], ctx->memidx);
454 case 0x5000: /* mov.l @(disp,Rm),Rn */
455 tcg_gen_addi_i32(cpu_T[0], REG(B7_4), B3_0 * 4);
456 tcg_gen_qemu_ld32s(REG(B11_8), cpu_T[0], ctx->memidx);
458 case 0xe000: /* mov #imm,Rn */
459 tcg_gen_movi_i32(REG(B11_8), B7_0s);
461 case 0x9000: /* mov.w @(disp,PC),Rn */
462 tcg_gen_movi_i32(cpu_T[0], ctx->pc + 4 + B7_0 * 2);
463 tcg_gen_qemu_ld16s(REG(B11_8), cpu_T[0], ctx->memidx);
465 case 0xd000: /* mov.l @(disp,PC),Rn */
466 tcg_gen_movi_i32(cpu_T[0], (ctx->pc + 4 + B7_0 * 4) & ~3);
467 tcg_gen_qemu_ld32s(REG(B11_8), cpu_T[0], ctx->memidx);
469 case 0x7000: /* add #imm,Rn */
470 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s);
472 case 0xa000: /* bra disp */
474 ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
475 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
476 ctx->flags |= DELAY_SLOT;
478 case 0xb000: /* bsr disp */
480 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
481 ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
482 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
483 ctx->flags |= DELAY_SLOT;
487 switch (ctx->opcode & 0xf00f) {
488 case 0x6003: /* mov Rm,Rn */
489 tcg_gen_mov_i32(REG(B11_8), REG(B7_4));
491 case 0x2000: /* mov.b Rm,@Rn */
492 tcg_gen_qemu_st8(REG(B7_4), REG(B11_8), ctx->memidx);
494 case 0x2001: /* mov.w Rm,@Rn */
495 tcg_gen_qemu_st16(REG(B7_4), REG(B11_8), ctx->memidx);
497 case 0x2002: /* mov.l Rm,@Rn */
498 tcg_gen_qemu_st32(REG(B7_4), REG(B11_8), ctx->memidx);
500 case 0x6000: /* mov.b @Rm,Rn */
501 tcg_gen_qemu_ld8s(REG(B11_8), REG(B7_4), ctx->memidx);
503 case 0x6001: /* mov.w @Rm,Rn */
504 tcg_gen_qemu_ld16s(REG(B11_8), REG(B7_4), ctx->memidx);
506 case 0x6002: /* mov.l @Rm,Rn */
507 tcg_gen_qemu_ld32s(REG(B11_8), REG(B7_4), ctx->memidx);
509 case 0x2004: /* mov.b Rm,@-Rn */
510 tcg_gen_subi_i32(cpu_T[0], REG(B11_8), 1);
511 tcg_gen_qemu_st8(REG(B7_4), cpu_T[0], ctx->memidx); /* might cause re-execution */
512 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1); /* modify register status */
514 case 0x2005: /* mov.w Rm,@-Rn */
515 tcg_gen_subi_i32(cpu_T[0], REG(B11_8), 2);
516 tcg_gen_qemu_st16(REG(B7_4), cpu_T[0], ctx->memidx);
517 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 2);
519 case 0x2006: /* mov.l Rm,@-Rn */
520 tcg_gen_subi_i32(cpu_T[0], REG(B11_8), 4);
521 tcg_gen_qemu_st32(REG(B7_4), cpu_T[0], ctx->memidx);
522 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
524 case 0x6004: /* mov.b @Rm+,Rn */
525 tcg_gen_qemu_ld8s(REG(B11_8), REG(B7_4), ctx->memidx);
527 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1);
529 case 0x6005: /* mov.w @Rm+,Rn */
530 tcg_gen_qemu_ld16s(REG(B11_8), REG(B7_4), ctx->memidx);
532 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
534 case 0x6006: /* mov.l @Rm+,Rn */
535 tcg_gen_qemu_ld32s(REG(B11_8), REG(B7_4), ctx->memidx);
537 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
539 case 0x0004: /* mov.b Rm,@(R0,Rn) */
540 tcg_gen_add_i32(cpu_T[0], REG(B11_8), REG(0));
541 tcg_gen_qemu_st8(REG(B7_4), cpu_T[0], ctx->memidx);
543 case 0x0005: /* mov.w Rm,@(R0,Rn) */
544 tcg_gen_add_i32(cpu_T[0], REG(B11_8), REG(0));
545 tcg_gen_qemu_st16(REG(B7_4), cpu_T[0], ctx->memidx);
547 case 0x0006: /* mov.l Rm,@(R0,Rn) */
548 tcg_gen_add_i32(cpu_T[0], REG(B11_8), REG(0));
549 tcg_gen_qemu_st32(REG(B7_4), cpu_T[0], ctx->memidx);
551 case 0x000c: /* mov.b @(R0,Rm),Rn */
552 tcg_gen_add_i32(cpu_T[0], REG(B7_4), REG(0));
553 tcg_gen_qemu_ld8s(REG(B11_8), cpu_T[0], ctx->memidx);
555 case 0x000d: /* mov.w @(R0,Rm),Rn */
556 tcg_gen_add_i32(cpu_T[0], REG(B7_4), REG(0));
557 tcg_gen_qemu_ld16s(REG(B11_8), cpu_T[0], ctx->memidx);
559 case 0x000e: /* mov.l @(R0,Rm),Rn */
560 tcg_gen_add_i32(cpu_T[0], REG(B7_4), REG(0));
561 tcg_gen_qemu_ld32s(REG(B11_8), cpu_T[0], ctx->memidx);
563 case 0x6008: /* swap.b Rm,Rn */
564 tcg_gen_ext8u_i32(cpu_T[0], REG(B7_4));
565 tcg_gen_shli_i32(cpu_T[0], cpu_T[0], 8);
566 tcg_gen_shri_i32(cpu_T[1], REG(B7_4), 8);
567 tcg_gen_ext8u_i32(cpu_T[1], cpu_T[1]);
568 tcg_gen_or_i32(REG(B11_8), cpu_T[0], cpu_T[1]);
570 case 0x6009: /* swap.w Rm,Rn */
571 tcg_gen_ext16u_i32(cpu_T[0], REG(B7_4));
572 tcg_gen_shli_i32(cpu_T[0], cpu_T[0], 16);
573 tcg_gen_shri_i32(cpu_T[1], REG(B7_4), 16);
574 tcg_gen_ext16u_i32(cpu_T[1], cpu_T[1]);
575 tcg_gen_or_i32(REG(B11_8), cpu_T[0], cpu_T[1]);
577 case 0x200d: /* xtrct Rm,Rn */
578 tcg_gen_ext16u_i32(cpu_T[0], REG(B7_4));
579 tcg_gen_shli_i32(cpu_T[0], cpu_T[0], 16);
580 tcg_gen_shri_i32(cpu_T[1], REG(B11_8), 16);
581 tcg_gen_ext16u_i32(cpu_T[1], cpu_T[1]);
582 tcg_gen_or_i32(REG(B11_8), cpu_T[0], cpu_T[1]);
584 case 0x300c: /* add Rm,Rn */
585 tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4));
587 case 0x300e: /* addc Rm,Rn */
588 tcg_gen_helper_1_2(helper_addc, REG(B11_8), REG(B7_4), REG(B11_8));
590 case 0x300f: /* addv Rm,Rn */
591 tcg_gen_helper_1_2(helper_addv, REG(B11_8), REG(B7_4), REG(B11_8));
593 case 0x2009: /* and Rm,Rn */
594 tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4));
596 case 0x3000: /* cmp/eq Rm,Rn */
597 gen_cmp(TCG_COND_EQ, REG(B7_4), REG(B11_8));
599 case 0x3003: /* cmp/ge Rm,Rn */
600 gen_cmp(TCG_COND_GE, REG(B7_4), REG(B11_8));
602 case 0x3007: /* cmp/gt Rm,Rn */
603 gen_cmp(TCG_COND_GT, REG(B7_4), REG(B11_8));
605 case 0x3006: /* cmp/hi Rm,Rn */
606 gen_cmp(TCG_COND_GTU, REG(B7_4), REG(B11_8));
608 case 0x3002: /* cmp/hs Rm,Rn */
609 gen_cmp(TCG_COND_GEU, REG(B7_4), REG(B11_8));
611 case 0x200c: /* cmp/str Rm,Rn */
613 int label1 = gen_new_label();
614 int label2 = gen_new_label();
615 tcg_gen_xor_i32(cpu_T[0], REG(B7_4), REG(B11_8));
616 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], 0xff000000);
617 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_T[0], 0, label1);
618 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], 0x00ff0000);
619 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_T[0], 0, label1);
620 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], 0x0000ff00);
621 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_T[0], 0, label1);
622 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], 0x000000ff);
623 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_T[0], 0, label1);
624 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
626 gen_set_label(label1);
627 tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T);
628 gen_set_label(label2);
631 case 0x2007: /* div0s Rm,Rn */
632 gen_copy_bit_i32(cpu_sr, 8, REG(B11_8), 31); /* SR_Q */
633 gen_copy_bit_i32(cpu_sr, 9, REG(B7_4), 31); /* SR_M */
634 tcg_gen_xor_i32(cpu_T[0], REG(B7_4), REG(B11_8));
635 gen_copy_bit_i32(cpu_sr, 0, cpu_T[0], 31); /* SR_T */
637 case 0x3004: /* div1 Rm,Rn */
638 tcg_gen_helper_1_2(helper_div1, REG(B11_8), REG(B7_4), REG(B11_8));
640 case 0x300d: /* dmuls.l Rm,Rn */
642 TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
643 TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
645 tcg_gen_ext_i32_i64(tmp1, REG(B7_4));
646 tcg_gen_ext_i32_i64(tmp2, REG(B11_8));
647 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
648 tcg_gen_trunc_i64_i32(cpu_macl, tmp1);
649 tcg_gen_shri_i64(tmp1, tmp1, 32);
650 tcg_gen_trunc_i64_i32(cpu_mach, tmp1);
656 case 0x3005: /* dmulu.l Rm,Rn */
658 TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
659 TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
661 tcg_gen_extu_i32_i64(tmp1, REG(B7_4));
662 tcg_gen_extu_i32_i64(tmp2, REG(B11_8));
663 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
664 tcg_gen_trunc_i64_i32(cpu_macl, tmp1);
665 tcg_gen_shri_i64(tmp1, tmp1, 32);
666 tcg_gen_trunc_i64_i32(cpu_mach, tmp1);
672 case 0x600e: /* exts.b Rm,Rn */
673 tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4));
675 case 0x600f: /* exts.w Rm,Rn */
676 tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4));
678 case 0x600c: /* extu.b Rm,Rn */
679 tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4));
681 case 0x600d: /* extu.w Rm,Rn */
682 tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4));
684 case 0x000f: /* mac.l @Rm+,@Rn+ */
685 tcg_gen_qemu_ld32s(cpu_T[0], REG(B7_4), ctx->memidx);
686 tcg_gen_qemu_ld32s(cpu_T[1], REG(B11_8), ctx->memidx);
687 tcg_gen_helper_0_2(helper_macl, cpu_T[0], cpu_T[1]);
688 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
689 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
691 case 0x400f: /* mac.w @Rm+,@Rn+ */
692 tcg_gen_qemu_ld32s(cpu_T[0], REG(B7_4), ctx->memidx);
693 tcg_gen_qemu_ld32s(cpu_T[1], REG(B11_8), ctx->memidx);
694 tcg_gen_helper_0_2(helper_macw, cpu_T[0], cpu_T[1]);
695 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2);
696 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
698 case 0x0007: /* mul.l Rm,Rn */
699 tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8));
701 case 0x200f: /* muls.w Rm,Rn */
702 tcg_gen_ext16s_i32(cpu_T[0], REG(B7_4));
703 tcg_gen_ext16s_i32(cpu_T[1], REG(B11_8));
704 tcg_gen_mul_i32(cpu_macl, cpu_T[0], cpu_T[1]);
706 case 0x200e: /* mulu.w Rm,Rn */
707 tcg_gen_ext16u_i32(cpu_T[0], REG(B7_4));
708 tcg_gen_ext16u_i32(cpu_T[1], REG(B11_8));
709 tcg_gen_mul_i32(cpu_macl, cpu_T[0], cpu_T[1]);
711 case 0x600b: /* neg Rm,Rn */
712 tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
714 case 0x600a: /* negc Rm,Rn */
715 tcg_gen_helper_1_1(helper_negc, REG(B11_8), REG(B7_4));
717 case 0x6007: /* not Rm,Rn */
718 tcg_gen_not_i32(REG(B11_8), REG(B7_4));
720 case 0x200b: /* or Rm,Rn */
721 tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4));
723 case 0x400c: /* shad Rm,Rn */
725 int label1 = gen_new_label();
726 int label2 = gen_new_label();
727 int label3 = gen_new_label();
728 int label4 = gen_new_label();
729 tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
730 /* Rm positive, shift to the left */
731 tcg_gen_andi_i32(cpu_T[0], REG(B7_4), 0x1f);
732 tcg_gen_shl_i32(REG(B11_8), REG(B11_8), cpu_T[0]);
734 /* Rm negative, shift to the right */
735 gen_set_label(label1);
736 tcg_gen_andi_i32(cpu_T[0], REG(B7_4), 0x1f);
737 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_T[0], 0, label2);
738 tcg_gen_not_i32(cpu_T[0], REG(B7_4));
739 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], 0x1f);
740 tcg_gen_addi_i32(cpu_T[0], cpu_T[0], 1);
741 tcg_gen_sar_i32(REG(B11_8), REG(B11_8), cpu_T[0]);
744 gen_set_label(label2);
745 tcg_gen_brcondi_i32(TCG_COND_LT, REG(B11_8), 0, label3);
746 tcg_gen_movi_i32(REG(B11_8), 0);
748 gen_set_label(label3);
749 tcg_gen_movi_i32(REG(B11_8), 0xffffffff);
750 gen_set_label(label4);
753 case 0x400d: /* shld Rm,Rn */
755 int label1 = gen_new_label();
756 int label2 = gen_new_label();
757 int label3 = gen_new_label();
758 tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
759 /* Rm positive, shift to the left */
760 tcg_gen_andi_i32(cpu_T[0], REG(B7_4), 0x1f);
761 tcg_gen_shl_i32(REG(B11_8), REG(B11_8), cpu_T[0]);
763 /* Rm negative, shift to the right */
764 gen_set_label(label1);
765 tcg_gen_andi_i32(cpu_T[0], REG(B7_4), 0x1f);
766 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_T[0], 0, label2);
767 tcg_gen_not_i32(cpu_T[0], REG(B7_4));
768 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], 0x1f);
769 tcg_gen_addi_i32(cpu_T[0], cpu_T[0], 1);
770 tcg_gen_shr_i32(REG(B11_8), REG(B11_8), cpu_T[0]);
773 gen_set_label(label2);
774 tcg_gen_movi_i32(REG(B11_8), 0);
775 gen_set_label(label3);
778 case 0x3008: /* sub Rm,Rn */
779 tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4));
781 case 0x300a: /* subc Rm,Rn */
782 tcg_gen_helper_1_2(helper_subc, REG(B11_8), REG(B7_4), REG(B11_8));
784 case 0x300b: /* subv Rm,Rn */
785 tcg_gen_helper_1_2(helper_subv, REG(B11_8), REG(B7_4), REG(B11_8));
787 case 0x2008: /* tst Rm,Rn */
788 tcg_gen_and_i32(cpu_T[0], REG(B7_4), REG(B11_8));
789 gen_cmp_imm(TCG_COND_EQ, cpu_T[0], 0);
791 case 0x200a: /* xor Rm,Rn */
792 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4));
794 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
795 if (ctx->fpscr & FPSCR_SZ) {
796 gen_op_fmov_drN_DT0(XREG(B7_4));
797 gen_op_fmov_DT0_drN(XREG(B11_8));
799 gen_op_fmov_frN_FT0(FREG(B7_4));
800 gen_op_fmov_FT0_frN(FREG(B11_8));
803 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
804 if (ctx->fpscr & FPSCR_SZ) {
805 gen_op_fmov_drN_DT0(XREG(B7_4));
806 tcg_gen_mov_i32(cpu_T[1], REG(B11_8));
807 gen_op_stfq_DT0_T1(ctx);
809 gen_op_fmov_frN_FT0(FREG(B7_4));
810 tcg_gen_mov_i32(cpu_T[1], REG(B11_8));
811 gen_op_stfl_FT0_T1(ctx);
814 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
815 if (ctx->fpscr & FPSCR_SZ) {
816 tcg_gen_mov_i32(cpu_T[0], REG(B7_4));
817 gen_op_ldfq_T0_DT0(ctx);
818 gen_op_fmov_DT0_drN(XREG(B11_8));
820 tcg_gen_mov_i32(cpu_T[0], REG(B7_4));
821 gen_op_ldfl_T0_FT0(ctx);
822 gen_op_fmov_FT0_frN(FREG(B11_8));
825 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
826 if (ctx->fpscr & FPSCR_SZ) {
827 tcg_gen_mov_i32(cpu_T[0], REG(B7_4));
828 gen_op_ldfq_T0_DT0(ctx);
829 gen_op_fmov_DT0_drN(XREG(B11_8));
830 tcg_gen_addi_i32(REG(B7_4),
833 tcg_gen_mov_i32(cpu_T[0], REG(B7_4));
834 gen_op_ldfl_T0_FT0(ctx);
835 gen_op_fmov_FT0_frN(FREG(B11_8));
836 tcg_gen_addi_i32(REG(B7_4),
840 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
841 if (ctx->fpscr & FPSCR_SZ) {
842 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 8);
843 gen_op_fmov_drN_DT0(XREG(B7_4));
844 tcg_gen_mov_i32(cpu_T[1], REG(B11_8));
845 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 8);
846 gen_op_stfq_DT0_T1(ctx);
847 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 8);
849 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
850 gen_op_fmov_frN_FT0(FREG(B7_4));
851 tcg_gen_mov_i32(cpu_T[1], REG(B11_8));
852 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
853 gen_op_stfl_FT0_T1(ctx);
854 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
857 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
858 tcg_gen_add_i32(cpu_T[0], REG(B7_4), REG(0));
859 if (ctx->fpscr & FPSCR_SZ) {
860 gen_op_ldfq_T0_DT0(ctx);
861 gen_op_fmov_DT0_drN(XREG(B11_8));
863 gen_op_ldfl_T0_FT0(ctx);
864 gen_op_fmov_FT0_frN(FREG(B11_8));
867 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
868 if (ctx->fpscr & FPSCR_SZ) {
869 gen_op_fmov_drN_DT0(XREG(B7_4));
870 tcg_gen_mov_i32(cpu_T[1], REG(B11_8));
871 tcg_gen_add_i32(cpu_T[1], cpu_T[1], REG(0));
872 gen_op_stfq_DT0_T1(ctx);
874 gen_op_fmov_frN_FT0(FREG(B7_4));
875 tcg_gen_mov_i32(cpu_T[1], REG(B11_8));
876 tcg_gen_add_i32(cpu_T[1], cpu_T[1], REG(0));
877 gen_op_stfl_FT0_T1(ctx);
880 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
881 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
882 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
883 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
884 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
885 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
886 if (ctx->fpscr & FPSCR_PR) {
887 if (ctx->opcode & 0x0110)
888 break; /* illegal instruction */
889 gen_op_fmov_drN_DT1(DREG(B7_4));
890 gen_op_fmov_drN_DT0(DREG(B11_8));
893 gen_op_fmov_frN_FT1(FREG(B7_4));
894 gen_op_fmov_frN_FT0(FREG(B11_8));
897 switch (ctx->opcode & 0xf00f) {
898 case 0xf000: /* fadd Rm,Rn */
899 ctx->fpscr & FPSCR_PR ? gen_op_fadd_DT() : gen_op_fadd_FT();
901 case 0xf001: /* fsub Rm,Rn */
902 ctx->fpscr & FPSCR_PR ? gen_op_fsub_DT() : gen_op_fsub_FT();
904 case 0xf002: /* fmul Rm,Rn */
905 ctx->fpscr & FPSCR_PR ? gen_op_fmul_DT() : gen_op_fmul_FT();
907 case 0xf003: /* fdiv Rm,Rn */
908 ctx->fpscr & FPSCR_PR ? gen_op_fdiv_DT() : gen_op_fdiv_FT();
910 case 0xf004: /* fcmp/eq Rm,Rn */
911 ctx->fpscr & FPSCR_PR ? gen_op_fcmp_eq_DT() : gen_op_fcmp_eq_FT();
913 case 0xf005: /* fcmp/gt Rm,Rn */
914 ctx->fpscr & FPSCR_PR ? gen_op_fcmp_gt_DT() : gen_op_fcmp_gt_FT();
918 if (ctx->fpscr & FPSCR_PR) {
919 gen_op_fmov_DT0_drN(DREG(B11_8));
922 gen_op_fmov_FT0_frN(FREG(B11_8));
927 switch (ctx->opcode & 0xff00) {
928 case 0xc900: /* and #imm,R0 */
929 tcg_gen_andi_i32(REG(0), REG(0), B7_0);
931 case 0xcd00: /* and.b #imm,@(R0,GBR) */
932 tcg_gen_add_i32(cpu_T[1], REG(0), cpu_gbr);
933 tcg_gen_qemu_ld8u(cpu_T[0], cpu_T[1], ctx->memidx);
934 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], B7_0);
935 tcg_gen_qemu_st8(cpu_T[0], cpu_T[1], ctx->memidx);
937 case 0x8b00: /* bf label */
939 gen_conditional_jump(ctx, ctx->pc + 2,
940 ctx->pc + 4 + B7_0s * 2);
941 ctx->bstate = BS_BRANCH;
943 case 0x8f00: /* bf/s label */
945 gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 0);
946 ctx->flags |= DELAY_SLOT_CONDITIONAL;
948 case 0x8900: /* bt label */
950 gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2,
952 ctx->bstate = BS_BRANCH;
954 case 0x8d00: /* bt/s label */
956 gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 1);
957 ctx->flags |= DELAY_SLOT_CONDITIONAL;
959 case 0x8800: /* cmp/eq #imm,R0 */
960 gen_cmp_imm(TCG_COND_EQ, REG(0), B7_0s);
962 case 0xc400: /* mov.b @(disp,GBR),R0 */
963 tcg_gen_addi_i32(cpu_T[0], cpu_gbr, B7_0);
964 tcg_gen_qemu_ld8s(REG(0), cpu_T[0], ctx->memidx);
966 case 0xc500: /* mov.w @(disp,GBR),R0 */
967 tcg_gen_addi_i32(cpu_T[0], cpu_gbr, B7_0 * 2);
968 tcg_gen_qemu_ld16s(REG(0), cpu_T[0], ctx->memidx);
970 case 0xc600: /* mov.l @(disp,GBR),R0 */
971 tcg_gen_addi_i32(cpu_T[0], cpu_gbr, B7_0 * 4);
972 tcg_gen_qemu_ld32s(REG(0), cpu_T[0], ctx->memidx);
974 case 0xc000: /* mov.b R0,@(disp,GBR) */
975 tcg_gen_addi_i32(cpu_T[0], cpu_gbr, B7_0);
976 tcg_gen_qemu_st8(REG(0), cpu_T[0], ctx->memidx);
978 case 0xc100: /* mov.w R0,@(disp,GBR) */
979 tcg_gen_addi_i32(cpu_T[0], cpu_gbr, B7_0 * 2);
980 tcg_gen_qemu_st16(REG(0), cpu_T[0], ctx->memidx);
982 case 0xc200: /* mov.l R0,@(disp,GBR) */
983 tcg_gen_addi_i32(cpu_T[0], cpu_gbr, B7_0 * 4);
984 tcg_gen_qemu_st32(REG(0), cpu_T[0], ctx->memidx);
986 case 0x8000: /* mov.b R0,@(disp,Rn) */
987 tcg_gen_addi_i32(cpu_T[0], REG(B7_4), B3_0);
988 tcg_gen_qemu_st8(REG(0), cpu_T[0], ctx->memidx);
990 case 0x8100: /* mov.w R0,@(disp,Rn) */
991 tcg_gen_addi_i32(cpu_T[0], REG(B7_4), B3_0 * 2);
992 tcg_gen_qemu_st16(REG(0), cpu_T[0], ctx->memidx);
994 case 0x8400: /* mov.b @(disp,Rn),R0 */
995 tcg_gen_addi_i32(cpu_T[0], REG(B7_4), B3_0);
996 tcg_gen_qemu_ld8s(REG(0), cpu_T[0], ctx->memidx);
998 case 0x8500: /* mov.w @(disp,Rn),R0 */
999 tcg_gen_addi_i32(cpu_T[0], REG(B7_4), B3_0 * 2);
1000 tcg_gen_qemu_ld16s(REG(0), cpu_T[0], ctx->memidx);
1002 case 0xc700: /* mova @(disp,PC),R0 */
1003 tcg_gen_movi_i32(REG(0), ((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3);
1005 case 0xcb00: /* or #imm,R0 */
1006 tcg_gen_ori_i32(REG(0), REG(0), B7_0);
1008 case 0xcf00: /* or.b #imm,@(R0,GBR) */
1009 tcg_gen_add_i32(cpu_T[1], REG(0), cpu_gbr);
1010 tcg_gen_qemu_ld8u(cpu_T[0], cpu_T[1], ctx->memidx);
1011 tcg_gen_ori_i32(cpu_T[0], cpu_T[0], B7_0);
1012 tcg_gen_qemu_st8(cpu_T[0], cpu_T[1], ctx->memidx);
1014 case 0xc300: /* trapa #imm */
1015 CHECK_NOT_DELAY_SLOT
1016 tcg_gen_movi_i32(cpu_pc, ctx->pc);
1017 tcg_gen_movi_i32(cpu_T[0], B7_0);
1018 tcg_gen_helper_0_1(helper_trapa, cpu_T[0]);
1019 ctx->bstate = BS_BRANCH;
1021 case 0xc800: /* tst #imm,R0 */
1022 tcg_gen_andi_i32(cpu_T[0], REG(0), B7_0);
1023 gen_cmp_imm(TCG_COND_EQ, cpu_T[0], 0);
1025 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
1026 tcg_gen_add_i32(cpu_T[0], REG(0), cpu_gbr);
1027 tcg_gen_qemu_ld8u(cpu_T[0], cpu_T[0], ctx->memidx);
1028 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], B7_0);
1029 gen_cmp_imm(TCG_COND_EQ, cpu_T[0], 0);
1031 case 0xca00: /* xor #imm,R0 */
1032 tcg_gen_xori_i32(REG(0), REG(0), B7_0);
1034 case 0xce00: /* xor.b #imm,@(R0,GBR) */
1035 tcg_gen_add_i32(cpu_T[1], REG(0), cpu_gbr);
1036 tcg_gen_qemu_ld8u(cpu_T[0], cpu_T[1], ctx->memidx);
1037 tcg_gen_xori_i32(cpu_T[0], cpu_T[0], B7_0);
1038 tcg_gen_qemu_st8(cpu_T[0], cpu_T[1], ctx->memidx);
1042 switch (ctx->opcode & 0xf08f) {
1043 case 0x408e: /* ldc Rm,Rn_BANK */
1044 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8));
1046 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
1047 tcg_gen_qemu_ld32s(ALTREG(B6_4), REG(B11_8), ctx->memidx);
1048 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1050 case 0x0082: /* stc Rm_BANK,Rn */
1051 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4));
1053 case 0x4083: /* stc.l Rm_BANK,@-Rn */
1054 tcg_gen_subi_i32(cpu_T[0], REG(B11_8), 4);
1055 tcg_gen_qemu_st32(ALTREG(B6_4), cpu_T[0], ctx->memidx);
1056 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
1060 switch (ctx->opcode & 0xf0ff) {
1061 case 0x0023: /* braf Rn */
1062 CHECK_NOT_DELAY_SLOT
1063 tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->pc + 4);
1064 ctx->flags |= DELAY_SLOT;
1065 ctx->delayed_pc = (uint32_t) - 1;
1067 case 0x0003: /* bsrf Rn */
1068 CHECK_NOT_DELAY_SLOT
1069 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
1070 tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
1071 ctx->flags |= DELAY_SLOT;
1072 ctx->delayed_pc = (uint32_t) - 1;
1074 case 0x4015: /* cmp/pl Rn */
1075 gen_cmp_imm(TCG_COND_GT, REG(B11_8), 0);
1077 case 0x4011: /* cmp/pz Rn */
1078 gen_cmp_imm(TCG_COND_GE, REG(B11_8), 0);
1080 case 0x4010: /* dt Rn */
1081 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1);
1082 gen_cmp_imm(TCG_COND_EQ, REG(B11_8), 0);
1084 case 0x402b: /* jmp @Rn */
1085 CHECK_NOT_DELAY_SLOT
1086 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1087 ctx->flags |= DELAY_SLOT;
1088 ctx->delayed_pc = (uint32_t) - 1;
1090 case 0x400b: /* jsr @Rn */
1091 CHECK_NOT_DELAY_SLOT
1092 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
1093 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1094 ctx->flags |= DELAY_SLOT;
1095 ctx->delayed_pc = (uint32_t) - 1;
1097 case 0x400e: /* lds Rm,SR */
1098 tcg_gen_andi_i32(cpu_sr, REG(B11_8), 0x700083f3);
1099 ctx->bstate = BS_STOP;
1101 case 0x4007: /* lds.l @Rm+,SR */
1102 tcg_gen_qemu_ld32s(cpu_T[0], REG(B11_8), ctx->memidx);
1103 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1104 tcg_gen_andi_i32(cpu_sr, cpu_T[0], 0x700083f3);
1105 ctx->bstate = BS_STOP;
1107 case 0x0002: /* sts SR,Rn */
1108 tcg_gen_mov_i32(REG(B11_8), cpu_sr);
1110 case 0x4003: /* sts SR,@-Rn */
1111 tcg_gen_subi_i32(cpu_T[0], REG(B11_8), 4);
1112 tcg_gen_qemu_st32(cpu_sr, cpu_T[0], ctx->memidx);
1113 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
1115 #define LDST(reg,ldnum,ldpnum,stnum,stpnum) \
1117 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \
1120 tcg_gen_qemu_ld32s (cpu_##reg, REG(B11_8), ctx->memidx); \
1121 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \
1124 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \
1127 tcg_gen_subi_i32(cpu_T[0], REG(B11_8), 4); \
1128 tcg_gen_qemu_st32 (cpu_##reg, cpu_T[0], ctx->memidx); \
1129 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4); \
1131 LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013)
1132 LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023)
1133 LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033)
1134 LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043)
1135 LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2)
1136 LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002)
1137 LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012)
1138 LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022)
1139 LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052)
1140 case 0x406a: /* lds Rm,FPSCR */
1141 tcg_gen_helper_0_1(helper_ld_fpscr, REG(B11_8));
1142 ctx->bstate = BS_STOP;
1144 case 0x4066: /* lds.l @Rm+,FPSCR */
1145 tcg_gen_qemu_ld32s(cpu_T[0], REG(B11_8), ctx->memidx);
1146 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1147 tcg_gen_helper_0_1(helper_ld_fpscr, cpu_T[0]);
1148 ctx->bstate = BS_STOP;
1150 case 0x006a: /* sts FPSCR,Rn */
1151 tcg_gen_andi_i32(cpu_T[0], cpu_fpscr, 0x003fffff);
1152 tcg_gen_mov_i32(REG(B11_8), cpu_T[0]);
1154 case 0x4062: /* sts FPSCR,@-Rn */
1155 tcg_gen_andi_i32(cpu_T[0], cpu_fpscr, 0x003fffff);
1156 tcg_gen_subi_i32(cpu_T[1], REG(B11_8), 4);
1157 tcg_gen_qemu_st32(cpu_T[0], cpu_T[1], ctx->memidx);
1158 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
1160 case 0x00c3: /* movca.l R0,@Rm */
1161 tcg_gen_qemu_st32(REG(0), REG(B11_8), ctx->memidx);
1163 case 0x0029: /* movt Rn */
1164 tcg_gen_andi_i32(REG(B11_8), cpu_sr, SR_T);
1166 case 0x0093: /* ocbi @Rn */
1167 tcg_gen_qemu_ld32s(cpu_T[0], REG(B11_8), ctx->memidx);
1169 case 0x00a3: /* ocbp @Rn */
1170 tcg_gen_qemu_ld32s(cpu_T[0], REG(B11_8), ctx->memidx);
1172 case 0x00b3: /* ocbwb @Rn */
1173 tcg_gen_qemu_ld32s(cpu_T[0], REG(B11_8), ctx->memidx);
1175 case 0x0083: /* pref @Rn */
1177 case 0x4024: /* rotcl Rn */
1178 tcg_gen_mov_i32(cpu_T[0], cpu_sr);
1179 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 31);
1180 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1181 gen_copy_bit_i32(REG(B11_8), 0, cpu_T[0], 0);
1183 case 0x4025: /* rotcr Rn */
1184 tcg_gen_mov_i32(cpu_T[0], cpu_sr);
1185 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
1186 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1187 gen_copy_bit_i32(REG(B11_8), 31, cpu_T[0], 0);
1189 case 0x4004: /* rotl Rn */
1190 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 31);
1191 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1192 gen_copy_bit_i32(REG(B11_8), 0, cpu_sr, 0);
1194 case 0x4005: /* rotr Rn */
1195 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
1196 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1197 gen_copy_bit_i32(REG(B11_8), 31, cpu_sr, 0);
1199 case 0x4000: /* shll Rn */
1200 case 0x4020: /* shal Rn */
1201 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 31);
1202 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1204 case 0x4021: /* shar Rn */
1205 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
1206 tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1);
1208 case 0x4001: /* shlr Rn */
1209 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
1210 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1212 case 0x4008: /* shll2 Rn */
1213 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2);
1215 case 0x4018: /* shll8 Rn */
1216 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8);
1218 case 0x4028: /* shll16 Rn */
1219 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16);
1221 case 0x4009: /* shlr2 Rn */
1222 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2);
1224 case 0x4019: /* shlr8 Rn */
1225 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8);
1227 case 0x4029: /* shlr16 Rn */
1228 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16);
1230 case 0x401b: /* tas.b @Rn */
1231 tcg_gen_mov_i32(cpu_T[1], REG(B11_8));
1232 tcg_gen_qemu_ld8u(cpu_T[0], cpu_T[1], ctx->memidx);
1233 gen_cmp_imm(TCG_COND_EQ, cpu_T[0], 0);
1234 tcg_gen_ori_i32(cpu_T[0], cpu_T[0], 0x80);
1235 tcg_gen_qemu_st8(cpu_T[0], cpu_T[1], ctx->memidx);
1237 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1238 gen_op_movl_fpul_FT0();
1239 gen_op_fmov_FT0_frN(FREG(B11_8));
1241 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1242 gen_op_fmov_frN_FT0(FREG(B11_8));
1243 gen_op_movl_FT0_fpul();
1245 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
1246 if (ctx->fpscr & FPSCR_PR) {
1247 if (ctx->opcode & 0x0100)
1248 break; /* illegal instruction */
1250 gen_op_fmov_DT0_drN(DREG(B11_8));
1254 gen_op_fmov_FT0_frN(FREG(B11_8));
1257 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1258 if (ctx->fpscr & FPSCR_PR) {
1259 if (ctx->opcode & 0x0100)
1260 break; /* illegal instruction */
1261 gen_op_fmov_drN_DT0(DREG(B11_8));
1265 gen_op_fmov_frN_FT0(FREG(B11_8));
1269 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
1270 gen_op_fneg_frN(FREG(B11_8));
1272 case 0xf05d: /* fabs FRn/DRn */
1273 if (ctx->fpscr & FPSCR_PR) {
1274 if (ctx->opcode & 0x0100)
1275 break; /* illegal instruction */
1276 gen_op_fmov_drN_DT0(DREG(B11_8));
1278 gen_op_fmov_DT0_drN(DREG(B11_8));
1280 gen_op_fmov_frN_FT0(FREG(B11_8));
1282 gen_op_fmov_FT0_frN(FREG(B11_8));
1285 case 0xf06d: /* fsqrt FRn */
1286 if (ctx->fpscr & FPSCR_PR) {
1287 if (ctx->opcode & 0x0100)
1288 break; /* illegal instruction */
1289 gen_op_fmov_drN_DT0(FREG(B11_8));
1291 gen_op_fmov_DT0_drN(FREG(B11_8));
1293 gen_op_fmov_frN_FT0(FREG(B11_8));
1295 gen_op_fmov_FT0_frN(FREG(B11_8));
1298 case 0xf07d: /* fsrra FRn */
1300 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
1301 if (!(ctx->fpscr & FPSCR_PR)) {
1302 tcg_gen_movi_i32(cpu_T[0], 0);
1303 gen_op_fmov_T0_frN(FREG(B11_8));
1307 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
1308 if (!(ctx->fpscr & FPSCR_PR)) {
1309 tcg_gen_movi_i32(cpu_T[0], 0x3f800000);
1310 gen_op_fmov_T0_frN(FREG(B11_8));
1314 case 0xf0ad: /* fcnvsd FPUL,DRn */
1315 gen_op_movl_fpul_FT0();
1316 gen_op_fcnvsd_FT_DT();
1317 gen_op_fmov_DT0_drN(DREG(B11_8));
1319 case 0xf0bd: /* fcnvds DRn,FPUL */
1320 gen_op_fmov_drN_DT0(DREG(B11_8));
1321 gen_op_fcnvds_DT_FT();
1322 gen_op_movl_FT0_fpul();
1326 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1327 ctx->opcode, ctx->pc);
1328 tcg_gen_helper_0_0(helper_raise_illegal_instruction);
1329 ctx->bstate = BS_EXCP;
1332 void decode_opc(DisasContext * ctx)
1334 uint32_t old_flags = ctx->flags;
1338 if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
1339 if (ctx->flags & DELAY_SLOT_CLEARME) {
1342 /* go out of the delay slot */
1343 uint32_t new_flags = ctx->flags;
1344 new_flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
1345 gen_store_flags(new_flags);
1348 ctx->bstate = BS_BRANCH;
1349 if (old_flags & DELAY_SLOT_CONDITIONAL) {
1350 gen_delayed_conditional_jump(ctx);
1351 } else if (old_flags & DELAY_SLOT) {
1357 /* go into a delay slot */
1358 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL))
1359 gen_store_flags(ctx->flags);
1363 gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
1367 target_ulong pc_start;
1368 static uint16_t *gen_opc_end;
1374 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1376 ctx.flags = (uint32_t)tb->flags;
1377 ctx.bstate = BS_NONE;
1379 ctx.fpscr = env->fpscr;
1380 ctx.memidx = (env->sr & SR_MD) ? 1 : 0;
1381 /* We don't know if the delayed pc came from a dynamic or static branch,
1382 so assume it is a dynamic branch. */
1383 ctx.delayed_pc = -1; /* use delayed pc from env pointer */
1385 ctx.singlestep_enabled = env->singlestep_enabled;
1388 if (loglevel & CPU_LOG_TB_CPU) {
1390 "------------------------------------------------\n");
1391 cpu_dump_state(env, logfile, fprintf, 0);
1397 max_insns = tb->cflags & CF_COUNT_MASK;
1399 max_insns = CF_COUNT_MASK;
1401 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1402 if (env->nb_breakpoints > 0) {
1403 for (i = 0; i < env->nb_breakpoints; i++) {
1404 if (ctx.pc == env->breakpoints[i]) {
1405 /* We have hit a breakpoint - make sure PC is up-to-date */
1406 tcg_gen_movi_i32(cpu_pc, ctx.pc);
1407 tcg_gen_helper_0_0(helper_debug);
1408 ctx.bstate = BS_EXCP;
1414 i = gen_opc_ptr - gen_opc_buf;
1418 gen_opc_instr_start[ii++] = 0;
1420 gen_opc_pc[ii] = ctx.pc;
1421 gen_opc_hflags[ii] = ctx.flags;
1422 gen_opc_instr_start[ii] = 1;
1423 gen_opc_icount[ii] = num_insns;
1425 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
1428 fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
1431 ctx.opcode = lduw_code(ctx.pc);
1435 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1437 if (env->singlestep_enabled)
1439 if (num_insns >= max_insns)
1441 #ifdef SH4_SINGLE_STEP
1445 if (tb->cflags & CF_LAST_IO)
1447 if (env->singlestep_enabled) {
1448 tcg_gen_helper_0_0(helper_debug);
1450 switch (ctx.bstate) {
1452 /* gen_op_interrupt_restart(); */
1456 gen_store_flags(ctx.flags | DELAY_SLOT_CLEARME);
1458 gen_goto_tb(&ctx, 0, ctx.pc);
1461 /* gen_op_interrupt_restart(); */
1470 gen_icount_end(tb, num_insns);
1471 *gen_opc_ptr = INDEX_op_end;
1473 i = gen_opc_ptr - gen_opc_buf;
1476 gen_opc_instr_start[ii++] = 0;
1478 tb->size = ctx.pc - pc_start;
1479 tb->icount = num_insns;
1483 #ifdef SH4_DEBUG_DISAS
1484 if (loglevel & CPU_LOG_TB_IN_ASM)
1485 fprintf(logfile, "\n");
1487 if (loglevel & CPU_LOG_TB_IN_ASM) {
1488 fprintf(logfile, "IN:\n"); /* , lookup_symbol(pc_start)); */
1489 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1490 fprintf(logfile, "\n");
1495 void gen_intermediate_code(CPUState * env, struct TranslationBlock *tb)
1497 gen_intermediate_code_internal(env, tb, 0);
1500 void gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
1502 gen_intermediate_code_internal(env, tb, 1);
1505 void gen_pc_load(CPUState *env, TranslationBlock *tb,
1506 unsigned long searched_pc, int pc_pos, void *puc)
1508 env->pc = gen_opc_pc[pc_pos];
1509 env->flags = gen_opc_hflags[pc_pos];