exec/memop: Adding signedness to quad definitions
[qemu.git] / target / sh4 / translate.c
blob43bc88b7b32b04c93643ea0df444bf71e9960fc5
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 "exec/log.h"
32 #include "qemu/qemu-print.h"
35 typedef struct DisasContext {
36 DisasContextBase base;
38 uint32_t tbflags; /* should stay unmodified during the TB translation */
39 uint32_t envflags; /* should stay in sync with env->flags using TCG ops */
40 int memidx;
41 int gbank;
42 int fbank;
43 uint32_t delayed_pc;
44 uint32_t features;
46 uint16_t opcode;
48 bool has_movcal;
49 } DisasContext;
51 #if defined(CONFIG_USER_ONLY)
52 #define IS_USER(ctx) 1
53 #define UNALIGN(C) (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN)
54 #else
55 #define IS_USER(ctx) (!(ctx->tbflags & (1u << SR_MD)))
56 #define UNALIGN(C) 0
57 #endif
59 /* Target-specific values for ctx->base.is_jmp. */
60 /* We want to exit back to the cpu loop for some reason.
61 Usually this is to recognize interrupts immediately. */
62 #define DISAS_STOP DISAS_TARGET_0
64 /* global register indexes */
65 static TCGv cpu_gregs[32];
66 static TCGv cpu_sr, cpu_sr_m, cpu_sr_q, cpu_sr_t;
67 static TCGv cpu_pc, cpu_ssr, cpu_spc, cpu_gbr;
68 static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl;
69 static TCGv cpu_pr, cpu_fpscr, cpu_fpul;
70 static TCGv cpu_lock_addr, cpu_lock_value;
71 static TCGv cpu_fregs[32];
73 /* internal register indexes */
74 static TCGv cpu_flags, cpu_delayed_pc, cpu_delayed_cond;
76 #include "exec/gen-icount.h"
78 void sh4_translate_init(void)
80 int i;
81 static const char * const gregnames[24] = {
82 "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
83 "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
84 "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
85 "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
86 "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
88 static const char * const fregnames[32] = {
89 "FPR0_BANK0", "FPR1_BANK0", "FPR2_BANK0", "FPR3_BANK0",
90 "FPR4_BANK0", "FPR5_BANK0", "FPR6_BANK0", "FPR7_BANK0",
91 "FPR8_BANK0", "FPR9_BANK0", "FPR10_BANK0", "FPR11_BANK0",
92 "FPR12_BANK0", "FPR13_BANK0", "FPR14_BANK0", "FPR15_BANK0",
93 "FPR0_BANK1", "FPR1_BANK1", "FPR2_BANK1", "FPR3_BANK1",
94 "FPR4_BANK1", "FPR5_BANK1", "FPR6_BANK1", "FPR7_BANK1",
95 "FPR8_BANK1", "FPR9_BANK1", "FPR10_BANK1", "FPR11_BANK1",
96 "FPR12_BANK1", "FPR13_BANK1", "FPR14_BANK1", "FPR15_BANK1",
99 for (i = 0; i < 24; i++) {
100 cpu_gregs[i] = tcg_global_mem_new_i32(cpu_env,
101 offsetof(CPUSH4State, gregs[i]),
102 gregnames[i]);
104 memcpy(cpu_gregs + 24, cpu_gregs + 8, 8 * sizeof(TCGv));
106 cpu_pc = tcg_global_mem_new_i32(cpu_env,
107 offsetof(CPUSH4State, pc), "PC");
108 cpu_sr = tcg_global_mem_new_i32(cpu_env,
109 offsetof(CPUSH4State, sr), "SR");
110 cpu_sr_m = tcg_global_mem_new_i32(cpu_env,
111 offsetof(CPUSH4State, sr_m), "SR_M");
112 cpu_sr_q = tcg_global_mem_new_i32(cpu_env,
113 offsetof(CPUSH4State, sr_q), "SR_Q");
114 cpu_sr_t = tcg_global_mem_new_i32(cpu_env,
115 offsetof(CPUSH4State, sr_t), "SR_T");
116 cpu_ssr = tcg_global_mem_new_i32(cpu_env,
117 offsetof(CPUSH4State, ssr), "SSR");
118 cpu_spc = tcg_global_mem_new_i32(cpu_env,
119 offsetof(CPUSH4State, spc), "SPC");
120 cpu_gbr = tcg_global_mem_new_i32(cpu_env,
121 offsetof(CPUSH4State, gbr), "GBR");
122 cpu_vbr = tcg_global_mem_new_i32(cpu_env,
123 offsetof(CPUSH4State, vbr), "VBR");
124 cpu_sgr = tcg_global_mem_new_i32(cpu_env,
125 offsetof(CPUSH4State, sgr), "SGR");
126 cpu_dbr = tcg_global_mem_new_i32(cpu_env,
127 offsetof(CPUSH4State, dbr), "DBR");
128 cpu_mach = tcg_global_mem_new_i32(cpu_env,
129 offsetof(CPUSH4State, mach), "MACH");
130 cpu_macl = tcg_global_mem_new_i32(cpu_env,
131 offsetof(CPUSH4State, macl), "MACL");
132 cpu_pr = tcg_global_mem_new_i32(cpu_env,
133 offsetof(CPUSH4State, pr), "PR");
134 cpu_fpscr = tcg_global_mem_new_i32(cpu_env,
135 offsetof(CPUSH4State, fpscr), "FPSCR");
136 cpu_fpul = tcg_global_mem_new_i32(cpu_env,
137 offsetof(CPUSH4State, fpul), "FPUL");
139 cpu_flags = tcg_global_mem_new_i32(cpu_env,
140 offsetof(CPUSH4State, flags), "_flags_");
141 cpu_delayed_pc = tcg_global_mem_new_i32(cpu_env,
142 offsetof(CPUSH4State, delayed_pc),
143 "_delayed_pc_");
144 cpu_delayed_cond = tcg_global_mem_new_i32(cpu_env,
145 offsetof(CPUSH4State,
146 delayed_cond),
147 "_delayed_cond_");
148 cpu_lock_addr = tcg_global_mem_new_i32(cpu_env,
149 offsetof(CPUSH4State, lock_addr),
150 "_lock_addr_");
151 cpu_lock_value = tcg_global_mem_new_i32(cpu_env,
152 offsetof(CPUSH4State, lock_value),
153 "_lock_value_");
155 for (i = 0; i < 32; i++)
156 cpu_fregs[i] = tcg_global_mem_new_i32(cpu_env,
157 offsetof(CPUSH4State, fregs[i]),
158 fregnames[i]);
161 void superh_cpu_dump_state(CPUState *cs, FILE *f, int flags)
163 SuperHCPU *cpu = SUPERH_CPU(cs);
164 CPUSH4State *env = &cpu->env;
165 int i;
167 qemu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
168 env->pc, cpu_read_sr(env), env->pr, env->fpscr);
169 qemu_fprintf(f, "spc=0x%08x ssr=0x%08x gbr=0x%08x vbr=0x%08x\n",
170 env->spc, env->ssr, env->gbr, env->vbr);
171 qemu_fprintf(f, "sgr=0x%08x dbr=0x%08x delayed_pc=0x%08x fpul=0x%08x\n",
172 env->sgr, env->dbr, env->delayed_pc, env->fpul);
173 for (i = 0; i < 24; i += 4) {
174 qemu_printf("r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
175 i, env->gregs[i], i + 1, env->gregs[i + 1],
176 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
178 if (env->flags & DELAY_SLOT) {
179 qemu_printf("in delay slot (delayed_pc=0x%08x)\n",
180 env->delayed_pc);
181 } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
182 qemu_printf("in conditional delay slot (delayed_pc=0x%08x)\n",
183 env->delayed_pc);
184 } else if (env->flags & DELAY_SLOT_RTE) {
185 qemu_fprintf(f, "in rte delay slot (delayed_pc=0x%08x)\n",
186 env->delayed_pc);
190 static void gen_read_sr(TCGv dst)
192 TCGv t0 = tcg_temp_new();
193 tcg_gen_shli_i32(t0, cpu_sr_q, SR_Q);
194 tcg_gen_or_i32(dst, dst, t0);
195 tcg_gen_shli_i32(t0, cpu_sr_m, SR_M);
196 tcg_gen_or_i32(dst, dst, t0);
197 tcg_gen_shli_i32(t0, cpu_sr_t, SR_T);
198 tcg_gen_or_i32(dst, cpu_sr, t0);
199 tcg_temp_free_i32(t0);
202 static void gen_write_sr(TCGv src)
204 tcg_gen_andi_i32(cpu_sr, src,
205 ~((1u << SR_Q) | (1u << SR_M) | (1u << SR_T)));
206 tcg_gen_extract_i32(cpu_sr_q, src, SR_Q, 1);
207 tcg_gen_extract_i32(cpu_sr_m, src, SR_M, 1);
208 tcg_gen_extract_i32(cpu_sr_t, src, SR_T, 1);
211 static inline void gen_save_cpu_state(DisasContext *ctx, bool save_pc)
213 if (save_pc) {
214 tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
216 if (ctx->delayed_pc != (uint32_t) -1) {
217 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
219 if ((ctx->tbflags & TB_FLAG_ENVFLAGS_MASK) != ctx->envflags) {
220 tcg_gen_movi_i32(cpu_flags, ctx->envflags);
224 static inline bool use_exit_tb(DisasContext *ctx)
226 return (ctx->tbflags & GUSA_EXCLUSIVE) != 0;
229 static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
231 if (use_exit_tb(ctx)) {
232 return false;
234 return translator_use_goto_tb(&ctx->base, dest);
237 static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
239 if (use_goto_tb(ctx, dest)) {
240 tcg_gen_goto_tb(n);
241 tcg_gen_movi_i32(cpu_pc, dest);
242 tcg_gen_exit_tb(ctx->base.tb, n);
243 } else {
244 tcg_gen_movi_i32(cpu_pc, dest);
245 if (use_exit_tb(ctx)) {
246 tcg_gen_exit_tb(NULL, 0);
247 } else {
248 tcg_gen_lookup_and_goto_ptr();
251 ctx->base.is_jmp = DISAS_NORETURN;
254 static void gen_jump(DisasContext * ctx)
256 if (ctx->delayed_pc == -1) {
257 /* Target is not statically known, it comes necessarily from a
258 delayed jump as immediate jump are conditinal jumps */
259 tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc);
260 tcg_gen_discard_i32(cpu_delayed_pc);
261 if (use_exit_tb(ctx)) {
262 tcg_gen_exit_tb(NULL, 0);
263 } else {
264 tcg_gen_lookup_and_goto_ptr();
266 ctx->base.is_jmp = DISAS_NORETURN;
267 } else {
268 gen_goto_tb(ctx, 0, ctx->delayed_pc);
272 /* Immediate conditional jump (bt or bf) */
273 static void gen_conditional_jump(DisasContext *ctx, target_ulong dest,
274 bool jump_if_true)
276 TCGLabel *l1 = gen_new_label();
277 TCGCond cond_not_taken = jump_if_true ? TCG_COND_EQ : TCG_COND_NE;
279 if (ctx->tbflags & GUSA_EXCLUSIVE) {
280 /* When in an exclusive region, we must continue to the end.
281 Therefore, exit the region on a taken branch, but otherwise
282 fall through to the next instruction. */
283 tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
284 tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK);
285 /* Note that this won't actually use a goto_tb opcode because we
286 disallow it in use_goto_tb, but it handles exit + singlestep. */
287 gen_goto_tb(ctx, 0, dest);
288 gen_set_label(l1);
289 ctx->base.is_jmp = DISAS_NEXT;
290 return;
293 gen_save_cpu_state(ctx, false);
294 tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
295 gen_goto_tb(ctx, 0, dest);
296 gen_set_label(l1);
297 gen_goto_tb(ctx, 1, ctx->base.pc_next + 2);
298 ctx->base.is_jmp = DISAS_NORETURN;
301 /* Delayed conditional jump (bt or bf) */
302 static void gen_delayed_conditional_jump(DisasContext * ctx)
304 TCGLabel *l1 = gen_new_label();
305 TCGv ds = tcg_temp_new();
307 tcg_gen_mov_i32(ds, cpu_delayed_cond);
308 tcg_gen_discard_i32(cpu_delayed_cond);
310 if (ctx->tbflags & GUSA_EXCLUSIVE) {
311 /* When in an exclusive region, we must continue to the end.
312 Therefore, exit the region on a taken branch, but otherwise
313 fall through to the next instruction. */
314 tcg_gen_brcondi_i32(TCG_COND_EQ, ds, 0, l1);
316 /* Leave the gUSA region. */
317 tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK);
318 gen_jump(ctx);
320 gen_set_label(l1);
321 ctx->base.is_jmp = DISAS_NEXT;
322 return;
325 tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
326 gen_goto_tb(ctx, 1, ctx->base.pc_next + 2);
327 gen_set_label(l1);
328 gen_jump(ctx);
331 static inline void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
333 /* We have already signaled illegal instruction for odd Dr. */
334 tcg_debug_assert((reg & 1) == 0);
335 reg ^= ctx->fbank;
336 tcg_gen_concat_i32_i64(t, cpu_fregs[reg + 1], cpu_fregs[reg]);
339 static inline void gen_store_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_extr_i64_i32(cpu_fregs[reg + 1], cpu_fregs[reg], t);
347 #define B3_0 (ctx->opcode & 0xf)
348 #define B6_4 ((ctx->opcode >> 4) & 0x7)
349 #define B7_4 ((ctx->opcode >> 4) & 0xf)
350 #define B7_0 (ctx->opcode & 0xff)
351 #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
352 #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
353 (ctx->opcode & 0xfff))
354 #define B11_8 ((ctx->opcode >> 8) & 0xf)
355 #define B15_12 ((ctx->opcode >> 12) & 0xf)
357 #define REG(x) cpu_gregs[(x) ^ ctx->gbank]
358 #define ALTREG(x) cpu_gregs[(x) ^ ctx->gbank ^ 0x10]
359 #define FREG(x) cpu_fregs[(x) ^ ctx->fbank]
361 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
363 #define CHECK_NOT_DELAY_SLOT \
364 if (ctx->envflags & DELAY_SLOT_MASK) { \
365 goto do_illegal_slot; \
368 #define CHECK_PRIVILEGED \
369 if (IS_USER(ctx)) { \
370 goto do_illegal; \
373 #define CHECK_FPU_ENABLED \
374 if (ctx->tbflags & (1u << SR_FD)) { \
375 goto do_fpu_disabled; \
378 #define CHECK_FPSCR_PR_0 \
379 if (ctx->tbflags & FPSCR_PR) { \
380 goto do_illegal; \
383 #define CHECK_FPSCR_PR_1 \
384 if (!(ctx->tbflags & FPSCR_PR)) { \
385 goto do_illegal; \
388 #define CHECK_SH4A \
389 if (!(ctx->features & SH_FEATURE_SH4A)) { \
390 goto do_illegal; \
393 static void _decode_opc(DisasContext * ctx)
395 /* This code tries to make movcal emulation sufficiently
396 accurate for Linux purposes. This instruction writes
397 memory, and prior to that, always allocates a cache line.
398 It is used in two contexts:
399 - in memcpy, where data is copied in blocks, the first write
400 of to a block uses movca.l for performance.
401 - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used
402 to flush the cache. Here, the data written by movcal.l is never
403 written to memory, and the data written is just bogus.
405 To simulate this, we simulate movcal.l, we store the value to memory,
406 but we also remember the previous content. If we see ocbi, we check
407 if movcal.l for that address was done previously. If so, the write should
408 not have hit the memory, so we restore the previous content.
409 When we see an instruction that is neither movca.l
410 nor ocbi, the previous content is discarded.
412 To optimize, we only try to flush stores when we're at the start of
413 TB, or if we already saw movca.l in this TB and did not flush stores
414 yet. */
415 if (ctx->has_movcal)
417 int opcode = ctx->opcode & 0xf0ff;
418 if (opcode != 0x0093 /* ocbi */
419 && opcode != 0x00c3 /* movca.l */)
421 gen_helper_discard_movcal_backup(cpu_env);
422 ctx->has_movcal = 0;
426 #if 0
427 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
428 #endif
430 switch (ctx->opcode) {
431 case 0x0019: /* div0u */
432 tcg_gen_movi_i32(cpu_sr_m, 0);
433 tcg_gen_movi_i32(cpu_sr_q, 0);
434 tcg_gen_movi_i32(cpu_sr_t, 0);
435 return;
436 case 0x000b: /* rts */
437 CHECK_NOT_DELAY_SLOT
438 tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
439 ctx->envflags |= DELAY_SLOT;
440 ctx->delayed_pc = (uint32_t) - 1;
441 return;
442 case 0x0028: /* clrmac */
443 tcg_gen_movi_i32(cpu_mach, 0);
444 tcg_gen_movi_i32(cpu_macl, 0);
445 return;
446 case 0x0048: /* clrs */
447 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(1u << SR_S));
448 return;
449 case 0x0008: /* clrt */
450 tcg_gen_movi_i32(cpu_sr_t, 0);
451 return;
452 case 0x0038: /* ldtlb */
453 CHECK_PRIVILEGED
454 gen_helper_ldtlb(cpu_env);
455 return;
456 case 0x002b: /* rte */
457 CHECK_PRIVILEGED
458 CHECK_NOT_DELAY_SLOT
459 gen_write_sr(cpu_ssr);
460 tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
461 ctx->envflags |= DELAY_SLOT_RTE;
462 ctx->delayed_pc = (uint32_t) - 1;
463 ctx->base.is_jmp = DISAS_STOP;
464 return;
465 case 0x0058: /* sets */
466 tcg_gen_ori_i32(cpu_sr, cpu_sr, (1u << SR_S));
467 return;
468 case 0x0018: /* sett */
469 tcg_gen_movi_i32(cpu_sr_t, 1);
470 return;
471 case 0xfbfd: /* frchg */
472 CHECK_FPSCR_PR_0
473 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
474 ctx->base.is_jmp = DISAS_STOP;
475 return;
476 case 0xf3fd: /* fschg */
477 CHECK_FPSCR_PR_0
478 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ);
479 ctx->base.is_jmp = DISAS_STOP;
480 return;
481 case 0xf7fd: /* fpchg */
482 CHECK_SH4A
483 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_PR);
484 ctx->base.is_jmp = DISAS_STOP;
485 return;
486 case 0x0009: /* nop */
487 return;
488 case 0x001b: /* sleep */
489 CHECK_PRIVILEGED
490 tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next + 2);
491 gen_helper_sleep(cpu_env);
492 return;
495 switch (ctx->opcode & 0xf000) {
496 case 0x1000: /* mov.l Rm,@(disp,Rn) */
498 TCGv addr = tcg_temp_new();
499 tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
500 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
501 MO_TEUL | UNALIGN(ctx));
502 tcg_temp_free(addr);
504 return;
505 case 0x5000: /* mov.l @(disp,Rm),Rn */
507 TCGv addr = tcg_temp_new();
508 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
509 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
510 MO_TESL | UNALIGN(ctx));
511 tcg_temp_free(addr);
513 return;
514 case 0xe000: /* mov #imm,Rn */
515 #ifdef CONFIG_USER_ONLY
516 /* Detect the start of a gUSA region. If so, update envflags
517 and end the TB. This will allow us to see the end of the
518 region (stored in R0) in the next TB. */
519 if (B11_8 == 15 && B7_0s < 0 &&
520 (tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
521 ctx->envflags = deposit32(ctx->envflags, GUSA_SHIFT, 8, B7_0s);
522 ctx->base.is_jmp = DISAS_STOP;
524 #endif
525 tcg_gen_movi_i32(REG(B11_8), B7_0s);
526 return;
527 case 0x9000: /* mov.w @(disp,PC),Rn */
529 TCGv addr = tcg_const_i32(ctx->base.pc_next + 4 + B7_0 * 2);
530 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW);
531 tcg_temp_free(addr);
533 return;
534 case 0xd000: /* mov.l @(disp,PC),Rn */
536 TCGv addr = tcg_const_i32((ctx->base.pc_next + 4 + B7_0 * 4) & ~3);
537 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
538 tcg_temp_free(addr);
540 return;
541 case 0x7000: /* add #imm,Rn */
542 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s);
543 return;
544 case 0xa000: /* bra disp */
545 CHECK_NOT_DELAY_SLOT
546 ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2;
547 ctx->envflags |= DELAY_SLOT;
548 return;
549 case 0xb000: /* bsr disp */
550 CHECK_NOT_DELAY_SLOT
551 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
552 ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2;
553 ctx->envflags |= DELAY_SLOT;
554 return;
557 switch (ctx->opcode & 0xf00f) {
558 case 0x6003: /* mov Rm,Rn */
559 tcg_gen_mov_i32(REG(B11_8), REG(B7_4));
560 return;
561 case 0x2000: /* mov.b Rm,@Rn */
562 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB);
563 return;
564 case 0x2001: /* mov.w Rm,@Rn */
565 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx,
566 MO_TEUW | UNALIGN(ctx));
567 return;
568 case 0x2002: /* mov.l Rm,@Rn */
569 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx,
570 MO_TEUL | UNALIGN(ctx));
571 return;
572 case 0x6000: /* mov.b @Rm,Rn */
573 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
574 return;
575 case 0x6001: /* mov.w @Rm,Rn */
576 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx,
577 MO_TESW | UNALIGN(ctx));
578 return;
579 case 0x6002: /* mov.l @Rm,Rn */
580 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx,
581 MO_TESL | UNALIGN(ctx));
582 return;
583 case 0x2004: /* mov.b Rm,@-Rn */
585 TCGv addr = tcg_temp_new();
586 tcg_gen_subi_i32(addr, REG(B11_8), 1);
587 /* might cause re-execution */
588 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB);
589 tcg_gen_mov_i32(REG(B11_8), addr); /* modify register status */
590 tcg_temp_free(addr);
592 return;
593 case 0x2005: /* mov.w Rm,@-Rn */
595 TCGv addr = tcg_temp_new();
596 tcg_gen_subi_i32(addr, REG(B11_8), 2);
597 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
598 MO_TEUW | UNALIGN(ctx));
599 tcg_gen_mov_i32(REG(B11_8), addr);
600 tcg_temp_free(addr);
602 return;
603 case 0x2006: /* mov.l Rm,@-Rn */
605 TCGv addr = tcg_temp_new();
606 tcg_gen_subi_i32(addr, REG(B11_8), 4);
607 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
608 MO_TEUL | UNALIGN(ctx));
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,
620 MO_TESW | UNALIGN(ctx));
621 if ( B11_8 != B7_4 )
622 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
623 return;
624 case 0x6006: /* mov.l @Rm+,Rn */
625 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx,
626 MO_TESL | UNALIGN(ctx));
627 if ( B11_8 != B7_4 )
628 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
629 return;
630 case 0x0004: /* mov.b Rm,@(R0,Rn) */
632 TCGv addr = tcg_temp_new();
633 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
634 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB);
635 tcg_temp_free(addr);
637 return;
638 case 0x0005: /* mov.w Rm,@(R0,Rn) */
640 TCGv addr = tcg_temp_new();
641 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
642 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
643 MO_TEUW | UNALIGN(ctx));
644 tcg_temp_free(addr);
646 return;
647 case 0x0006: /* mov.l Rm,@(R0,Rn) */
649 TCGv addr = tcg_temp_new();
650 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
651 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
652 MO_TEUL | UNALIGN(ctx));
653 tcg_temp_free(addr);
655 return;
656 case 0x000c: /* mov.b @(R0,Rm),Rn */
658 TCGv addr = tcg_temp_new();
659 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
660 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_SB);
661 tcg_temp_free(addr);
663 return;
664 case 0x000d: /* mov.w @(R0,Rm),Rn */
666 TCGv addr = tcg_temp_new();
667 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
668 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
669 MO_TESW | UNALIGN(ctx));
670 tcg_temp_free(addr);
672 return;
673 case 0x000e: /* mov.l @(R0,Rm),Rn */
675 TCGv addr = tcg_temp_new();
676 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
677 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
678 MO_TESL | UNALIGN(ctx));
679 tcg_temp_free(addr);
681 return;
682 case 0x6008: /* swap.b Rm,Rn */
684 TCGv low = tcg_temp_new();
685 tcg_gen_bswap16_i32(low, REG(B7_4), 0);
686 tcg_gen_deposit_i32(REG(B11_8), REG(B7_4), low, 0, 16);
687 tcg_temp_free(low);
689 return;
690 case 0x6009: /* swap.w Rm,Rn */
691 tcg_gen_rotli_i32(REG(B11_8), REG(B7_4), 16);
692 return;
693 case 0x200d: /* xtrct Rm,Rn */
695 TCGv high, low;
696 high = tcg_temp_new();
697 tcg_gen_shli_i32(high, REG(B7_4), 16);
698 low = tcg_temp_new();
699 tcg_gen_shri_i32(low, REG(B11_8), 16);
700 tcg_gen_or_i32(REG(B11_8), high, low);
701 tcg_temp_free(low);
702 tcg_temp_free(high);
704 return;
705 case 0x300c: /* add Rm,Rn */
706 tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4));
707 return;
708 case 0x300e: /* addc Rm,Rn */
710 TCGv t0, t1;
711 t0 = tcg_const_tl(0);
712 t1 = tcg_temp_new();
713 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0);
714 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t,
715 REG(B11_8), t0, t1, cpu_sr_t);
716 tcg_temp_free(t0);
717 tcg_temp_free(t1);
719 return;
720 case 0x300f: /* addv Rm,Rn */
722 TCGv t0, t1, t2;
723 t0 = tcg_temp_new();
724 tcg_gen_add_i32(t0, REG(B7_4), REG(B11_8));
725 t1 = tcg_temp_new();
726 tcg_gen_xor_i32(t1, t0, REG(B11_8));
727 t2 = tcg_temp_new();
728 tcg_gen_xor_i32(t2, REG(B7_4), REG(B11_8));
729 tcg_gen_andc_i32(cpu_sr_t, t1, t2);
730 tcg_temp_free(t2);
731 tcg_gen_shri_i32(cpu_sr_t, cpu_sr_t, 31);
732 tcg_temp_free(t1);
733 tcg_gen_mov_i32(REG(B7_4), t0);
734 tcg_temp_free(t0);
736 return;
737 case 0x2009: /* and Rm,Rn */
738 tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4));
739 return;
740 case 0x3000: /* cmp/eq Rm,Rn */
741 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), REG(B7_4));
742 return;
743 case 0x3003: /* cmp/ge Rm,Rn */
744 tcg_gen_setcond_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), REG(B7_4));
745 return;
746 case 0x3007: /* cmp/gt Rm,Rn */
747 tcg_gen_setcond_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), REG(B7_4));
748 return;
749 case 0x3006: /* cmp/hi Rm,Rn */
750 tcg_gen_setcond_i32(TCG_COND_GTU, cpu_sr_t, REG(B11_8), REG(B7_4));
751 return;
752 case 0x3002: /* cmp/hs Rm,Rn */
753 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_sr_t, REG(B11_8), REG(B7_4));
754 return;
755 case 0x200c: /* cmp/str Rm,Rn */
757 TCGv cmp1 = tcg_temp_new();
758 TCGv cmp2 = tcg_temp_new();
759 tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8));
760 tcg_gen_subi_i32(cmp1, cmp2, 0x01010101);
761 tcg_gen_andc_i32(cmp1, cmp1, cmp2);
762 tcg_gen_andi_i32(cmp1, cmp1, 0x80808080);
763 tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0);
764 tcg_temp_free(cmp2);
765 tcg_temp_free(cmp1);
767 return;
768 case 0x2007: /* div0s Rm,Rn */
769 tcg_gen_shri_i32(cpu_sr_q, REG(B11_8), 31); /* SR_Q */
770 tcg_gen_shri_i32(cpu_sr_m, REG(B7_4), 31); /* SR_M */
771 tcg_gen_xor_i32(cpu_sr_t, cpu_sr_q, cpu_sr_m); /* SR_T */
772 return;
773 case 0x3004: /* div1 Rm,Rn */
775 TCGv t0 = tcg_temp_new();
776 TCGv t1 = tcg_temp_new();
777 TCGv t2 = tcg_temp_new();
778 TCGv zero = tcg_const_i32(0);
780 /* shift left arg1, saving the bit being pushed out and inserting
781 T on the right */
782 tcg_gen_shri_i32(t0, REG(B11_8), 31);
783 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
784 tcg_gen_or_i32(REG(B11_8), REG(B11_8), cpu_sr_t);
786 /* Add or subtract arg0 from arg1 depending if Q == M. To avoid
787 using 64-bit temps, we compute arg0's high part from q ^ m, so
788 that it is 0x00000000 when adding the value or 0xffffffff when
789 subtracting it. */
790 tcg_gen_xor_i32(t1, cpu_sr_q, cpu_sr_m);
791 tcg_gen_subi_i32(t1, t1, 1);
792 tcg_gen_neg_i32(t2, REG(B7_4));
793 tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, zero, REG(B7_4), t2);
794 tcg_gen_add2_i32(REG(B11_8), t1, REG(B11_8), zero, t2, t1);
796 /* compute T and Q depending on carry */
797 tcg_gen_andi_i32(t1, t1, 1);
798 tcg_gen_xor_i32(t1, t1, t0);
799 tcg_gen_xori_i32(cpu_sr_t, t1, 1);
800 tcg_gen_xor_i32(cpu_sr_q, cpu_sr_m, t1);
802 tcg_temp_free(zero);
803 tcg_temp_free(t2);
804 tcg_temp_free(t1);
805 tcg_temp_free(t0);
807 return;
808 case 0x300d: /* dmuls.l Rm,Rn */
809 tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
810 return;
811 case 0x3005: /* dmulu.l Rm,Rn */
812 tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
813 return;
814 case 0x600e: /* exts.b Rm,Rn */
815 tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4));
816 return;
817 case 0x600f: /* exts.w Rm,Rn */
818 tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4));
819 return;
820 case 0x600c: /* extu.b Rm,Rn */
821 tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4));
822 return;
823 case 0x600d: /* extu.w Rm,Rn */
824 tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4));
825 return;
826 case 0x000f: /* mac.l @Rm+,@Rn+ */
828 TCGv arg0, arg1;
829 arg0 = tcg_temp_new();
830 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL);
831 arg1 = tcg_temp_new();
832 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL);
833 gen_helper_macl(cpu_env, arg0, arg1);
834 tcg_temp_free(arg1);
835 tcg_temp_free(arg0);
836 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
837 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
839 return;
840 case 0x400f: /* mac.w @Rm+,@Rn+ */
842 TCGv arg0, arg1;
843 arg0 = tcg_temp_new();
844 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL);
845 arg1 = tcg_temp_new();
846 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL);
847 gen_helper_macw(cpu_env, arg0, arg1);
848 tcg_temp_free(arg1);
849 tcg_temp_free(arg0);
850 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2);
851 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
853 return;
854 case 0x0007: /* mul.l Rm,Rn */
855 tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8));
856 return;
857 case 0x200f: /* muls.w Rm,Rn */
859 TCGv arg0, arg1;
860 arg0 = tcg_temp_new();
861 tcg_gen_ext16s_i32(arg0, REG(B7_4));
862 arg1 = tcg_temp_new();
863 tcg_gen_ext16s_i32(arg1, REG(B11_8));
864 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
865 tcg_temp_free(arg1);
866 tcg_temp_free(arg0);
868 return;
869 case 0x200e: /* mulu.w Rm,Rn */
871 TCGv arg0, arg1;
872 arg0 = tcg_temp_new();
873 tcg_gen_ext16u_i32(arg0, REG(B7_4));
874 arg1 = tcg_temp_new();
875 tcg_gen_ext16u_i32(arg1, REG(B11_8));
876 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
877 tcg_temp_free(arg1);
878 tcg_temp_free(arg0);
880 return;
881 case 0x600b: /* neg Rm,Rn */
882 tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
883 return;
884 case 0x600a: /* negc Rm,Rn */
886 TCGv t0 = tcg_const_i32(0);
887 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t,
888 REG(B7_4), t0, cpu_sr_t, t0);
889 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
890 t0, t0, REG(B11_8), cpu_sr_t);
891 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
892 tcg_temp_free(t0);
894 return;
895 case 0x6007: /* not Rm,Rn */
896 tcg_gen_not_i32(REG(B11_8), REG(B7_4));
897 return;
898 case 0x200b: /* or Rm,Rn */
899 tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4));
900 return;
901 case 0x400c: /* shad Rm,Rn */
903 TCGv t0 = tcg_temp_new();
904 TCGv t1 = tcg_temp_new();
905 TCGv t2 = tcg_temp_new();
907 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
909 /* positive case: shift to the left */
910 tcg_gen_shl_i32(t1, REG(B11_8), t0);
912 /* negative case: shift to the right in two steps to
913 correctly handle the -32 case */
914 tcg_gen_xori_i32(t0, t0, 0x1f);
915 tcg_gen_sar_i32(t2, REG(B11_8), t0);
916 tcg_gen_sari_i32(t2, t2, 1);
918 /* select between the two cases */
919 tcg_gen_movi_i32(t0, 0);
920 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
922 tcg_temp_free(t0);
923 tcg_temp_free(t1);
924 tcg_temp_free(t2);
926 return;
927 case 0x400d: /* shld Rm,Rn */
929 TCGv t0 = tcg_temp_new();
930 TCGv t1 = tcg_temp_new();
931 TCGv t2 = tcg_temp_new();
933 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
935 /* positive case: shift to the left */
936 tcg_gen_shl_i32(t1, REG(B11_8), t0);
938 /* negative case: shift to the right in two steps to
939 correctly handle the -32 case */
940 tcg_gen_xori_i32(t0, t0, 0x1f);
941 tcg_gen_shr_i32(t2, REG(B11_8), t0);
942 tcg_gen_shri_i32(t2, t2, 1);
944 /* select between the two cases */
945 tcg_gen_movi_i32(t0, 0);
946 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
948 tcg_temp_free(t0);
949 tcg_temp_free(t1);
950 tcg_temp_free(t2);
952 return;
953 case 0x3008: /* sub Rm,Rn */
954 tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4));
955 return;
956 case 0x300a: /* subc Rm,Rn */
958 TCGv t0, t1;
959 t0 = tcg_const_tl(0);
960 t1 = tcg_temp_new();
961 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0);
962 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
963 REG(B11_8), t0, t1, cpu_sr_t);
964 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
965 tcg_temp_free(t0);
966 tcg_temp_free(t1);
968 return;
969 case 0x300b: /* subv Rm,Rn */
971 TCGv t0, t1, t2;
972 t0 = tcg_temp_new();
973 tcg_gen_sub_i32(t0, REG(B11_8), REG(B7_4));
974 t1 = tcg_temp_new();
975 tcg_gen_xor_i32(t1, t0, REG(B7_4));
976 t2 = tcg_temp_new();
977 tcg_gen_xor_i32(t2, REG(B11_8), REG(B7_4));
978 tcg_gen_and_i32(t1, t1, t2);
979 tcg_temp_free(t2);
980 tcg_gen_shri_i32(cpu_sr_t, t1, 31);
981 tcg_temp_free(t1);
982 tcg_gen_mov_i32(REG(B11_8), t0);
983 tcg_temp_free(t0);
985 return;
986 case 0x2008: /* tst Rm,Rn */
988 TCGv val = tcg_temp_new();
989 tcg_gen_and_i32(val, REG(B7_4), REG(B11_8));
990 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
991 tcg_temp_free(val);
993 return;
994 case 0x200a: /* xor Rm,Rn */
995 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4));
996 return;
997 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
998 CHECK_FPU_ENABLED
999 if (ctx->tbflags & FPSCR_SZ) {
1000 int xsrc = XHACK(B7_4);
1001 int xdst = XHACK(B11_8);
1002 tcg_gen_mov_i32(FREG(xdst), FREG(xsrc));
1003 tcg_gen_mov_i32(FREG(xdst + 1), FREG(xsrc + 1));
1004 } else {
1005 tcg_gen_mov_i32(FREG(B11_8), FREG(B7_4));
1007 return;
1008 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
1009 CHECK_FPU_ENABLED
1010 if (ctx->tbflags & FPSCR_SZ) {
1011 TCGv_i64 fp = tcg_temp_new_i64();
1012 gen_load_fpr64(ctx, fp, XHACK(B7_4));
1013 tcg_gen_qemu_st_i64(fp, REG(B11_8), ctx->memidx, MO_TEUQ);
1014 tcg_temp_free_i64(fp);
1015 } else {
1016 tcg_gen_qemu_st_i32(FREG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL);
1018 return;
1019 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
1020 CHECK_FPU_ENABLED
1021 if (ctx->tbflags & FPSCR_SZ) {
1022 TCGv_i64 fp = tcg_temp_new_i64();
1023 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEUQ);
1024 gen_store_fpr64(ctx, fp, XHACK(B11_8));
1025 tcg_temp_free_i64(fp);
1026 } else {
1027 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx, MO_TEUL);
1029 return;
1030 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
1031 CHECK_FPU_ENABLED
1032 if (ctx->tbflags & FPSCR_SZ) {
1033 TCGv_i64 fp = tcg_temp_new_i64();
1034 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEUQ);
1035 gen_store_fpr64(ctx, fp, XHACK(B11_8));
1036 tcg_temp_free_i64(fp);
1037 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8);
1038 } else {
1039 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx, MO_TEUL);
1040 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
1042 return;
1043 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
1044 CHECK_FPU_ENABLED
1046 TCGv addr = tcg_temp_new_i32();
1047 if (ctx->tbflags & FPSCR_SZ) {
1048 TCGv_i64 fp = tcg_temp_new_i64();
1049 gen_load_fpr64(ctx, fp, XHACK(B7_4));
1050 tcg_gen_subi_i32(addr, REG(B11_8), 8);
1051 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEUQ);
1052 tcg_temp_free_i64(fp);
1053 } else {
1054 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1055 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, MO_TEUL);
1057 tcg_gen_mov_i32(REG(B11_8), addr);
1058 tcg_temp_free(addr);
1060 return;
1061 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
1062 CHECK_FPU_ENABLED
1064 TCGv addr = tcg_temp_new_i32();
1065 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
1066 if (ctx->tbflags & FPSCR_SZ) {
1067 TCGv_i64 fp = tcg_temp_new_i64();
1068 tcg_gen_qemu_ld_i64(fp, addr, ctx->memidx, MO_TEUQ);
1069 gen_store_fpr64(ctx, fp, XHACK(B11_8));
1070 tcg_temp_free_i64(fp);
1071 } else {
1072 tcg_gen_qemu_ld_i32(FREG(B11_8), addr, ctx->memidx, MO_TEUL);
1074 tcg_temp_free(addr);
1076 return;
1077 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
1078 CHECK_FPU_ENABLED
1080 TCGv addr = tcg_temp_new();
1081 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
1082 if (ctx->tbflags & FPSCR_SZ) {
1083 TCGv_i64 fp = tcg_temp_new_i64();
1084 gen_load_fpr64(ctx, fp, XHACK(B7_4));
1085 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEUQ);
1086 tcg_temp_free_i64(fp);
1087 } else {
1088 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, MO_TEUL);
1090 tcg_temp_free(addr);
1092 return;
1093 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1094 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1095 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1096 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1097 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1098 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1100 CHECK_FPU_ENABLED
1101 if (ctx->tbflags & FPSCR_PR) {
1102 TCGv_i64 fp0, fp1;
1104 if (ctx->opcode & 0x0110) {
1105 goto do_illegal;
1107 fp0 = tcg_temp_new_i64();
1108 fp1 = tcg_temp_new_i64();
1109 gen_load_fpr64(ctx, fp0, B11_8);
1110 gen_load_fpr64(ctx, fp1, B7_4);
1111 switch (ctx->opcode & 0xf00f) {
1112 case 0xf000: /* fadd Rm,Rn */
1113 gen_helper_fadd_DT(fp0, cpu_env, fp0, fp1);
1114 break;
1115 case 0xf001: /* fsub Rm,Rn */
1116 gen_helper_fsub_DT(fp0, cpu_env, fp0, fp1);
1117 break;
1118 case 0xf002: /* fmul Rm,Rn */
1119 gen_helper_fmul_DT(fp0, cpu_env, fp0, fp1);
1120 break;
1121 case 0xf003: /* fdiv Rm,Rn */
1122 gen_helper_fdiv_DT(fp0, cpu_env, fp0, fp1);
1123 break;
1124 case 0xf004: /* fcmp/eq Rm,Rn */
1125 gen_helper_fcmp_eq_DT(cpu_sr_t, cpu_env, fp0, fp1);
1126 return;
1127 case 0xf005: /* fcmp/gt Rm,Rn */
1128 gen_helper_fcmp_gt_DT(cpu_sr_t, cpu_env, fp0, fp1);
1129 return;
1131 gen_store_fpr64(ctx, fp0, B11_8);
1132 tcg_temp_free_i64(fp0);
1133 tcg_temp_free_i64(fp1);
1134 } else {
1135 switch (ctx->opcode & 0xf00f) {
1136 case 0xf000: /* fadd Rm,Rn */
1137 gen_helper_fadd_FT(FREG(B11_8), cpu_env,
1138 FREG(B11_8), FREG(B7_4));
1139 break;
1140 case 0xf001: /* fsub Rm,Rn */
1141 gen_helper_fsub_FT(FREG(B11_8), cpu_env,
1142 FREG(B11_8), FREG(B7_4));
1143 break;
1144 case 0xf002: /* fmul Rm,Rn */
1145 gen_helper_fmul_FT(FREG(B11_8), cpu_env,
1146 FREG(B11_8), FREG(B7_4));
1147 break;
1148 case 0xf003: /* fdiv Rm,Rn */
1149 gen_helper_fdiv_FT(FREG(B11_8), cpu_env,
1150 FREG(B11_8), FREG(B7_4));
1151 break;
1152 case 0xf004: /* fcmp/eq Rm,Rn */
1153 gen_helper_fcmp_eq_FT(cpu_sr_t, cpu_env,
1154 FREG(B11_8), FREG(B7_4));
1155 return;
1156 case 0xf005: /* fcmp/gt Rm,Rn */
1157 gen_helper_fcmp_gt_FT(cpu_sr_t, cpu_env,
1158 FREG(B11_8), FREG(B7_4));
1159 return;
1163 return;
1164 case 0xf00e: /* fmac FR0,RM,Rn */
1165 CHECK_FPU_ENABLED
1166 CHECK_FPSCR_PR_0
1167 gen_helper_fmac_FT(FREG(B11_8), cpu_env,
1168 FREG(0), FREG(B7_4), FREG(B11_8));
1169 return;
1172 switch (ctx->opcode & 0xff00) {
1173 case 0xc900: /* and #imm,R0 */
1174 tcg_gen_andi_i32(REG(0), REG(0), B7_0);
1175 return;
1176 case 0xcd00: /* and.b #imm,@(R0,GBR) */
1178 TCGv addr, val;
1179 addr = tcg_temp_new();
1180 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1181 val = tcg_temp_new();
1182 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1183 tcg_gen_andi_i32(val, val, B7_0);
1184 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1185 tcg_temp_free(val);
1186 tcg_temp_free(addr);
1188 return;
1189 case 0x8b00: /* bf label */
1190 CHECK_NOT_DELAY_SLOT
1191 gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, false);
1192 return;
1193 case 0x8f00: /* bf/s label */
1194 CHECK_NOT_DELAY_SLOT
1195 tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1);
1196 ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
1197 ctx->envflags |= DELAY_SLOT_CONDITIONAL;
1198 return;
1199 case 0x8900: /* bt label */
1200 CHECK_NOT_DELAY_SLOT
1201 gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, true);
1202 return;
1203 case 0x8d00: /* bt/s label */
1204 CHECK_NOT_DELAY_SLOT
1205 tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t);
1206 ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
1207 ctx->envflags |= DELAY_SLOT_CONDITIONAL;
1208 return;
1209 case 0x8800: /* cmp/eq #imm,R0 */
1210 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s);
1211 return;
1212 case 0xc400: /* mov.b @(disp,GBR),R0 */
1214 TCGv addr = tcg_temp_new();
1215 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1216 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
1217 tcg_temp_free(addr);
1219 return;
1220 case 0xc500: /* mov.w @(disp,GBR),R0 */
1222 TCGv addr = tcg_temp_new();
1223 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1224 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW);
1225 tcg_temp_free(addr);
1227 return;
1228 case 0xc600: /* mov.l @(disp,GBR),R0 */
1230 TCGv addr = tcg_temp_new();
1231 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1232 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESL);
1233 tcg_temp_free(addr);
1235 return;
1236 case 0xc000: /* mov.b R0,@(disp,GBR) */
1238 TCGv addr = tcg_temp_new();
1239 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1240 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
1241 tcg_temp_free(addr);
1243 return;
1244 case 0xc100: /* mov.w R0,@(disp,GBR) */
1246 TCGv addr = tcg_temp_new();
1247 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1248 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW);
1249 tcg_temp_free(addr);
1251 return;
1252 case 0xc200: /* mov.l R0,@(disp,GBR) */
1254 TCGv addr = tcg_temp_new();
1255 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1256 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUL);
1257 tcg_temp_free(addr);
1259 return;
1260 case 0x8000: /* mov.b R0,@(disp,Rn) */
1262 TCGv addr = tcg_temp_new();
1263 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1264 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
1265 tcg_temp_free(addr);
1267 return;
1268 case 0x8100: /* mov.w R0,@(disp,Rn) */
1270 TCGv addr = tcg_temp_new();
1271 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1272 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx,
1273 MO_TEUW | UNALIGN(ctx));
1274 tcg_temp_free(addr);
1276 return;
1277 case 0x8400: /* mov.b @(disp,Rn),R0 */
1279 TCGv addr = tcg_temp_new();
1280 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1281 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
1282 tcg_temp_free(addr);
1284 return;
1285 case 0x8500: /* mov.w @(disp,Rn),R0 */
1287 TCGv addr = tcg_temp_new();
1288 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1289 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx,
1290 MO_TESW | UNALIGN(ctx));
1291 tcg_temp_free(addr);
1293 return;
1294 case 0xc700: /* mova @(disp,PC),R0 */
1295 tcg_gen_movi_i32(REG(0), ((ctx->base.pc_next & 0xfffffffc) +
1296 4 + B7_0 * 4) & ~3);
1297 return;
1298 case 0xcb00: /* or #imm,R0 */
1299 tcg_gen_ori_i32(REG(0), REG(0), B7_0);
1300 return;
1301 case 0xcf00: /* or.b #imm,@(R0,GBR) */
1303 TCGv addr, val;
1304 addr = tcg_temp_new();
1305 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1306 val = tcg_temp_new();
1307 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1308 tcg_gen_ori_i32(val, val, B7_0);
1309 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1310 tcg_temp_free(val);
1311 tcg_temp_free(addr);
1313 return;
1314 case 0xc300: /* trapa #imm */
1316 TCGv imm;
1317 CHECK_NOT_DELAY_SLOT
1318 gen_save_cpu_state(ctx, true);
1319 imm = tcg_const_i32(B7_0);
1320 gen_helper_trapa(cpu_env, imm);
1321 tcg_temp_free(imm);
1322 ctx->base.is_jmp = DISAS_NORETURN;
1324 return;
1325 case 0xc800: /* tst #imm,R0 */
1327 TCGv val = tcg_temp_new();
1328 tcg_gen_andi_i32(val, REG(0), B7_0);
1329 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1330 tcg_temp_free(val);
1332 return;
1333 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
1335 TCGv val = tcg_temp_new();
1336 tcg_gen_add_i32(val, REG(0), cpu_gbr);
1337 tcg_gen_qemu_ld_i32(val, val, ctx->memidx, MO_UB);
1338 tcg_gen_andi_i32(val, val, B7_0);
1339 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1340 tcg_temp_free(val);
1342 return;
1343 case 0xca00: /* xor #imm,R0 */
1344 tcg_gen_xori_i32(REG(0), REG(0), B7_0);
1345 return;
1346 case 0xce00: /* xor.b #imm,@(R0,GBR) */
1348 TCGv addr, val;
1349 addr = tcg_temp_new();
1350 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1351 val = tcg_temp_new();
1352 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1353 tcg_gen_xori_i32(val, val, B7_0);
1354 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1355 tcg_temp_free(val);
1356 tcg_temp_free(addr);
1358 return;
1361 switch (ctx->opcode & 0xf08f) {
1362 case 0x408e: /* ldc Rm,Rn_BANK */
1363 CHECK_PRIVILEGED
1364 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8));
1365 return;
1366 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
1367 CHECK_PRIVILEGED
1368 tcg_gen_qemu_ld_i32(ALTREG(B6_4), REG(B11_8), ctx->memidx, MO_TESL);
1369 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1370 return;
1371 case 0x0082: /* stc Rm_BANK,Rn */
1372 CHECK_PRIVILEGED
1373 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4));
1374 return;
1375 case 0x4083: /* stc.l Rm_BANK,@-Rn */
1376 CHECK_PRIVILEGED
1378 TCGv addr = tcg_temp_new();
1379 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1380 tcg_gen_qemu_st_i32(ALTREG(B6_4), addr, ctx->memidx, MO_TEUL);
1381 tcg_gen_mov_i32(REG(B11_8), addr);
1382 tcg_temp_free(addr);
1384 return;
1387 switch (ctx->opcode & 0xf0ff) {
1388 case 0x0023: /* braf Rn */
1389 CHECK_NOT_DELAY_SLOT
1390 tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->base.pc_next + 4);
1391 ctx->envflags |= DELAY_SLOT;
1392 ctx->delayed_pc = (uint32_t) - 1;
1393 return;
1394 case 0x0003: /* bsrf Rn */
1395 CHECK_NOT_DELAY_SLOT
1396 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
1397 tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
1398 ctx->envflags |= DELAY_SLOT;
1399 ctx->delayed_pc = (uint32_t) - 1;
1400 return;
1401 case 0x4015: /* cmp/pl Rn */
1402 tcg_gen_setcondi_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), 0);
1403 return;
1404 case 0x4011: /* cmp/pz Rn */
1405 tcg_gen_setcondi_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), 0);
1406 return;
1407 case 0x4010: /* dt Rn */
1408 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1);
1409 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), 0);
1410 return;
1411 case 0x402b: /* jmp @Rn */
1412 CHECK_NOT_DELAY_SLOT
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 0x400b: /* jsr @Rn */
1418 CHECK_NOT_DELAY_SLOT
1419 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
1420 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1421 ctx->envflags |= DELAY_SLOT;
1422 ctx->delayed_pc = (uint32_t) - 1;
1423 return;
1424 case 0x400e: /* ldc Rm,SR */
1425 CHECK_PRIVILEGED
1427 TCGv val = tcg_temp_new();
1428 tcg_gen_andi_i32(val, REG(B11_8), 0x700083f3);
1429 gen_write_sr(val);
1430 tcg_temp_free(val);
1431 ctx->base.is_jmp = DISAS_STOP;
1433 return;
1434 case 0x4007: /* ldc.l @Rm+,SR */
1435 CHECK_PRIVILEGED
1437 TCGv val = tcg_temp_new();
1438 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TESL);
1439 tcg_gen_andi_i32(val, val, 0x700083f3);
1440 gen_write_sr(val);
1441 tcg_temp_free(val);
1442 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1443 ctx->base.is_jmp = DISAS_STOP;
1445 return;
1446 case 0x0002: /* stc SR,Rn */
1447 CHECK_PRIVILEGED
1448 gen_read_sr(REG(B11_8));
1449 return;
1450 case 0x4003: /* stc SR,@-Rn */
1451 CHECK_PRIVILEGED
1453 TCGv addr = tcg_temp_new();
1454 TCGv val = tcg_temp_new();
1455 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1456 gen_read_sr(val);
1457 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL);
1458 tcg_gen_mov_i32(REG(B11_8), addr);
1459 tcg_temp_free(val);
1460 tcg_temp_free(addr);
1462 return;
1463 #define LD(reg,ldnum,ldpnum,prechk) \
1464 case ldnum: \
1465 prechk \
1466 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \
1467 return; \
1468 case ldpnum: \
1469 prechk \
1470 tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, MO_TESL); \
1471 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \
1472 return;
1473 #define ST(reg,stnum,stpnum,prechk) \
1474 case stnum: \
1475 prechk \
1476 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \
1477 return; \
1478 case stpnum: \
1479 prechk \
1481 TCGv addr = tcg_temp_new(); \
1482 tcg_gen_subi_i32(addr, REG(B11_8), 4); \
1483 tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, MO_TEUL); \
1484 tcg_gen_mov_i32(REG(B11_8), addr); \
1485 tcg_temp_free(addr); \
1487 return;
1488 #define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \
1489 LD(reg,ldnum,ldpnum,prechk) \
1490 ST(reg,stnum,stpnum,prechk)
1491 LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {})
1492 LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED)
1493 LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED)
1494 LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED)
1495 ST(sgr, 0x003a, 0x4032, CHECK_PRIVILEGED)
1496 LD(sgr, 0x403a, 0x4036, CHECK_PRIVILEGED CHECK_SH4A)
1497 LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED)
1498 LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {})
1499 LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {})
1500 LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {})
1501 LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED})
1502 case 0x406a: /* lds Rm,FPSCR */
1503 CHECK_FPU_ENABLED
1504 gen_helper_ld_fpscr(cpu_env, REG(B11_8));
1505 ctx->base.is_jmp = DISAS_STOP;
1506 return;
1507 case 0x4066: /* lds.l @Rm+,FPSCR */
1508 CHECK_FPU_ENABLED
1510 TCGv addr = tcg_temp_new();
1511 tcg_gen_qemu_ld_i32(addr, REG(B11_8), ctx->memidx, MO_TESL);
1512 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1513 gen_helper_ld_fpscr(cpu_env, addr);
1514 tcg_temp_free(addr);
1515 ctx->base.is_jmp = DISAS_STOP;
1517 return;
1518 case 0x006a: /* sts FPSCR,Rn */
1519 CHECK_FPU_ENABLED
1520 tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff);
1521 return;
1522 case 0x4062: /* sts FPSCR,@-Rn */
1523 CHECK_FPU_ENABLED
1525 TCGv addr, val;
1526 val = tcg_temp_new();
1527 tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff);
1528 addr = tcg_temp_new();
1529 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1530 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL);
1531 tcg_gen_mov_i32(REG(B11_8), addr);
1532 tcg_temp_free(addr);
1533 tcg_temp_free(val);
1535 return;
1536 case 0x00c3: /* movca.l R0,@Rm */
1538 TCGv val = tcg_temp_new();
1539 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TEUL);
1540 gen_helper_movcal(cpu_env, REG(B11_8), val);
1541 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
1542 tcg_temp_free(val);
1544 ctx->has_movcal = 1;
1545 return;
1546 case 0x40a9: /* movua.l @Rm,R0 */
1547 CHECK_SH4A
1548 /* Load non-boundary-aligned data */
1549 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1550 MO_TEUL | MO_UNALN);
1551 return;
1552 case 0x40e9: /* movua.l @Rm+,R0 */
1553 CHECK_SH4A
1554 /* Load non-boundary-aligned data */
1555 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1556 MO_TEUL | MO_UNALN);
1557 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1558 return;
1559 case 0x0029: /* movt Rn */
1560 tcg_gen_mov_i32(REG(B11_8), cpu_sr_t);
1561 return;
1562 case 0x0073:
1563 /* MOVCO.L
1564 * LDST -> T
1565 * If (T == 1) R0 -> (Rn)
1566 * 0 -> LDST
1568 * The above description doesn't work in a parallel context.
1569 * Since we currently support no smp boards, this implies user-mode.
1570 * But we can still support the official mechanism while user-mode
1571 * is single-threaded. */
1572 CHECK_SH4A
1574 TCGLabel *fail = gen_new_label();
1575 TCGLabel *done = gen_new_label();
1577 if ((tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
1578 TCGv tmp;
1580 tcg_gen_brcond_i32(TCG_COND_NE, REG(B11_8),
1581 cpu_lock_addr, fail);
1582 tmp = tcg_temp_new();
1583 tcg_gen_atomic_cmpxchg_i32(tmp, REG(B11_8), cpu_lock_value,
1584 REG(0), ctx->memidx, MO_TEUL);
1585 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, tmp, cpu_lock_value);
1586 tcg_temp_free(tmp);
1587 } else {
1588 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_lock_addr, -1, fail);
1589 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
1590 tcg_gen_movi_i32(cpu_sr_t, 1);
1592 tcg_gen_br(done);
1594 gen_set_label(fail);
1595 tcg_gen_movi_i32(cpu_sr_t, 0);
1597 gen_set_label(done);
1598 tcg_gen_movi_i32(cpu_lock_addr, -1);
1600 return;
1601 case 0x0063:
1602 /* MOVLI.L @Rm,R0
1603 * 1 -> LDST
1604 * (Rm) -> R0
1605 * When interrupt/exception
1606 * occurred 0 -> LDST
1608 * In a parallel context, we must also save the loaded value
1609 * for use with the cmpxchg that we'll use with movco.l. */
1610 CHECK_SH4A
1611 if ((tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
1612 TCGv tmp = tcg_temp_new();
1613 tcg_gen_mov_i32(tmp, REG(B11_8));
1614 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TESL);
1615 tcg_gen_mov_i32(cpu_lock_value, REG(0));
1616 tcg_gen_mov_i32(cpu_lock_addr, tmp);
1617 tcg_temp_free(tmp);
1618 } else {
1619 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TESL);
1620 tcg_gen_movi_i32(cpu_lock_addr, 0);
1622 return;
1623 case 0x0093: /* ocbi @Rn */
1625 gen_helper_ocbi(cpu_env, REG(B11_8));
1627 return;
1628 case 0x00a3: /* ocbp @Rn */
1629 case 0x00b3: /* ocbwb @Rn */
1630 /* These instructions are supposed to do nothing in case of
1631 a cache miss. Given that we only partially emulate caches
1632 it is safe to simply ignore them. */
1633 return;
1634 case 0x0083: /* pref @Rn */
1635 return;
1636 case 0x00d3: /* prefi @Rn */
1637 CHECK_SH4A
1638 return;
1639 case 0x00e3: /* icbi @Rn */
1640 CHECK_SH4A
1641 return;
1642 case 0x00ab: /* synco */
1643 CHECK_SH4A
1644 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
1645 return;
1646 case 0x4024: /* rotcl Rn */
1648 TCGv tmp = tcg_temp_new();
1649 tcg_gen_mov_i32(tmp, cpu_sr_t);
1650 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
1651 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1652 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
1653 tcg_temp_free(tmp);
1655 return;
1656 case 0x4025: /* rotcr Rn */
1658 TCGv tmp = tcg_temp_new();
1659 tcg_gen_shli_i32(tmp, cpu_sr_t, 31);
1660 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1661 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1662 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
1663 tcg_temp_free(tmp);
1665 return;
1666 case 0x4004: /* rotl Rn */
1667 tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1);
1668 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
1669 return;
1670 case 0x4005: /* rotr Rn */
1671 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
1672 tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1);
1673 return;
1674 case 0x4000: /* shll Rn */
1675 case 0x4020: /* shal Rn */
1676 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
1677 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1678 return;
1679 case 0x4021: /* shar Rn */
1680 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1681 tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1);
1682 return;
1683 case 0x4001: /* shlr Rn */
1684 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1685 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1686 return;
1687 case 0x4008: /* shll2 Rn */
1688 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2);
1689 return;
1690 case 0x4018: /* shll8 Rn */
1691 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8);
1692 return;
1693 case 0x4028: /* shll16 Rn */
1694 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16);
1695 return;
1696 case 0x4009: /* shlr2 Rn */
1697 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2);
1698 return;
1699 case 0x4019: /* shlr8 Rn */
1700 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8);
1701 return;
1702 case 0x4029: /* shlr16 Rn */
1703 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16);
1704 return;
1705 case 0x401b: /* tas.b @Rn */
1707 TCGv val = tcg_const_i32(0x80);
1708 tcg_gen_atomic_fetch_or_i32(val, REG(B11_8), val,
1709 ctx->memidx, MO_UB);
1710 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1711 tcg_temp_free(val);
1713 return;
1714 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1715 CHECK_FPU_ENABLED
1716 tcg_gen_mov_i32(FREG(B11_8), cpu_fpul);
1717 return;
1718 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1719 CHECK_FPU_ENABLED
1720 tcg_gen_mov_i32(cpu_fpul, FREG(B11_8));
1721 return;
1722 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
1723 CHECK_FPU_ENABLED
1724 if (ctx->tbflags & FPSCR_PR) {
1725 TCGv_i64 fp;
1726 if (ctx->opcode & 0x0100) {
1727 goto do_illegal;
1729 fp = tcg_temp_new_i64();
1730 gen_helper_float_DT(fp, cpu_env, cpu_fpul);
1731 gen_store_fpr64(ctx, fp, B11_8);
1732 tcg_temp_free_i64(fp);
1734 else {
1735 gen_helper_float_FT(FREG(B11_8), cpu_env, cpu_fpul);
1737 return;
1738 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1739 CHECK_FPU_ENABLED
1740 if (ctx->tbflags & FPSCR_PR) {
1741 TCGv_i64 fp;
1742 if (ctx->opcode & 0x0100) {
1743 goto do_illegal;
1745 fp = tcg_temp_new_i64();
1746 gen_load_fpr64(ctx, fp, B11_8);
1747 gen_helper_ftrc_DT(cpu_fpul, cpu_env, fp);
1748 tcg_temp_free_i64(fp);
1750 else {
1751 gen_helper_ftrc_FT(cpu_fpul, cpu_env, FREG(B11_8));
1753 return;
1754 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
1755 CHECK_FPU_ENABLED
1756 tcg_gen_xori_i32(FREG(B11_8), FREG(B11_8), 0x80000000);
1757 return;
1758 case 0xf05d: /* fabs FRn/DRn - FPCSR: Nothing */
1759 CHECK_FPU_ENABLED
1760 tcg_gen_andi_i32(FREG(B11_8), FREG(B11_8), 0x7fffffff);
1761 return;
1762 case 0xf06d: /* fsqrt FRn */
1763 CHECK_FPU_ENABLED
1764 if (ctx->tbflags & FPSCR_PR) {
1765 if (ctx->opcode & 0x0100) {
1766 goto do_illegal;
1768 TCGv_i64 fp = tcg_temp_new_i64();
1769 gen_load_fpr64(ctx, fp, B11_8);
1770 gen_helper_fsqrt_DT(fp, cpu_env, fp);
1771 gen_store_fpr64(ctx, fp, B11_8);
1772 tcg_temp_free_i64(fp);
1773 } else {
1774 gen_helper_fsqrt_FT(FREG(B11_8), cpu_env, FREG(B11_8));
1776 return;
1777 case 0xf07d: /* fsrra FRn */
1778 CHECK_FPU_ENABLED
1779 CHECK_FPSCR_PR_0
1780 gen_helper_fsrra_FT(FREG(B11_8), cpu_env, FREG(B11_8));
1781 break;
1782 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
1783 CHECK_FPU_ENABLED
1784 CHECK_FPSCR_PR_0
1785 tcg_gen_movi_i32(FREG(B11_8), 0);
1786 return;
1787 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
1788 CHECK_FPU_ENABLED
1789 CHECK_FPSCR_PR_0
1790 tcg_gen_movi_i32(FREG(B11_8), 0x3f800000);
1791 return;
1792 case 0xf0ad: /* fcnvsd FPUL,DRn */
1793 CHECK_FPU_ENABLED
1795 TCGv_i64 fp = tcg_temp_new_i64();
1796 gen_helper_fcnvsd_FT_DT(fp, cpu_env, cpu_fpul);
1797 gen_store_fpr64(ctx, fp, B11_8);
1798 tcg_temp_free_i64(fp);
1800 return;
1801 case 0xf0bd: /* fcnvds DRn,FPUL */
1802 CHECK_FPU_ENABLED
1804 TCGv_i64 fp = tcg_temp_new_i64();
1805 gen_load_fpr64(ctx, fp, B11_8);
1806 gen_helper_fcnvds_DT_FT(cpu_fpul, cpu_env, fp);
1807 tcg_temp_free_i64(fp);
1809 return;
1810 case 0xf0ed: /* fipr FVm,FVn */
1811 CHECK_FPU_ENABLED
1812 CHECK_FPSCR_PR_1
1814 TCGv m = tcg_const_i32((ctx->opcode >> 8) & 3);
1815 TCGv n = tcg_const_i32((ctx->opcode >> 10) & 3);
1816 gen_helper_fipr(cpu_env, m, n);
1817 tcg_temp_free(m);
1818 tcg_temp_free(n);
1819 return;
1821 break;
1822 case 0xf0fd: /* ftrv XMTRX,FVn */
1823 CHECK_FPU_ENABLED
1824 CHECK_FPSCR_PR_1
1826 if ((ctx->opcode & 0x0300) != 0x0100) {
1827 goto do_illegal;
1829 TCGv n = tcg_const_i32((ctx->opcode >> 10) & 3);
1830 gen_helper_ftrv(cpu_env, n);
1831 tcg_temp_free(n);
1832 return;
1834 break;
1836 #if 0
1837 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1838 ctx->opcode, ctx->base.pc_next);
1839 fflush(stderr);
1840 #endif
1841 do_illegal:
1842 if (ctx->envflags & DELAY_SLOT_MASK) {
1843 do_illegal_slot:
1844 gen_save_cpu_state(ctx, true);
1845 gen_helper_raise_slot_illegal_instruction(cpu_env);
1846 } else {
1847 gen_save_cpu_state(ctx, true);
1848 gen_helper_raise_illegal_instruction(cpu_env);
1850 ctx->base.is_jmp = DISAS_NORETURN;
1851 return;
1853 do_fpu_disabled:
1854 gen_save_cpu_state(ctx, true);
1855 if (ctx->envflags & DELAY_SLOT_MASK) {
1856 gen_helper_raise_slot_fpu_disable(cpu_env);
1857 } else {
1858 gen_helper_raise_fpu_disable(cpu_env);
1860 ctx->base.is_jmp = DISAS_NORETURN;
1861 return;
1864 static void decode_opc(DisasContext * ctx)
1866 uint32_t old_flags = ctx->envflags;
1868 _decode_opc(ctx);
1870 if (old_flags & DELAY_SLOT_MASK) {
1871 /* go out of the delay slot */
1872 ctx->envflags &= ~DELAY_SLOT_MASK;
1874 /* When in an exclusive region, we must continue to the end
1875 for conditional branches. */
1876 if (ctx->tbflags & GUSA_EXCLUSIVE
1877 && old_flags & DELAY_SLOT_CONDITIONAL) {
1878 gen_delayed_conditional_jump(ctx);
1879 return;
1881 /* Otherwise this is probably an invalid gUSA region.
1882 Drop the GUSA bits so the next TB doesn't see them. */
1883 ctx->envflags &= ~GUSA_MASK;
1885 tcg_gen_movi_i32(cpu_flags, ctx->envflags);
1886 if (old_flags & DELAY_SLOT_CONDITIONAL) {
1887 gen_delayed_conditional_jump(ctx);
1888 } else {
1889 gen_jump(ctx);
1894 #ifdef CONFIG_USER_ONLY
1895 /* For uniprocessors, SH4 uses optimistic restartable atomic sequences.
1896 Upon an interrupt, a real kernel would simply notice magic values in
1897 the registers and reset the PC to the start of the sequence.
1899 For QEMU, we cannot do this in quite the same way. Instead, we notice
1900 the normal start of such a sequence (mov #-x,r15). While we can handle
1901 any sequence via cpu_exec_step_atomic, we can recognize the "normal"
1902 sequences and transform them into atomic operations as seen by the host.
1904 static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
1906 uint16_t insns[5];
1907 int ld_adr, ld_dst, ld_mop;
1908 int op_dst, op_src, op_opc;
1909 int mv_src, mt_dst, st_src, st_mop;
1910 TCGv op_arg;
1911 uint32_t pc = ctx->base.pc_next;
1912 uint32_t pc_end = ctx->base.tb->cs_base;
1913 int max_insns = (pc_end - pc) / 2;
1914 int i;
1916 /* The state machine below will consume only a few insns.
1917 If there are more than that in a region, fail now. */
1918 if (max_insns > ARRAY_SIZE(insns)) {
1919 goto fail;
1922 /* Read all of the insns for the region. */
1923 for (i = 0; i < max_insns; ++i) {
1924 insns[i] = translator_lduw(env, &ctx->base, pc + i * 2);
1927 ld_adr = ld_dst = ld_mop = -1;
1928 mv_src = -1;
1929 op_dst = op_src = op_opc = -1;
1930 mt_dst = -1;
1931 st_src = st_mop = -1;
1932 op_arg = NULL;
1933 i = 0;
1935 #define NEXT_INSN \
1936 do { if (i >= max_insns) goto fail; ctx->opcode = insns[i++]; } while (0)
1939 * Expect a load to begin the region.
1941 NEXT_INSN;
1942 switch (ctx->opcode & 0xf00f) {
1943 case 0x6000: /* mov.b @Rm,Rn */
1944 ld_mop = MO_SB;
1945 break;
1946 case 0x6001: /* mov.w @Rm,Rn */
1947 ld_mop = MO_TESW;
1948 break;
1949 case 0x6002: /* mov.l @Rm,Rn */
1950 ld_mop = MO_TESL;
1951 break;
1952 default:
1953 goto fail;
1955 ld_adr = B7_4;
1956 ld_dst = B11_8;
1957 if (ld_adr == ld_dst) {
1958 goto fail;
1960 /* Unless we see a mov, any two-operand operation must use ld_dst. */
1961 op_dst = ld_dst;
1964 * Expect an optional register move.
1966 NEXT_INSN;
1967 switch (ctx->opcode & 0xf00f) {
1968 case 0x6003: /* mov Rm,Rn */
1970 * Here we want to recognize ld_dst being saved for later consumption,
1971 * or for another input register being copied so that ld_dst need not
1972 * be clobbered during the operation.
1974 op_dst = B11_8;
1975 mv_src = B7_4;
1976 if (op_dst == ld_dst) {
1977 /* Overwriting the load output. */
1978 goto fail;
1980 if (mv_src != ld_dst) {
1981 /* Copying a new input; constrain op_src to match the load. */
1982 op_src = ld_dst;
1984 break;
1986 default:
1987 /* Put back and re-examine as operation. */
1988 --i;
1992 * Expect the operation.
1994 NEXT_INSN;
1995 switch (ctx->opcode & 0xf00f) {
1996 case 0x300c: /* add Rm,Rn */
1997 op_opc = INDEX_op_add_i32;
1998 goto do_reg_op;
1999 case 0x2009: /* and Rm,Rn */
2000 op_opc = INDEX_op_and_i32;
2001 goto do_reg_op;
2002 case 0x200a: /* xor Rm,Rn */
2003 op_opc = INDEX_op_xor_i32;
2004 goto do_reg_op;
2005 case 0x200b: /* or Rm,Rn */
2006 op_opc = INDEX_op_or_i32;
2007 do_reg_op:
2008 /* The operation register should be as expected, and the
2009 other input cannot depend on the load. */
2010 if (op_dst != B11_8) {
2011 goto fail;
2013 if (op_src < 0) {
2014 /* Unconstrainted input. */
2015 op_src = B7_4;
2016 } else if (op_src == B7_4) {
2017 /* Constrained input matched load. All operations are
2018 commutative; "swap" them by "moving" the load output
2019 to the (implicit) first argument and the move source
2020 to the (explicit) second argument. */
2021 op_src = mv_src;
2022 } else {
2023 goto fail;
2025 op_arg = REG(op_src);
2026 break;
2028 case 0x6007: /* not Rm,Rn */
2029 if (ld_dst != B7_4 || mv_src >= 0) {
2030 goto fail;
2032 op_dst = B11_8;
2033 op_opc = INDEX_op_xor_i32;
2034 op_arg = tcg_const_i32(-1);
2035 break;
2037 case 0x7000 ... 0x700f: /* add #imm,Rn */
2038 if (op_dst != B11_8 || mv_src >= 0) {
2039 goto fail;
2041 op_opc = INDEX_op_add_i32;
2042 op_arg = tcg_const_i32(B7_0s);
2043 break;
2045 case 0x3000: /* cmp/eq Rm,Rn */
2046 /* Looking for the middle of a compare-and-swap sequence,
2047 beginning with the compare. Operands can be either order,
2048 but with only one overlapping the load. */
2049 if ((ld_dst == B11_8) + (ld_dst == B7_4) != 1 || mv_src >= 0) {
2050 goto fail;
2052 op_opc = INDEX_op_setcond_i32; /* placeholder */
2053 op_src = (ld_dst == B11_8 ? B7_4 : B11_8);
2054 op_arg = REG(op_src);
2056 NEXT_INSN;
2057 switch (ctx->opcode & 0xff00) {
2058 case 0x8b00: /* bf label */
2059 case 0x8f00: /* bf/s label */
2060 if (pc + (i + 1 + B7_0s) * 2 != pc_end) {
2061 goto fail;
2063 if ((ctx->opcode & 0xff00) == 0x8b00) { /* bf label */
2064 break;
2066 /* We're looking to unconditionally modify Rn with the
2067 result of the comparison, within the delay slot of
2068 the branch. This is used by older gcc. */
2069 NEXT_INSN;
2070 if ((ctx->opcode & 0xf0ff) == 0x0029) { /* movt Rn */
2071 mt_dst = B11_8;
2072 } else {
2073 goto fail;
2075 break;
2077 default:
2078 goto fail;
2080 break;
2082 case 0x2008: /* tst Rm,Rn */
2083 /* Looking for a compare-and-swap against zero. */
2084 if (ld_dst != B11_8 || ld_dst != B7_4 || mv_src >= 0) {
2085 goto fail;
2087 op_opc = INDEX_op_setcond_i32;
2088 op_arg = tcg_const_i32(0);
2090 NEXT_INSN;
2091 if ((ctx->opcode & 0xff00) != 0x8900 /* bt label */
2092 || pc + (i + 1 + B7_0s) * 2 != pc_end) {
2093 goto fail;
2095 break;
2097 default:
2098 /* Put back and re-examine as store. */
2099 --i;
2103 * Expect the store.
2105 /* The store must be the last insn. */
2106 if (i != max_insns - 1) {
2107 goto fail;
2109 NEXT_INSN;
2110 switch (ctx->opcode & 0xf00f) {
2111 case 0x2000: /* mov.b Rm,@Rn */
2112 st_mop = MO_UB;
2113 break;
2114 case 0x2001: /* mov.w Rm,@Rn */
2115 st_mop = MO_UW;
2116 break;
2117 case 0x2002: /* mov.l Rm,@Rn */
2118 st_mop = MO_UL;
2119 break;
2120 default:
2121 goto fail;
2123 /* The store must match the load. */
2124 if (ld_adr != B11_8 || st_mop != (ld_mop & MO_SIZE)) {
2125 goto fail;
2127 st_src = B7_4;
2129 #undef NEXT_INSN
2132 * Emit the operation.
2134 switch (op_opc) {
2135 case -1:
2136 /* No operation found. Look for exchange pattern. */
2137 if (st_src == ld_dst || mv_src >= 0) {
2138 goto fail;
2140 tcg_gen_atomic_xchg_i32(REG(ld_dst), REG(ld_adr), REG(st_src),
2141 ctx->memidx, ld_mop);
2142 break;
2144 case INDEX_op_add_i32:
2145 if (op_dst != st_src) {
2146 goto fail;
2148 if (op_dst == ld_dst && st_mop == MO_UL) {
2149 tcg_gen_atomic_add_fetch_i32(REG(ld_dst), REG(ld_adr),
2150 op_arg, ctx->memidx, ld_mop);
2151 } else {
2152 tcg_gen_atomic_fetch_add_i32(REG(ld_dst), REG(ld_adr),
2153 op_arg, ctx->memidx, ld_mop);
2154 if (op_dst != ld_dst) {
2155 /* Note that mop sizes < 4 cannot use add_fetch
2156 because it won't carry into the higher bits. */
2157 tcg_gen_add_i32(REG(op_dst), REG(ld_dst), op_arg);
2160 break;
2162 case INDEX_op_and_i32:
2163 if (op_dst != st_src) {
2164 goto fail;
2166 if (op_dst == ld_dst) {
2167 tcg_gen_atomic_and_fetch_i32(REG(ld_dst), REG(ld_adr),
2168 op_arg, ctx->memidx, ld_mop);
2169 } else {
2170 tcg_gen_atomic_fetch_and_i32(REG(ld_dst), REG(ld_adr),
2171 op_arg, ctx->memidx, ld_mop);
2172 tcg_gen_and_i32(REG(op_dst), REG(ld_dst), op_arg);
2174 break;
2176 case INDEX_op_or_i32:
2177 if (op_dst != st_src) {
2178 goto fail;
2180 if (op_dst == ld_dst) {
2181 tcg_gen_atomic_or_fetch_i32(REG(ld_dst), REG(ld_adr),
2182 op_arg, ctx->memidx, ld_mop);
2183 } else {
2184 tcg_gen_atomic_fetch_or_i32(REG(ld_dst), REG(ld_adr),
2185 op_arg, ctx->memidx, ld_mop);
2186 tcg_gen_or_i32(REG(op_dst), REG(ld_dst), op_arg);
2188 break;
2190 case INDEX_op_xor_i32:
2191 if (op_dst != st_src) {
2192 goto fail;
2194 if (op_dst == ld_dst) {
2195 tcg_gen_atomic_xor_fetch_i32(REG(ld_dst), REG(ld_adr),
2196 op_arg, ctx->memidx, ld_mop);
2197 } else {
2198 tcg_gen_atomic_fetch_xor_i32(REG(ld_dst), REG(ld_adr),
2199 op_arg, ctx->memidx, ld_mop);
2200 tcg_gen_xor_i32(REG(op_dst), REG(ld_dst), op_arg);
2202 break;
2204 case INDEX_op_setcond_i32:
2205 if (st_src == ld_dst) {
2206 goto fail;
2208 tcg_gen_atomic_cmpxchg_i32(REG(ld_dst), REG(ld_adr), op_arg,
2209 REG(st_src), ctx->memidx, ld_mop);
2210 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(ld_dst), op_arg);
2211 if (mt_dst >= 0) {
2212 tcg_gen_mov_i32(REG(mt_dst), cpu_sr_t);
2214 break;
2216 default:
2217 g_assert_not_reached();
2220 /* If op_src is not a valid register, then op_arg was a constant. */
2221 if (op_src < 0 && op_arg) {
2222 tcg_temp_free_i32(op_arg);
2225 /* The entire region has been translated. */
2226 ctx->envflags &= ~GUSA_MASK;
2227 ctx->base.pc_next = pc_end;
2228 ctx->base.num_insns += max_insns - 1;
2229 return;
2231 fail:
2232 qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n",
2233 pc, pc_end);
2235 /* Restart with the EXCLUSIVE bit set, within a TB run via
2236 cpu_exec_step_atomic holding the exclusive lock. */
2237 ctx->envflags |= GUSA_EXCLUSIVE;
2238 gen_save_cpu_state(ctx, false);
2239 gen_helper_exclusive(cpu_env);
2240 ctx->base.is_jmp = DISAS_NORETURN;
2242 /* We're not executing an instruction, but we must report one for the
2243 purposes of accounting within the TB. We might as well report the
2244 entire region consumed via ctx->base.pc_next so that it's immediately
2245 available in the disassembly dump. */
2246 ctx->base.pc_next = pc_end;
2247 ctx->base.num_insns += max_insns - 1;
2249 #endif
2251 static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
2253 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2254 CPUSH4State *env = cs->env_ptr;
2255 uint32_t tbflags;
2256 int bound;
2258 ctx->tbflags = tbflags = ctx->base.tb->flags;
2259 ctx->envflags = tbflags & TB_FLAG_ENVFLAGS_MASK;
2260 ctx->memidx = (tbflags & (1u << SR_MD)) == 0 ? 1 : 0;
2261 /* We don't know if the delayed pc came from a dynamic or static branch,
2262 so assume it is a dynamic branch. */
2263 ctx->delayed_pc = -1; /* use delayed pc from env pointer */
2264 ctx->features = env->features;
2265 ctx->has_movcal = (tbflags & TB_FLAG_PENDING_MOVCA);
2266 ctx->gbank = ((tbflags & (1 << SR_MD)) &&
2267 (tbflags & (1 << SR_RB))) * 0x10;
2268 ctx->fbank = tbflags & FPSCR_FR ? 0x10 : 0;
2270 if (tbflags & GUSA_MASK) {
2271 uint32_t pc = ctx->base.pc_next;
2272 uint32_t pc_end = ctx->base.tb->cs_base;
2273 int backup = sextract32(ctx->tbflags, GUSA_SHIFT, 8);
2274 int max_insns = (pc_end - pc) / 2;
2276 if (pc != pc_end + backup || max_insns < 2) {
2277 /* This is a malformed gUSA region. Don't do anything special,
2278 since the interpreter is likely to get confused. */
2279 ctx->envflags &= ~GUSA_MASK;
2280 } else if (tbflags & GUSA_EXCLUSIVE) {
2281 /* Regardless of single-stepping or the end of the page,
2282 we must complete execution of the gUSA region while
2283 holding the exclusive lock. */
2284 ctx->base.max_insns = max_insns;
2285 return;
2289 /* Since the ISA is fixed-width, we can bound by the number
2290 of instructions remaining on the page. */
2291 bound = -(ctx->base.pc_next | TARGET_PAGE_MASK) / 2;
2292 ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
2295 static void sh4_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
2299 static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
2301 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2303 tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags);
2306 static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
2308 CPUSH4State *env = cs->env_ptr;
2309 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2311 #ifdef CONFIG_USER_ONLY
2312 if (unlikely(ctx->envflags & GUSA_MASK)
2313 && !(ctx->envflags & GUSA_EXCLUSIVE)) {
2314 /* We're in an gUSA region, and we have not already fallen
2315 back on using an exclusive region. Attempt to parse the
2316 region into a single supported atomic operation. Failure
2317 is handled within the parser by raising an exception to
2318 retry using an exclusive region. */
2319 decode_gusa(ctx, env);
2320 return;
2322 #endif
2324 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next);
2325 decode_opc(ctx);
2326 ctx->base.pc_next += 2;
2329 static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
2331 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2333 if (ctx->tbflags & GUSA_EXCLUSIVE) {
2334 /* Ending the region of exclusivity. Clear the bits. */
2335 ctx->envflags &= ~GUSA_MASK;
2338 switch (ctx->base.is_jmp) {
2339 case DISAS_STOP:
2340 gen_save_cpu_state(ctx, true);
2341 tcg_gen_exit_tb(NULL, 0);
2342 break;
2343 case DISAS_NEXT:
2344 case DISAS_TOO_MANY:
2345 gen_save_cpu_state(ctx, false);
2346 gen_goto_tb(ctx, 0, ctx->base.pc_next);
2347 break;
2348 case DISAS_NORETURN:
2349 break;
2350 default:
2351 g_assert_not_reached();
2355 static void sh4_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
2357 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
2358 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
2361 static const TranslatorOps sh4_tr_ops = {
2362 .init_disas_context = sh4_tr_init_disas_context,
2363 .tb_start = sh4_tr_tb_start,
2364 .insn_start = sh4_tr_insn_start,
2365 .translate_insn = sh4_tr_translate_insn,
2366 .tb_stop = sh4_tr_tb_stop,
2367 .disas_log = sh4_tr_disas_log,
2370 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
2372 DisasContext ctx;
2374 translator_loop(&sh4_tr_ops, &ctx.base, cs, tb, max_insns);
2377 void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb,
2378 target_ulong *data)
2380 env->pc = data[0];
2381 env->flags = data[1];
2382 /* Theoretically delayed_pc should also be restored. In practice the
2383 branch instruction is re-executed after exception, so the delayed
2384 branch target will be recomputed. */