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