]> git.proxmox.com Git - mirror_qemu.git/blame - target-sh4/translate.c
sh4: CPU versioning.
[mirror_qemu.git] / target-sh4 / translate.c
CommitLineData
fdf9b3e8
FB
1/*
2 * SH4 translation
5fafdf24 3 *
fdf9b3e8
FB
4 * Copyright (c) 2005 Samuel Tardieu
5 *
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.
10 *
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.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <stdarg.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <inttypes.h>
25#include <assert.h>
26
27#define DEBUG_DISAS
28#define SH4_DEBUG_DISAS
29//#define SH4_SINGLE_STEP
30
31#include "cpu.h"
32#include "exec-all.h"
33#include "disas.h"
988d7eaa 34#include "helper.h"
57fec1fe 35#include "tcg-op.h"
ca10f867 36#include "qemu-common.h"
fdf9b3e8
FB
37
38typedef struct DisasContext {
39 struct TranslationBlock *tb;
40 target_ulong pc;
41 uint32_t sr;
eda9b09b 42 uint32_t fpscr;
fdf9b3e8
FB
43 uint16_t opcode;
44 uint32_t flags;
823029f9 45 int bstate;
fdf9b3e8
FB
46 int memidx;
47 uint32_t delayed_pc;
48 int singlestep_enabled;
49} DisasContext;
50
823029f9
TS
51enum {
52 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
53 * exception condition
54 */
55 BS_STOP = 1, /* We want to stop translation for any reason */
56 BS_BRANCH = 2, /* We reached a branch condition */
57 BS_EXCP = 3, /* We reached an exception condition */
58};
59
1e8864f7
AJ
60/* global register indexes */
61static TCGv cpu_env;
62static TCGv cpu_gregs[24];
3a8a44c4
AJ
63static TCGv cpu_pc, cpu_sr, cpu_ssr, cpu_spc, cpu_gbr;
64static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl;
1000822b
AJ
65static TCGv cpu_pr, cpu_fpscr, cpu_fpul, cpu_flags;
66
67/* internal register indexes */
68static TCGv cpu_flags, cpu_delayed_pc;
1e8864f7 69
2e70f6ef
PB
70#include "gen-icount.h"
71
a5f1b965 72static void sh4_translate_init(void)
2e70f6ef 73{
1e8864f7 74 int i;
2e70f6ef 75 static int done_init = 0;
559dd74d 76 static const char * const gregnames[24] = {
1e8864f7
AJ
77 "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
78 "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
79 "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
80 "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
81 "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
82 };
83
2e70f6ef
PB
84 if (done_init)
85 return;
1e8864f7 86
2e70f6ef 87 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
1e8864f7
AJ
88
89 for (i = 0; i < 24; i++)
90 cpu_gregs[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
91 offsetof(CPUState, gregs[i]),
92 gregnames[i]);
988d7eaa 93
3a8a44c4
AJ
94 cpu_pc = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
95 offsetof(CPUState, pc), "PC");
96 cpu_sr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
97 offsetof(CPUState, sr), "SR");
98 cpu_ssr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
99 offsetof(CPUState, ssr), "SSR");
100 cpu_spc = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
101 offsetof(CPUState, spc), "SPC");
102 cpu_gbr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
103 offsetof(CPUState, gbr), "GBR");
104 cpu_vbr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
105 offsetof(CPUState, vbr), "VBR");
106 cpu_sgr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
107 offsetof(CPUState, sgr), "SGR");
108 cpu_dbr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
109 offsetof(CPUState, dbr), "DBR");
110 cpu_mach = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
111 offsetof(CPUState, mach), "MACH");
112 cpu_macl = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
113 offsetof(CPUState, macl), "MACL");
114 cpu_pr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
115 offsetof(CPUState, pr), "PR");
116 cpu_fpscr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
117 offsetof(CPUState, fpscr), "FPSCR");
118 cpu_fpul = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
119 offsetof(CPUState, fpul), "FPUL");
120
1000822b
AJ
121 cpu_flags = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
122 offsetof(CPUState, flags), "_flags_");
123 cpu_delayed_pc = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
124 offsetof(CPUState, delayed_pc),
125 "_delayed_pc_");
126
988d7eaa
AJ
127 /* register helpers */
128#undef DEF_HELPER
129#define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
130#include "helper.h"
131
2e70f6ef
PB
132 done_init = 1;
133}
134
fdf9b3e8
FB
135void cpu_dump_state(CPUState * env, FILE * f,
136 int (*cpu_fprintf) (FILE * f, const char *fmt, ...),
137 int flags)
138{
139 int i;
eda9b09b
FB
140 cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
141 env->pc, env->sr, env->pr, env->fpscr);
274a9e70
AJ
142 cpu_fprintf(f, "spc=0x%08x ssr=0x%08x gbr=0x%08x vbr=0x%08x\n",
143 env->spc, env->ssr, env->gbr, env->vbr);
144 cpu_fprintf(f, "sgr=0x%08x dbr=0x%08x delayed_pc=0x%08x fpul=0x%08x\n",
145 env->sgr, env->dbr, env->delayed_pc, env->fpul);
fdf9b3e8
FB
146 for (i = 0; i < 24; i += 4) {
147 cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
148 i, env->gregs[i], i + 1, env->gregs[i + 1],
149 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
150 }
151 if (env->flags & DELAY_SLOT) {
152 cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
153 env->delayed_pc);
154 } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
155 cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
156 env->delayed_pc);
157 }
158}
159
160void cpu_sh4_reset(CPUSH4State * env)
161{
9c2a9ea1 162#if defined(CONFIG_USER_ONLY)
4c909d14 163 env->sr = SR_FD; /* FD - kernel does lazy fpu context switch */
9c2a9ea1 164#else
fdf9b3e8 165 env->sr = 0x700000F0; /* MD, RB, BL, I3-I0 */
9c2a9ea1 166#endif
fdf9b3e8
FB
167 env->vbr = 0;
168 env->pc = 0xA0000000;
ea6cf6be
TS
169#if defined(CONFIG_USER_ONLY)
170 env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
b0b3de89 171 set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
ea6cf6be
TS
172#else
173 env->fpscr = 0x00040001; /* CPU reset value according to SH4 manual */
b0b3de89 174 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
ea6cf6be 175#endif
fdf9b3e8
FB
176 env->mmucr = 0;
177}
178
0fd3ca30
AJ
179typedef struct {
180 const unsigned char *name;
181 int id;
182 uint32_t pvr;
183 uint32_t prr;
184 uint32_t cvr;
185} sh4_def_t;
186
187static sh4_def_t sh4_defs[] = {
188 {
189 .name = "SH7750R",
190 .id = SH_CPU_SH7750R,
191 .pvr = 0x00050000,
192 .prr = 0x00000100,
193 .cvr = 0x00110000,
194 }, {
195 .name = "SH7751R",
196 .id = SH_CPU_SH7751R,
197 .pvr = 0x04050005,
198 .prr = 0x00000113,
199 .cvr = 0x00110000, /* Neutered caches, should be 0x20480000 */
200 },
201};
202
203static const sh4_def_t *cpu_sh4_find_by_name(const unsigned char *name)
204{
205 int i;
206
207 if (strcasecmp(name, "any") == 0)
208 return &sh4_defs[0];
209
210 for (i = 0; i < sizeof(sh4_defs) / sizeof(*sh4_defs); i++)
211 if (strcasecmp(name, sh4_defs[i].name) == 0)
212 return &sh4_defs[i];
213
214 return NULL;
215}
216
217void sh4_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
218{
219 int i;
220
221 for (i = 0; i < sizeof(sh4_defs) / sizeof(*sh4_defs); i++)
222 (*cpu_fprintf)(f, "%s\n", sh4_defs[i].name);
223}
224
225static int cpu_sh4_register(CPUSH4State *env, const sh4_def_t *def)
226{
227 env->pvr = def->pvr;
228 env->prr = def->prr;
229 env->cvr = def->cvr;
230 env->id = def->id;
231}
232
aaed909a 233CPUSH4State *cpu_sh4_init(const char *cpu_model)
fdf9b3e8
FB
234{
235 CPUSH4State *env;
0fd3ca30 236 const sh4_def_t *def;
fdf9b3e8 237
0fd3ca30
AJ
238 def = cpu_sh4_find_by_name(cpu_model);
239 if (!def)
240 return NULL;
fdf9b3e8
FB
241 env = qemu_mallocz(sizeof(CPUSH4State));
242 if (!env)
243 return NULL;
244 cpu_exec_init(env);
2e70f6ef 245 sh4_translate_init();
fdf9b3e8 246 cpu_sh4_reset(env);
0fd3ca30 247 cpu_sh4_register(env, def);
fdf9b3e8
FB
248 tlb_flush(env, 1);
249 return env;
250}
251
fdf9b3e8
FB
252static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
253{
254 TranslationBlock *tb;
255 tb = ctx->tb;
256
257 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
258 !ctx->singlestep_enabled) {
259 /* Use a direct jump if in same page and singlestep not enabled */
57fec1fe 260 tcg_gen_goto_tb(n);
3a8a44c4 261 tcg_gen_movi_i32(cpu_pc, dest);
57fec1fe 262 tcg_gen_exit_tb((long) tb + n);
fdf9b3e8 263 } else {
3a8a44c4 264 tcg_gen_movi_i32(cpu_pc, dest);
57fec1fe 265 if (ctx->singlestep_enabled)
e6afc2f4 266 tcg_gen_helper_0_0(helper_debug);
57fec1fe 267 tcg_gen_exit_tb(0);
fdf9b3e8 268 }
fdf9b3e8
FB
269}
270
fdf9b3e8
FB
271static void gen_jump(DisasContext * ctx)
272{
273 if (ctx->delayed_pc == (uint32_t) - 1) {
274 /* Target is not statically known, it comes necessarily from a
275 delayed jump as immediate jump are conditinal jumps */
1000822b 276 tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc);
fdf9b3e8 277 if (ctx->singlestep_enabled)
e6afc2f4 278 tcg_gen_helper_0_0(helper_debug);
57fec1fe 279 tcg_gen_exit_tb(0);
fdf9b3e8
FB
280 } else {
281 gen_goto_tb(ctx, 0, ctx->delayed_pc);
282 }
283}
284
1000822b
AJ
285static inline void gen_branch_slot(uint32_t delayed_pc, int t)
286{
c55497ec 287 TCGv sr;
1000822b
AJ
288 int label = gen_new_label();
289 tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc);
c55497ec
AJ
290 sr = tcg_temp_new(TCG_TYPE_I32);
291 tcg_gen_andi_i32(sr, cpu_sr, SR_T);
292 tcg_gen_brcondi_i32(TCG_COND_NE, sr, t ? SR_T : 0, label);
1000822b
AJ
293 tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
294 gen_set_label(label);
295}
296
fdf9b3e8
FB
297/* Immediate conditional jump (bt or bf) */
298static void gen_conditional_jump(DisasContext * ctx,
299 target_ulong ift, target_ulong ifnott)
300{
301 int l1;
c55497ec 302 TCGv sr;
fdf9b3e8
FB
303
304 l1 = gen_new_label();
c55497ec
AJ
305 sr = tcg_temp_new(TCG_TYPE_I32);
306 tcg_gen_andi_i32(sr, cpu_sr, SR_T);
307 tcg_gen_brcondi_i32(TCG_COND_EQ, sr, SR_T, l1);
fdf9b3e8
FB
308 gen_goto_tb(ctx, 0, ifnott);
309 gen_set_label(l1);
310 gen_goto_tb(ctx, 1, ift);
311}
312
313/* Delayed conditional jump (bt or bf) */
314static void gen_delayed_conditional_jump(DisasContext * ctx)
315{
316 int l1;
c55497ec 317 TCGv ds;
fdf9b3e8
FB
318
319 l1 = gen_new_label();
c55497ec
AJ
320 ds = tcg_temp_new(TCG_TYPE_I32);
321 tcg_gen_andi_i32(ds, cpu_flags, DELAY_SLOT_TRUE);
322 tcg_gen_brcondi_i32(TCG_COND_EQ, ds, DELAY_SLOT_TRUE, l1);
823029f9 323 gen_goto_tb(ctx, 1, ctx->pc + 2);
fdf9b3e8 324 gen_set_label(l1);
1000822b 325 tcg_gen_andi_i32(cpu_flags, cpu_flags, ~DELAY_SLOT_TRUE);
9c2a9ea1 326 gen_jump(ctx);
fdf9b3e8
FB
327}
328
a4625612
AJ
329static inline void gen_set_t(void)
330{
331 tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T);
332}
333
334static inline void gen_clr_t(void)
335{
336 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
337}
338
339static inline void gen_cmp(int cond, TCGv t0, TCGv t1)
340{
341 int label1 = gen_new_label();
342 int label2 = gen_new_label();
343 tcg_gen_brcond_i32(cond, t1, t0, label1);
344 gen_clr_t();
345 tcg_gen_br(label2);
346 gen_set_label(label1);
347 gen_set_t();
348 gen_set_label(label2);
349}
350
351static inline void gen_cmp_imm(int cond, TCGv t0, int32_t imm)
352{
353 int label1 = gen_new_label();
354 int label2 = gen_new_label();
355 tcg_gen_brcondi_i32(cond, t0, imm, label1);
356 gen_clr_t();
357 tcg_gen_br(label2);
358 gen_set_label(label1);
359 gen_set_t();
360 gen_set_label(label2);
361}
362
1000822b
AJ
363static inline void gen_store_flags(uint32_t flags)
364{
365 tcg_gen_andi_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
366 tcg_gen_ori_i32(cpu_flags, cpu_flags, flags);
367}
368
69d6275b
AJ
369static inline void gen_copy_bit_i32(TCGv t0, int p0, TCGv t1, int p1)
370{
371 TCGv tmp = tcg_temp_new(TCG_TYPE_I32);
372
373 p0 &= 0x1f;
374 p1 &= 0x1f;
375
376 tcg_gen_andi_i32(tmp, t1, (1 << p1));
377 tcg_gen_andi_i32(t0, t0, ~(1 << p0));
378 if (p0 < p1)
379 tcg_gen_shri_i32(tmp, tmp, p1 - p0);
380 else if (p0 > p1)
381 tcg_gen_shli_i32(tmp, tmp, p0 - p1);
382 tcg_gen_or_i32(t0, t0, tmp);
383
384 tcg_temp_free(tmp);
385}
386
cc4ba6a9
AJ
387
388static inline void gen_load_fpr32(TCGv t, int reg)
389{
390 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, fregs[reg]));
391}
392
393static inline void gen_load_fpr64(TCGv t, int reg)
394{
395 TCGv tmp1 = tcg_temp_new(TCG_TYPE_I32);
396 TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
397
398 tcg_gen_ld_i32(tmp1, cpu_env, offsetof(CPUState, fregs[reg]));
399 tcg_gen_extu_i32_i64(t, tmp1);
400 tcg_gen_shli_i64(t, t, 32);
401 tcg_gen_ld_i32(tmp1, cpu_env, offsetof(CPUState, fregs[reg + 1]));
402 tcg_gen_extu_i32_i64(tmp2, tmp1);
403 tcg_temp_free(tmp1);
404 tcg_gen_or_i64(t, t, tmp2);
405 tcg_temp_free(tmp2);
406}
407
408static inline void gen_store_fpr32(TCGv t, int reg)
409{
410 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, fregs[reg]));
411}
412
413static inline void gen_store_fpr64 (TCGv t, int reg)
414{
415 TCGv tmp = tcg_temp_new(TCG_TYPE_I32);
416
417 tcg_gen_trunc_i64_i32(tmp, t);
418 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, fregs[reg + 1]));
419 tcg_gen_shri_i64(t, t, 32);
420 tcg_gen_trunc_i64_i32(tmp, t);
421 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, fregs[reg]));
422 tcg_temp_free(tmp);
423}
424
fdf9b3e8
FB
425#define B3_0 (ctx->opcode & 0xf)
426#define B6_4 ((ctx->opcode >> 4) & 0x7)
427#define B7_4 ((ctx->opcode >> 4) & 0xf)
428#define B7_0 (ctx->opcode & 0xff)
429#define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
430#define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
431 (ctx->opcode & 0xfff))
432#define B11_8 ((ctx->opcode >> 8) & 0xf)
433#define B15_12 ((ctx->opcode >> 12) & 0xf)
434
435#define REG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB) ? \
7efbe241 436 (cpu_gregs[x + 16]) : (cpu_gregs[x]))
fdf9b3e8
FB
437
438#define ALTREG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) != (SR_MD | SR_RB) \
7efbe241 439 ? (cpu_gregs[x + 16]) : (cpu_gregs[x]))
fdf9b3e8 440
eda9b09b 441#define FREG(x) (ctx->fpscr & FPSCR_FR ? (x) ^ 0x10 : (x))
f09111e0 442#define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
eda9b09b 443#define XREG(x) (ctx->fpscr & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x))
ea6cf6be 444#define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */
eda9b09b 445
fdf9b3e8
FB
446#define CHECK_NOT_DELAY_SLOT \
447 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
e6afc2f4 448 {tcg_gen_helper_0_0(helper_raise_slot_illegal_instruction); ctx->bstate = BS_EXCP; \
fdf9b3e8
FB
449 return;}
450
823029f9 451void _decode_opc(DisasContext * ctx)
fdf9b3e8
FB
452{
453#if 0
454 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
455#endif
456 switch (ctx->opcode) {
457 case 0x0019: /* div0u */
3a8a44c4 458 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(SR_M | SR_Q | SR_T));
fdf9b3e8
FB
459 return;
460 case 0x000b: /* rts */
1000822b
AJ
461 CHECK_NOT_DELAY_SLOT
462 tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
fdf9b3e8
FB
463 ctx->flags |= DELAY_SLOT;
464 ctx->delayed_pc = (uint32_t) - 1;
465 return;
466 case 0x0028: /* clrmac */
3a8a44c4
AJ
467 tcg_gen_movi_i32(cpu_mach, 0);
468 tcg_gen_movi_i32(cpu_macl, 0);
fdf9b3e8
FB
469 return;
470 case 0x0048: /* clrs */
3a8a44c4 471 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_S);
fdf9b3e8
FB
472 return;
473 case 0x0008: /* clrt */
a4625612 474 gen_clr_t();
fdf9b3e8
FB
475 return;
476 case 0x0038: /* ldtlb */
ea2b542a 477#if defined(CONFIG_USER_ONLY)
fdf9b3e8 478 assert(0); /* XXXXX */
ea2b542a 479#else
e6afc2f4 480 tcg_gen_helper_0_0(helper_ldtlb);
ea2b542a 481#endif
fdf9b3e8 482 return;
c5e814b2 483 case 0x002b: /* rte */
1000822b
AJ
484 CHECK_NOT_DELAY_SLOT
485 tcg_gen_mov_i32(cpu_sr, cpu_ssr);
486 tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
fdf9b3e8
FB
487 ctx->flags |= DELAY_SLOT;
488 ctx->delayed_pc = (uint32_t) - 1;
489 return;
490 case 0x0058: /* sets */
3a8a44c4 491 tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_S);
fdf9b3e8
FB
492 return;
493 case 0x0018: /* sett */
a4625612 494 gen_set_t();
fdf9b3e8 495 return;
24988dc2 496 case 0xfbfd: /* frchg */
6f06939b 497 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
823029f9 498 ctx->bstate = BS_STOP;
fdf9b3e8 499 return;
24988dc2 500 case 0xf3fd: /* fschg */
6f06939b 501 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ);
823029f9 502 ctx->bstate = BS_STOP;
fdf9b3e8
FB
503 return;
504 case 0x0009: /* nop */
505 return;
506 case 0x001b: /* sleep */
833ed386 507 if (ctx->memidx) {
e6afc2f4 508 tcg_gen_helper_0_0(helper_sleep);
833ed386 509 } else {
e6afc2f4 510 tcg_gen_helper_0_0(helper_raise_illegal_instruction);
833ed386
AJ
511 ctx->bstate = BS_EXCP;
512 }
fdf9b3e8
FB
513 return;
514 }
515
516 switch (ctx->opcode & 0xf000) {
517 case 0x1000: /* mov.l Rm,@(disp,Rn) */
c55497ec
AJ
518 {
519 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
520 tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
521 tcg_gen_qemu_st32(REG(B7_4), addr, ctx->memidx);
522 tcg_temp_free(addr);
523 }
fdf9b3e8
FB
524 return;
525 case 0x5000: /* mov.l @(disp,Rm),Rn */
c55497ec
AJ
526 {
527 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
528 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
529 tcg_gen_qemu_ld32s(REG(B11_8), addr, ctx->memidx);
530 tcg_temp_free(addr);
531 }
fdf9b3e8 532 return;
24988dc2 533 case 0xe000: /* mov #imm,Rn */
7efbe241 534 tcg_gen_movi_i32(REG(B11_8), B7_0s);
fdf9b3e8
FB
535 return;
536 case 0x9000: /* mov.w @(disp,PC),Rn */
c55497ec
AJ
537 {
538 TCGv addr = tcg_const_i32(ctx->pc + 4 + B7_0 * 2);
539 tcg_gen_qemu_ld16s(REG(B11_8), addr, ctx->memidx);
540 tcg_temp_free(addr);
541 }
fdf9b3e8
FB
542 return;
543 case 0xd000: /* mov.l @(disp,PC),Rn */
c55497ec
AJ
544 {
545 TCGv addr = tcg_const_i32((ctx->pc + 4 + B7_0 * 4) & ~3);
546 tcg_gen_qemu_ld32s(REG(B11_8), addr, ctx->memidx);
547 tcg_temp_free(addr);
548 }
fdf9b3e8 549 return;
24988dc2 550 case 0x7000: /* add #imm,Rn */
7efbe241 551 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s);
fdf9b3e8
FB
552 return;
553 case 0xa000: /* bra disp */
554 CHECK_NOT_DELAY_SLOT
1000822b
AJ
555 ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
556 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
fdf9b3e8
FB
557 ctx->flags |= DELAY_SLOT;
558 return;
559 case 0xb000: /* bsr disp */
560 CHECK_NOT_DELAY_SLOT
1000822b
AJ
561 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
562 ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
563 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
fdf9b3e8
FB
564 ctx->flags |= DELAY_SLOT;
565 return;
566 }
567
568 switch (ctx->opcode & 0xf00f) {
569 case 0x6003: /* mov Rm,Rn */
7efbe241 570 tcg_gen_mov_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
571 return;
572 case 0x2000: /* mov.b Rm,@Rn */
7efbe241 573 tcg_gen_qemu_st8(REG(B7_4), REG(B11_8), ctx->memidx);
fdf9b3e8
FB
574 return;
575 case 0x2001: /* mov.w Rm,@Rn */
7efbe241 576 tcg_gen_qemu_st16(REG(B7_4), REG(B11_8), ctx->memidx);
fdf9b3e8
FB
577 return;
578 case 0x2002: /* mov.l Rm,@Rn */
7efbe241 579 tcg_gen_qemu_st32(REG(B7_4), REG(B11_8), ctx->memidx);
fdf9b3e8
FB
580 return;
581 case 0x6000: /* mov.b @Rm,Rn */
7efbe241 582 tcg_gen_qemu_ld8s(REG(B11_8), REG(B7_4), ctx->memidx);
fdf9b3e8
FB
583 return;
584 case 0x6001: /* mov.w @Rm,Rn */
7efbe241 585 tcg_gen_qemu_ld16s(REG(B11_8), REG(B7_4), ctx->memidx);
fdf9b3e8
FB
586 return;
587 case 0x6002: /* mov.l @Rm,Rn */
7efbe241 588 tcg_gen_qemu_ld32s(REG(B11_8), REG(B7_4), ctx->memidx);
fdf9b3e8
FB
589 return;
590 case 0x2004: /* mov.b Rm,@-Rn */
c55497ec
AJ
591 {
592 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
593 tcg_gen_subi_i32(addr, REG(B11_8), 1);
594 tcg_gen_qemu_st8(REG(B7_4), addr, ctx->memidx); /* might cause re-execution */
595 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1); /* modify register status */
596 tcg_temp_free(addr);
597 }
fdf9b3e8
FB
598 return;
599 case 0x2005: /* mov.w Rm,@-Rn */
c55497ec
AJ
600 {
601 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
602 tcg_gen_subi_i32(addr, REG(B11_8), 2);
603 tcg_gen_qemu_st16(REG(B7_4), addr, ctx->memidx);
604 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 2);
605 tcg_temp_free(addr);
606 }
fdf9b3e8
FB
607 return;
608 case 0x2006: /* mov.l Rm,@-Rn */
c55497ec
AJ
609 {
610 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
611 tcg_gen_subi_i32(addr, REG(B11_8), 4);
612 tcg_gen_qemu_st32(REG(B7_4), addr, ctx->memidx);
613 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
614 }
fdf9b3e8 615 return;
eda9b09b 616 case 0x6004: /* mov.b @Rm+,Rn */
7efbe241 617 tcg_gen_qemu_ld8s(REG(B11_8), REG(B7_4), ctx->memidx);
24988dc2 618 if ( B11_8 != B7_4 )
7efbe241 619 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1);
fdf9b3e8
FB
620 return;
621 case 0x6005: /* mov.w @Rm+,Rn */
7efbe241 622 tcg_gen_qemu_ld16s(REG(B11_8), REG(B7_4), ctx->memidx);
24988dc2 623 if ( B11_8 != B7_4 )
7efbe241 624 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
fdf9b3e8
FB
625 return;
626 case 0x6006: /* mov.l @Rm+,Rn */
7efbe241 627 tcg_gen_qemu_ld32s(REG(B11_8), REG(B7_4), ctx->memidx);
24988dc2 628 if ( B11_8 != B7_4 )
7efbe241 629 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
fdf9b3e8
FB
630 return;
631 case 0x0004: /* mov.b Rm,@(R0,Rn) */
c55497ec
AJ
632 {
633 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
634 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
635 tcg_gen_qemu_st8(REG(B7_4), addr, ctx->memidx);
636 tcg_temp_free(addr);
637 }
fdf9b3e8
FB
638 return;
639 case 0x0005: /* mov.w Rm,@(R0,Rn) */
c55497ec
AJ
640 {
641 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
642 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
643 tcg_gen_qemu_st16(REG(B7_4), addr, ctx->memidx);
644 tcg_temp_free(addr);
645 }
fdf9b3e8
FB
646 return;
647 case 0x0006: /* mov.l Rm,@(R0,Rn) */
c55497ec
AJ
648 {
649 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
650 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
651 tcg_gen_qemu_st32(REG(B7_4), addr, ctx->memidx);
652 tcg_temp_free(addr);
653 }
fdf9b3e8
FB
654 return;
655 case 0x000c: /* mov.b @(R0,Rm),Rn */
c55497ec
AJ
656 {
657 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
658 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
659 tcg_gen_qemu_ld8s(REG(B11_8), addr, ctx->memidx);
660 tcg_temp_free(addr);
661 }
fdf9b3e8
FB
662 return;
663 case 0x000d: /* mov.w @(R0,Rm),Rn */
c55497ec
AJ
664 {
665 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
666 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
667 tcg_gen_qemu_ld16s(REG(B11_8), addr, ctx->memidx);
668 tcg_temp_free(addr);
669 }
fdf9b3e8
FB
670 return;
671 case 0x000e: /* mov.l @(R0,Rm),Rn */
c55497ec
AJ
672 {
673 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
674 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
675 tcg_gen_qemu_ld32s(REG(B11_8), addr, ctx->memidx);
676 tcg_temp_free(addr);
677 }
fdf9b3e8
FB
678 return;
679 case 0x6008: /* swap.b Rm,Rn */
c55497ec
AJ
680 {
681 TCGv high, low;
682 high = tcg_temp_new(TCG_TYPE_I32);
683 tcg_gen_ext8u_i32(high, REG(B7_4));
684 tcg_gen_shli_i32(high, high, 8);
685 low = tcg_temp_new(TCG_TYPE_I32);
686 tcg_gen_shri_i32(low, REG(B7_4), 8);
687 tcg_gen_ext8u_i32(low, low);
688 tcg_gen_or_i32(REG(B11_8), high, low);
689 tcg_temp_free(low);
690 tcg_temp_free(high);
691 }
fdf9b3e8
FB
692 return;
693 case 0x6009: /* swap.w Rm,Rn */
c55497ec
AJ
694 {
695 TCGv high, low;
696 high = tcg_temp_new(TCG_TYPE_I32);
697 tcg_gen_ext16u_i32(high, REG(B7_4));
698 tcg_gen_shli_i32(high, high, 16);
699 low = tcg_temp_new(TCG_TYPE_I32);
700 tcg_gen_shri_i32(low, REG(B7_4), 16);
701 tcg_gen_ext16u_i32(low, low);
702 tcg_gen_or_i32(REG(B11_8), high, low);
703 tcg_temp_free(low);
704 tcg_temp_free(high);
705 }
fdf9b3e8
FB
706 return;
707 case 0x200d: /* xtrct Rm,Rn */
c55497ec
AJ
708 {
709 TCGv high, low;
710 high = tcg_temp_new(TCG_TYPE_I32);
711 tcg_gen_ext16u_i32(high, REG(B7_4));
712 tcg_gen_shli_i32(high, high, 16);
713 low = tcg_temp_new(TCG_TYPE_I32);
714 tcg_gen_shri_i32(low, REG(B11_8), 16);
715 tcg_gen_ext16u_i32(low, low);
716 tcg_gen_or_i32(REG(B11_8), high, low);
717 tcg_temp_free(low);
718 tcg_temp_free(high);
719 }
fdf9b3e8
FB
720 return;
721 case 0x300c: /* add Rm,Rn */
7efbe241 722 tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8
FB
723 return;
724 case 0x300e: /* addc Rm,Rn */
7efbe241 725 tcg_gen_helper_1_2(helper_addc, REG(B11_8), REG(B7_4), REG(B11_8));
fdf9b3e8
FB
726 return;
727 case 0x300f: /* addv Rm,Rn */
7efbe241 728 tcg_gen_helper_1_2(helper_addv, REG(B11_8), REG(B7_4), REG(B11_8));
fdf9b3e8
FB
729 return;
730 case 0x2009: /* and Rm,Rn */
7efbe241 731 tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8
FB
732 return;
733 case 0x3000: /* cmp/eq Rm,Rn */
7efbe241 734 gen_cmp(TCG_COND_EQ, REG(B7_4), REG(B11_8));
fdf9b3e8
FB
735 return;
736 case 0x3003: /* cmp/ge Rm,Rn */
7efbe241 737 gen_cmp(TCG_COND_GE, REG(B7_4), REG(B11_8));
fdf9b3e8
FB
738 return;
739 case 0x3007: /* cmp/gt Rm,Rn */
7efbe241 740 gen_cmp(TCG_COND_GT, REG(B7_4), REG(B11_8));
fdf9b3e8
FB
741 return;
742 case 0x3006: /* cmp/hi Rm,Rn */
7efbe241 743 gen_cmp(TCG_COND_GTU, REG(B7_4), REG(B11_8));
fdf9b3e8
FB
744 return;
745 case 0x3002: /* cmp/hs Rm,Rn */
7efbe241 746 gen_cmp(TCG_COND_GEU, REG(B7_4), REG(B11_8));
fdf9b3e8
FB
747 return;
748 case 0x200c: /* cmp/str Rm,Rn */
69d6275b
AJ
749 {
750 int label1 = gen_new_label();
751 int label2 = gen_new_label();
c55497ec
AJ
752 TCGv cmp1 = tcg_temp_local_new(TCG_TYPE_I32);
753 TCGv cmp2 = tcg_temp_local_new(TCG_TYPE_I32);
754 tcg_gen_xor_i32(cmp1, REG(B7_4), REG(B11_8));
755 tcg_gen_andi_i32(cmp2, cmp1, 0xff000000);
756 tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
757 tcg_gen_andi_i32(cmp2, cmp1, 0x00ff0000);
758 tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
759 tcg_gen_andi_i32(cmp2, cmp1, 0x0000ff00);
760 tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
761 tcg_gen_andi_i32(cmp2, cmp1, 0x000000ff);
762 tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
69d6275b
AJ
763 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
764 tcg_gen_br(label2);
765 gen_set_label(label1);
766 tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T);
767 gen_set_label(label2);
c55497ec
AJ
768 tcg_temp_free(cmp2);
769 tcg_temp_free(cmp1);
69d6275b 770 }
fdf9b3e8
FB
771 return;
772 case 0x2007: /* div0s Rm,Rn */
c55497ec
AJ
773 {
774 gen_copy_bit_i32(cpu_sr, 8, REG(B11_8), 31); /* SR_Q */
775 gen_copy_bit_i32(cpu_sr, 9, REG(B7_4), 31); /* SR_M */
776 TCGv val = tcg_temp_new(TCG_TYPE_I32);
777 tcg_gen_xor_i32(val, REG(B7_4), REG(B11_8));
778 gen_copy_bit_i32(cpu_sr, 0, val, 31); /* SR_T */
779 tcg_temp_free(val);
780 }
fdf9b3e8
FB
781 return;
782 case 0x3004: /* div1 Rm,Rn */
7efbe241 783 tcg_gen_helper_1_2(helper_div1, REG(B11_8), REG(B7_4), REG(B11_8));
fdf9b3e8
FB
784 return;
785 case 0x300d: /* dmuls.l Rm,Rn */
6f06939b
AJ
786 {
787 TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
788 TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
789
7efbe241
AJ
790 tcg_gen_ext_i32_i64(tmp1, REG(B7_4));
791 tcg_gen_ext_i32_i64(tmp2, REG(B11_8));
6f06939b
AJ
792 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
793 tcg_gen_trunc_i64_i32(cpu_macl, tmp1);
794 tcg_gen_shri_i64(tmp1, tmp1, 32);
795 tcg_gen_trunc_i64_i32(cpu_mach, tmp1);
796
6f06939b 797 tcg_temp_free(tmp2);
c55497ec 798 tcg_temp_free(tmp1);
6f06939b 799 }
fdf9b3e8
FB
800 return;
801 case 0x3005: /* dmulu.l Rm,Rn */
6f06939b
AJ
802 {
803 TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
804 TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
805
7efbe241
AJ
806 tcg_gen_extu_i32_i64(tmp1, REG(B7_4));
807 tcg_gen_extu_i32_i64(tmp2, REG(B11_8));
6f06939b
AJ
808 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
809 tcg_gen_trunc_i64_i32(cpu_macl, tmp1);
810 tcg_gen_shri_i64(tmp1, tmp1, 32);
811 tcg_gen_trunc_i64_i32(cpu_mach, tmp1);
812
6f06939b 813 tcg_temp_free(tmp2);
c55497ec 814 tcg_temp_free(tmp1);
6f06939b 815 }
fdf9b3e8
FB
816 return;
817 case 0x600e: /* exts.b Rm,Rn */
7efbe241 818 tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
819 return;
820 case 0x600f: /* exts.w Rm,Rn */
7efbe241 821 tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
822 return;
823 case 0x600c: /* extu.b Rm,Rn */
7efbe241 824 tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
825 return;
826 case 0x600d: /* extu.w Rm,Rn */
7efbe241 827 tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4));
fdf9b3e8 828 return;
24988dc2 829 case 0x000f: /* mac.l @Rm+,@Rn+ */
c55497ec
AJ
830 {
831 TCGv arg0, arg1;
832 arg0 = tcg_temp_new(TCG_TYPE_I32);
833 tcg_gen_qemu_ld32s(arg0, REG(B7_4), ctx->memidx);
834 arg1 = tcg_temp_new(TCG_TYPE_I32);
835 tcg_gen_qemu_ld32s(arg1, REG(B11_8), ctx->memidx);
836 tcg_gen_helper_0_2(helper_macl, arg0, arg1);
837 tcg_temp_free(arg1);
838 tcg_temp_free(arg0);
839 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
840 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
841 }
fdf9b3e8
FB
842 return;
843 case 0x400f: /* mac.w @Rm+,@Rn+ */
c55497ec
AJ
844 {
845 TCGv arg0, arg1;
846 arg0 = tcg_temp_new(TCG_TYPE_I32);
847 tcg_gen_qemu_ld32s(arg0, REG(B7_4), ctx->memidx);
848 arg1 = tcg_temp_new(TCG_TYPE_I32);
849 tcg_gen_qemu_ld32s(arg1, REG(B11_8), ctx->memidx);
850 tcg_gen_helper_0_2(helper_macw, arg0, arg1);
851 tcg_temp_free(arg1);
852 tcg_temp_free(arg0);
853 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2);
854 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
855 }
fdf9b3e8
FB
856 return;
857 case 0x0007: /* mul.l Rm,Rn */
7efbe241 858 tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8));
fdf9b3e8
FB
859 return;
860 case 0x200f: /* muls.w Rm,Rn */
c55497ec
AJ
861 {
862 TCGv arg0, arg1;
863 arg0 = tcg_temp_new(TCG_TYPE_I32);
864 tcg_gen_ext16s_i32(arg0, REG(B7_4));
865 arg1 = tcg_temp_new(TCG_TYPE_I32);
866 tcg_gen_ext16s_i32(arg1, REG(B11_8));
867 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
868 tcg_temp_free(arg1);
869 tcg_temp_free(arg0);
870 }
fdf9b3e8
FB
871 return;
872 case 0x200e: /* mulu.w Rm,Rn */
c55497ec
AJ
873 {
874 TCGv arg0, arg1;
875 arg0 = tcg_temp_new(TCG_TYPE_I32);
876 tcg_gen_ext16u_i32(arg0, REG(B7_4));
877 arg1 = tcg_temp_new(TCG_TYPE_I32);
878 tcg_gen_ext16u_i32(arg1, REG(B11_8));
879 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
880 tcg_temp_free(arg1);
881 tcg_temp_free(arg0);
882 }
fdf9b3e8
FB
883 return;
884 case 0x600b: /* neg Rm,Rn */
7efbe241 885 tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
886 return;
887 case 0x600a: /* negc Rm,Rn */
7efbe241 888 tcg_gen_helper_1_1(helper_negc, REG(B11_8), REG(B7_4));
fdf9b3e8
FB
889 return;
890 case 0x6007: /* not Rm,Rn */
7efbe241 891 tcg_gen_not_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
892 return;
893 case 0x200b: /* or Rm,Rn */
7efbe241 894 tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8
FB
895 return;
896 case 0x400c: /* shad Rm,Rn */
69d6275b
AJ
897 {
898 int label1 = gen_new_label();
899 int label2 = gen_new_label();
900 int label3 = gen_new_label();
901 int label4 = gen_new_label();
c55497ec 902 TCGv shift = tcg_temp_local_new(TCG_TYPE_I32);
7efbe241 903 tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
69d6275b 904 /* Rm positive, shift to the left */
c55497ec
AJ
905 tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
906 tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
69d6275b
AJ
907 tcg_gen_br(label4);
908 /* Rm negative, shift to the right */
909 gen_set_label(label1);
c55497ec
AJ
910 tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
911 tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2);
912 tcg_gen_not_i32(shift, REG(B7_4));
913 tcg_gen_andi_i32(shift, shift, 0x1f);
914 tcg_gen_addi_i32(shift, shift, 1);
915 tcg_gen_sar_i32(REG(B11_8), REG(B11_8), shift);
69d6275b
AJ
916 tcg_gen_br(label4);
917 /* Rm = -32 */
918 gen_set_label(label2);
7efbe241
AJ
919 tcg_gen_brcondi_i32(TCG_COND_LT, REG(B11_8), 0, label3);
920 tcg_gen_movi_i32(REG(B11_8), 0);
69d6275b
AJ
921 tcg_gen_br(label4);
922 gen_set_label(label3);
7efbe241 923 tcg_gen_movi_i32(REG(B11_8), 0xffffffff);
69d6275b 924 gen_set_label(label4);
c55497ec 925 tcg_temp_free(shift);
69d6275b 926 }
fdf9b3e8
FB
927 return;
928 case 0x400d: /* shld Rm,Rn */
69d6275b
AJ
929 {
930 int label1 = gen_new_label();
931 int label2 = gen_new_label();
932 int label3 = gen_new_label();
c55497ec 933 TCGv shift = tcg_temp_local_new(TCG_TYPE_I32);
7efbe241 934 tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
69d6275b 935 /* Rm positive, shift to the left */
c55497ec
AJ
936 tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
937 tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
69d6275b
AJ
938 tcg_gen_br(label3);
939 /* Rm negative, shift to the right */
940 gen_set_label(label1);
c55497ec
AJ
941 tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
942 tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2);
943 tcg_gen_not_i32(shift, REG(B7_4));
944 tcg_gen_andi_i32(shift, shift, 0x1f);
945 tcg_gen_addi_i32(shift, shift, 1);
946 tcg_gen_shr_i32(REG(B11_8), REG(B11_8), shift);
69d6275b
AJ
947 tcg_gen_br(label3);
948 /* Rm = -32 */
949 gen_set_label(label2);
7efbe241 950 tcg_gen_movi_i32(REG(B11_8), 0);
69d6275b 951 gen_set_label(label3);
c55497ec 952 tcg_temp_free(shift);
69d6275b 953 }
fdf9b3e8
FB
954 return;
955 case 0x3008: /* sub Rm,Rn */
7efbe241 956 tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8
FB
957 return;
958 case 0x300a: /* subc Rm,Rn */
7efbe241 959 tcg_gen_helper_1_2(helper_subc, REG(B11_8), REG(B7_4), REG(B11_8));
fdf9b3e8
FB
960 return;
961 case 0x300b: /* subv Rm,Rn */
7efbe241 962 tcg_gen_helper_1_2(helper_subv, REG(B11_8), REG(B7_4), REG(B11_8));
fdf9b3e8
FB
963 return;
964 case 0x2008: /* tst Rm,Rn */
c55497ec
AJ
965 {
966 TCGv val = tcg_temp_new(TCG_TYPE_I32);
967 tcg_gen_and_i32(val, REG(B7_4), REG(B11_8));
968 gen_cmp_imm(TCG_COND_EQ, val, 0);
969 tcg_temp_free(val);
970 }
fdf9b3e8
FB
971 return;
972 case 0x200a: /* xor Rm,Rn */
7efbe241 973 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8 974 return;
e67888a7 975 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
022a22c7 976 if (ctx->fpscr & FPSCR_SZ) {
cc4ba6a9
AJ
977 TCGv fp = tcg_temp_new(TCG_TYPE_I64);
978 gen_load_fpr64(fp, XREG(B7_4));
979 gen_store_fpr64(fp, XREG(B11_8));
980 tcg_temp_free(fp);
eda9b09b 981 } else {
cc4ba6a9
AJ
982 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
983 gen_load_fpr32(fp, FREG(B7_4));
984 gen_store_fpr32(fp, FREG(B11_8));
985 tcg_temp_free(fp);
eda9b09b
FB
986 }
987 return;
e67888a7 988 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
022a22c7 989 if (ctx->fpscr & FPSCR_SZ) {
cc4ba6a9
AJ
990 TCGv fp = tcg_temp_new(TCG_TYPE_I64);
991 gen_load_fpr64(fp, XREG(B7_4));
992 tcg_gen_qemu_st64(fp, REG(B11_8), ctx->memidx);
993 tcg_temp_free(fp);
eda9b09b 994 } else {
cc4ba6a9
AJ
995 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
996 gen_load_fpr32(fp, FREG(B7_4));
997 tcg_gen_qemu_st32(fp, REG(B11_8), ctx->memidx);
998 tcg_temp_free(fp);
eda9b09b
FB
999 }
1000 return;
e67888a7 1001 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
022a22c7 1002 if (ctx->fpscr & FPSCR_SZ) {
cc4ba6a9
AJ
1003 TCGv fp = tcg_temp_new(TCG_TYPE_I64);
1004 tcg_gen_qemu_ld64(fp, REG(B7_4), ctx->memidx);
1005 gen_store_fpr64(fp, XREG(B11_8));
1006 tcg_temp_free(fp);
eda9b09b 1007 } else {
cc4ba6a9
AJ
1008 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
1009 tcg_gen_qemu_ld32u(fp, REG(B7_4), ctx->memidx);
1010 gen_store_fpr32(fp, FREG(B11_8));
1011 tcg_temp_free(fp);
eda9b09b
FB
1012 }
1013 return;
e67888a7 1014 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
022a22c7 1015 if (ctx->fpscr & FPSCR_SZ) {
cc4ba6a9
AJ
1016 TCGv fp = tcg_temp_new(TCG_TYPE_I64);
1017 tcg_gen_qemu_ld64(fp, REG(B7_4), ctx->memidx);
1018 gen_store_fpr64(fp, XREG(B11_8));
1019 tcg_temp_free(fp);
1020 tcg_gen_addi_i32(REG(B7_4),REG(B7_4), 8);
eda9b09b 1021 } else {
cc4ba6a9
AJ
1022 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
1023 tcg_gen_qemu_ld32u(fp, REG(B7_4), ctx->memidx);
1024 gen_store_fpr32(fp, FREG(B11_8));
1025 tcg_temp_free(fp);
1026 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
eda9b09b
FB
1027 }
1028 return;
e67888a7 1029 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
022a22c7 1030 if (ctx->fpscr & FPSCR_SZ) {
cc4ba6a9
AJ
1031 TCGv addr, fp;
1032 addr = tcg_temp_new(TCG_TYPE_I32);
1033 tcg_gen_subi_i32(addr, REG(B11_8), 8);
1034 fp = tcg_temp_new(TCG_TYPE_I64);
1035 gen_load_fpr64(fp, XREG(B7_4));
1036 tcg_gen_qemu_st64(fp, addr, ctx->memidx);
1037 tcg_temp_free(fp);
1038 tcg_temp_free(addr);
7efbe241 1039 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 8);
eda9b09b 1040 } else {
cc4ba6a9
AJ
1041 TCGv addr, fp;
1042 addr = tcg_temp_new(TCG_TYPE_I32);
1043 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1044 fp = tcg_temp_new(TCG_TYPE_I32);
1045 gen_load_fpr32(fp, FREG(B7_4));
1046 tcg_gen_qemu_st32(fp, addr, ctx->memidx);
1047 tcg_temp_free(fp);
1048 tcg_temp_free(addr);
7efbe241 1049 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
eda9b09b
FB
1050 }
1051 return;
e67888a7 1052 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
cc4ba6a9
AJ
1053 {
1054 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1055 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
1056 if (ctx->fpscr & FPSCR_SZ) {
1057 TCGv fp = tcg_temp_new(TCG_TYPE_I64);
1058 tcg_gen_qemu_ld64(fp, addr, ctx->memidx);
1059 gen_store_fpr64(fp, XREG(B11_8));
1060 tcg_temp_free(fp);
1061 } else {
1062 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
1063 tcg_gen_qemu_ld32u(fp, addr, ctx->memidx);
1064 gen_store_fpr32(fp, FREG(B11_8));
1065 tcg_temp_free(fp);
1066 }
1067 tcg_temp_free(addr);
eda9b09b
FB
1068 }
1069 return;
e67888a7 1070 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
cc4ba6a9
AJ
1071 {
1072 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1073 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
1074 if (ctx->fpscr & FPSCR_SZ) {
1075 TCGv fp = tcg_temp_new(TCG_TYPE_I64);
1076 gen_load_fpr64(fp, XREG(B7_4));
1077 tcg_gen_qemu_st64(fp, addr, ctx->memidx);
1078 tcg_temp_free(fp);
1079 } else {
1080 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
1081 gen_load_fpr32(fp, FREG(B7_4));
1082 tcg_gen_qemu_st32(fp, addr, ctx->memidx);
1083 tcg_temp_free(fp);
1084 }
1085 tcg_temp_free(addr);
eda9b09b
FB
1086 }
1087 return;
e67888a7
TS
1088 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1089 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1090 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1091 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1092 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1093 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
cc4ba6a9
AJ
1094 {
1095 TCGv fp0, fp1;
1096
1097 if (ctx->fpscr & FPSCR_PR) {
1098 if (ctx->opcode & 0x0110)
1099 break; /* illegal instruction */
1100 fp0 = tcg_temp_new(TCG_TYPE_I64);
1101 fp1 = tcg_temp_new(TCG_TYPE_I64);
1102 gen_load_fpr64(fp0, DREG(B11_8));
1103 gen_load_fpr64(fp1, DREG(B7_4));
1104 }
1105 else {
1106 fp0 = tcg_temp_new(TCG_TYPE_I32);
1107 fp1 = tcg_temp_new(TCG_TYPE_I32);
1108 gen_load_fpr32(fp0, FREG(B11_8));
1109 gen_load_fpr32(fp1, FREG(B7_4));
1110 }
1111
1112 switch (ctx->opcode & 0xf00f) {
1113 case 0xf000: /* fadd Rm,Rn */
1114 if (ctx->fpscr & FPSCR_PR)
1115 tcg_gen_helper_1_2(helper_fadd_DT, fp0, fp0, fp1);
1116 else
1117 tcg_gen_helper_1_2(helper_fadd_FT, fp0, fp0, fp1);
1118 break;
1119 case 0xf001: /* fsub Rm,Rn */
1120 if (ctx->fpscr & FPSCR_PR)
1121 tcg_gen_helper_1_2(helper_fsub_DT, fp0, fp0, fp1);
1122 else
1123 tcg_gen_helper_1_2(helper_fsub_FT, fp0, fp0, fp1);
1124 break;
1125 case 0xf002: /* fmul Rm,Rn */
1126 if (ctx->fpscr & FPSCR_PR)
1127 tcg_gen_helper_1_2(helper_fmul_DT, fp0, fp0, fp1);
1128 else
1129 tcg_gen_helper_1_2(helper_fmul_FT, fp0, fp0, fp1);
1130 break;
1131 case 0xf003: /* fdiv Rm,Rn */
1132 if (ctx->fpscr & FPSCR_PR)
1133 tcg_gen_helper_1_2(helper_fdiv_DT, fp0, fp0, fp1);
1134 else
1135 tcg_gen_helper_1_2(helper_fdiv_FT, fp0, fp0, fp1);
1136 break;
1137 case 0xf004: /* fcmp/eq Rm,Rn */
1138 if (ctx->fpscr & FPSCR_PR)
1139 tcg_gen_helper_0_2(helper_fcmp_eq_DT, fp0, fp1);
1140 else
1141 tcg_gen_helper_0_2(helper_fcmp_eq_FT, fp0, fp1);
1142 return;
1143 case 0xf005: /* fcmp/gt Rm,Rn */
1144 if (ctx->fpscr & FPSCR_PR)
1145 tcg_gen_helper_0_2(helper_fcmp_gt_DT, fp0, fp1);
1146 else
1147 tcg_gen_helper_0_2(helper_fcmp_gt_FT, fp0, fp1);
1148 return;
1149 }
1150
1151 if (ctx->fpscr & FPSCR_PR) {
1152 gen_store_fpr64(fp0, DREG(B11_8));
1153 }
1154 else {
1155 gen_store_fpr32(fp0, FREG(B11_8));
1156 }
1157 tcg_temp_free(fp1);
1158 tcg_temp_free(fp0);
ea6cf6be
TS
1159 }
1160 return;
fdf9b3e8
FB
1161 }
1162
1163 switch (ctx->opcode & 0xff00) {
1164 case 0xc900: /* and #imm,R0 */
7efbe241 1165 tcg_gen_andi_i32(REG(0), REG(0), B7_0);
fdf9b3e8 1166 return;
24988dc2 1167 case 0xcd00: /* and.b #imm,@(R0,GBR) */
c55497ec
AJ
1168 {
1169 TCGv addr, val;
1170 addr = tcg_temp_new(TCG_TYPE_I32);
1171 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1172 val = tcg_temp_new(TCG_TYPE_I32);
1173 tcg_gen_qemu_ld8u(val, addr, ctx->memidx);
1174 tcg_gen_andi_i32(val, val, B7_0);
1175 tcg_gen_qemu_st8(val, addr, ctx->memidx);
1176 tcg_temp_free(val);
1177 tcg_temp_free(addr);
1178 }
fdf9b3e8
FB
1179 return;
1180 case 0x8b00: /* bf label */
1181 CHECK_NOT_DELAY_SLOT
1182 gen_conditional_jump(ctx, ctx->pc + 2,
1183 ctx->pc + 4 + B7_0s * 2);
823029f9 1184 ctx->bstate = BS_BRANCH;
fdf9b3e8
FB
1185 return;
1186 case 0x8f00: /* bf/s label */
1187 CHECK_NOT_DELAY_SLOT
1000822b 1188 gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 0);
fdf9b3e8
FB
1189 ctx->flags |= DELAY_SLOT_CONDITIONAL;
1190 return;
1191 case 0x8900: /* bt label */
1192 CHECK_NOT_DELAY_SLOT
1193 gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2,
1194 ctx->pc + 2);
823029f9 1195 ctx->bstate = BS_BRANCH;
fdf9b3e8
FB
1196 return;
1197 case 0x8d00: /* bt/s label */
1198 CHECK_NOT_DELAY_SLOT
1000822b 1199 gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 1);
fdf9b3e8
FB
1200 ctx->flags |= DELAY_SLOT_CONDITIONAL;
1201 return;
1202 case 0x8800: /* cmp/eq #imm,R0 */
7efbe241 1203 gen_cmp_imm(TCG_COND_EQ, REG(0), B7_0s);
fdf9b3e8
FB
1204 return;
1205 case 0xc400: /* mov.b @(disp,GBR),R0 */
c55497ec
AJ
1206 {
1207 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1208 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1209 tcg_gen_qemu_ld8s(REG(0), addr, ctx->memidx);
1210 tcg_temp_free(addr);
1211 }
fdf9b3e8
FB
1212 return;
1213 case 0xc500: /* mov.w @(disp,GBR),R0 */
c55497ec
AJ
1214 {
1215 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1216 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1217 tcg_gen_qemu_ld16s(REG(0), addr, ctx->memidx);
1218 tcg_temp_free(addr);
1219 }
fdf9b3e8
FB
1220 return;
1221 case 0xc600: /* mov.l @(disp,GBR),R0 */
c55497ec
AJ
1222 {
1223 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1224 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1225 tcg_gen_qemu_ld32s(REG(0), addr, ctx->memidx);
1226 tcg_temp_free(addr);
1227 }
fdf9b3e8
FB
1228 return;
1229 case 0xc000: /* mov.b R0,@(disp,GBR) */
c55497ec
AJ
1230 {
1231 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1232 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1233 tcg_gen_qemu_st8(REG(0), addr, ctx->memidx);
1234 tcg_temp_free(addr);
1235 }
fdf9b3e8
FB
1236 return;
1237 case 0xc100: /* mov.w R0,@(disp,GBR) */
c55497ec
AJ
1238 {
1239 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1240 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1241 tcg_gen_qemu_st16(REG(0), addr, ctx->memidx);
1242 tcg_temp_free(addr);
1243 }
fdf9b3e8
FB
1244 return;
1245 case 0xc200: /* mov.l R0,@(disp,GBR) */
c55497ec
AJ
1246 {
1247 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1248 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1249 tcg_gen_qemu_st32(REG(0), addr, ctx->memidx);
1250 tcg_temp_free(addr);
1251 }
fdf9b3e8
FB
1252 return;
1253 case 0x8000: /* mov.b R0,@(disp,Rn) */
c55497ec
AJ
1254 {
1255 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1256 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1257 tcg_gen_qemu_st8(REG(0), addr, ctx->memidx);
1258 tcg_temp_free(addr);
1259 }
fdf9b3e8
FB
1260 return;
1261 case 0x8100: /* mov.w R0,@(disp,Rn) */
c55497ec
AJ
1262 {
1263 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1264 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1265 tcg_gen_qemu_st16(REG(0), addr, ctx->memidx);
1266 tcg_temp_free(addr);
1267 }
fdf9b3e8
FB
1268 return;
1269 case 0x8400: /* mov.b @(disp,Rn),R0 */
c55497ec
AJ
1270 {
1271 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1272 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1273 tcg_gen_qemu_ld8s(REG(0), addr, ctx->memidx);
1274 tcg_temp_free(addr);
1275 }
fdf9b3e8
FB
1276 return;
1277 case 0x8500: /* mov.w @(disp,Rn),R0 */
c55497ec
AJ
1278 {
1279 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1280 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1281 tcg_gen_qemu_ld16s(REG(0), addr, ctx->memidx);
1282 tcg_temp_free(addr);
1283 }
fdf9b3e8
FB
1284 return;
1285 case 0xc700: /* mova @(disp,PC),R0 */
7efbe241 1286 tcg_gen_movi_i32(REG(0), ((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3);
fdf9b3e8
FB
1287 return;
1288 case 0xcb00: /* or #imm,R0 */
7efbe241 1289 tcg_gen_ori_i32(REG(0), REG(0), B7_0);
fdf9b3e8 1290 return;
24988dc2 1291 case 0xcf00: /* or.b #imm,@(R0,GBR) */
c55497ec
AJ
1292 {
1293 TCGv addr, val;
1294 addr = tcg_temp_new(TCG_TYPE_I32);
1295 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1296 val = tcg_temp_new(TCG_TYPE_I32);
1297 tcg_gen_qemu_ld8u(val, addr, ctx->memidx);
1298 tcg_gen_ori_i32(val, val, B7_0);
1299 tcg_gen_qemu_st8(val, addr, ctx->memidx);
1300 tcg_temp_free(val);
1301 tcg_temp_free(addr);
1302 }
fdf9b3e8
FB
1303 return;
1304 case 0xc300: /* trapa #imm */
c55497ec
AJ
1305 {
1306 TCGv imm;
1307 CHECK_NOT_DELAY_SLOT
1308 tcg_gen_movi_i32(cpu_pc, ctx->pc);
1309 imm = tcg_const_i32(B7_0);
1310 tcg_gen_helper_0_1(helper_trapa, imm);
1311 tcg_temp_free(imm);
1312 ctx->bstate = BS_BRANCH;
1313 }
fdf9b3e8
FB
1314 return;
1315 case 0xc800: /* tst #imm,R0 */
c55497ec
AJ
1316 {
1317 TCGv val = tcg_temp_new(TCG_TYPE_I32);
1318 tcg_gen_andi_i32(val, REG(0), B7_0);
1319 gen_cmp_imm(TCG_COND_EQ, val, 0);
1320 tcg_temp_free(val);
1321 }
fdf9b3e8 1322 return;
24988dc2 1323 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
c55497ec
AJ
1324 {
1325 TCGv val = tcg_temp_new(TCG_TYPE_I32);
1326 tcg_gen_add_i32(val, REG(0), cpu_gbr);
1327 tcg_gen_qemu_ld8u(val, val, ctx->memidx);
1328 tcg_gen_andi_i32(val, val, B7_0);
1329 gen_cmp_imm(TCG_COND_EQ, val, 0);
1330 tcg_temp_free(val);
1331 }
fdf9b3e8
FB
1332 return;
1333 case 0xca00: /* xor #imm,R0 */
7efbe241 1334 tcg_gen_xori_i32(REG(0), REG(0), B7_0);
fdf9b3e8 1335 return;
24988dc2 1336 case 0xce00: /* xor.b #imm,@(R0,GBR) */
c55497ec
AJ
1337 {
1338 TCGv addr, val;
1339 addr = tcg_temp_new(TCG_TYPE_I32);
1340 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1341 val = tcg_temp_new(TCG_TYPE_I32);
1342 tcg_gen_qemu_ld8u(val, addr, ctx->memidx);
1343 tcg_gen_xori_i32(val, val, B7_0);
1344 tcg_gen_qemu_st8(val, addr, ctx->memidx);
1345 tcg_temp_free(val);
1346 tcg_temp_free(addr);
1347 }
fdf9b3e8
FB
1348 return;
1349 }
1350
1351 switch (ctx->opcode & 0xf08f) {
1352 case 0x408e: /* ldc Rm,Rn_BANK */
7efbe241 1353 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8));
fdf9b3e8
FB
1354 return;
1355 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
7efbe241
AJ
1356 tcg_gen_qemu_ld32s(ALTREG(B6_4), REG(B11_8), ctx->memidx);
1357 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
fdf9b3e8
FB
1358 return;
1359 case 0x0082: /* stc Rm_BANK,Rn */
7efbe241 1360 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4));
fdf9b3e8
FB
1361 return;
1362 case 0x4083: /* stc.l Rm_BANK,@-Rn */
c55497ec
AJ
1363 {
1364 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1365 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1366 tcg_gen_qemu_st32(ALTREG(B6_4), addr, ctx->memidx);
1367 tcg_temp_free(addr);
1368 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
1369 }
fdf9b3e8
FB
1370 return;
1371 }
1372
1373 switch (ctx->opcode & 0xf0ff) {
1374 case 0x0023: /* braf Rn */
7efbe241
AJ
1375 CHECK_NOT_DELAY_SLOT
1376 tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->pc + 4);
fdf9b3e8
FB
1377 ctx->flags |= DELAY_SLOT;
1378 ctx->delayed_pc = (uint32_t) - 1;
1379 return;
1380 case 0x0003: /* bsrf Rn */
7efbe241 1381 CHECK_NOT_DELAY_SLOT
1000822b 1382 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
7efbe241 1383 tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
fdf9b3e8
FB
1384 ctx->flags |= DELAY_SLOT;
1385 ctx->delayed_pc = (uint32_t) - 1;
1386 return;
1387 case 0x4015: /* cmp/pl Rn */
7efbe241 1388 gen_cmp_imm(TCG_COND_GT, REG(B11_8), 0);
fdf9b3e8
FB
1389 return;
1390 case 0x4011: /* cmp/pz Rn */
7efbe241 1391 gen_cmp_imm(TCG_COND_GE, REG(B11_8), 0);
fdf9b3e8
FB
1392 return;
1393 case 0x4010: /* dt Rn */
7efbe241
AJ
1394 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1);
1395 gen_cmp_imm(TCG_COND_EQ, REG(B11_8), 0);
fdf9b3e8
FB
1396 return;
1397 case 0x402b: /* jmp @Rn */
7efbe241
AJ
1398 CHECK_NOT_DELAY_SLOT
1399 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
fdf9b3e8
FB
1400 ctx->flags |= DELAY_SLOT;
1401 ctx->delayed_pc = (uint32_t) - 1;
1402 return;
1403 case 0x400b: /* jsr @Rn */
7efbe241 1404 CHECK_NOT_DELAY_SLOT
1000822b 1405 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
7efbe241 1406 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
fdf9b3e8
FB
1407 ctx->flags |= DELAY_SLOT;
1408 ctx->delayed_pc = (uint32_t) - 1;
1409 return;
390af821 1410 case 0x400e: /* lds Rm,SR */
7efbe241 1411 tcg_gen_andi_i32(cpu_sr, REG(B11_8), 0x700083f3);
390af821
AJ
1412 ctx->bstate = BS_STOP;
1413 return;
1414 case 0x4007: /* lds.l @Rm+,SR */
c55497ec
AJ
1415 {
1416 TCGv val = tcg_temp_new(TCG_TYPE_I32);
1417 tcg_gen_qemu_ld32s(val, REG(B11_8), ctx->memidx);
1418 tcg_gen_andi_i32(cpu_sr, val, 0x700083f3);
1419 tcg_temp_free(val);
1420 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1421 ctx->bstate = BS_STOP;
1422 }
390af821
AJ
1423 return;
1424 case 0x0002: /* sts SR,Rn */
7efbe241 1425 tcg_gen_mov_i32(REG(B11_8), cpu_sr);
390af821
AJ
1426 return;
1427 case 0x4003: /* sts SR,@-Rn */
c55497ec
AJ
1428 {
1429 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1430 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1431 tcg_gen_qemu_st32(cpu_sr, addr, ctx->memidx);
1432 tcg_temp_free(addr);
1433 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
1434 }
390af821
AJ
1435 return;
1436#define LDST(reg,ldnum,ldpnum,stnum,stpnum) \
fdf9b3e8 1437 case ldnum: \
7efbe241 1438 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \
fdf9b3e8
FB
1439 return; \
1440 case ldpnum: \
7efbe241
AJ
1441 tcg_gen_qemu_ld32s (cpu_##reg, REG(B11_8), ctx->memidx); \
1442 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \
fdf9b3e8
FB
1443 return; \
1444 case stnum: \
7efbe241 1445 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \
fdf9b3e8
FB
1446 return; \
1447 case stpnum: \
c55497ec
AJ
1448 { \
1449 TCGv addr = tcg_temp_new(TCG_TYPE_I32); \
1450 tcg_gen_subi_i32(addr, REG(B11_8), 4); \
1451 tcg_gen_qemu_st32 (cpu_##reg, addr, ctx->memidx); \
1452 tcg_temp_free(addr); \
1453 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4); \
86e0abc7 1454 } \
fdf9b3e8 1455 return;
390af821
AJ
1456 LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013)
1457 LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023)
1458 LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033)
1459 LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043)
1460 LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2)
1461 LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002)
1462 LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012)
1463 LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022)
1464 LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052)
1465 case 0x406a: /* lds Rm,FPSCR */
7efbe241 1466 tcg_gen_helper_0_1(helper_ld_fpscr, REG(B11_8));
390af821
AJ
1467 ctx->bstate = BS_STOP;
1468 return;
1469 case 0x4066: /* lds.l @Rm+,FPSCR */
c55497ec
AJ
1470 {
1471 TCGv addr = tcg_temp_new(TCG_TYPE_I32);
1472 tcg_gen_qemu_ld32s(addr, REG(B11_8), ctx->memidx);
1473 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1474 tcg_gen_helper_0_1(helper_ld_fpscr, addr);
1475 tcg_temp_free(addr);
1476 ctx->bstate = BS_STOP;
1477 }
390af821
AJ
1478 return;
1479 case 0x006a: /* sts FPSCR,Rn */
c55497ec 1480 tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff);
390af821
AJ
1481 return;
1482 case 0x4062: /* sts FPSCR,@-Rn */
c55497ec
AJ
1483 {
1484 TCGv addr, val;
1485 val = tcg_temp_new(TCG_TYPE_I32);
1486 tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff);
1487 addr = tcg_temp_new(TCG_TYPE_I32);
1488 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1489 tcg_gen_qemu_st32(val, addr, ctx->memidx);
1490 tcg_temp_free(addr);
1491 tcg_temp_free(val);
1492 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4);
1493 }
390af821 1494 return;
fdf9b3e8 1495 case 0x00c3: /* movca.l R0,@Rm */
7efbe241 1496 tcg_gen_qemu_st32(REG(0), REG(B11_8), ctx->memidx);
fdf9b3e8
FB
1497 return;
1498 case 0x0029: /* movt Rn */
7efbe241 1499 tcg_gen_andi_i32(REG(B11_8), cpu_sr, SR_T);
fdf9b3e8
FB
1500 return;
1501 case 0x0093: /* ocbi @Rn */
c55497ec
AJ
1502 {
1503 TCGv dummy = tcg_temp_new(TCG_TYPE_I32);
1504 tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx);
1505 tcg_temp_free(dummy);
1506 }
fdf9b3e8 1507 return;
24988dc2 1508 case 0x00a3: /* ocbp @Rn */
c55497ec
AJ
1509 {
1510 TCGv dummy = tcg_temp_new(TCG_TYPE_I32);
1511 tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx);
1512 tcg_temp_free(dummy);
1513 }
fdf9b3e8
FB
1514 return;
1515 case 0x00b3: /* ocbwb @Rn */
c55497ec
AJ
1516 {
1517 TCGv dummy = tcg_temp_new(TCG_TYPE_I32);
1518 tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx);
1519 tcg_temp_free(dummy);
1520 }
fdf9b3e8
FB
1521 return;
1522 case 0x0083: /* pref @Rn */
1523 return;
1524 case 0x4024: /* rotcl Rn */
c55497ec
AJ
1525 {
1526 TCGv tmp = tcg_temp_new(TCG_TYPE_I32);
1527 tcg_gen_mov_i32(tmp, cpu_sr);
1528 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 31);
1529 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1530 gen_copy_bit_i32(REG(B11_8), 0, tmp, 0);
1531 tcg_temp_free(tmp);
1532 }
fdf9b3e8
FB
1533 return;
1534 case 0x4025: /* rotcr Rn */
c55497ec
AJ
1535 {
1536 TCGv tmp = tcg_temp_new(TCG_TYPE_I32);
1537 tcg_gen_mov_i32(tmp, cpu_sr);
1538 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
1539 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1540 gen_copy_bit_i32(REG(B11_8), 31, tmp, 0);
1541 tcg_temp_free(tmp);
1542 }
fdf9b3e8
FB
1543 return;
1544 case 0x4004: /* rotl Rn */
7efbe241
AJ
1545 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 31);
1546 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1547 gen_copy_bit_i32(REG(B11_8), 0, cpu_sr, 0);
fdf9b3e8
FB
1548 return;
1549 case 0x4005: /* rotr Rn */
7efbe241
AJ
1550 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
1551 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1552 gen_copy_bit_i32(REG(B11_8), 31, cpu_sr, 0);
fdf9b3e8
FB
1553 return;
1554 case 0x4000: /* shll Rn */
1555 case 0x4020: /* shal Rn */
7efbe241
AJ
1556 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 31);
1557 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
fdf9b3e8
FB
1558 return;
1559 case 0x4021: /* shar Rn */
7efbe241
AJ
1560 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
1561 tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1);
fdf9b3e8
FB
1562 return;
1563 case 0x4001: /* shlr Rn */
7efbe241
AJ
1564 gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
1565 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
fdf9b3e8
FB
1566 return;
1567 case 0x4008: /* shll2 Rn */
7efbe241 1568 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2);
fdf9b3e8
FB
1569 return;
1570 case 0x4018: /* shll8 Rn */
7efbe241 1571 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8);
fdf9b3e8
FB
1572 return;
1573 case 0x4028: /* shll16 Rn */
7efbe241 1574 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16);
fdf9b3e8
FB
1575 return;
1576 case 0x4009: /* shlr2 Rn */
7efbe241 1577 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2);
fdf9b3e8
FB
1578 return;
1579 case 0x4019: /* shlr8 Rn */
7efbe241 1580 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8);
fdf9b3e8
FB
1581 return;
1582 case 0x4029: /* shlr16 Rn */
7efbe241 1583 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16);
fdf9b3e8
FB
1584 return;
1585 case 0x401b: /* tas.b @Rn */
c55497ec
AJ
1586 {
1587 TCGv addr, val;
1588 addr = tcg_temp_local_new(TCG_TYPE_I32);
1589 tcg_gen_mov_i32(addr, REG(B11_8));
1590 val = tcg_temp_local_new(TCG_TYPE_I32);
1591 tcg_gen_qemu_ld8u(val, addr, ctx->memidx);
1592 gen_cmp_imm(TCG_COND_EQ, val, 0);
1593 tcg_gen_ori_i32(val, val, 0x80);
1594 tcg_gen_qemu_st8(val, addr, ctx->memidx);
1595 tcg_temp_free(val);
1596 tcg_temp_free(addr);
1597 }
fdf9b3e8 1598 return;
e67888a7 1599 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
cc4ba6a9
AJ
1600 {
1601 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
1602 tcg_gen_mov_i32(fp, cpu_fpul);
1603 gen_store_fpr32(fp, FREG(B11_8));
1604 tcg_temp_free(fp);
1605 }
eda9b09b 1606 return;
e67888a7 1607 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
cc4ba6a9
AJ
1608 {
1609 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
1610 gen_load_fpr32(fp, FREG(B11_8));
1611 tcg_gen_mov_i32(cpu_fpul, fp);
1612 tcg_temp_free(fp);
1613 }
eda9b09b 1614 return;
e67888a7 1615 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
ea6cf6be 1616 if (ctx->fpscr & FPSCR_PR) {
cc4ba6a9 1617 TCGv fp;
ea6cf6be
TS
1618 if (ctx->opcode & 0x0100)
1619 break; /* illegal instruction */
cc4ba6a9
AJ
1620 fp = tcg_temp_new(TCG_TYPE_I64);
1621 tcg_gen_helper_1_1(helper_float_DT, fp, cpu_fpul);
1622 gen_store_fpr64(fp, DREG(B11_8));
1623 tcg_temp_free(fp);
ea6cf6be
TS
1624 }
1625 else {
cc4ba6a9
AJ
1626 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
1627 tcg_gen_helper_1_1(helper_float_FT, fp, cpu_fpul);
1628 gen_store_fpr32(fp, FREG(B11_8));
1629 tcg_temp_free(fp);
ea6cf6be
TS
1630 }
1631 return;
e67888a7 1632 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
ea6cf6be 1633 if (ctx->fpscr & FPSCR_PR) {
cc4ba6a9 1634 TCGv fp;
ea6cf6be
TS
1635 if (ctx->opcode & 0x0100)
1636 break; /* illegal instruction */
cc4ba6a9
AJ
1637 fp = tcg_temp_new(TCG_TYPE_I64);
1638 gen_load_fpr64(fp, DREG(B11_8));
1639 tcg_gen_helper_1_1(helper_ftrc_DT, cpu_fpul, fp);
1640 tcg_temp_free(fp);
ea6cf6be
TS
1641 }
1642 else {
cc4ba6a9
AJ
1643 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
1644 gen_load_fpr32(fp, FREG(B11_8));
1645 tcg_gen_helper_1_1(helper_ftrc_FT, cpu_fpul, fp);
1646 tcg_temp_free(fp);
ea6cf6be
TS
1647 }
1648 return;
24988dc2 1649 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
7fdf924f
AJ
1650 {
1651 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
1652 gen_load_fpr32(fp, FREG(B11_8));
1653 tcg_gen_helper_1_1(helper_fneg_T, fp, fp);
1654 gen_store_fpr32(fp, FREG(B11_8));
1655 tcg_temp_free(fp);
1656 }
24988dc2
AJ
1657 return;
1658 case 0xf05d: /* fabs FRn/DRn */
1659 if (ctx->fpscr & FPSCR_PR) {
1660 if (ctx->opcode & 0x0100)
1661 break; /* illegal instruction */
cc4ba6a9
AJ
1662 TCGv fp = tcg_temp_new(TCG_TYPE_I64);
1663 gen_load_fpr64(fp, DREG(B11_8));
1664 tcg_gen_helper_1_1(helper_fabs_DT, fp, fp);
1665 gen_store_fpr64(fp, DREG(B11_8));
1666 tcg_temp_free(fp);
24988dc2 1667 } else {
cc4ba6a9
AJ
1668 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
1669 gen_load_fpr32(fp, FREG(B11_8));
1670 tcg_gen_helper_1_1(helper_fabs_FT, fp, fp);
1671 gen_store_fpr32(fp, FREG(B11_8));
1672 tcg_temp_free(fp);
24988dc2
AJ
1673 }
1674 return;
1675 case 0xf06d: /* fsqrt FRn */
1676 if (ctx->fpscr & FPSCR_PR) {
1677 if (ctx->opcode & 0x0100)
1678 break; /* illegal instruction */
cc4ba6a9
AJ
1679 TCGv fp = tcg_temp_new(TCG_TYPE_I64);
1680 gen_load_fpr64(fp, DREG(B11_8));
1681 tcg_gen_helper_1_1(helper_fsqrt_DT, fp, fp);
1682 gen_store_fpr64(fp, DREG(B11_8));
1683 tcg_temp_free(fp);
24988dc2 1684 } else {
cc4ba6a9
AJ
1685 TCGv fp = tcg_temp_new(TCG_TYPE_I32);
1686 gen_load_fpr32(fp, FREG(B11_8));
1687 tcg_gen_helper_1_1(helper_fsqrt_FT, fp, fp);
1688 gen_store_fpr32(fp, FREG(B11_8));
1689 tcg_temp_free(fp);
24988dc2
AJ
1690 }
1691 return;
1692 case 0xf07d: /* fsrra FRn */
1693 break;
e67888a7 1694 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
ea6cf6be 1695 if (!(ctx->fpscr & FPSCR_PR)) {
cc4ba6a9
AJ
1696 TCGv val = tcg_const_i32(0);
1697 gen_load_fpr32(val, FREG(B11_8));
1698 tcg_temp_free(val);
ea6cf6be
TS
1699 return;
1700 }
1701 break;
e67888a7 1702 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
ea6cf6be 1703 if (!(ctx->fpscr & FPSCR_PR)) {
cc4ba6a9
AJ
1704 TCGv val = tcg_const_i32(0x3f800000);
1705 gen_load_fpr32(val, FREG(B11_8));
1706 tcg_temp_free(val);
ea6cf6be
TS
1707 return;
1708 }
1709 break;
24988dc2 1710 case 0xf0ad: /* fcnvsd FPUL,DRn */
cc4ba6a9
AJ
1711 {
1712 TCGv fp = tcg_temp_new(TCG_TYPE_I64);
1713 tcg_gen_helper_1_1(helper_fcnvsd_FT_DT, fp, cpu_fpul);
1714 gen_store_fpr64(fp, DREG(B11_8));
1715 tcg_temp_free(fp);
1716 }
24988dc2
AJ
1717 return;
1718 case 0xf0bd: /* fcnvds DRn,FPUL */
cc4ba6a9
AJ
1719 {
1720 TCGv fp = tcg_temp_new(TCG_TYPE_I64);
1721 gen_load_fpr64(fp, DREG(B11_8));
1722 tcg_gen_helper_1_1(helper_fcnvds_DT_FT, cpu_fpul, fp);
1723 tcg_temp_free(fp);
1724 }
24988dc2 1725 return;
fdf9b3e8
FB
1726 }
1727
1728 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1729 ctx->opcode, ctx->pc);
e6afc2f4 1730 tcg_gen_helper_0_0(helper_raise_illegal_instruction);
823029f9
TS
1731 ctx->bstate = BS_EXCP;
1732}
1733
1734void decode_opc(DisasContext * ctx)
1735{
1736 uint32_t old_flags = ctx->flags;
1737
1738 _decode_opc(ctx);
1739
1740 if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
1741 if (ctx->flags & DELAY_SLOT_CLEARME) {
1000822b 1742 gen_store_flags(0);
274a9e70
AJ
1743 } else {
1744 /* go out of the delay slot */
1745 uint32_t new_flags = ctx->flags;
1746 new_flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
1000822b 1747 gen_store_flags(new_flags);
823029f9
TS
1748 }
1749 ctx->flags = 0;
1750 ctx->bstate = BS_BRANCH;
1751 if (old_flags & DELAY_SLOT_CONDITIONAL) {
1752 gen_delayed_conditional_jump(ctx);
1753 } else if (old_flags & DELAY_SLOT) {
1754 gen_jump(ctx);
1755 }
1756
1757 }
274a9e70
AJ
1758
1759 /* go into a delay slot */
1760 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL))
1000822b 1761 gen_store_flags(ctx->flags);
fdf9b3e8
FB
1762}
1763
2cfc5f17 1764static inline void
820e00f2
TS
1765gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
1766 int search_pc)
fdf9b3e8
FB
1767{
1768 DisasContext ctx;
1769 target_ulong pc_start;
1770 static uint16_t *gen_opc_end;
355fb23d 1771 int i, ii;
2e70f6ef
PB
1772 int num_insns;
1773 int max_insns;
fdf9b3e8
FB
1774
1775 pc_start = tb->pc;
fdf9b3e8 1776 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
fdf9b3e8 1777 ctx.pc = pc_start;
823029f9
TS
1778 ctx.flags = (uint32_t)tb->flags;
1779 ctx.bstate = BS_NONE;
fdf9b3e8 1780 ctx.sr = env->sr;
eda9b09b 1781 ctx.fpscr = env->fpscr;
fdf9b3e8 1782 ctx.memidx = (env->sr & SR_MD) ? 1 : 0;
9854bc46
PB
1783 /* We don't know if the delayed pc came from a dynamic or static branch,
1784 so assume it is a dynamic branch. */
823029f9 1785 ctx.delayed_pc = -1; /* use delayed pc from env pointer */
fdf9b3e8
FB
1786 ctx.tb = tb;
1787 ctx.singlestep_enabled = env->singlestep_enabled;
fdf9b3e8
FB
1788
1789#ifdef DEBUG_DISAS
1790 if (loglevel & CPU_LOG_TB_CPU) {
1791 fprintf(logfile,
1792 "------------------------------------------------\n");
1793 cpu_dump_state(env, logfile, fprintf, 0);
1794 }
1795#endif
1796
355fb23d 1797 ii = -1;
2e70f6ef
PB
1798 num_insns = 0;
1799 max_insns = tb->cflags & CF_COUNT_MASK;
1800 if (max_insns == 0)
1801 max_insns = CF_COUNT_MASK;
1802 gen_icount_start();
823029f9 1803 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
fdf9b3e8
FB
1804 if (env->nb_breakpoints > 0) {
1805 for (i = 0; i < env->nb_breakpoints; i++) {
1806 if (ctx.pc == env->breakpoints[i]) {
1807 /* We have hit a breakpoint - make sure PC is up-to-date */
3a8a44c4 1808 tcg_gen_movi_i32(cpu_pc, ctx.pc);
e6afc2f4 1809 tcg_gen_helper_0_0(helper_debug);
823029f9 1810 ctx.bstate = BS_EXCP;
fdf9b3e8
FB
1811 break;
1812 }
1813 }
1814 }
355fb23d
PB
1815 if (search_pc) {
1816 i = gen_opc_ptr - gen_opc_buf;
1817 if (ii < i) {
1818 ii++;
1819 while (ii < i)
1820 gen_opc_instr_start[ii++] = 0;
1821 }
1822 gen_opc_pc[ii] = ctx.pc;
823029f9 1823 gen_opc_hflags[ii] = ctx.flags;
355fb23d 1824 gen_opc_instr_start[ii] = 1;
2e70f6ef 1825 gen_opc_icount[ii] = num_insns;
355fb23d 1826 }
2e70f6ef
PB
1827 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
1828 gen_io_start();
fdf9b3e8
FB
1829#if 0
1830 fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
1831 fflush(stderr);
1832#endif
1833 ctx.opcode = lduw_code(ctx.pc);
1834 decode_opc(&ctx);
2e70f6ef 1835 num_insns++;
fdf9b3e8
FB
1836 ctx.pc += 2;
1837 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1838 break;
1839 if (env->singlestep_enabled)
1840 break;
2e70f6ef
PB
1841 if (num_insns >= max_insns)
1842 break;
fdf9b3e8
FB
1843#ifdef SH4_SINGLE_STEP
1844 break;
1845#endif
1846 }
2e70f6ef
PB
1847 if (tb->cflags & CF_LAST_IO)
1848 gen_io_end();
fdf9b3e8 1849 if (env->singlestep_enabled) {
e6afc2f4 1850 tcg_gen_helper_0_0(helper_debug);
823029f9
TS
1851 } else {
1852 switch (ctx.bstate) {
1853 case BS_STOP:
1854 /* gen_op_interrupt_restart(); */
1855 /* fall through */
1856 case BS_NONE:
1857 if (ctx.flags) {
1000822b 1858 gen_store_flags(ctx.flags | DELAY_SLOT_CLEARME);
823029f9
TS
1859 }
1860 gen_goto_tb(&ctx, 0, ctx.pc);
1861 break;
1862 case BS_EXCP:
1863 /* gen_op_interrupt_restart(); */
57fec1fe 1864 tcg_gen_exit_tb(0);
823029f9
TS
1865 break;
1866 case BS_BRANCH:
1867 default:
1868 break;
1869 }
fdf9b3e8 1870 }
823029f9 1871
2e70f6ef 1872 gen_icount_end(tb, num_insns);
fdf9b3e8 1873 *gen_opc_ptr = INDEX_op_end;
355fb23d
PB
1874 if (search_pc) {
1875 i = gen_opc_ptr - gen_opc_buf;
1876 ii++;
1877 while (ii <= i)
1878 gen_opc_instr_start[ii++] = 0;
355fb23d
PB
1879 } else {
1880 tb->size = ctx.pc - pc_start;
2e70f6ef 1881 tb->icount = num_insns;
355fb23d 1882 }
fdf9b3e8
FB
1883
1884#ifdef DEBUG_DISAS
1885#ifdef SH4_DEBUG_DISAS
1886 if (loglevel & CPU_LOG_TB_IN_ASM)
1887 fprintf(logfile, "\n");
1888#endif
1889 if (loglevel & CPU_LOG_TB_IN_ASM) {
1890 fprintf(logfile, "IN:\n"); /* , lookup_symbol(pc_start)); */
1891 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1892 fprintf(logfile, "\n");
1893 }
fdf9b3e8 1894#endif
fdf9b3e8
FB
1895}
1896
2cfc5f17 1897void gen_intermediate_code(CPUState * env, struct TranslationBlock *tb)
fdf9b3e8 1898{
2cfc5f17 1899 gen_intermediate_code_internal(env, tb, 0);
fdf9b3e8
FB
1900}
1901
2cfc5f17 1902void gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
fdf9b3e8 1903{
2cfc5f17 1904 gen_intermediate_code_internal(env, tb, 1);
fdf9b3e8 1905}
d2856f1a
AJ
1906
1907void gen_pc_load(CPUState *env, TranslationBlock *tb,
1908 unsigned long searched_pc, int pc_pos, void *puc)
1909{
1910 env->pc = gen_opc_pc[pc_pos];
1911 env->flags = gen_opc_hflags[pc_pos];
1912}