]> git.proxmox.com Git - mirror_qemu.git/blame - target-sh4/translate.c
target-sh4: improve cmp/str 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();
eb6ca2b4
AJ
691 tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8));
692 tcg_gen_subi_i32(cmp1, cmp2, 0x01010101);
693 tcg_gen_andc_i32(cmp1, cmp1, cmp2);
694 tcg_gen_andi_i32(cmp1, cmp1, 0x80808080);
695 tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0);
c55497ec
AJ
696 tcg_temp_free(cmp2);
697 tcg_temp_free(cmp1);
69d6275b 698 }
fdf9b3e8
FB
699 return;
700 case 0x2007: /* div0s Rm,Rn */
1d565b21
AJ
701 tcg_gen_shri_i32(cpu_sr_q, REG(B11_8), 31); /* SR_Q */
702 tcg_gen_shri_i32(cpu_sr_m, REG(B7_4), 31); /* SR_M */
703 tcg_gen_xor_i32(cpu_sr_t, cpu_sr_q, cpu_sr_m); /* SR_T */
fdf9b3e8
FB
704 return;
705 case 0x3004: /* div1 Rm,Rn */
1d565b21
AJ
706 {
707 TCGv t0 = tcg_temp_new();
708 TCGv t1 = tcg_temp_new();
709 TCGv t2 = tcg_temp_new();
710 TCGv zero = tcg_const_i32(0);
711
712 /* shift left arg1, saving the bit being pushed out and inserting
713 T on the right */
714 tcg_gen_shri_i32(t0, REG(B11_8), 31);
715 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
716 tcg_gen_or_i32(REG(B11_8), REG(B11_8), cpu_sr_t);
717
718 /* Add or subtract arg0 from arg1 depending if Q == M. To avoid
719 using 64-bit temps, we compute arg0's high part from q ^ m, so
720 that it is 0x00000000 when adding the value or 0xffffffff when
721 subtracting it. */
722 tcg_gen_xor_i32(t1, cpu_sr_q, cpu_sr_m);
723 tcg_gen_subi_i32(t1, t1, 1);
724 tcg_gen_neg_i32(t2, REG(B7_4));
725 tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, zero, REG(B7_4), t2);
726 tcg_gen_add2_i32(REG(B11_8), t1, REG(B11_8), zero, t2, t1);
727
728 /* compute T and Q depending on carry */
729 tcg_gen_andi_i32(t1, t1, 1);
730 tcg_gen_xor_i32(t1, t1, t0);
731 tcg_gen_xori_i32(cpu_sr_t, t1, 1);
732 tcg_gen_xor_i32(cpu_sr_q, cpu_sr_m, t1);
733
734 tcg_temp_free(zero);
735 tcg_temp_free(t2);
736 tcg_temp_free(t1);
737 tcg_temp_free(t0);
738 }
fdf9b3e8
FB
739 return;
740 case 0x300d: /* dmuls.l Rm,Rn */
1d3b7084 741 tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
fdf9b3e8
FB
742 return;
743 case 0x3005: /* dmulu.l Rm,Rn */
1d3b7084 744 tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
fdf9b3e8
FB
745 return;
746 case 0x600e: /* exts.b Rm,Rn */
7efbe241 747 tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
748 return;
749 case 0x600f: /* exts.w Rm,Rn */
7efbe241 750 tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
751 return;
752 case 0x600c: /* extu.b Rm,Rn */
7efbe241 753 tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
754 return;
755 case 0x600d: /* extu.w Rm,Rn */
7efbe241 756 tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4));
fdf9b3e8 757 return;
24988dc2 758 case 0x000f: /* mac.l @Rm+,@Rn+ */
c55497ec
AJ
759 {
760 TCGv arg0, arg1;
a7812ae4 761 arg0 = tcg_temp_new();
3376f415 762 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL);
a7812ae4 763 arg1 = tcg_temp_new();
3376f415 764 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL);
485d0035 765 gen_helper_macl(cpu_env, arg0, arg1);
c55497ec
AJ
766 tcg_temp_free(arg1);
767 tcg_temp_free(arg0);
768 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
769 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
770 }
fdf9b3e8
FB
771 return;
772 case 0x400f: /* mac.w @Rm+,@Rn+ */
c55497ec
AJ
773 {
774 TCGv arg0, arg1;
a7812ae4 775 arg0 = tcg_temp_new();
3376f415 776 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL);
a7812ae4 777 arg1 = tcg_temp_new();
3376f415 778 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL);
485d0035 779 gen_helper_macw(cpu_env, arg0, arg1);
c55497ec
AJ
780 tcg_temp_free(arg1);
781 tcg_temp_free(arg0);
782 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2);
783 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
784 }
fdf9b3e8
FB
785 return;
786 case 0x0007: /* mul.l Rm,Rn */
7efbe241 787 tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8));
fdf9b3e8
FB
788 return;
789 case 0x200f: /* muls.w Rm,Rn */
c55497ec
AJ
790 {
791 TCGv arg0, arg1;
a7812ae4 792 arg0 = tcg_temp_new();
c55497ec 793 tcg_gen_ext16s_i32(arg0, REG(B7_4));
a7812ae4 794 arg1 = tcg_temp_new();
c55497ec
AJ
795 tcg_gen_ext16s_i32(arg1, REG(B11_8));
796 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
797 tcg_temp_free(arg1);
798 tcg_temp_free(arg0);
799 }
fdf9b3e8
FB
800 return;
801 case 0x200e: /* mulu.w Rm,Rn */
c55497ec
AJ
802 {
803 TCGv arg0, arg1;
a7812ae4 804 arg0 = tcg_temp_new();
c55497ec 805 tcg_gen_ext16u_i32(arg0, REG(B7_4));
a7812ae4 806 arg1 = tcg_temp_new();
c55497ec
AJ
807 tcg_gen_ext16u_i32(arg1, REG(B11_8));
808 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
809 tcg_temp_free(arg1);
810 tcg_temp_free(arg0);
811 }
fdf9b3e8
FB
812 return;
813 case 0x600b: /* neg Rm,Rn */
7efbe241 814 tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
815 return;
816 case 0x600a: /* negc Rm,Rn */
b2d9eda5 817 {
60eb27fe
AJ
818 TCGv t0 = tcg_const_i32(0);
819 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t,
820 REG(B7_4), t0, cpu_sr_t, t0);
821 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
822 t0, t0, REG(B11_8), cpu_sr_t);
823 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
b2d9eda5 824 tcg_temp_free(t0);
b2d9eda5 825 }
fdf9b3e8
FB
826 return;
827 case 0x6007: /* not Rm,Rn */
7efbe241 828 tcg_gen_not_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
829 return;
830 case 0x200b: /* or Rm,Rn */
7efbe241 831 tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8
FB
832 return;
833 case 0x400c: /* shad Rm,Rn */
69d6275b 834 {
42a268c2
RH
835 TCGLabel *label1 = gen_new_label();
836 TCGLabel *label2 = gen_new_label();
837 TCGLabel *label3 = gen_new_label();
838 TCGLabel *label4 = gen_new_label();
3101e99c 839 TCGv shift;
7efbe241 840 tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
69d6275b 841 /* Rm positive, shift to the left */
3101e99c 842 shift = tcg_temp_new();
c55497ec
AJ
843 tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
844 tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
3101e99c 845 tcg_temp_free(shift);
69d6275b
AJ
846 tcg_gen_br(label4);
847 /* Rm negative, shift to the right */
848 gen_set_label(label1);
3101e99c 849 shift = tcg_temp_new();
c55497ec
AJ
850 tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
851 tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2);
852 tcg_gen_not_i32(shift, REG(B7_4));
853 tcg_gen_andi_i32(shift, shift, 0x1f);
854 tcg_gen_addi_i32(shift, shift, 1);
855 tcg_gen_sar_i32(REG(B11_8), REG(B11_8), shift);
3101e99c 856 tcg_temp_free(shift);
69d6275b
AJ
857 tcg_gen_br(label4);
858 /* Rm = -32 */
859 gen_set_label(label2);
7efbe241
AJ
860 tcg_gen_brcondi_i32(TCG_COND_LT, REG(B11_8), 0, label3);
861 tcg_gen_movi_i32(REG(B11_8), 0);
69d6275b
AJ
862 tcg_gen_br(label4);
863 gen_set_label(label3);
7efbe241 864 tcg_gen_movi_i32(REG(B11_8), 0xffffffff);
69d6275b
AJ
865 gen_set_label(label4);
866 }
fdf9b3e8
FB
867 return;
868 case 0x400d: /* shld Rm,Rn */
69d6275b 869 {
42a268c2
RH
870 TCGLabel *label1 = gen_new_label();
871 TCGLabel *label2 = gen_new_label();
872 TCGLabel *label3 = gen_new_label();
3101e99c 873 TCGv shift;
7efbe241 874 tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
69d6275b 875 /* Rm positive, shift to the left */
3101e99c 876 shift = tcg_temp_new();
c55497ec
AJ
877 tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
878 tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
3101e99c 879 tcg_temp_free(shift);
69d6275b
AJ
880 tcg_gen_br(label3);
881 /* Rm negative, shift to the right */
882 gen_set_label(label1);
3101e99c 883 shift = tcg_temp_new();
c55497ec
AJ
884 tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
885 tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2);
886 tcg_gen_not_i32(shift, REG(B7_4));
887 tcg_gen_andi_i32(shift, shift, 0x1f);
888 tcg_gen_addi_i32(shift, shift, 1);
889 tcg_gen_shr_i32(REG(B11_8), REG(B11_8), shift);
3101e99c 890 tcg_temp_free(shift);
69d6275b
AJ
891 tcg_gen_br(label3);
892 /* Rm = -32 */
893 gen_set_label(label2);
7efbe241 894 tcg_gen_movi_i32(REG(B11_8), 0);
69d6275b
AJ
895 gen_set_label(label3);
896 }
fdf9b3e8
FB
897 return;
898 case 0x3008: /* sub Rm,Rn */
7efbe241 899 tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8
FB
900 return;
901 case 0x300a: /* subc Rm,Rn */
22b88fd7 902 {
d0f44a55
AJ
903 TCGv t0, t1;
904 t0 = tcg_const_tl(0);
22b88fd7 905 t1 = tcg_temp_new();
d0f44a55
AJ
906 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0);
907 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
908 REG(B11_8), t0, t1, cpu_sr_t);
909 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
22b88fd7 910 tcg_temp_free(t0);
d0f44a55 911 tcg_temp_free(t1);
22b88fd7 912 }
fdf9b3e8
FB
913 return;
914 case 0x300b: /* subv Rm,Rn */
ad8d25a1
AJ
915 {
916 TCGv t0, t1, t2;
917 t0 = tcg_temp_new();
918 tcg_gen_sub_i32(t0, REG(B11_8), REG(B7_4));
919 t1 = tcg_temp_new();
920 tcg_gen_xor_i32(t1, t0, REG(B7_4));
921 t2 = tcg_temp_new();
922 tcg_gen_xor_i32(t2, REG(B11_8), REG(B7_4));
923 tcg_gen_and_i32(t1, t1, t2);
924 tcg_temp_free(t2);
34086945 925 tcg_gen_shri_i32(cpu_sr_t, t1, 31);
ad8d25a1
AJ
926 tcg_temp_free(t1);
927 tcg_gen_mov_i32(REG(B11_8), t0);
928 tcg_temp_free(t0);
929 }
fdf9b3e8
FB
930 return;
931 case 0x2008: /* tst Rm,Rn */
c55497ec 932 {
a7812ae4 933 TCGv val = tcg_temp_new();
c55497ec 934 tcg_gen_and_i32(val, REG(B7_4), REG(B11_8));
34086945 935 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
c55497ec
AJ
936 tcg_temp_free(val);
937 }
fdf9b3e8
FB
938 return;
939 case 0x200a: /* xor Rm,Rn */
7efbe241 940 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8 941 return;
e67888a7 942 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
f6198371 943 CHECK_FPU_ENABLED
7a64244f 944 if (ctx->flags & FPSCR_SZ) {
a7812ae4 945 TCGv_i64 fp = tcg_temp_new_i64();
cc4ba6a9
AJ
946 gen_load_fpr64(fp, XREG(B7_4));
947 gen_store_fpr64(fp, XREG(B11_8));
a7812ae4 948 tcg_temp_free_i64(fp);
eda9b09b 949 } else {
66ba317c 950 tcg_gen_mov_i32(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]);
eda9b09b
FB
951 }
952 return;
e67888a7 953 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
f6198371 954 CHECK_FPU_ENABLED
7a64244f 955 if (ctx->flags & FPSCR_SZ) {
11bb09f1
AJ
956 TCGv addr_hi = tcg_temp_new();
957 int fr = XREG(B7_4);
958 tcg_gen_addi_i32(addr_hi, REG(B11_8), 4);
3376f415
AJ
959 tcg_gen_qemu_st_i32(cpu_fregs[fr], REG(B11_8),
960 ctx->memidx, MO_TEUL);
961 tcg_gen_qemu_st_i32(cpu_fregs[fr+1], addr_hi,
962 ctx->memidx, MO_TEUL);
11bb09f1 963 tcg_temp_free(addr_hi);
eda9b09b 964 } else {
3376f415
AJ
965 tcg_gen_qemu_st_i32(cpu_fregs[FREG(B7_4)], REG(B11_8),
966 ctx->memidx, MO_TEUL);
eda9b09b
FB
967 }
968 return;
e67888a7 969 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
f6198371 970 CHECK_FPU_ENABLED
7a64244f 971 if (ctx->flags & FPSCR_SZ) {
11bb09f1
AJ
972 TCGv addr_hi = tcg_temp_new();
973 int fr = XREG(B11_8);
974 tcg_gen_addi_i32(addr_hi, REG(B7_4), 4);
3376f415
AJ
975 tcg_gen_qemu_ld_i32(cpu_fregs[fr], REG(B7_4), ctx->memidx, MO_TEUL);
976 tcg_gen_qemu_ld_i32(cpu_fregs[fr+1], addr_hi, ctx->memidx, MO_TEUL);
11bb09f1 977 tcg_temp_free(addr_hi);
eda9b09b 978 } else {
3376f415
AJ
979 tcg_gen_qemu_ld_i32(cpu_fregs[FREG(B11_8)], REG(B7_4),
980 ctx->memidx, MO_TEUL);
eda9b09b
FB
981 }
982 return;
e67888a7 983 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
f6198371 984 CHECK_FPU_ENABLED
7a64244f 985 if (ctx->flags & FPSCR_SZ) {
11bb09f1
AJ
986 TCGv addr_hi = tcg_temp_new();
987 int fr = XREG(B11_8);
988 tcg_gen_addi_i32(addr_hi, REG(B7_4), 4);
3376f415
AJ
989 tcg_gen_qemu_ld_i32(cpu_fregs[fr], REG(B7_4), ctx->memidx, MO_TEUL);
990 tcg_gen_qemu_ld_i32(cpu_fregs[fr+1], addr_hi, ctx->memidx, MO_TEUL);
11bb09f1
AJ
991 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8);
992 tcg_temp_free(addr_hi);
eda9b09b 993 } else {
3376f415
AJ
994 tcg_gen_qemu_ld_i32(cpu_fregs[FREG(B11_8)], REG(B7_4),
995 ctx->memidx, MO_TEUL);
cc4ba6a9 996 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
eda9b09b
FB
997 }
998 return;
e67888a7 999 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
f6198371 1000 CHECK_FPU_ENABLED
91b4d29f
AJ
1001 TCGv addr = tcg_temp_new_i32();
1002 tcg_gen_subi_i32(addr, REG(B11_8), 4);
7a64244f 1003 if (ctx->flags & FPSCR_SZ) {
11bb09f1 1004 int fr = XREG(B7_4);
3376f415 1005 tcg_gen_qemu_st_i32(cpu_fregs[fr+1], addr, ctx->memidx, MO_TEUL);
3101e99c 1006 tcg_gen_subi_i32(addr, addr, 4);
3376f415 1007 tcg_gen_qemu_st_i32(cpu_fregs[fr], addr, ctx->memidx, MO_TEUL);
eda9b09b 1008 } else {
3376f415
AJ
1009 tcg_gen_qemu_st_i32(cpu_fregs[FREG(B7_4)], addr,
1010 ctx->memidx, MO_TEUL);
eda9b09b 1011 }
91b4d29f
AJ
1012 tcg_gen_mov_i32(REG(B11_8), addr);
1013 tcg_temp_free(addr);
eda9b09b 1014 return;
e67888a7 1015 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
f6198371 1016 CHECK_FPU_ENABLED
cc4ba6a9 1017 {
a7812ae4 1018 TCGv addr = tcg_temp_new_i32();
cc4ba6a9 1019 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
7a64244f 1020 if (ctx->flags & FPSCR_SZ) {
11bb09f1 1021 int fr = XREG(B11_8);
3376f415
AJ
1022 tcg_gen_qemu_ld_i32(cpu_fregs[fr], addr,
1023 ctx->memidx, MO_TEUL);
11bb09f1 1024 tcg_gen_addi_i32(addr, addr, 4);
3376f415
AJ
1025 tcg_gen_qemu_ld_i32(cpu_fregs[fr+1], addr,
1026 ctx->memidx, MO_TEUL);
cc4ba6a9 1027 } else {
3376f415
AJ
1028 tcg_gen_qemu_ld_i32(cpu_fregs[FREG(B11_8)], addr,
1029 ctx->memidx, MO_TEUL);
cc4ba6a9
AJ
1030 }
1031 tcg_temp_free(addr);
eda9b09b
FB
1032 }
1033 return;
e67888a7 1034 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
f6198371 1035 CHECK_FPU_ENABLED
cc4ba6a9 1036 {
a7812ae4 1037 TCGv addr = tcg_temp_new();
cc4ba6a9 1038 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
7a64244f 1039 if (ctx->flags & FPSCR_SZ) {
11bb09f1 1040 int fr = XREG(B7_4);
3376f415
AJ
1041 tcg_gen_qemu_ld_i32(cpu_fregs[fr], addr,
1042 ctx->memidx, MO_TEUL);
11bb09f1 1043 tcg_gen_addi_i32(addr, addr, 4);
3376f415
AJ
1044 tcg_gen_qemu_ld_i32(cpu_fregs[fr+1], addr,
1045 ctx->memidx, MO_TEUL);
cc4ba6a9 1046 } else {
3376f415
AJ
1047 tcg_gen_qemu_st_i32(cpu_fregs[FREG(B7_4)], addr,
1048 ctx->memidx, MO_TEUL);
cc4ba6a9
AJ
1049 }
1050 tcg_temp_free(addr);
eda9b09b
FB
1051 }
1052 return;
e67888a7
TS
1053 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1054 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1055 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1056 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1057 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1058 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
cc4ba6a9 1059 {
f6198371 1060 CHECK_FPU_ENABLED
7a64244f 1061 if (ctx->flags & FPSCR_PR) {
a7812ae4
PB
1062 TCGv_i64 fp0, fp1;
1063
cc4ba6a9
AJ
1064 if (ctx->opcode & 0x0110)
1065 break; /* illegal instruction */
a7812ae4
PB
1066 fp0 = tcg_temp_new_i64();
1067 fp1 = tcg_temp_new_i64();
cc4ba6a9
AJ
1068 gen_load_fpr64(fp0, DREG(B11_8));
1069 gen_load_fpr64(fp1, DREG(B7_4));
a7812ae4
PB
1070 switch (ctx->opcode & 0xf00f) {
1071 case 0xf000: /* fadd Rm,Rn */
485d0035 1072 gen_helper_fadd_DT(fp0, cpu_env, fp0, fp1);
a7812ae4
PB
1073 break;
1074 case 0xf001: /* fsub Rm,Rn */
485d0035 1075 gen_helper_fsub_DT(fp0, cpu_env, fp0, fp1);
a7812ae4
PB
1076 break;
1077 case 0xf002: /* fmul Rm,Rn */
485d0035 1078 gen_helper_fmul_DT(fp0, cpu_env, fp0, fp1);
a7812ae4
PB
1079 break;
1080 case 0xf003: /* fdiv Rm,Rn */
485d0035 1081 gen_helper_fdiv_DT(fp0, cpu_env, fp0, fp1);
a7812ae4
PB
1082 break;
1083 case 0xf004: /* fcmp/eq Rm,Rn */
485d0035 1084 gen_helper_fcmp_eq_DT(cpu_env, fp0, fp1);
a7812ae4
PB
1085 return;
1086 case 0xf005: /* fcmp/gt Rm,Rn */
485d0035 1087 gen_helper_fcmp_gt_DT(cpu_env, fp0, fp1);
a7812ae4
PB
1088 return;
1089 }
1090 gen_store_fpr64(fp0, DREG(B11_8));
1091 tcg_temp_free_i64(fp0);
1092 tcg_temp_free_i64(fp1);
1093 } else {
a7812ae4
PB
1094 switch (ctx->opcode & 0xf00f) {
1095 case 0xf000: /* fadd Rm,Rn */
485d0035
BS
1096 gen_helper_fadd_FT(cpu_fregs[FREG(B11_8)], cpu_env,
1097 cpu_fregs[FREG(B11_8)],
1098 cpu_fregs[FREG(B7_4)]);
a7812ae4
PB
1099 break;
1100 case 0xf001: /* fsub Rm,Rn */
485d0035
BS
1101 gen_helper_fsub_FT(cpu_fregs[FREG(B11_8)], cpu_env,
1102 cpu_fregs[FREG(B11_8)],
1103 cpu_fregs[FREG(B7_4)]);
a7812ae4
PB
1104 break;
1105 case 0xf002: /* fmul Rm,Rn */
485d0035
BS
1106 gen_helper_fmul_FT(cpu_fregs[FREG(B11_8)], cpu_env,
1107 cpu_fregs[FREG(B11_8)],
1108 cpu_fregs[FREG(B7_4)]);
a7812ae4
PB
1109 break;
1110 case 0xf003: /* fdiv Rm,Rn */
485d0035
BS
1111 gen_helper_fdiv_FT(cpu_fregs[FREG(B11_8)], cpu_env,
1112 cpu_fregs[FREG(B11_8)],
1113 cpu_fregs[FREG(B7_4)]);
a7812ae4
PB
1114 break;
1115 case 0xf004: /* fcmp/eq Rm,Rn */
485d0035
BS
1116 gen_helper_fcmp_eq_FT(cpu_env, cpu_fregs[FREG(B11_8)],
1117 cpu_fregs[FREG(B7_4)]);
a7812ae4
PB
1118 return;
1119 case 0xf005: /* fcmp/gt Rm,Rn */
485d0035
BS
1120 gen_helper_fcmp_gt_FT(cpu_env, cpu_fregs[FREG(B11_8)],
1121 cpu_fregs[FREG(B7_4)]);
a7812ae4
PB
1122 return;
1123 }
cc4ba6a9 1124 }
ea6cf6be
TS
1125 }
1126 return;
5b7141a1
AJ
1127 case 0xf00e: /* fmac FR0,RM,Rn */
1128 {
1129 CHECK_FPU_ENABLED
7a64244f 1130 if (ctx->flags & FPSCR_PR) {
5b7141a1
AJ
1131 break; /* illegal instruction */
1132 } else {
485d0035
BS
1133 gen_helper_fmac_FT(cpu_fregs[FREG(B11_8)], cpu_env,
1134 cpu_fregs[FREG(0)], cpu_fregs[FREG(B7_4)],
1135 cpu_fregs[FREG(B11_8)]);
5b7141a1
AJ
1136 return;
1137 }
1138 }
fdf9b3e8
FB
1139 }
1140
1141 switch (ctx->opcode & 0xff00) {
1142 case 0xc900: /* and #imm,R0 */
7efbe241 1143 tcg_gen_andi_i32(REG(0), REG(0), B7_0);
fdf9b3e8 1144 return;
24988dc2 1145 case 0xcd00: /* and.b #imm,@(R0,GBR) */
c55497ec
AJ
1146 {
1147 TCGv addr, val;
a7812ae4 1148 addr = tcg_temp_new();
c55497ec 1149 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
a7812ae4 1150 val = tcg_temp_new();
3376f415 1151 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
c55497ec 1152 tcg_gen_andi_i32(val, val, B7_0);
3376f415 1153 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
c55497ec
AJ
1154 tcg_temp_free(val);
1155 tcg_temp_free(addr);
1156 }
fdf9b3e8
FB
1157 return;
1158 case 0x8b00: /* bf label */
1159 CHECK_NOT_DELAY_SLOT
1160 gen_conditional_jump(ctx, ctx->pc + 2,
1161 ctx->pc + 4 + B7_0s * 2);
823029f9 1162 ctx->bstate = BS_BRANCH;
fdf9b3e8
FB
1163 return;
1164 case 0x8f00: /* bf/s label */
1165 CHECK_NOT_DELAY_SLOT
1000822b 1166 gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 0);
fdf9b3e8
FB
1167 ctx->flags |= DELAY_SLOT_CONDITIONAL;
1168 return;
1169 case 0x8900: /* bt label */
1170 CHECK_NOT_DELAY_SLOT
1171 gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2,
1172 ctx->pc + 2);
823029f9 1173 ctx->bstate = BS_BRANCH;
fdf9b3e8
FB
1174 return;
1175 case 0x8d00: /* bt/s label */
1176 CHECK_NOT_DELAY_SLOT
1000822b 1177 gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 1);
fdf9b3e8
FB
1178 ctx->flags |= DELAY_SLOT_CONDITIONAL;
1179 return;
1180 case 0x8800: /* cmp/eq #imm,R0 */
34086945 1181 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s);
fdf9b3e8
FB
1182 return;
1183 case 0xc400: /* mov.b @(disp,GBR),R0 */
c55497ec 1184 {
a7812ae4 1185 TCGv addr = tcg_temp_new();
c55497ec 1186 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
3376f415 1187 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
c55497ec
AJ
1188 tcg_temp_free(addr);
1189 }
fdf9b3e8
FB
1190 return;
1191 case 0xc500: /* mov.w @(disp,GBR),R0 */
c55497ec 1192 {
a7812ae4 1193 TCGv addr = tcg_temp_new();
c55497ec 1194 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
3376f415 1195 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW);
c55497ec
AJ
1196 tcg_temp_free(addr);
1197 }
fdf9b3e8
FB
1198 return;
1199 case 0xc600: /* mov.l @(disp,GBR),R0 */
c55497ec 1200 {
a7812ae4 1201 TCGv addr = tcg_temp_new();
c55497ec 1202 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
3376f415 1203 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESL);
c55497ec
AJ
1204 tcg_temp_free(addr);
1205 }
fdf9b3e8
FB
1206 return;
1207 case 0xc000: /* mov.b R0,@(disp,GBR) */
c55497ec 1208 {
a7812ae4 1209 TCGv addr = tcg_temp_new();
c55497ec 1210 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
3376f415 1211 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
c55497ec
AJ
1212 tcg_temp_free(addr);
1213 }
fdf9b3e8
FB
1214 return;
1215 case 0xc100: /* mov.w R0,@(disp,GBR) */
c55497ec 1216 {
a7812ae4 1217 TCGv addr = tcg_temp_new();
c55497ec 1218 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
3376f415 1219 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW);
c55497ec
AJ
1220 tcg_temp_free(addr);
1221 }
fdf9b3e8
FB
1222 return;
1223 case 0xc200: /* mov.l R0,@(disp,GBR) */
c55497ec 1224 {
a7812ae4 1225 TCGv addr = tcg_temp_new();
c55497ec 1226 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
3376f415 1227 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUL);
c55497ec
AJ
1228 tcg_temp_free(addr);
1229 }
fdf9b3e8
FB
1230 return;
1231 case 0x8000: /* mov.b R0,@(disp,Rn) */
c55497ec 1232 {
a7812ae4 1233 TCGv addr = tcg_temp_new();
c55497ec 1234 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
3376f415 1235 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
c55497ec
AJ
1236 tcg_temp_free(addr);
1237 }
fdf9b3e8
FB
1238 return;
1239 case 0x8100: /* mov.w R0,@(disp,Rn) */
c55497ec 1240 {
a7812ae4 1241 TCGv addr = tcg_temp_new();
c55497ec 1242 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
3376f415 1243 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW);
c55497ec
AJ
1244 tcg_temp_free(addr);
1245 }
fdf9b3e8
FB
1246 return;
1247 case 0x8400: /* mov.b @(disp,Rn),R0 */
c55497ec 1248 {
a7812ae4 1249 TCGv addr = tcg_temp_new();
c55497ec 1250 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
3376f415 1251 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
c55497ec
AJ
1252 tcg_temp_free(addr);
1253 }
fdf9b3e8
FB
1254 return;
1255 case 0x8500: /* mov.w @(disp,Rn),R0 */
c55497ec 1256 {
a7812ae4 1257 TCGv addr = tcg_temp_new();
c55497ec 1258 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
3376f415 1259 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW);
c55497ec
AJ
1260 tcg_temp_free(addr);
1261 }
fdf9b3e8
FB
1262 return;
1263 case 0xc700: /* mova @(disp,PC),R0 */
7efbe241 1264 tcg_gen_movi_i32(REG(0), ((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3);
fdf9b3e8
FB
1265 return;
1266 case 0xcb00: /* or #imm,R0 */
7efbe241 1267 tcg_gen_ori_i32(REG(0), REG(0), B7_0);
fdf9b3e8 1268 return;
24988dc2 1269 case 0xcf00: /* or.b #imm,@(R0,GBR) */
c55497ec
AJ
1270 {
1271 TCGv addr, val;
a7812ae4 1272 addr = tcg_temp_new();
c55497ec 1273 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
a7812ae4 1274 val = tcg_temp_new();
3376f415 1275 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
c55497ec 1276 tcg_gen_ori_i32(val, val, B7_0);
3376f415 1277 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
c55497ec
AJ
1278 tcg_temp_free(val);
1279 tcg_temp_free(addr);
1280 }
fdf9b3e8
FB
1281 return;
1282 case 0xc300: /* trapa #imm */
c55497ec
AJ
1283 {
1284 TCGv imm;
1285 CHECK_NOT_DELAY_SLOT
10127400 1286 tcg_gen_movi_i32(cpu_pc, ctx->pc);
c55497ec 1287 imm = tcg_const_i32(B7_0);
485d0035 1288 gen_helper_trapa(cpu_env, imm);
c55497ec
AJ
1289 tcg_temp_free(imm);
1290 ctx->bstate = BS_BRANCH;
1291 }
fdf9b3e8
FB
1292 return;
1293 case 0xc800: /* tst #imm,R0 */
c55497ec 1294 {
a7812ae4 1295 TCGv val = tcg_temp_new();
c55497ec 1296 tcg_gen_andi_i32(val, REG(0), B7_0);
34086945 1297 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
c55497ec
AJ
1298 tcg_temp_free(val);
1299 }
fdf9b3e8 1300 return;
24988dc2 1301 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
c55497ec 1302 {
a7812ae4 1303 TCGv val = tcg_temp_new();
c55497ec 1304 tcg_gen_add_i32(val, REG(0), cpu_gbr);
3376f415 1305 tcg_gen_qemu_ld_i32(val, val, ctx->memidx, MO_UB);
c55497ec 1306 tcg_gen_andi_i32(val, val, B7_0);
34086945 1307 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
c55497ec
AJ
1308 tcg_temp_free(val);
1309 }
fdf9b3e8
FB
1310 return;
1311 case 0xca00: /* xor #imm,R0 */
7efbe241 1312 tcg_gen_xori_i32(REG(0), REG(0), B7_0);
fdf9b3e8 1313 return;
24988dc2 1314 case 0xce00: /* xor.b #imm,@(R0,GBR) */
c55497ec
AJ
1315 {
1316 TCGv addr, val;
a7812ae4 1317 addr = tcg_temp_new();
c55497ec 1318 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
a7812ae4 1319 val = tcg_temp_new();
3376f415 1320 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
c55497ec 1321 tcg_gen_xori_i32(val, val, B7_0);
3376f415 1322 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
c55497ec
AJ
1323 tcg_temp_free(val);
1324 tcg_temp_free(addr);
1325 }
fdf9b3e8
FB
1326 return;
1327 }
1328
1329 switch (ctx->opcode & 0xf08f) {
1330 case 0x408e: /* ldc Rm,Rn_BANK */
fe25591e 1331 CHECK_PRIVILEGED
7efbe241 1332 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8));
fdf9b3e8
FB
1333 return;
1334 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
fe25591e 1335 CHECK_PRIVILEGED
3376f415 1336 tcg_gen_qemu_ld_i32(ALTREG(B6_4), REG(B11_8), ctx->memidx, MO_TESL);
7efbe241 1337 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
fdf9b3e8
FB
1338 return;
1339 case 0x0082: /* stc Rm_BANK,Rn */
fe25591e 1340 CHECK_PRIVILEGED
7efbe241 1341 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4));
fdf9b3e8
FB
1342 return;
1343 case 0x4083: /* stc.l Rm_BANK,@-Rn */
fe25591e 1344 CHECK_PRIVILEGED
c55497ec 1345 {
a7812ae4 1346 TCGv addr = tcg_temp_new();
c55497ec 1347 tcg_gen_subi_i32(addr, REG(B11_8), 4);
3376f415 1348 tcg_gen_qemu_st_i32(ALTREG(B6_4), addr, ctx->memidx, MO_TEUL);
3101e99c 1349 tcg_gen_mov_i32(REG(B11_8), addr);
c55497ec 1350 tcg_temp_free(addr);
c55497ec 1351 }
fdf9b3e8
FB
1352 return;
1353 }
1354
1355 switch (ctx->opcode & 0xf0ff) {
1356 case 0x0023: /* braf Rn */
7efbe241
AJ
1357 CHECK_NOT_DELAY_SLOT
1358 tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->pc + 4);
fdf9b3e8
FB
1359 ctx->flags |= DELAY_SLOT;
1360 ctx->delayed_pc = (uint32_t) - 1;
1361 return;
1362 case 0x0003: /* bsrf Rn */
7efbe241 1363 CHECK_NOT_DELAY_SLOT
1000822b 1364 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
7efbe241 1365 tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
fdf9b3e8
FB
1366 ctx->flags |= DELAY_SLOT;
1367 ctx->delayed_pc = (uint32_t) - 1;
1368 return;
1369 case 0x4015: /* cmp/pl Rn */
34086945 1370 tcg_gen_setcondi_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), 0);
fdf9b3e8
FB
1371 return;
1372 case 0x4011: /* cmp/pz Rn */
34086945 1373 tcg_gen_setcondi_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), 0);
fdf9b3e8
FB
1374 return;
1375 case 0x4010: /* dt Rn */
7efbe241 1376 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1);
34086945 1377 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), 0);
fdf9b3e8
FB
1378 return;
1379 case 0x402b: /* jmp @Rn */
7efbe241
AJ
1380 CHECK_NOT_DELAY_SLOT
1381 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
fdf9b3e8
FB
1382 ctx->flags |= DELAY_SLOT;
1383 ctx->delayed_pc = (uint32_t) - 1;
1384 return;
1385 case 0x400b: /* jsr @Rn */
7efbe241 1386 CHECK_NOT_DELAY_SLOT
1000822b 1387 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
7efbe241 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;
fe25591e
AJ
1392 case 0x400e: /* ldc Rm,SR */
1393 CHECK_PRIVILEGED
34086945
AJ
1394 {
1395 TCGv val = tcg_temp_new();
1396 tcg_gen_andi_i32(val, REG(B11_8), 0x700083f3);
1397 gen_write_sr(val);
1398 tcg_temp_free(val);
1399 ctx->bstate = BS_STOP;
1400 }
390af821 1401 return;
fe25591e
AJ
1402 case 0x4007: /* ldc.l @Rm+,SR */
1403 CHECK_PRIVILEGED
c55497ec 1404 {
a7812ae4 1405 TCGv val = tcg_temp_new();
3376f415 1406 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TESL);
34086945
AJ
1407 tcg_gen_andi_i32(val, val, 0x700083f3);
1408 gen_write_sr(val);
c55497ec
AJ
1409 tcg_temp_free(val);
1410 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1411 ctx->bstate = BS_STOP;
1412 }
390af821 1413 return;
fe25591e
AJ
1414 case 0x0002: /* stc SR,Rn */
1415 CHECK_PRIVILEGED
34086945 1416 gen_read_sr(REG(B11_8));
390af821 1417 return;
fe25591e
AJ
1418 case 0x4003: /* stc SR,@-Rn */
1419 CHECK_PRIVILEGED
c55497ec 1420 {
a7812ae4 1421 TCGv addr = tcg_temp_new();
34086945 1422 TCGv val = tcg_temp_new();
c55497ec 1423 tcg_gen_subi_i32(addr, REG(B11_8), 4);
34086945
AJ
1424 gen_read_sr(val);
1425 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL);
3101e99c 1426 tcg_gen_mov_i32(REG(B11_8), addr);
34086945 1427 tcg_temp_free(val);
c55497ec 1428 tcg_temp_free(addr);
c55497ec 1429 }
390af821 1430 return;
8e9b0678 1431#define LD(reg,ldnum,ldpnum,prechk) \
fdf9b3e8 1432 case ldnum: \
fe25591e 1433 prechk \
7efbe241 1434 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \
fdf9b3e8
FB
1435 return; \
1436 case ldpnum: \
fe25591e 1437 prechk \
3376f415 1438 tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, MO_TESL); \
7efbe241 1439 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \
8e9b0678
AC
1440 return;
1441#define ST(reg,stnum,stpnum,prechk) \
fdf9b3e8 1442 case stnum: \
fe25591e 1443 prechk \
7efbe241 1444 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \
fdf9b3e8
FB
1445 return; \
1446 case stpnum: \
fe25591e 1447 prechk \
c55497ec 1448 { \
3101e99c 1449 TCGv addr = tcg_temp_new(); \
c55497ec 1450 tcg_gen_subi_i32(addr, REG(B11_8), 4); \
3376f415 1451 tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, MO_TEUL); \
3101e99c 1452 tcg_gen_mov_i32(REG(B11_8), addr); \
c55497ec 1453 tcg_temp_free(addr); \
86e0abc7 1454 } \
fdf9b3e8 1455 return;
8e9b0678
AC
1456#define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \
1457 LD(reg,ldnum,ldpnum,prechk) \
1458 ST(reg,stnum,stpnum,prechk)
fe25591e
AJ
1459 LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {})
1460 LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED)
1461 LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED)
1462 LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED)
935fc175
AC
1463 ST(sgr, 0x003a, 0x4032, CHECK_PRIVILEGED)
1464 LD(sgr, 0x403a, 0x4036, CHECK_PRIVILEGED if (!(ctx->features & SH_FEATURE_SH4A)) break;)
fe25591e
AJ
1465 LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED)
1466 LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {})
1467 LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {})
1468 LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {})
d8299bcc 1469 LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED})
390af821 1470 case 0x406a: /* lds Rm,FPSCR */
d8299bcc 1471 CHECK_FPU_ENABLED
485d0035 1472 gen_helper_ld_fpscr(cpu_env, REG(B11_8));
390af821
AJ
1473 ctx->bstate = BS_STOP;
1474 return;
1475 case 0x4066: /* lds.l @Rm+,FPSCR */
d8299bcc 1476 CHECK_FPU_ENABLED
c55497ec 1477 {
a7812ae4 1478 TCGv addr = tcg_temp_new();
3376f415 1479 tcg_gen_qemu_ld_i32(addr, REG(B11_8), ctx->memidx, MO_TESL);
c55497ec 1480 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
485d0035 1481 gen_helper_ld_fpscr(cpu_env, addr);
c55497ec
AJ
1482 tcg_temp_free(addr);
1483 ctx->bstate = BS_STOP;
1484 }
390af821
AJ
1485 return;
1486 case 0x006a: /* sts FPSCR,Rn */
d8299bcc 1487 CHECK_FPU_ENABLED
c55497ec 1488 tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff);
390af821
AJ
1489 return;
1490 case 0x4062: /* sts FPSCR,@-Rn */
d8299bcc 1491 CHECK_FPU_ENABLED
c55497ec
AJ
1492 {
1493 TCGv addr, val;
a7812ae4 1494 val = tcg_temp_new();
c55497ec 1495 tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff);
a7812ae4 1496 addr = tcg_temp_new();
c55497ec 1497 tcg_gen_subi_i32(addr, REG(B11_8), 4);
3376f415 1498 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL);
3101e99c 1499 tcg_gen_mov_i32(REG(B11_8), addr);
c55497ec
AJ
1500 tcg_temp_free(addr);
1501 tcg_temp_free(val);
c55497ec 1502 }
390af821 1503 return;
fdf9b3e8 1504 case 0x00c3: /* movca.l R0,@Rm */
852d481f
EI
1505 {
1506 TCGv val = tcg_temp_new();
3376f415 1507 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TEUL);
485d0035 1508 gen_helper_movcal(cpu_env, REG(B11_8), val);
3376f415 1509 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
852d481f
EI
1510 }
1511 ctx->has_movcal = 1;
fdf9b3e8 1512 return;
7526aa2d
AJ
1513 case 0x40a9:
1514 /* MOVUA.L @Rm,R0 (Rm) -> R0
1515 Load non-boundary-aligned data */
3376f415 1516 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
7526aa2d
AJ
1517 return;
1518 case 0x40e9:
1519 /* MOVUA.L @Rm+,R0 (Rm) -> R0, Rm + 4 -> Rm
1520 Load non-boundary-aligned data */
3376f415 1521 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
7526aa2d
AJ
1522 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1523 return;
fdf9b3e8 1524 case 0x0029: /* movt Rn */
34086945 1525 tcg_gen_mov_i32(REG(B11_8), cpu_sr_t);
fdf9b3e8 1526 return;
66c7c806
AJ
1527 case 0x0073:
1528 /* MOVCO.L
1529 LDST -> T
1530 If (T == 1) R0 -> (Rn)
1531 0 -> LDST
1532 */
1533 if (ctx->features & SH_FEATURE_SH4A) {
42a268c2 1534 TCGLabel *label = gen_new_label();
34086945 1535 tcg_gen_mov_i32(cpu_sr_t, cpu_ldst);
66c7c806 1536 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ldst, 0, label);
3376f415 1537 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
66c7c806
AJ
1538 gen_set_label(label);
1539 tcg_gen_movi_i32(cpu_ldst, 0);
1540 return;
1541 } else
1542 break;
1543 case 0x0063:
1544 /* MOVLI.L @Rm,R0
1545 1 -> LDST
1546 (Rm) -> R0
1547 When interrupt/exception
1548 occurred 0 -> LDST
1549 */
1550 if (ctx->features & SH_FEATURE_SH4A) {
1551 tcg_gen_movi_i32(cpu_ldst, 0);
3376f415 1552 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TESL);
66c7c806
AJ
1553 tcg_gen_movi_i32(cpu_ldst, 1);
1554 return;
1555 } else
1556 break;
fdf9b3e8 1557 case 0x0093: /* ocbi @Rn */
c55497ec 1558 {
485d0035 1559 gen_helper_ocbi(cpu_env, REG(B11_8));
c55497ec 1560 }
fdf9b3e8 1561 return;
24988dc2 1562 case 0x00a3: /* ocbp @Rn */
fdf9b3e8 1563 case 0x00b3: /* ocbwb @Rn */
0cdb9554
AJ
1564 /* These instructions are supposed to do nothing in case of
1565 a cache miss. Given that we only partially emulate caches
1566 it is safe to simply ignore them. */
fdf9b3e8
FB
1567 return;
1568 case 0x0083: /* pref @Rn */
1569 return;
71968fa6
AJ
1570 case 0x00d3: /* prefi @Rn */
1571 if (ctx->features & SH_FEATURE_SH4A)
1572 return;
1573 else
1574 break;
1575 case 0x00e3: /* icbi @Rn */
1576 if (ctx->features & SH_FEATURE_SH4A)
1577 return;
1578 else
1579 break;
1580 case 0x00ab: /* synco */
1581 if (ctx->features & SH_FEATURE_SH4A)
1582 return;
1583 else
1584 break;
fdf9b3e8 1585 case 0x4024: /* rotcl Rn */
c55497ec 1586 {
a7812ae4 1587 TCGv tmp = tcg_temp_new();
34086945
AJ
1588 tcg_gen_mov_i32(tmp, cpu_sr_t);
1589 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
c55497ec 1590 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
34086945 1591 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
c55497ec
AJ
1592 tcg_temp_free(tmp);
1593 }
fdf9b3e8
FB
1594 return;
1595 case 0x4025: /* rotcr Rn */
c55497ec 1596 {
a7812ae4 1597 TCGv tmp = tcg_temp_new();
34086945
AJ
1598 tcg_gen_shli_i32(tmp, cpu_sr_t, 31);
1599 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
c55497ec 1600 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
34086945 1601 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
c55497ec
AJ
1602 tcg_temp_free(tmp);
1603 }
fdf9b3e8
FB
1604 return;
1605 case 0x4004: /* rotl Rn */
2411fde9 1606 tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1);
34086945 1607 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
fdf9b3e8
FB
1608 return;
1609 case 0x4005: /* rotr Rn */
34086945 1610 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
2411fde9 1611 tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1);
fdf9b3e8
FB
1612 return;
1613 case 0x4000: /* shll Rn */
1614 case 0x4020: /* shal Rn */
34086945 1615 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
7efbe241 1616 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
fdf9b3e8
FB
1617 return;
1618 case 0x4021: /* shar Rn */
34086945 1619 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
7efbe241 1620 tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1);
fdf9b3e8
FB
1621 return;
1622 case 0x4001: /* shlr Rn */
34086945 1623 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
7efbe241 1624 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
fdf9b3e8
FB
1625 return;
1626 case 0x4008: /* shll2 Rn */
7efbe241 1627 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2);
fdf9b3e8
FB
1628 return;
1629 case 0x4018: /* shll8 Rn */
7efbe241 1630 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8);
fdf9b3e8
FB
1631 return;
1632 case 0x4028: /* shll16 Rn */
7efbe241 1633 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16);
fdf9b3e8
FB
1634 return;
1635 case 0x4009: /* shlr2 Rn */
7efbe241 1636 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2);
fdf9b3e8
FB
1637 return;
1638 case 0x4019: /* shlr8 Rn */
7efbe241 1639 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8);
fdf9b3e8
FB
1640 return;
1641 case 0x4029: /* shlr16 Rn */
7efbe241 1642 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16);
fdf9b3e8
FB
1643 return;
1644 case 0x401b: /* tas.b @Rn */
c55497ec
AJ
1645 {
1646 TCGv addr, val;
df9247b2 1647 addr = tcg_temp_local_new();
c55497ec 1648 tcg_gen_mov_i32(addr, REG(B11_8));
df9247b2 1649 val = tcg_temp_local_new();
3376f415 1650 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
34086945 1651 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
c55497ec 1652 tcg_gen_ori_i32(val, val, 0x80);
3376f415 1653 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
c55497ec
AJ
1654 tcg_temp_free(val);
1655 tcg_temp_free(addr);
1656 }
fdf9b3e8 1657 return;
e67888a7 1658 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
f6198371
AJ
1659 CHECK_FPU_ENABLED
1660 tcg_gen_mov_i32(cpu_fregs[FREG(B11_8)], cpu_fpul);
eda9b09b 1661 return;
e67888a7 1662 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
f6198371
AJ
1663 CHECK_FPU_ENABLED
1664 tcg_gen_mov_i32(cpu_fpul, cpu_fregs[FREG(B11_8)]);
eda9b09b 1665 return;
e67888a7 1666 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
f6198371 1667 CHECK_FPU_ENABLED
7a64244f 1668 if (ctx->flags & FPSCR_PR) {
a7812ae4 1669 TCGv_i64 fp;
ea6cf6be
TS
1670 if (ctx->opcode & 0x0100)
1671 break; /* illegal instruction */
a7812ae4 1672 fp = tcg_temp_new_i64();
485d0035 1673 gen_helper_float_DT(fp, cpu_env, cpu_fpul);
cc4ba6a9 1674 gen_store_fpr64(fp, DREG(B11_8));
a7812ae4 1675 tcg_temp_free_i64(fp);
ea6cf6be
TS
1676 }
1677 else {
485d0035 1678 gen_helper_float_FT(cpu_fregs[FREG(B11_8)], cpu_env, cpu_fpul);
ea6cf6be
TS
1679 }
1680 return;
e67888a7 1681 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
f6198371 1682 CHECK_FPU_ENABLED
7a64244f 1683 if (ctx->flags & FPSCR_PR) {
a7812ae4 1684 TCGv_i64 fp;
ea6cf6be
TS
1685 if (ctx->opcode & 0x0100)
1686 break; /* illegal instruction */
a7812ae4 1687 fp = tcg_temp_new_i64();
cc4ba6a9 1688 gen_load_fpr64(fp, DREG(B11_8));
485d0035 1689 gen_helper_ftrc_DT(cpu_fpul, cpu_env, fp);
a7812ae4 1690 tcg_temp_free_i64(fp);
ea6cf6be
TS
1691 }
1692 else {
485d0035 1693 gen_helper_ftrc_FT(cpu_fpul, cpu_env, cpu_fregs[FREG(B11_8)]);
ea6cf6be
TS
1694 }
1695 return;
24988dc2 1696 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
f6198371 1697 CHECK_FPU_ENABLED
7fdf924f 1698 {
66ba317c 1699 gen_helper_fneg_T(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)]);
7fdf924f 1700 }
24988dc2
AJ
1701 return;
1702 case 0xf05d: /* fabs FRn/DRn */
f6198371 1703 CHECK_FPU_ENABLED
7a64244f 1704 if (ctx->flags & FPSCR_PR) {
24988dc2
AJ
1705 if (ctx->opcode & 0x0100)
1706 break; /* illegal instruction */
a7812ae4 1707 TCGv_i64 fp = tcg_temp_new_i64();
cc4ba6a9 1708 gen_load_fpr64(fp, DREG(B11_8));
a7812ae4 1709 gen_helper_fabs_DT(fp, fp);
cc4ba6a9 1710 gen_store_fpr64(fp, DREG(B11_8));
a7812ae4 1711 tcg_temp_free_i64(fp);
24988dc2 1712 } else {
66ba317c 1713 gen_helper_fabs_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)]);
24988dc2
AJ
1714 }
1715 return;
1716 case 0xf06d: /* fsqrt FRn */
f6198371 1717 CHECK_FPU_ENABLED
7a64244f 1718 if (ctx->flags & FPSCR_PR) {
24988dc2
AJ
1719 if (ctx->opcode & 0x0100)
1720 break; /* illegal instruction */
a7812ae4 1721 TCGv_i64 fp = tcg_temp_new_i64();
cc4ba6a9 1722 gen_load_fpr64(fp, DREG(B11_8));
485d0035 1723 gen_helper_fsqrt_DT(fp, cpu_env, fp);
cc4ba6a9 1724 gen_store_fpr64(fp, DREG(B11_8));
a7812ae4 1725 tcg_temp_free_i64(fp);
24988dc2 1726 } else {
485d0035
BS
1727 gen_helper_fsqrt_FT(cpu_fregs[FREG(B11_8)], cpu_env,
1728 cpu_fregs[FREG(B11_8)]);
24988dc2
AJ
1729 }
1730 return;
1731 case 0xf07d: /* fsrra FRn */
f6198371 1732 CHECK_FPU_ENABLED
24988dc2 1733 break;
e67888a7 1734 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
f6198371 1735 CHECK_FPU_ENABLED
7a64244f 1736 if (!(ctx->flags & FPSCR_PR)) {
66ba317c 1737 tcg_gen_movi_i32(cpu_fregs[FREG(B11_8)], 0);
ea6cf6be 1738 }
12d96138 1739 return;
e67888a7 1740 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
f6198371 1741 CHECK_FPU_ENABLED
7a64244f 1742 if (!(ctx->flags & FPSCR_PR)) {
66ba317c 1743 tcg_gen_movi_i32(cpu_fregs[FREG(B11_8)], 0x3f800000);
ea6cf6be 1744 }
12d96138 1745 return;
24988dc2 1746 case 0xf0ad: /* fcnvsd FPUL,DRn */
f6198371 1747 CHECK_FPU_ENABLED
cc4ba6a9 1748 {
a7812ae4 1749 TCGv_i64 fp = tcg_temp_new_i64();
485d0035 1750 gen_helper_fcnvsd_FT_DT(fp, cpu_env, cpu_fpul);
cc4ba6a9 1751 gen_store_fpr64(fp, DREG(B11_8));
a7812ae4 1752 tcg_temp_free_i64(fp);
cc4ba6a9 1753 }
24988dc2
AJ
1754 return;
1755 case 0xf0bd: /* fcnvds DRn,FPUL */
f6198371 1756 CHECK_FPU_ENABLED
cc4ba6a9 1757 {
a7812ae4 1758 TCGv_i64 fp = tcg_temp_new_i64();
cc4ba6a9 1759 gen_load_fpr64(fp, DREG(B11_8));
485d0035 1760 gen_helper_fcnvds_DT_FT(cpu_fpul, cpu_env, fp);
a7812ae4 1761 tcg_temp_free_i64(fp);
cc4ba6a9 1762 }
24988dc2 1763 return;
af8c2bde
AJ
1764 case 0xf0ed: /* fipr FVm,FVn */
1765 CHECK_FPU_ENABLED
7a64244f 1766 if ((ctx->flags & FPSCR_PR) == 0) {
af8c2bde 1767 TCGv m, n;
f840fa99
SW
1768 m = tcg_const_i32((ctx->opcode >> 8) & 3);
1769 n = tcg_const_i32((ctx->opcode >> 10) & 3);
485d0035 1770 gen_helper_fipr(cpu_env, m, n);
af8c2bde
AJ
1771 tcg_temp_free(m);
1772 tcg_temp_free(n);
1773 return;
1774 }
1775 break;
17075f10
AJ
1776 case 0xf0fd: /* ftrv XMTRX,FVn */
1777 CHECK_FPU_ENABLED
1778 if ((ctx->opcode & 0x0300) == 0x0100 &&
7a64244f 1779 (ctx->flags & FPSCR_PR) == 0) {
17075f10 1780 TCGv n;
f840fa99 1781 n = tcg_const_i32((ctx->opcode >> 10) & 3);
485d0035 1782 gen_helper_ftrv(cpu_env, n);
17075f10
AJ
1783 tcg_temp_free(n);
1784 return;
1785 }
1786 break;
fdf9b3e8 1787 }
bacc637a 1788#if 0
fdf9b3e8
FB
1789 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1790 ctx->opcode, ctx->pc);
bacc637a
AJ
1791 fflush(stderr);
1792#endif
10127400 1793 tcg_gen_movi_i32(cpu_pc, ctx->pc);
86865c5f 1794 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
485d0035 1795 gen_helper_raise_slot_illegal_instruction(cpu_env);
86865c5f 1796 } else {
485d0035 1797 gen_helper_raise_illegal_instruction(cpu_env);
86865c5f 1798 }
10127400 1799 ctx->bstate = BS_BRANCH;
823029f9
TS
1800}
1801
b1d8e52e 1802static void decode_opc(DisasContext * ctx)
823029f9
TS
1803{
1804 uint32_t old_flags = ctx->flags;
1805
fdefe51c 1806 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
be15c50d
AJ
1807 tcg_gen_debug_insn_start(ctx->pc);
1808 }
1809
823029f9
TS
1810 _decode_opc(ctx);
1811
1812 if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
1813 if (ctx->flags & DELAY_SLOT_CLEARME) {
1000822b 1814 gen_store_flags(0);
274a9e70
AJ
1815 } else {
1816 /* go out of the delay slot */
1817 uint32_t new_flags = ctx->flags;
1818 new_flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
1000822b 1819 gen_store_flags(new_flags);
823029f9
TS
1820 }
1821 ctx->flags = 0;
1822 ctx->bstate = BS_BRANCH;
1823 if (old_flags & DELAY_SLOT_CONDITIONAL) {
1824 gen_delayed_conditional_jump(ctx);
1825 } else if (old_flags & DELAY_SLOT) {
1826 gen_jump(ctx);
1827 }
1828
1829 }
274a9e70
AJ
1830
1831 /* go into a delay slot */
1832 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL))
1000822b 1833 gen_store_flags(ctx->flags);
fdf9b3e8
FB
1834}
1835
2cfc5f17 1836static inline void
38e30810
AF
1837gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
1838 bool search_pc)
fdf9b3e8 1839{
ed2803da 1840 CPUState *cs = CPU(cpu);
38e30810 1841 CPUSH4State *env = &cpu->env;
fdf9b3e8
FB
1842 DisasContext ctx;
1843 target_ulong pc_start;
a1d1bb31 1844 CPUBreakpoint *bp;
355fb23d 1845 int i, ii;
2e70f6ef
PB
1846 int num_insns;
1847 int max_insns;
fdf9b3e8
FB
1848
1849 pc_start = tb->pc;
fdf9b3e8 1850 ctx.pc = pc_start;
823029f9
TS
1851 ctx.flags = (uint32_t)tb->flags;
1852 ctx.bstate = BS_NONE;
5ed9a259 1853 ctx.memidx = (ctx.flags & (1u << SR_MD)) == 0 ? 1 : 0;
9854bc46
PB
1854 /* We don't know if the delayed pc came from a dynamic or static branch,
1855 so assume it is a dynamic branch. */
823029f9 1856 ctx.delayed_pc = -1; /* use delayed pc from env pointer */
fdf9b3e8 1857 ctx.tb = tb;
ed2803da 1858 ctx.singlestep_enabled = cs->singlestep_enabled;
71968fa6 1859 ctx.features = env->features;
7a64244f 1860 ctx.has_movcal = (ctx.flags & TB_FLAG_PENDING_MOVCA);
fdf9b3e8 1861
355fb23d 1862 ii = -1;
2e70f6ef
PB
1863 num_insns = 0;
1864 max_insns = tb->cflags & CF_COUNT_MASK;
1865 if (max_insns == 0)
1866 max_insns = CF_COUNT_MASK;
cd42d5b2 1867 gen_tb_start(tb);
fe700adb 1868 while (ctx.bstate == BS_NONE && !tcg_op_buf_full()) {
f0c3c505
AF
1869 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
1870 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
a1d1bb31 1871 if (ctx.pc == bp->pc) {
fdf9b3e8 1872 /* We have hit a breakpoint - make sure PC is up-to-date */
3a8a44c4 1873 tcg_gen_movi_i32(cpu_pc, ctx.pc);
485d0035 1874 gen_helper_debug(cpu_env);
10127400 1875 ctx.bstate = BS_BRANCH;
fdf9b3e8
FB
1876 break;
1877 }
1878 }
1879 }
355fb23d 1880 if (search_pc) {
fe700adb 1881 i = tcg_op_buf_count();
355fb23d
PB
1882 if (ii < i) {
1883 ii++;
1884 while (ii < i)
ab1103de 1885 tcg_ctx.gen_opc_instr_start[ii++] = 0;
355fb23d 1886 }
25983cad 1887 tcg_ctx.gen_opc_pc[ii] = ctx.pc;
823029f9 1888 gen_opc_hflags[ii] = ctx.flags;
ab1103de 1889 tcg_ctx.gen_opc_instr_start[ii] = 1;
c9c99c22 1890 tcg_ctx.gen_opc_icount[ii] = num_insns;
355fb23d 1891 }
2e70f6ef
PB
1892 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
1893 gen_io_start();
fdf9b3e8
FB
1894#if 0
1895 fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
1896 fflush(stderr);
1897#endif
485d0035 1898 ctx.opcode = cpu_lduw_code(env, ctx.pc);
fdf9b3e8 1899 decode_opc(&ctx);
2e70f6ef 1900 num_insns++;
fdf9b3e8
FB
1901 ctx.pc += 2;
1902 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1903 break;
ed2803da 1904 if (cs->singlestep_enabled) {
fdf9b3e8 1905 break;
ed2803da 1906 }
2e70f6ef
PB
1907 if (num_insns >= max_insns)
1908 break;
1b530a6d
AJ
1909 if (singlestep)
1910 break;
fdf9b3e8 1911 }
2e70f6ef
PB
1912 if (tb->cflags & CF_LAST_IO)
1913 gen_io_end();
ed2803da 1914 if (cs->singlestep_enabled) {
bdbf22e6 1915 tcg_gen_movi_i32(cpu_pc, ctx.pc);
485d0035 1916 gen_helper_debug(cpu_env);
823029f9
TS
1917 } else {
1918 switch (ctx.bstate) {
1919 case BS_STOP:
1920 /* gen_op_interrupt_restart(); */
1921 /* fall through */
1922 case BS_NONE:
1923 if (ctx.flags) {
1000822b 1924 gen_store_flags(ctx.flags | DELAY_SLOT_CLEARME);
823029f9
TS
1925 }
1926 gen_goto_tb(&ctx, 0, ctx.pc);
1927 break;
1928 case BS_EXCP:
1929 /* gen_op_interrupt_restart(); */
57fec1fe 1930 tcg_gen_exit_tb(0);
823029f9
TS
1931 break;
1932 case BS_BRANCH:
1933 default:
1934 break;
1935 }
fdf9b3e8 1936 }
823029f9 1937
806f352d 1938 gen_tb_end(tb, num_insns);
0a7df5da 1939
355fb23d 1940 if (search_pc) {
fe700adb 1941 i = tcg_op_buf_count();
355fb23d
PB
1942 ii++;
1943 while (ii <= i)
ab1103de 1944 tcg_ctx.gen_opc_instr_start[ii++] = 0;
355fb23d
PB
1945 } else {
1946 tb->size = ctx.pc - pc_start;
2e70f6ef 1947 tb->icount = num_insns;
355fb23d 1948 }
fdf9b3e8
FB
1949
1950#ifdef DEBUG_DISAS
8fec2b8c 1951 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39 1952 qemu_log("IN:\n"); /* , lookup_symbol(pc_start)); */
d49190c4 1953 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
93fcfe39 1954 qemu_log("\n");
fdf9b3e8 1955 }
fdf9b3e8 1956#endif
fdf9b3e8
FB
1957}
1958
73e5716c 1959void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
fdf9b3e8 1960{
38e30810 1961 gen_intermediate_code_internal(sh_env_get_cpu(env), tb, false);
fdf9b3e8
FB
1962}
1963
73e5716c 1964void gen_intermediate_code_pc(CPUSH4State * env, struct TranslationBlock *tb)
fdf9b3e8 1965{
38e30810 1966 gen_intermediate_code_internal(sh_env_get_cpu(env), tb, true);
fdf9b3e8 1967}
d2856f1a 1968
73e5716c 1969void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, int pc_pos)
d2856f1a 1970{
25983cad 1971 env->pc = tcg_ctx.gen_opc_pc[pc_pos];
d2856f1a
AJ
1972 env->flags = gen_opc_hflags[pc_pos];
1973}