musicpal: Coding style fixes
[armpft.git] / target-sh4 / translate.c
blob895b978d38757a4509879dae9129fd977de30191
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/>.
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
25 #define DEBUG_DISAS
26 #define SH4_DEBUG_DISAS
27 //#define SH4_SINGLE_STEP
29 #include "cpu.h"
30 #include "exec-all.h"
31 #include "disas.h"
32 #include "tcg-op.h"
33 #include "qemu-common.h"
35 #include "helper.h"
36 #define GEN_HELPER 1
37 #include "helper.h"
39 typedef struct DisasContext {
40 struct TranslationBlock *tb;
41 target_ulong pc;
42 uint32_t sr;
43 uint32_t fpscr;
44 uint16_t opcode;
45 uint32_t flags;
46 int bstate;
47 int memidx;
48 uint32_t delayed_pc;
49 int singlestep_enabled;
50 uint32_t features;
51 int has_movcal;
52 } DisasContext;
54 #if defined(CONFIG_USER_ONLY)
55 #define IS_USER(ctx) 1
56 #else
57 #define IS_USER(ctx) (!(ctx->sr & SR_MD))
58 #endif
60 enum {
61 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
62 * exception condition
64 BS_STOP = 1, /* We want to stop translation for any reason */
65 BS_BRANCH = 2, /* We reached a branch condition */
66 BS_EXCP = 3, /* We reached an exception condition */
69 /* global register indexes */
70 static TCGv_ptr cpu_env;
71 static TCGv cpu_gregs[24];
72 static TCGv cpu_pc, cpu_sr, cpu_ssr, cpu_spc, cpu_gbr;
73 static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl;
74 static TCGv cpu_pr, cpu_fpscr, cpu_fpul, cpu_ldst;
75 static TCGv cpu_fregs[32];
77 /* internal register indexes */
78 static TCGv cpu_flags, cpu_delayed_pc;
80 #include "gen-icount.h"
82 static void sh4_translate_init(void)
84 int i;
85 static int done_init = 0;
86 static const char * const gregnames[24] = {
87 "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
88 "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
89 "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
90 "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
91 "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
93 static const char * const fregnames[32] = {
94 "FPR0_BANK0", "FPR1_BANK0", "FPR2_BANK0", "FPR3_BANK0",
95 "FPR4_BANK0", "FPR5_BANK0", "FPR6_BANK0", "FPR7_BANK0",
96 "FPR8_BANK0", "FPR9_BANK0", "FPR10_BANK0", "FPR11_BANK0",
97 "FPR12_BANK0", "FPR13_BANK0", "FPR14_BANK0", "FPR15_BANK0",
98 "FPR0_BANK1", "FPR1_BANK1", "FPR2_BANK1", "FPR3_BANK1",
99 "FPR4_BANK1", "FPR5_BANK1", "FPR6_BANK1", "FPR7_BANK1",
100 "FPR8_BANK1", "FPR9_BANK1", "FPR10_BANK1", "FPR11_BANK1",
101 "FPR12_BANK1", "FPR13_BANK1", "FPR14_BANK1", "FPR15_BANK1",
104 if (done_init)
105 return;
107 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
109 for (i = 0; i < 24; i++)
110 cpu_gregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
111 offsetof(CPUState, gregs[i]),
112 gregnames[i]);
114 cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
115 offsetof(CPUState, pc), "PC");
116 cpu_sr = tcg_global_mem_new_i32(TCG_AREG0,
117 offsetof(CPUState, sr), "SR");
118 cpu_ssr = tcg_global_mem_new_i32(TCG_AREG0,
119 offsetof(CPUState, ssr), "SSR");
120 cpu_spc = tcg_global_mem_new_i32(TCG_AREG0,
121 offsetof(CPUState, spc), "SPC");
122 cpu_gbr = tcg_global_mem_new_i32(TCG_AREG0,
123 offsetof(CPUState, gbr), "GBR");
124 cpu_vbr = tcg_global_mem_new_i32(TCG_AREG0,
125 offsetof(CPUState, vbr), "VBR");
126 cpu_sgr = tcg_global_mem_new_i32(TCG_AREG0,
127 offsetof(CPUState, sgr), "SGR");
128 cpu_dbr = tcg_global_mem_new_i32(TCG_AREG0,
129 offsetof(CPUState, dbr), "DBR");
130 cpu_mach = tcg_global_mem_new_i32(TCG_AREG0,
131 offsetof(CPUState, mach), "MACH");
132 cpu_macl = tcg_global_mem_new_i32(TCG_AREG0,
133 offsetof(CPUState, macl), "MACL");
134 cpu_pr = tcg_global_mem_new_i32(TCG_AREG0,
135 offsetof(CPUState, pr), "PR");
136 cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
137 offsetof(CPUState, fpscr), "FPSCR");
138 cpu_fpul = tcg_global_mem_new_i32(TCG_AREG0,
139 offsetof(CPUState, fpul), "FPUL");
141 cpu_flags = tcg_global_mem_new_i32(TCG_AREG0,
142 offsetof(CPUState, flags), "_flags_");
143 cpu_delayed_pc = tcg_global_mem_new_i32(TCG_AREG0,
144 offsetof(CPUState, delayed_pc),
145 "_delayed_pc_");
146 cpu_ldst = tcg_global_mem_new_i32(TCG_AREG0,
147 offsetof(CPUState, ldst), "_ldst_");
149 for (i = 0; i < 32; i++)
150 cpu_fregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
151 offsetof(CPUState, fregs[i]),
152 fregnames[i]);
154 /* register helpers */
155 #define GEN_HELPER 2
156 #include "helper.h"
158 done_init = 1;
161 void cpu_dump_state(CPUState * env, FILE * f,
162 int (*cpu_fprintf) (FILE * f, const char *fmt, ...),
163 int flags)
165 int i;
166 cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
167 env->pc, env->sr, env->pr, env->fpscr);
168 cpu_fprintf(f, "spc=0x%08x ssr=0x%08x gbr=0x%08x vbr=0x%08x\n",
169 env->spc, env->ssr, env->gbr, env->vbr);
170 cpu_fprintf(f, "sgr=0x%08x dbr=0x%08x delayed_pc=0x%08x fpul=0x%08x\n",
171 env->sgr, env->dbr, env->delayed_pc, env->fpul);
172 for (i = 0; i < 24; i += 4) {
173 cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
174 i, env->gregs[i], i + 1, env->gregs[i + 1],
175 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
177 if (env->flags & DELAY_SLOT) {
178 cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
179 env->delayed_pc);
180 } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
181 cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
182 env->delayed_pc);
186 static void cpu_sh4_reset(CPUSH4State * env)
188 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
189 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
190 log_cpu_state(env, 0);
193 #if defined(CONFIG_USER_ONLY)
194 env->sr = 0;
195 #else
196 env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0;
197 #endif
198 env->vbr = 0;
199 env->pc = 0xA0000000;
200 #if defined(CONFIG_USER_ONLY)
201 env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
202 set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
203 #else
204 env->fpscr = 0x00040001; /* CPU reset value according to SH4 manual */
205 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
206 #endif
207 env->mmucr = 0;
210 typedef struct {
211 const char *name;
212 int id;
213 uint32_t pvr;
214 uint32_t prr;
215 uint32_t cvr;
216 uint32_t features;
217 } sh4_def_t;
219 static sh4_def_t sh4_defs[] = {
221 .name = "SH7750R",
222 .id = SH_CPU_SH7750R,
223 .pvr = 0x00050000,
224 .prr = 0x00000100,
225 .cvr = 0x00110000,
226 .features = SH_FEATURE_BCR3_AND_BCR4,
227 }, {
228 .name = "SH7751R",
229 .id = SH_CPU_SH7751R,
230 .pvr = 0x04050005,
231 .prr = 0x00000113,
232 .cvr = 0x00110000, /* Neutered caches, should be 0x20480000 */
233 .features = SH_FEATURE_BCR3_AND_BCR4,
234 }, {
235 .name = "SH7785",
236 .id = SH_CPU_SH7785,
237 .pvr = 0x10300700,
238 .prr = 0x00000200,
239 .cvr = 0x71440211,
240 .features = SH_FEATURE_SH4A,
244 static const sh4_def_t *cpu_sh4_find_by_name(const char *name)
246 int i;
248 if (strcasecmp(name, "any") == 0)
249 return &sh4_defs[0];
251 for (i = 0; i < ARRAY_SIZE(sh4_defs); i++)
252 if (strcasecmp(name, sh4_defs[i].name) == 0)
253 return &sh4_defs[i];
255 return NULL;
258 void sh4_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
260 int i;
262 for (i = 0; i < ARRAY_SIZE(sh4_defs); i++)
263 (*cpu_fprintf)(f, "%s\n", sh4_defs[i].name);
266 static void cpu_sh4_register(CPUSH4State *env, const sh4_def_t *def)
268 env->pvr = def->pvr;
269 env->prr = def->prr;
270 env->cvr = def->cvr;
271 env->id = def->id;
274 CPUSH4State *cpu_sh4_init(const char *cpu_model)
276 CPUSH4State *env;
277 const sh4_def_t *def;
279 def = cpu_sh4_find_by_name(cpu_model);
280 if (!def)
281 return NULL;
282 env = qemu_mallocz(sizeof(CPUSH4State));
283 env->features = def->features;
284 cpu_exec_init(env);
285 env->movcal_backup_tail = &(env->movcal_backup);
286 sh4_translate_init();
287 env->cpu_model_str = cpu_model;
288 cpu_sh4_reset(env);
289 cpu_sh4_register(env, def);
290 tlb_flush(env, 1);
291 qemu_init_vcpu(env);
292 return env;
295 static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
297 TranslationBlock *tb;
298 tb = ctx->tb;
300 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
301 !ctx->singlestep_enabled) {
302 /* Use a direct jump if in same page and singlestep not enabled */
303 tcg_gen_goto_tb(n);
304 tcg_gen_movi_i32(cpu_pc, dest);
305 tcg_gen_exit_tb((long) tb + n);
306 } else {
307 tcg_gen_movi_i32(cpu_pc, dest);
308 if (ctx->singlestep_enabled)
309 gen_helper_debug();
310 tcg_gen_exit_tb(0);
314 static void gen_jump(DisasContext * ctx)
316 if (ctx->delayed_pc == (uint32_t) - 1) {
317 /* Target is not statically known, it comes necessarily from a
318 delayed jump as immediate jump are conditinal jumps */
319 tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc);
320 if (ctx->singlestep_enabled)
321 gen_helper_debug();
322 tcg_gen_exit_tb(0);
323 } else {
324 gen_goto_tb(ctx, 0, ctx->delayed_pc);
328 static inline void gen_branch_slot(uint32_t delayed_pc, int t)
330 TCGv sr;
331 int label = gen_new_label();
332 tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc);
333 sr = tcg_temp_new();
334 tcg_gen_andi_i32(sr, cpu_sr, SR_T);
335 tcg_gen_brcondi_i32(TCG_COND_NE, sr, t ? SR_T : 0, label);
336 tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
337 gen_set_label(label);
340 /* Immediate conditional jump (bt or bf) */
341 static void gen_conditional_jump(DisasContext * ctx,
342 target_ulong ift, target_ulong ifnott)
344 int l1;
345 TCGv sr;
347 l1 = gen_new_label();
348 sr = tcg_temp_new();
349 tcg_gen_andi_i32(sr, cpu_sr, SR_T);
350 tcg_gen_brcondi_i32(TCG_COND_EQ, sr, SR_T, l1);
351 gen_goto_tb(ctx, 0, ifnott);
352 gen_set_label(l1);
353 gen_goto_tb(ctx, 1, ift);
356 /* Delayed conditional jump (bt or bf) */
357 static void gen_delayed_conditional_jump(DisasContext * ctx)
359 int l1;
360 TCGv ds;
362 l1 = gen_new_label();
363 ds = tcg_temp_new();
364 tcg_gen_andi_i32(ds, cpu_flags, DELAY_SLOT_TRUE);
365 tcg_gen_brcondi_i32(TCG_COND_EQ, ds, DELAY_SLOT_TRUE, l1);
366 gen_goto_tb(ctx, 1, ctx->pc + 2);
367 gen_set_label(l1);
368 tcg_gen_andi_i32(cpu_flags, cpu_flags, ~DELAY_SLOT_TRUE);
369 gen_jump(ctx);
372 static inline void gen_set_t(void)
374 tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T);
377 static inline void gen_clr_t(void)
379 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
382 static inline void gen_cmp(int cond, TCGv t0, TCGv t1)
384 int label1 = gen_new_label();
385 int label2 = gen_new_label();
386 tcg_gen_brcond_i32(cond, t1, t0, label1);
387 gen_clr_t();
388 tcg_gen_br(label2);
389 gen_set_label(label1);
390 gen_set_t();
391 gen_set_label(label2);
394 static inline void gen_cmp_imm(int cond, TCGv t0, int32_t imm)
396 int label1 = gen_new_label();
397 int label2 = gen_new_label();
398 tcg_gen_brcondi_i32(cond, t0, imm, label1);
399 gen_clr_t();
400 tcg_gen_br(label2);
401 gen_set_label(label1);
402 gen_set_t();
403 gen_set_label(label2);
406 static inline void gen_store_flags(uint32_t flags)
408 tcg_gen_andi_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
409 tcg_gen_ori_i32(cpu_flags, cpu_flags, flags);
412 static inline void gen_copy_bit_i32(TCGv t0, int p0, TCGv t1, int p1)
414 TCGv tmp = tcg_temp_new();
416 p0 &= 0x1f;
417 p1 &= 0x1f;
419 tcg_gen_andi_i32(tmp, t1, (1 << p1));
420 tcg_gen_andi_i32(t0, t0, ~(1 << p0));
421 if (p0 < p1)
422 tcg_gen_shri_i32(tmp, tmp, p1 - p0);
423 else if (p0 > p1)
424 tcg_gen_shli_i32(tmp, tmp, p0 - p1);
425 tcg_gen_or_i32(t0, t0, tmp);
427 tcg_temp_free(tmp);
430 static inline void gen_load_fpr64(TCGv_i64 t, int reg)
432 tcg_gen_concat_i32_i64(t, cpu_fregs[reg + 1], cpu_fregs[reg]);
435 static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
437 TCGv_i32 tmp = tcg_temp_new_i32();
438 tcg_gen_trunc_i64_i32(tmp, t);
439 tcg_gen_mov_i32(cpu_fregs[reg + 1], tmp);
440 tcg_gen_shri_i64(t, t, 32);
441 tcg_gen_trunc_i64_i32(tmp, t);
442 tcg_gen_mov_i32(cpu_fregs[reg], tmp);
443 tcg_temp_free_i32(tmp);
446 #define B3_0 (ctx->opcode & 0xf)
447 #define B6_4 ((ctx->opcode >> 4) & 0x7)
448 #define B7_4 ((ctx->opcode >> 4) & 0xf)
449 #define B7_0 (ctx->opcode & 0xff)
450 #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
451 #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
452 (ctx->opcode & 0xfff))
453 #define B11_8 ((ctx->opcode >> 8) & 0xf)
454 #define B15_12 ((ctx->opcode >> 12) & 0xf)
456 #define REG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB) ? \
457 (cpu_gregs[x + 16]) : (cpu_gregs[x]))
459 #define ALTREG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) != (SR_MD | SR_RB) \
460 ? (cpu_gregs[x + 16]) : (cpu_gregs[x]))
462 #define FREG(x) (ctx->fpscr & FPSCR_FR ? (x) ^ 0x10 : (x))
463 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
464 #define XREG(x) (ctx->fpscr & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x))
465 #define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */
467 #define CHECK_NOT_DELAY_SLOT \
468 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
470 tcg_gen_movi_i32(cpu_pc, ctx->pc-2); \
471 gen_helper_raise_slot_illegal_instruction(); \
472 ctx->bstate = BS_EXCP; \
473 return; \
476 #define CHECK_PRIVILEGED \
477 if (IS_USER(ctx)) { \
478 tcg_gen_movi_i32(cpu_pc, ctx->pc); \
479 gen_helper_raise_illegal_instruction(); \
480 ctx->bstate = BS_EXCP; \
481 return; \
484 #define CHECK_FPU_ENABLED \
485 if (ctx->flags & SR_FD) { \
486 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
487 tcg_gen_movi_i32(cpu_pc, ctx->pc-2); \
488 gen_helper_raise_slot_fpu_disable(); \
489 } else { \
490 tcg_gen_movi_i32(cpu_pc, ctx->pc); \
491 gen_helper_raise_fpu_disable(); \
493 ctx->bstate = BS_EXCP; \
494 return; \
497 static void _decode_opc(DisasContext * ctx)
499 /* This code tries to make movcal emulation sufficiently
500 accurate for Linux purposes. This instruction writes
501 memory, and prior to that, always allocates a cache line.
502 It is used in two contexts:
503 - in memcpy, where data is copied in blocks, the first write
504 of to a block uses movca.l for performance.
505 - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used
506 to flush the cache. Here, the data written by movcal.l is never
507 written to memory, and the data written is just bogus.
509 To simulate this, we simulate movcal.l, we store the value to memory,
510 but we also remember the previous content. If we see ocbi, we check
511 if movcal.l for that address was done previously. If so, the write should
512 not have hit the memory, so we restore the previous content.
513 When we see an instruction that is neither movca.l
514 nor ocbi, the previous content is discarded.
516 To optimize, we only try to flush stores when we're at the start of
517 TB, or if we already saw movca.l in this TB and did not flush stores
518 yet. */
519 if (ctx->has_movcal)
521 int opcode = ctx->opcode & 0xf0ff;
522 if (opcode != 0x0093 /* ocbi */
523 && opcode != 0x00c3 /* movca.l */)
525 gen_helper_discard_movcal_backup ();
526 ctx->has_movcal = 0;
530 #if 0
531 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
532 #endif
534 switch (ctx->opcode) {
535 case 0x0019: /* div0u */
536 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(SR_M | SR_Q | SR_T));
537 return;
538 case 0x000b: /* rts */
539 CHECK_NOT_DELAY_SLOT
540 tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
541 ctx->flags |= DELAY_SLOT;
542 ctx->delayed_pc = (uint32_t) - 1;
543 return;
544 case 0x0028: /* clrmac */
545 tcg_gen_movi_i32(cpu_mach, 0);
546 tcg_gen_movi_i32(cpu_macl, 0);
547 return;
548 case 0x0048: /* clrs */
549 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_S);
550 return;
551 case 0x0008: /* clrt */
552 gen_clr_t();
553 return;
554 case 0x0038: /* ldtlb */
555 CHECK_PRIVILEGED
556 gen_helper_ldtlb();
557 return;
558 case 0x002b: /* rte */
559 CHECK_PRIVILEGED
560 CHECK_NOT_DELAY_SLOT
561 tcg_gen_mov_i32(cpu_sr, cpu_ssr);
562 tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
563 ctx->flags |= DELAY_SLOT;
564 ctx->delayed_pc = (uint32_t) - 1;
565 return;
566 case 0x0058: /* sets */
567 tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_S);
568 return;
569 case 0x0018: /* sett */
570 gen_set_t();
571 return;
572 case 0xfbfd: /* frchg */
573 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
574 ctx->bstate = BS_STOP;
575 return;
576 case 0xf3fd: /* fschg */
577 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ);
578 ctx->bstate = BS_STOP;
579 return;
580 case 0x0009: /* nop */
581 return;
582 case 0x001b: /* sleep */
583 CHECK_PRIVILEGED
584 gen_helper_sleep(tcg_const_i32(ctx->pc + 2));
585 return;
588 switch (ctx->opcode & 0xf000) {
589 case 0x1000: /* mov.l Rm,@(disp,Rn) */
591 TCGv addr = tcg_temp_new();
592 tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
593 tcg_gen_qemu_st32(REG(B7_4), addr, ctx->memidx);
594 tcg_temp_free(addr);
596 return;
597 case 0x5000: /* mov.l @(disp,Rm),Rn */
599 TCGv addr = tcg_temp_new();
600 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
601 tcg_gen_qemu_ld32s(REG(B11_8), addr, ctx->memidx);
602 tcg_temp_free(addr);
604 return;
605 case 0xe000: /* mov #imm,Rn */
606 tcg_gen_movi_i32(REG(B11_8), B7_0s);
607 return;
608 case 0x9000: /* mov.w @(disp,PC),Rn */
610 TCGv addr = tcg_const_i32(ctx->pc + 4 + B7_0 * 2);
611 tcg_gen_qemu_ld16s(REG(B11_8), addr, ctx->memidx);
612 tcg_temp_free(addr);
614 return;
615 case 0xd000: /* mov.l @(disp,PC),Rn */
617 TCGv addr = tcg_const_i32((ctx->pc + 4 + B7_0 * 4) & ~3);
618 tcg_gen_qemu_ld32s(REG(B11_8), addr, ctx->memidx);
619 tcg_temp_free(addr);
621 return;
622 case 0x7000: /* add #imm,Rn */
623 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s);
624 return;
625 case 0xa000: /* bra disp */
626 CHECK_NOT_DELAY_SLOT
627 ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
628 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
629 ctx->flags |= DELAY_SLOT;
630 return;
631 case 0xb000: /* bsr disp */
632 CHECK_NOT_DELAY_SLOT
633 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
634 ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
635 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
636 ctx->flags |= DELAY_SLOT;
637 return;
640 switch (ctx->opcode & 0xf00f) {
641 case 0x6003: /* mov Rm,Rn */
642 tcg_gen_mov_i32(REG(B11_8), REG(B7_4));
643 return;
644 case 0x2000: /* mov.b Rm,@Rn */
645 tcg_gen_qemu_st8(REG(B7_4), REG(B11_8), ctx->memidx);
646 return;
647 case 0x2001: /* mov.w Rm,@Rn */
648 tcg_gen_qemu_st16(REG(B7_4), REG(B11_8), ctx->memidx);
649 return;
650 case 0x2002: /* mov.l Rm,@Rn */
651 tcg_gen_qemu_st32(REG(B7_4), REG(B11_8), ctx->memidx);
652 return;
653 case 0x6000: /* mov.b @Rm,Rn */
654 tcg_gen_qemu_ld8s(REG(B11_8), REG(B7_4), ctx->memidx);
655 return;
656 case 0x6001: /* mov.w @Rm,Rn */
657 tcg_gen_qemu_ld16s(REG(B11_8), REG(B7_4), ctx->memidx);
658 return;
659 case 0x6002: /* mov.l @Rm,Rn */
660 tcg_gen_qemu_ld32s(REG(B11_8), REG(B7_4), ctx->memidx);
661 return;
662 case 0x2004: /* mov.b Rm,@-Rn */
664 TCGv addr = tcg_temp_new();
665 tcg_gen_subi_i32(addr, REG(B11_8), 1);
666 tcg_gen_qemu_st8(REG(B7_4), addr, ctx->memidx); /* might cause re-execution */
667 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1); /* modify register status */
668 tcg_temp_free(addr);
670 return;
671 case 0x2005: /* mov.w Rm,@-Rn */
673 TCGv addr = tcg_temp_new();
674 tcg_gen_subi_i32(addr, REG(B11_8), 2);
675 tcg_gen_qemu_st16(REG(B7_4), addr, ctx->memidx);
676 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 2);
677 tcg_temp_free(addr);
679 return;
680 case 0x2006: /* mov.l Rm,@-Rn */
682 TCGv addr = tcg_temp_new();
683 tcg_gen_subi_i32(addr, REG(B11_8), 4);
684 tcg_gen_qemu_st32(REG(B7_4), addr, ctx->memidx);
685 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
687 return;
688 case 0x6004: /* mov.b @Rm+,Rn */
689 tcg_gen_qemu_ld8s(REG(B11_8), REG(B7_4), ctx->memidx);
690 if ( B11_8 != B7_4 )
691 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1);
692 return;
693 case 0x6005: /* mov.w @Rm+,Rn */
694 tcg_gen_qemu_ld16s(REG(B11_8), REG(B7_4), ctx->memidx);
695 if ( B11_8 != B7_4 )
696 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
697 return;
698 case 0x6006: /* mov.l @Rm+,Rn */
699 tcg_gen_qemu_ld32s(REG(B11_8), REG(B7_4), ctx->memidx);
700 if ( B11_8 != B7_4 )
701 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
702 return;
703 case 0x0004: /* mov.b Rm,@(R0,Rn) */
705 TCGv addr = tcg_temp_new();
706 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
707 tcg_gen_qemu_st8(REG(B7_4), addr, ctx->memidx);
708 tcg_temp_free(addr);
710 return;
711 case 0x0005: /* mov.w Rm,@(R0,Rn) */
713 TCGv addr = tcg_temp_new();
714 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
715 tcg_gen_qemu_st16(REG(B7_4), addr, ctx->memidx);
716 tcg_temp_free(addr);
718 return;
719 case 0x0006: /* mov.l Rm,@(R0,Rn) */
721 TCGv addr = tcg_temp_new();
722 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
723 tcg_gen_qemu_st32(REG(B7_4), addr, ctx->memidx);
724 tcg_temp_free(addr);
726 return;
727 case 0x000c: /* mov.b @(R0,Rm),Rn */
729 TCGv addr = tcg_temp_new();
730 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
731 tcg_gen_qemu_ld8s(REG(B11_8), addr, ctx->memidx);
732 tcg_temp_free(addr);
734 return;
735 case 0x000d: /* mov.w @(R0,Rm),Rn */
737 TCGv addr = tcg_temp_new();
738 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
739 tcg_gen_qemu_ld16s(REG(B11_8), addr, ctx->memidx);
740 tcg_temp_free(addr);
742 return;
743 case 0x000e: /* mov.l @(R0,Rm),Rn */
745 TCGv addr = tcg_temp_new();
746 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
747 tcg_gen_qemu_ld32s(REG(B11_8), addr, ctx->memidx);
748 tcg_temp_free(addr);
750 return;
751 case 0x6008: /* swap.b Rm,Rn */
753 TCGv highw, high, low;
754 highw = tcg_temp_new();
755 tcg_gen_andi_i32(highw, REG(B7_4), 0xffff0000);
756 high = tcg_temp_new();
757 tcg_gen_ext8u_i32(high, REG(B7_4));
758 tcg_gen_shli_i32(high, high, 8);
759 low = tcg_temp_new();
760 tcg_gen_shri_i32(low, REG(B7_4), 8);
761 tcg_gen_ext8u_i32(low, low);
762 tcg_gen_or_i32(REG(B11_8), high, low);
763 tcg_gen_or_i32(REG(B11_8), REG(B11_8), highw);
764 tcg_temp_free(low);
765 tcg_temp_free(high);
767 return;
768 case 0x6009: /* swap.w Rm,Rn */
770 TCGv high, low;
771 high = tcg_temp_new();
772 tcg_gen_ext16u_i32(high, REG(B7_4));
773 tcg_gen_shli_i32(high, high, 16);
774 low = tcg_temp_new();
775 tcg_gen_shri_i32(low, REG(B7_4), 16);
776 tcg_gen_ext16u_i32(low, low);
777 tcg_gen_or_i32(REG(B11_8), high, low);
778 tcg_temp_free(low);
779 tcg_temp_free(high);
781 return;
782 case 0x200d: /* xtrct Rm,Rn */
784 TCGv high, low;
785 high = tcg_temp_new();
786 tcg_gen_ext16u_i32(high, REG(B7_4));
787 tcg_gen_shli_i32(high, high, 16);
788 low = tcg_temp_new();
789 tcg_gen_shri_i32(low, REG(B11_8), 16);
790 tcg_gen_ext16u_i32(low, low);
791 tcg_gen_or_i32(REG(B11_8), high, low);
792 tcg_temp_free(low);
793 tcg_temp_free(high);
795 return;
796 case 0x300c: /* add Rm,Rn */
797 tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4));
798 return;
799 case 0x300e: /* addc Rm,Rn */
800 gen_helper_addc(REG(B11_8), REG(B7_4), REG(B11_8));
801 return;
802 case 0x300f: /* addv Rm,Rn */
803 gen_helper_addv(REG(B11_8), REG(B7_4), REG(B11_8));
804 return;
805 case 0x2009: /* and Rm,Rn */
806 tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4));
807 return;
808 case 0x3000: /* cmp/eq Rm,Rn */
809 gen_cmp(TCG_COND_EQ, REG(B7_4), REG(B11_8));
810 return;
811 case 0x3003: /* cmp/ge Rm,Rn */
812 gen_cmp(TCG_COND_GE, REG(B7_4), REG(B11_8));
813 return;
814 case 0x3007: /* cmp/gt Rm,Rn */
815 gen_cmp(TCG_COND_GT, REG(B7_4), REG(B11_8));
816 return;
817 case 0x3006: /* cmp/hi Rm,Rn */
818 gen_cmp(TCG_COND_GTU, REG(B7_4), REG(B11_8));
819 return;
820 case 0x3002: /* cmp/hs Rm,Rn */
821 gen_cmp(TCG_COND_GEU, REG(B7_4), REG(B11_8));
822 return;
823 case 0x200c: /* cmp/str Rm,Rn */
825 int label1 = gen_new_label();
826 int label2 = gen_new_label();
827 TCGv cmp1 = tcg_temp_local_new();
828 TCGv cmp2 = tcg_temp_local_new();
829 tcg_gen_xor_i32(cmp1, REG(B7_4), REG(B11_8));
830 tcg_gen_andi_i32(cmp2, cmp1, 0xff000000);
831 tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
832 tcg_gen_andi_i32(cmp2, cmp1, 0x00ff0000);
833 tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
834 tcg_gen_andi_i32(cmp2, cmp1, 0x0000ff00);
835 tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
836 tcg_gen_andi_i32(cmp2, cmp1, 0x000000ff);
837 tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
838 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
839 tcg_gen_br(label2);
840 gen_set_label(label1);
841 tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T);
842 gen_set_label(label2);
843 tcg_temp_free(cmp2);
844 tcg_temp_free(cmp1);
846 return;
847 case 0x2007: /* div0s Rm,Rn */
849 gen_copy_bit_i32(cpu_sr, 8, REG(B11_8), 31); /* SR_Q */
850 gen_copy_bit_i32(cpu_sr, 9, REG(B7_4), 31); /* SR_M */
851 TCGv val = tcg_temp_new();
852 tcg_gen_xor_i32(val, REG(B7_4), REG(B11_8));
853 gen_copy_bit_i32(cpu_sr, 0, val, 31); /* SR_T */
854 tcg_temp_free(val);
856 return;
857 case 0x3004: /* div1 Rm,Rn */
858 gen_helper_div1(REG(B11_8), REG(B7_4), REG(B11_8));
859 return;
860 case 0x300d: /* dmuls.l Rm,Rn */
862 TCGv_i64 tmp1 = tcg_temp_new_i64();
863 TCGv_i64 tmp2 = tcg_temp_new_i64();
865 tcg_gen_ext_i32_i64(tmp1, REG(B7_4));
866 tcg_gen_ext_i32_i64(tmp2, REG(B11_8));
867 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
868 tcg_gen_trunc_i64_i32(cpu_macl, tmp1);
869 tcg_gen_shri_i64(tmp1, tmp1, 32);
870 tcg_gen_trunc_i64_i32(cpu_mach, tmp1);
872 tcg_temp_free_i64(tmp2);
873 tcg_temp_free_i64(tmp1);
875 return;
876 case 0x3005: /* dmulu.l Rm,Rn */
878 TCGv_i64 tmp1 = tcg_temp_new_i64();
879 TCGv_i64 tmp2 = tcg_temp_new_i64();
881 tcg_gen_extu_i32_i64(tmp1, REG(B7_4));
882 tcg_gen_extu_i32_i64(tmp2, REG(B11_8));
883 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
884 tcg_gen_trunc_i64_i32(cpu_macl, tmp1);
885 tcg_gen_shri_i64(tmp1, tmp1, 32);
886 tcg_gen_trunc_i64_i32(cpu_mach, tmp1);
888 tcg_temp_free_i64(tmp2);
889 tcg_temp_free_i64(tmp1);
891 return;
892 case 0x600e: /* exts.b Rm,Rn */
893 tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4));
894 return;
895 case 0x600f: /* exts.w Rm,Rn */
896 tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4));
897 return;
898 case 0x600c: /* extu.b Rm,Rn */
899 tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4));
900 return;
901 case 0x600d: /* extu.w Rm,Rn */
902 tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4));
903 return;
904 case 0x000f: /* mac.l @Rm+,@Rn+ */
906 TCGv arg0, arg1;
907 arg0 = tcg_temp_new();
908 tcg_gen_qemu_ld32s(arg0, REG(B7_4), ctx->memidx);
909 arg1 = tcg_temp_new();
910 tcg_gen_qemu_ld32s(arg1, REG(B11_8), ctx->memidx);
911 gen_helper_macl(arg0, arg1);
912 tcg_temp_free(arg1);
913 tcg_temp_free(arg0);
914 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
915 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
917 return;
918 case 0x400f: /* mac.w @Rm+,@Rn+ */
920 TCGv arg0, arg1;
921 arg0 = tcg_temp_new();
922 tcg_gen_qemu_ld32s(arg0, REG(B7_4), ctx->memidx);
923 arg1 = tcg_temp_new();
924 tcg_gen_qemu_ld32s(arg1, REG(B11_8), ctx->memidx);
925 gen_helper_macw(arg0, arg1);
926 tcg_temp_free(arg1);
927 tcg_temp_free(arg0);
928 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2);
929 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
931 return;
932 case 0x0007: /* mul.l Rm,Rn */
933 tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8));
934 return;
935 case 0x200f: /* muls.w Rm,Rn */
937 TCGv arg0, arg1;
938 arg0 = tcg_temp_new();
939 tcg_gen_ext16s_i32(arg0, REG(B7_4));
940 arg1 = tcg_temp_new();
941 tcg_gen_ext16s_i32(arg1, REG(B11_8));
942 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
943 tcg_temp_free(arg1);
944 tcg_temp_free(arg0);
946 return;
947 case 0x200e: /* mulu.w Rm,Rn */
949 TCGv arg0, arg1;
950 arg0 = tcg_temp_new();
951 tcg_gen_ext16u_i32(arg0, REG(B7_4));
952 arg1 = tcg_temp_new();
953 tcg_gen_ext16u_i32(arg1, REG(B11_8));
954 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
955 tcg_temp_free(arg1);
956 tcg_temp_free(arg0);
958 return;
959 case 0x600b: /* neg Rm,Rn */
960 tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
961 return;
962 case 0x600a: /* negc Rm,Rn */
963 gen_helper_negc(REG(B11_8), REG(B7_4));
964 return;
965 case 0x6007: /* not Rm,Rn */
966 tcg_gen_not_i32(REG(B11_8), REG(B7_4));
967 return;
968 case 0x200b: /* or Rm,Rn */
969 tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4));
970 return;
971 case 0x400c: /* shad Rm,Rn */
973 int label1 = gen_new_label();
974 int label2 = gen_new_label();
975 int label3 = gen_new_label();
976 int label4 = gen_new_label();
977 TCGv shift = tcg_temp_local_new();
978 tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
979 /* Rm positive, shift to the left */
980 tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
981 tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
982 tcg_gen_br(label4);
983 /* Rm negative, shift to the right */
984 gen_set_label(label1);
985 tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
986 tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2);
987 tcg_gen_not_i32(shift, REG(B7_4));
988 tcg_gen_andi_i32(shift, shift, 0x1f);
989 tcg_gen_addi_i32(shift, shift, 1);
990 tcg_gen_sar_i32(REG(B11_8), REG(B11_8), shift);
991 tcg_gen_br(label4);
992 /* Rm = -32 */
993 gen_set_label(label2);
994 tcg_gen_brcondi_i32(TCG_COND_LT, REG(B11_8), 0, label3);
995 tcg_gen_movi_i32(REG(B11_8), 0);
996 tcg_gen_br(label4);
997 gen_set_label(label3);
998 tcg_gen_movi_i32(REG(B11_8), 0xffffffff);
999 gen_set_label(label4);
1000 tcg_temp_free(shift);
1002 return;
1003 case 0x400d: /* shld Rm,Rn */
1005 int label1 = gen_new_label();
1006 int label2 = gen_new_label();
1007 int label3 = gen_new_label();
1008 TCGv shift = tcg_temp_local_new();
1009 tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
1010 /* Rm positive, shift to the left */
1011 tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
1012 tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
1013 tcg_gen_br(label3);
1014 /* Rm negative, shift to the right */
1015 gen_set_label(label1);
1016 tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
1017 tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2);
1018 tcg_gen_not_i32(shift, REG(B7_4));
1019 tcg_gen_andi_i32(shift, shift, 0x1f);
1020 tcg_gen_addi_i32(shift, shift, 1);
1021 tcg_gen_shr_i32(REG(B11_8), REG(B11_8), shift);
1022 tcg_gen_br(label3);
1023 /* Rm = -32 */
1024 gen_set_label(label2);
1025 tcg_gen_movi_i32(REG(B11_8), 0);
1026 gen_set_label(label3);
1027 tcg_temp_free(shift);
1029 return;
1030 case 0x3008: /* sub Rm,Rn */
1031 tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4));
1032 return;
1033 case 0x300a: /* subc Rm,Rn */
1034 gen_helper_subc(REG(B11_8), REG(B7_4), REG(B11_8));
1035 return;
1036 case 0x300b: /* subv Rm,Rn */
1037 gen_helper_subv(REG(B11_8), REG(B7_4), REG(B11_8));
1038 return;
1039 case 0x2008: /* tst Rm,Rn */
1041 TCGv val = tcg_temp_new();
1042 tcg_gen_and_i32(val, REG(B7_4), REG(B11_8));
1043 gen_cmp_imm(TCG_COND_EQ, val, 0);
1044 tcg_temp_free(val);
1046 return;
1047 case 0x200a: /* xor Rm,Rn */
1048 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4));
1049 return;
1050 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
1051 CHECK_FPU_ENABLED
1052 if (ctx->fpscr & FPSCR_SZ) {
1053 TCGv_i64 fp = tcg_temp_new_i64();
1054 gen_load_fpr64(fp, XREG(B7_4));
1055 gen_store_fpr64(fp, XREG(B11_8));
1056 tcg_temp_free_i64(fp);
1057 } else {
1058 tcg_gen_mov_i32(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]);
1060 return;
1061 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
1062 CHECK_FPU_ENABLED
1063 if (ctx->fpscr & FPSCR_SZ) {
1064 TCGv addr_hi = tcg_temp_new();
1065 int fr = XREG(B7_4);
1066 tcg_gen_addi_i32(addr_hi, REG(B11_8), 4);
1067 tcg_gen_qemu_st32(cpu_fregs[fr ], REG(B11_8), ctx->memidx);
1068 tcg_gen_qemu_st32(cpu_fregs[fr+1], addr_hi, ctx->memidx);
1069 tcg_temp_free(addr_hi);
1070 } else {
1071 tcg_gen_qemu_st32(cpu_fregs[FREG(B7_4)], REG(B11_8), ctx->memidx);
1073 return;
1074 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
1075 CHECK_FPU_ENABLED
1076 if (ctx->fpscr & FPSCR_SZ) {
1077 TCGv addr_hi = tcg_temp_new();
1078 int fr = XREG(B11_8);
1079 tcg_gen_addi_i32(addr_hi, REG(B7_4), 4);
1080 tcg_gen_qemu_ld32u(cpu_fregs[fr ], REG(B7_4), ctx->memidx);
1081 tcg_gen_qemu_ld32u(cpu_fregs[fr+1], addr_hi, ctx->memidx);
1082 tcg_temp_free(addr_hi);
1083 } else {
1084 tcg_gen_qemu_ld32u(cpu_fregs[FREG(B11_8)], REG(B7_4), ctx->memidx);
1086 return;
1087 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
1088 CHECK_FPU_ENABLED
1089 if (ctx->fpscr & FPSCR_SZ) {
1090 TCGv addr_hi = tcg_temp_new();
1091 int fr = XREG(B11_8);
1092 tcg_gen_addi_i32(addr_hi, REG(B7_4), 4);
1093 tcg_gen_qemu_ld32u(cpu_fregs[fr ], REG(B7_4), ctx->memidx);
1094 tcg_gen_qemu_ld32u(cpu_fregs[fr+1], addr_hi, ctx->memidx);
1095 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8);
1096 tcg_temp_free(addr_hi);
1097 } else {
1098 tcg_gen_qemu_ld32u(cpu_fregs[FREG(B11_8)], REG(B7_4), ctx->memidx);
1099 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
1101 return;
1102 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
1103 CHECK_FPU_ENABLED
1104 if (ctx->fpscr & FPSCR_SZ) {
1105 TCGv addr = tcg_temp_new_i32();
1106 int fr = XREG(B7_4);
1107 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1108 tcg_gen_qemu_st32(cpu_fregs[fr+1], addr, ctx->memidx);
1109 tcg_gen_subi_i32(addr, REG(B11_8), 8);
1110 tcg_gen_qemu_st32(cpu_fregs[fr ], addr, ctx->memidx);
1111 tcg_gen_mov_i32(REG(B11_8), addr);
1112 tcg_temp_free(addr);
1113 } else {
1114 TCGv addr;
1115 addr = tcg_temp_new_i32();
1116 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1117 tcg_gen_qemu_st32(cpu_fregs[FREG(B7_4)], addr, ctx->memidx);
1118 tcg_temp_free(addr);
1119 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
1121 return;
1122 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
1123 CHECK_FPU_ENABLED
1125 TCGv addr = tcg_temp_new_i32();
1126 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
1127 if (ctx->fpscr & FPSCR_SZ) {
1128 int fr = XREG(B11_8);
1129 tcg_gen_qemu_ld32u(cpu_fregs[fr ], addr, ctx->memidx);
1130 tcg_gen_addi_i32(addr, addr, 4);
1131 tcg_gen_qemu_ld32u(cpu_fregs[fr+1], addr, ctx->memidx);
1132 } else {
1133 tcg_gen_qemu_ld32u(cpu_fregs[FREG(B11_8)], addr, ctx->memidx);
1135 tcg_temp_free(addr);
1137 return;
1138 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
1139 CHECK_FPU_ENABLED
1141 TCGv addr = tcg_temp_new();
1142 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
1143 if (ctx->fpscr & FPSCR_SZ) {
1144 int fr = XREG(B7_4);
1145 tcg_gen_qemu_ld32u(cpu_fregs[fr ], addr, ctx->memidx);
1146 tcg_gen_addi_i32(addr, addr, 4);
1147 tcg_gen_qemu_ld32u(cpu_fregs[fr+1], addr, ctx->memidx);
1148 } else {
1149 tcg_gen_qemu_st32(cpu_fregs[FREG(B7_4)], addr, ctx->memidx);
1151 tcg_temp_free(addr);
1153 return;
1154 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1155 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1156 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1157 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1158 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1159 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1161 CHECK_FPU_ENABLED
1162 if (ctx->fpscr & FPSCR_PR) {
1163 TCGv_i64 fp0, fp1;
1165 if (ctx->opcode & 0x0110)
1166 break; /* illegal instruction */
1167 fp0 = tcg_temp_new_i64();
1168 fp1 = tcg_temp_new_i64();
1169 gen_load_fpr64(fp0, DREG(B11_8));
1170 gen_load_fpr64(fp1, DREG(B7_4));
1171 switch (ctx->opcode & 0xf00f) {
1172 case 0xf000: /* fadd Rm,Rn */
1173 gen_helper_fadd_DT(fp0, fp0, fp1);
1174 break;
1175 case 0xf001: /* fsub Rm,Rn */
1176 gen_helper_fsub_DT(fp0, fp0, fp1);
1177 break;
1178 case 0xf002: /* fmul Rm,Rn */
1179 gen_helper_fmul_DT(fp0, fp0, fp1);
1180 break;
1181 case 0xf003: /* fdiv Rm,Rn */
1182 gen_helper_fdiv_DT(fp0, fp0, fp1);
1183 break;
1184 case 0xf004: /* fcmp/eq Rm,Rn */
1185 gen_helper_fcmp_eq_DT(fp0, fp1);
1186 return;
1187 case 0xf005: /* fcmp/gt Rm,Rn */
1188 gen_helper_fcmp_gt_DT(fp0, fp1);
1189 return;
1191 gen_store_fpr64(fp0, DREG(B11_8));
1192 tcg_temp_free_i64(fp0);
1193 tcg_temp_free_i64(fp1);
1194 } else {
1195 switch (ctx->opcode & 0xf00f) {
1196 case 0xf000: /* fadd Rm,Rn */
1197 gen_helper_fadd_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]);
1198 break;
1199 case 0xf001: /* fsub Rm,Rn */
1200 gen_helper_fsub_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]);
1201 break;
1202 case 0xf002: /* fmul Rm,Rn */
1203 gen_helper_fmul_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]);
1204 break;
1205 case 0xf003: /* fdiv Rm,Rn */
1206 gen_helper_fdiv_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]);
1207 break;
1208 case 0xf004: /* fcmp/eq Rm,Rn */
1209 gen_helper_fcmp_eq_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]);
1210 return;
1211 case 0xf005: /* fcmp/gt Rm,Rn */
1212 gen_helper_fcmp_gt_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]);
1213 return;
1217 return;
1218 case 0xf00e: /* fmac FR0,RM,Rn */
1220 CHECK_FPU_ENABLED
1221 if (ctx->fpscr & FPSCR_PR) {
1222 break; /* illegal instruction */
1223 } else {
1224 gen_helper_fmac_FT(cpu_fregs[FREG(B11_8)],
1225 cpu_fregs[FREG(0)], cpu_fregs[FREG(B7_4)], cpu_fregs[FREG(B11_8)]);
1226 return;
1231 switch (ctx->opcode & 0xff00) {
1232 case 0xc900: /* and #imm,R0 */
1233 tcg_gen_andi_i32(REG(0), REG(0), B7_0);
1234 return;
1235 case 0xcd00: /* and.b #imm,@(R0,GBR) */
1237 TCGv addr, val;
1238 addr = tcg_temp_new();
1239 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1240 val = tcg_temp_new();
1241 tcg_gen_qemu_ld8u(val, addr, ctx->memidx);
1242 tcg_gen_andi_i32(val, val, B7_0);
1243 tcg_gen_qemu_st8(val, addr, ctx->memidx);
1244 tcg_temp_free(val);
1245 tcg_temp_free(addr);
1247 return;
1248 case 0x8b00: /* bf label */
1249 CHECK_NOT_DELAY_SLOT
1250 gen_conditional_jump(ctx, ctx->pc + 2,
1251 ctx->pc + 4 + B7_0s * 2);
1252 ctx->bstate = BS_BRANCH;
1253 return;
1254 case 0x8f00: /* bf/s label */
1255 CHECK_NOT_DELAY_SLOT
1256 gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 0);
1257 ctx->flags |= DELAY_SLOT_CONDITIONAL;
1258 return;
1259 case 0x8900: /* bt label */
1260 CHECK_NOT_DELAY_SLOT
1261 gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2,
1262 ctx->pc + 2);
1263 ctx->bstate = BS_BRANCH;
1264 return;
1265 case 0x8d00: /* bt/s label */
1266 CHECK_NOT_DELAY_SLOT
1267 gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 1);
1268 ctx->flags |= DELAY_SLOT_CONDITIONAL;
1269 return;
1270 case 0x8800: /* cmp/eq #imm,R0 */
1271 gen_cmp_imm(TCG_COND_EQ, REG(0), B7_0s);
1272 return;
1273 case 0xc400: /* mov.b @(disp,GBR),R0 */
1275 TCGv addr = tcg_temp_new();
1276 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1277 tcg_gen_qemu_ld8s(REG(0), addr, ctx->memidx);
1278 tcg_temp_free(addr);
1280 return;
1281 case 0xc500: /* mov.w @(disp,GBR),R0 */
1283 TCGv addr = tcg_temp_new();
1284 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1285 tcg_gen_qemu_ld16s(REG(0), addr, ctx->memidx);
1286 tcg_temp_free(addr);
1288 return;
1289 case 0xc600: /* mov.l @(disp,GBR),R0 */
1291 TCGv addr = tcg_temp_new();
1292 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1293 tcg_gen_qemu_ld32s(REG(0), addr, ctx->memidx);
1294 tcg_temp_free(addr);
1296 return;
1297 case 0xc000: /* mov.b R0,@(disp,GBR) */
1299 TCGv addr = tcg_temp_new();
1300 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1301 tcg_gen_qemu_st8(REG(0), addr, ctx->memidx);
1302 tcg_temp_free(addr);
1304 return;
1305 case 0xc100: /* mov.w R0,@(disp,GBR) */
1307 TCGv addr = tcg_temp_new();
1308 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1309 tcg_gen_qemu_st16(REG(0), addr, ctx->memidx);
1310 tcg_temp_free(addr);
1312 return;
1313 case 0xc200: /* mov.l R0,@(disp,GBR) */
1315 TCGv addr = tcg_temp_new();
1316 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1317 tcg_gen_qemu_st32(REG(0), addr, ctx->memidx);
1318 tcg_temp_free(addr);
1320 return;
1321 case 0x8000: /* mov.b R0,@(disp,Rn) */
1323 TCGv addr = tcg_temp_new();
1324 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1325 tcg_gen_qemu_st8(REG(0), addr, ctx->memidx);
1326 tcg_temp_free(addr);
1328 return;
1329 case 0x8100: /* mov.w R0,@(disp,Rn) */
1331 TCGv addr = tcg_temp_new();
1332 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1333 tcg_gen_qemu_st16(REG(0), addr, ctx->memidx);
1334 tcg_temp_free(addr);
1336 return;
1337 case 0x8400: /* mov.b @(disp,Rn),R0 */
1339 TCGv addr = tcg_temp_new();
1340 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1341 tcg_gen_qemu_ld8s(REG(0), addr, ctx->memidx);
1342 tcg_temp_free(addr);
1344 return;
1345 case 0x8500: /* mov.w @(disp,Rn),R0 */
1347 TCGv addr = tcg_temp_new();
1348 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1349 tcg_gen_qemu_ld16s(REG(0), addr, ctx->memidx);
1350 tcg_temp_free(addr);
1352 return;
1353 case 0xc700: /* mova @(disp,PC),R0 */
1354 tcg_gen_movi_i32(REG(0), ((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3);
1355 return;
1356 case 0xcb00: /* or #imm,R0 */
1357 tcg_gen_ori_i32(REG(0), REG(0), B7_0);
1358 return;
1359 case 0xcf00: /* or.b #imm,@(R0,GBR) */
1361 TCGv addr, val;
1362 addr = tcg_temp_new();
1363 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1364 val = tcg_temp_new();
1365 tcg_gen_qemu_ld8u(val, addr, ctx->memidx);
1366 tcg_gen_ori_i32(val, val, B7_0);
1367 tcg_gen_qemu_st8(val, addr, ctx->memidx);
1368 tcg_temp_free(val);
1369 tcg_temp_free(addr);
1371 return;
1372 case 0xc300: /* trapa #imm */
1374 TCGv imm;
1375 CHECK_NOT_DELAY_SLOT
1376 tcg_gen_movi_i32(cpu_pc, ctx->pc);
1377 imm = tcg_const_i32(B7_0);
1378 gen_helper_trapa(imm);
1379 tcg_temp_free(imm);
1380 ctx->bstate = BS_BRANCH;
1382 return;
1383 case 0xc800: /* tst #imm,R0 */
1385 TCGv val = tcg_temp_new();
1386 tcg_gen_andi_i32(val, REG(0), B7_0);
1387 gen_cmp_imm(TCG_COND_EQ, val, 0);
1388 tcg_temp_free(val);
1390 return;
1391 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
1393 TCGv val = tcg_temp_new();
1394 tcg_gen_add_i32(val, REG(0), cpu_gbr);
1395 tcg_gen_qemu_ld8u(val, val, ctx->memidx);
1396 tcg_gen_andi_i32(val, val, B7_0);
1397 gen_cmp_imm(TCG_COND_EQ, val, 0);
1398 tcg_temp_free(val);
1400 return;
1401 case 0xca00: /* xor #imm,R0 */
1402 tcg_gen_xori_i32(REG(0), REG(0), B7_0);
1403 return;
1404 case 0xce00: /* xor.b #imm,@(R0,GBR) */
1406 TCGv addr, val;
1407 addr = tcg_temp_new();
1408 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1409 val = tcg_temp_new();
1410 tcg_gen_qemu_ld8u(val, addr, ctx->memidx);
1411 tcg_gen_xori_i32(val, val, B7_0);
1412 tcg_gen_qemu_st8(val, addr, ctx->memidx);
1413 tcg_temp_free(val);
1414 tcg_temp_free(addr);
1416 return;
1419 switch (ctx->opcode & 0xf08f) {
1420 case 0x408e: /* ldc Rm,Rn_BANK */
1421 CHECK_PRIVILEGED
1422 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8));
1423 return;
1424 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
1425 CHECK_PRIVILEGED
1426 tcg_gen_qemu_ld32s(ALTREG(B6_4), REG(B11_8), ctx->memidx);
1427 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1428 return;
1429 case 0x0082: /* stc Rm_BANK,Rn */
1430 CHECK_PRIVILEGED
1431 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4));
1432 return;
1433 case 0x4083: /* stc.l Rm_BANK,@-Rn */
1434 CHECK_PRIVILEGED
1436 TCGv addr = tcg_temp_new();
1437 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1438 tcg_gen_qemu_st32(ALTREG(B6_4), addr, ctx->memidx);
1439 tcg_temp_free(addr);
1440 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
1442 return;
1445 switch (ctx->opcode & 0xf0ff) {
1446 case 0x0023: /* braf Rn */
1447 CHECK_NOT_DELAY_SLOT
1448 tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->pc + 4);
1449 ctx->flags |= DELAY_SLOT;
1450 ctx->delayed_pc = (uint32_t) - 1;
1451 return;
1452 case 0x0003: /* bsrf Rn */
1453 CHECK_NOT_DELAY_SLOT
1454 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
1455 tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
1456 ctx->flags |= DELAY_SLOT;
1457 ctx->delayed_pc = (uint32_t) - 1;
1458 return;
1459 case 0x4015: /* cmp/pl Rn */
1460 gen_cmp_imm(TCG_COND_GT, REG(B11_8), 0);
1461 return;
1462 case 0x4011: /* cmp/pz Rn */
1463 gen_cmp_imm(TCG_COND_GE, REG(B11_8), 0);
1464 return;
1465 case 0x4010: /* dt Rn */
1466 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1);
1467 gen_cmp_imm(TCG_COND_EQ, REG(B11_8), 0);
1468 return;
1469 case 0x402b: /* jmp @Rn */
1470 CHECK_NOT_DELAY_SLOT
1471 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1472 ctx->flags |= DELAY_SLOT;
1473 ctx->delayed_pc = (uint32_t) - 1;
1474 return;
1475 case 0x400b: /* jsr @Rn */
1476 CHECK_NOT_DELAY_SLOT
1477 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
1478 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1479 ctx->flags |= DELAY_SLOT;
1480 ctx->delayed_pc = (uint32_t) - 1;
1481 return;
1482 case 0x400e: /* ldc Rm,SR */
1483 CHECK_PRIVILEGED
1484 tcg_gen_andi_i32(cpu_sr, REG(B11_8), 0x700083f3);
1485 ctx->bstate = BS_STOP;
1486 return;
1487 case 0x4007: /* ldc.l @Rm+,SR */
1488 CHECK_PRIVILEGED
1490 TCGv val = tcg_temp_new();
1491 tcg_gen_qemu_ld32s(val, REG(B11_8), ctx->memidx);
1492 tcg_gen_andi_i32(cpu_sr, val, 0x700083f3);
1493 tcg_temp_free(val);
1494 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1495 ctx->bstate = BS_STOP;
1497 return;
1498 case 0x0002: /* stc SR,Rn */
1499 CHECK_PRIVILEGED
1500 tcg_gen_mov_i32(REG(B11_8), cpu_sr);
1501 return;
1502 case 0x4003: /* stc SR,@-Rn */
1503 CHECK_PRIVILEGED
1505 TCGv addr = tcg_temp_new();
1506 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1507 tcg_gen_qemu_st32(cpu_sr, addr, ctx->memidx);
1508 tcg_temp_free(addr);
1509 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
1511 return;
1512 #define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \
1513 case ldnum: \
1514 prechk \
1515 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \
1516 return; \
1517 case ldpnum: \
1518 prechk \
1519 tcg_gen_qemu_ld32s (cpu_##reg, REG(B11_8), ctx->memidx); \
1520 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \
1521 return; \
1522 case stnum: \
1523 prechk \
1524 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \
1525 return; \
1526 case stpnum: \
1527 prechk \
1529 TCGv addr = tcg_temp_new(); \
1530 tcg_gen_subi_i32(addr, REG(B11_8), 4); \
1531 tcg_gen_qemu_st32 (cpu_##reg, addr, ctx->memidx); \
1532 tcg_temp_free(addr); \
1533 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4); \
1535 return;
1536 LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {})
1537 LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED)
1538 LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED)
1539 LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED)
1540 LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED)
1541 LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {})
1542 LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {})
1543 LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {})
1544 LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED})
1545 case 0x406a: /* lds Rm,FPSCR */
1546 CHECK_FPU_ENABLED
1547 gen_helper_ld_fpscr(REG(B11_8));
1548 ctx->bstate = BS_STOP;
1549 return;
1550 case 0x4066: /* lds.l @Rm+,FPSCR */
1551 CHECK_FPU_ENABLED
1553 TCGv addr = tcg_temp_new();
1554 tcg_gen_qemu_ld32s(addr, REG(B11_8), ctx->memidx);
1555 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1556 gen_helper_ld_fpscr(addr);
1557 tcg_temp_free(addr);
1558 ctx->bstate = BS_STOP;
1560 return;
1561 case 0x006a: /* sts FPSCR,Rn */
1562 CHECK_FPU_ENABLED
1563 tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff);
1564 return;
1565 case 0x4062: /* sts FPSCR,@-Rn */
1566 CHECK_FPU_ENABLED
1568 TCGv addr, val;
1569 val = tcg_temp_new();
1570 tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff);
1571 addr = tcg_temp_new();
1572 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1573 tcg_gen_qemu_st32(val, addr, ctx->memidx);
1574 tcg_temp_free(addr);
1575 tcg_temp_free(val);
1576 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
1578 return;
1579 case 0x00c3: /* movca.l R0,@Rm */
1581 TCGv val = tcg_temp_new();
1582 tcg_gen_qemu_ld32u(val, REG(B11_8), ctx->memidx);
1583 gen_helper_movcal (REG(B11_8), val);
1584 tcg_gen_qemu_st32(REG(0), REG(B11_8), ctx->memidx);
1586 ctx->has_movcal = 1;
1587 return;
1588 case 0x40a9:
1589 /* MOVUA.L @Rm,R0 (Rm) -> R0
1590 Load non-boundary-aligned data */
1591 tcg_gen_qemu_ld32u(REG(0), REG(B11_8), ctx->memidx);
1592 return;
1593 case 0x40e9:
1594 /* MOVUA.L @Rm+,R0 (Rm) -> R0, Rm + 4 -> Rm
1595 Load non-boundary-aligned data */
1596 tcg_gen_qemu_ld32u(REG(0), REG(B11_8), ctx->memidx);
1597 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1598 return;
1599 case 0x0029: /* movt Rn */
1600 tcg_gen_andi_i32(REG(B11_8), cpu_sr, SR_T);
1601 return;
1602 case 0x0073:
1603 /* MOVCO.L
1604 LDST -> T
1605 If (T == 1) R0 -> (Rn)
1606 0 -> LDST
1608 if (ctx->features & SH_FEATURE_SH4A) {
1609 int label = gen_new_label();
1610 gen_clr_t();
1611 tcg_gen_or_i32(cpu_sr, cpu_sr, cpu_ldst);
1612 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ldst, 0, label);
1613 tcg_gen_qemu_st32(REG(0), REG(B11_8), ctx->memidx);
1614 gen_set_label(label);
1615 tcg_gen_movi_i32(cpu_ldst, 0);
1616 return;
1617 } else
1618 break;
1619 case 0x0063:
1620 /* MOVLI.L @Rm,R0
1621 1 -> LDST
1622 (Rm) -> R0
1623 When interrupt/exception
1624 occurred 0 -> LDST
1626 if (ctx->features & SH_FEATURE_SH4A) {
1627 tcg_gen_movi_i32(cpu_ldst, 0);
1628 tcg_gen_qemu_ld32s(REG(0), REG(B11_8), ctx->memidx);
1629 tcg_gen_movi_i32(cpu_ldst, 1);
1630 return;
1631 } else
1632 break;
1633 case 0x0093: /* ocbi @Rn */
1635 gen_helper_ocbi (REG(B11_8));
1637 return;
1638 case 0x00a3: /* ocbp @Rn */
1640 TCGv dummy = tcg_temp_new();
1641 tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx);
1642 tcg_temp_free(dummy);
1644 return;
1645 case 0x00b3: /* ocbwb @Rn */
1647 TCGv dummy = tcg_temp_new();
1648 tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx);
1649 tcg_temp_free(dummy);
1651 return;
1652 case 0x0083: /* pref @Rn */
1653 return;
1654 case 0x00d3: /* prefi @Rn */
1655 if (ctx->features & SH_FEATURE_SH4A)
1656 return;
1657 else
1658 break;
1659 case 0x00e3: /* icbi @Rn */
1660 if (ctx->features & SH_FEATURE_SH4A)
1661 return;
1662 else
1663 break;
1664 case 0x00ab: /* synco */
1665 if (ctx->features & SH_FEATURE_SH4A)
1666 return;
1667 else
1668 break;
1669 case 0x4024: /* rotcl Rn */
1671 TCGv tmp = tcg_temp_new();
1672 tcg_gen_mov_i32(tmp, cpu_sr);
1673 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 31);
1674 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1675 gen_copy_bit_i32(REG(B11_8), 0, tmp, 0);
1676 tcg_temp_free(tmp);
1678 return;
1679 case 0x4025: /* rotcr Rn */
1681 TCGv tmp = tcg_temp_new();
1682 tcg_gen_mov_i32(tmp, cpu_sr);
1683 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
1684 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1685 gen_copy_bit_i32(REG(B11_8), 31, tmp, 0);
1686 tcg_temp_free(tmp);
1688 return;
1689 case 0x4004: /* rotl Rn */
1690 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 31);
1691 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1692 gen_copy_bit_i32(REG(B11_8), 0, cpu_sr, 0);
1693 return;
1694 case 0x4005: /* rotr Rn */
1695 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
1696 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1697 gen_copy_bit_i32(REG(B11_8), 31, cpu_sr, 0);
1698 return;
1699 case 0x4000: /* shll Rn */
1700 case 0x4020: /* shal Rn */
1701 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 31);
1702 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1703 return;
1704 case 0x4021: /* shar Rn */
1705 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
1706 tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1);
1707 return;
1708 case 0x4001: /* shlr Rn */
1709 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
1710 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1711 return;
1712 case 0x4008: /* shll2 Rn */
1713 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2);
1714 return;
1715 case 0x4018: /* shll8 Rn */
1716 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8);
1717 return;
1718 case 0x4028: /* shll16 Rn */
1719 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16);
1720 return;
1721 case 0x4009: /* shlr2 Rn */
1722 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2);
1723 return;
1724 case 0x4019: /* shlr8 Rn */
1725 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8);
1726 return;
1727 case 0x4029: /* shlr16 Rn */
1728 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16);
1729 return;
1730 case 0x401b: /* tas.b @Rn */
1732 TCGv addr, val;
1733 addr = tcg_temp_local_new();
1734 tcg_gen_mov_i32(addr, REG(B11_8));
1735 val = tcg_temp_local_new();
1736 tcg_gen_qemu_ld8u(val, addr, ctx->memidx);
1737 gen_cmp_imm(TCG_COND_EQ, val, 0);
1738 tcg_gen_ori_i32(val, val, 0x80);
1739 tcg_gen_qemu_st8(val, addr, ctx->memidx);
1740 tcg_temp_free(val);
1741 tcg_temp_free(addr);
1743 return;
1744 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1745 CHECK_FPU_ENABLED
1746 tcg_gen_mov_i32(cpu_fregs[FREG(B11_8)], cpu_fpul);
1747 return;
1748 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1749 CHECK_FPU_ENABLED
1750 tcg_gen_mov_i32(cpu_fpul, cpu_fregs[FREG(B11_8)]);
1751 return;
1752 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
1753 CHECK_FPU_ENABLED
1754 if (ctx->fpscr & FPSCR_PR) {
1755 TCGv_i64 fp;
1756 if (ctx->opcode & 0x0100)
1757 break; /* illegal instruction */
1758 fp = tcg_temp_new_i64();
1759 gen_helper_float_DT(fp, cpu_fpul);
1760 gen_store_fpr64(fp, DREG(B11_8));
1761 tcg_temp_free_i64(fp);
1763 else {
1764 gen_helper_float_FT(cpu_fregs[FREG(B11_8)], cpu_fpul);
1766 return;
1767 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1768 CHECK_FPU_ENABLED
1769 if (ctx->fpscr & FPSCR_PR) {
1770 TCGv_i64 fp;
1771 if (ctx->opcode & 0x0100)
1772 break; /* illegal instruction */
1773 fp = tcg_temp_new_i64();
1774 gen_load_fpr64(fp, DREG(B11_8));
1775 gen_helper_ftrc_DT(cpu_fpul, fp);
1776 tcg_temp_free_i64(fp);
1778 else {
1779 gen_helper_ftrc_FT(cpu_fpul, cpu_fregs[FREG(B11_8)]);
1781 return;
1782 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
1783 CHECK_FPU_ENABLED
1785 gen_helper_fneg_T(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)]);
1787 return;
1788 case 0xf05d: /* fabs FRn/DRn */
1789 CHECK_FPU_ENABLED
1790 if (ctx->fpscr & FPSCR_PR) {
1791 if (ctx->opcode & 0x0100)
1792 break; /* illegal instruction */
1793 TCGv_i64 fp = tcg_temp_new_i64();
1794 gen_load_fpr64(fp, DREG(B11_8));
1795 gen_helper_fabs_DT(fp, fp);
1796 gen_store_fpr64(fp, DREG(B11_8));
1797 tcg_temp_free_i64(fp);
1798 } else {
1799 gen_helper_fabs_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)]);
1801 return;
1802 case 0xf06d: /* fsqrt FRn */
1803 CHECK_FPU_ENABLED
1804 if (ctx->fpscr & FPSCR_PR) {
1805 if (ctx->opcode & 0x0100)
1806 break; /* illegal instruction */
1807 TCGv_i64 fp = tcg_temp_new_i64();
1808 gen_load_fpr64(fp, DREG(B11_8));
1809 gen_helper_fsqrt_DT(fp, fp);
1810 gen_store_fpr64(fp, DREG(B11_8));
1811 tcg_temp_free_i64(fp);
1812 } else {
1813 gen_helper_fsqrt_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)]);
1815 return;
1816 case 0xf07d: /* fsrra FRn */
1817 CHECK_FPU_ENABLED
1818 break;
1819 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
1820 CHECK_FPU_ENABLED
1821 if (!(ctx->fpscr & FPSCR_PR)) {
1822 tcg_gen_movi_i32(cpu_fregs[FREG(B11_8)], 0);
1824 return;
1825 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
1826 CHECK_FPU_ENABLED
1827 if (!(ctx->fpscr & FPSCR_PR)) {
1828 tcg_gen_movi_i32(cpu_fregs[FREG(B11_8)], 0x3f800000);
1830 return;
1831 case 0xf0ad: /* fcnvsd FPUL,DRn */
1832 CHECK_FPU_ENABLED
1834 TCGv_i64 fp = tcg_temp_new_i64();
1835 gen_helper_fcnvsd_FT_DT(fp, cpu_fpul);
1836 gen_store_fpr64(fp, DREG(B11_8));
1837 tcg_temp_free_i64(fp);
1839 return;
1840 case 0xf0bd: /* fcnvds DRn,FPUL */
1841 CHECK_FPU_ENABLED
1843 TCGv_i64 fp = tcg_temp_new_i64();
1844 gen_load_fpr64(fp, DREG(B11_8));
1845 gen_helper_fcnvds_DT_FT(cpu_fpul, fp);
1846 tcg_temp_free_i64(fp);
1848 return;
1850 #if 0
1851 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1852 ctx->opcode, ctx->pc);
1853 fflush(stderr);
1854 #endif
1855 gen_helper_raise_illegal_instruction();
1856 ctx->bstate = BS_EXCP;
1859 static void decode_opc(DisasContext * ctx)
1861 uint32_t old_flags = ctx->flags;
1863 _decode_opc(ctx);
1865 if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
1866 if (ctx->flags & DELAY_SLOT_CLEARME) {
1867 gen_store_flags(0);
1868 } else {
1869 /* go out of the delay slot */
1870 uint32_t new_flags = ctx->flags;
1871 new_flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
1872 gen_store_flags(new_flags);
1874 ctx->flags = 0;
1875 ctx->bstate = BS_BRANCH;
1876 if (old_flags & DELAY_SLOT_CONDITIONAL) {
1877 gen_delayed_conditional_jump(ctx);
1878 } else if (old_flags & DELAY_SLOT) {
1879 gen_jump(ctx);
1884 /* go into a delay slot */
1885 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL))
1886 gen_store_flags(ctx->flags);
1889 static inline void
1890 gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
1891 int search_pc)
1893 DisasContext ctx;
1894 target_ulong pc_start;
1895 static uint16_t *gen_opc_end;
1896 CPUBreakpoint *bp;
1897 int i, ii;
1898 int num_insns;
1899 int max_insns;
1901 pc_start = tb->pc;
1902 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1903 ctx.pc = pc_start;
1904 ctx.flags = (uint32_t)tb->flags;
1905 ctx.bstate = BS_NONE;
1906 ctx.sr = env->sr;
1907 ctx.fpscr = env->fpscr;
1908 ctx.memidx = (env->sr & SR_MD) ? 1 : 0;
1909 /* We don't know if the delayed pc came from a dynamic or static branch,
1910 so assume it is a dynamic branch. */
1911 ctx.delayed_pc = -1; /* use delayed pc from env pointer */
1912 ctx.tb = tb;
1913 ctx.singlestep_enabled = env->singlestep_enabled;
1914 ctx.features = env->features;
1915 ctx.has_movcal = (tb->flags & TB_FLAG_PENDING_MOVCA);
1917 #ifdef DEBUG_DISAS
1918 qemu_log_mask(CPU_LOG_TB_CPU,
1919 "------------------------------------------------\n");
1920 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
1921 #endif
1923 ii = -1;
1924 num_insns = 0;
1925 max_insns = tb->cflags & CF_COUNT_MASK;
1926 if (max_insns == 0)
1927 max_insns = CF_COUNT_MASK;
1928 gen_icount_start();
1929 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1930 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
1931 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1932 if (ctx.pc == bp->pc) {
1933 /* We have hit a breakpoint - make sure PC is up-to-date */
1934 tcg_gen_movi_i32(cpu_pc, ctx.pc);
1935 gen_helper_debug();
1936 ctx.bstate = BS_EXCP;
1937 break;
1941 if (search_pc) {
1942 i = gen_opc_ptr - gen_opc_buf;
1943 if (ii < i) {
1944 ii++;
1945 while (ii < i)
1946 gen_opc_instr_start[ii++] = 0;
1948 gen_opc_pc[ii] = ctx.pc;
1949 gen_opc_hflags[ii] = ctx.flags;
1950 gen_opc_instr_start[ii] = 1;
1951 gen_opc_icount[ii] = num_insns;
1953 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
1954 gen_io_start();
1955 #if 0
1956 fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
1957 fflush(stderr);
1958 #endif
1959 ctx.opcode = lduw_code(ctx.pc);
1960 decode_opc(&ctx);
1961 num_insns++;
1962 ctx.pc += 2;
1963 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1964 break;
1965 if (env->singlestep_enabled)
1966 break;
1967 if (num_insns >= max_insns)
1968 break;
1969 if (singlestep)
1970 break;
1972 if (tb->cflags & CF_LAST_IO)
1973 gen_io_end();
1974 if (env->singlestep_enabled) {
1975 tcg_gen_movi_i32(cpu_pc, ctx.pc);
1976 gen_helper_debug();
1977 } else {
1978 switch (ctx.bstate) {
1979 case BS_STOP:
1980 /* gen_op_interrupt_restart(); */
1981 /* fall through */
1982 case BS_NONE:
1983 if (ctx.flags) {
1984 gen_store_flags(ctx.flags | DELAY_SLOT_CLEARME);
1986 gen_goto_tb(&ctx, 0, ctx.pc);
1987 break;
1988 case BS_EXCP:
1989 /* gen_op_interrupt_restart(); */
1990 tcg_gen_exit_tb(0);
1991 break;
1992 case BS_BRANCH:
1993 default:
1994 break;
1998 gen_icount_end(tb, num_insns);
1999 *gen_opc_ptr = INDEX_op_end;
2000 if (search_pc) {
2001 i = gen_opc_ptr - gen_opc_buf;
2002 ii++;
2003 while (ii <= i)
2004 gen_opc_instr_start[ii++] = 0;
2005 } else {
2006 tb->size = ctx.pc - pc_start;
2007 tb->icount = num_insns;
2010 #ifdef DEBUG_DISAS
2011 #ifdef SH4_DEBUG_DISAS
2012 qemu_log_mask(CPU_LOG_TB_IN_ASM, "\n");
2013 #endif
2014 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
2015 qemu_log("IN:\n"); /* , lookup_symbol(pc_start)); */
2016 log_target_disas(pc_start, ctx.pc - pc_start, 0);
2017 qemu_log("\n");
2019 #endif
2022 void gen_intermediate_code(CPUState * env, struct TranslationBlock *tb)
2024 gen_intermediate_code_internal(env, tb, 0);
2027 void gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
2029 gen_intermediate_code_internal(env, tb, 1);
2032 void gen_pc_load(CPUState *env, TranslationBlock *tb,
2033 unsigned long searched_pc, int pc_pos, void *puc)
2035 env->pc = gen_opc_pc[pc_pos];
2036 env->flags = gen_opc_hflags[pc_pos];