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