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