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