KVM: add support for any length io eventfd
[qemu/kevin.git] / target-sh4 / translate.c
blob7bc621649a56d3392199e65fcb86ab516e345961
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 "cpu.h"
23 #include "disas/disas.h"
24 #include "tcg-op.h"
25 #include "exec/cpu_ldst.h"
27 #include "exec/helper-proto.h"
28 #include "exec/helper-gen.h"
30 #include "trace-tcg.h"
33 typedef struct DisasContext {
34 struct TranslationBlock *tb;
35 target_ulong pc;
36 uint16_t opcode;
37 uint32_t flags;
38 int bstate;
39 int memidx;
40 uint32_t delayed_pc;
41 int singlestep_enabled;
42 uint32_t features;
43 int has_movcal;
44 } DisasContext;
46 #if defined(CONFIG_USER_ONLY)
47 #define IS_USER(ctx) 1
48 #else
49 #define IS_USER(ctx) (!(ctx->flags & (1u << SR_MD)))
50 #endif
52 enum {
53 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
54 * exception condition
56 BS_STOP = 1, /* We want to stop translation for any reason */
57 BS_BRANCH = 2, /* We reached a branch condition */
58 BS_EXCP = 3, /* We reached an exception condition */
61 /* global register indexes */
62 static TCGv_ptr cpu_env;
63 static TCGv cpu_gregs[24];
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, cpu_ldst;
68 static TCGv cpu_fregs[32];
70 /* internal register indexes */
71 static TCGv cpu_flags, cpu_delayed_pc;
73 #include "exec/gen-icount.h"
75 void sh4_translate_init(void)
77 int i;
78 static int done_init = 0;
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 if (done_init)
98 return;
100 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
102 for (i = 0; i < 24; i++)
103 cpu_gregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
104 offsetof(CPUSH4State, gregs[i]),
105 gregnames[i]);
107 cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
108 offsetof(CPUSH4State, pc), "PC");
109 cpu_sr = tcg_global_mem_new_i32(TCG_AREG0,
110 offsetof(CPUSH4State, sr), "SR");
111 cpu_sr_m = tcg_global_mem_new_i32(TCG_AREG0,
112 offsetof(CPUSH4State, sr_m), "SR_M");
113 cpu_sr_q = tcg_global_mem_new_i32(TCG_AREG0,
114 offsetof(CPUSH4State, sr_q), "SR_Q");
115 cpu_sr_t = tcg_global_mem_new_i32(TCG_AREG0,
116 offsetof(CPUSH4State, sr_t), "SR_T");
117 cpu_ssr = tcg_global_mem_new_i32(TCG_AREG0,
118 offsetof(CPUSH4State, ssr), "SSR");
119 cpu_spc = tcg_global_mem_new_i32(TCG_AREG0,
120 offsetof(CPUSH4State, spc), "SPC");
121 cpu_gbr = tcg_global_mem_new_i32(TCG_AREG0,
122 offsetof(CPUSH4State, gbr), "GBR");
123 cpu_vbr = tcg_global_mem_new_i32(TCG_AREG0,
124 offsetof(CPUSH4State, vbr), "VBR");
125 cpu_sgr = tcg_global_mem_new_i32(TCG_AREG0,
126 offsetof(CPUSH4State, sgr), "SGR");
127 cpu_dbr = tcg_global_mem_new_i32(TCG_AREG0,
128 offsetof(CPUSH4State, dbr), "DBR");
129 cpu_mach = tcg_global_mem_new_i32(TCG_AREG0,
130 offsetof(CPUSH4State, mach), "MACH");
131 cpu_macl = tcg_global_mem_new_i32(TCG_AREG0,
132 offsetof(CPUSH4State, macl), "MACL");
133 cpu_pr = tcg_global_mem_new_i32(TCG_AREG0,
134 offsetof(CPUSH4State, pr), "PR");
135 cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
136 offsetof(CPUSH4State, fpscr), "FPSCR");
137 cpu_fpul = tcg_global_mem_new_i32(TCG_AREG0,
138 offsetof(CPUSH4State, fpul), "FPUL");
140 cpu_flags = tcg_global_mem_new_i32(TCG_AREG0,
141 offsetof(CPUSH4State, flags), "_flags_");
142 cpu_delayed_pc = tcg_global_mem_new_i32(TCG_AREG0,
143 offsetof(CPUSH4State, delayed_pc),
144 "_delayed_pc_");
145 cpu_ldst = tcg_global_mem_new_i32(TCG_AREG0,
146 offsetof(CPUSH4State, ldst), "_ldst_");
148 for (i = 0; i < 32; i++)
149 cpu_fregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
150 offsetof(CPUSH4State, fregs[i]),
151 fregnames[i]);
153 done_init = 1;
156 void superh_cpu_dump_state(CPUState *cs, FILE *f,
157 fprintf_function cpu_fprintf, int flags)
159 SuperHCPU *cpu = SUPERH_CPU(cs);
160 CPUSH4State *env = &cpu->env;
161 int i;
162 cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
163 env->pc, cpu_read_sr(env), env->pr, env->fpscr);
164 cpu_fprintf(f, "spc=0x%08x ssr=0x%08x gbr=0x%08x vbr=0x%08x\n",
165 env->spc, env->ssr, env->gbr, env->vbr);
166 cpu_fprintf(f, "sgr=0x%08x dbr=0x%08x delayed_pc=0x%08x fpul=0x%08x\n",
167 env->sgr, env->dbr, env->delayed_pc, env->fpul);
168 for (i = 0; i < 24; i += 4) {
169 cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
170 i, env->gregs[i], i + 1, env->gregs[i + 1],
171 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
173 if (env->flags & DELAY_SLOT) {
174 cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
175 env->delayed_pc);
176 } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
177 cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
178 env->delayed_pc);
182 static void gen_read_sr(TCGv dst)
184 TCGv t0 = tcg_temp_new();
185 tcg_gen_shli_i32(t0, cpu_sr_q, SR_Q);
186 tcg_gen_or_i32(dst, dst, t0);
187 tcg_gen_shli_i32(t0, cpu_sr_m, SR_M);
188 tcg_gen_or_i32(dst, dst, t0);
189 tcg_gen_shli_i32(t0, cpu_sr_t, SR_T);
190 tcg_gen_or_i32(dst, cpu_sr, t0);
191 tcg_temp_free_i32(t0);
194 static void gen_write_sr(TCGv src)
196 tcg_gen_andi_i32(cpu_sr, src,
197 ~((1u << SR_Q) | (1u << SR_M) | (1u << SR_T)));
198 tcg_gen_shri_i32(cpu_sr_q, src, SR_Q);
199 tcg_gen_andi_i32(cpu_sr_q, cpu_sr_q, 1);
200 tcg_gen_shri_i32(cpu_sr_m, src, SR_M);
201 tcg_gen_andi_i32(cpu_sr_m, cpu_sr_m, 1);
202 tcg_gen_shri_i32(cpu_sr_t, src, SR_T);
203 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
206 static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
208 TranslationBlock *tb;
209 tb = ctx->tb;
211 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
212 !ctx->singlestep_enabled) {
213 /* Use a direct jump if in same page and singlestep not enabled */
214 tcg_gen_goto_tb(n);
215 tcg_gen_movi_i32(cpu_pc, dest);
216 tcg_gen_exit_tb((uintptr_t)tb + n);
217 } else {
218 tcg_gen_movi_i32(cpu_pc, dest);
219 if (ctx->singlestep_enabled)
220 gen_helper_debug(cpu_env);
221 tcg_gen_exit_tb(0);
225 static void gen_jump(DisasContext * ctx)
227 if (ctx->delayed_pc == (uint32_t) - 1) {
228 /* Target is not statically known, it comes necessarily from a
229 delayed jump as immediate jump are conditinal jumps */
230 tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc);
231 if (ctx->singlestep_enabled)
232 gen_helper_debug(cpu_env);
233 tcg_gen_exit_tb(0);
234 } else {
235 gen_goto_tb(ctx, 0, ctx->delayed_pc);
239 static inline void gen_branch_slot(uint32_t delayed_pc, int t)
241 TCGLabel *label = gen_new_label();
242 tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc);
243 tcg_gen_brcondi_i32(t ? TCG_COND_EQ : TCG_COND_NE, cpu_sr_t, 0, label);
244 tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
245 gen_set_label(label);
248 /* Immediate conditional jump (bt or bf) */
249 static void gen_conditional_jump(DisasContext * ctx,
250 target_ulong ift, target_ulong ifnott)
252 TCGLabel *l1 = gen_new_label();
253 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_sr_t, 0, l1);
254 gen_goto_tb(ctx, 0, ifnott);
255 gen_set_label(l1);
256 gen_goto_tb(ctx, 1, ift);
259 /* Delayed conditional jump (bt or bf) */
260 static void gen_delayed_conditional_jump(DisasContext * ctx)
262 TCGLabel *l1;
263 TCGv ds;
265 l1 = gen_new_label();
266 ds = tcg_temp_new();
267 tcg_gen_andi_i32(ds, cpu_flags, DELAY_SLOT_TRUE);
268 tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
269 gen_goto_tb(ctx, 1, ctx->pc + 2);
270 gen_set_label(l1);
271 tcg_gen_andi_i32(cpu_flags, cpu_flags, ~DELAY_SLOT_TRUE);
272 gen_jump(ctx);
275 static inline void gen_store_flags(uint32_t flags)
277 tcg_gen_andi_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
278 tcg_gen_ori_i32(cpu_flags, cpu_flags, flags);
281 static inline void gen_load_fpr64(TCGv_i64 t, int reg)
283 tcg_gen_concat_i32_i64(t, cpu_fregs[reg + 1], cpu_fregs[reg]);
286 static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
288 TCGv_i32 tmp = tcg_temp_new_i32();
289 tcg_gen_extrl_i64_i32(tmp, t);
290 tcg_gen_mov_i32(cpu_fregs[reg + 1], tmp);
291 tcg_gen_shri_i64(t, t, 32);
292 tcg_gen_extrl_i64_i32(tmp, t);
293 tcg_gen_mov_i32(cpu_fregs[reg], tmp);
294 tcg_temp_free_i32(tmp);
297 #define B3_0 (ctx->opcode & 0xf)
298 #define B6_4 ((ctx->opcode >> 4) & 0x7)
299 #define B7_4 ((ctx->opcode >> 4) & 0xf)
300 #define B7_0 (ctx->opcode & 0xff)
301 #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
302 #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
303 (ctx->opcode & 0xfff))
304 #define B11_8 ((ctx->opcode >> 8) & 0xf)
305 #define B15_12 ((ctx->opcode >> 12) & 0xf)
307 #define REG(x) ((x) < 8 && (ctx->flags & (1u << SR_MD))\
308 && (ctx->flags & (1u << SR_RB))\
309 ? (cpu_gregs[x + 16]) : (cpu_gregs[x]))
311 #define ALTREG(x) ((x) < 8 && (!(ctx->flags & (1u << SR_MD))\
312 || !(ctx->flags & (1u << SR_RB)))\
313 ? (cpu_gregs[x + 16]) : (cpu_gregs[x]))
315 #define FREG(x) (ctx->flags & FPSCR_FR ? (x) ^ 0x10 : (x))
316 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
317 #define XREG(x) (ctx->flags & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x))
318 #define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */
320 #define CHECK_NOT_DELAY_SLOT \
321 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
323 tcg_gen_movi_i32(cpu_pc, ctx->pc); \
324 gen_helper_raise_slot_illegal_instruction(cpu_env); \
325 ctx->bstate = BS_BRANCH; \
326 return; \
329 #define CHECK_PRIVILEGED \
330 if (IS_USER(ctx)) { \
331 tcg_gen_movi_i32(cpu_pc, ctx->pc); \
332 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
333 gen_helper_raise_slot_illegal_instruction(cpu_env); \
334 } else { \
335 gen_helper_raise_illegal_instruction(cpu_env); \
337 ctx->bstate = BS_BRANCH; \
338 return; \
341 #define CHECK_FPU_ENABLED \
342 if (ctx->flags & (1u << SR_FD)) { \
343 tcg_gen_movi_i32(cpu_pc, ctx->pc); \
344 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
345 gen_helper_raise_slot_fpu_disable(cpu_env); \
346 } else { \
347 gen_helper_raise_fpu_disable(cpu_env); \
349 ctx->bstate = BS_BRANCH; \
350 return; \
353 static void _decode_opc(DisasContext * ctx)
355 /* This code tries to make movcal emulation sufficiently
356 accurate for Linux purposes. This instruction writes
357 memory, and prior to that, always allocates a cache line.
358 It is used in two contexts:
359 - in memcpy, where data is copied in blocks, the first write
360 of to a block uses movca.l for performance.
361 - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used
362 to flush the cache. Here, the data written by movcal.l is never
363 written to memory, and the data written is just bogus.
365 To simulate this, we simulate movcal.l, we store the value to memory,
366 but we also remember the previous content. If we see ocbi, we check
367 if movcal.l for that address was done previously. If so, the write should
368 not have hit the memory, so we restore the previous content.
369 When we see an instruction that is neither movca.l
370 nor ocbi, the previous content is discarded.
372 To optimize, we only try to flush stores when we're at the start of
373 TB, or if we already saw movca.l in this TB and did not flush stores
374 yet. */
375 if (ctx->has_movcal)
377 int opcode = ctx->opcode & 0xf0ff;
378 if (opcode != 0x0093 /* ocbi */
379 && opcode != 0x00c3 /* movca.l */)
381 gen_helper_discard_movcal_backup(cpu_env);
382 ctx->has_movcal = 0;
386 #if 0
387 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
388 #endif
390 switch (ctx->opcode) {
391 case 0x0019: /* div0u */
392 tcg_gen_movi_i32(cpu_sr_m, 0);
393 tcg_gen_movi_i32(cpu_sr_q, 0);
394 tcg_gen_movi_i32(cpu_sr_t, 0);
395 return;
396 case 0x000b: /* rts */
397 CHECK_NOT_DELAY_SLOT
398 tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
399 ctx->flags |= DELAY_SLOT;
400 ctx->delayed_pc = (uint32_t) - 1;
401 return;
402 case 0x0028: /* clrmac */
403 tcg_gen_movi_i32(cpu_mach, 0);
404 tcg_gen_movi_i32(cpu_macl, 0);
405 return;
406 case 0x0048: /* clrs */
407 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(1u << SR_S));
408 return;
409 case 0x0008: /* clrt */
410 tcg_gen_movi_i32(cpu_sr_t, 0);
411 return;
412 case 0x0038: /* ldtlb */
413 CHECK_PRIVILEGED
414 gen_helper_ldtlb(cpu_env);
415 return;
416 case 0x002b: /* rte */
417 CHECK_PRIVILEGED
418 CHECK_NOT_DELAY_SLOT
419 gen_write_sr(cpu_ssr);
420 tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
421 ctx->flags |= DELAY_SLOT;
422 ctx->delayed_pc = (uint32_t) - 1;
423 return;
424 case 0x0058: /* sets */
425 tcg_gen_ori_i32(cpu_sr, cpu_sr, (1u << SR_S));
426 return;
427 case 0x0018: /* sett */
428 tcg_gen_movi_i32(cpu_sr_t, 1);
429 return;
430 case 0xfbfd: /* frchg */
431 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
432 ctx->bstate = BS_STOP;
433 return;
434 case 0xf3fd: /* fschg */
435 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ);
436 ctx->bstate = BS_STOP;
437 return;
438 case 0x0009: /* nop */
439 return;
440 case 0x001b: /* sleep */
441 CHECK_PRIVILEGED
442 tcg_gen_movi_i32(cpu_pc, ctx->pc + 2);
443 gen_helper_sleep(cpu_env);
444 return;
447 switch (ctx->opcode & 0xf000) {
448 case 0x1000: /* mov.l Rm,@(disp,Rn) */
450 TCGv addr = tcg_temp_new();
451 tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
452 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
453 tcg_temp_free(addr);
455 return;
456 case 0x5000: /* mov.l @(disp,Rm),Rn */
458 TCGv addr = tcg_temp_new();
459 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
460 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
461 tcg_temp_free(addr);
463 return;
464 case 0xe000: /* mov #imm,Rn */
465 tcg_gen_movi_i32(REG(B11_8), B7_0s);
466 return;
467 case 0x9000: /* mov.w @(disp,PC),Rn */
469 TCGv addr = tcg_const_i32(ctx->pc + 4 + B7_0 * 2);
470 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW);
471 tcg_temp_free(addr);
473 return;
474 case 0xd000: /* mov.l @(disp,PC),Rn */
476 TCGv addr = tcg_const_i32((ctx->pc + 4 + B7_0 * 4) & ~3);
477 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
478 tcg_temp_free(addr);
480 return;
481 case 0x7000: /* add #imm,Rn */
482 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s);
483 return;
484 case 0xa000: /* bra disp */
485 CHECK_NOT_DELAY_SLOT
486 ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
487 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
488 ctx->flags |= DELAY_SLOT;
489 return;
490 case 0xb000: /* bsr disp */
491 CHECK_NOT_DELAY_SLOT
492 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
493 ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
494 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
495 ctx->flags |= DELAY_SLOT;
496 return;
499 switch (ctx->opcode & 0xf00f) {
500 case 0x6003: /* mov Rm,Rn */
501 tcg_gen_mov_i32(REG(B11_8), REG(B7_4));
502 return;
503 case 0x2000: /* mov.b Rm,@Rn */
504 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB);
505 return;
506 case 0x2001: /* mov.w Rm,@Rn */
507 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUW);
508 return;
509 case 0x2002: /* mov.l Rm,@Rn */
510 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL);
511 return;
512 case 0x6000: /* mov.b @Rm,Rn */
513 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
514 return;
515 case 0x6001: /* mov.w @Rm,Rn */
516 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW);
517 return;
518 case 0x6002: /* mov.l @Rm,Rn */
519 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL);
520 return;
521 case 0x2004: /* mov.b Rm,@-Rn */
523 TCGv addr = tcg_temp_new();
524 tcg_gen_subi_i32(addr, REG(B11_8), 1);
525 /* might cause re-execution */
526 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB);
527 tcg_gen_mov_i32(REG(B11_8), addr); /* modify register status */
528 tcg_temp_free(addr);
530 return;
531 case 0x2005: /* mov.w Rm,@-Rn */
533 TCGv addr = tcg_temp_new();
534 tcg_gen_subi_i32(addr, REG(B11_8), 2);
535 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW);
536 tcg_gen_mov_i32(REG(B11_8), addr);
537 tcg_temp_free(addr);
539 return;
540 case 0x2006: /* mov.l Rm,@-Rn */
542 TCGv addr = tcg_temp_new();
543 tcg_gen_subi_i32(addr, REG(B11_8), 4);
544 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
545 tcg_gen_mov_i32(REG(B11_8), addr);
547 return;
548 case 0x6004: /* mov.b @Rm+,Rn */
549 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
550 if ( B11_8 != B7_4 )
551 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1);
552 return;
553 case 0x6005: /* mov.w @Rm+,Rn */
554 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW);
555 if ( B11_8 != B7_4 )
556 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
557 return;
558 case 0x6006: /* mov.l @Rm+,Rn */
559 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL);
560 if ( B11_8 != B7_4 )
561 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
562 return;
563 case 0x0004: /* mov.b Rm,@(R0,Rn) */
565 TCGv addr = tcg_temp_new();
566 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
567 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB);
568 tcg_temp_free(addr);
570 return;
571 case 0x0005: /* mov.w Rm,@(R0,Rn) */
573 TCGv addr = tcg_temp_new();
574 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
575 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW);
576 tcg_temp_free(addr);
578 return;
579 case 0x0006: /* mov.l Rm,@(R0,Rn) */
581 TCGv addr = tcg_temp_new();
582 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
583 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
584 tcg_temp_free(addr);
586 return;
587 case 0x000c: /* mov.b @(R0,Rm),Rn */
589 TCGv addr = tcg_temp_new();
590 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
591 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_SB);
592 tcg_temp_free(addr);
594 return;
595 case 0x000d: /* mov.w @(R0,Rm),Rn */
597 TCGv addr = tcg_temp_new();
598 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
599 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW);
600 tcg_temp_free(addr);
602 return;
603 case 0x000e: /* mov.l @(R0,Rm),Rn */
605 TCGv addr = tcg_temp_new();
606 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
607 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
608 tcg_temp_free(addr);
610 return;
611 case 0x6008: /* swap.b Rm,Rn */
613 TCGv low = tcg_temp_new();;
614 tcg_gen_ext16u_i32(low, REG(B7_4));
615 tcg_gen_bswap16_i32(low, low);
616 tcg_gen_deposit_i32(REG(B11_8), REG(B7_4), low, 0, 16);
617 tcg_temp_free(low);
619 return;
620 case 0x6009: /* swap.w Rm,Rn */
621 tcg_gen_rotli_i32(REG(B11_8), REG(B7_4), 16);
622 return;
623 case 0x200d: /* xtrct Rm,Rn */
625 TCGv high, low;
626 high = tcg_temp_new();
627 tcg_gen_shli_i32(high, REG(B7_4), 16);
628 low = tcg_temp_new();
629 tcg_gen_shri_i32(low, REG(B11_8), 16);
630 tcg_gen_or_i32(REG(B11_8), high, low);
631 tcg_temp_free(low);
632 tcg_temp_free(high);
634 return;
635 case 0x300c: /* add Rm,Rn */
636 tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4));
637 return;
638 case 0x300e: /* addc Rm,Rn */
640 TCGv t0, t1;
641 t0 = tcg_const_tl(0);
642 t1 = tcg_temp_new();
643 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0);
644 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t,
645 REG(B11_8), t0, t1, cpu_sr_t);
646 tcg_temp_free(t0);
647 tcg_temp_free(t1);
649 return;
650 case 0x300f: /* addv Rm,Rn */
652 TCGv t0, t1, t2;
653 t0 = tcg_temp_new();
654 tcg_gen_add_i32(t0, REG(B7_4), REG(B11_8));
655 t1 = tcg_temp_new();
656 tcg_gen_xor_i32(t1, t0, REG(B11_8));
657 t2 = tcg_temp_new();
658 tcg_gen_xor_i32(t2, REG(B7_4), REG(B11_8));
659 tcg_gen_andc_i32(cpu_sr_t, t1, t2);
660 tcg_temp_free(t2);
661 tcg_gen_shri_i32(cpu_sr_t, cpu_sr_t, 31);
662 tcg_temp_free(t1);
663 tcg_gen_mov_i32(REG(B7_4), t0);
664 tcg_temp_free(t0);
666 return;
667 case 0x2009: /* and Rm,Rn */
668 tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4));
669 return;
670 case 0x3000: /* cmp/eq Rm,Rn */
671 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), REG(B7_4));
672 return;
673 case 0x3003: /* cmp/ge Rm,Rn */
674 tcg_gen_setcond_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), REG(B7_4));
675 return;
676 case 0x3007: /* cmp/gt Rm,Rn */
677 tcg_gen_setcond_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), REG(B7_4));
678 return;
679 case 0x3006: /* cmp/hi Rm,Rn */
680 tcg_gen_setcond_i32(TCG_COND_GTU, cpu_sr_t, REG(B11_8), REG(B7_4));
681 return;
682 case 0x3002: /* cmp/hs Rm,Rn */
683 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_sr_t, REG(B11_8), REG(B7_4));
684 return;
685 case 0x200c: /* cmp/str Rm,Rn */
687 TCGv cmp1 = tcg_temp_new();
688 TCGv cmp2 = tcg_temp_new();
689 tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8));
690 tcg_gen_subi_i32(cmp1, cmp2, 0x01010101);
691 tcg_gen_andc_i32(cmp1, cmp1, cmp2);
692 tcg_gen_andi_i32(cmp1, cmp1, 0x80808080);
693 tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0);
694 tcg_temp_free(cmp2);
695 tcg_temp_free(cmp1);
697 return;
698 case 0x2007: /* div0s Rm,Rn */
699 tcg_gen_shri_i32(cpu_sr_q, REG(B11_8), 31); /* SR_Q */
700 tcg_gen_shri_i32(cpu_sr_m, REG(B7_4), 31); /* SR_M */
701 tcg_gen_xor_i32(cpu_sr_t, cpu_sr_q, cpu_sr_m); /* SR_T */
702 return;
703 case 0x3004: /* div1 Rm,Rn */
705 TCGv t0 = tcg_temp_new();
706 TCGv t1 = tcg_temp_new();
707 TCGv t2 = tcg_temp_new();
708 TCGv zero = tcg_const_i32(0);
710 /* shift left arg1, saving the bit being pushed out and inserting
711 T on the right */
712 tcg_gen_shri_i32(t0, REG(B11_8), 31);
713 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
714 tcg_gen_or_i32(REG(B11_8), REG(B11_8), cpu_sr_t);
716 /* Add or subtract arg0 from arg1 depending if Q == M. To avoid
717 using 64-bit temps, we compute arg0's high part from q ^ m, so
718 that it is 0x00000000 when adding the value or 0xffffffff when
719 subtracting it. */
720 tcg_gen_xor_i32(t1, cpu_sr_q, cpu_sr_m);
721 tcg_gen_subi_i32(t1, t1, 1);
722 tcg_gen_neg_i32(t2, REG(B7_4));
723 tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, zero, REG(B7_4), t2);
724 tcg_gen_add2_i32(REG(B11_8), t1, REG(B11_8), zero, t2, t1);
726 /* compute T and Q depending on carry */
727 tcg_gen_andi_i32(t1, t1, 1);
728 tcg_gen_xor_i32(t1, t1, t0);
729 tcg_gen_xori_i32(cpu_sr_t, t1, 1);
730 tcg_gen_xor_i32(cpu_sr_q, cpu_sr_m, t1);
732 tcg_temp_free(zero);
733 tcg_temp_free(t2);
734 tcg_temp_free(t1);
735 tcg_temp_free(t0);
737 return;
738 case 0x300d: /* dmuls.l Rm,Rn */
739 tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
740 return;
741 case 0x3005: /* dmulu.l Rm,Rn */
742 tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
743 return;
744 case 0x600e: /* exts.b Rm,Rn */
745 tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4));
746 return;
747 case 0x600f: /* exts.w Rm,Rn */
748 tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4));
749 return;
750 case 0x600c: /* extu.b Rm,Rn */
751 tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4));
752 return;
753 case 0x600d: /* extu.w Rm,Rn */
754 tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4));
755 return;
756 case 0x000f: /* mac.l @Rm+,@Rn+ */
758 TCGv arg0, arg1;
759 arg0 = tcg_temp_new();
760 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL);
761 arg1 = tcg_temp_new();
762 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL);
763 gen_helper_macl(cpu_env, arg0, arg1);
764 tcg_temp_free(arg1);
765 tcg_temp_free(arg0);
766 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
767 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
769 return;
770 case 0x400f: /* mac.w @Rm+,@Rn+ */
772 TCGv arg0, arg1;
773 arg0 = tcg_temp_new();
774 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL);
775 arg1 = tcg_temp_new();
776 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL);
777 gen_helper_macw(cpu_env, arg0, arg1);
778 tcg_temp_free(arg1);
779 tcg_temp_free(arg0);
780 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2);
781 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
783 return;
784 case 0x0007: /* mul.l Rm,Rn */
785 tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8));
786 return;
787 case 0x200f: /* muls.w Rm,Rn */
789 TCGv arg0, arg1;
790 arg0 = tcg_temp_new();
791 tcg_gen_ext16s_i32(arg0, REG(B7_4));
792 arg1 = tcg_temp_new();
793 tcg_gen_ext16s_i32(arg1, REG(B11_8));
794 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
795 tcg_temp_free(arg1);
796 tcg_temp_free(arg0);
798 return;
799 case 0x200e: /* mulu.w Rm,Rn */
801 TCGv arg0, arg1;
802 arg0 = tcg_temp_new();
803 tcg_gen_ext16u_i32(arg0, REG(B7_4));
804 arg1 = tcg_temp_new();
805 tcg_gen_ext16u_i32(arg1, REG(B11_8));
806 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
807 tcg_temp_free(arg1);
808 tcg_temp_free(arg0);
810 return;
811 case 0x600b: /* neg Rm,Rn */
812 tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
813 return;
814 case 0x600a: /* negc Rm,Rn */
816 TCGv t0 = tcg_const_i32(0);
817 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t,
818 REG(B7_4), t0, cpu_sr_t, t0);
819 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
820 t0, t0, REG(B11_8), cpu_sr_t);
821 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
822 tcg_temp_free(t0);
824 return;
825 case 0x6007: /* not Rm,Rn */
826 tcg_gen_not_i32(REG(B11_8), REG(B7_4));
827 return;
828 case 0x200b: /* or Rm,Rn */
829 tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4));
830 return;
831 case 0x400c: /* shad Rm,Rn */
833 TCGv t0 = tcg_temp_new();
834 TCGv t1 = tcg_temp_new();
835 TCGv t2 = tcg_temp_new();
837 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
839 /* positive case: shift to the left */
840 tcg_gen_shl_i32(t1, REG(B11_8), t0);
842 /* negative case: shift to the right in two steps to
843 correctly handle the -32 case */
844 tcg_gen_xori_i32(t0, t0, 0x1f);
845 tcg_gen_sar_i32(t2, REG(B11_8), t0);
846 tcg_gen_sari_i32(t2, t2, 1);
848 /* select between the two cases */
849 tcg_gen_movi_i32(t0, 0);
850 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
852 tcg_temp_free(t0);
853 tcg_temp_free(t1);
854 tcg_temp_free(t2);
856 return;
857 case 0x400d: /* shld Rm,Rn */
859 TCGv t0 = tcg_temp_new();
860 TCGv t1 = tcg_temp_new();
861 TCGv t2 = tcg_temp_new();
863 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
865 /* positive case: shift to the left */
866 tcg_gen_shl_i32(t1, REG(B11_8), t0);
868 /* negative case: shift to the right in two steps to
869 correctly handle the -32 case */
870 tcg_gen_xori_i32(t0, t0, 0x1f);
871 tcg_gen_shr_i32(t2, REG(B11_8), t0);
872 tcg_gen_shri_i32(t2, t2, 1);
874 /* select between the two cases */
875 tcg_gen_movi_i32(t0, 0);
876 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
878 tcg_temp_free(t0);
879 tcg_temp_free(t1);
880 tcg_temp_free(t2);
882 return;
883 case 0x3008: /* sub Rm,Rn */
884 tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4));
885 return;
886 case 0x300a: /* subc Rm,Rn */
888 TCGv t0, t1;
889 t0 = tcg_const_tl(0);
890 t1 = tcg_temp_new();
891 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0);
892 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
893 REG(B11_8), t0, t1, cpu_sr_t);
894 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
895 tcg_temp_free(t0);
896 tcg_temp_free(t1);
898 return;
899 case 0x300b: /* subv Rm,Rn */
901 TCGv t0, t1, t2;
902 t0 = tcg_temp_new();
903 tcg_gen_sub_i32(t0, REG(B11_8), REG(B7_4));
904 t1 = tcg_temp_new();
905 tcg_gen_xor_i32(t1, t0, REG(B7_4));
906 t2 = tcg_temp_new();
907 tcg_gen_xor_i32(t2, REG(B11_8), REG(B7_4));
908 tcg_gen_and_i32(t1, t1, t2);
909 tcg_temp_free(t2);
910 tcg_gen_shri_i32(cpu_sr_t, t1, 31);
911 tcg_temp_free(t1);
912 tcg_gen_mov_i32(REG(B11_8), t0);
913 tcg_temp_free(t0);
915 return;
916 case 0x2008: /* tst Rm,Rn */
918 TCGv val = tcg_temp_new();
919 tcg_gen_and_i32(val, REG(B7_4), REG(B11_8));
920 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
921 tcg_temp_free(val);
923 return;
924 case 0x200a: /* xor Rm,Rn */
925 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4));
926 return;
927 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
928 CHECK_FPU_ENABLED
929 if (ctx->flags & FPSCR_SZ) {
930 TCGv_i64 fp = tcg_temp_new_i64();
931 gen_load_fpr64(fp, XREG(B7_4));
932 gen_store_fpr64(fp, XREG(B11_8));
933 tcg_temp_free_i64(fp);
934 } else {
935 tcg_gen_mov_i32(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]);
937 return;
938 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
939 CHECK_FPU_ENABLED
940 if (ctx->flags & FPSCR_SZ) {
941 TCGv addr_hi = tcg_temp_new();
942 int fr = XREG(B7_4);
943 tcg_gen_addi_i32(addr_hi, REG(B11_8), 4);
944 tcg_gen_qemu_st_i32(cpu_fregs[fr], REG(B11_8),
945 ctx->memidx, MO_TEUL);
946 tcg_gen_qemu_st_i32(cpu_fregs[fr+1], addr_hi,
947 ctx->memidx, MO_TEUL);
948 tcg_temp_free(addr_hi);
949 } else {
950 tcg_gen_qemu_st_i32(cpu_fregs[FREG(B7_4)], REG(B11_8),
951 ctx->memidx, MO_TEUL);
953 return;
954 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
955 CHECK_FPU_ENABLED
956 if (ctx->flags & FPSCR_SZ) {
957 TCGv addr_hi = tcg_temp_new();
958 int fr = XREG(B11_8);
959 tcg_gen_addi_i32(addr_hi, REG(B7_4), 4);
960 tcg_gen_qemu_ld_i32(cpu_fregs[fr], REG(B7_4), ctx->memidx, MO_TEUL);
961 tcg_gen_qemu_ld_i32(cpu_fregs[fr+1], addr_hi, ctx->memidx, MO_TEUL);
962 tcg_temp_free(addr_hi);
963 } else {
964 tcg_gen_qemu_ld_i32(cpu_fregs[FREG(B11_8)], REG(B7_4),
965 ctx->memidx, MO_TEUL);
967 return;
968 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
969 CHECK_FPU_ENABLED
970 if (ctx->flags & FPSCR_SZ) {
971 TCGv addr_hi = tcg_temp_new();
972 int fr = XREG(B11_8);
973 tcg_gen_addi_i32(addr_hi, REG(B7_4), 4);
974 tcg_gen_qemu_ld_i32(cpu_fregs[fr], REG(B7_4), ctx->memidx, MO_TEUL);
975 tcg_gen_qemu_ld_i32(cpu_fregs[fr+1], addr_hi, ctx->memidx, MO_TEUL);
976 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8);
977 tcg_temp_free(addr_hi);
978 } else {
979 tcg_gen_qemu_ld_i32(cpu_fregs[FREG(B11_8)], REG(B7_4),
980 ctx->memidx, MO_TEUL);
981 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
983 return;
984 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
985 CHECK_FPU_ENABLED
986 TCGv addr = tcg_temp_new_i32();
987 tcg_gen_subi_i32(addr, REG(B11_8), 4);
988 if (ctx->flags & FPSCR_SZ) {
989 int fr = XREG(B7_4);
990 tcg_gen_qemu_st_i32(cpu_fregs[fr+1], addr, ctx->memidx, MO_TEUL);
991 tcg_gen_subi_i32(addr, addr, 4);
992 tcg_gen_qemu_st_i32(cpu_fregs[fr], addr, ctx->memidx, MO_TEUL);
993 } else {
994 tcg_gen_qemu_st_i32(cpu_fregs[FREG(B7_4)], addr,
995 ctx->memidx, MO_TEUL);
997 tcg_gen_mov_i32(REG(B11_8), addr);
998 tcg_temp_free(addr);
999 return;
1000 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
1001 CHECK_FPU_ENABLED
1003 TCGv addr = tcg_temp_new_i32();
1004 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
1005 if (ctx->flags & FPSCR_SZ) {
1006 int fr = XREG(B11_8);
1007 tcg_gen_qemu_ld_i32(cpu_fregs[fr], addr,
1008 ctx->memidx, MO_TEUL);
1009 tcg_gen_addi_i32(addr, addr, 4);
1010 tcg_gen_qemu_ld_i32(cpu_fregs[fr+1], addr,
1011 ctx->memidx, MO_TEUL);
1012 } else {
1013 tcg_gen_qemu_ld_i32(cpu_fregs[FREG(B11_8)], addr,
1014 ctx->memidx, MO_TEUL);
1016 tcg_temp_free(addr);
1018 return;
1019 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
1020 CHECK_FPU_ENABLED
1022 TCGv addr = tcg_temp_new();
1023 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
1024 if (ctx->flags & FPSCR_SZ) {
1025 int fr = XREG(B7_4);
1026 tcg_gen_qemu_ld_i32(cpu_fregs[fr], addr,
1027 ctx->memidx, MO_TEUL);
1028 tcg_gen_addi_i32(addr, addr, 4);
1029 tcg_gen_qemu_ld_i32(cpu_fregs[fr+1], addr,
1030 ctx->memidx, MO_TEUL);
1031 } else {
1032 tcg_gen_qemu_st_i32(cpu_fregs[FREG(B7_4)], addr,
1033 ctx->memidx, MO_TEUL);
1035 tcg_temp_free(addr);
1037 return;
1038 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1039 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1040 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1041 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1042 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1043 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1045 CHECK_FPU_ENABLED
1046 if (ctx->flags & FPSCR_PR) {
1047 TCGv_i64 fp0, fp1;
1049 if (ctx->opcode & 0x0110)
1050 break; /* illegal instruction */
1051 fp0 = tcg_temp_new_i64();
1052 fp1 = tcg_temp_new_i64();
1053 gen_load_fpr64(fp0, DREG(B11_8));
1054 gen_load_fpr64(fp1, DREG(B7_4));
1055 switch (ctx->opcode & 0xf00f) {
1056 case 0xf000: /* fadd Rm,Rn */
1057 gen_helper_fadd_DT(fp0, cpu_env, fp0, fp1);
1058 break;
1059 case 0xf001: /* fsub Rm,Rn */
1060 gen_helper_fsub_DT(fp0, cpu_env, fp0, fp1);
1061 break;
1062 case 0xf002: /* fmul Rm,Rn */
1063 gen_helper_fmul_DT(fp0, cpu_env, fp0, fp1);
1064 break;
1065 case 0xf003: /* fdiv Rm,Rn */
1066 gen_helper_fdiv_DT(fp0, cpu_env, fp0, fp1);
1067 break;
1068 case 0xf004: /* fcmp/eq Rm,Rn */
1069 gen_helper_fcmp_eq_DT(cpu_env, fp0, fp1);
1070 return;
1071 case 0xf005: /* fcmp/gt Rm,Rn */
1072 gen_helper_fcmp_gt_DT(cpu_env, fp0, fp1);
1073 return;
1075 gen_store_fpr64(fp0, DREG(B11_8));
1076 tcg_temp_free_i64(fp0);
1077 tcg_temp_free_i64(fp1);
1078 } else {
1079 switch (ctx->opcode & 0xf00f) {
1080 case 0xf000: /* fadd Rm,Rn */
1081 gen_helper_fadd_FT(cpu_fregs[FREG(B11_8)], cpu_env,
1082 cpu_fregs[FREG(B11_8)],
1083 cpu_fregs[FREG(B7_4)]);
1084 break;
1085 case 0xf001: /* fsub Rm,Rn */
1086 gen_helper_fsub_FT(cpu_fregs[FREG(B11_8)], cpu_env,
1087 cpu_fregs[FREG(B11_8)],
1088 cpu_fregs[FREG(B7_4)]);
1089 break;
1090 case 0xf002: /* fmul Rm,Rn */
1091 gen_helper_fmul_FT(cpu_fregs[FREG(B11_8)], cpu_env,
1092 cpu_fregs[FREG(B11_8)],
1093 cpu_fregs[FREG(B7_4)]);
1094 break;
1095 case 0xf003: /* fdiv Rm,Rn */
1096 gen_helper_fdiv_FT(cpu_fregs[FREG(B11_8)], cpu_env,
1097 cpu_fregs[FREG(B11_8)],
1098 cpu_fregs[FREG(B7_4)]);
1099 break;
1100 case 0xf004: /* fcmp/eq Rm,Rn */
1101 gen_helper_fcmp_eq_FT(cpu_env, cpu_fregs[FREG(B11_8)],
1102 cpu_fregs[FREG(B7_4)]);
1103 return;
1104 case 0xf005: /* fcmp/gt Rm,Rn */
1105 gen_helper_fcmp_gt_FT(cpu_env, cpu_fregs[FREG(B11_8)],
1106 cpu_fregs[FREG(B7_4)]);
1107 return;
1111 return;
1112 case 0xf00e: /* fmac FR0,RM,Rn */
1114 CHECK_FPU_ENABLED
1115 if (ctx->flags & FPSCR_PR) {
1116 break; /* illegal instruction */
1117 } else {
1118 gen_helper_fmac_FT(cpu_fregs[FREG(B11_8)], cpu_env,
1119 cpu_fregs[FREG(0)], cpu_fregs[FREG(B7_4)],
1120 cpu_fregs[FREG(B11_8)]);
1121 return;
1126 switch (ctx->opcode & 0xff00) {
1127 case 0xc900: /* and #imm,R0 */
1128 tcg_gen_andi_i32(REG(0), REG(0), B7_0);
1129 return;
1130 case 0xcd00: /* and.b #imm,@(R0,GBR) */
1132 TCGv addr, val;
1133 addr = tcg_temp_new();
1134 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1135 val = tcg_temp_new();
1136 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1137 tcg_gen_andi_i32(val, val, B7_0);
1138 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1139 tcg_temp_free(val);
1140 tcg_temp_free(addr);
1142 return;
1143 case 0x8b00: /* bf label */
1144 CHECK_NOT_DELAY_SLOT
1145 gen_conditional_jump(ctx, ctx->pc + 2,
1146 ctx->pc + 4 + B7_0s * 2);
1147 ctx->bstate = BS_BRANCH;
1148 return;
1149 case 0x8f00: /* bf/s label */
1150 CHECK_NOT_DELAY_SLOT
1151 gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 0);
1152 ctx->flags |= DELAY_SLOT_CONDITIONAL;
1153 return;
1154 case 0x8900: /* bt label */
1155 CHECK_NOT_DELAY_SLOT
1156 gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2,
1157 ctx->pc + 2);
1158 ctx->bstate = BS_BRANCH;
1159 return;
1160 case 0x8d00: /* bt/s label */
1161 CHECK_NOT_DELAY_SLOT
1162 gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 1);
1163 ctx->flags |= DELAY_SLOT_CONDITIONAL;
1164 return;
1165 case 0x8800: /* cmp/eq #imm,R0 */
1166 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s);
1167 return;
1168 case 0xc400: /* mov.b @(disp,GBR),R0 */
1170 TCGv addr = tcg_temp_new();
1171 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1172 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
1173 tcg_temp_free(addr);
1175 return;
1176 case 0xc500: /* mov.w @(disp,GBR),R0 */
1178 TCGv addr = tcg_temp_new();
1179 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1180 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW);
1181 tcg_temp_free(addr);
1183 return;
1184 case 0xc600: /* mov.l @(disp,GBR),R0 */
1186 TCGv addr = tcg_temp_new();
1187 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1188 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESL);
1189 tcg_temp_free(addr);
1191 return;
1192 case 0xc000: /* mov.b R0,@(disp,GBR) */
1194 TCGv addr = tcg_temp_new();
1195 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1196 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
1197 tcg_temp_free(addr);
1199 return;
1200 case 0xc100: /* mov.w R0,@(disp,GBR) */
1202 TCGv addr = tcg_temp_new();
1203 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1204 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW);
1205 tcg_temp_free(addr);
1207 return;
1208 case 0xc200: /* mov.l R0,@(disp,GBR) */
1210 TCGv addr = tcg_temp_new();
1211 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1212 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUL);
1213 tcg_temp_free(addr);
1215 return;
1216 case 0x8000: /* mov.b R0,@(disp,Rn) */
1218 TCGv addr = tcg_temp_new();
1219 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1220 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
1221 tcg_temp_free(addr);
1223 return;
1224 case 0x8100: /* mov.w R0,@(disp,Rn) */
1226 TCGv addr = tcg_temp_new();
1227 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1228 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW);
1229 tcg_temp_free(addr);
1231 return;
1232 case 0x8400: /* mov.b @(disp,Rn),R0 */
1234 TCGv addr = tcg_temp_new();
1235 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1236 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
1237 tcg_temp_free(addr);
1239 return;
1240 case 0x8500: /* mov.w @(disp,Rn),R0 */
1242 TCGv addr = tcg_temp_new();
1243 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1244 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW);
1245 tcg_temp_free(addr);
1247 return;
1248 case 0xc700: /* mova @(disp,PC),R0 */
1249 tcg_gen_movi_i32(REG(0), ((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3);
1250 return;
1251 case 0xcb00: /* or #imm,R0 */
1252 tcg_gen_ori_i32(REG(0), REG(0), B7_0);
1253 return;
1254 case 0xcf00: /* or.b #imm,@(R0,GBR) */
1256 TCGv addr, val;
1257 addr = tcg_temp_new();
1258 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1259 val = tcg_temp_new();
1260 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1261 tcg_gen_ori_i32(val, val, B7_0);
1262 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1263 tcg_temp_free(val);
1264 tcg_temp_free(addr);
1266 return;
1267 case 0xc300: /* trapa #imm */
1269 TCGv imm;
1270 CHECK_NOT_DELAY_SLOT
1271 tcg_gen_movi_i32(cpu_pc, ctx->pc);
1272 imm = tcg_const_i32(B7_0);
1273 gen_helper_trapa(cpu_env, imm);
1274 tcg_temp_free(imm);
1275 ctx->bstate = BS_BRANCH;
1277 return;
1278 case 0xc800: /* tst #imm,R0 */
1280 TCGv val = tcg_temp_new();
1281 tcg_gen_andi_i32(val, REG(0), B7_0);
1282 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1283 tcg_temp_free(val);
1285 return;
1286 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
1288 TCGv val = tcg_temp_new();
1289 tcg_gen_add_i32(val, REG(0), cpu_gbr);
1290 tcg_gen_qemu_ld_i32(val, val, ctx->memidx, MO_UB);
1291 tcg_gen_andi_i32(val, val, B7_0);
1292 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1293 tcg_temp_free(val);
1295 return;
1296 case 0xca00: /* xor #imm,R0 */
1297 tcg_gen_xori_i32(REG(0), REG(0), B7_0);
1298 return;
1299 case 0xce00: /* xor.b #imm,@(R0,GBR) */
1301 TCGv addr, val;
1302 addr = tcg_temp_new();
1303 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1304 val = tcg_temp_new();
1305 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1306 tcg_gen_xori_i32(val, val, B7_0);
1307 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1308 tcg_temp_free(val);
1309 tcg_temp_free(addr);
1311 return;
1314 switch (ctx->opcode & 0xf08f) {
1315 case 0x408e: /* ldc Rm,Rn_BANK */
1316 CHECK_PRIVILEGED
1317 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8));
1318 return;
1319 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
1320 CHECK_PRIVILEGED
1321 tcg_gen_qemu_ld_i32(ALTREG(B6_4), REG(B11_8), ctx->memidx, MO_TESL);
1322 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1323 return;
1324 case 0x0082: /* stc Rm_BANK,Rn */
1325 CHECK_PRIVILEGED
1326 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4));
1327 return;
1328 case 0x4083: /* stc.l Rm_BANK,@-Rn */
1329 CHECK_PRIVILEGED
1331 TCGv addr = tcg_temp_new();
1332 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1333 tcg_gen_qemu_st_i32(ALTREG(B6_4), addr, ctx->memidx, MO_TEUL);
1334 tcg_gen_mov_i32(REG(B11_8), addr);
1335 tcg_temp_free(addr);
1337 return;
1340 switch (ctx->opcode & 0xf0ff) {
1341 case 0x0023: /* braf Rn */
1342 CHECK_NOT_DELAY_SLOT
1343 tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->pc + 4);
1344 ctx->flags |= DELAY_SLOT;
1345 ctx->delayed_pc = (uint32_t) - 1;
1346 return;
1347 case 0x0003: /* bsrf Rn */
1348 CHECK_NOT_DELAY_SLOT
1349 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
1350 tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
1351 ctx->flags |= DELAY_SLOT;
1352 ctx->delayed_pc = (uint32_t) - 1;
1353 return;
1354 case 0x4015: /* cmp/pl Rn */
1355 tcg_gen_setcondi_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), 0);
1356 return;
1357 case 0x4011: /* cmp/pz Rn */
1358 tcg_gen_setcondi_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), 0);
1359 return;
1360 case 0x4010: /* dt Rn */
1361 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1);
1362 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), 0);
1363 return;
1364 case 0x402b: /* jmp @Rn */
1365 CHECK_NOT_DELAY_SLOT
1366 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1367 ctx->flags |= DELAY_SLOT;
1368 ctx->delayed_pc = (uint32_t) - 1;
1369 return;
1370 case 0x400b: /* jsr @Rn */
1371 CHECK_NOT_DELAY_SLOT
1372 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
1373 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1374 ctx->flags |= DELAY_SLOT;
1375 ctx->delayed_pc = (uint32_t) - 1;
1376 return;
1377 case 0x400e: /* ldc Rm,SR */
1378 CHECK_PRIVILEGED
1380 TCGv val = tcg_temp_new();
1381 tcg_gen_andi_i32(val, REG(B11_8), 0x700083f3);
1382 gen_write_sr(val);
1383 tcg_temp_free(val);
1384 ctx->bstate = BS_STOP;
1386 return;
1387 case 0x4007: /* ldc.l @Rm+,SR */
1388 CHECK_PRIVILEGED
1390 TCGv val = tcg_temp_new();
1391 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TESL);
1392 tcg_gen_andi_i32(val, val, 0x700083f3);
1393 gen_write_sr(val);
1394 tcg_temp_free(val);
1395 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1396 ctx->bstate = BS_STOP;
1398 return;
1399 case 0x0002: /* stc SR,Rn */
1400 CHECK_PRIVILEGED
1401 gen_read_sr(REG(B11_8));
1402 return;
1403 case 0x4003: /* stc SR,@-Rn */
1404 CHECK_PRIVILEGED
1406 TCGv addr = tcg_temp_new();
1407 TCGv val = tcg_temp_new();
1408 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1409 gen_read_sr(val);
1410 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL);
1411 tcg_gen_mov_i32(REG(B11_8), addr);
1412 tcg_temp_free(val);
1413 tcg_temp_free(addr);
1415 return;
1416 #define LD(reg,ldnum,ldpnum,prechk) \
1417 case ldnum: \
1418 prechk \
1419 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \
1420 return; \
1421 case ldpnum: \
1422 prechk \
1423 tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, MO_TESL); \
1424 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \
1425 return;
1426 #define ST(reg,stnum,stpnum,prechk) \
1427 case stnum: \
1428 prechk \
1429 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \
1430 return; \
1431 case stpnum: \
1432 prechk \
1434 TCGv addr = tcg_temp_new(); \
1435 tcg_gen_subi_i32(addr, REG(B11_8), 4); \
1436 tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, MO_TEUL); \
1437 tcg_gen_mov_i32(REG(B11_8), addr); \
1438 tcg_temp_free(addr); \
1440 return;
1441 #define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \
1442 LD(reg,ldnum,ldpnum,prechk) \
1443 ST(reg,stnum,stpnum,prechk)
1444 LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {})
1445 LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED)
1446 LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED)
1447 LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED)
1448 ST(sgr, 0x003a, 0x4032, CHECK_PRIVILEGED)
1449 LD(sgr, 0x403a, 0x4036, CHECK_PRIVILEGED if (!(ctx->features & SH_FEATURE_SH4A)) break;)
1450 LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED)
1451 LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {})
1452 LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {})
1453 LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {})
1454 LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED})
1455 case 0x406a: /* lds Rm,FPSCR */
1456 CHECK_FPU_ENABLED
1457 gen_helper_ld_fpscr(cpu_env, REG(B11_8));
1458 ctx->bstate = BS_STOP;
1459 return;
1460 case 0x4066: /* lds.l @Rm+,FPSCR */
1461 CHECK_FPU_ENABLED
1463 TCGv addr = tcg_temp_new();
1464 tcg_gen_qemu_ld_i32(addr, REG(B11_8), ctx->memidx, MO_TESL);
1465 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1466 gen_helper_ld_fpscr(cpu_env, addr);
1467 tcg_temp_free(addr);
1468 ctx->bstate = BS_STOP;
1470 return;
1471 case 0x006a: /* sts FPSCR,Rn */
1472 CHECK_FPU_ENABLED
1473 tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff);
1474 return;
1475 case 0x4062: /* sts FPSCR,@-Rn */
1476 CHECK_FPU_ENABLED
1478 TCGv addr, val;
1479 val = tcg_temp_new();
1480 tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff);
1481 addr = tcg_temp_new();
1482 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1483 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL);
1484 tcg_gen_mov_i32(REG(B11_8), addr);
1485 tcg_temp_free(addr);
1486 tcg_temp_free(val);
1488 return;
1489 case 0x00c3: /* movca.l R0,@Rm */
1491 TCGv val = tcg_temp_new();
1492 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TEUL);
1493 gen_helper_movcal(cpu_env, REG(B11_8), val);
1494 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
1496 ctx->has_movcal = 1;
1497 return;
1498 case 0x40a9:
1499 /* MOVUA.L @Rm,R0 (Rm) -> R0
1500 Load non-boundary-aligned data */
1501 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
1502 return;
1503 case 0x40e9:
1504 /* MOVUA.L @Rm+,R0 (Rm) -> R0, Rm + 4 -> Rm
1505 Load non-boundary-aligned data */
1506 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
1507 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1508 return;
1509 case 0x0029: /* movt Rn */
1510 tcg_gen_mov_i32(REG(B11_8), cpu_sr_t);
1511 return;
1512 case 0x0073:
1513 /* MOVCO.L
1514 LDST -> T
1515 If (T == 1) R0 -> (Rn)
1516 0 -> LDST
1518 if (ctx->features & SH_FEATURE_SH4A) {
1519 TCGLabel *label = gen_new_label();
1520 tcg_gen_mov_i32(cpu_sr_t, cpu_ldst);
1521 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ldst, 0, label);
1522 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
1523 gen_set_label(label);
1524 tcg_gen_movi_i32(cpu_ldst, 0);
1525 return;
1526 } else
1527 break;
1528 case 0x0063:
1529 /* MOVLI.L @Rm,R0
1530 1 -> LDST
1531 (Rm) -> R0
1532 When interrupt/exception
1533 occurred 0 -> LDST
1535 if (ctx->features & SH_FEATURE_SH4A) {
1536 tcg_gen_movi_i32(cpu_ldst, 0);
1537 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TESL);
1538 tcg_gen_movi_i32(cpu_ldst, 1);
1539 return;
1540 } else
1541 break;
1542 case 0x0093: /* ocbi @Rn */
1544 gen_helper_ocbi(cpu_env, REG(B11_8));
1546 return;
1547 case 0x00a3: /* ocbp @Rn */
1548 case 0x00b3: /* ocbwb @Rn */
1549 /* These instructions are supposed to do nothing in case of
1550 a cache miss. Given that we only partially emulate caches
1551 it is safe to simply ignore them. */
1552 return;
1553 case 0x0083: /* pref @Rn */
1554 return;
1555 case 0x00d3: /* prefi @Rn */
1556 if (ctx->features & SH_FEATURE_SH4A)
1557 return;
1558 else
1559 break;
1560 case 0x00e3: /* icbi @Rn */
1561 if (ctx->features & SH_FEATURE_SH4A)
1562 return;
1563 else
1564 break;
1565 case 0x00ab: /* synco */
1566 if (ctx->features & SH_FEATURE_SH4A)
1567 return;
1568 else
1569 break;
1570 case 0x4024: /* rotcl Rn */
1572 TCGv tmp = tcg_temp_new();
1573 tcg_gen_mov_i32(tmp, cpu_sr_t);
1574 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
1575 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1576 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
1577 tcg_temp_free(tmp);
1579 return;
1580 case 0x4025: /* rotcr Rn */
1582 TCGv tmp = tcg_temp_new();
1583 tcg_gen_shli_i32(tmp, cpu_sr_t, 31);
1584 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1585 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1586 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
1587 tcg_temp_free(tmp);
1589 return;
1590 case 0x4004: /* rotl Rn */
1591 tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1);
1592 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
1593 return;
1594 case 0x4005: /* rotr Rn */
1595 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
1596 tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1);
1597 return;
1598 case 0x4000: /* shll Rn */
1599 case 0x4020: /* shal Rn */
1600 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
1601 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1602 return;
1603 case 0x4021: /* shar Rn */
1604 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1605 tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1);
1606 return;
1607 case 0x4001: /* shlr Rn */
1608 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1609 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1610 return;
1611 case 0x4008: /* shll2 Rn */
1612 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2);
1613 return;
1614 case 0x4018: /* shll8 Rn */
1615 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8);
1616 return;
1617 case 0x4028: /* shll16 Rn */
1618 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16);
1619 return;
1620 case 0x4009: /* shlr2 Rn */
1621 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2);
1622 return;
1623 case 0x4019: /* shlr8 Rn */
1624 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8);
1625 return;
1626 case 0x4029: /* shlr16 Rn */
1627 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16);
1628 return;
1629 case 0x401b: /* tas.b @Rn */
1631 TCGv addr, val;
1632 addr = tcg_temp_local_new();
1633 tcg_gen_mov_i32(addr, REG(B11_8));
1634 val = tcg_temp_local_new();
1635 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1636 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1637 tcg_gen_ori_i32(val, val, 0x80);
1638 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1639 tcg_temp_free(val);
1640 tcg_temp_free(addr);
1642 return;
1643 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1644 CHECK_FPU_ENABLED
1645 tcg_gen_mov_i32(cpu_fregs[FREG(B11_8)], cpu_fpul);
1646 return;
1647 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1648 CHECK_FPU_ENABLED
1649 tcg_gen_mov_i32(cpu_fpul, cpu_fregs[FREG(B11_8)]);
1650 return;
1651 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
1652 CHECK_FPU_ENABLED
1653 if (ctx->flags & FPSCR_PR) {
1654 TCGv_i64 fp;
1655 if (ctx->opcode & 0x0100)
1656 break; /* illegal instruction */
1657 fp = tcg_temp_new_i64();
1658 gen_helper_float_DT(fp, cpu_env, cpu_fpul);
1659 gen_store_fpr64(fp, DREG(B11_8));
1660 tcg_temp_free_i64(fp);
1662 else {
1663 gen_helper_float_FT(cpu_fregs[FREG(B11_8)], cpu_env, cpu_fpul);
1665 return;
1666 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1667 CHECK_FPU_ENABLED
1668 if (ctx->flags & FPSCR_PR) {
1669 TCGv_i64 fp;
1670 if (ctx->opcode & 0x0100)
1671 break; /* illegal instruction */
1672 fp = tcg_temp_new_i64();
1673 gen_load_fpr64(fp, DREG(B11_8));
1674 gen_helper_ftrc_DT(cpu_fpul, cpu_env, fp);
1675 tcg_temp_free_i64(fp);
1677 else {
1678 gen_helper_ftrc_FT(cpu_fpul, cpu_env, cpu_fregs[FREG(B11_8)]);
1680 return;
1681 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
1682 CHECK_FPU_ENABLED
1684 gen_helper_fneg_T(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)]);
1686 return;
1687 case 0xf05d: /* fabs FRn/DRn */
1688 CHECK_FPU_ENABLED
1689 if (ctx->flags & FPSCR_PR) {
1690 if (ctx->opcode & 0x0100)
1691 break; /* illegal instruction */
1692 TCGv_i64 fp = tcg_temp_new_i64();
1693 gen_load_fpr64(fp, DREG(B11_8));
1694 gen_helper_fabs_DT(fp, fp);
1695 gen_store_fpr64(fp, DREG(B11_8));
1696 tcg_temp_free_i64(fp);
1697 } else {
1698 gen_helper_fabs_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)]);
1700 return;
1701 case 0xf06d: /* fsqrt FRn */
1702 CHECK_FPU_ENABLED
1703 if (ctx->flags & FPSCR_PR) {
1704 if (ctx->opcode & 0x0100)
1705 break; /* illegal instruction */
1706 TCGv_i64 fp = tcg_temp_new_i64();
1707 gen_load_fpr64(fp, DREG(B11_8));
1708 gen_helper_fsqrt_DT(fp, cpu_env, fp);
1709 gen_store_fpr64(fp, DREG(B11_8));
1710 tcg_temp_free_i64(fp);
1711 } else {
1712 gen_helper_fsqrt_FT(cpu_fregs[FREG(B11_8)], cpu_env,
1713 cpu_fregs[FREG(B11_8)]);
1715 return;
1716 case 0xf07d: /* fsrra FRn */
1717 CHECK_FPU_ENABLED
1718 break;
1719 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
1720 CHECK_FPU_ENABLED
1721 if (!(ctx->flags & FPSCR_PR)) {
1722 tcg_gen_movi_i32(cpu_fregs[FREG(B11_8)], 0);
1724 return;
1725 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
1726 CHECK_FPU_ENABLED
1727 if (!(ctx->flags & FPSCR_PR)) {
1728 tcg_gen_movi_i32(cpu_fregs[FREG(B11_8)], 0x3f800000);
1730 return;
1731 case 0xf0ad: /* fcnvsd FPUL,DRn */
1732 CHECK_FPU_ENABLED
1734 TCGv_i64 fp = tcg_temp_new_i64();
1735 gen_helper_fcnvsd_FT_DT(fp, cpu_env, cpu_fpul);
1736 gen_store_fpr64(fp, DREG(B11_8));
1737 tcg_temp_free_i64(fp);
1739 return;
1740 case 0xf0bd: /* fcnvds DRn,FPUL */
1741 CHECK_FPU_ENABLED
1743 TCGv_i64 fp = tcg_temp_new_i64();
1744 gen_load_fpr64(fp, DREG(B11_8));
1745 gen_helper_fcnvds_DT_FT(cpu_fpul, cpu_env, fp);
1746 tcg_temp_free_i64(fp);
1748 return;
1749 case 0xf0ed: /* fipr FVm,FVn */
1750 CHECK_FPU_ENABLED
1751 if ((ctx->flags & FPSCR_PR) == 0) {
1752 TCGv m, n;
1753 m = tcg_const_i32((ctx->opcode >> 8) & 3);
1754 n = tcg_const_i32((ctx->opcode >> 10) & 3);
1755 gen_helper_fipr(cpu_env, m, n);
1756 tcg_temp_free(m);
1757 tcg_temp_free(n);
1758 return;
1760 break;
1761 case 0xf0fd: /* ftrv XMTRX,FVn */
1762 CHECK_FPU_ENABLED
1763 if ((ctx->opcode & 0x0300) == 0x0100 &&
1764 (ctx->flags & FPSCR_PR) == 0) {
1765 TCGv n;
1766 n = tcg_const_i32((ctx->opcode >> 10) & 3);
1767 gen_helper_ftrv(cpu_env, n);
1768 tcg_temp_free(n);
1769 return;
1771 break;
1773 #if 0
1774 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1775 ctx->opcode, ctx->pc);
1776 fflush(stderr);
1777 #endif
1778 tcg_gen_movi_i32(cpu_pc, ctx->pc);
1779 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
1780 gen_helper_raise_slot_illegal_instruction(cpu_env);
1781 } else {
1782 gen_helper_raise_illegal_instruction(cpu_env);
1784 ctx->bstate = BS_BRANCH;
1787 static void decode_opc(DisasContext * ctx)
1789 uint32_t old_flags = ctx->flags;
1791 _decode_opc(ctx);
1793 if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
1794 if (ctx->flags & DELAY_SLOT_CLEARME) {
1795 gen_store_flags(0);
1796 } else {
1797 /* go out of the delay slot */
1798 uint32_t new_flags = ctx->flags;
1799 new_flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
1800 gen_store_flags(new_flags);
1802 ctx->flags = 0;
1803 ctx->bstate = BS_BRANCH;
1804 if (old_flags & DELAY_SLOT_CONDITIONAL) {
1805 gen_delayed_conditional_jump(ctx);
1806 } else if (old_flags & DELAY_SLOT) {
1807 gen_jump(ctx);
1812 /* go into a delay slot */
1813 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL))
1814 gen_store_flags(ctx->flags);
1817 void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
1819 SuperHCPU *cpu = sh_env_get_cpu(env);
1820 CPUState *cs = CPU(cpu);
1821 DisasContext ctx;
1822 target_ulong pc_start;
1823 int num_insns;
1824 int max_insns;
1826 pc_start = tb->pc;
1827 ctx.pc = pc_start;
1828 ctx.flags = (uint32_t)tb->flags;
1829 ctx.bstate = BS_NONE;
1830 ctx.memidx = (ctx.flags & (1u << SR_MD)) == 0 ? 1 : 0;
1831 /* We don't know if the delayed pc came from a dynamic or static branch,
1832 so assume it is a dynamic branch. */
1833 ctx.delayed_pc = -1; /* use delayed pc from env pointer */
1834 ctx.tb = tb;
1835 ctx.singlestep_enabled = cs->singlestep_enabled;
1836 ctx.features = env->features;
1837 ctx.has_movcal = (ctx.flags & TB_FLAG_PENDING_MOVCA);
1839 num_insns = 0;
1840 max_insns = tb->cflags & CF_COUNT_MASK;
1841 if (max_insns == 0) {
1842 max_insns = CF_COUNT_MASK;
1844 if (max_insns > TCG_MAX_INSNS) {
1845 max_insns = TCG_MAX_INSNS;
1848 gen_tb_start(tb);
1849 while (ctx.bstate == BS_NONE && !tcg_op_buf_full()) {
1850 tcg_gen_insn_start(ctx.pc, ctx.flags);
1851 num_insns++;
1853 if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
1854 /* We have hit a breakpoint - make sure PC is up-to-date */
1855 tcg_gen_movi_i32(cpu_pc, ctx.pc);
1856 gen_helper_debug(cpu_env);
1857 ctx.bstate = BS_BRANCH;
1858 /* The address covered by the breakpoint must be included in
1859 [tb->pc, tb->pc + tb->size) in order to for it to be
1860 properly cleared -- thus we increment the PC here so that
1861 the logic setting tb->size below does the right thing. */
1862 ctx.pc += 2;
1863 break;
1866 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
1867 gen_io_start();
1870 ctx.opcode = cpu_lduw_code(env, ctx.pc);
1871 decode_opc(&ctx);
1872 ctx.pc += 2;
1873 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1874 break;
1875 if (cs->singlestep_enabled) {
1876 break;
1878 if (num_insns >= max_insns)
1879 break;
1880 if (singlestep)
1881 break;
1883 if (tb->cflags & CF_LAST_IO)
1884 gen_io_end();
1885 if (cs->singlestep_enabled) {
1886 tcg_gen_movi_i32(cpu_pc, ctx.pc);
1887 gen_helper_debug(cpu_env);
1888 } else {
1889 switch (ctx.bstate) {
1890 case BS_STOP:
1891 /* gen_op_interrupt_restart(); */
1892 /* fall through */
1893 case BS_NONE:
1894 if (ctx.flags) {
1895 gen_store_flags(ctx.flags | DELAY_SLOT_CLEARME);
1897 gen_goto_tb(&ctx, 0, ctx.pc);
1898 break;
1899 case BS_EXCP:
1900 /* gen_op_interrupt_restart(); */
1901 tcg_gen_exit_tb(0);
1902 break;
1903 case BS_BRANCH:
1904 default:
1905 break;
1909 gen_tb_end(tb, num_insns);
1911 tb->size = ctx.pc - pc_start;
1912 tb->icount = num_insns;
1914 #ifdef DEBUG_DISAS
1915 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1916 qemu_log("IN:\n"); /* , lookup_symbol(pc_start)); */
1917 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
1918 qemu_log("\n");
1920 #endif
1923 void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb,
1924 target_ulong *data)
1926 env->pc = data[0];
1927 env->flags = data[1];