hw/timer/sse-timer: Model the SSE Subsystem System Timer
[qemu/ar7.git] / target / sh4 / translate.c
blob9312790623730b76b147ddfd765b5cf603379155
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.1 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, see <http://www.gnu.org/licenses/>.
20 #define DEBUG_DISAS
22 #include "qemu/osdep.h"
23 #include "cpu.h"
24 #include "disas/disas.h"
25 #include "exec/exec-all.h"
26 #include "tcg/tcg-op.h"
27 #include "exec/cpu_ldst.h"
28 #include "exec/helper-proto.h"
29 #include "exec/helper-gen.h"
30 #include "exec/translator.h"
31 #include "trace-tcg.h"
32 #include "exec/log.h"
33 #include "qemu/qemu-print.h"
36 typedef struct DisasContext {
37 DisasContextBase base;
39 uint32_t tbflags; /* should stay unmodified during the TB translation */
40 uint32_t envflags; /* should stay in sync with env->flags using TCG ops */
41 int memidx;
42 int gbank;
43 int fbank;
44 uint32_t delayed_pc;
45 uint32_t features;
47 uint16_t opcode;
49 bool has_movcal;
50 } DisasContext;
52 #if defined(CONFIG_USER_ONLY)
53 #define IS_USER(ctx) 1
54 #else
55 #define IS_USER(ctx) (!(ctx->tbflags & (1u << SR_MD)))
56 #endif
58 /* Target-specific values for ctx->base.is_jmp. */
59 /* We want to exit back to the cpu loop for some reason.
60 Usually this is to recognize interrupts immediately. */
61 #define DISAS_STOP DISAS_TARGET_0
63 /* global register indexes */
64 static TCGv cpu_gregs[32];
65 static TCGv cpu_sr, cpu_sr_m, cpu_sr_q, cpu_sr_t;
66 static TCGv cpu_pc, cpu_ssr, cpu_spc, cpu_gbr;
67 static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl;
68 static TCGv cpu_pr, cpu_fpscr, cpu_fpul;
69 static TCGv cpu_lock_addr, cpu_lock_value;
70 static TCGv cpu_fregs[32];
72 /* internal register indexes */
73 static TCGv cpu_flags, cpu_delayed_pc, cpu_delayed_cond;
75 #include "exec/gen-icount.h"
77 void sh4_translate_init(void)
79 int i;
80 static const char * const gregnames[24] = {
81 "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
82 "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
83 "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
84 "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
85 "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
87 static const char * const fregnames[32] = {
88 "FPR0_BANK0", "FPR1_BANK0", "FPR2_BANK0", "FPR3_BANK0",
89 "FPR4_BANK0", "FPR5_BANK0", "FPR6_BANK0", "FPR7_BANK0",
90 "FPR8_BANK0", "FPR9_BANK0", "FPR10_BANK0", "FPR11_BANK0",
91 "FPR12_BANK0", "FPR13_BANK0", "FPR14_BANK0", "FPR15_BANK0",
92 "FPR0_BANK1", "FPR1_BANK1", "FPR2_BANK1", "FPR3_BANK1",
93 "FPR4_BANK1", "FPR5_BANK1", "FPR6_BANK1", "FPR7_BANK1",
94 "FPR8_BANK1", "FPR9_BANK1", "FPR10_BANK1", "FPR11_BANK1",
95 "FPR12_BANK1", "FPR13_BANK1", "FPR14_BANK1", "FPR15_BANK1",
98 for (i = 0; i < 24; i++) {
99 cpu_gregs[i] = tcg_global_mem_new_i32(cpu_env,
100 offsetof(CPUSH4State, gregs[i]),
101 gregnames[i]);
103 memcpy(cpu_gregs + 24, cpu_gregs + 8, 8 * sizeof(TCGv));
105 cpu_pc = tcg_global_mem_new_i32(cpu_env,
106 offsetof(CPUSH4State, pc), "PC");
107 cpu_sr = tcg_global_mem_new_i32(cpu_env,
108 offsetof(CPUSH4State, sr), "SR");
109 cpu_sr_m = tcg_global_mem_new_i32(cpu_env,
110 offsetof(CPUSH4State, sr_m), "SR_M");
111 cpu_sr_q = tcg_global_mem_new_i32(cpu_env,
112 offsetof(CPUSH4State, sr_q), "SR_Q");
113 cpu_sr_t = tcg_global_mem_new_i32(cpu_env,
114 offsetof(CPUSH4State, sr_t), "SR_T");
115 cpu_ssr = tcg_global_mem_new_i32(cpu_env,
116 offsetof(CPUSH4State, ssr), "SSR");
117 cpu_spc = tcg_global_mem_new_i32(cpu_env,
118 offsetof(CPUSH4State, spc), "SPC");
119 cpu_gbr = tcg_global_mem_new_i32(cpu_env,
120 offsetof(CPUSH4State, gbr), "GBR");
121 cpu_vbr = tcg_global_mem_new_i32(cpu_env,
122 offsetof(CPUSH4State, vbr), "VBR");
123 cpu_sgr = tcg_global_mem_new_i32(cpu_env,
124 offsetof(CPUSH4State, sgr), "SGR");
125 cpu_dbr = tcg_global_mem_new_i32(cpu_env,
126 offsetof(CPUSH4State, dbr), "DBR");
127 cpu_mach = tcg_global_mem_new_i32(cpu_env,
128 offsetof(CPUSH4State, mach), "MACH");
129 cpu_macl = tcg_global_mem_new_i32(cpu_env,
130 offsetof(CPUSH4State, macl), "MACL");
131 cpu_pr = tcg_global_mem_new_i32(cpu_env,
132 offsetof(CPUSH4State, pr), "PR");
133 cpu_fpscr = tcg_global_mem_new_i32(cpu_env,
134 offsetof(CPUSH4State, fpscr), "FPSCR");
135 cpu_fpul = tcg_global_mem_new_i32(cpu_env,
136 offsetof(CPUSH4State, fpul), "FPUL");
138 cpu_flags = tcg_global_mem_new_i32(cpu_env,
139 offsetof(CPUSH4State, flags), "_flags_");
140 cpu_delayed_pc = tcg_global_mem_new_i32(cpu_env,
141 offsetof(CPUSH4State, delayed_pc),
142 "_delayed_pc_");
143 cpu_delayed_cond = tcg_global_mem_new_i32(cpu_env,
144 offsetof(CPUSH4State,
145 delayed_cond),
146 "_delayed_cond_");
147 cpu_lock_addr = tcg_global_mem_new_i32(cpu_env,
148 offsetof(CPUSH4State, lock_addr),
149 "_lock_addr_");
150 cpu_lock_value = tcg_global_mem_new_i32(cpu_env,
151 offsetof(CPUSH4State, lock_value),
152 "_lock_value_");
154 for (i = 0; i < 32; i++)
155 cpu_fregs[i] = tcg_global_mem_new_i32(cpu_env,
156 offsetof(CPUSH4State, fregs[i]),
157 fregnames[i]);
160 void superh_cpu_dump_state(CPUState *cs, FILE *f, int flags)
162 SuperHCPU *cpu = SUPERH_CPU(cs);
163 CPUSH4State *env = &cpu->env;
164 int i;
166 qemu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
167 env->pc, cpu_read_sr(env), env->pr, env->fpscr);
168 qemu_fprintf(f, "spc=0x%08x ssr=0x%08x gbr=0x%08x vbr=0x%08x\n",
169 env->spc, env->ssr, env->gbr, env->vbr);
170 qemu_fprintf(f, "sgr=0x%08x dbr=0x%08x delayed_pc=0x%08x fpul=0x%08x\n",
171 env->sgr, env->dbr, env->delayed_pc, env->fpul);
172 for (i = 0; i < 24; i += 4) {
173 qemu_printf("r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
174 i, env->gregs[i], i + 1, env->gregs[i + 1],
175 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
177 if (env->flags & DELAY_SLOT) {
178 qemu_printf("in delay slot (delayed_pc=0x%08x)\n",
179 env->delayed_pc);
180 } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
181 qemu_printf("in conditional delay slot (delayed_pc=0x%08x)\n",
182 env->delayed_pc);
183 } else if (env->flags & DELAY_SLOT_RTE) {
184 qemu_fprintf(f, "in rte delay slot (delayed_pc=0x%08x)\n",
185 env->delayed_pc);
189 static void gen_read_sr(TCGv dst)
191 TCGv t0 = tcg_temp_new();
192 tcg_gen_shli_i32(t0, cpu_sr_q, SR_Q);
193 tcg_gen_or_i32(dst, dst, t0);
194 tcg_gen_shli_i32(t0, cpu_sr_m, SR_M);
195 tcg_gen_or_i32(dst, dst, t0);
196 tcg_gen_shli_i32(t0, cpu_sr_t, SR_T);
197 tcg_gen_or_i32(dst, cpu_sr, t0);
198 tcg_temp_free_i32(t0);
201 static void gen_write_sr(TCGv src)
203 tcg_gen_andi_i32(cpu_sr, src,
204 ~((1u << SR_Q) | (1u << SR_M) | (1u << SR_T)));
205 tcg_gen_extract_i32(cpu_sr_q, src, SR_Q, 1);
206 tcg_gen_extract_i32(cpu_sr_m, src, SR_M, 1);
207 tcg_gen_extract_i32(cpu_sr_t, src, SR_T, 1);
210 static inline void gen_save_cpu_state(DisasContext *ctx, bool save_pc)
212 if (save_pc) {
213 tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
215 if (ctx->delayed_pc != (uint32_t) -1) {
216 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
218 if ((ctx->tbflags & TB_FLAG_ENVFLAGS_MASK) != ctx->envflags) {
219 tcg_gen_movi_i32(cpu_flags, ctx->envflags);
223 static inline bool use_exit_tb(DisasContext *ctx)
225 return (ctx->tbflags & GUSA_EXCLUSIVE) != 0;
228 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
230 /* Use a direct jump if in same page and singlestep not enabled */
231 if (unlikely(ctx->base.singlestep_enabled || use_exit_tb(ctx))) {
232 return false;
234 #ifndef CONFIG_USER_ONLY
235 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
236 #else
237 return true;
238 #endif
241 static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
243 if (use_goto_tb(ctx, dest)) {
244 tcg_gen_goto_tb(n);
245 tcg_gen_movi_i32(cpu_pc, dest);
246 tcg_gen_exit_tb(ctx->base.tb, n);
247 } else {
248 tcg_gen_movi_i32(cpu_pc, dest);
249 if (ctx->base.singlestep_enabled) {
250 gen_helper_debug(cpu_env);
251 } else if (use_exit_tb(ctx)) {
252 tcg_gen_exit_tb(NULL, 0);
253 } else {
254 tcg_gen_lookup_and_goto_ptr();
257 ctx->base.is_jmp = DISAS_NORETURN;
260 static void gen_jump(DisasContext * ctx)
262 if (ctx->delayed_pc == -1) {
263 /* Target is not statically known, it comes necessarily from a
264 delayed jump as immediate jump are conditinal jumps */
265 tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc);
266 tcg_gen_discard_i32(cpu_delayed_pc);
267 if (ctx->base.singlestep_enabled) {
268 gen_helper_debug(cpu_env);
269 } else if (use_exit_tb(ctx)) {
270 tcg_gen_exit_tb(NULL, 0);
271 } else {
272 tcg_gen_lookup_and_goto_ptr();
274 ctx->base.is_jmp = DISAS_NORETURN;
275 } else {
276 gen_goto_tb(ctx, 0, ctx->delayed_pc);
280 /* Immediate conditional jump (bt or bf) */
281 static void gen_conditional_jump(DisasContext *ctx, target_ulong dest,
282 bool jump_if_true)
284 TCGLabel *l1 = gen_new_label();
285 TCGCond cond_not_taken = jump_if_true ? TCG_COND_EQ : TCG_COND_NE;
287 if (ctx->tbflags & GUSA_EXCLUSIVE) {
288 /* When in an exclusive region, we must continue to the end.
289 Therefore, exit the region on a taken branch, but otherwise
290 fall through to the next instruction. */
291 tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
292 tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK);
293 /* Note that this won't actually use a goto_tb opcode because we
294 disallow it in use_goto_tb, but it handles exit + singlestep. */
295 gen_goto_tb(ctx, 0, dest);
296 gen_set_label(l1);
297 ctx->base.is_jmp = DISAS_NEXT;
298 return;
301 gen_save_cpu_state(ctx, false);
302 tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
303 gen_goto_tb(ctx, 0, dest);
304 gen_set_label(l1);
305 gen_goto_tb(ctx, 1, ctx->base.pc_next + 2);
306 ctx->base.is_jmp = DISAS_NORETURN;
309 /* Delayed conditional jump (bt or bf) */
310 static void gen_delayed_conditional_jump(DisasContext * ctx)
312 TCGLabel *l1 = gen_new_label();
313 TCGv ds = tcg_temp_new();
315 tcg_gen_mov_i32(ds, cpu_delayed_cond);
316 tcg_gen_discard_i32(cpu_delayed_cond);
318 if (ctx->tbflags & GUSA_EXCLUSIVE) {
319 /* When in an exclusive region, we must continue to the end.
320 Therefore, exit the region on a taken branch, but otherwise
321 fall through to the next instruction. */
322 tcg_gen_brcondi_i32(TCG_COND_EQ, ds, 0, l1);
324 /* Leave the gUSA region. */
325 tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK);
326 gen_jump(ctx);
328 gen_set_label(l1);
329 ctx->base.is_jmp = DISAS_NEXT;
330 return;
333 tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
334 gen_goto_tb(ctx, 1, ctx->base.pc_next + 2);
335 gen_set_label(l1);
336 gen_jump(ctx);
339 static inline void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
341 /* We have already signaled illegal instruction for odd Dr. */
342 tcg_debug_assert((reg & 1) == 0);
343 reg ^= ctx->fbank;
344 tcg_gen_concat_i32_i64(t, cpu_fregs[reg + 1], cpu_fregs[reg]);
347 static inline void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
349 /* We have already signaled illegal instruction for odd Dr. */
350 tcg_debug_assert((reg & 1) == 0);
351 reg ^= ctx->fbank;
352 tcg_gen_extr_i64_i32(cpu_fregs[reg + 1], cpu_fregs[reg], t);
355 #define B3_0 (ctx->opcode & 0xf)
356 #define B6_4 ((ctx->opcode >> 4) & 0x7)
357 #define B7_4 ((ctx->opcode >> 4) & 0xf)
358 #define B7_0 (ctx->opcode & 0xff)
359 #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
360 #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
361 (ctx->opcode & 0xfff))
362 #define B11_8 ((ctx->opcode >> 8) & 0xf)
363 #define B15_12 ((ctx->opcode >> 12) & 0xf)
365 #define REG(x) cpu_gregs[(x) ^ ctx->gbank]
366 #define ALTREG(x) cpu_gregs[(x) ^ ctx->gbank ^ 0x10]
367 #define FREG(x) cpu_fregs[(x) ^ ctx->fbank]
369 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
371 #define CHECK_NOT_DELAY_SLOT \
372 if (ctx->envflags & DELAY_SLOT_MASK) { \
373 goto do_illegal_slot; \
376 #define CHECK_PRIVILEGED \
377 if (IS_USER(ctx)) { \
378 goto do_illegal; \
381 #define CHECK_FPU_ENABLED \
382 if (ctx->tbflags & (1u << SR_FD)) { \
383 goto do_fpu_disabled; \
386 #define CHECK_FPSCR_PR_0 \
387 if (ctx->tbflags & FPSCR_PR) { \
388 goto do_illegal; \
391 #define CHECK_FPSCR_PR_1 \
392 if (!(ctx->tbflags & FPSCR_PR)) { \
393 goto do_illegal; \
396 #define CHECK_SH4A \
397 if (!(ctx->features & SH_FEATURE_SH4A)) { \
398 goto do_illegal; \
401 static void _decode_opc(DisasContext * ctx)
403 /* This code tries to make movcal emulation sufficiently
404 accurate for Linux purposes. This instruction writes
405 memory, and prior to that, always allocates a cache line.
406 It is used in two contexts:
407 - in memcpy, where data is copied in blocks, the first write
408 of to a block uses movca.l for performance.
409 - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used
410 to flush the cache. Here, the data written by movcal.l is never
411 written to memory, and the data written is just bogus.
413 To simulate this, we simulate movcal.l, we store the value to memory,
414 but we also remember the previous content. If we see ocbi, we check
415 if movcal.l for that address was done previously. If so, the write should
416 not have hit the memory, so we restore the previous content.
417 When we see an instruction that is neither movca.l
418 nor ocbi, the previous content is discarded.
420 To optimize, we only try to flush stores when we're at the start of
421 TB, or if we already saw movca.l in this TB and did not flush stores
422 yet. */
423 if (ctx->has_movcal)
425 int opcode = ctx->opcode & 0xf0ff;
426 if (opcode != 0x0093 /* ocbi */
427 && opcode != 0x00c3 /* movca.l */)
429 gen_helper_discard_movcal_backup(cpu_env);
430 ctx->has_movcal = 0;
434 #if 0
435 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
436 #endif
438 switch (ctx->opcode) {
439 case 0x0019: /* div0u */
440 tcg_gen_movi_i32(cpu_sr_m, 0);
441 tcg_gen_movi_i32(cpu_sr_q, 0);
442 tcg_gen_movi_i32(cpu_sr_t, 0);
443 return;
444 case 0x000b: /* rts */
445 CHECK_NOT_DELAY_SLOT
446 tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
447 ctx->envflags |= DELAY_SLOT;
448 ctx->delayed_pc = (uint32_t) - 1;
449 return;
450 case 0x0028: /* clrmac */
451 tcg_gen_movi_i32(cpu_mach, 0);
452 tcg_gen_movi_i32(cpu_macl, 0);
453 return;
454 case 0x0048: /* clrs */
455 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(1u << SR_S));
456 return;
457 case 0x0008: /* clrt */
458 tcg_gen_movi_i32(cpu_sr_t, 0);
459 return;
460 case 0x0038: /* ldtlb */
461 CHECK_PRIVILEGED
462 gen_helper_ldtlb(cpu_env);
463 return;
464 case 0x002b: /* rte */
465 CHECK_PRIVILEGED
466 CHECK_NOT_DELAY_SLOT
467 gen_write_sr(cpu_ssr);
468 tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
469 ctx->envflags |= DELAY_SLOT_RTE;
470 ctx->delayed_pc = (uint32_t) - 1;
471 ctx->base.is_jmp = DISAS_STOP;
472 return;
473 case 0x0058: /* sets */
474 tcg_gen_ori_i32(cpu_sr, cpu_sr, (1u << SR_S));
475 return;
476 case 0x0018: /* sett */
477 tcg_gen_movi_i32(cpu_sr_t, 1);
478 return;
479 case 0xfbfd: /* frchg */
480 CHECK_FPSCR_PR_0
481 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
482 ctx->base.is_jmp = DISAS_STOP;
483 return;
484 case 0xf3fd: /* fschg */
485 CHECK_FPSCR_PR_0
486 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ);
487 ctx->base.is_jmp = DISAS_STOP;
488 return;
489 case 0xf7fd: /* fpchg */
490 CHECK_SH4A
491 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_PR);
492 ctx->base.is_jmp = DISAS_STOP;
493 return;
494 case 0x0009: /* nop */
495 return;
496 case 0x001b: /* sleep */
497 CHECK_PRIVILEGED
498 tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next + 2);
499 gen_helper_sleep(cpu_env);
500 return;
503 switch (ctx->opcode & 0xf000) {
504 case 0x1000: /* mov.l Rm,@(disp,Rn) */
506 TCGv addr = tcg_temp_new();
507 tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
508 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
509 tcg_temp_free(addr);
511 return;
512 case 0x5000: /* mov.l @(disp,Rm),Rn */
514 TCGv addr = tcg_temp_new();
515 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
516 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
517 tcg_temp_free(addr);
519 return;
520 case 0xe000: /* mov #imm,Rn */
521 #ifdef CONFIG_USER_ONLY
522 /* Detect the start of a gUSA region. If so, update envflags
523 and end the TB. This will allow us to see the end of the
524 region (stored in R0) in the next TB. */
525 if (B11_8 == 15 && B7_0s < 0 &&
526 (tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
527 ctx->envflags = deposit32(ctx->envflags, GUSA_SHIFT, 8, B7_0s);
528 ctx->base.is_jmp = DISAS_STOP;
530 #endif
531 tcg_gen_movi_i32(REG(B11_8), B7_0s);
532 return;
533 case 0x9000: /* mov.w @(disp,PC),Rn */
535 TCGv addr = tcg_const_i32(ctx->base.pc_next + 4 + B7_0 * 2);
536 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW);
537 tcg_temp_free(addr);
539 return;
540 case 0xd000: /* mov.l @(disp,PC),Rn */
542 TCGv addr = tcg_const_i32((ctx->base.pc_next + 4 + B7_0 * 4) & ~3);
543 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
544 tcg_temp_free(addr);
546 return;
547 case 0x7000: /* add #imm,Rn */
548 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s);
549 return;
550 case 0xa000: /* bra disp */
551 CHECK_NOT_DELAY_SLOT
552 ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2;
553 ctx->envflags |= DELAY_SLOT;
554 return;
555 case 0xb000: /* bsr disp */
556 CHECK_NOT_DELAY_SLOT
557 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
558 ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2;
559 ctx->envflags |= DELAY_SLOT;
560 return;
563 switch (ctx->opcode & 0xf00f) {
564 case 0x6003: /* mov Rm,Rn */
565 tcg_gen_mov_i32(REG(B11_8), REG(B7_4));
566 return;
567 case 0x2000: /* mov.b Rm,@Rn */
568 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB);
569 return;
570 case 0x2001: /* mov.w Rm,@Rn */
571 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUW);
572 return;
573 case 0x2002: /* mov.l Rm,@Rn */
574 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL);
575 return;
576 case 0x6000: /* mov.b @Rm,Rn */
577 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
578 return;
579 case 0x6001: /* mov.w @Rm,Rn */
580 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW);
581 return;
582 case 0x6002: /* mov.l @Rm,Rn */
583 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL);
584 return;
585 case 0x2004: /* mov.b Rm,@-Rn */
587 TCGv addr = tcg_temp_new();
588 tcg_gen_subi_i32(addr, REG(B11_8), 1);
589 /* might cause re-execution */
590 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB);
591 tcg_gen_mov_i32(REG(B11_8), addr); /* modify register status */
592 tcg_temp_free(addr);
594 return;
595 case 0x2005: /* mov.w Rm,@-Rn */
597 TCGv addr = tcg_temp_new();
598 tcg_gen_subi_i32(addr, REG(B11_8), 2);
599 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW);
600 tcg_gen_mov_i32(REG(B11_8), addr);
601 tcg_temp_free(addr);
603 return;
604 case 0x2006: /* mov.l Rm,@-Rn */
606 TCGv addr = tcg_temp_new();
607 tcg_gen_subi_i32(addr, REG(B11_8), 4);
608 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
609 tcg_gen_mov_i32(REG(B11_8), addr);
610 tcg_temp_free(addr);
612 return;
613 case 0x6004: /* mov.b @Rm+,Rn */
614 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
615 if ( B11_8 != B7_4 )
616 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1);
617 return;
618 case 0x6005: /* mov.w @Rm+,Rn */
619 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW);
620 if ( B11_8 != B7_4 )
621 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
622 return;
623 case 0x6006: /* mov.l @Rm+,Rn */
624 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL);
625 if ( B11_8 != B7_4 )
626 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
627 return;
628 case 0x0004: /* mov.b Rm,@(R0,Rn) */
630 TCGv addr = tcg_temp_new();
631 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
632 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB);
633 tcg_temp_free(addr);
635 return;
636 case 0x0005: /* mov.w Rm,@(R0,Rn) */
638 TCGv addr = tcg_temp_new();
639 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
640 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW);
641 tcg_temp_free(addr);
643 return;
644 case 0x0006: /* mov.l Rm,@(R0,Rn) */
646 TCGv addr = tcg_temp_new();
647 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
648 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
649 tcg_temp_free(addr);
651 return;
652 case 0x000c: /* mov.b @(R0,Rm),Rn */
654 TCGv addr = tcg_temp_new();
655 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
656 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_SB);
657 tcg_temp_free(addr);
659 return;
660 case 0x000d: /* mov.w @(R0,Rm),Rn */
662 TCGv addr = tcg_temp_new();
663 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
664 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW);
665 tcg_temp_free(addr);
667 return;
668 case 0x000e: /* mov.l @(R0,Rm),Rn */
670 TCGv addr = tcg_temp_new();
671 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
672 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
673 tcg_temp_free(addr);
675 return;
676 case 0x6008: /* swap.b Rm,Rn */
678 TCGv low = tcg_temp_new();
679 tcg_gen_ext16u_i32(low, REG(B7_4));
680 tcg_gen_bswap16_i32(low, low);
681 tcg_gen_deposit_i32(REG(B11_8), REG(B7_4), low, 0, 16);
682 tcg_temp_free(low);
684 return;
685 case 0x6009: /* swap.w Rm,Rn */
686 tcg_gen_rotli_i32(REG(B11_8), REG(B7_4), 16);
687 return;
688 case 0x200d: /* xtrct Rm,Rn */
690 TCGv high, low;
691 high = tcg_temp_new();
692 tcg_gen_shli_i32(high, REG(B7_4), 16);
693 low = tcg_temp_new();
694 tcg_gen_shri_i32(low, REG(B11_8), 16);
695 tcg_gen_or_i32(REG(B11_8), high, low);
696 tcg_temp_free(low);
697 tcg_temp_free(high);
699 return;
700 case 0x300c: /* add Rm,Rn */
701 tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4));
702 return;
703 case 0x300e: /* addc Rm,Rn */
705 TCGv t0, t1;
706 t0 = tcg_const_tl(0);
707 t1 = tcg_temp_new();
708 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0);
709 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t,
710 REG(B11_8), t0, t1, cpu_sr_t);
711 tcg_temp_free(t0);
712 tcg_temp_free(t1);
714 return;
715 case 0x300f: /* addv Rm,Rn */
717 TCGv t0, t1, t2;
718 t0 = tcg_temp_new();
719 tcg_gen_add_i32(t0, REG(B7_4), REG(B11_8));
720 t1 = tcg_temp_new();
721 tcg_gen_xor_i32(t1, t0, REG(B11_8));
722 t2 = tcg_temp_new();
723 tcg_gen_xor_i32(t2, REG(B7_4), REG(B11_8));
724 tcg_gen_andc_i32(cpu_sr_t, t1, t2);
725 tcg_temp_free(t2);
726 tcg_gen_shri_i32(cpu_sr_t, cpu_sr_t, 31);
727 tcg_temp_free(t1);
728 tcg_gen_mov_i32(REG(B7_4), t0);
729 tcg_temp_free(t0);
731 return;
732 case 0x2009: /* and Rm,Rn */
733 tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4));
734 return;
735 case 0x3000: /* cmp/eq Rm,Rn */
736 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), REG(B7_4));
737 return;
738 case 0x3003: /* cmp/ge Rm,Rn */
739 tcg_gen_setcond_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), REG(B7_4));
740 return;
741 case 0x3007: /* cmp/gt Rm,Rn */
742 tcg_gen_setcond_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), REG(B7_4));
743 return;
744 case 0x3006: /* cmp/hi Rm,Rn */
745 tcg_gen_setcond_i32(TCG_COND_GTU, cpu_sr_t, REG(B11_8), REG(B7_4));
746 return;
747 case 0x3002: /* cmp/hs Rm,Rn */
748 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_sr_t, REG(B11_8), REG(B7_4));
749 return;
750 case 0x200c: /* cmp/str Rm,Rn */
752 TCGv cmp1 = tcg_temp_new();
753 TCGv cmp2 = tcg_temp_new();
754 tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8));
755 tcg_gen_subi_i32(cmp1, cmp2, 0x01010101);
756 tcg_gen_andc_i32(cmp1, cmp1, cmp2);
757 tcg_gen_andi_i32(cmp1, cmp1, 0x80808080);
758 tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0);
759 tcg_temp_free(cmp2);
760 tcg_temp_free(cmp1);
762 return;
763 case 0x2007: /* div0s Rm,Rn */
764 tcg_gen_shri_i32(cpu_sr_q, REG(B11_8), 31); /* SR_Q */
765 tcg_gen_shri_i32(cpu_sr_m, REG(B7_4), 31); /* SR_M */
766 tcg_gen_xor_i32(cpu_sr_t, cpu_sr_q, cpu_sr_m); /* SR_T */
767 return;
768 case 0x3004: /* div1 Rm,Rn */
770 TCGv t0 = tcg_temp_new();
771 TCGv t1 = tcg_temp_new();
772 TCGv t2 = tcg_temp_new();
773 TCGv zero = tcg_const_i32(0);
775 /* shift left arg1, saving the bit being pushed out and inserting
776 T on the right */
777 tcg_gen_shri_i32(t0, REG(B11_8), 31);
778 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
779 tcg_gen_or_i32(REG(B11_8), REG(B11_8), cpu_sr_t);
781 /* Add or subtract arg0 from arg1 depending if Q == M. To avoid
782 using 64-bit temps, we compute arg0's high part from q ^ m, so
783 that it is 0x00000000 when adding the value or 0xffffffff when
784 subtracting it. */
785 tcg_gen_xor_i32(t1, cpu_sr_q, cpu_sr_m);
786 tcg_gen_subi_i32(t1, t1, 1);
787 tcg_gen_neg_i32(t2, REG(B7_4));
788 tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, zero, REG(B7_4), t2);
789 tcg_gen_add2_i32(REG(B11_8), t1, REG(B11_8), zero, t2, t1);
791 /* compute T and Q depending on carry */
792 tcg_gen_andi_i32(t1, t1, 1);
793 tcg_gen_xor_i32(t1, t1, t0);
794 tcg_gen_xori_i32(cpu_sr_t, t1, 1);
795 tcg_gen_xor_i32(cpu_sr_q, cpu_sr_m, t1);
797 tcg_temp_free(zero);
798 tcg_temp_free(t2);
799 tcg_temp_free(t1);
800 tcg_temp_free(t0);
802 return;
803 case 0x300d: /* dmuls.l Rm,Rn */
804 tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
805 return;
806 case 0x3005: /* dmulu.l Rm,Rn */
807 tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
808 return;
809 case 0x600e: /* exts.b Rm,Rn */
810 tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4));
811 return;
812 case 0x600f: /* exts.w Rm,Rn */
813 tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4));
814 return;
815 case 0x600c: /* extu.b Rm,Rn */
816 tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4));
817 return;
818 case 0x600d: /* extu.w Rm,Rn */
819 tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4));
820 return;
821 case 0x000f: /* mac.l @Rm+,@Rn+ */
823 TCGv arg0, arg1;
824 arg0 = tcg_temp_new();
825 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL);
826 arg1 = tcg_temp_new();
827 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL);
828 gen_helper_macl(cpu_env, arg0, arg1);
829 tcg_temp_free(arg1);
830 tcg_temp_free(arg0);
831 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
832 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
834 return;
835 case 0x400f: /* mac.w @Rm+,@Rn+ */
837 TCGv arg0, arg1;
838 arg0 = tcg_temp_new();
839 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL);
840 arg1 = tcg_temp_new();
841 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL);
842 gen_helper_macw(cpu_env, arg0, arg1);
843 tcg_temp_free(arg1);
844 tcg_temp_free(arg0);
845 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2);
846 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
848 return;
849 case 0x0007: /* mul.l Rm,Rn */
850 tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8));
851 return;
852 case 0x200f: /* muls.w Rm,Rn */
854 TCGv arg0, arg1;
855 arg0 = tcg_temp_new();
856 tcg_gen_ext16s_i32(arg0, REG(B7_4));
857 arg1 = tcg_temp_new();
858 tcg_gen_ext16s_i32(arg1, REG(B11_8));
859 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
860 tcg_temp_free(arg1);
861 tcg_temp_free(arg0);
863 return;
864 case 0x200e: /* mulu.w Rm,Rn */
866 TCGv arg0, arg1;
867 arg0 = tcg_temp_new();
868 tcg_gen_ext16u_i32(arg0, REG(B7_4));
869 arg1 = tcg_temp_new();
870 tcg_gen_ext16u_i32(arg1, REG(B11_8));
871 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
872 tcg_temp_free(arg1);
873 tcg_temp_free(arg0);
875 return;
876 case 0x600b: /* neg Rm,Rn */
877 tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
878 return;
879 case 0x600a: /* negc Rm,Rn */
881 TCGv t0 = tcg_const_i32(0);
882 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t,
883 REG(B7_4), t0, cpu_sr_t, t0);
884 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
885 t0, t0, REG(B11_8), cpu_sr_t);
886 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
887 tcg_temp_free(t0);
889 return;
890 case 0x6007: /* not Rm,Rn */
891 tcg_gen_not_i32(REG(B11_8), REG(B7_4));
892 return;
893 case 0x200b: /* or Rm,Rn */
894 tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4));
895 return;
896 case 0x400c: /* shad Rm,Rn */
898 TCGv t0 = tcg_temp_new();
899 TCGv t1 = tcg_temp_new();
900 TCGv t2 = tcg_temp_new();
902 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
904 /* positive case: shift to the left */
905 tcg_gen_shl_i32(t1, REG(B11_8), t0);
907 /* negative case: shift to the right in two steps to
908 correctly handle the -32 case */
909 tcg_gen_xori_i32(t0, t0, 0x1f);
910 tcg_gen_sar_i32(t2, REG(B11_8), t0);
911 tcg_gen_sari_i32(t2, t2, 1);
913 /* select between the two cases */
914 tcg_gen_movi_i32(t0, 0);
915 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
917 tcg_temp_free(t0);
918 tcg_temp_free(t1);
919 tcg_temp_free(t2);
921 return;
922 case 0x400d: /* shld Rm,Rn */
924 TCGv t0 = tcg_temp_new();
925 TCGv t1 = tcg_temp_new();
926 TCGv t2 = tcg_temp_new();
928 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
930 /* positive case: shift to the left */
931 tcg_gen_shl_i32(t1, REG(B11_8), t0);
933 /* negative case: shift to the right in two steps to
934 correctly handle the -32 case */
935 tcg_gen_xori_i32(t0, t0, 0x1f);
936 tcg_gen_shr_i32(t2, REG(B11_8), t0);
937 tcg_gen_shri_i32(t2, t2, 1);
939 /* select between the two cases */
940 tcg_gen_movi_i32(t0, 0);
941 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
943 tcg_temp_free(t0);
944 tcg_temp_free(t1);
945 tcg_temp_free(t2);
947 return;
948 case 0x3008: /* sub Rm,Rn */
949 tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4));
950 return;
951 case 0x300a: /* subc Rm,Rn */
953 TCGv t0, t1;
954 t0 = tcg_const_tl(0);
955 t1 = tcg_temp_new();
956 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0);
957 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
958 REG(B11_8), t0, t1, cpu_sr_t);
959 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
960 tcg_temp_free(t0);
961 tcg_temp_free(t1);
963 return;
964 case 0x300b: /* subv Rm,Rn */
966 TCGv t0, t1, t2;
967 t0 = tcg_temp_new();
968 tcg_gen_sub_i32(t0, REG(B11_8), REG(B7_4));
969 t1 = tcg_temp_new();
970 tcg_gen_xor_i32(t1, t0, REG(B7_4));
971 t2 = tcg_temp_new();
972 tcg_gen_xor_i32(t2, REG(B11_8), REG(B7_4));
973 tcg_gen_and_i32(t1, t1, t2);
974 tcg_temp_free(t2);
975 tcg_gen_shri_i32(cpu_sr_t, t1, 31);
976 tcg_temp_free(t1);
977 tcg_gen_mov_i32(REG(B11_8), t0);
978 tcg_temp_free(t0);
980 return;
981 case 0x2008: /* tst Rm,Rn */
983 TCGv val = tcg_temp_new();
984 tcg_gen_and_i32(val, REG(B7_4), REG(B11_8));
985 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
986 tcg_temp_free(val);
988 return;
989 case 0x200a: /* xor Rm,Rn */
990 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4));
991 return;
992 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
993 CHECK_FPU_ENABLED
994 if (ctx->tbflags & FPSCR_SZ) {
995 int xsrc = XHACK(B7_4);
996 int xdst = XHACK(B11_8);
997 tcg_gen_mov_i32(FREG(xdst), FREG(xsrc));
998 tcg_gen_mov_i32(FREG(xdst + 1), FREG(xsrc + 1));
999 } else {
1000 tcg_gen_mov_i32(FREG(B11_8), FREG(B7_4));
1002 return;
1003 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
1004 CHECK_FPU_ENABLED
1005 if (ctx->tbflags & FPSCR_SZ) {
1006 TCGv_i64 fp = tcg_temp_new_i64();
1007 gen_load_fpr64(ctx, fp, XHACK(B7_4));
1008 tcg_gen_qemu_st_i64(fp, REG(B11_8), ctx->memidx, MO_TEQ);
1009 tcg_temp_free_i64(fp);
1010 } else {
1011 tcg_gen_qemu_st_i32(FREG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL);
1013 return;
1014 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
1015 CHECK_FPU_ENABLED
1016 if (ctx->tbflags & FPSCR_SZ) {
1017 TCGv_i64 fp = tcg_temp_new_i64();
1018 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEQ);
1019 gen_store_fpr64(ctx, fp, XHACK(B11_8));
1020 tcg_temp_free_i64(fp);
1021 } else {
1022 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx, MO_TEUL);
1024 return;
1025 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
1026 CHECK_FPU_ENABLED
1027 if (ctx->tbflags & FPSCR_SZ) {
1028 TCGv_i64 fp = tcg_temp_new_i64();
1029 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEQ);
1030 gen_store_fpr64(ctx, fp, XHACK(B11_8));
1031 tcg_temp_free_i64(fp);
1032 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8);
1033 } else {
1034 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx, MO_TEUL);
1035 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
1037 return;
1038 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
1039 CHECK_FPU_ENABLED
1041 TCGv addr = tcg_temp_new_i32();
1042 if (ctx->tbflags & FPSCR_SZ) {
1043 TCGv_i64 fp = tcg_temp_new_i64();
1044 gen_load_fpr64(ctx, fp, XHACK(B7_4));
1045 tcg_gen_subi_i32(addr, REG(B11_8), 8);
1046 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEQ);
1047 tcg_temp_free_i64(fp);
1048 } else {
1049 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1050 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, MO_TEUL);
1052 tcg_gen_mov_i32(REG(B11_8), addr);
1053 tcg_temp_free(addr);
1055 return;
1056 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
1057 CHECK_FPU_ENABLED
1059 TCGv addr = tcg_temp_new_i32();
1060 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
1061 if (ctx->tbflags & FPSCR_SZ) {
1062 TCGv_i64 fp = tcg_temp_new_i64();
1063 tcg_gen_qemu_ld_i64(fp, addr, ctx->memidx, MO_TEQ);
1064 gen_store_fpr64(ctx, fp, XHACK(B11_8));
1065 tcg_temp_free_i64(fp);
1066 } else {
1067 tcg_gen_qemu_ld_i32(FREG(B11_8), addr, ctx->memidx, MO_TEUL);
1069 tcg_temp_free(addr);
1071 return;
1072 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
1073 CHECK_FPU_ENABLED
1075 TCGv addr = tcg_temp_new();
1076 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
1077 if (ctx->tbflags & FPSCR_SZ) {
1078 TCGv_i64 fp = tcg_temp_new_i64();
1079 gen_load_fpr64(ctx, fp, XHACK(B7_4));
1080 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEQ);
1081 tcg_temp_free_i64(fp);
1082 } else {
1083 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, MO_TEUL);
1085 tcg_temp_free(addr);
1087 return;
1088 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1089 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1090 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1091 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1092 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1093 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1095 CHECK_FPU_ENABLED
1096 if (ctx->tbflags & FPSCR_PR) {
1097 TCGv_i64 fp0, fp1;
1099 if (ctx->opcode & 0x0110) {
1100 goto do_illegal;
1102 fp0 = tcg_temp_new_i64();
1103 fp1 = tcg_temp_new_i64();
1104 gen_load_fpr64(ctx, fp0, B11_8);
1105 gen_load_fpr64(ctx, fp1, B7_4);
1106 switch (ctx->opcode & 0xf00f) {
1107 case 0xf000: /* fadd Rm,Rn */
1108 gen_helper_fadd_DT(fp0, cpu_env, fp0, fp1);
1109 break;
1110 case 0xf001: /* fsub Rm,Rn */
1111 gen_helper_fsub_DT(fp0, cpu_env, fp0, fp1);
1112 break;
1113 case 0xf002: /* fmul Rm,Rn */
1114 gen_helper_fmul_DT(fp0, cpu_env, fp0, fp1);
1115 break;
1116 case 0xf003: /* fdiv Rm,Rn */
1117 gen_helper_fdiv_DT(fp0, cpu_env, fp0, fp1);
1118 break;
1119 case 0xf004: /* fcmp/eq Rm,Rn */
1120 gen_helper_fcmp_eq_DT(cpu_sr_t, cpu_env, fp0, fp1);
1121 return;
1122 case 0xf005: /* fcmp/gt Rm,Rn */
1123 gen_helper_fcmp_gt_DT(cpu_sr_t, cpu_env, fp0, fp1);
1124 return;
1126 gen_store_fpr64(ctx, fp0, B11_8);
1127 tcg_temp_free_i64(fp0);
1128 tcg_temp_free_i64(fp1);
1129 } else {
1130 switch (ctx->opcode & 0xf00f) {
1131 case 0xf000: /* fadd Rm,Rn */
1132 gen_helper_fadd_FT(FREG(B11_8), cpu_env,
1133 FREG(B11_8), FREG(B7_4));
1134 break;
1135 case 0xf001: /* fsub Rm,Rn */
1136 gen_helper_fsub_FT(FREG(B11_8), cpu_env,
1137 FREG(B11_8), FREG(B7_4));
1138 break;
1139 case 0xf002: /* fmul Rm,Rn */
1140 gen_helper_fmul_FT(FREG(B11_8), cpu_env,
1141 FREG(B11_8), FREG(B7_4));
1142 break;
1143 case 0xf003: /* fdiv Rm,Rn */
1144 gen_helper_fdiv_FT(FREG(B11_8), cpu_env,
1145 FREG(B11_8), FREG(B7_4));
1146 break;
1147 case 0xf004: /* fcmp/eq Rm,Rn */
1148 gen_helper_fcmp_eq_FT(cpu_sr_t, cpu_env,
1149 FREG(B11_8), FREG(B7_4));
1150 return;
1151 case 0xf005: /* fcmp/gt Rm,Rn */
1152 gen_helper_fcmp_gt_FT(cpu_sr_t, cpu_env,
1153 FREG(B11_8), FREG(B7_4));
1154 return;
1158 return;
1159 case 0xf00e: /* fmac FR0,RM,Rn */
1160 CHECK_FPU_ENABLED
1161 CHECK_FPSCR_PR_0
1162 gen_helper_fmac_FT(FREG(B11_8), cpu_env,
1163 FREG(0), FREG(B7_4), FREG(B11_8));
1164 return;
1167 switch (ctx->opcode & 0xff00) {
1168 case 0xc900: /* and #imm,R0 */
1169 tcg_gen_andi_i32(REG(0), REG(0), B7_0);
1170 return;
1171 case 0xcd00: /* and.b #imm,@(R0,GBR) */
1173 TCGv addr, val;
1174 addr = tcg_temp_new();
1175 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1176 val = tcg_temp_new();
1177 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1178 tcg_gen_andi_i32(val, val, B7_0);
1179 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1180 tcg_temp_free(val);
1181 tcg_temp_free(addr);
1183 return;
1184 case 0x8b00: /* bf label */
1185 CHECK_NOT_DELAY_SLOT
1186 gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, false);
1187 return;
1188 case 0x8f00: /* bf/s label */
1189 CHECK_NOT_DELAY_SLOT
1190 tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1);
1191 ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
1192 ctx->envflags |= DELAY_SLOT_CONDITIONAL;
1193 return;
1194 case 0x8900: /* bt label */
1195 CHECK_NOT_DELAY_SLOT
1196 gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, true);
1197 return;
1198 case 0x8d00: /* bt/s label */
1199 CHECK_NOT_DELAY_SLOT
1200 tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t);
1201 ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
1202 ctx->envflags |= DELAY_SLOT_CONDITIONAL;
1203 return;
1204 case 0x8800: /* cmp/eq #imm,R0 */
1205 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s);
1206 return;
1207 case 0xc400: /* mov.b @(disp,GBR),R0 */
1209 TCGv addr = tcg_temp_new();
1210 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1211 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
1212 tcg_temp_free(addr);
1214 return;
1215 case 0xc500: /* mov.w @(disp,GBR),R0 */
1217 TCGv addr = tcg_temp_new();
1218 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1219 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW);
1220 tcg_temp_free(addr);
1222 return;
1223 case 0xc600: /* mov.l @(disp,GBR),R0 */
1225 TCGv addr = tcg_temp_new();
1226 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1227 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESL);
1228 tcg_temp_free(addr);
1230 return;
1231 case 0xc000: /* mov.b R0,@(disp,GBR) */
1233 TCGv addr = tcg_temp_new();
1234 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1235 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
1236 tcg_temp_free(addr);
1238 return;
1239 case 0xc100: /* mov.w R0,@(disp,GBR) */
1241 TCGv addr = tcg_temp_new();
1242 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1243 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW);
1244 tcg_temp_free(addr);
1246 return;
1247 case 0xc200: /* mov.l R0,@(disp,GBR) */
1249 TCGv addr = tcg_temp_new();
1250 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1251 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUL);
1252 tcg_temp_free(addr);
1254 return;
1255 case 0x8000: /* mov.b R0,@(disp,Rn) */
1257 TCGv addr = tcg_temp_new();
1258 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1259 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
1260 tcg_temp_free(addr);
1262 return;
1263 case 0x8100: /* mov.w R0,@(disp,Rn) */
1265 TCGv addr = tcg_temp_new();
1266 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1267 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW);
1268 tcg_temp_free(addr);
1270 return;
1271 case 0x8400: /* mov.b @(disp,Rn),R0 */
1273 TCGv addr = tcg_temp_new();
1274 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1275 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
1276 tcg_temp_free(addr);
1278 return;
1279 case 0x8500: /* mov.w @(disp,Rn),R0 */
1281 TCGv addr = tcg_temp_new();
1282 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1283 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW);
1284 tcg_temp_free(addr);
1286 return;
1287 case 0xc700: /* mova @(disp,PC),R0 */
1288 tcg_gen_movi_i32(REG(0), ((ctx->base.pc_next & 0xfffffffc) +
1289 4 + B7_0 * 4) & ~3);
1290 return;
1291 case 0xcb00: /* or #imm,R0 */
1292 tcg_gen_ori_i32(REG(0), REG(0), B7_0);
1293 return;
1294 case 0xcf00: /* or.b #imm,@(R0,GBR) */
1296 TCGv addr, val;
1297 addr = tcg_temp_new();
1298 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1299 val = tcg_temp_new();
1300 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1301 tcg_gen_ori_i32(val, val, B7_0);
1302 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1303 tcg_temp_free(val);
1304 tcg_temp_free(addr);
1306 return;
1307 case 0xc300: /* trapa #imm */
1309 TCGv imm;
1310 CHECK_NOT_DELAY_SLOT
1311 gen_save_cpu_state(ctx, true);
1312 imm = tcg_const_i32(B7_0);
1313 gen_helper_trapa(cpu_env, imm);
1314 tcg_temp_free(imm);
1315 ctx->base.is_jmp = DISAS_NORETURN;
1317 return;
1318 case 0xc800: /* tst #imm,R0 */
1320 TCGv val = tcg_temp_new();
1321 tcg_gen_andi_i32(val, REG(0), B7_0);
1322 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1323 tcg_temp_free(val);
1325 return;
1326 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
1328 TCGv val = tcg_temp_new();
1329 tcg_gen_add_i32(val, REG(0), cpu_gbr);
1330 tcg_gen_qemu_ld_i32(val, val, ctx->memidx, MO_UB);
1331 tcg_gen_andi_i32(val, val, B7_0);
1332 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1333 tcg_temp_free(val);
1335 return;
1336 case 0xca00: /* xor #imm,R0 */
1337 tcg_gen_xori_i32(REG(0), REG(0), B7_0);
1338 return;
1339 case 0xce00: /* xor.b #imm,@(R0,GBR) */
1341 TCGv addr, val;
1342 addr = tcg_temp_new();
1343 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1344 val = tcg_temp_new();
1345 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1346 tcg_gen_xori_i32(val, val, B7_0);
1347 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1348 tcg_temp_free(val);
1349 tcg_temp_free(addr);
1351 return;
1354 switch (ctx->opcode & 0xf08f) {
1355 case 0x408e: /* ldc Rm,Rn_BANK */
1356 CHECK_PRIVILEGED
1357 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8));
1358 return;
1359 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
1360 CHECK_PRIVILEGED
1361 tcg_gen_qemu_ld_i32(ALTREG(B6_4), REG(B11_8), ctx->memidx, MO_TESL);
1362 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1363 return;
1364 case 0x0082: /* stc Rm_BANK,Rn */
1365 CHECK_PRIVILEGED
1366 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4));
1367 return;
1368 case 0x4083: /* stc.l Rm_BANK,@-Rn */
1369 CHECK_PRIVILEGED
1371 TCGv addr = tcg_temp_new();
1372 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1373 tcg_gen_qemu_st_i32(ALTREG(B6_4), addr, ctx->memidx, MO_TEUL);
1374 tcg_gen_mov_i32(REG(B11_8), addr);
1375 tcg_temp_free(addr);
1377 return;
1380 switch (ctx->opcode & 0xf0ff) {
1381 case 0x0023: /* braf Rn */
1382 CHECK_NOT_DELAY_SLOT
1383 tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->base.pc_next + 4);
1384 ctx->envflags |= DELAY_SLOT;
1385 ctx->delayed_pc = (uint32_t) - 1;
1386 return;
1387 case 0x0003: /* bsrf Rn */
1388 CHECK_NOT_DELAY_SLOT
1389 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
1390 tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
1391 ctx->envflags |= DELAY_SLOT;
1392 ctx->delayed_pc = (uint32_t) - 1;
1393 return;
1394 case 0x4015: /* cmp/pl Rn */
1395 tcg_gen_setcondi_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), 0);
1396 return;
1397 case 0x4011: /* cmp/pz Rn */
1398 tcg_gen_setcondi_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), 0);
1399 return;
1400 case 0x4010: /* dt Rn */
1401 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1);
1402 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), 0);
1403 return;
1404 case 0x402b: /* jmp @Rn */
1405 CHECK_NOT_DELAY_SLOT
1406 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1407 ctx->envflags |= DELAY_SLOT;
1408 ctx->delayed_pc = (uint32_t) - 1;
1409 return;
1410 case 0x400b: /* jsr @Rn */
1411 CHECK_NOT_DELAY_SLOT
1412 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
1413 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1414 ctx->envflags |= DELAY_SLOT;
1415 ctx->delayed_pc = (uint32_t) - 1;
1416 return;
1417 case 0x400e: /* ldc Rm,SR */
1418 CHECK_PRIVILEGED
1420 TCGv val = tcg_temp_new();
1421 tcg_gen_andi_i32(val, REG(B11_8), 0x700083f3);
1422 gen_write_sr(val);
1423 tcg_temp_free(val);
1424 ctx->base.is_jmp = DISAS_STOP;
1426 return;
1427 case 0x4007: /* ldc.l @Rm+,SR */
1428 CHECK_PRIVILEGED
1430 TCGv val = tcg_temp_new();
1431 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TESL);
1432 tcg_gen_andi_i32(val, val, 0x700083f3);
1433 gen_write_sr(val);
1434 tcg_temp_free(val);
1435 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1436 ctx->base.is_jmp = DISAS_STOP;
1438 return;
1439 case 0x0002: /* stc SR,Rn */
1440 CHECK_PRIVILEGED
1441 gen_read_sr(REG(B11_8));
1442 return;
1443 case 0x4003: /* stc SR,@-Rn */
1444 CHECK_PRIVILEGED
1446 TCGv addr = tcg_temp_new();
1447 TCGv val = tcg_temp_new();
1448 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1449 gen_read_sr(val);
1450 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL);
1451 tcg_gen_mov_i32(REG(B11_8), addr);
1452 tcg_temp_free(val);
1453 tcg_temp_free(addr);
1455 return;
1456 #define LD(reg,ldnum,ldpnum,prechk) \
1457 case ldnum: \
1458 prechk \
1459 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \
1460 return; \
1461 case ldpnum: \
1462 prechk \
1463 tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, MO_TESL); \
1464 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \
1465 return;
1466 #define ST(reg,stnum,stpnum,prechk) \
1467 case stnum: \
1468 prechk \
1469 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \
1470 return; \
1471 case stpnum: \
1472 prechk \
1474 TCGv addr = tcg_temp_new(); \
1475 tcg_gen_subi_i32(addr, REG(B11_8), 4); \
1476 tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, MO_TEUL); \
1477 tcg_gen_mov_i32(REG(B11_8), addr); \
1478 tcg_temp_free(addr); \
1480 return;
1481 #define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \
1482 LD(reg,ldnum,ldpnum,prechk) \
1483 ST(reg,stnum,stpnum,prechk)
1484 LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {})
1485 LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED)
1486 LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED)
1487 LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED)
1488 ST(sgr, 0x003a, 0x4032, CHECK_PRIVILEGED)
1489 LD(sgr, 0x403a, 0x4036, CHECK_PRIVILEGED CHECK_SH4A)
1490 LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED)
1491 LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {})
1492 LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {})
1493 LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {})
1494 LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED})
1495 case 0x406a: /* lds Rm,FPSCR */
1496 CHECK_FPU_ENABLED
1497 gen_helper_ld_fpscr(cpu_env, REG(B11_8));
1498 ctx->base.is_jmp = DISAS_STOP;
1499 return;
1500 case 0x4066: /* lds.l @Rm+,FPSCR */
1501 CHECK_FPU_ENABLED
1503 TCGv addr = tcg_temp_new();
1504 tcg_gen_qemu_ld_i32(addr, REG(B11_8), ctx->memidx, MO_TESL);
1505 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1506 gen_helper_ld_fpscr(cpu_env, addr);
1507 tcg_temp_free(addr);
1508 ctx->base.is_jmp = DISAS_STOP;
1510 return;
1511 case 0x006a: /* sts FPSCR,Rn */
1512 CHECK_FPU_ENABLED
1513 tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff);
1514 return;
1515 case 0x4062: /* sts FPSCR,@-Rn */
1516 CHECK_FPU_ENABLED
1518 TCGv addr, val;
1519 val = tcg_temp_new();
1520 tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff);
1521 addr = tcg_temp_new();
1522 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1523 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL);
1524 tcg_gen_mov_i32(REG(B11_8), addr);
1525 tcg_temp_free(addr);
1526 tcg_temp_free(val);
1528 return;
1529 case 0x00c3: /* movca.l R0,@Rm */
1531 TCGv val = tcg_temp_new();
1532 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TEUL);
1533 gen_helper_movcal(cpu_env, REG(B11_8), val);
1534 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
1535 tcg_temp_free(val);
1537 ctx->has_movcal = 1;
1538 return;
1539 case 0x40a9: /* movua.l @Rm,R0 */
1540 CHECK_SH4A
1541 /* Load non-boundary-aligned data */
1542 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1543 MO_TEUL | MO_UNALN);
1544 return;
1545 case 0x40e9: /* movua.l @Rm+,R0 */
1546 CHECK_SH4A
1547 /* Load non-boundary-aligned data */
1548 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1549 MO_TEUL | MO_UNALN);
1550 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1551 return;
1552 case 0x0029: /* movt Rn */
1553 tcg_gen_mov_i32(REG(B11_8), cpu_sr_t);
1554 return;
1555 case 0x0073:
1556 /* MOVCO.L
1557 * LDST -> T
1558 * If (T == 1) R0 -> (Rn)
1559 * 0 -> LDST
1561 * The above description doesn't work in a parallel context.
1562 * Since we currently support no smp boards, this implies user-mode.
1563 * But we can still support the official mechanism while user-mode
1564 * is single-threaded. */
1565 CHECK_SH4A
1567 TCGLabel *fail = gen_new_label();
1568 TCGLabel *done = gen_new_label();
1570 if ((tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
1571 TCGv tmp;
1573 tcg_gen_brcond_i32(TCG_COND_NE, REG(B11_8),
1574 cpu_lock_addr, fail);
1575 tmp = tcg_temp_new();
1576 tcg_gen_atomic_cmpxchg_i32(tmp, REG(B11_8), cpu_lock_value,
1577 REG(0), ctx->memidx, MO_TEUL);
1578 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, tmp, cpu_lock_value);
1579 tcg_temp_free(tmp);
1580 } else {
1581 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_lock_addr, -1, fail);
1582 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
1583 tcg_gen_movi_i32(cpu_sr_t, 1);
1585 tcg_gen_br(done);
1587 gen_set_label(fail);
1588 tcg_gen_movi_i32(cpu_sr_t, 0);
1590 gen_set_label(done);
1591 tcg_gen_movi_i32(cpu_lock_addr, -1);
1593 return;
1594 case 0x0063:
1595 /* MOVLI.L @Rm,R0
1596 * 1 -> LDST
1597 * (Rm) -> R0
1598 * When interrupt/exception
1599 * occurred 0 -> LDST
1601 * In a parallel context, we must also save the loaded value
1602 * for use with the cmpxchg that we'll use with movco.l. */
1603 CHECK_SH4A
1604 if ((tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
1605 TCGv tmp = tcg_temp_new();
1606 tcg_gen_mov_i32(tmp, REG(B11_8));
1607 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TESL);
1608 tcg_gen_mov_i32(cpu_lock_value, REG(0));
1609 tcg_gen_mov_i32(cpu_lock_addr, tmp);
1610 tcg_temp_free(tmp);
1611 } else {
1612 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TESL);
1613 tcg_gen_movi_i32(cpu_lock_addr, 0);
1615 return;
1616 case 0x0093: /* ocbi @Rn */
1618 gen_helper_ocbi(cpu_env, REG(B11_8));
1620 return;
1621 case 0x00a3: /* ocbp @Rn */
1622 case 0x00b3: /* ocbwb @Rn */
1623 /* These instructions are supposed to do nothing in case of
1624 a cache miss. Given that we only partially emulate caches
1625 it is safe to simply ignore them. */
1626 return;
1627 case 0x0083: /* pref @Rn */
1628 return;
1629 case 0x00d3: /* prefi @Rn */
1630 CHECK_SH4A
1631 return;
1632 case 0x00e3: /* icbi @Rn */
1633 CHECK_SH4A
1634 return;
1635 case 0x00ab: /* synco */
1636 CHECK_SH4A
1637 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
1638 return;
1639 case 0x4024: /* rotcl Rn */
1641 TCGv tmp = tcg_temp_new();
1642 tcg_gen_mov_i32(tmp, cpu_sr_t);
1643 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
1644 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1645 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
1646 tcg_temp_free(tmp);
1648 return;
1649 case 0x4025: /* rotcr Rn */
1651 TCGv tmp = tcg_temp_new();
1652 tcg_gen_shli_i32(tmp, cpu_sr_t, 31);
1653 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1654 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1655 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
1656 tcg_temp_free(tmp);
1658 return;
1659 case 0x4004: /* rotl Rn */
1660 tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1);
1661 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
1662 return;
1663 case 0x4005: /* rotr Rn */
1664 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
1665 tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1);
1666 return;
1667 case 0x4000: /* shll Rn */
1668 case 0x4020: /* shal Rn */
1669 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
1670 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1671 return;
1672 case 0x4021: /* shar Rn */
1673 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1674 tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1);
1675 return;
1676 case 0x4001: /* shlr Rn */
1677 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1678 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1679 return;
1680 case 0x4008: /* shll2 Rn */
1681 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2);
1682 return;
1683 case 0x4018: /* shll8 Rn */
1684 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8);
1685 return;
1686 case 0x4028: /* shll16 Rn */
1687 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16);
1688 return;
1689 case 0x4009: /* shlr2 Rn */
1690 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2);
1691 return;
1692 case 0x4019: /* shlr8 Rn */
1693 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8);
1694 return;
1695 case 0x4029: /* shlr16 Rn */
1696 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16);
1697 return;
1698 case 0x401b: /* tas.b @Rn */
1700 TCGv val = tcg_const_i32(0x80);
1701 tcg_gen_atomic_fetch_or_i32(val, REG(B11_8), val,
1702 ctx->memidx, MO_UB);
1703 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1704 tcg_temp_free(val);
1706 return;
1707 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1708 CHECK_FPU_ENABLED
1709 tcg_gen_mov_i32(FREG(B11_8), cpu_fpul);
1710 return;
1711 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1712 CHECK_FPU_ENABLED
1713 tcg_gen_mov_i32(cpu_fpul, FREG(B11_8));
1714 return;
1715 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
1716 CHECK_FPU_ENABLED
1717 if (ctx->tbflags & FPSCR_PR) {
1718 TCGv_i64 fp;
1719 if (ctx->opcode & 0x0100) {
1720 goto do_illegal;
1722 fp = tcg_temp_new_i64();
1723 gen_helper_float_DT(fp, cpu_env, cpu_fpul);
1724 gen_store_fpr64(ctx, fp, B11_8);
1725 tcg_temp_free_i64(fp);
1727 else {
1728 gen_helper_float_FT(FREG(B11_8), cpu_env, cpu_fpul);
1730 return;
1731 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1732 CHECK_FPU_ENABLED
1733 if (ctx->tbflags & FPSCR_PR) {
1734 TCGv_i64 fp;
1735 if (ctx->opcode & 0x0100) {
1736 goto do_illegal;
1738 fp = tcg_temp_new_i64();
1739 gen_load_fpr64(ctx, fp, B11_8);
1740 gen_helper_ftrc_DT(cpu_fpul, cpu_env, fp);
1741 tcg_temp_free_i64(fp);
1743 else {
1744 gen_helper_ftrc_FT(cpu_fpul, cpu_env, FREG(B11_8));
1746 return;
1747 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
1748 CHECK_FPU_ENABLED
1749 tcg_gen_xori_i32(FREG(B11_8), FREG(B11_8), 0x80000000);
1750 return;
1751 case 0xf05d: /* fabs FRn/DRn - FPCSR: Nothing */
1752 CHECK_FPU_ENABLED
1753 tcg_gen_andi_i32(FREG(B11_8), FREG(B11_8), 0x7fffffff);
1754 return;
1755 case 0xf06d: /* fsqrt FRn */
1756 CHECK_FPU_ENABLED
1757 if (ctx->tbflags & FPSCR_PR) {
1758 if (ctx->opcode & 0x0100) {
1759 goto do_illegal;
1761 TCGv_i64 fp = tcg_temp_new_i64();
1762 gen_load_fpr64(ctx, fp, B11_8);
1763 gen_helper_fsqrt_DT(fp, cpu_env, fp);
1764 gen_store_fpr64(ctx, fp, B11_8);
1765 tcg_temp_free_i64(fp);
1766 } else {
1767 gen_helper_fsqrt_FT(FREG(B11_8), cpu_env, FREG(B11_8));
1769 return;
1770 case 0xf07d: /* fsrra FRn */
1771 CHECK_FPU_ENABLED
1772 CHECK_FPSCR_PR_0
1773 gen_helper_fsrra_FT(FREG(B11_8), cpu_env, FREG(B11_8));
1774 break;
1775 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
1776 CHECK_FPU_ENABLED
1777 CHECK_FPSCR_PR_0
1778 tcg_gen_movi_i32(FREG(B11_8), 0);
1779 return;
1780 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
1781 CHECK_FPU_ENABLED
1782 CHECK_FPSCR_PR_0
1783 tcg_gen_movi_i32(FREG(B11_8), 0x3f800000);
1784 return;
1785 case 0xf0ad: /* fcnvsd FPUL,DRn */
1786 CHECK_FPU_ENABLED
1788 TCGv_i64 fp = tcg_temp_new_i64();
1789 gen_helper_fcnvsd_FT_DT(fp, cpu_env, cpu_fpul);
1790 gen_store_fpr64(ctx, fp, B11_8);
1791 tcg_temp_free_i64(fp);
1793 return;
1794 case 0xf0bd: /* fcnvds DRn,FPUL */
1795 CHECK_FPU_ENABLED
1797 TCGv_i64 fp = tcg_temp_new_i64();
1798 gen_load_fpr64(ctx, fp, B11_8);
1799 gen_helper_fcnvds_DT_FT(cpu_fpul, cpu_env, fp);
1800 tcg_temp_free_i64(fp);
1802 return;
1803 case 0xf0ed: /* fipr FVm,FVn */
1804 CHECK_FPU_ENABLED
1805 CHECK_FPSCR_PR_1
1807 TCGv m = tcg_const_i32((ctx->opcode >> 8) & 3);
1808 TCGv n = tcg_const_i32((ctx->opcode >> 10) & 3);
1809 gen_helper_fipr(cpu_env, m, n);
1810 tcg_temp_free(m);
1811 tcg_temp_free(n);
1812 return;
1814 break;
1815 case 0xf0fd: /* ftrv XMTRX,FVn */
1816 CHECK_FPU_ENABLED
1817 CHECK_FPSCR_PR_1
1819 if ((ctx->opcode & 0x0300) != 0x0100) {
1820 goto do_illegal;
1822 TCGv n = tcg_const_i32((ctx->opcode >> 10) & 3);
1823 gen_helper_ftrv(cpu_env, n);
1824 tcg_temp_free(n);
1825 return;
1827 break;
1829 #if 0
1830 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1831 ctx->opcode, ctx->base.pc_next);
1832 fflush(stderr);
1833 #endif
1834 do_illegal:
1835 if (ctx->envflags & DELAY_SLOT_MASK) {
1836 do_illegal_slot:
1837 gen_save_cpu_state(ctx, true);
1838 gen_helper_raise_slot_illegal_instruction(cpu_env);
1839 } else {
1840 gen_save_cpu_state(ctx, true);
1841 gen_helper_raise_illegal_instruction(cpu_env);
1843 ctx->base.is_jmp = DISAS_NORETURN;
1844 return;
1846 do_fpu_disabled:
1847 gen_save_cpu_state(ctx, true);
1848 if (ctx->envflags & DELAY_SLOT_MASK) {
1849 gen_helper_raise_slot_fpu_disable(cpu_env);
1850 } else {
1851 gen_helper_raise_fpu_disable(cpu_env);
1853 ctx->base.is_jmp = DISAS_NORETURN;
1854 return;
1857 static void decode_opc(DisasContext * ctx)
1859 uint32_t old_flags = ctx->envflags;
1861 _decode_opc(ctx);
1863 if (old_flags & DELAY_SLOT_MASK) {
1864 /* go out of the delay slot */
1865 ctx->envflags &= ~DELAY_SLOT_MASK;
1867 /* When in an exclusive region, we must continue to the end
1868 for conditional branches. */
1869 if (ctx->tbflags & GUSA_EXCLUSIVE
1870 && old_flags & DELAY_SLOT_CONDITIONAL) {
1871 gen_delayed_conditional_jump(ctx);
1872 return;
1874 /* Otherwise this is probably an invalid gUSA region.
1875 Drop the GUSA bits so the next TB doesn't see them. */
1876 ctx->envflags &= ~GUSA_MASK;
1878 tcg_gen_movi_i32(cpu_flags, ctx->envflags);
1879 if (old_flags & DELAY_SLOT_CONDITIONAL) {
1880 gen_delayed_conditional_jump(ctx);
1881 } else {
1882 gen_jump(ctx);
1887 #ifdef CONFIG_USER_ONLY
1888 /* For uniprocessors, SH4 uses optimistic restartable atomic sequences.
1889 Upon an interrupt, a real kernel would simply notice magic values in
1890 the registers and reset the PC to the start of the sequence.
1892 For QEMU, we cannot do this in quite the same way. Instead, we notice
1893 the normal start of such a sequence (mov #-x,r15). While we can handle
1894 any sequence via cpu_exec_step_atomic, we can recognize the "normal"
1895 sequences and transform them into atomic operations as seen by the host.
1897 static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
1899 uint16_t insns[5];
1900 int ld_adr, ld_dst, ld_mop;
1901 int op_dst, op_src, op_opc;
1902 int mv_src, mt_dst, st_src, st_mop;
1903 TCGv op_arg;
1904 uint32_t pc = ctx->base.pc_next;
1905 uint32_t pc_end = ctx->base.tb->cs_base;
1906 int max_insns = (pc_end - pc) / 2;
1907 int i;
1909 /* The state machine below will consume only a few insns.
1910 If there are more than that in a region, fail now. */
1911 if (max_insns > ARRAY_SIZE(insns)) {
1912 goto fail;
1915 /* Read all of the insns for the region. */
1916 for (i = 0; i < max_insns; ++i) {
1917 insns[i] = translator_lduw(env, pc + i * 2);
1920 ld_adr = ld_dst = ld_mop = -1;
1921 mv_src = -1;
1922 op_dst = op_src = op_opc = -1;
1923 mt_dst = -1;
1924 st_src = st_mop = -1;
1925 op_arg = NULL;
1926 i = 0;
1928 #define NEXT_INSN \
1929 do { if (i >= max_insns) goto fail; ctx->opcode = insns[i++]; } while (0)
1932 * Expect a load to begin the region.
1934 NEXT_INSN;
1935 switch (ctx->opcode & 0xf00f) {
1936 case 0x6000: /* mov.b @Rm,Rn */
1937 ld_mop = MO_SB;
1938 break;
1939 case 0x6001: /* mov.w @Rm,Rn */
1940 ld_mop = MO_TESW;
1941 break;
1942 case 0x6002: /* mov.l @Rm,Rn */
1943 ld_mop = MO_TESL;
1944 break;
1945 default:
1946 goto fail;
1948 ld_adr = B7_4;
1949 ld_dst = B11_8;
1950 if (ld_adr == ld_dst) {
1951 goto fail;
1953 /* Unless we see a mov, any two-operand operation must use ld_dst. */
1954 op_dst = ld_dst;
1957 * Expect an optional register move.
1959 NEXT_INSN;
1960 switch (ctx->opcode & 0xf00f) {
1961 case 0x6003: /* mov Rm,Rn */
1963 * Here we want to recognize ld_dst being saved for later consumption,
1964 * or for another input register being copied so that ld_dst need not
1965 * be clobbered during the operation.
1967 op_dst = B11_8;
1968 mv_src = B7_4;
1969 if (op_dst == ld_dst) {
1970 /* Overwriting the load output. */
1971 goto fail;
1973 if (mv_src != ld_dst) {
1974 /* Copying a new input; constrain op_src to match the load. */
1975 op_src = ld_dst;
1977 break;
1979 default:
1980 /* Put back and re-examine as operation. */
1981 --i;
1985 * Expect the operation.
1987 NEXT_INSN;
1988 switch (ctx->opcode & 0xf00f) {
1989 case 0x300c: /* add Rm,Rn */
1990 op_opc = INDEX_op_add_i32;
1991 goto do_reg_op;
1992 case 0x2009: /* and Rm,Rn */
1993 op_opc = INDEX_op_and_i32;
1994 goto do_reg_op;
1995 case 0x200a: /* xor Rm,Rn */
1996 op_opc = INDEX_op_xor_i32;
1997 goto do_reg_op;
1998 case 0x200b: /* or Rm,Rn */
1999 op_opc = INDEX_op_or_i32;
2000 do_reg_op:
2001 /* The operation register should be as expected, and the
2002 other input cannot depend on the load. */
2003 if (op_dst != B11_8) {
2004 goto fail;
2006 if (op_src < 0) {
2007 /* Unconstrainted input. */
2008 op_src = B7_4;
2009 } else if (op_src == B7_4) {
2010 /* Constrained input matched load. All operations are
2011 commutative; "swap" them by "moving" the load output
2012 to the (implicit) first argument and the move source
2013 to the (explicit) second argument. */
2014 op_src = mv_src;
2015 } else {
2016 goto fail;
2018 op_arg = REG(op_src);
2019 break;
2021 case 0x6007: /* not Rm,Rn */
2022 if (ld_dst != B7_4 || mv_src >= 0) {
2023 goto fail;
2025 op_dst = B11_8;
2026 op_opc = INDEX_op_xor_i32;
2027 op_arg = tcg_const_i32(-1);
2028 break;
2030 case 0x7000 ... 0x700f: /* add #imm,Rn */
2031 if (op_dst != B11_8 || mv_src >= 0) {
2032 goto fail;
2034 op_opc = INDEX_op_add_i32;
2035 op_arg = tcg_const_i32(B7_0s);
2036 break;
2038 case 0x3000: /* cmp/eq Rm,Rn */
2039 /* Looking for the middle of a compare-and-swap sequence,
2040 beginning with the compare. Operands can be either order,
2041 but with only one overlapping the load. */
2042 if ((ld_dst == B11_8) + (ld_dst == B7_4) != 1 || mv_src >= 0) {
2043 goto fail;
2045 op_opc = INDEX_op_setcond_i32; /* placeholder */
2046 op_src = (ld_dst == B11_8 ? B7_4 : B11_8);
2047 op_arg = REG(op_src);
2049 NEXT_INSN;
2050 switch (ctx->opcode & 0xff00) {
2051 case 0x8b00: /* bf label */
2052 case 0x8f00: /* bf/s label */
2053 if (pc + (i + 1 + B7_0s) * 2 != pc_end) {
2054 goto fail;
2056 if ((ctx->opcode & 0xff00) == 0x8b00) { /* bf label */
2057 break;
2059 /* We're looking to unconditionally modify Rn with the
2060 result of the comparison, within the delay slot of
2061 the branch. This is used by older gcc. */
2062 NEXT_INSN;
2063 if ((ctx->opcode & 0xf0ff) == 0x0029) { /* movt Rn */
2064 mt_dst = B11_8;
2065 } else {
2066 goto fail;
2068 break;
2070 default:
2071 goto fail;
2073 break;
2075 case 0x2008: /* tst Rm,Rn */
2076 /* Looking for a compare-and-swap against zero. */
2077 if (ld_dst != B11_8 || ld_dst != B7_4 || mv_src >= 0) {
2078 goto fail;
2080 op_opc = INDEX_op_setcond_i32;
2081 op_arg = tcg_const_i32(0);
2083 NEXT_INSN;
2084 if ((ctx->opcode & 0xff00) != 0x8900 /* bt label */
2085 || pc + (i + 1 + B7_0s) * 2 != pc_end) {
2086 goto fail;
2088 break;
2090 default:
2091 /* Put back and re-examine as store. */
2092 --i;
2096 * Expect the store.
2098 /* The store must be the last insn. */
2099 if (i != max_insns - 1) {
2100 goto fail;
2102 NEXT_INSN;
2103 switch (ctx->opcode & 0xf00f) {
2104 case 0x2000: /* mov.b Rm,@Rn */
2105 st_mop = MO_UB;
2106 break;
2107 case 0x2001: /* mov.w Rm,@Rn */
2108 st_mop = MO_UW;
2109 break;
2110 case 0x2002: /* mov.l Rm,@Rn */
2111 st_mop = MO_UL;
2112 break;
2113 default:
2114 goto fail;
2116 /* The store must match the load. */
2117 if (ld_adr != B11_8 || st_mop != (ld_mop & MO_SIZE)) {
2118 goto fail;
2120 st_src = B7_4;
2122 #undef NEXT_INSN
2125 * Emit the operation.
2127 switch (op_opc) {
2128 case -1:
2129 /* No operation found. Look for exchange pattern. */
2130 if (st_src == ld_dst || mv_src >= 0) {
2131 goto fail;
2133 tcg_gen_atomic_xchg_i32(REG(ld_dst), REG(ld_adr), REG(st_src),
2134 ctx->memidx, ld_mop);
2135 break;
2137 case INDEX_op_add_i32:
2138 if (op_dst != st_src) {
2139 goto fail;
2141 if (op_dst == ld_dst && st_mop == MO_UL) {
2142 tcg_gen_atomic_add_fetch_i32(REG(ld_dst), REG(ld_adr),
2143 op_arg, ctx->memidx, ld_mop);
2144 } else {
2145 tcg_gen_atomic_fetch_add_i32(REG(ld_dst), REG(ld_adr),
2146 op_arg, ctx->memidx, ld_mop);
2147 if (op_dst != ld_dst) {
2148 /* Note that mop sizes < 4 cannot use add_fetch
2149 because it won't carry into the higher bits. */
2150 tcg_gen_add_i32(REG(op_dst), REG(ld_dst), op_arg);
2153 break;
2155 case INDEX_op_and_i32:
2156 if (op_dst != st_src) {
2157 goto fail;
2159 if (op_dst == ld_dst) {
2160 tcg_gen_atomic_and_fetch_i32(REG(ld_dst), REG(ld_adr),
2161 op_arg, ctx->memidx, ld_mop);
2162 } else {
2163 tcg_gen_atomic_fetch_and_i32(REG(ld_dst), REG(ld_adr),
2164 op_arg, ctx->memidx, ld_mop);
2165 tcg_gen_and_i32(REG(op_dst), REG(ld_dst), op_arg);
2167 break;
2169 case INDEX_op_or_i32:
2170 if (op_dst != st_src) {
2171 goto fail;
2173 if (op_dst == ld_dst) {
2174 tcg_gen_atomic_or_fetch_i32(REG(ld_dst), REG(ld_adr),
2175 op_arg, ctx->memidx, ld_mop);
2176 } else {
2177 tcg_gen_atomic_fetch_or_i32(REG(ld_dst), REG(ld_adr),
2178 op_arg, ctx->memidx, ld_mop);
2179 tcg_gen_or_i32(REG(op_dst), REG(ld_dst), op_arg);
2181 break;
2183 case INDEX_op_xor_i32:
2184 if (op_dst != st_src) {
2185 goto fail;
2187 if (op_dst == ld_dst) {
2188 tcg_gen_atomic_xor_fetch_i32(REG(ld_dst), REG(ld_adr),
2189 op_arg, ctx->memidx, ld_mop);
2190 } else {
2191 tcg_gen_atomic_fetch_xor_i32(REG(ld_dst), REG(ld_adr),
2192 op_arg, ctx->memidx, ld_mop);
2193 tcg_gen_xor_i32(REG(op_dst), REG(ld_dst), op_arg);
2195 break;
2197 case INDEX_op_setcond_i32:
2198 if (st_src == ld_dst) {
2199 goto fail;
2201 tcg_gen_atomic_cmpxchg_i32(REG(ld_dst), REG(ld_adr), op_arg,
2202 REG(st_src), ctx->memidx, ld_mop);
2203 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(ld_dst), op_arg);
2204 if (mt_dst >= 0) {
2205 tcg_gen_mov_i32(REG(mt_dst), cpu_sr_t);
2207 break;
2209 default:
2210 g_assert_not_reached();
2213 /* If op_src is not a valid register, then op_arg was a constant. */
2214 if (op_src < 0 && op_arg) {
2215 tcg_temp_free_i32(op_arg);
2218 /* The entire region has been translated. */
2219 ctx->envflags &= ~GUSA_MASK;
2220 ctx->base.pc_next = pc_end;
2221 ctx->base.num_insns += max_insns - 1;
2222 return;
2224 fail:
2225 qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n",
2226 pc, pc_end);
2228 /* Restart with the EXCLUSIVE bit set, within a TB run via
2229 cpu_exec_step_atomic holding the exclusive lock. */
2230 ctx->envflags |= GUSA_EXCLUSIVE;
2231 gen_save_cpu_state(ctx, false);
2232 gen_helper_exclusive(cpu_env);
2233 ctx->base.is_jmp = DISAS_NORETURN;
2235 /* We're not executing an instruction, but we must report one for the
2236 purposes of accounting within the TB. We might as well report the
2237 entire region consumed via ctx->base.pc_next so that it's immediately
2238 available in the disassembly dump. */
2239 ctx->base.pc_next = pc_end;
2240 ctx->base.num_insns += max_insns - 1;
2242 #endif
2244 static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
2246 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2247 CPUSH4State *env = cs->env_ptr;
2248 uint32_t tbflags;
2249 int bound;
2251 ctx->tbflags = tbflags = ctx->base.tb->flags;
2252 ctx->envflags = tbflags & TB_FLAG_ENVFLAGS_MASK;
2253 ctx->memidx = (tbflags & (1u << SR_MD)) == 0 ? 1 : 0;
2254 /* We don't know if the delayed pc came from a dynamic or static branch,
2255 so assume it is a dynamic branch. */
2256 ctx->delayed_pc = -1; /* use delayed pc from env pointer */
2257 ctx->features = env->features;
2258 ctx->has_movcal = (tbflags & TB_FLAG_PENDING_MOVCA);
2259 ctx->gbank = ((tbflags & (1 << SR_MD)) &&
2260 (tbflags & (1 << SR_RB))) * 0x10;
2261 ctx->fbank = tbflags & FPSCR_FR ? 0x10 : 0;
2263 if (tbflags & GUSA_MASK) {
2264 uint32_t pc = ctx->base.pc_next;
2265 uint32_t pc_end = ctx->base.tb->cs_base;
2266 int backup = sextract32(ctx->tbflags, GUSA_SHIFT, 8);
2267 int max_insns = (pc_end - pc) / 2;
2269 if (pc != pc_end + backup || max_insns < 2) {
2270 /* This is a malformed gUSA region. Don't do anything special,
2271 since the interpreter is likely to get confused. */
2272 ctx->envflags &= ~GUSA_MASK;
2273 } else if (tbflags & GUSA_EXCLUSIVE) {
2274 /* Regardless of single-stepping or the end of the page,
2275 we must complete execution of the gUSA region while
2276 holding the exclusive lock. */
2277 ctx->base.max_insns = max_insns;
2278 return;
2282 /* Since the ISA is fixed-width, we can bound by the number
2283 of instructions remaining on the page. */
2284 bound = -(ctx->base.pc_next | TARGET_PAGE_MASK) / 2;
2285 ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
2288 static void sh4_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
2292 static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
2294 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2296 tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags);
2299 static bool sh4_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
2300 const CPUBreakpoint *bp)
2302 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2304 /* We have hit a breakpoint - make sure PC is up-to-date */
2305 gen_save_cpu_state(ctx, true);
2306 gen_helper_debug(cpu_env);
2307 ctx->base.is_jmp = DISAS_NORETURN;
2308 /* The address covered by the breakpoint must be included in
2309 [tb->pc, tb->pc + tb->size) in order to for it to be
2310 properly cleared -- thus we increment the PC here so that
2311 the logic setting tb->size below does the right thing. */
2312 ctx->base.pc_next += 2;
2313 return true;
2316 static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
2318 CPUSH4State *env = cs->env_ptr;
2319 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2321 #ifdef CONFIG_USER_ONLY
2322 if (unlikely(ctx->envflags & GUSA_MASK)
2323 && !(ctx->envflags & GUSA_EXCLUSIVE)) {
2324 /* We're in an gUSA region, and we have not already fallen
2325 back on using an exclusive region. Attempt to parse the
2326 region into a single supported atomic operation. Failure
2327 is handled within the parser by raising an exception to
2328 retry using an exclusive region. */
2329 decode_gusa(ctx, env);
2330 return;
2332 #endif
2334 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
2335 decode_opc(ctx);
2336 ctx->base.pc_next += 2;
2339 static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
2341 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2343 if (ctx->tbflags & GUSA_EXCLUSIVE) {
2344 /* Ending the region of exclusivity. Clear the bits. */
2345 ctx->envflags &= ~GUSA_MASK;
2348 switch (ctx->base.is_jmp) {
2349 case DISAS_STOP:
2350 gen_save_cpu_state(ctx, true);
2351 if (ctx->base.singlestep_enabled) {
2352 gen_helper_debug(cpu_env);
2353 } else {
2354 tcg_gen_exit_tb(NULL, 0);
2356 break;
2357 case DISAS_NEXT:
2358 case DISAS_TOO_MANY:
2359 gen_save_cpu_state(ctx, false);
2360 gen_goto_tb(ctx, 0, ctx->base.pc_next);
2361 break;
2362 case DISAS_NORETURN:
2363 break;
2364 default:
2365 g_assert_not_reached();
2369 static void sh4_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
2371 qemu_log("IN:\n"); /* , lookup_symbol(dcbase->pc_first)); */
2372 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
2375 static const TranslatorOps sh4_tr_ops = {
2376 .init_disas_context = sh4_tr_init_disas_context,
2377 .tb_start = sh4_tr_tb_start,
2378 .insn_start = sh4_tr_insn_start,
2379 .breakpoint_check = sh4_tr_breakpoint_check,
2380 .translate_insn = sh4_tr_translate_insn,
2381 .tb_stop = sh4_tr_tb_stop,
2382 .disas_log = sh4_tr_disas_log,
2385 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
2387 DisasContext ctx;
2389 translator_loop(&sh4_tr_ops, &ctx.base, cs, tb, max_insns);
2392 void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb,
2393 target_ulong *data)
2395 env->pc = data[0];
2396 env->flags = data[1];
2397 /* Theoretically delayed_pc should also be restored. In practice the
2398 branch instruction is re-executed after exception, so the delayed
2399 branch target will be recomputed. */