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