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