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