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