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