target/mips/mxu: Add Q8ADDE Q8ACCE D8SUM D8SUMC instructions
[qemu/kevin.git] / target / sh4 / translate.c
blob49c87d7a011c3d6d5f9f4a4ecbe76c8a65eef922
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 #include "qemu/osdep.h"
21 #include "cpu.h"
22 #include "disas/disas.h"
23 #include "exec/exec-all.h"
24 #include "tcg/tcg-op.h"
25 #include "exec/cpu_ldst.h"
26 #include "exec/helper-proto.h"
27 #include "exec/helper-gen.h"
28 #include "exec/translator.h"
29 #include "exec/log.h"
30 #include "qemu/qemu-print.h"
32 #define HELPER_H "helper.h"
33 #include "exec/helper-info.c.inc"
34 #undef HELPER_H
37 typedef struct DisasContext {
38 DisasContextBase base;
40 uint32_t tbflags; /* should stay unmodified during the TB translation */
41 uint32_t envflags; /* should stay in sync with env->flags using TCG ops */
42 int memidx;
43 int gbank;
44 int fbank;
45 uint32_t delayed_pc;
46 uint32_t features;
48 uint16_t opcode;
50 bool has_movcal;
51 } DisasContext;
53 #if defined(CONFIG_USER_ONLY)
54 #define IS_USER(ctx) 1
55 #define UNALIGN(C) (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN)
56 #else
57 #define IS_USER(ctx) (!(ctx->tbflags & (1u << SR_MD)))
58 #define UNALIGN(C) 0
59 #endif
61 /* Target-specific values for ctx->base.is_jmp. */
62 /* We want to exit back to the cpu loop for some reason.
63 Usually this is to recognize interrupts immediately. */
64 #define DISAS_STOP DISAS_TARGET_0
66 /* global register indexes */
67 static TCGv cpu_gregs[32];
68 static TCGv cpu_sr, cpu_sr_m, cpu_sr_q, cpu_sr_t;
69 static TCGv cpu_pc, cpu_ssr, cpu_spc, cpu_gbr;
70 static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl;
71 static TCGv cpu_pr, cpu_fpscr, cpu_fpul;
72 static TCGv cpu_lock_addr, cpu_lock_value;
73 static TCGv cpu_fregs[32];
75 /* internal register indexes */
76 static TCGv cpu_flags, cpu_delayed_pc, cpu_delayed_cond;
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_fprintf(f, "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 & TB_FLAG_DELAY_SLOT) {
179 qemu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
180 env->delayed_pc);
181 } else if (env->flags & TB_FLAG_DELAY_SLOT_COND) {
182 qemu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
183 env->delayed_pc);
184 } else if (env->flags & TB_FLAG_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);
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 & TB_FLAG_GUSA_EXCLUSIVE) != 0;
228 static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
230 if (use_exit_tb(ctx)) {
231 return false;
233 return translator_use_goto_tb(&ctx->base, dest);
236 static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
238 if (use_goto_tb(ctx, dest)) {
239 tcg_gen_goto_tb(n);
240 tcg_gen_movi_i32(cpu_pc, dest);
241 tcg_gen_exit_tb(ctx->base.tb, n);
242 } else {
243 tcg_gen_movi_i32(cpu_pc, dest);
244 if (use_exit_tb(ctx)) {
245 tcg_gen_exit_tb(NULL, 0);
246 } else {
247 tcg_gen_lookup_and_goto_ptr();
250 ctx->base.is_jmp = DISAS_NORETURN;
253 static void gen_jump(DisasContext * ctx)
255 if (ctx->delayed_pc == -1) {
256 /* Target is not statically known, it comes necessarily from a
257 delayed jump as immediate jump are conditinal jumps */
258 tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc);
259 tcg_gen_discard_i32(cpu_delayed_pc);
260 if (use_exit_tb(ctx)) {
261 tcg_gen_exit_tb(NULL, 0);
262 } else {
263 tcg_gen_lookup_and_goto_ptr();
265 ctx->base.is_jmp = DISAS_NORETURN;
266 } else {
267 gen_goto_tb(ctx, 0, ctx->delayed_pc);
271 /* Immediate conditional jump (bt or bf) */
272 static void gen_conditional_jump(DisasContext *ctx, target_ulong dest,
273 bool jump_if_true)
275 TCGLabel *l1 = gen_new_label();
276 TCGCond cond_not_taken = jump_if_true ? TCG_COND_EQ : TCG_COND_NE;
278 if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
279 /* When in an exclusive region, we must continue to the end.
280 Therefore, exit the region on a taken branch, but otherwise
281 fall through to the next instruction. */
282 tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
283 tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~TB_FLAG_GUSA_MASK);
284 /* Note that this won't actually use a goto_tb opcode because we
285 disallow it in use_goto_tb, but it handles exit + singlestep. */
286 gen_goto_tb(ctx, 0, dest);
287 gen_set_label(l1);
288 ctx->base.is_jmp = DISAS_NEXT;
289 return;
292 gen_save_cpu_state(ctx, false);
293 tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
294 gen_goto_tb(ctx, 0, dest);
295 gen_set_label(l1);
296 gen_goto_tb(ctx, 1, ctx->base.pc_next + 2);
297 ctx->base.is_jmp = DISAS_NORETURN;
300 /* Delayed conditional jump (bt or bf) */
301 static void gen_delayed_conditional_jump(DisasContext * ctx)
303 TCGLabel *l1 = gen_new_label();
304 TCGv ds = tcg_temp_new();
306 tcg_gen_mov_i32(ds, cpu_delayed_cond);
307 tcg_gen_discard_i32(cpu_delayed_cond);
309 if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
310 /* When in an exclusive region, we must continue to the end.
311 Therefore, exit the region on a taken branch, but otherwise
312 fall through to the next instruction. */
313 tcg_gen_brcondi_i32(TCG_COND_EQ, ds, 0, l1);
315 /* Leave the gUSA region. */
316 tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~TB_FLAG_GUSA_MASK);
317 gen_jump(ctx);
319 gen_set_label(l1);
320 ctx->base.is_jmp = DISAS_NEXT;
321 return;
324 tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
325 gen_goto_tb(ctx, 1, ctx->base.pc_next + 2);
326 gen_set_label(l1);
327 gen_jump(ctx);
330 static inline void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
332 /* We have already signaled illegal instruction for odd Dr. */
333 tcg_debug_assert((reg & 1) == 0);
334 reg ^= ctx->fbank;
335 tcg_gen_concat_i32_i64(t, cpu_fregs[reg + 1], cpu_fregs[reg]);
338 static inline void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
340 /* We have already signaled illegal instruction for odd Dr. */
341 tcg_debug_assert((reg & 1) == 0);
342 reg ^= ctx->fbank;
343 tcg_gen_extr_i64_i32(cpu_fregs[reg + 1], cpu_fregs[reg], t);
346 #define B3_0 (ctx->opcode & 0xf)
347 #define B6_4 ((ctx->opcode >> 4) & 0x7)
348 #define B7_4 ((ctx->opcode >> 4) & 0xf)
349 #define B7_0 (ctx->opcode & 0xff)
350 #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
351 #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
352 (ctx->opcode & 0xfff))
353 #define B11_8 ((ctx->opcode >> 8) & 0xf)
354 #define B15_12 ((ctx->opcode >> 12) & 0xf)
356 #define REG(x) cpu_gregs[(x) ^ ctx->gbank]
357 #define ALTREG(x) cpu_gregs[(x) ^ ctx->gbank ^ 0x10]
358 #define FREG(x) cpu_fregs[(x) ^ ctx->fbank]
360 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
362 #define CHECK_NOT_DELAY_SLOT \
363 if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) { \
364 goto do_illegal_slot; \
367 #define CHECK_PRIVILEGED \
368 if (IS_USER(ctx)) { \
369 goto do_illegal; \
372 #define CHECK_FPU_ENABLED \
373 if (ctx->tbflags & (1u << SR_FD)) { \
374 goto do_fpu_disabled; \
377 #define CHECK_FPSCR_PR_0 \
378 if (ctx->tbflags & FPSCR_PR) { \
379 goto do_illegal; \
382 #define CHECK_FPSCR_PR_1 \
383 if (!(ctx->tbflags & FPSCR_PR)) { \
384 goto do_illegal; \
387 #define CHECK_SH4A \
388 if (!(ctx->features & SH_FEATURE_SH4A)) { \
389 goto do_illegal; \
392 static void _decode_opc(DisasContext * ctx)
394 /* This code tries to make movcal emulation sufficiently
395 accurate for Linux purposes. This instruction writes
396 memory, and prior to that, always allocates a cache line.
397 It is used in two contexts:
398 - in memcpy, where data is copied in blocks, the first write
399 of to a block uses movca.l for performance.
400 - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used
401 to flush the cache. Here, the data written by movcal.l is never
402 written to memory, and the data written is just bogus.
404 To simulate this, we simulate movcal.l, we store the value to memory,
405 but we also remember the previous content. If we see ocbi, we check
406 if movcal.l for that address was done previously. If so, the write should
407 not have hit the memory, so we restore the previous content.
408 When we see an instruction that is neither movca.l
409 nor ocbi, the previous content is discarded.
411 To optimize, we only try to flush stores when we're at the start of
412 TB, or if we already saw movca.l in this TB and did not flush stores
413 yet. */
414 if (ctx->has_movcal)
416 int opcode = ctx->opcode & 0xf0ff;
417 if (opcode != 0x0093 /* ocbi */
418 && opcode != 0x00c3 /* movca.l */)
420 gen_helper_discard_movcal_backup(cpu_env);
421 ctx->has_movcal = 0;
425 #if 0
426 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
427 #endif
429 switch (ctx->opcode) {
430 case 0x0019: /* div0u */
431 tcg_gen_movi_i32(cpu_sr_m, 0);
432 tcg_gen_movi_i32(cpu_sr_q, 0);
433 tcg_gen_movi_i32(cpu_sr_t, 0);
434 return;
435 case 0x000b: /* rts */
436 CHECK_NOT_DELAY_SLOT
437 tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
438 ctx->envflags |= TB_FLAG_DELAY_SLOT;
439 ctx->delayed_pc = (uint32_t) - 1;
440 return;
441 case 0x0028: /* clrmac */
442 tcg_gen_movi_i32(cpu_mach, 0);
443 tcg_gen_movi_i32(cpu_macl, 0);
444 return;
445 case 0x0048: /* clrs */
446 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(1u << SR_S));
447 return;
448 case 0x0008: /* clrt */
449 tcg_gen_movi_i32(cpu_sr_t, 0);
450 return;
451 case 0x0038: /* ldtlb */
452 CHECK_PRIVILEGED
453 gen_helper_ldtlb(cpu_env);
454 return;
455 case 0x002b: /* rte */
456 CHECK_PRIVILEGED
457 CHECK_NOT_DELAY_SLOT
458 gen_write_sr(cpu_ssr);
459 tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
460 ctx->envflags |= TB_FLAG_DELAY_SLOT_RTE;
461 ctx->delayed_pc = (uint32_t) - 1;
462 ctx->base.is_jmp = DISAS_STOP;
463 return;
464 case 0x0058: /* sets */
465 tcg_gen_ori_i32(cpu_sr, cpu_sr, (1u << SR_S));
466 return;
467 case 0x0018: /* sett */
468 tcg_gen_movi_i32(cpu_sr_t, 1);
469 return;
470 case 0xfbfd: /* frchg */
471 CHECK_FPSCR_PR_0
472 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
473 ctx->base.is_jmp = DISAS_STOP;
474 return;
475 case 0xf3fd: /* fschg */
476 CHECK_FPSCR_PR_0
477 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ);
478 ctx->base.is_jmp = DISAS_STOP;
479 return;
480 case 0xf7fd: /* fpchg */
481 CHECK_SH4A
482 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_PR);
483 ctx->base.is_jmp = DISAS_STOP;
484 return;
485 case 0x0009: /* nop */
486 return;
487 case 0x001b: /* sleep */
488 CHECK_PRIVILEGED
489 tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next + 2);
490 gen_helper_sleep(cpu_env);
491 return;
494 switch (ctx->opcode & 0xf000) {
495 case 0x1000: /* mov.l Rm,@(disp,Rn) */
497 TCGv addr = tcg_temp_new();
498 tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
499 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
500 MO_TEUL | UNALIGN(ctx));
502 return;
503 case 0x5000: /* mov.l @(disp,Rm),Rn */
505 TCGv addr = tcg_temp_new();
506 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
507 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
508 MO_TESL | UNALIGN(ctx));
510 return;
511 case 0xe000: /* mov #imm,Rn */
512 #ifdef CONFIG_USER_ONLY
514 * Detect the start of a gUSA region (mov #-n, r15).
515 * If so, update envflags and end the TB. This will allow us
516 * to see the end of the region (stored in R0) in the next TB.
518 if (B11_8 == 15 && B7_0s < 0 &&
519 (tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
520 ctx->envflags =
521 deposit32(ctx->envflags, TB_FLAG_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_constant_i32(ctx->base.pc_next + 4 + B7_0 * 2);
530 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
531 MO_TESW | MO_ALIGN);
533 return;
534 case 0xd000: /* mov.l @(disp,PC),Rn */
536 TCGv addr = tcg_constant_i32((ctx->base.pc_next + 4 + B7_0 * 4) & ~3);
537 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
538 MO_TESL | MO_ALIGN);
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 |= TB_FLAG_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 |= TB_FLAG_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 */
591 return;
592 case 0x2005: /* mov.w Rm,@-Rn */
594 TCGv addr = tcg_temp_new();
595 tcg_gen_subi_i32(addr, REG(B11_8), 2);
596 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
597 MO_TEUW | UNALIGN(ctx));
598 tcg_gen_mov_i32(REG(B11_8), addr);
600 return;
601 case 0x2006: /* mov.l Rm,@-Rn */
603 TCGv addr = tcg_temp_new();
604 tcg_gen_subi_i32(addr, REG(B11_8), 4);
605 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
606 MO_TEUL | UNALIGN(ctx));
607 tcg_gen_mov_i32(REG(B11_8), addr);
609 return;
610 case 0x6004: /* mov.b @Rm+,Rn */
611 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
612 if ( B11_8 != B7_4 )
613 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1);
614 return;
615 case 0x6005: /* mov.w @Rm+,Rn */
616 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx,
617 MO_TESW | UNALIGN(ctx));
618 if ( B11_8 != B7_4 )
619 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
620 return;
621 case 0x6006: /* mov.l @Rm+,Rn */
622 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx,
623 MO_TESL | UNALIGN(ctx));
624 if ( B11_8 != B7_4 )
625 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
626 return;
627 case 0x0004: /* mov.b Rm,@(R0,Rn) */
629 TCGv addr = tcg_temp_new();
630 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
631 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB);
633 return;
634 case 0x0005: /* mov.w Rm,@(R0,Rn) */
636 TCGv addr = tcg_temp_new();
637 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
638 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
639 MO_TEUW | UNALIGN(ctx));
641 return;
642 case 0x0006: /* mov.l Rm,@(R0,Rn) */
644 TCGv addr = tcg_temp_new();
645 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
646 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
647 MO_TEUL | UNALIGN(ctx));
649 return;
650 case 0x000c: /* mov.b @(R0,Rm),Rn */
652 TCGv addr = tcg_temp_new();
653 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
654 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_SB);
656 return;
657 case 0x000d: /* mov.w @(R0,Rm),Rn */
659 TCGv addr = tcg_temp_new();
660 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
661 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
662 MO_TESW | UNALIGN(ctx));
664 return;
665 case 0x000e: /* mov.l @(R0,Rm),Rn */
667 TCGv addr = tcg_temp_new();
668 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
669 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
670 MO_TESL | UNALIGN(ctx));
672 return;
673 case 0x6008: /* swap.b Rm,Rn */
675 TCGv low = tcg_temp_new();
676 tcg_gen_bswap16_i32(low, REG(B7_4), 0);
677 tcg_gen_deposit_i32(REG(B11_8), REG(B7_4), low, 0, 16);
679 return;
680 case 0x6009: /* swap.w Rm,Rn */
681 tcg_gen_rotli_i32(REG(B11_8), REG(B7_4), 16);
682 return;
683 case 0x200d: /* xtrct Rm,Rn */
685 TCGv high, low;
686 high = tcg_temp_new();
687 tcg_gen_shli_i32(high, REG(B7_4), 16);
688 low = tcg_temp_new();
689 tcg_gen_shri_i32(low, REG(B11_8), 16);
690 tcg_gen_or_i32(REG(B11_8), high, low);
692 return;
693 case 0x300c: /* add Rm,Rn */
694 tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4));
695 return;
696 case 0x300e: /* addc Rm,Rn */
698 TCGv t0, t1;
699 t0 = tcg_constant_tl(0);
700 t1 = tcg_temp_new();
701 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0);
702 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t,
703 REG(B11_8), t0, t1, cpu_sr_t);
705 return;
706 case 0x300f: /* addv Rm,Rn */
708 TCGv t0, t1, t2;
709 t0 = tcg_temp_new();
710 tcg_gen_add_i32(t0, REG(B7_4), REG(B11_8));
711 t1 = tcg_temp_new();
712 tcg_gen_xor_i32(t1, t0, REG(B11_8));
713 t2 = tcg_temp_new();
714 tcg_gen_xor_i32(t2, REG(B7_4), REG(B11_8));
715 tcg_gen_andc_i32(cpu_sr_t, t1, t2);
716 tcg_gen_shri_i32(cpu_sr_t, cpu_sr_t, 31);
717 tcg_gen_mov_i32(REG(B7_4), t0);
719 return;
720 case 0x2009: /* and Rm,Rn */
721 tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4));
722 return;
723 case 0x3000: /* cmp/eq Rm,Rn */
724 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), REG(B7_4));
725 return;
726 case 0x3003: /* cmp/ge Rm,Rn */
727 tcg_gen_setcond_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), REG(B7_4));
728 return;
729 case 0x3007: /* cmp/gt Rm,Rn */
730 tcg_gen_setcond_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), REG(B7_4));
731 return;
732 case 0x3006: /* cmp/hi Rm,Rn */
733 tcg_gen_setcond_i32(TCG_COND_GTU, cpu_sr_t, REG(B11_8), REG(B7_4));
734 return;
735 case 0x3002: /* cmp/hs Rm,Rn */
736 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_sr_t, REG(B11_8), REG(B7_4));
737 return;
738 case 0x200c: /* cmp/str Rm,Rn */
740 TCGv cmp1 = tcg_temp_new();
741 TCGv cmp2 = tcg_temp_new();
742 tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8));
743 tcg_gen_subi_i32(cmp1, cmp2, 0x01010101);
744 tcg_gen_andc_i32(cmp1, cmp1, cmp2);
745 tcg_gen_andi_i32(cmp1, cmp1, 0x80808080);
746 tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0);
748 return;
749 case 0x2007: /* div0s Rm,Rn */
750 tcg_gen_shri_i32(cpu_sr_q, REG(B11_8), 31); /* SR_Q */
751 tcg_gen_shri_i32(cpu_sr_m, REG(B7_4), 31); /* SR_M */
752 tcg_gen_xor_i32(cpu_sr_t, cpu_sr_q, cpu_sr_m); /* SR_T */
753 return;
754 case 0x3004: /* div1 Rm,Rn */
756 TCGv t0 = tcg_temp_new();
757 TCGv t1 = tcg_temp_new();
758 TCGv t2 = tcg_temp_new();
759 TCGv zero = tcg_constant_i32(0);
761 /* shift left arg1, saving the bit being pushed out and inserting
762 T on the right */
763 tcg_gen_shri_i32(t0, REG(B11_8), 31);
764 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
765 tcg_gen_or_i32(REG(B11_8), REG(B11_8), cpu_sr_t);
767 /* Add or subtract arg0 from arg1 depending if Q == M. To avoid
768 using 64-bit temps, we compute arg0's high part from q ^ m, so
769 that it is 0x00000000 when adding the value or 0xffffffff when
770 subtracting it. */
771 tcg_gen_xor_i32(t1, cpu_sr_q, cpu_sr_m);
772 tcg_gen_subi_i32(t1, t1, 1);
773 tcg_gen_neg_i32(t2, REG(B7_4));
774 tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, zero, REG(B7_4), t2);
775 tcg_gen_add2_i32(REG(B11_8), t1, REG(B11_8), zero, t2, t1);
777 /* compute T and Q depending on carry */
778 tcg_gen_andi_i32(t1, t1, 1);
779 tcg_gen_xor_i32(t1, t1, t0);
780 tcg_gen_xori_i32(cpu_sr_t, t1, 1);
781 tcg_gen_xor_i32(cpu_sr_q, cpu_sr_m, t1);
783 return;
784 case 0x300d: /* dmuls.l Rm,Rn */
785 tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
786 return;
787 case 0x3005: /* dmulu.l Rm,Rn */
788 tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
789 return;
790 case 0x600e: /* exts.b Rm,Rn */
791 tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4));
792 return;
793 case 0x600f: /* exts.w Rm,Rn */
794 tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4));
795 return;
796 case 0x600c: /* extu.b Rm,Rn */
797 tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4));
798 return;
799 case 0x600d: /* extu.w Rm,Rn */
800 tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4));
801 return;
802 case 0x000f: /* mac.l @Rm+,@Rn+ */
804 TCGv arg0, arg1;
805 arg0 = tcg_temp_new();
806 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx,
807 MO_TESL | MO_ALIGN);
808 arg1 = tcg_temp_new();
809 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx,
810 MO_TESL | MO_ALIGN);
811 gen_helper_macl(cpu_env, arg0, arg1);
812 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
813 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
815 return;
816 case 0x400f: /* mac.w @Rm+,@Rn+ */
818 TCGv arg0, arg1;
819 arg0 = tcg_temp_new();
820 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx,
821 MO_TESL | MO_ALIGN);
822 arg1 = tcg_temp_new();
823 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx,
824 MO_TESL | MO_ALIGN);
825 gen_helper_macw(cpu_env, arg0, arg1);
826 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2);
827 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
829 return;
830 case 0x0007: /* mul.l Rm,Rn */
831 tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8));
832 return;
833 case 0x200f: /* muls.w Rm,Rn */
835 TCGv arg0, arg1;
836 arg0 = tcg_temp_new();
837 tcg_gen_ext16s_i32(arg0, REG(B7_4));
838 arg1 = tcg_temp_new();
839 tcg_gen_ext16s_i32(arg1, REG(B11_8));
840 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
842 return;
843 case 0x200e: /* mulu.w Rm,Rn */
845 TCGv arg0, arg1;
846 arg0 = tcg_temp_new();
847 tcg_gen_ext16u_i32(arg0, REG(B7_4));
848 arg1 = tcg_temp_new();
849 tcg_gen_ext16u_i32(arg1, REG(B11_8));
850 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
852 return;
853 case 0x600b: /* neg Rm,Rn */
854 tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
855 return;
856 case 0x600a: /* negc Rm,Rn */
858 TCGv t0 = tcg_constant_i32(0);
859 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t,
860 REG(B7_4), t0, cpu_sr_t, t0);
861 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
862 t0, t0, REG(B11_8), cpu_sr_t);
863 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
865 return;
866 case 0x6007: /* not Rm,Rn */
867 tcg_gen_not_i32(REG(B11_8), REG(B7_4));
868 return;
869 case 0x200b: /* or Rm,Rn */
870 tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4));
871 return;
872 case 0x400c: /* shad Rm,Rn */
874 TCGv t0 = tcg_temp_new();
875 TCGv t1 = tcg_temp_new();
876 TCGv t2 = tcg_temp_new();
878 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
880 /* positive case: shift to the left */
881 tcg_gen_shl_i32(t1, REG(B11_8), t0);
883 /* negative case: shift to the right in two steps to
884 correctly handle the -32 case */
885 tcg_gen_xori_i32(t0, t0, 0x1f);
886 tcg_gen_sar_i32(t2, REG(B11_8), t0);
887 tcg_gen_sari_i32(t2, t2, 1);
889 /* select between the two cases */
890 tcg_gen_movi_i32(t0, 0);
891 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
893 return;
894 case 0x400d: /* shld Rm,Rn */
896 TCGv t0 = tcg_temp_new();
897 TCGv t1 = tcg_temp_new();
898 TCGv t2 = tcg_temp_new();
900 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
902 /* positive case: shift to the left */
903 tcg_gen_shl_i32(t1, REG(B11_8), t0);
905 /* negative case: shift to the right in two steps to
906 correctly handle the -32 case */
907 tcg_gen_xori_i32(t0, t0, 0x1f);
908 tcg_gen_shr_i32(t2, REG(B11_8), t0);
909 tcg_gen_shri_i32(t2, t2, 1);
911 /* select between the two cases */
912 tcg_gen_movi_i32(t0, 0);
913 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
915 return;
916 case 0x3008: /* sub Rm,Rn */
917 tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4));
918 return;
919 case 0x300a: /* subc Rm,Rn */
921 TCGv t0, t1;
922 t0 = tcg_constant_tl(0);
923 t1 = tcg_temp_new();
924 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0);
925 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
926 REG(B11_8), t0, t1, cpu_sr_t);
927 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
929 return;
930 case 0x300b: /* subv Rm,Rn */
932 TCGv t0, t1, t2;
933 t0 = tcg_temp_new();
934 tcg_gen_sub_i32(t0, REG(B11_8), REG(B7_4));
935 t1 = tcg_temp_new();
936 tcg_gen_xor_i32(t1, t0, REG(B7_4));
937 t2 = tcg_temp_new();
938 tcg_gen_xor_i32(t2, REG(B11_8), REG(B7_4));
939 tcg_gen_and_i32(t1, t1, t2);
940 tcg_gen_shri_i32(cpu_sr_t, t1, 31);
941 tcg_gen_mov_i32(REG(B11_8), t0);
943 return;
944 case 0x2008: /* tst Rm,Rn */
946 TCGv val = tcg_temp_new();
947 tcg_gen_and_i32(val, REG(B7_4), REG(B11_8));
948 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
950 return;
951 case 0x200a: /* xor Rm,Rn */
952 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4));
953 return;
954 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
955 CHECK_FPU_ENABLED
956 if (ctx->tbflags & FPSCR_SZ) {
957 int xsrc = XHACK(B7_4);
958 int xdst = XHACK(B11_8);
959 tcg_gen_mov_i32(FREG(xdst), FREG(xsrc));
960 tcg_gen_mov_i32(FREG(xdst + 1), FREG(xsrc + 1));
961 } else {
962 tcg_gen_mov_i32(FREG(B11_8), FREG(B7_4));
964 return;
965 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
966 CHECK_FPU_ENABLED
967 if (ctx->tbflags & FPSCR_SZ) {
968 TCGv_i64 fp = tcg_temp_new_i64();
969 gen_load_fpr64(ctx, fp, XHACK(B7_4));
970 tcg_gen_qemu_st_i64(fp, REG(B11_8), ctx->memidx,
971 MO_TEUQ | MO_ALIGN);
972 } else {
973 tcg_gen_qemu_st_i32(FREG(B7_4), REG(B11_8), ctx->memidx,
974 MO_TEUL | MO_ALIGN);
976 return;
977 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
978 CHECK_FPU_ENABLED
979 if (ctx->tbflags & FPSCR_SZ) {
980 TCGv_i64 fp = tcg_temp_new_i64();
981 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx,
982 MO_TEUQ | MO_ALIGN);
983 gen_store_fpr64(ctx, fp, XHACK(B11_8));
984 } else {
985 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx,
986 MO_TEUL | MO_ALIGN);
988 return;
989 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
990 CHECK_FPU_ENABLED
991 if (ctx->tbflags & FPSCR_SZ) {
992 TCGv_i64 fp = tcg_temp_new_i64();
993 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx,
994 MO_TEUQ | MO_ALIGN);
995 gen_store_fpr64(ctx, fp, XHACK(B11_8));
996 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8);
997 } else {
998 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx,
999 MO_TEUL | MO_ALIGN);
1000 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
1002 return;
1003 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
1004 CHECK_FPU_ENABLED
1006 TCGv addr = tcg_temp_new_i32();
1007 if (ctx->tbflags & FPSCR_SZ) {
1008 TCGv_i64 fp = tcg_temp_new_i64();
1009 gen_load_fpr64(ctx, fp, XHACK(B7_4));
1010 tcg_gen_subi_i32(addr, REG(B11_8), 8);
1011 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx,
1012 MO_TEUQ | MO_ALIGN);
1013 } else {
1014 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1015 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx,
1016 MO_TEUL | MO_ALIGN);
1018 tcg_gen_mov_i32(REG(B11_8), addr);
1020 return;
1021 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
1022 CHECK_FPU_ENABLED
1024 TCGv addr = tcg_temp_new_i32();
1025 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
1026 if (ctx->tbflags & FPSCR_SZ) {
1027 TCGv_i64 fp = tcg_temp_new_i64();
1028 tcg_gen_qemu_ld_i64(fp, addr, ctx->memidx,
1029 MO_TEUQ | MO_ALIGN);
1030 gen_store_fpr64(ctx, fp, XHACK(B11_8));
1031 } else {
1032 tcg_gen_qemu_ld_i32(FREG(B11_8), addr, ctx->memidx,
1033 MO_TEUL | MO_ALIGN);
1036 return;
1037 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
1038 CHECK_FPU_ENABLED
1040 TCGv addr = tcg_temp_new();
1041 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
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_qemu_st_i64(fp, addr, ctx->memidx,
1046 MO_TEUQ | MO_ALIGN);
1047 } else {
1048 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx,
1049 MO_TEUL | MO_ALIGN);
1052 return;
1053 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1054 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1055 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1056 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1057 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1058 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1060 CHECK_FPU_ENABLED
1061 if (ctx->tbflags & FPSCR_PR) {
1062 TCGv_i64 fp0, fp1;
1064 if (ctx->opcode & 0x0110) {
1065 goto do_illegal;
1067 fp0 = tcg_temp_new_i64();
1068 fp1 = tcg_temp_new_i64();
1069 gen_load_fpr64(ctx, fp0, B11_8);
1070 gen_load_fpr64(ctx, fp1, B7_4);
1071 switch (ctx->opcode & 0xf00f) {
1072 case 0xf000: /* fadd Rm,Rn */
1073 gen_helper_fadd_DT(fp0, cpu_env, fp0, fp1);
1074 break;
1075 case 0xf001: /* fsub Rm,Rn */
1076 gen_helper_fsub_DT(fp0, cpu_env, fp0, fp1);
1077 break;
1078 case 0xf002: /* fmul Rm,Rn */
1079 gen_helper_fmul_DT(fp0, cpu_env, fp0, fp1);
1080 break;
1081 case 0xf003: /* fdiv Rm,Rn */
1082 gen_helper_fdiv_DT(fp0, cpu_env, fp0, fp1);
1083 break;
1084 case 0xf004: /* fcmp/eq Rm,Rn */
1085 gen_helper_fcmp_eq_DT(cpu_sr_t, cpu_env, fp0, fp1);
1086 return;
1087 case 0xf005: /* fcmp/gt Rm,Rn */
1088 gen_helper_fcmp_gt_DT(cpu_sr_t, cpu_env, fp0, fp1);
1089 return;
1091 gen_store_fpr64(ctx, fp0, B11_8);
1092 } else {
1093 switch (ctx->opcode & 0xf00f) {
1094 case 0xf000: /* fadd Rm,Rn */
1095 gen_helper_fadd_FT(FREG(B11_8), cpu_env,
1096 FREG(B11_8), FREG(B7_4));
1097 break;
1098 case 0xf001: /* fsub Rm,Rn */
1099 gen_helper_fsub_FT(FREG(B11_8), cpu_env,
1100 FREG(B11_8), FREG(B7_4));
1101 break;
1102 case 0xf002: /* fmul Rm,Rn */
1103 gen_helper_fmul_FT(FREG(B11_8), cpu_env,
1104 FREG(B11_8), FREG(B7_4));
1105 break;
1106 case 0xf003: /* fdiv Rm,Rn */
1107 gen_helper_fdiv_FT(FREG(B11_8), cpu_env,
1108 FREG(B11_8), FREG(B7_4));
1109 break;
1110 case 0xf004: /* fcmp/eq Rm,Rn */
1111 gen_helper_fcmp_eq_FT(cpu_sr_t, cpu_env,
1112 FREG(B11_8), FREG(B7_4));
1113 return;
1114 case 0xf005: /* fcmp/gt Rm,Rn */
1115 gen_helper_fcmp_gt_FT(cpu_sr_t, cpu_env,
1116 FREG(B11_8), FREG(B7_4));
1117 return;
1121 return;
1122 case 0xf00e: /* fmac FR0,RM,Rn */
1123 CHECK_FPU_ENABLED
1124 CHECK_FPSCR_PR_0
1125 gen_helper_fmac_FT(FREG(B11_8), cpu_env,
1126 FREG(0), FREG(B7_4), FREG(B11_8));
1127 return;
1130 switch (ctx->opcode & 0xff00) {
1131 case 0xc900: /* and #imm,R0 */
1132 tcg_gen_andi_i32(REG(0), REG(0), B7_0);
1133 return;
1134 case 0xcd00: /* and.b #imm,@(R0,GBR) */
1136 TCGv addr, val;
1137 addr = tcg_temp_new();
1138 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1139 val = tcg_temp_new();
1140 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1141 tcg_gen_andi_i32(val, val, B7_0);
1142 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1144 return;
1145 case 0x8b00: /* bf label */
1146 CHECK_NOT_DELAY_SLOT
1147 gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, false);
1148 return;
1149 case 0x8f00: /* bf/s label */
1150 CHECK_NOT_DELAY_SLOT
1151 tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1);
1152 ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
1153 ctx->envflags |= TB_FLAG_DELAY_SLOT_COND;
1154 return;
1155 case 0x8900: /* bt label */
1156 CHECK_NOT_DELAY_SLOT
1157 gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, true);
1158 return;
1159 case 0x8d00: /* bt/s label */
1160 CHECK_NOT_DELAY_SLOT
1161 tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t);
1162 ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
1163 ctx->envflags |= TB_FLAG_DELAY_SLOT_COND;
1164 return;
1165 case 0x8800: /* cmp/eq #imm,R0 */
1166 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s);
1167 return;
1168 case 0xc400: /* mov.b @(disp,GBR),R0 */
1170 TCGv addr = tcg_temp_new();
1171 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1172 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
1174 return;
1175 case 0xc500: /* mov.w @(disp,GBR),R0 */
1177 TCGv addr = tcg_temp_new();
1178 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1179 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW | MO_ALIGN);
1181 return;
1182 case 0xc600: /* mov.l @(disp,GBR),R0 */
1184 TCGv addr = tcg_temp_new();
1185 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1186 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESL | MO_ALIGN);
1188 return;
1189 case 0xc000: /* mov.b R0,@(disp,GBR) */
1191 TCGv addr = tcg_temp_new();
1192 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1193 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
1195 return;
1196 case 0xc100: /* mov.w R0,@(disp,GBR) */
1198 TCGv addr = tcg_temp_new();
1199 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1200 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW | MO_ALIGN);
1202 return;
1203 case 0xc200: /* mov.l R0,@(disp,GBR) */
1205 TCGv addr = tcg_temp_new();
1206 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1207 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUL | MO_ALIGN);
1209 return;
1210 case 0x8000: /* mov.b R0,@(disp,Rn) */
1212 TCGv addr = tcg_temp_new();
1213 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1214 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
1216 return;
1217 case 0x8100: /* mov.w R0,@(disp,Rn) */
1219 TCGv addr = tcg_temp_new();
1220 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1221 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx,
1222 MO_TEUW | UNALIGN(ctx));
1224 return;
1225 case 0x8400: /* mov.b @(disp,Rn),R0 */
1227 TCGv addr = tcg_temp_new();
1228 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1229 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
1231 return;
1232 case 0x8500: /* mov.w @(disp,Rn),R0 */
1234 TCGv addr = tcg_temp_new();
1235 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1236 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx,
1237 MO_TESW | UNALIGN(ctx));
1239 return;
1240 case 0xc700: /* mova @(disp,PC),R0 */
1241 tcg_gen_movi_i32(REG(0), ((ctx->base.pc_next & 0xfffffffc) +
1242 4 + B7_0 * 4) & ~3);
1243 return;
1244 case 0xcb00: /* or #imm,R0 */
1245 tcg_gen_ori_i32(REG(0), REG(0), B7_0);
1246 return;
1247 case 0xcf00: /* or.b #imm,@(R0,GBR) */
1249 TCGv addr, val;
1250 addr = tcg_temp_new();
1251 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1252 val = tcg_temp_new();
1253 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1254 tcg_gen_ori_i32(val, val, B7_0);
1255 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1257 return;
1258 case 0xc300: /* trapa #imm */
1260 TCGv imm;
1261 CHECK_NOT_DELAY_SLOT
1262 gen_save_cpu_state(ctx, true);
1263 imm = tcg_constant_i32(B7_0);
1264 gen_helper_trapa(cpu_env, imm);
1265 ctx->base.is_jmp = DISAS_NORETURN;
1267 return;
1268 case 0xc800: /* tst #imm,R0 */
1270 TCGv val = tcg_temp_new();
1271 tcg_gen_andi_i32(val, REG(0), B7_0);
1272 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1274 return;
1275 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
1277 TCGv val = tcg_temp_new();
1278 tcg_gen_add_i32(val, REG(0), cpu_gbr);
1279 tcg_gen_qemu_ld_i32(val, val, ctx->memidx, MO_UB);
1280 tcg_gen_andi_i32(val, val, B7_0);
1281 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1283 return;
1284 case 0xca00: /* xor #imm,R0 */
1285 tcg_gen_xori_i32(REG(0), REG(0), B7_0);
1286 return;
1287 case 0xce00: /* xor.b #imm,@(R0,GBR) */
1289 TCGv addr, val;
1290 addr = tcg_temp_new();
1291 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1292 val = tcg_temp_new();
1293 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1294 tcg_gen_xori_i32(val, val, B7_0);
1295 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1297 return;
1300 switch (ctx->opcode & 0xf08f) {
1301 case 0x408e: /* ldc Rm,Rn_BANK */
1302 CHECK_PRIVILEGED
1303 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8));
1304 return;
1305 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
1306 CHECK_PRIVILEGED
1307 tcg_gen_qemu_ld_i32(ALTREG(B6_4), REG(B11_8), ctx->memidx,
1308 MO_TESL | MO_ALIGN);
1309 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1310 return;
1311 case 0x0082: /* stc Rm_BANK,Rn */
1312 CHECK_PRIVILEGED
1313 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4));
1314 return;
1315 case 0x4083: /* stc.l Rm_BANK,@-Rn */
1316 CHECK_PRIVILEGED
1318 TCGv addr = tcg_temp_new();
1319 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1320 tcg_gen_qemu_st_i32(ALTREG(B6_4), addr, ctx->memidx,
1321 MO_TEUL | MO_ALIGN);
1322 tcg_gen_mov_i32(REG(B11_8), addr);
1324 return;
1327 switch (ctx->opcode & 0xf0ff) {
1328 case 0x0023: /* braf Rn */
1329 CHECK_NOT_DELAY_SLOT
1330 tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->base.pc_next + 4);
1331 ctx->envflags |= TB_FLAG_DELAY_SLOT;
1332 ctx->delayed_pc = (uint32_t) - 1;
1333 return;
1334 case 0x0003: /* bsrf Rn */
1335 CHECK_NOT_DELAY_SLOT
1336 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
1337 tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
1338 ctx->envflags |= TB_FLAG_DELAY_SLOT;
1339 ctx->delayed_pc = (uint32_t) - 1;
1340 return;
1341 case 0x4015: /* cmp/pl Rn */
1342 tcg_gen_setcondi_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), 0);
1343 return;
1344 case 0x4011: /* cmp/pz Rn */
1345 tcg_gen_setcondi_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), 0);
1346 return;
1347 case 0x4010: /* dt Rn */
1348 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1);
1349 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), 0);
1350 return;
1351 case 0x402b: /* jmp @Rn */
1352 CHECK_NOT_DELAY_SLOT
1353 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1354 ctx->envflags |= TB_FLAG_DELAY_SLOT;
1355 ctx->delayed_pc = (uint32_t) - 1;
1356 return;
1357 case 0x400b: /* jsr @Rn */
1358 CHECK_NOT_DELAY_SLOT
1359 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
1360 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1361 ctx->envflags |= TB_FLAG_DELAY_SLOT;
1362 ctx->delayed_pc = (uint32_t) - 1;
1363 return;
1364 case 0x400e: /* ldc Rm,SR */
1365 CHECK_PRIVILEGED
1367 TCGv val = tcg_temp_new();
1368 tcg_gen_andi_i32(val, REG(B11_8), 0x700083f3);
1369 gen_write_sr(val);
1370 ctx->base.is_jmp = DISAS_STOP;
1372 return;
1373 case 0x4007: /* ldc.l @Rm+,SR */
1374 CHECK_PRIVILEGED
1376 TCGv val = tcg_temp_new();
1377 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx,
1378 MO_TESL | MO_ALIGN);
1379 tcg_gen_andi_i32(val, val, 0x700083f3);
1380 gen_write_sr(val);
1381 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1382 ctx->base.is_jmp = DISAS_STOP;
1384 return;
1385 case 0x0002: /* stc SR,Rn */
1386 CHECK_PRIVILEGED
1387 gen_read_sr(REG(B11_8));
1388 return;
1389 case 0x4003: /* stc SR,@-Rn */
1390 CHECK_PRIVILEGED
1392 TCGv addr = tcg_temp_new();
1393 TCGv val = tcg_temp_new();
1394 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1395 gen_read_sr(val);
1396 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL | MO_ALIGN);
1397 tcg_gen_mov_i32(REG(B11_8), addr);
1399 return;
1400 #define LD(reg,ldnum,ldpnum,prechk) \
1401 case ldnum: \
1402 prechk \
1403 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \
1404 return; \
1405 case ldpnum: \
1406 prechk \
1407 tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, \
1408 MO_TESL | MO_ALIGN); \
1409 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \
1410 return;
1411 #define ST(reg,stnum,stpnum,prechk) \
1412 case stnum: \
1413 prechk \
1414 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \
1415 return; \
1416 case stpnum: \
1417 prechk \
1419 TCGv addr = tcg_temp_new(); \
1420 tcg_gen_subi_i32(addr, REG(B11_8), 4); \
1421 tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, \
1422 MO_TEUL | MO_ALIGN); \
1423 tcg_gen_mov_i32(REG(B11_8), addr); \
1425 return;
1426 #define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \
1427 LD(reg,ldnum,ldpnum,prechk) \
1428 ST(reg,stnum,stpnum,prechk)
1429 LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {})
1430 LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED)
1431 LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED)
1432 LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED)
1433 ST(sgr, 0x003a, 0x4032, CHECK_PRIVILEGED)
1434 LD(sgr, 0x403a, 0x4036, CHECK_PRIVILEGED CHECK_SH4A)
1435 LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED)
1436 LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {})
1437 LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {})
1438 LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {})
1439 LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED})
1440 case 0x406a: /* lds Rm,FPSCR */
1441 CHECK_FPU_ENABLED
1442 gen_helper_ld_fpscr(cpu_env, REG(B11_8));
1443 ctx->base.is_jmp = DISAS_STOP;
1444 return;
1445 case 0x4066: /* lds.l @Rm+,FPSCR */
1446 CHECK_FPU_ENABLED
1448 TCGv addr = tcg_temp_new();
1449 tcg_gen_qemu_ld_i32(addr, REG(B11_8), ctx->memidx,
1450 MO_TESL | MO_ALIGN);
1451 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1452 gen_helper_ld_fpscr(cpu_env, addr);
1453 ctx->base.is_jmp = DISAS_STOP;
1455 return;
1456 case 0x006a: /* sts FPSCR,Rn */
1457 CHECK_FPU_ENABLED
1458 tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff);
1459 return;
1460 case 0x4062: /* sts FPSCR,@-Rn */
1461 CHECK_FPU_ENABLED
1463 TCGv addr, val;
1464 val = tcg_temp_new();
1465 tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff);
1466 addr = tcg_temp_new();
1467 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1468 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL | MO_ALIGN);
1469 tcg_gen_mov_i32(REG(B11_8), addr);
1471 return;
1472 case 0x00c3: /* movca.l R0,@Rm */
1474 TCGv val = tcg_temp_new();
1475 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx,
1476 MO_TEUL | MO_ALIGN);
1477 gen_helper_movcal(cpu_env, REG(B11_8), val);
1478 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx,
1479 MO_TEUL | MO_ALIGN);
1481 ctx->has_movcal = 1;
1482 return;
1483 case 0x40a9: /* movua.l @Rm,R0 */
1484 CHECK_SH4A
1485 /* Load non-boundary-aligned data */
1486 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1487 MO_TEUL | MO_UNALN);
1488 return;
1489 case 0x40e9: /* movua.l @Rm+,R0 */
1490 CHECK_SH4A
1491 /* Load non-boundary-aligned data */
1492 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1493 MO_TEUL | MO_UNALN);
1494 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1495 return;
1496 case 0x0029: /* movt Rn */
1497 tcg_gen_mov_i32(REG(B11_8), cpu_sr_t);
1498 return;
1499 case 0x0073:
1500 /* MOVCO.L
1501 * LDST -> T
1502 * If (T == 1) R0 -> (Rn)
1503 * 0 -> LDST
1505 * The above description doesn't work in a parallel context.
1506 * Since we currently support no smp boards, this implies user-mode.
1507 * But we can still support the official mechanism while user-mode
1508 * is single-threaded. */
1509 CHECK_SH4A
1511 TCGLabel *fail = gen_new_label();
1512 TCGLabel *done = gen_new_label();
1514 if ((tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
1515 TCGv tmp;
1517 tcg_gen_brcond_i32(TCG_COND_NE, REG(B11_8),
1518 cpu_lock_addr, fail);
1519 tmp = tcg_temp_new();
1520 tcg_gen_atomic_cmpxchg_i32(tmp, REG(B11_8), cpu_lock_value,
1521 REG(0), ctx->memidx,
1522 MO_TEUL | MO_ALIGN);
1523 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, tmp, cpu_lock_value);
1524 } else {
1525 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_lock_addr, -1, fail);
1526 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx,
1527 MO_TEUL | MO_ALIGN);
1528 tcg_gen_movi_i32(cpu_sr_t, 1);
1530 tcg_gen_br(done);
1532 gen_set_label(fail);
1533 tcg_gen_movi_i32(cpu_sr_t, 0);
1535 gen_set_label(done);
1536 tcg_gen_movi_i32(cpu_lock_addr, -1);
1538 return;
1539 case 0x0063:
1540 /* MOVLI.L @Rm,R0
1541 * 1 -> LDST
1542 * (Rm) -> R0
1543 * When interrupt/exception
1544 * occurred 0 -> LDST
1546 * In a parallel context, we must also save the loaded value
1547 * for use with the cmpxchg that we'll use with movco.l. */
1548 CHECK_SH4A
1549 if ((tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
1550 TCGv tmp = tcg_temp_new();
1551 tcg_gen_mov_i32(tmp, REG(B11_8));
1552 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1553 MO_TESL | MO_ALIGN);
1554 tcg_gen_mov_i32(cpu_lock_value, REG(0));
1555 tcg_gen_mov_i32(cpu_lock_addr, tmp);
1556 } else {
1557 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1558 MO_TESL | MO_ALIGN);
1559 tcg_gen_movi_i32(cpu_lock_addr, 0);
1561 return;
1562 case 0x0093: /* ocbi @Rn */
1564 gen_helper_ocbi(cpu_env, REG(B11_8));
1566 return;
1567 case 0x00a3: /* ocbp @Rn */
1568 case 0x00b3: /* ocbwb @Rn */
1569 /* These instructions are supposed to do nothing in case of
1570 a cache miss. Given that we only partially emulate caches
1571 it is safe to simply ignore them. */
1572 return;
1573 case 0x0083: /* pref @Rn */
1574 return;
1575 case 0x00d3: /* prefi @Rn */
1576 CHECK_SH4A
1577 return;
1578 case 0x00e3: /* icbi @Rn */
1579 CHECK_SH4A
1580 return;
1581 case 0x00ab: /* synco */
1582 CHECK_SH4A
1583 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
1584 return;
1585 case 0x4024: /* rotcl Rn */
1587 TCGv tmp = tcg_temp_new();
1588 tcg_gen_mov_i32(tmp, cpu_sr_t);
1589 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
1590 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1591 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
1593 return;
1594 case 0x4025: /* rotcr Rn */
1596 TCGv tmp = tcg_temp_new();
1597 tcg_gen_shli_i32(tmp, cpu_sr_t, 31);
1598 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1599 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1600 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
1602 return;
1603 case 0x4004: /* rotl Rn */
1604 tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1);
1605 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
1606 return;
1607 case 0x4005: /* rotr Rn */
1608 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
1609 tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1);
1610 return;
1611 case 0x4000: /* shll Rn */
1612 case 0x4020: /* shal Rn */
1613 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
1614 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1615 return;
1616 case 0x4021: /* shar Rn */
1617 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1618 tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1);
1619 return;
1620 case 0x4001: /* shlr Rn */
1621 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1622 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1623 return;
1624 case 0x4008: /* shll2 Rn */
1625 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2);
1626 return;
1627 case 0x4018: /* shll8 Rn */
1628 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8);
1629 return;
1630 case 0x4028: /* shll16 Rn */
1631 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16);
1632 return;
1633 case 0x4009: /* shlr2 Rn */
1634 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2);
1635 return;
1636 case 0x4019: /* shlr8 Rn */
1637 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8);
1638 return;
1639 case 0x4029: /* shlr16 Rn */
1640 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16);
1641 return;
1642 case 0x401b: /* tas.b @Rn */
1643 tcg_gen_atomic_fetch_or_i32(cpu_sr_t, REG(B11_8),
1644 tcg_constant_i32(0x80), ctx->memidx, MO_UB);
1645 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, cpu_sr_t, 0);
1646 return;
1647 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1648 CHECK_FPU_ENABLED
1649 tcg_gen_mov_i32(FREG(B11_8), cpu_fpul);
1650 return;
1651 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1652 CHECK_FPU_ENABLED
1653 tcg_gen_mov_i32(cpu_fpul, FREG(B11_8));
1654 return;
1655 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
1656 CHECK_FPU_ENABLED
1657 if (ctx->tbflags & FPSCR_PR) {
1658 TCGv_i64 fp;
1659 if (ctx->opcode & 0x0100) {
1660 goto do_illegal;
1662 fp = tcg_temp_new_i64();
1663 gen_helper_float_DT(fp, cpu_env, cpu_fpul);
1664 gen_store_fpr64(ctx, fp, B11_8);
1666 else {
1667 gen_helper_float_FT(FREG(B11_8), cpu_env, cpu_fpul);
1669 return;
1670 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1671 CHECK_FPU_ENABLED
1672 if (ctx->tbflags & FPSCR_PR) {
1673 TCGv_i64 fp;
1674 if (ctx->opcode & 0x0100) {
1675 goto do_illegal;
1677 fp = tcg_temp_new_i64();
1678 gen_load_fpr64(ctx, fp, B11_8);
1679 gen_helper_ftrc_DT(cpu_fpul, cpu_env, fp);
1681 else {
1682 gen_helper_ftrc_FT(cpu_fpul, cpu_env, FREG(B11_8));
1684 return;
1685 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
1686 CHECK_FPU_ENABLED
1687 tcg_gen_xori_i32(FREG(B11_8), FREG(B11_8), 0x80000000);
1688 return;
1689 case 0xf05d: /* fabs FRn/DRn - FPCSR: Nothing */
1690 CHECK_FPU_ENABLED
1691 tcg_gen_andi_i32(FREG(B11_8), FREG(B11_8), 0x7fffffff);
1692 return;
1693 case 0xf06d: /* fsqrt FRn */
1694 CHECK_FPU_ENABLED
1695 if (ctx->tbflags & FPSCR_PR) {
1696 if (ctx->opcode & 0x0100) {
1697 goto do_illegal;
1699 TCGv_i64 fp = tcg_temp_new_i64();
1700 gen_load_fpr64(ctx, fp, B11_8);
1701 gen_helper_fsqrt_DT(fp, cpu_env, fp);
1702 gen_store_fpr64(ctx, fp, B11_8);
1703 } else {
1704 gen_helper_fsqrt_FT(FREG(B11_8), cpu_env, FREG(B11_8));
1706 return;
1707 case 0xf07d: /* fsrra FRn */
1708 CHECK_FPU_ENABLED
1709 CHECK_FPSCR_PR_0
1710 gen_helper_fsrra_FT(FREG(B11_8), cpu_env, FREG(B11_8));
1711 break;
1712 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
1713 CHECK_FPU_ENABLED
1714 CHECK_FPSCR_PR_0
1715 tcg_gen_movi_i32(FREG(B11_8), 0);
1716 return;
1717 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
1718 CHECK_FPU_ENABLED
1719 CHECK_FPSCR_PR_0
1720 tcg_gen_movi_i32(FREG(B11_8), 0x3f800000);
1721 return;
1722 case 0xf0ad: /* fcnvsd FPUL,DRn */
1723 CHECK_FPU_ENABLED
1725 TCGv_i64 fp = tcg_temp_new_i64();
1726 gen_helper_fcnvsd_FT_DT(fp, cpu_env, cpu_fpul);
1727 gen_store_fpr64(ctx, fp, B11_8);
1729 return;
1730 case 0xf0bd: /* fcnvds DRn,FPUL */
1731 CHECK_FPU_ENABLED
1733 TCGv_i64 fp = tcg_temp_new_i64();
1734 gen_load_fpr64(ctx, fp, B11_8);
1735 gen_helper_fcnvds_DT_FT(cpu_fpul, cpu_env, fp);
1737 return;
1738 case 0xf0ed: /* fipr FVm,FVn */
1739 CHECK_FPU_ENABLED
1740 CHECK_FPSCR_PR_1
1742 TCGv m = tcg_constant_i32((ctx->opcode >> 8) & 3);
1743 TCGv n = tcg_constant_i32((ctx->opcode >> 10) & 3);
1744 gen_helper_fipr(cpu_env, m, n);
1745 return;
1747 break;
1748 case 0xf0fd: /* ftrv XMTRX,FVn */
1749 CHECK_FPU_ENABLED
1750 CHECK_FPSCR_PR_1
1752 if ((ctx->opcode & 0x0300) != 0x0100) {
1753 goto do_illegal;
1755 TCGv n = tcg_constant_i32((ctx->opcode >> 10) & 3);
1756 gen_helper_ftrv(cpu_env, n);
1757 return;
1759 break;
1761 #if 0
1762 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1763 ctx->opcode, ctx->base.pc_next);
1764 fflush(stderr);
1765 #endif
1766 do_illegal:
1767 if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) {
1768 do_illegal_slot:
1769 gen_save_cpu_state(ctx, true);
1770 gen_helper_raise_slot_illegal_instruction(cpu_env);
1771 } else {
1772 gen_save_cpu_state(ctx, true);
1773 gen_helper_raise_illegal_instruction(cpu_env);
1775 ctx->base.is_jmp = DISAS_NORETURN;
1776 return;
1778 do_fpu_disabled:
1779 gen_save_cpu_state(ctx, true);
1780 if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) {
1781 gen_helper_raise_slot_fpu_disable(cpu_env);
1782 } else {
1783 gen_helper_raise_fpu_disable(cpu_env);
1785 ctx->base.is_jmp = DISAS_NORETURN;
1786 return;
1789 static void decode_opc(DisasContext * ctx)
1791 uint32_t old_flags = ctx->envflags;
1793 _decode_opc(ctx);
1795 if (old_flags & TB_FLAG_DELAY_SLOT_MASK) {
1796 /* go out of the delay slot */
1797 ctx->envflags &= ~TB_FLAG_DELAY_SLOT_MASK;
1799 /* When in an exclusive region, we must continue to the end
1800 for conditional branches. */
1801 if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE
1802 && old_flags & TB_FLAG_DELAY_SLOT_COND) {
1803 gen_delayed_conditional_jump(ctx);
1804 return;
1806 /* Otherwise this is probably an invalid gUSA region.
1807 Drop the GUSA bits so the next TB doesn't see them. */
1808 ctx->envflags &= ~TB_FLAG_GUSA_MASK;
1810 tcg_gen_movi_i32(cpu_flags, ctx->envflags);
1811 if (old_flags & TB_FLAG_DELAY_SLOT_COND) {
1812 gen_delayed_conditional_jump(ctx);
1813 } else {
1814 gen_jump(ctx);
1819 #ifdef CONFIG_USER_ONLY
1820 /* For uniprocessors, SH4 uses optimistic restartable atomic sequences.
1821 Upon an interrupt, a real kernel would simply notice magic values in
1822 the registers and reset the PC to the start of the sequence.
1824 For QEMU, we cannot do this in quite the same way. Instead, we notice
1825 the normal start of such a sequence (mov #-x,r15). While we can handle
1826 any sequence via cpu_exec_step_atomic, we can recognize the "normal"
1827 sequences and transform them into atomic operations as seen by the host.
1829 static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
1831 uint16_t insns[5];
1832 int ld_adr, ld_dst, ld_mop;
1833 int op_dst, op_src, op_opc;
1834 int mv_src, mt_dst, st_src, st_mop;
1835 TCGv op_arg;
1836 uint32_t pc = ctx->base.pc_next;
1837 uint32_t pc_end = ctx->base.tb->cs_base;
1838 int max_insns = (pc_end - pc) / 2;
1839 int i;
1841 /* The state machine below will consume only a few insns.
1842 If there are more than that in a region, fail now. */
1843 if (max_insns > ARRAY_SIZE(insns)) {
1844 goto fail;
1847 /* Read all of the insns for the region. */
1848 for (i = 0; i < max_insns; ++i) {
1849 insns[i] = translator_lduw(env, &ctx->base, pc + i * 2);
1852 ld_adr = ld_dst = ld_mop = -1;
1853 mv_src = -1;
1854 op_dst = op_src = op_opc = -1;
1855 mt_dst = -1;
1856 st_src = st_mop = -1;
1857 op_arg = NULL;
1858 i = 0;
1860 #define NEXT_INSN \
1861 do { if (i >= max_insns) goto fail; ctx->opcode = insns[i++]; } while (0)
1864 * Expect a load to begin the region.
1866 NEXT_INSN;
1867 switch (ctx->opcode & 0xf00f) {
1868 case 0x6000: /* mov.b @Rm,Rn */
1869 ld_mop = MO_SB;
1870 break;
1871 case 0x6001: /* mov.w @Rm,Rn */
1872 ld_mop = MO_TESW;
1873 break;
1874 case 0x6002: /* mov.l @Rm,Rn */
1875 ld_mop = MO_TESL;
1876 break;
1877 default:
1878 goto fail;
1880 ld_adr = B7_4;
1881 ld_dst = B11_8;
1882 if (ld_adr == ld_dst) {
1883 goto fail;
1885 /* Unless we see a mov, any two-operand operation must use ld_dst. */
1886 op_dst = ld_dst;
1889 * Expect an optional register move.
1891 NEXT_INSN;
1892 switch (ctx->opcode & 0xf00f) {
1893 case 0x6003: /* mov Rm,Rn */
1895 * Here we want to recognize ld_dst being saved for later consumption,
1896 * or for another input register being copied so that ld_dst need not
1897 * be clobbered during the operation.
1899 op_dst = B11_8;
1900 mv_src = B7_4;
1901 if (op_dst == ld_dst) {
1902 /* Overwriting the load output. */
1903 goto fail;
1905 if (mv_src != ld_dst) {
1906 /* Copying a new input; constrain op_src to match the load. */
1907 op_src = ld_dst;
1909 break;
1911 default:
1912 /* Put back and re-examine as operation. */
1913 --i;
1917 * Expect the operation.
1919 NEXT_INSN;
1920 switch (ctx->opcode & 0xf00f) {
1921 case 0x300c: /* add Rm,Rn */
1922 op_opc = INDEX_op_add_i32;
1923 goto do_reg_op;
1924 case 0x2009: /* and Rm,Rn */
1925 op_opc = INDEX_op_and_i32;
1926 goto do_reg_op;
1927 case 0x200a: /* xor Rm,Rn */
1928 op_opc = INDEX_op_xor_i32;
1929 goto do_reg_op;
1930 case 0x200b: /* or Rm,Rn */
1931 op_opc = INDEX_op_or_i32;
1932 do_reg_op:
1933 /* The operation register should be as expected, and the
1934 other input cannot depend on the load. */
1935 if (op_dst != B11_8) {
1936 goto fail;
1938 if (op_src < 0) {
1939 /* Unconstrainted input. */
1940 op_src = B7_4;
1941 } else if (op_src == B7_4) {
1942 /* Constrained input matched load. All operations are
1943 commutative; "swap" them by "moving" the load output
1944 to the (implicit) first argument and the move source
1945 to the (explicit) second argument. */
1946 op_src = mv_src;
1947 } else {
1948 goto fail;
1950 op_arg = REG(op_src);
1951 break;
1953 case 0x6007: /* not Rm,Rn */
1954 if (ld_dst != B7_4 || mv_src >= 0) {
1955 goto fail;
1957 op_dst = B11_8;
1958 op_opc = INDEX_op_xor_i32;
1959 op_arg = tcg_constant_i32(-1);
1960 break;
1962 case 0x7000 ... 0x700f: /* add #imm,Rn */
1963 if (op_dst != B11_8 || mv_src >= 0) {
1964 goto fail;
1966 op_opc = INDEX_op_add_i32;
1967 op_arg = tcg_constant_i32(B7_0s);
1968 break;
1970 case 0x3000: /* cmp/eq Rm,Rn */
1971 /* Looking for the middle of a compare-and-swap sequence,
1972 beginning with the compare. Operands can be either order,
1973 but with only one overlapping the load. */
1974 if ((ld_dst == B11_8) + (ld_dst == B7_4) != 1 || mv_src >= 0) {
1975 goto fail;
1977 op_opc = INDEX_op_setcond_i32; /* placeholder */
1978 op_src = (ld_dst == B11_8 ? B7_4 : B11_8);
1979 op_arg = REG(op_src);
1981 NEXT_INSN;
1982 switch (ctx->opcode & 0xff00) {
1983 case 0x8b00: /* bf label */
1984 case 0x8f00: /* bf/s label */
1985 if (pc + (i + 1 + B7_0s) * 2 != pc_end) {
1986 goto fail;
1988 if ((ctx->opcode & 0xff00) == 0x8b00) { /* bf label */
1989 break;
1991 /* We're looking to unconditionally modify Rn with the
1992 result of the comparison, within the delay slot of
1993 the branch. This is used by older gcc. */
1994 NEXT_INSN;
1995 if ((ctx->opcode & 0xf0ff) == 0x0029) { /* movt Rn */
1996 mt_dst = B11_8;
1997 } else {
1998 goto fail;
2000 break;
2002 default:
2003 goto fail;
2005 break;
2007 case 0x2008: /* tst Rm,Rn */
2008 /* Looking for a compare-and-swap against zero. */
2009 if (ld_dst != B11_8 || ld_dst != B7_4 || mv_src >= 0) {
2010 goto fail;
2012 op_opc = INDEX_op_setcond_i32;
2013 op_arg = tcg_constant_i32(0);
2015 NEXT_INSN;
2016 if ((ctx->opcode & 0xff00) != 0x8900 /* bt label */
2017 || pc + (i + 1 + B7_0s) * 2 != pc_end) {
2018 goto fail;
2020 break;
2022 default:
2023 /* Put back and re-examine as store. */
2024 --i;
2028 * Expect the store.
2030 /* The store must be the last insn. */
2031 if (i != max_insns - 1) {
2032 goto fail;
2034 NEXT_INSN;
2035 switch (ctx->opcode & 0xf00f) {
2036 case 0x2000: /* mov.b Rm,@Rn */
2037 st_mop = MO_UB;
2038 break;
2039 case 0x2001: /* mov.w Rm,@Rn */
2040 st_mop = MO_UW;
2041 break;
2042 case 0x2002: /* mov.l Rm,@Rn */
2043 st_mop = MO_UL;
2044 break;
2045 default:
2046 goto fail;
2048 /* The store must match the load. */
2049 if (ld_adr != B11_8 || st_mop != (ld_mop & MO_SIZE)) {
2050 goto fail;
2052 st_src = B7_4;
2054 #undef NEXT_INSN
2057 * Emit the operation.
2059 switch (op_opc) {
2060 case -1:
2061 /* No operation found. Look for exchange pattern. */
2062 if (st_src == ld_dst || mv_src >= 0) {
2063 goto fail;
2065 tcg_gen_atomic_xchg_i32(REG(ld_dst), REG(ld_adr), REG(st_src),
2066 ctx->memidx, ld_mop);
2067 break;
2069 case INDEX_op_add_i32:
2070 if (op_dst != st_src) {
2071 goto fail;
2073 if (op_dst == ld_dst && st_mop == MO_UL) {
2074 tcg_gen_atomic_add_fetch_i32(REG(ld_dst), REG(ld_adr),
2075 op_arg, ctx->memidx, ld_mop);
2076 } else {
2077 tcg_gen_atomic_fetch_add_i32(REG(ld_dst), REG(ld_adr),
2078 op_arg, ctx->memidx, ld_mop);
2079 if (op_dst != ld_dst) {
2080 /* Note that mop sizes < 4 cannot use add_fetch
2081 because it won't carry into the higher bits. */
2082 tcg_gen_add_i32(REG(op_dst), REG(ld_dst), op_arg);
2085 break;
2087 case INDEX_op_and_i32:
2088 if (op_dst != st_src) {
2089 goto fail;
2091 if (op_dst == ld_dst) {
2092 tcg_gen_atomic_and_fetch_i32(REG(ld_dst), REG(ld_adr),
2093 op_arg, ctx->memidx, ld_mop);
2094 } else {
2095 tcg_gen_atomic_fetch_and_i32(REG(ld_dst), REG(ld_adr),
2096 op_arg, ctx->memidx, ld_mop);
2097 tcg_gen_and_i32(REG(op_dst), REG(ld_dst), op_arg);
2099 break;
2101 case INDEX_op_or_i32:
2102 if (op_dst != st_src) {
2103 goto fail;
2105 if (op_dst == ld_dst) {
2106 tcg_gen_atomic_or_fetch_i32(REG(ld_dst), REG(ld_adr),
2107 op_arg, ctx->memidx, ld_mop);
2108 } else {
2109 tcg_gen_atomic_fetch_or_i32(REG(ld_dst), REG(ld_adr),
2110 op_arg, ctx->memidx, ld_mop);
2111 tcg_gen_or_i32(REG(op_dst), REG(ld_dst), op_arg);
2113 break;
2115 case INDEX_op_xor_i32:
2116 if (op_dst != st_src) {
2117 goto fail;
2119 if (op_dst == ld_dst) {
2120 tcg_gen_atomic_xor_fetch_i32(REG(ld_dst), REG(ld_adr),
2121 op_arg, ctx->memidx, ld_mop);
2122 } else {
2123 tcg_gen_atomic_fetch_xor_i32(REG(ld_dst), REG(ld_adr),
2124 op_arg, ctx->memidx, ld_mop);
2125 tcg_gen_xor_i32(REG(op_dst), REG(ld_dst), op_arg);
2127 break;
2129 case INDEX_op_setcond_i32:
2130 if (st_src == ld_dst) {
2131 goto fail;
2133 tcg_gen_atomic_cmpxchg_i32(REG(ld_dst), REG(ld_adr), op_arg,
2134 REG(st_src), ctx->memidx, ld_mop);
2135 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(ld_dst), op_arg);
2136 if (mt_dst >= 0) {
2137 tcg_gen_mov_i32(REG(mt_dst), cpu_sr_t);
2139 break;
2141 default:
2142 g_assert_not_reached();
2145 /* The entire region has been translated. */
2146 ctx->envflags &= ~TB_FLAG_GUSA_MASK;
2147 goto done;
2149 fail:
2150 qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n",
2151 pc, pc_end);
2153 /* Restart with the EXCLUSIVE bit set, within a TB run via
2154 cpu_exec_step_atomic holding the exclusive lock. */
2155 ctx->envflags |= TB_FLAG_GUSA_EXCLUSIVE;
2156 gen_save_cpu_state(ctx, false);
2157 gen_helper_exclusive(cpu_env);
2158 ctx->base.is_jmp = DISAS_NORETURN;
2160 /* We're not executing an instruction, but we must report one for the
2161 purposes of accounting within the TB. We might as well report the
2162 entire region consumed via ctx->base.pc_next so that it's immediately
2163 available in the disassembly dump. */
2165 done:
2166 ctx->base.pc_next = pc_end;
2167 ctx->base.num_insns += max_insns - 1;
2170 * Emit insn_start to cover each of the insns in the region.
2171 * This matches an assert in tcg.c making sure that we have
2172 * tb->icount * insn_start.
2174 for (i = 1; i < max_insns; ++i) {
2175 tcg_gen_insn_start(pc + i * 2, ctx->envflags);
2178 #endif
2180 static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
2182 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2183 CPUSH4State *env = cs->env_ptr;
2184 uint32_t tbflags;
2185 int bound;
2187 ctx->tbflags = tbflags = ctx->base.tb->flags;
2188 ctx->envflags = tbflags & TB_FLAG_ENVFLAGS_MASK;
2189 ctx->memidx = (tbflags & (1u << SR_MD)) == 0 ? 1 : 0;
2190 /* We don't know if the delayed pc came from a dynamic or static branch,
2191 so assume it is a dynamic branch. */
2192 ctx->delayed_pc = -1; /* use delayed pc from env pointer */
2193 ctx->features = env->features;
2194 ctx->has_movcal = (tbflags & TB_FLAG_PENDING_MOVCA);
2195 ctx->gbank = ((tbflags & (1 << SR_MD)) &&
2196 (tbflags & (1 << SR_RB))) * 0x10;
2197 ctx->fbank = tbflags & FPSCR_FR ? 0x10 : 0;
2199 #ifdef CONFIG_USER_ONLY
2200 if (tbflags & TB_FLAG_GUSA_MASK) {
2201 /* In gUSA exclusive region. */
2202 uint32_t pc = ctx->base.pc_next;
2203 uint32_t pc_end = ctx->base.tb->cs_base;
2204 int backup = sextract32(ctx->tbflags, TB_FLAG_GUSA_SHIFT, 8);
2205 int max_insns = (pc_end - pc) / 2;
2207 if (pc != pc_end + backup || max_insns < 2) {
2208 /* This is a malformed gUSA region. Don't do anything special,
2209 since the interpreter is likely to get confused. */
2210 ctx->envflags &= ~TB_FLAG_GUSA_MASK;
2211 } else if (tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
2212 /* Regardless of single-stepping or the end of the page,
2213 we must complete execution of the gUSA region while
2214 holding the exclusive lock. */
2215 ctx->base.max_insns = max_insns;
2216 return;
2219 #endif
2221 /* Since the ISA is fixed-width, we can bound by the number
2222 of instructions remaining on the page. */
2223 bound = -(ctx->base.pc_next | TARGET_PAGE_MASK) / 2;
2224 ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
2227 static void sh4_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
2231 static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
2233 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2235 tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags);
2238 static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
2240 CPUSH4State *env = cs->env_ptr;
2241 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2243 #ifdef CONFIG_USER_ONLY
2244 if (unlikely(ctx->envflags & TB_FLAG_GUSA_MASK)
2245 && !(ctx->envflags & TB_FLAG_GUSA_EXCLUSIVE)) {
2246 /* We're in an gUSA region, and we have not already fallen
2247 back on using an exclusive region. Attempt to parse the
2248 region into a single supported atomic operation. Failure
2249 is handled within the parser by raising an exception to
2250 retry using an exclusive region. */
2251 decode_gusa(ctx, env);
2252 return;
2254 #endif
2256 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next);
2257 decode_opc(ctx);
2258 ctx->base.pc_next += 2;
2261 static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
2263 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2265 if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
2266 /* Ending the region of exclusivity. Clear the bits. */
2267 ctx->envflags &= ~TB_FLAG_GUSA_MASK;
2270 switch (ctx->base.is_jmp) {
2271 case DISAS_STOP:
2272 gen_save_cpu_state(ctx, true);
2273 tcg_gen_exit_tb(NULL, 0);
2274 break;
2275 case DISAS_NEXT:
2276 case DISAS_TOO_MANY:
2277 gen_save_cpu_state(ctx, false);
2278 gen_goto_tb(ctx, 0, ctx->base.pc_next);
2279 break;
2280 case DISAS_NORETURN:
2281 break;
2282 default:
2283 g_assert_not_reached();
2287 static void sh4_tr_disas_log(const DisasContextBase *dcbase,
2288 CPUState *cs, FILE *logfile)
2290 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
2291 target_disas(logfile, cs, dcbase->pc_first, dcbase->tb->size);
2294 static const TranslatorOps sh4_tr_ops = {
2295 .init_disas_context = sh4_tr_init_disas_context,
2296 .tb_start = sh4_tr_tb_start,
2297 .insn_start = sh4_tr_insn_start,
2298 .translate_insn = sh4_tr_translate_insn,
2299 .tb_stop = sh4_tr_tb_stop,
2300 .disas_log = sh4_tr_disas_log,
2303 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
2304 target_ulong pc, void *host_pc)
2306 DisasContext ctx;
2308 translator_loop(cs, tb, max_insns, pc, host_pc, &sh4_tr_ops, &ctx.base);