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