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