]> git.proxmox.com Git - mirror_qemu.git/blame - target/sh4/translate.c
target/sh4: Unify code for CHECK_PRIVILEGED
[mirror_qemu.git] / target / sh4 / translate.c
CommitLineData
fdf9b3e8
FB
1/*
2 * SH4 translation
5fafdf24 3 *
fdf9b3e8
FB
4 * Copyright (c) 2005 Samuel Tardieu
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
fdf9b3e8 18 */
fdf9b3e8
FB
19
20#define DEBUG_DISAS
fdf9b3e8 21
9d4c9946 22#include "qemu/osdep.h"
fdf9b3e8 23#include "cpu.h"
76cad711 24#include "disas/disas.h"
63c91552 25#include "exec/exec-all.h"
57fec1fe 26#include "tcg-op.h"
f08b6170 27#include "exec/cpu_ldst.h"
fdf9b3e8 28
2ef6175a
RH
29#include "exec/helper-proto.h"
30#include "exec/helper-gen.h"
a7812ae4 31
a7e30d84 32#include "trace-tcg.h"
508127e2 33#include "exec/log.h"
a7e30d84
LV
34
35
fdf9b3e8
FB
36typedef struct DisasContext {
37 struct TranslationBlock *tb;
38 target_ulong pc;
fdf9b3e8 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 43 int memidx;
3a3bb8d2 44 int gbank;
5c13bad9 45 int fbank;
fdf9b3e8
FB
46 uint32_t delayed_pc;
47 int singlestep_enabled;
71968fa6 48 uint32_t features;
852d481f 49 int has_movcal;
fdf9b3e8
FB
50} DisasContext;
51
fe25591e
AJ
52#if defined(CONFIG_USER_ONLY)
53#define IS_USER(ctx) 1
54#else
a6215749 55#define IS_USER(ctx) (!(ctx->tbflags & (1u << SR_MD)))
fe25591e
AJ
56#endif
57
823029f9
TS
58enum {
59 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
60 * exception condition
61 */
62 BS_STOP = 1, /* We want to stop translation for any reason */
63 BS_BRANCH = 2, /* We reached a branch condition */
64 BS_EXCP = 3, /* We reached an exception condition */
65};
66
1e8864f7 67/* global register indexes */
1bcea73e 68static TCGv_env cpu_env;
3a3bb8d2 69static TCGv cpu_gregs[32];
1d565b21
AJ
70static TCGv cpu_sr, cpu_sr_m, cpu_sr_q, cpu_sr_t;
71static TCGv cpu_pc, cpu_ssr, cpu_spc, cpu_gbr;
3a8a44c4 72static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl;
66c7c806 73static TCGv cpu_pr, cpu_fpscr, cpu_fpul, cpu_ldst;
66ba317c 74static TCGv cpu_fregs[32];
1000822b
AJ
75
76/* internal register indexes */
47b9f4d5 77static TCGv cpu_flags, cpu_delayed_pc, cpu_delayed_cond;
1e8864f7 78
022c62cb 79#include "exec/gen-icount.h"
2e70f6ef 80
aa7408ec 81void sh4_translate_init(void)
2e70f6ef 82{
1e8864f7 83 int i;
2e70f6ef 84 static int done_init = 0;
559dd74d 85 static const char * const gregnames[24] = {
1e8864f7
AJ
86 "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
87 "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
88 "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
89 "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
90 "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
91 };
66ba317c
AJ
92 static const char * const fregnames[32] = {
93 "FPR0_BANK0", "FPR1_BANK0", "FPR2_BANK0", "FPR3_BANK0",
94 "FPR4_BANK0", "FPR5_BANK0", "FPR6_BANK0", "FPR7_BANK0",
95 "FPR8_BANK0", "FPR9_BANK0", "FPR10_BANK0", "FPR11_BANK0",
96 "FPR12_BANK0", "FPR13_BANK0", "FPR14_BANK0", "FPR15_BANK0",
97 "FPR0_BANK1", "FPR1_BANK1", "FPR2_BANK1", "FPR3_BANK1",
98 "FPR4_BANK1", "FPR5_BANK1", "FPR6_BANK1", "FPR7_BANK1",
99 "FPR8_BANK1", "FPR9_BANK1", "FPR10_BANK1", "FPR11_BANK1",
100 "FPR12_BANK1", "FPR13_BANK1", "FPR14_BANK1", "FPR15_BANK1",
101 };
1e8864f7 102
3a3bb8d2 103 if (done_init) {
2e70f6ef 104 return;
3a3bb8d2 105 }
1e8864f7 106
a7812ae4 107 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7c255043 108 tcg_ctx.tcg_env = cpu_env;
1e8864f7 109
3a3bb8d2 110 for (i = 0; i < 24; i++) {
e1ccc054 111 cpu_gregs[i] = tcg_global_mem_new_i32(cpu_env,
73e5716c 112 offsetof(CPUSH4State, gregs[i]),
66ba317c 113 gregnames[i]);
3a3bb8d2
RH
114 }
115 memcpy(cpu_gregs + 24, cpu_gregs + 8, 8 * sizeof(TCGv));
988d7eaa 116
e1ccc054 117 cpu_pc = tcg_global_mem_new_i32(cpu_env,
73e5716c 118 offsetof(CPUSH4State, pc), "PC");
e1ccc054 119 cpu_sr = tcg_global_mem_new_i32(cpu_env,
73e5716c 120 offsetof(CPUSH4State, sr), "SR");
e1ccc054
RH
121 cpu_sr_m = tcg_global_mem_new_i32(cpu_env,
122 offsetof(CPUSH4State, sr_m), "SR_M");
123 cpu_sr_q = tcg_global_mem_new_i32(cpu_env,
124 offsetof(CPUSH4State, sr_q), "SR_Q");
125 cpu_sr_t = tcg_global_mem_new_i32(cpu_env,
126 offsetof(CPUSH4State, sr_t), "SR_T");
127 cpu_ssr = tcg_global_mem_new_i32(cpu_env,
73e5716c 128 offsetof(CPUSH4State, ssr), "SSR");
e1ccc054 129 cpu_spc = tcg_global_mem_new_i32(cpu_env,
73e5716c 130 offsetof(CPUSH4State, spc), "SPC");
e1ccc054 131 cpu_gbr = tcg_global_mem_new_i32(cpu_env,
73e5716c 132 offsetof(CPUSH4State, gbr), "GBR");
e1ccc054 133 cpu_vbr = tcg_global_mem_new_i32(cpu_env,
73e5716c 134 offsetof(CPUSH4State, vbr), "VBR");
e1ccc054 135 cpu_sgr = tcg_global_mem_new_i32(cpu_env,
73e5716c 136 offsetof(CPUSH4State, sgr), "SGR");
e1ccc054 137 cpu_dbr = tcg_global_mem_new_i32(cpu_env,
73e5716c 138 offsetof(CPUSH4State, dbr), "DBR");
e1ccc054 139 cpu_mach = tcg_global_mem_new_i32(cpu_env,
73e5716c 140 offsetof(CPUSH4State, mach), "MACH");
e1ccc054 141 cpu_macl = tcg_global_mem_new_i32(cpu_env,
73e5716c 142 offsetof(CPUSH4State, macl), "MACL");
e1ccc054 143 cpu_pr = tcg_global_mem_new_i32(cpu_env,
73e5716c 144 offsetof(CPUSH4State, pr), "PR");
e1ccc054 145 cpu_fpscr = tcg_global_mem_new_i32(cpu_env,
73e5716c 146 offsetof(CPUSH4State, fpscr), "FPSCR");
e1ccc054 147 cpu_fpul = tcg_global_mem_new_i32(cpu_env,
73e5716c 148 offsetof(CPUSH4State, fpul), "FPUL");
a7812ae4 149
e1ccc054 150 cpu_flags = tcg_global_mem_new_i32(cpu_env,
73e5716c 151 offsetof(CPUSH4State, flags), "_flags_");
e1ccc054 152 cpu_delayed_pc = tcg_global_mem_new_i32(cpu_env,
73e5716c 153 offsetof(CPUSH4State, delayed_pc),
a7812ae4 154 "_delayed_pc_");
47b9f4d5
AJ
155 cpu_delayed_cond = tcg_global_mem_new_i32(cpu_env,
156 offsetof(CPUSH4State,
157 delayed_cond),
158 "_delayed_cond_");
e1ccc054 159 cpu_ldst = tcg_global_mem_new_i32(cpu_env,
73e5716c 160 offsetof(CPUSH4State, ldst), "_ldst_");
1000822b 161
66ba317c 162 for (i = 0; i < 32; i++)
e1ccc054 163 cpu_fregs[i] = tcg_global_mem_new_i32(cpu_env,
73e5716c 164 offsetof(CPUSH4State, fregs[i]),
66ba317c
AJ
165 fregnames[i]);
166
2e70f6ef
PB
167 done_init = 1;
168}
169
878096ee
AF
170void superh_cpu_dump_state(CPUState *cs, FILE *f,
171 fprintf_function cpu_fprintf, int flags)
fdf9b3e8 172{
878096ee
AF
173 SuperHCPU *cpu = SUPERH_CPU(cs);
174 CPUSH4State *env = &cpu->env;
fdf9b3e8 175 int i;
eda9b09b 176 cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
34086945 177 env->pc, cpu_read_sr(env), env->pr, env->fpscr);
274a9e70
AJ
178 cpu_fprintf(f, "spc=0x%08x ssr=0x%08x gbr=0x%08x vbr=0x%08x\n",
179 env->spc, env->ssr, env->gbr, env->vbr);
180 cpu_fprintf(f, "sgr=0x%08x dbr=0x%08x delayed_pc=0x%08x fpul=0x%08x\n",
181 env->sgr, env->dbr, env->delayed_pc, env->fpul);
fdf9b3e8
FB
182 for (i = 0; i < 24; i += 4) {
183 cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
184 i, env->gregs[i], i + 1, env->gregs[i + 1],
185 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
186 }
187 if (env->flags & DELAY_SLOT) {
188 cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
189 env->delayed_pc);
190 } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
191 cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
192 env->delayed_pc);
be53081a
AJ
193 } else if (env->flags & DELAY_SLOT_RTE) {
194 cpu_fprintf(f, "in rte delay slot (delayed_pc=0x%08x)\n",
195 env->delayed_pc);
fdf9b3e8
FB
196 }
197}
198
34086945
AJ
199static void gen_read_sr(TCGv dst)
200{
1d565b21
AJ
201 TCGv t0 = tcg_temp_new();
202 tcg_gen_shli_i32(t0, cpu_sr_q, SR_Q);
203 tcg_gen_or_i32(dst, dst, t0);
204 tcg_gen_shli_i32(t0, cpu_sr_m, SR_M);
205 tcg_gen_or_i32(dst, dst, t0);
206 tcg_gen_shli_i32(t0, cpu_sr_t, SR_T);
207 tcg_gen_or_i32(dst, cpu_sr, t0);
208 tcg_temp_free_i32(t0);
34086945
AJ
209}
210
211static void gen_write_sr(TCGv src)
212{
1d565b21
AJ
213 tcg_gen_andi_i32(cpu_sr, src,
214 ~((1u << SR_Q) | (1u << SR_M) | (1u << SR_T)));
a380f9db
AJ
215 tcg_gen_extract_i32(cpu_sr_q, src, SR_Q, 1);
216 tcg_gen_extract_i32(cpu_sr_m, src, SR_M, 1);
217 tcg_gen_extract_i32(cpu_sr_t, src, SR_T, 1);
34086945
AJ
218}
219
ac9707ea
AJ
220static inline void gen_save_cpu_state(DisasContext *ctx, bool save_pc)
221{
222 if (save_pc) {
223 tcg_gen_movi_i32(cpu_pc, ctx->pc);
224 }
225 if (ctx->delayed_pc != (uint32_t) -1) {
226 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
227 }
e1933d14 228 if ((ctx->tbflags & TB_FLAG_ENVFLAGS_MASK) != ctx->envflags) {
ac9707ea
AJ
229 tcg_gen_movi_i32(cpu_flags, ctx->envflags);
230 }
231}
232
90aa39a1 233static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
fdf9b3e8 234{
90aa39a1
SF
235 if (unlikely(ctx->singlestep_enabled)) {
236 return false;
237 }
4bfa602b
RH
238 if (ctx->tbflags & GUSA_EXCLUSIVE) {
239 return false;
240 }
90aa39a1
SF
241#ifndef CONFIG_USER_ONLY
242 return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
243#else
244 return true;
245#endif
246}
fdf9b3e8 247
90aa39a1
SF
248static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
249{
250 if (use_goto_tb(ctx, dest)) {
fdf9b3e8 251 /* Use a direct jump if in same page and singlestep not enabled */
57fec1fe 252 tcg_gen_goto_tb(n);
3a8a44c4 253 tcg_gen_movi_i32(cpu_pc, dest);
90aa39a1 254 tcg_gen_exit_tb((uintptr_t)ctx->tb + n);
fdf9b3e8 255 } else {
3a8a44c4 256 tcg_gen_movi_i32(cpu_pc, dest);
57fec1fe 257 if (ctx->singlestep_enabled)
485d0035 258 gen_helper_debug(cpu_env);
57fec1fe 259 tcg_gen_exit_tb(0);
fdf9b3e8 260 }
fdf9b3e8
FB
261}
262
fdf9b3e8
FB
263static void gen_jump(DisasContext * ctx)
264{
265 if (ctx->delayed_pc == (uint32_t) - 1) {
266 /* Target is not statically known, it comes necessarily from a
267 delayed jump as immediate jump are conditinal jumps */
1000822b 268 tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc);
ac9707ea 269 tcg_gen_discard_i32(cpu_delayed_pc);
fdf9b3e8 270 if (ctx->singlestep_enabled)
485d0035 271 gen_helper_debug(cpu_env);
57fec1fe 272 tcg_gen_exit_tb(0);
fdf9b3e8
FB
273 } else {
274 gen_goto_tb(ctx, 0, ctx->delayed_pc);
275 }
276}
277
278/* Immediate conditional jump (bt or bf) */
4bfa602b
RH
279static void gen_conditional_jump(DisasContext *ctx, target_ulong dest,
280 bool jump_if_true)
fdf9b3e8 281{
34086945 282 TCGLabel *l1 = gen_new_label();
4bfa602b
RH
283 TCGCond cond_not_taken = jump_if_true ? TCG_COND_EQ : TCG_COND_NE;
284
285 if (ctx->tbflags & GUSA_EXCLUSIVE) {
286 /* When in an exclusive region, we must continue to the end.
287 Therefore, exit the region on a taken branch, but otherwise
288 fall through to the next instruction. */
289 tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
290 tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK);
291 /* Note that this won't actually use a goto_tb opcode because we
292 disallow it in use_goto_tb, but it handles exit + singlestep. */
293 gen_goto_tb(ctx, 0, dest);
294 gen_set_label(l1);
295 return;
296 }
297
ac9707ea 298 gen_save_cpu_state(ctx, false);
4bfa602b
RH
299 tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
300 gen_goto_tb(ctx, 0, dest);
fdf9b3e8 301 gen_set_label(l1);
4bfa602b 302 gen_goto_tb(ctx, 1, ctx->pc + 2);
b3995c23 303 ctx->bstate = BS_BRANCH;
fdf9b3e8
FB
304}
305
306/* Delayed conditional jump (bt or bf) */
307static void gen_delayed_conditional_jump(DisasContext * ctx)
308{
4bfa602b
RH
309 TCGLabel *l1 = gen_new_label();
310 TCGv ds = tcg_temp_new();
fdf9b3e8 311
47b9f4d5
AJ
312 tcg_gen_mov_i32(ds, cpu_delayed_cond);
313 tcg_gen_discard_i32(cpu_delayed_cond);
4bfa602b
RH
314
315 if (ctx->tbflags & GUSA_EXCLUSIVE) {
316 /* When in an exclusive region, we must continue to the end.
317 Therefore, exit the region on a taken branch, but otherwise
318 fall through to the next instruction. */
319 tcg_gen_brcondi_i32(TCG_COND_EQ, ds, 0, l1);
320
321 /* Leave the gUSA region. */
322 tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK);
323 gen_jump(ctx);
324
325 gen_set_label(l1);
326 return;
327 }
328
6f396c8f 329 tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
823029f9 330 gen_goto_tb(ctx, 1, ctx->pc + 2);
fdf9b3e8 331 gen_set_label(l1);
9c2a9ea1 332 gen_jump(ctx);
fdf9b3e8
FB
333}
334
e5d8053e 335static inline void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
cc4ba6a9 336{
1e0b21d8
RH
337 /* We have already signaled illegal instruction for odd Dr. */
338 tcg_debug_assert((reg & 1) == 0);
339 reg ^= ctx->fbank;
66ba317c 340 tcg_gen_concat_i32_i64(t, cpu_fregs[reg + 1], cpu_fregs[reg]);
cc4ba6a9
AJ
341}
342
e5d8053e 343static inline void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
cc4ba6a9 344{
1e0b21d8
RH
345 /* We have already signaled illegal instruction for odd Dr. */
346 tcg_debug_assert((reg & 1) == 0);
347 reg ^= ctx->fbank;
58d2a9ae 348 tcg_gen_extr_i64_i32(cpu_fregs[reg + 1], cpu_fregs[reg], t);
cc4ba6a9
AJ
349}
350
fdf9b3e8
FB
351#define B3_0 (ctx->opcode & 0xf)
352#define B6_4 ((ctx->opcode >> 4) & 0x7)
353#define B7_4 ((ctx->opcode >> 4) & 0xf)
354#define B7_0 (ctx->opcode & 0xff)
355#define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
356#define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
357 (ctx->opcode & 0xfff))
358#define B11_8 ((ctx->opcode >> 8) & 0xf)
359#define B15_12 ((ctx->opcode >> 12) & 0xf)
360
3a3bb8d2
RH
361#define REG(x) cpu_gregs[(x) ^ ctx->gbank]
362#define ALTREG(x) cpu_gregs[(x) ^ ctx->gbank ^ 0x10]
5c13bad9 363#define FREG(x) cpu_fregs[(x) ^ ctx->fbank]
fdf9b3e8 364
f09111e0 365#define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
eda9b09b 366
fdf9b3e8 367#define CHECK_NOT_DELAY_SLOT \
dec16c6e
RH
368 if (ctx->envflags & DELAY_SLOT_MASK) { \
369 goto do_illegal_slot; \
a6215749
AJ
370 }
371
6b98213d
RH
372#define CHECK_PRIVILEGED \
373 if (IS_USER(ctx)) { \
374 goto do_illegal; \
a6215749
AJ
375 }
376
377#define CHECK_FPU_ENABLED \
378 if (ctx->tbflags & (1u << SR_FD)) { \
ac9707ea 379 gen_save_cpu_state(ctx, true); \
9a562ae7 380 if (ctx->envflags & DELAY_SLOT_MASK) { \
a6215749
AJ
381 gen_helper_raise_slot_fpu_disable(cpu_env); \
382 } else { \
383 gen_helper_raise_fpu_disable(cpu_env); \
384 } \
63205665 385 ctx->bstate = BS_EXCP; \
a6215749
AJ
386 return; \
387 }
d8299bcc 388
b1d8e52e 389static void _decode_opc(DisasContext * ctx)
fdf9b3e8 390{
852d481f
EI
391 /* This code tries to make movcal emulation sufficiently
392 accurate for Linux purposes. This instruction writes
393 memory, and prior to that, always allocates a cache line.
394 It is used in two contexts:
395 - in memcpy, where data is copied in blocks, the first write
396 of to a block uses movca.l for performance.
397 - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used
398 to flush the cache. Here, the data written by movcal.l is never
399 written to memory, and the data written is just bogus.
400
401 To simulate this, we simulate movcal.l, we store the value to memory,
402 but we also remember the previous content. If we see ocbi, we check
403 if movcal.l for that address was done previously. If so, the write should
404 not have hit the memory, so we restore the previous content.
405 When we see an instruction that is neither movca.l
406 nor ocbi, the previous content is discarded.
407
408 To optimize, we only try to flush stores when we're at the start of
409 TB, or if we already saw movca.l in this TB and did not flush stores
410 yet. */
411 if (ctx->has_movcal)
412 {
413 int opcode = ctx->opcode & 0xf0ff;
414 if (opcode != 0x0093 /* ocbi */
415 && opcode != 0x00c3 /* movca.l */)
416 {
485d0035 417 gen_helper_discard_movcal_backup(cpu_env);
852d481f
EI
418 ctx->has_movcal = 0;
419 }
420 }
421
fdf9b3e8
FB
422#if 0
423 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
424#endif
f6198371 425
fdf9b3e8
FB
426 switch (ctx->opcode) {
427 case 0x0019: /* div0u */
1d565b21
AJ
428 tcg_gen_movi_i32(cpu_sr_m, 0);
429 tcg_gen_movi_i32(cpu_sr_q, 0);
34086945 430 tcg_gen_movi_i32(cpu_sr_t, 0);
fdf9b3e8
FB
431 return;
432 case 0x000b: /* rts */
1000822b
AJ
433 CHECK_NOT_DELAY_SLOT
434 tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
a6215749 435 ctx->envflags |= DELAY_SLOT;
fdf9b3e8
FB
436 ctx->delayed_pc = (uint32_t) - 1;
437 return;
438 case 0x0028: /* clrmac */
3a8a44c4
AJ
439 tcg_gen_movi_i32(cpu_mach, 0);
440 tcg_gen_movi_i32(cpu_macl, 0);
fdf9b3e8
FB
441 return;
442 case 0x0048: /* clrs */
5ed9a259 443 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(1u << SR_S));
fdf9b3e8
FB
444 return;
445 case 0x0008: /* clrt */
34086945 446 tcg_gen_movi_i32(cpu_sr_t, 0);
fdf9b3e8
FB
447 return;
448 case 0x0038: /* ldtlb */
fe25591e 449 CHECK_PRIVILEGED
485d0035 450 gen_helper_ldtlb(cpu_env);
fdf9b3e8 451 return;
c5e814b2 452 case 0x002b: /* rte */
fe25591e 453 CHECK_PRIVILEGED
1000822b 454 CHECK_NOT_DELAY_SLOT
34086945 455 gen_write_sr(cpu_ssr);
1000822b 456 tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
be53081a 457 ctx->envflags |= DELAY_SLOT_RTE;
fdf9b3e8 458 ctx->delayed_pc = (uint32_t) - 1;
be53081a 459 ctx->bstate = BS_STOP;
fdf9b3e8
FB
460 return;
461 case 0x0058: /* sets */
5ed9a259 462 tcg_gen_ori_i32(cpu_sr, cpu_sr, (1u << SR_S));
fdf9b3e8
FB
463 return;
464 case 0x0018: /* sett */
34086945 465 tcg_gen_movi_i32(cpu_sr_t, 1);
fdf9b3e8 466 return;
24988dc2 467 case 0xfbfd: /* frchg */
6f06939b 468 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
823029f9 469 ctx->bstate = BS_STOP;
fdf9b3e8 470 return;
24988dc2 471 case 0xf3fd: /* fschg */
7a64244f 472 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ);
823029f9 473 ctx->bstate = BS_STOP;
fdf9b3e8
FB
474 return;
475 case 0x0009: /* nop */
476 return;
477 case 0x001b: /* sleep */
fe25591e 478 CHECK_PRIVILEGED
10127400
AJ
479 tcg_gen_movi_i32(cpu_pc, ctx->pc + 2);
480 gen_helper_sleep(cpu_env);
fdf9b3e8
FB
481 return;
482 }
483
484 switch (ctx->opcode & 0xf000) {
485 case 0x1000: /* mov.l Rm,@(disp,Rn) */
c55497ec 486 {
a7812ae4 487 TCGv addr = tcg_temp_new();
c55497ec 488 tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
3376f415 489 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
c55497ec
AJ
490 tcg_temp_free(addr);
491 }
fdf9b3e8
FB
492 return;
493 case 0x5000: /* mov.l @(disp,Rm),Rn */
c55497ec 494 {
a7812ae4 495 TCGv addr = tcg_temp_new();
c55497ec 496 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
3376f415 497 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
c55497ec
AJ
498 tcg_temp_free(addr);
499 }
fdf9b3e8 500 return;
24988dc2 501 case 0xe000: /* mov #imm,Rn */
4bfa602b
RH
502#ifdef CONFIG_USER_ONLY
503 /* Detect the start of a gUSA region. If so, update envflags
504 and end the TB. This will allow us to see the end of the
505 region (stored in R0) in the next TB. */
506 if (B11_8 == 15 && B7_0s < 0 && parallel_cpus) {
507 ctx->envflags = deposit32(ctx->envflags, GUSA_SHIFT, 8, B7_0s);
508 ctx->bstate = BS_STOP;
509 }
510#endif
7efbe241 511 tcg_gen_movi_i32(REG(B11_8), B7_0s);
fdf9b3e8
FB
512 return;
513 case 0x9000: /* mov.w @(disp,PC),Rn */
c55497ec
AJ
514 {
515 TCGv addr = tcg_const_i32(ctx->pc + 4 + B7_0 * 2);
3376f415 516 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW);
c55497ec
AJ
517 tcg_temp_free(addr);
518 }
fdf9b3e8
FB
519 return;
520 case 0xd000: /* mov.l @(disp,PC),Rn */
c55497ec
AJ
521 {
522 TCGv addr = tcg_const_i32((ctx->pc + 4 + B7_0 * 4) & ~3);
3376f415 523 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
c55497ec
AJ
524 tcg_temp_free(addr);
525 }
fdf9b3e8 526 return;
24988dc2 527 case 0x7000: /* add #imm,Rn */
7efbe241 528 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s);
fdf9b3e8
FB
529 return;
530 case 0xa000: /* bra disp */
531 CHECK_NOT_DELAY_SLOT
1000822b 532 ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
a6215749 533 ctx->envflags |= DELAY_SLOT;
fdf9b3e8
FB
534 return;
535 case 0xb000: /* bsr disp */
536 CHECK_NOT_DELAY_SLOT
1000822b
AJ
537 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
538 ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
a6215749 539 ctx->envflags |= DELAY_SLOT;
fdf9b3e8
FB
540 return;
541 }
542
543 switch (ctx->opcode & 0xf00f) {
544 case 0x6003: /* mov Rm,Rn */
7efbe241 545 tcg_gen_mov_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
546 return;
547 case 0x2000: /* mov.b Rm,@Rn */
3376f415 548 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB);
fdf9b3e8
FB
549 return;
550 case 0x2001: /* mov.w Rm,@Rn */
3376f415 551 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUW);
fdf9b3e8
FB
552 return;
553 case 0x2002: /* mov.l Rm,@Rn */
3376f415 554 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL);
fdf9b3e8
FB
555 return;
556 case 0x6000: /* mov.b @Rm,Rn */
3376f415 557 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
fdf9b3e8
FB
558 return;
559 case 0x6001: /* mov.w @Rm,Rn */
3376f415 560 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW);
fdf9b3e8
FB
561 return;
562 case 0x6002: /* mov.l @Rm,Rn */
3376f415 563 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL);
fdf9b3e8
FB
564 return;
565 case 0x2004: /* mov.b Rm,@-Rn */
c55497ec 566 {
a7812ae4 567 TCGv addr = tcg_temp_new();
c55497ec 568 tcg_gen_subi_i32(addr, REG(B11_8), 1);
3376f415
AJ
569 /* might cause re-execution */
570 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB);
3101e99c 571 tcg_gen_mov_i32(REG(B11_8), addr); /* modify register status */
c55497ec
AJ
572 tcg_temp_free(addr);
573 }
fdf9b3e8
FB
574 return;
575 case 0x2005: /* mov.w Rm,@-Rn */
c55497ec 576 {
a7812ae4 577 TCGv addr = tcg_temp_new();
c55497ec 578 tcg_gen_subi_i32(addr, REG(B11_8), 2);
3376f415 579 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW);
3101e99c 580 tcg_gen_mov_i32(REG(B11_8), addr);
c55497ec
AJ
581 tcg_temp_free(addr);
582 }
fdf9b3e8
FB
583 return;
584 case 0x2006: /* mov.l Rm,@-Rn */
c55497ec 585 {
a7812ae4 586 TCGv addr = tcg_temp_new();
c55497ec 587 tcg_gen_subi_i32(addr, REG(B11_8), 4);
3376f415 588 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
3101e99c 589 tcg_gen_mov_i32(REG(B11_8), addr);
c55497ec 590 }
fdf9b3e8 591 return;
eda9b09b 592 case 0x6004: /* mov.b @Rm+,Rn */
3376f415 593 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
24988dc2 594 if ( B11_8 != B7_4 )
7efbe241 595 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1);
fdf9b3e8
FB
596 return;
597 case 0x6005: /* mov.w @Rm+,Rn */
3376f415 598 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW);
24988dc2 599 if ( B11_8 != B7_4 )
7efbe241 600 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
fdf9b3e8
FB
601 return;
602 case 0x6006: /* mov.l @Rm+,Rn */
3376f415 603 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL);
24988dc2 604 if ( B11_8 != B7_4 )
7efbe241 605 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
fdf9b3e8
FB
606 return;
607 case 0x0004: /* mov.b Rm,@(R0,Rn) */
c55497ec 608 {
a7812ae4 609 TCGv addr = tcg_temp_new();
c55497ec 610 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
3376f415 611 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB);
c55497ec
AJ
612 tcg_temp_free(addr);
613 }
fdf9b3e8
FB
614 return;
615 case 0x0005: /* mov.w Rm,@(R0,Rn) */
c55497ec 616 {
a7812ae4 617 TCGv addr = tcg_temp_new();
c55497ec 618 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
3376f415 619 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW);
c55497ec
AJ
620 tcg_temp_free(addr);
621 }
fdf9b3e8
FB
622 return;
623 case 0x0006: /* mov.l Rm,@(R0,Rn) */
c55497ec 624 {
a7812ae4 625 TCGv addr = tcg_temp_new();
c55497ec 626 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
3376f415 627 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
c55497ec
AJ
628 tcg_temp_free(addr);
629 }
fdf9b3e8
FB
630 return;
631 case 0x000c: /* mov.b @(R0,Rm),Rn */
c55497ec 632 {
a7812ae4 633 TCGv addr = tcg_temp_new();
c55497ec 634 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
3376f415 635 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_SB);
c55497ec
AJ
636 tcg_temp_free(addr);
637 }
fdf9b3e8
FB
638 return;
639 case 0x000d: /* mov.w @(R0,Rm),Rn */
c55497ec 640 {
a7812ae4 641 TCGv addr = tcg_temp_new();
c55497ec 642 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
3376f415 643 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW);
c55497ec
AJ
644 tcg_temp_free(addr);
645 }
fdf9b3e8
FB
646 return;
647 case 0x000e: /* mov.l @(R0,Rm),Rn */
c55497ec 648 {
a7812ae4 649 TCGv addr = tcg_temp_new();
c55497ec 650 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
3376f415 651 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
c55497ec
AJ
652 tcg_temp_free(addr);
653 }
fdf9b3e8
FB
654 return;
655 case 0x6008: /* swap.b Rm,Rn */
c55497ec 656 {
218fd730 657 TCGv low = tcg_temp_new();;
3101e99c
AJ
658 tcg_gen_ext16u_i32(low, REG(B7_4));
659 tcg_gen_bswap16_i32(low, low);
218fd730 660 tcg_gen_deposit_i32(REG(B11_8), REG(B7_4), low, 0, 16);
c55497ec 661 tcg_temp_free(low);
c55497ec 662 }
fdf9b3e8
FB
663 return;
664 case 0x6009: /* swap.w Rm,Rn */
c53b36d2 665 tcg_gen_rotli_i32(REG(B11_8), REG(B7_4), 16);
fdf9b3e8
FB
666 return;
667 case 0x200d: /* xtrct Rm,Rn */
c55497ec
AJ
668 {
669 TCGv high, low;
a7812ae4 670 high = tcg_temp_new();
3101e99c 671 tcg_gen_shli_i32(high, REG(B7_4), 16);
a7812ae4 672 low = tcg_temp_new();
c55497ec 673 tcg_gen_shri_i32(low, REG(B11_8), 16);
c55497ec
AJ
674 tcg_gen_or_i32(REG(B11_8), high, low);
675 tcg_temp_free(low);
676 tcg_temp_free(high);
677 }
fdf9b3e8
FB
678 return;
679 case 0x300c: /* add Rm,Rn */
7efbe241 680 tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8
FB
681 return;
682 case 0x300e: /* addc Rm,Rn */
22b88fd7 683 {
34086945 684 TCGv t0, t1;
a2368e01 685 t0 = tcg_const_tl(0);
22b88fd7 686 t1 = tcg_temp_new();
a2368e01
AJ
687 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0);
688 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t,
689 REG(B11_8), t0, t1, cpu_sr_t);
22b88fd7 690 tcg_temp_free(t0);
34086945 691 tcg_temp_free(t1);
22b88fd7 692 }
fdf9b3e8
FB
693 return;
694 case 0x300f: /* addv Rm,Rn */
ad8d25a1
AJ
695 {
696 TCGv t0, t1, t2;
697 t0 = tcg_temp_new();
698 tcg_gen_add_i32(t0, REG(B7_4), REG(B11_8));
699 t1 = tcg_temp_new();
700 tcg_gen_xor_i32(t1, t0, REG(B11_8));
701 t2 = tcg_temp_new();
702 tcg_gen_xor_i32(t2, REG(B7_4), REG(B11_8));
34086945 703 tcg_gen_andc_i32(cpu_sr_t, t1, t2);
ad8d25a1 704 tcg_temp_free(t2);
34086945 705 tcg_gen_shri_i32(cpu_sr_t, cpu_sr_t, 31);
ad8d25a1
AJ
706 tcg_temp_free(t1);
707 tcg_gen_mov_i32(REG(B7_4), t0);
708 tcg_temp_free(t0);
709 }
fdf9b3e8
FB
710 return;
711 case 0x2009: /* and Rm,Rn */
7efbe241 712 tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8
FB
713 return;
714 case 0x3000: /* cmp/eq Rm,Rn */
34086945 715 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), REG(B7_4));
fdf9b3e8
FB
716 return;
717 case 0x3003: /* cmp/ge Rm,Rn */
34086945 718 tcg_gen_setcond_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), REG(B7_4));
fdf9b3e8
FB
719 return;
720 case 0x3007: /* cmp/gt Rm,Rn */
34086945 721 tcg_gen_setcond_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), REG(B7_4));
fdf9b3e8
FB
722 return;
723 case 0x3006: /* cmp/hi Rm,Rn */
34086945 724 tcg_gen_setcond_i32(TCG_COND_GTU, cpu_sr_t, REG(B11_8), REG(B7_4));
fdf9b3e8
FB
725 return;
726 case 0x3002: /* cmp/hs Rm,Rn */
34086945 727 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_sr_t, REG(B11_8), REG(B7_4));
fdf9b3e8
FB
728 return;
729 case 0x200c: /* cmp/str Rm,Rn */
69d6275b 730 {
c5c19137
AJ
731 TCGv cmp1 = tcg_temp_new();
732 TCGv cmp2 = tcg_temp_new();
eb6ca2b4
AJ
733 tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8));
734 tcg_gen_subi_i32(cmp1, cmp2, 0x01010101);
735 tcg_gen_andc_i32(cmp1, cmp1, cmp2);
736 tcg_gen_andi_i32(cmp1, cmp1, 0x80808080);
737 tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0);
c55497ec
AJ
738 tcg_temp_free(cmp2);
739 tcg_temp_free(cmp1);
69d6275b 740 }
fdf9b3e8
FB
741 return;
742 case 0x2007: /* div0s Rm,Rn */
1d565b21
AJ
743 tcg_gen_shri_i32(cpu_sr_q, REG(B11_8), 31); /* SR_Q */
744 tcg_gen_shri_i32(cpu_sr_m, REG(B7_4), 31); /* SR_M */
745 tcg_gen_xor_i32(cpu_sr_t, cpu_sr_q, cpu_sr_m); /* SR_T */
fdf9b3e8
FB
746 return;
747 case 0x3004: /* div1 Rm,Rn */
1d565b21
AJ
748 {
749 TCGv t0 = tcg_temp_new();
750 TCGv t1 = tcg_temp_new();
751 TCGv t2 = tcg_temp_new();
752 TCGv zero = tcg_const_i32(0);
753
754 /* shift left arg1, saving the bit being pushed out and inserting
755 T on the right */
756 tcg_gen_shri_i32(t0, REG(B11_8), 31);
757 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
758 tcg_gen_or_i32(REG(B11_8), REG(B11_8), cpu_sr_t);
759
760 /* Add or subtract arg0 from arg1 depending if Q == M. To avoid
761 using 64-bit temps, we compute arg0's high part from q ^ m, so
762 that it is 0x00000000 when adding the value or 0xffffffff when
763 subtracting it. */
764 tcg_gen_xor_i32(t1, cpu_sr_q, cpu_sr_m);
765 tcg_gen_subi_i32(t1, t1, 1);
766 tcg_gen_neg_i32(t2, REG(B7_4));
767 tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, zero, REG(B7_4), t2);
768 tcg_gen_add2_i32(REG(B11_8), t1, REG(B11_8), zero, t2, t1);
769
770 /* compute T and Q depending on carry */
771 tcg_gen_andi_i32(t1, t1, 1);
772 tcg_gen_xor_i32(t1, t1, t0);
773 tcg_gen_xori_i32(cpu_sr_t, t1, 1);
774 tcg_gen_xor_i32(cpu_sr_q, cpu_sr_m, t1);
775
776 tcg_temp_free(zero);
777 tcg_temp_free(t2);
778 tcg_temp_free(t1);
779 tcg_temp_free(t0);
780 }
fdf9b3e8
FB
781 return;
782 case 0x300d: /* dmuls.l Rm,Rn */
1d3b7084 783 tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
fdf9b3e8
FB
784 return;
785 case 0x3005: /* dmulu.l Rm,Rn */
1d3b7084 786 tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
fdf9b3e8
FB
787 return;
788 case 0x600e: /* exts.b Rm,Rn */
7efbe241 789 tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
790 return;
791 case 0x600f: /* exts.w Rm,Rn */
7efbe241 792 tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
793 return;
794 case 0x600c: /* extu.b Rm,Rn */
7efbe241 795 tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
796 return;
797 case 0x600d: /* extu.w Rm,Rn */
7efbe241 798 tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4));
fdf9b3e8 799 return;
24988dc2 800 case 0x000f: /* mac.l @Rm+,@Rn+ */
c55497ec
AJ
801 {
802 TCGv arg0, arg1;
a7812ae4 803 arg0 = tcg_temp_new();
3376f415 804 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL);
a7812ae4 805 arg1 = tcg_temp_new();
3376f415 806 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL);
485d0035 807 gen_helper_macl(cpu_env, arg0, arg1);
c55497ec
AJ
808 tcg_temp_free(arg1);
809 tcg_temp_free(arg0);
810 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
811 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
812 }
fdf9b3e8
FB
813 return;
814 case 0x400f: /* mac.w @Rm+,@Rn+ */
c55497ec
AJ
815 {
816 TCGv arg0, arg1;
a7812ae4 817 arg0 = tcg_temp_new();
3376f415 818 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL);
a7812ae4 819 arg1 = tcg_temp_new();
3376f415 820 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL);
485d0035 821 gen_helper_macw(cpu_env, arg0, arg1);
c55497ec
AJ
822 tcg_temp_free(arg1);
823 tcg_temp_free(arg0);
824 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2);
825 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
826 }
fdf9b3e8
FB
827 return;
828 case 0x0007: /* mul.l Rm,Rn */
7efbe241 829 tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8));
fdf9b3e8
FB
830 return;
831 case 0x200f: /* muls.w Rm,Rn */
c55497ec
AJ
832 {
833 TCGv arg0, arg1;
a7812ae4 834 arg0 = tcg_temp_new();
c55497ec 835 tcg_gen_ext16s_i32(arg0, REG(B7_4));
a7812ae4 836 arg1 = tcg_temp_new();
c55497ec
AJ
837 tcg_gen_ext16s_i32(arg1, REG(B11_8));
838 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
839 tcg_temp_free(arg1);
840 tcg_temp_free(arg0);
841 }
fdf9b3e8
FB
842 return;
843 case 0x200e: /* mulu.w Rm,Rn */
c55497ec
AJ
844 {
845 TCGv arg0, arg1;
a7812ae4 846 arg0 = tcg_temp_new();
c55497ec 847 tcg_gen_ext16u_i32(arg0, REG(B7_4));
a7812ae4 848 arg1 = tcg_temp_new();
c55497ec
AJ
849 tcg_gen_ext16u_i32(arg1, REG(B11_8));
850 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
851 tcg_temp_free(arg1);
852 tcg_temp_free(arg0);
853 }
fdf9b3e8
FB
854 return;
855 case 0x600b: /* neg Rm,Rn */
7efbe241 856 tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
857 return;
858 case 0x600a: /* negc Rm,Rn */
b2d9eda5 859 {
60eb27fe
AJ
860 TCGv t0 = tcg_const_i32(0);
861 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t,
862 REG(B7_4), t0, cpu_sr_t, t0);
863 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
864 t0, t0, REG(B11_8), cpu_sr_t);
865 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
b2d9eda5 866 tcg_temp_free(t0);
b2d9eda5 867 }
fdf9b3e8
FB
868 return;
869 case 0x6007: /* not Rm,Rn */
7efbe241 870 tcg_gen_not_i32(REG(B11_8), REG(B7_4));
fdf9b3e8
FB
871 return;
872 case 0x200b: /* or Rm,Rn */
7efbe241 873 tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8
FB
874 return;
875 case 0x400c: /* shad Rm,Rn */
69d6275b 876 {
be654c83
AJ
877 TCGv t0 = tcg_temp_new();
878 TCGv t1 = tcg_temp_new();
879 TCGv t2 = tcg_temp_new();
880
881 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
882
883 /* positive case: shift to the left */
884 tcg_gen_shl_i32(t1, REG(B11_8), t0);
885
886 /* negative case: shift to the right in two steps to
887 correctly handle the -32 case */
888 tcg_gen_xori_i32(t0, t0, 0x1f);
889 tcg_gen_sar_i32(t2, REG(B11_8), t0);
890 tcg_gen_sari_i32(t2, t2, 1);
891
892 /* select between the two cases */
893 tcg_gen_movi_i32(t0, 0);
894 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
895
896 tcg_temp_free(t0);
897 tcg_temp_free(t1);
898 tcg_temp_free(t2);
69d6275b 899 }
fdf9b3e8
FB
900 return;
901 case 0x400d: /* shld Rm,Rn */
69d6275b 902 {
57760161
AJ
903 TCGv t0 = tcg_temp_new();
904 TCGv t1 = tcg_temp_new();
905 TCGv t2 = tcg_temp_new();
906
907 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
908
909 /* positive case: shift to the left */
910 tcg_gen_shl_i32(t1, REG(B11_8), t0);
911
912 /* negative case: shift to the right in two steps to
913 correctly handle the -32 case */
914 tcg_gen_xori_i32(t0, t0, 0x1f);
915 tcg_gen_shr_i32(t2, REG(B11_8), t0);
916 tcg_gen_shri_i32(t2, t2, 1);
917
918 /* select between the two cases */
919 tcg_gen_movi_i32(t0, 0);
920 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
921
922 tcg_temp_free(t0);
923 tcg_temp_free(t1);
924 tcg_temp_free(t2);
69d6275b 925 }
fdf9b3e8
FB
926 return;
927 case 0x3008: /* sub Rm,Rn */
7efbe241 928 tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8
FB
929 return;
930 case 0x300a: /* subc Rm,Rn */
22b88fd7 931 {
d0f44a55
AJ
932 TCGv t0, t1;
933 t0 = tcg_const_tl(0);
22b88fd7 934 t1 = tcg_temp_new();
d0f44a55
AJ
935 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0);
936 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
937 REG(B11_8), t0, t1, cpu_sr_t);
938 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
22b88fd7 939 tcg_temp_free(t0);
d0f44a55 940 tcg_temp_free(t1);
22b88fd7 941 }
fdf9b3e8
FB
942 return;
943 case 0x300b: /* subv Rm,Rn */
ad8d25a1
AJ
944 {
945 TCGv t0, t1, t2;
946 t0 = tcg_temp_new();
947 tcg_gen_sub_i32(t0, REG(B11_8), REG(B7_4));
948 t1 = tcg_temp_new();
949 tcg_gen_xor_i32(t1, t0, REG(B7_4));
950 t2 = tcg_temp_new();
951 tcg_gen_xor_i32(t2, REG(B11_8), REG(B7_4));
952 tcg_gen_and_i32(t1, t1, t2);
953 tcg_temp_free(t2);
34086945 954 tcg_gen_shri_i32(cpu_sr_t, t1, 31);
ad8d25a1
AJ
955 tcg_temp_free(t1);
956 tcg_gen_mov_i32(REG(B11_8), t0);
957 tcg_temp_free(t0);
958 }
fdf9b3e8
FB
959 return;
960 case 0x2008: /* tst Rm,Rn */
c55497ec 961 {
a7812ae4 962 TCGv val = tcg_temp_new();
c55497ec 963 tcg_gen_and_i32(val, REG(B7_4), REG(B11_8));
34086945 964 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
c55497ec
AJ
965 tcg_temp_free(val);
966 }
fdf9b3e8
FB
967 return;
968 case 0x200a: /* xor Rm,Rn */
7efbe241 969 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4));
fdf9b3e8 970 return;
e67888a7 971 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
f6198371 972 CHECK_FPU_ENABLED
a6215749 973 if (ctx->tbflags & FPSCR_SZ) {
bdcb3739
RH
974 int xsrc = XHACK(B7_4);
975 int xdst = XHACK(B11_8);
976 tcg_gen_mov_i32(FREG(xdst), FREG(xsrc));
977 tcg_gen_mov_i32(FREG(xdst + 1), FREG(xsrc + 1));
eda9b09b 978 } else {
7c9f7038 979 tcg_gen_mov_i32(FREG(B11_8), FREG(B7_4));
eda9b09b
FB
980 }
981 return;
e67888a7 982 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
f6198371 983 CHECK_FPU_ENABLED
a6215749 984 if (ctx->tbflags & FPSCR_SZ) {
4d57fa50
RH
985 TCGv_i64 fp = tcg_temp_new_i64();
986 gen_load_fpr64(ctx, fp, XHACK(B7_4));
987 tcg_gen_qemu_st_i64(fp, REG(B11_8), ctx->memidx, MO_TEQ);
988 tcg_temp_free_i64(fp);
eda9b09b 989 } else {
7c9f7038 990 tcg_gen_qemu_st_i32(FREG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL);
eda9b09b
FB
991 }
992 return;
e67888a7 993 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
f6198371 994 CHECK_FPU_ENABLED
a6215749 995 if (ctx->tbflags & FPSCR_SZ) {
4d57fa50
RH
996 TCGv_i64 fp = tcg_temp_new_i64();
997 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEQ);
998 gen_store_fpr64(ctx, fp, XHACK(B11_8));
999 tcg_temp_free_i64(fp);
eda9b09b 1000 } else {
7c9f7038 1001 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx, MO_TEUL);
eda9b09b
FB
1002 }
1003 return;
e67888a7 1004 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
f6198371 1005 CHECK_FPU_ENABLED
a6215749 1006 if (ctx->tbflags & FPSCR_SZ) {
4d57fa50
RH
1007 TCGv_i64 fp = tcg_temp_new_i64();
1008 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEQ);
1009 gen_store_fpr64(ctx, fp, XHACK(B11_8));
1010 tcg_temp_free_i64(fp);
1011 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8);
eda9b09b 1012 } else {
7c9f7038 1013 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx, MO_TEUL);
cc4ba6a9 1014 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
eda9b09b
FB
1015 }
1016 return;
e67888a7 1017 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
f6198371 1018 CHECK_FPU_ENABLED
4d57fa50
RH
1019 {
1020 TCGv addr = tcg_temp_new_i32();
1021 if (ctx->tbflags & FPSCR_SZ) {
1022 TCGv_i64 fp = tcg_temp_new_i64();
1023 gen_load_fpr64(ctx, fp, XHACK(B7_4));
1024 tcg_gen_subi_i32(addr, REG(B11_8), 8);
1025 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEQ);
1026 tcg_temp_free_i64(fp);
1027 } else {
1028 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1029 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, MO_TEUL);
1030 }
1031 tcg_gen_mov_i32(REG(B11_8), addr);
1032 tcg_temp_free(addr);
1033 }
eda9b09b 1034 return;
e67888a7 1035 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
f6198371 1036 CHECK_FPU_ENABLED
cc4ba6a9 1037 {
a7812ae4 1038 TCGv addr = tcg_temp_new_i32();
cc4ba6a9 1039 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
a6215749 1040 if (ctx->tbflags & FPSCR_SZ) {
4d57fa50
RH
1041 TCGv_i64 fp = tcg_temp_new_i64();
1042 tcg_gen_qemu_ld_i64(fp, addr, ctx->memidx, MO_TEQ);
1043 gen_store_fpr64(ctx, fp, XHACK(B11_8));
1044 tcg_temp_free_i64(fp);
cc4ba6a9 1045 } else {
7c9f7038 1046 tcg_gen_qemu_ld_i32(FREG(B11_8), addr, ctx->memidx, MO_TEUL);
cc4ba6a9
AJ
1047 }
1048 tcg_temp_free(addr);
eda9b09b
FB
1049 }
1050 return;
e67888a7 1051 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
f6198371 1052 CHECK_FPU_ENABLED
cc4ba6a9 1053 {
a7812ae4 1054 TCGv addr = tcg_temp_new();
cc4ba6a9 1055 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
a6215749 1056 if (ctx->tbflags & FPSCR_SZ) {
4d57fa50
RH
1057 TCGv_i64 fp = tcg_temp_new_i64();
1058 gen_load_fpr64(ctx, fp, XHACK(B7_4));
1059 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEQ);
1060 tcg_temp_free_i64(fp);
cc4ba6a9 1061 } else {
7c9f7038 1062 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, MO_TEUL);
cc4ba6a9
AJ
1063 }
1064 tcg_temp_free(addr);
eda9b09b
FB
1065 }
1066 return;
e67888a7
TS
1067 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1068 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1069 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1070 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1071 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1072 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
cc4ba6a9 1073 {
f6198371 1074 CHECK_FPU_ENABLED
a6215749 1075 if (ctx->tbflags & FPSCR_PR) {
a7812ae4
PB
1076 TCGv_i64 fp0, fp1;
1077
cc4ba6a9
AJ
1078 if (ctx->opcode & 0x0110)
1079 break; /* illegal instruction */
a7812ae4
PB
1080 fp0 = tcg_temp_new_i64();
1081 fp1 = tcg_temp_new_i64();
1e0b21d8
RH
1082 gen_load_fpr64(ctx, fp0, B11_8);
1083 gen_load_fpr64(ctx, fp1, B7_4);
a7812ae4
PB
1084 switch (ctx->opcode & 0xf00f) {
1085 case 0xf000: /* fadd Rm,Rn */
485d0035 1086 gen_helper_fadd_DT(fp0, cpu_env, fp0, fp1);
a7812ae4
PB
1087 break;
1088 case 0xf001: /* fsub Rm,Rn */
485d0035 1089 gen_helper_fsub_DT(fp0, cpu_env, fp0, fp1);
a7812ae4
PB
1090 break;
1091 case 0xf002: /* fmul Rm,Rn */
485d0035 1092 gen_helper_fmul_DT(fp0, cpu_env, fp0, fp1);
a7812ae4
PB
1093 break;
1094 case 0xf003: /* fdiv Rm,Rn */
485d0035 1095 gen_helper_fdiv_DT(fp0, cpu_env, fp0, fp1);
a7812ae4
PB
1096 break;
1097 case 0xf004: /* fcmp/eq Rm,Rn */
92f1f83e 1098 gen_helper_fcmp_eq_DT(cpu_sr_t, cpu_env, fp0, fp1);
a7812ae4
PB
1099 return;
1100 case 0xf005: /* fcmp/gt Rm,Rn */
92f1f83e 1101 gen_helper_fcmp_gt_DT(cpu_sr_t, cpu_env, fp0, fp1);
a7812ae4
PB
1102 return;
1103 }
1e0b21d8 1104 gen_store_fpr64(ctx, fp0, B11_8);
a7812ae4
PB
1105 tcg_temp_free_i64(fp0);
1106 tcg_temp_free_i64(fp1);
1107 } else {
a7812ae4
PB
1108 switch (ctx->opcode & 0xf00f) {
1109 case 0xf000: /* fadd Rm,Rn */
7c9f7038
RH
1110 gen_helper_fadd_FT(FREG(B11_8), cpu_env,
1111 FREG(B11_8), FREG(B7_4));
a7812ae4
PB
1112 break;
1113 case 0xf001: /* fsub Rm,Rn */
7c9f7038
RH
1114 gen_helper_fsub_FT(FREG(B11_8), cpu_env,
1115 FREG(B11_8), FREG(B7_4));
a7812ae4
PB
1116 break;
1117 case 0xf002: /* fmul Rm,Rn */
7c9f7038
RH
1118 gen_helper_fmul_FT(FREG(B11_8), cpu_env,
1119 FREG(B11_8), FREG(B7_4));
a7812ae4
PB
1120 break;
1121 case 0xf003: /* fdiv Rm,Rn */
7c9f7038
RH
1122 gen_helper_fdiv_FT(FREG(B11_8), cpu_env,
1123 FREG(B11_8), FREG(B7_4));
a7812ae4
PB
1124 break;
1125 case 0xf004: /* fcmp/eq Rm,Rn */
92f1f83e 1126 gen_helper_fcmp_eq_FT(cpu_sr_t, cpu_env,
7c9f7038 1127 FREG(B11_8), FREG(B7_4));
a7812ae4
PB
1128 return;
1129 case 0xf005: /* fcmp/gt Rm,Rn */
92f1f83e 1130 gen_helper_fcmp_gt_FT(cpu_sr_t, cpu_env,
7c9f7038 1131 FREG(B11_8), FREG(B7_4));
a7812ae4
PB
1132 return;
1133 }
cc4ba6a9 1134 }
ea6cf6be
TS
1135 }
1136 return;
5b7141a1
AJ
1137 case 0xf00e: /* fmac FR0,RM,Rn */
1138 {
1139 CHECK_FPU_ENABLED
a6215749 1140 if (ctx->tbflags & FPSCR_PR) {
5b7141a1
AJ
1141 break; /* illegal instruction */
1142 } else {
7c9f7038
RH
1143 gen_helper_fmac_FT(FREG(B11_8), cpu_env,
1144 FREG(0), FREG(B7_4), FREG(B11_8));
5b7141a1
AJ
1145 return;
1146 }
1147 }
fdf9b3e8
FB
1148 }
1149
1150 switch (ctx->opcode & 0xff00) {
1151 case 0xc900: /* and #imm,R0 */
7efbe241 1152 tcg_gen_andi_i32(REG(0), REG(0), B7_0);
fdf9b3e8 1153 return;
24988dc2 1154 case 0xcd00: /* and.b #imm,@(R0,GBR) */
c55497ec
AJ
1155 {
1156 TCGv addr, val;
a7812ae4 1157 addr = tcg_temp_new();
c55497ec 1158 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
a7812ae4 1159 val = tcg_temp_new();
3376f415 1160 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
c55497ec 1161 tcg_gen_andi_i32(val, val, B7_0);
3376f415 1162 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
c55497ec
AJ
1163 tcg_temp_free(val);
1164 tcg_temp_free(addr);
1165 }
fdf9b3e8
FB
1166 return;
1167 case 0x8b00: /* bf label */
1168 CHECK_NOT_DELAY_SLOT
4bfa602b 1169 gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2, false);
fdf9b3e8
FB
1170 return;
1171 case 0x8f00: /* bf/s label */
1172 CHECK_NOT_DELAY_SLOT
ac9707ea
AJ
1173 tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1);
1174 ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2;
a6215749 1175 ctx->envflags |= DELAY_SLOT_CONDITIONAL;
fdf9b3e8
FB
1176 return;
1177 case 0x8900: /* bt label */
1178 CHECK_NOT_DELAY_SLOT
4bfa602b 1179 gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2, true);
fdf9b3e8
FB
1180 return;
1181 case 0x8d00: /* bt/s label */
1182 CHECK_NOT_DELAY_SLOT
ac9707ea
AJ
1183 tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t);
1184 ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2;
a6215749 1185 ctx->envflags |= DELAY_SLOT_CONDITIONAL;
fdf9b3e8
FB
1186 return;
1187 case 0x8800: /* cmp/eq #imm,R0 */
34086945 1188 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s);
fdf9b3e8
FB
1189 return;
1190 case 0xc400: /* mov.b @(disp,GBR),R0 */
c55497ec 1191 {
a7812ae4 1192 TCGv addr = tcg_temp_new();
c55497ec 1193 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
3376f415 1194 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
c55497ec
AJ
1195 tcg_temp_free(addr);
1196 }
fdf9b3e8
FB
1197 return;
1198 case 0xc500: /* mov.w @(disp,GBR),R0 */
c55497ec 1199 {
a7812ae4 1200 TCGv addr = tcg_temp_new();
c55497ec 1201 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
3376f415 1202 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW);
c55497ec
AJ
1203 tcg_temp_free(addr);
1204 }
fdf9b3e8
FB
1205 return;
1206 case 0xc600: /* mov.l @(disp,GBR),R0 */
c55497ec 1207 {
a7812ae4 1208 TCGv addr = tcg_temp_new();
c55497ec 1209 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
3376f415 1210 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESL);
c55497ec
AJ
1211 tcg_temp_free(addr);
1212 }
fdf9b3e8
FB
1213 return;
1214 case 0xc000: /* mov.b R0,@(disp,GBR) */
c55497ec 1215 {
a7812ae4 1216 TCGv addr = tcg_temp_new();
c55497ec 1217 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
3376f415 1218 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
c55497ec
AJ
1219 tcg_temp_free(addr);
1220 }
fdf9b3e8
FB
1221 return;
1222 case 0xc100: /* mov.w R0,@(disp,GBR) */
c55497ec 1223 {
a7812ae4 1224 TCGv addr = tcg_temp_new();
c55497ec 1225 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
3376f415 1226 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW);
c55497ec
AJ
1227 tcg_temp_free(addr);
1228 }
fdf9b3e8
FB
1229 return;
1230 case 0xc200: /* mov.l R0,@(disp,GBR) */
c55497ec 1231 {
a7812ae4 1232 TCGv addr = tcg_temp_new();
c55497ec 1233 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
3376f415 1234 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUL);
c55497ec
AJ
1235 tcg_temp_free(addr);
1236 }
fdf9b3e8
FB
1237 return;
1238 case 0x8000: /* mov.b R0,@(disp,Rn) */
c55497ec 1239 {
a7812ae4 1240 TCGv addr = tcg_temp_new();
c55497ec 1241 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
3376f415 1242 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
c55497ec
AJ
1243 tcg_temp_free(addr);
1244 }
fdf9b3e8
FB
1245 return;
1246 case 0x8100: /* mov.w R0,@(disp,Rn) */
c55497ec 1247 {
a7812ae4 1248 TCGv addr = tcg_temp_new();
c55497ec 1249 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
3376f415 1250 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW);
c55497ec
AJ
1251 tcg_temp_free(addr);
1252 }
fdf9b3e8
FB
1253 return;
1254 case 0x8400: /* mov.b @(disp,Rn),R0 */
c55497ec 1255 {
a7812ae4 1256 TCGv addr = tcg_temp_new();
c55497ec 1257 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
3376f415 1258 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
c55497ec
AJ
1259 tcg_temp_free(addr);
1260 }
fdf9b3e8
FB
1261 return;
1262 case 0x8500: /* mov.w @(disp,Rn),R0 */
c55497ec 1263 {
a7812ae4 1264 TCGv addr = tcg_temp_new();
c55497ec 1265 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
3376f415 1266 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW);
c55497ec
AJ
1267 tcg_temp_free(addr);
1268 }
fdf9b3e8
FB
1269 return;
1270 case 0xc700: /* mova @(disp,PC),R0 */
7efbe241 1271 tcg_gen_movi_i32(REG(0), ((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3);
fdf9b3e8
FB
1272 return;
1273 case 0xcb00: /* or #imm,R0 */
7efbe241 1274 tcg_gen_ori_i32(REG(0), REG(0), B7_0);
fdf9b3e8 1275 return;
24988dc2 1276 case 0xcf00: /* or.b #imm,@(R0,GBR) */
c55497ec
AJ
1277 {
1278 TCGv addr, val;
a7812ae4 1279 addr = tcg_temp_new();
c55497ec 1280 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
a7812ae4 1281 val = tcg_temp_new();
3376f415 1282 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
c55497ec 1283 tcg_gen_ori_i32(val, val, B7_0);
3376f415 1284 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
c55497ec
AJ
1285 tcg_temp_free(val);
1286 tcg_temp_free(addr);
1287 }
fdf9b3e8
FB
1288 return;
1289 case 0xc300: /* trapa #imm */
c55497ec
AJ
1290 {
1291 TCGv imm;
1292 CHECK_NOT_DELAY_SLOT
ac9707ea 1293 gen_save_cpu_state(ctx, true);
c55497ec 1294 imm = tcg_const_i32(B7_0);
485d0035 1295 gen_helper_trapa(cpu_env, imm);
c55497ec 1296 tcg_temp_free(imm);
63205665 1297 ctx->bstate = BS_EXCP;
c55497ec 1298 }
fdf9b3e8
FB
1299 return;
1300 case 0xc800: /* tst #imm,R0 */
c55497ec 1301 {
a7812ae4 1302 TCGv val = tcg_temp_new();
c55497ec 1303 tcg_gen_andi_i32(val, REG(0), B7_0);
34086945 1304 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
c55497ec
AJ
1305 tcg_temp_free(val);
1306 }
fdf9b3e8 1307 return;
24988dc2 1308 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
c55497ec 1309 {
a7812ae4 1310 TCGv val = tcg_temp_new();
c55497ec 1311 tcg_gen_add_i32(val, REG(0), cpu_gbr);
3376f415 1312 tcg_gen_qemu_ld_i32(val, val, ctx->memidx, MO_UB);
c55497ec 1313 tcg_gen_andi_i32(val, val, B7_0);
34086945 1314 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
c55497ec
AJ
1315 tcg_temp_free(val);
1316 }
fdf9b3e8
FB
1317 return;
1318 case 0xca00: /* xor #imm,R0 */
7efbe241 1319 tcg_gen_xori_i32(REG(0), REG(0), B7_0);
fdf9b3e8 1320 return;
24988dc2 1321 case 0xce00: /* xor.b #imm,@(R0,GBR) */
c55497ec
AJ
1322 {
1323 TCGv addr, val;
a7812ae4 1324 addr = tcg_temp_new();
c55497ec 1325 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
a7812ae4 1326 val = tcg_temp_new();
3376f415 1327 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
c55497ec 1328 tcg_gen_xori_i32(val, val, B7_0);
3376f415 1329 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
c55497ec
AJ
1330 tcg_temp_free(val);
1331 tcg_temp_free(addr);
1332 }
fdf9b3e8
FB
1333 return;
1334 }
1335
1336 switch (ctx->opcode & 0xf08f) {
1337 case 0x408e: /* ldc Rm,Rn_BANK */
fe25591e 1338 CHECK_PRIVILEGED
7efbe241 1339 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8));
fdf9b3e8
FB
1340 return;
1341 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
fe25591e 1342 CHECK_PRIVILEGED
3376f415 1343 tcg_gen_qemu_ld_i32(ALTREG(B6_4), REG(B11_8), ctx->memidx, MO_TESL);
7efbe241 1344 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
fdf9b3e8
FB
1345 return;
1346 case 0x0082: /* stc Rm_BANK,Rn */
fe25591e 1347 CHECK_PRIVILEGED
7efbe241 1348 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4));
fdf9b3e8
FB
1349 return;
1350 case 0x4083: /* stc.l Rm_BANK,@-Rn */
fe25591e 1351 CHECK_PRIVILEGED
c55497ec 1352 {
a7812ae4 1353 TCGv addr = tcg_temp_new();
c55497ec 1354 tcg_gen_subi_i32(addr, REG(B11_8), 4);
3376f415 1355 tcg_gen_qemu_st_i32(ALTREG(B6_4), addr, ctx->memidx, MO_TEUL);
3101e99c 1356 tcg_gen_mov_i32(REG(B11_8), addr);
c55497ec 1357 tcg_temp_free(addr);
c55497ec 1358 }
fdf9b3e8
FB
1359 return;
1360 }
1361
1362 switch (ctx->opcode & 0xf0ff) {
1363 case 0x0023: /* braf Rn */
7efbe241
AJ
1364 CHECK_NOT_DELAY_SLOT
1365 tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->pc + 4);
a6215749 1366 ctx->envflags |= DELAY_SLOT;
fdf9b3e8
FB
1367 ctx->delayed_pc = (uint32_t) - 1;
1368 return;
1369 case 0x0003: /* bsrf Rn */
7efbe241 1370 CHECK_NOT_DELAY_SLOT
1000822b 1371 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
7efbe241 1372 tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
a6215749 1373 ctx->envflags |= DELAY_SLOT;
fdf9b3e8
FB
1374 ctx->delayed_pc = (uint32_t) - 1;
1375 return;
1376 case 0x4015: /* cmp/pl Rn */
34086945 1377 tcg_gen_setcondi_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), 0);
fdf9b3e8
FB
1378 return;
1379 case 0x4011: /* cmp/pz Rn */
34086945 1380 tcg_gen_setcondi_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), 0);
fdf9b3e8
FB
1381 return;
1382 case 0x4010: /* dt Rn */
7efbe241 1383 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1);
34086945 1384 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), 0);
fdf9b3e8
FB
1385 return;
1386 case 0x402b: /* jmp @Rn */
7efbe241
AJ
1387 CHECK_NOT_DELAY_SLOT
1388 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
a6215749 1389 ctx->envflags |= DELAY_SLOT;
fdf9b3e8
FB
1390 ctx->delayed_pc = (uint32_t) - 1;
1391 return;
1392 case 0x400b: /* jsr @Rn */
7efbe241 1393 CHECK_NOT_DELAY_SLOT
1000822b 1394 tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
7efbe241 1395 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
a6215749 1396 ctx->envflags |= DELAY_SLOT;
fdf9b3e8
FB
1397 ctx->delayed_pc = (uint32_t) - 1;
1398 return;
fe25591e
AJ
1399 case 0x400e: /* ldc Rm,SR */
1400 CHECK_PRIVILEGED
34086945
AJ
1401 {
1402 TCGv val = tcg_temp_new();
1403 tcg_gen_andi_i32(val, REG(B11_8), 0x700083f3);
1404 gen_write_sr(val);
1405 tcg_temp_free(val);
1406 ctx->bstate = BS_STOP;
1407 }
390af821 1408 return;
fe25591e
AJ
1409 case 0x4007: /* ldc.l @Rm+,SR */
1410 CHECK_PRIVILEGED
c55497ec 1411 {
a7812ae4 1412 TCGv val = tcg_temp_new();
3376f415 1413 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TESL);
34086945
AJ
1414 tcg_gen_andi_i32(val, val, 0x700083f3);
1415 gen_write_sr(val);
c55497ec
AJ
1416 tcg_temp_free(val);
1417 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1418 ctx->bstate = BS_STOP;
1419 }
390af821 1420 return;
fe25591e
AJ
1421 case 0x0002: /* stc SR,Rn */
1422 CHECK_PRIVILEGED
34086945 1423 gen_read_sr(REG(B11_8));
390af821 1424 return;
fe25591e
AJ
1425 case 0x4003: /* stc SR,@-Rn */
1426 CHECK_PRIVILEGED
c55497ec 1427 {
a7812ae4 1428 TCGv addr = tcg_temp_new();
34086945 1429 TCGv val = tcg_temp_new();
c55497ec 1430 tcg_gen_subi_i32(addr, REG(B11_8), 4);
34086945
AJ
1431 gen_read_sr(val);
1432 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL);
3101e99c 1433 tcg_gen_mov_i32(REG(B11_8), addr);
34086945 1434 tcg_temp_free(val);
c55497ec 1435 tcg_temp_free(addr);
c55497ec 1436 }
390af821 1437 return;
8e9b0678 1438#define LD(reg,ldnum,ldpnum,prechk) \
fdf9b3e8 1439 case ldnum: \
fe25591e 1440 prechk \
7efbe241 1441 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \
fdf9b3e8
FB
1442 return; \
1443 case ldpnum: \
fe25591e 1444 prechk \
3376f415 1445 tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, MO_TESL); \
7efbe241 1446 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \
8e9b0678
AC
1447 return;
1448#define ST(reg,stnum,stpnum,prechk) \
fdf9b3e8 1449 case stnum: \
fe25591e 1450 prechk \
7efbe241 1451 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \
fdf9b3e8
FB
1452 return; \
1453 case stpnum: \
fe25591e 1454 prechk \
c55497ec 1455 { \
3101e99c 1456 TCGv addr = tcg_temp_new(); \
c55497ec 1457 tcg_gen_subi_i32(addr, REG(B11_8), 4); \
3376f415 1458 tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, MO_TEUL); \
3101e99c 1459 tcg_gen_mov_i32(REG(B11_8), addr); \
c55497ec 1460 tcg_temp_free(addr); \
86e0abc7 1461 } \
fdf9b3e8 1462 return;
8e9b0678
AC
1463#define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \
1464 LD(reg,ldnum,ldpnum,prechk) \
1465 ST(reg,stnum,stpnum,prechk)
fe25591e
AJ
1466 LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {})
1467 LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED)
1468 LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED)
1469 LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED)
935fc175
AC
1470 ST(sgr, 0x003a, 0x4032, CHECK_PRIVILEGED)
1471 LD(sgr, 0x403a, 0x4036, CHECK_PRIVILEGED if (!(ctx->features & SH_FEATURE_SH4A)) break;)
fe25591e
AJ
1472 LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED)
1473 LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {})
1474 LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {})
1475 LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {})
d8299bcc 1476 LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED})
390af821 1477 case 0x406a: /* lds Rm,FPSCR */
d8299bcc 1478 CHECK_FPU_ENABLED
485d0035 1479 gen_helper_ld_fpscr(cpu_env, REG(B11_8));
390af821
AJ
1480 ctx->bstate = BS_STOP;
1481 return;
1482 case 0x4066: /* lds.l @Rm+,FPSCR */
d8299bcc 1483 CHECK_FPU_ENABLED
c55497ec 1484 {
a7812ae4 1485 TCGv addr = tcg_temp_new();
3376f415 1486 tcg_gen_qemu_ld_i32(addr, REG(B11_8), ctx->memidx, MO_TESL);
c55497ec 1487 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
485d0035 1488 gen_helper_ld_fpscr(cpu_env, addr);
c55497ec
AJ
1489 tcg_temp_free(addr);
1490 ctx->bstate = BS_STOP;
1491 }
390af821
AJ
1492 return;
1493 case 0x006a: /* sts FPSCR,Rn */
d8299bcc 1494 CHECK_FPU_ENABLED
c55497ec 1495 tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff);
390af821
AJ
1496 return;
1497 case 0x4062: /* sts FPSCR,@-Rn */
d8299bcc 1498 CHECK_FPU_ENABLED
c55497ec
AJ
1499 {
1500 TCGv addr, val;
a7812ae4 1501 val = tcg_temp_new();
c55497ec 1502 tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff);
a7812ae4 1503 addr = tcg_temp_new();
c55497ec 1504 tcg_gen_subi_i32(addr, REG(B11_8), 4);
3376f415 1505 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL);
3101e99c 1506 tcg_gen_mov_i32(REG(B11_8), addr);
c55497ec
AJ
1507 tcg_temp_free(addr);
1508 tcg_temp_free(val);
c55497ec 1509 }
390af821 1510 return;
fdf9b3e8 1511 case 0x00c3: /* movca.l R0,@Rm */
852d481f
EI
1512 {
1513 TCGv val = tcg_temp_new();
3376f415 1514 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TEUL);
485d0035 1515 gen_helper_movcal(cpu_env, REG(B11_8), val);
3376f415 1516 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
852d481f
EI
1517 }
1518 ctx->has_movcal = 1;
fdf9b3e8 1519 return;
143021b2
AJ
1520 case 0x40a9: /* movua.l @Rm,R0 */
1521 /* Load non-boundary-aligned data */
1522 if (ctx->features & SH_FEATURE_SH4A) {
34257c21
AJ
1523 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1524 MO_TEUL | MO_UNALN);
143021b2
AJ
1525 return;
1526 }
1527 break;
1528 case 0x40e9: /* movua.l @Rm+,R0 */
1529 /* Load non-boundary-aligned data */
1530 if (ctx->features & SH_FEATURE_SH4A) {
34257c21
AJ
1531 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1532 MO_TEUL | MO_UNALN);
143021b2
AJ
1533 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1534 return;
1535 }
1536 break;
fdf9b3e8 1537 case 0x0029: /* movt Rn */
34086945 1538 tcg_gen_mov_i32(REG(B11_8), cpu_sr_t);
fdf9b3e8 1539 return;
66c7c806
AJ
1540 case 0x0073:
1541 /* MOVCO.L
1542 LDST -> T
1543 If (T == 1) R0 -> (Rn)
1544 0 -> LDST
1545 */
1546 if (ctx->features & SH_FEATURE_SH4A) {
42a268c2 1547 TCGLabel *label = gen_new_label();
34086945 1548 tcg_gen_mov_i32(cpu_sr_t, cpu_ldst);
66c7c806 1549 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ldst, 0, label);
3376f415 1550 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
66c7c806
AJ
1551 gen_set_label(label);
1552 tcg_gen_movi_i32(cpu_ldst, 0);
1553 return;
1554 } else
1555 break;
1556 case 0x0063:
1557 /* MOVLI.L @Rm,R0
1558 1 -> LDST
1559 (Rm) -> R0
1560 When interrupt/exception
1561 occurred 0 -> LDST
1562 */
1563 if (ctx->features & SH_FEATURE_SH4A) {
1564 tcg_gen_movi_i32(cpu_ldst, 0);
3376f415 1565 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TESL);
66c7c806
AJ
1566 tcg_gen_movi_i32(cpu_ldst, 1);
1567 return;
1568 } else
1569 break;
fdf9b3e8 1570 case 0x0093: /* ocbi @Rn */
c55497ec 1571 {
485d0035 1572 gen_helper_ocbi(cpu_env, REG(B11_8));
c55497ec 1573 }
fdf9b3e8 1574 return;
24988dc2 1575 case 0x00a3: /* ocbp @Rn */
fdf9b3e8 1576 case 0x00b3: /* ocbwb @Rn */
0cdb9554
AJ
1577 /* These instructions are supposed to do nothing in case of
1578 a cache miss. Given that we only partially emulate caches
1579 it is safe to simply ignore them. */
fdf9b3e8
FB
1580 return;
1581 case 0x0083: /* pref @Rn */
1582 return;
71968fa6
AJ
1583 case 0x00d3: /* prefi @Rn */
1584 if (ctx->features & SH_FEATURE_SH4A)
1585 return;
1586 else
1587 break;
1588 case 0x00e3: /* icbi @Rn */
1589 if (ctx->features & SH_FEATURE_SH4A)
1590 return;
1591 else
1592 break;
1593 case 0x00ab: /* synco */
aa351317
AJ
1594 if (ctx->features & SH_FEATURE_SH4A) {
1595 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
1596 return;
1597 }
1598 break;
fdf9b3e8 1599 case 0x4024: /* rotcl Rn */
c55497ec 1600 {
a7812ae4 1601 TCGv tmp = tcg_temp_new();
34086945
AJ
1602 tcg_gen_mov_i32(tmp, cpu_sr_t);
1603 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
c55497ec 1604 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
34086945 1605 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
c55497ec
AJ
1606 tcg_temp_free(tmp);
1607 }
fdf9b3e8
FB
1608 return;
1609 case 0x4025: /* rotcr Rn */
c55497ec 1610 {
a7812ae4 1611 TCGv tmp = tcg_temp_new();
34086945
AJ
1612 tcg_gen_shli_i32(tmp, cpu_sr_t, 31);
1613 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
c55497ec 1614 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
34086945 1615 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
c55497ec
AJ
1616 tcg_temp_free(tmp);
1617 }
fdf9b3e8
FB
1618 return;
1619 case 0x4004: /* rotl Rn */
2411fde9 1620 tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1);
34086945 1621 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
fdf9b3e8
FB
1622 return;
1623 case 0x4005: /* rotr Rn */
34086945 1624 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
2411fde9 1625 tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1);
fdf9b3e8
FB
1626 return;
1627 case 0x4000: /* shll Rn */
1628 case 0x4020: /* shal Rn */
34086945 1629 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
7efbe241 1630 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
fdf9b3e8
FB
1631 return;
1632 case 0x4021: /* shar Rn */
34086945 1633 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
7efbe241 1634 tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1);
fdf9b3e8
FB
1635 return;
1636 case 0x4001: /* shlr Rn */
34086945 1637 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
7efbe241 1638 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
fdf9b3e8
FB
1639 return;
1640 case 0x4008: /* shll2 Rn */
7efbe241 1641 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2);
fdf9b3e8
FB
1642 return;
1643 case 0x4018: /* shll8 Rn */
7efbe241 1644 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8);
fdf9b3e8
FB
1645 return;
1646 case 0x4028: /* shll16 Rn */
7efbe241 1647 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16);
fdf9b3e8
FB
1648 return;
1649 case 0x4009: /* shlr2 Rn */
7efbe241 1650 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2);
fdf9b3e8
FB
1651 return;
1652 case 0x4019: /* shlr8 Rn */
7efbe241 1653 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8);
fdf9b3e8
FB
1654 return;
1655 case 0x4029: /* shlr16 Rn */
7efbe241 1656 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16);
fdf9b3e8
FB
1657 return;
1658 case 0x401b: /* tas.b @Rn */
cb32f179
AJ
1659 {
1660 TCGv val = tcg_const_i32(0x80);
1661 tcg_gen_atomic_fetch_or_i32(val, REG(B11_8), val,
1662 ctx->memidx, MO_UB);
34086945 1663 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
cb32f179
AJ
1664 tcg_temp_free(val);
1665 }
1666 return;
e67888a7 1667 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
f6198371 1668 CHECK_FPU_ENABLED
7c9f7038 1669 tcg_gen_mov_i32(FREG(B11_8), cpu_fpul);
eda9b09b 1670 return;
e67888a7 1671 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
f6198371 1672 CHECK_FPU_ENABLED
7c9f7038 1673 tcg_gen_mov_i32(cpu_fpul, FREG(B11_8));
eda9b09b 1674 return;
e67888a7 1675 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
f6198371 1676 CHECK_FPU_ENABLED
a6215749 1677 if (ctx->tbflags & FPSCR_PR) {
a7812ae4 1678 TCGv_i64 fp;
ea6cf6be
TS
1679 if (ctx->opcode & 0x0100)
1680 break; /* illegal instruction */
a7812ae4 1681 fp = tcg_temp_new_i64();
485d0035 1682 gen_helper_float_DT(fp, cpu_env, cpu_fpul);
1e0b21d8 1683 gen_store_fpr64(ctx, fp, B11_8);
a7812ae4 1684 tcg_temp_free_i64(fp);
ea6cf6be
TS
1685 }
1686 else {
7c9f7038 1687 gen_helper_float_FT(FREG(B11_8), cpu_env, cpu_fpul);
ea6cf6be
TS
1688 }
1689 return;
e67888a7 1690 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
f6198371 1691 CHECK_FPU_ENABLED
a6215749 1692 if (ctx->tbflags & FPSCR_PR) {
a7812ae4 1693 TCGv_i64 fp;
ea6cf6be
TS
1694 if (ctx->opcode & 0x0100)
1695 break; /* illegal instruction */
a7812ae4 1696 fp = tcg_temp_new_i64();
1e0b21d8 1697 gen_load_fpr64(ctx, fp, B11_8);
485d0035 1698 gen_helper_ftrc_DT(cpu_fpul, cpu_env, fp);
a7812ae4 1699 tcg_temp_free_i64(fp);
ea6cf6be
TS
1700 }
1701 else {
7c9f7038 1702 gen_helper_ftrc_FT(cpu_fpul, cpu_env, FREG(B11_8));
ea6cf6be
TS
1703 }
1704 return;
24988dc2 1705 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
f6198371 1706 CHECK_FPU_ENABLED
7c9f7038 1707 tcg_gen_xori_i32(FREG(B11_8), FREG(B11_8), 0x80000000);
24988dc2 1708 return;
57f5c1b0 1709 case 0xf05d: /* fabs FRn/DRn - FPCSR: Nothing */
f6198371 1710 CHECK_FPU_ENABLED
7c9f7038 1711 tcg_gen_andi_i32(FREG(B11_8), FREG(B11_8), 0x7fffffff);
24988dc2
AJ
1712 return;
1713 case 0xf06d: /* fsqrt FRn */
f6198371 1714 CHECK_FPU_ENABLED
a6215749 1715 if (ctx->tbflags & FPSCR_PR) {
24988dc2
AJ
1716 if (ctx->opcode & 0x0100)
1717 break; /* illegal instruction */
a7812ae4 1718 TCGv_i64 fp = tcg_temp_new_i64();
1e0b21d8 1719 gen_load_fpr64(ctx, fp, B11_8);
485d0035 1720 gen_helper_fsqrt_DT(fp, cpu_env, fp);
1e0b21d8 1721 gen_store_fpr64(ctx, fp, B11_8);
a7812ae4 1722 tcg_temp_free_i64(fp);
24988dc2 1723 } else {
7c9f7038 1724 gen_helper_fsqrt_FT(FREG(B11_8), cpu_env, 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)) {
7c9f7038 1733 tcg_gen_movi_i32(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)) {
7c9f7038 1739 tcg_gen_movi_i32(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);
1e0b21d8 1747 gen_store_fpr64(ctx, fp, 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();
1e0b21d8 1755 gen_load_fpr64(ctx, fp, 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
6b98213d 1789 do_illegal:
9a562ae7 1790 if (ctx->envflags & DELAY_SLOT_MASK) {
dec16c6e
RH
1791 do_illegal_slot:
1792 gen_save_cpu_state(ctx, true);
485d0035 1793 gen_helper_raise_slot_illegal_instruction(cpu_env);
86865c5f 1794 } else {
dec16c6e 1795 gen_save_cpu_state(ctx, true);
485d0035 1796 gen_helper_raise_illegal_instruction(cpu_env);
86865c5f 1797 }
63205665 1798 ctx->bstate = BS_EXCP;
823029f9
TS
1799}
1800
b1d8e52e 1801static void decode_opc(DisasContext * ctx)
823029f9 1802{
a6215749 1803 uint32_t old_flags = ctx->envflags;
823029f9
TS
1804
1805 _decode_opc(ctx);
1806
9a562ae7 1807 if (old_flags & DELAY_SLOT_MASK) {
39682608 1808 /* go out of the delay slot */
9a562ae7 1809 ctx->envflags &= ~DELAY_SLOT_MASK;
4bfa602b
RH
1810
1811 /* When in an exclusive region, we must continue to the end
1812 for conditional branches. */
1813 if (ctx->tbflags & GUSA_EXCLUSIVE
1814 && old_flags & DELAY_SLOT_CONDITIONAL) {
1815 gen_delayed_conditional_jump(ctx);
1816 return;
1817 }
1818 /* Otherwise this is probably an invalid gUSA region.
1819 Drop the GUSA bits so the next TB doesn't see them. */
1820 ctx->envflags &= ~GUSA_MASK;
1821
ac9707ea 1822 tcg_gen_movi_i32(cpu_flags, ctx->envflags);
823029f9
TS
1823 ctx->bstate = BS_BRANCH;
1824 if (old_flags & DELAY_SLOT_CONDITIONAL) {
1825 gen_delayed_conditional_jump(ctx);
be53081a 1826 } else {
823029f9
TS
1827 gen_jump(ctx);
1828 }
4bfa602b
RH
1829 }
1830}
1831
1832#ifdef CONFIG_USER_ONLY
1833/* For uniprocessors, SH4 uses optimistic restartable atomic sequences.
1834 Upon an interrupt, a real kernel would simply notice magic values in
1835 the registers and reset the PC to the start of the sequence.
1836
1837 For QEMU, we cannot do this in quite the same way. Instead, we notice
1838 the normal start of such a sequence (mov #-x,r15). While we can handle
1839 any sequence via cpu_exec_step_atomic, we can recognize the "normal"
1840 sequences and transform them into atomic operations as seen by the host.
1841*/
1842static int decode_gusa(DisasContext *ctx, CPUSH4State *env, int *pmax_insns)
1843{
d6a6cffd
RH
1844 uint16_t insns[5];
1845 int ld_adr, ld_dst, ld_mop;
1846 int op_dst, op_src, op_opc;
1847 int mv_src, mt_dst, st_src, st_mop;
1848 TCGv op_arg;
1849
4bfa602b
RH
1850 uint32_t pc = ctx->pc;
1851 uint32_t pc_end = ctx->tb->cs_base;
1852 int backup = sextract32(ctx->tbflags, GUSA_SHIFT, 8);
1853 int max_insns = (pc_end - pc) / 2;
d6a6cffd 1854 int i;
4bfa602b
RH
1855
1856 if (pc != pc_end + backup || max_insns < 2) {
1857 /* This is a malformed gUSA region. Don't do anything special,
1858 since the interpreter is likely to get confused. */
1859 ctx->envflags &= ~GUSA_MASK;
1860 return 0;
1861 }
823029f9 1862
4bfa602b
RH
1863 if (ctx->tbflags & GUSA_EXCLUSIVE) {
1864 /* Regardless of single-stepping or the end of the page,
1865 we must complete execution of the gUSA region while
1866 holding the exclusive lock. */
1867 *pmax_insns = max_insns;
1868 return 0;
823029f9 1869 }
4bfa602b 1870
d6a6cffd
RH
1871 /* The state machine below will consume only a few insns.
1872 If there are more than that in a region, fail now. */
1873 if (max_insns > ARRAY_SIZE(insns)) {
1874 goto fail;
1875 }
1876
1877 /* Read all of the insns for the region. */
1878 for (i = 0; i < max_insns; ++i) {
1879 insns[i] = cpu_lduw_code(env, pc + i * 2);
1880 }
1881
1882 ld_adr = ld_dst = ld_mop = -1;
1883 mv_src = -1;
1884 op_dst = op_src = op_opc = -1;
1885 mt_dst = -1;
1886 st_src = st_mop = -1;
1887 TCGV_UNUSED(op_arg);
1888 i = 0;
1889
1890#define NEXT_INSN \
1891 do { if (i >= max_insns) goto fail; ctx->opcode = insns[i++]; } while (0)
1892
1893 /*
1894 * Expect a load to begin the region.
1895 */
1896 NEXT_INSN;
1897 switch (ctx->opcode & 0xf00f) {
1898 case 0x6000: /* mov.b @Rm,Rn */
1899 ld_mop = MO_SB;
1900 break;
1901 case 0x6001: /* mov.w @Rm,Rn */
1902 ld_mop = MO_TESW;
1903 break;
1904 case 0x6002: /* mov.l @Rm,Rn */
1905 ld_mop = MO_TESL;
1906 break;
1907 default:
1908 goto fail;
1909 }
1910 ld_adr = B7_4;
1911 ld_dst = B11_8;
1912 if (ld_adr == ld_dst) {
1913 goto fail;
1914 }
1915 /* Unless we see a mov, any two-operand operation must use ld_dst. */
1916 op_dst = ld_dst;
1917
1918 /*
1919 * Expect an optional register move.
1920 */
1921 NEXT_INSN;
1922 switch (ctx->opcode & 0xf00f) {
1923 case 0x6003: /* mov Rm,Rn */
1924 /* Here we want to recognize ld_dst being saved for later consumtion,
1925 or for another input register being copied so that ld_dst need not
1926 be clobbered during the operation. */
1927 op_dst = B11_8;
1928 mv_src = B7_4;
1929 if (op_dst == ld_dst) {
1930 /* Overwriting the load output. */
1931 goto fail;
1932 }
1933 if (mv_src != ld_dst) {
1934 /* Copying a new input; constrain op_src to match the load. */
1935 op_src = ld_dst;
1936 }
1937 break;
1938
1939 default:
1940 /* Put back and re-examine as operation. */
1941 --i;
1942 }
1943
1944 /*
1945 * Expect the operation.
1946 */
1947 NEXT_INSN;
1948 switch (ctx->opcode & 0xf00f) {
1949 case 0x300c: /* add Rm,Rn */
1950 op_opc = INDEX_op_add_i32;
1951 goto do_reg_op;
1952 case 0x2009: /* and Rm,Rn */
1953 op_opc = INDEX_op_and_i32;
1954 goto do_reg_op;
1955 case 0x200a: /* xor Rm,Rn */
1956 op_opc = INDEX_op_xor_i32;
1957 goto do_reg_op;
1958 case 0x200b: /* or Rm,Rn */
1959 op_opc = INDEX_op_or_i32;
1960 do_reg_op:
1961 /* The operation register should be as expected, and the
1962 other input cannot depend on the load. */
1963 if (op_dst != B11_8) {
1964 goto fail;
1965 }
1966 if (op_src < 0) {
1967 /* Unconstrainted input. */
1968 op_src = B7_4;
1969 } else if (op_src == B7_4) {
1970 /* Constrained input matched load. All operations are
1971 commutative; "swap" them by "moving" the load output
1972 to the (implicit) first argument and the move source
1973 to the (explicit) second argument. */
1974 op_src = mv_src;
1975 } else {
1976 goto fail;
1977 }
1978 op_arg = REG(op_src);
1979 break;
1980
1981 case 0x6007: /* not Rm,Rn */
1982 if (ld_dst != B7_4 || mv_src >= 0) {
1983 goto fail;
1984 }
1985 op_dst = B11_8;
1986 op_opc = INDEX_op_xor_i32;
1987 op_arg = tcg_const_i32(-1);
1988 break;
1989
1990 case 0x7000 ... 0x700f: /* add #imm,Rn */
1991 if (op_dst != B11_8 || mv_src >= 0) {
1992 goto fail;
1993 }
1994 op_opc = INDEX_op_add_i32;
1995 op_arg = tcg_const_i32(B7_0s);
1996 break;
1997
1998 case 0x3000: /* cmp/eq Rm,Rn */
1999 /* Looking for the middle of a compare-and-swap sequence,
2000 beginning with the compare. Operands can be either order,
2001 but with only one overlapping the load. */
2002 if ((ld_dst == B11_8) + (ld_dst == B7_4) != 1 || mv_src >= 0) {
2003 goto fail;
2004 }
2005 op_opc = INDEX_op_setcond_i32; /* placeholder */
2006 op_src = (ld_dst == B11_8 ? B7_4 : B11_8);
2007 op_arg = REG(op_src);
2008
2009 NEXT_INSN;
2010 switch (ctx->opcode & 0xff00) {
2011 case 0x8b00: /* bf label */
2012 case 0x8f00: /* bf/s label */
2013 if (pc + (i + 1 + B7_0s) * 2 != pc_end) {
2014 goto fail;
2015 }
2016 if ((ctx->opcode & 0xff00) == 0x8b00) { /* bf label */
2017 break;
2018 }
2019 /* We're looking to unconditionally modify Rn with the
2020 result of the comparison, within the delay slot of
2021 the branch. This is used by older gcc. */
2022 NEXT_INSN;
2023 if ((ctx->opcode & 0xf0ff) == 0x0029) { /* movt Rn */
2024 mt_dst = B11_8;
2025 } else {
2026 goto fail;
2027 }
2028 break;
2029
2030 default:
2031 goto fail;
2032 }
2033 break;
2034
2035 case 0x2008: /* tst Rm,Rn */
2036 /* Looking for a compare-and-swap against zero. */
2037 if (ld_dst != B11_8 || ld_dst != B7_4 || mv_src >= 0) {
2038 goto fail;
2039 }
2040 op_opc = INDEX_op_setcond_i32;
2041 op_arg = tcg_const_i32(0);
2042
2043 NEXT_INSN;
2044 if ((ctx->opcode & 0xff00) != 0x8900 /* bt label */
2045 || pc + (i + 1 + B7_0s) * 2 != pc_end) {
2046 goto fail;
2047 }
2048 break;
2049
2050 default:
2051 /* Put back and re-examine as store. */
2052 --i;
2053 }
2054
2055 /*
2056 * Expect the store.
2057 */
2058 /* The store must be the last insn. */
2059 if (i != max_insns - 1) {
2060 goto fail;
2061 }
2062 NEXT_INSN;
2063 switch (ctx->opcode & 0xf00f) {
2064 case 0x2000: /* mov.b Rm,@Rn */
2065 st_mop = MO_UB;
2066 break;
2067 case 0x2001: /* mov.w Rm,@Rn */
2068 st_mop = MO_UW;
2069 break;
2070 case 0x2002: /* mov.l Rm,@Rn */
2071 st_mop = MO_UL;
2072 break;
2073 default:
2074 goto fail;
2075 }
2076 /* The store must match the load. */
2077 if (ld_adr != B11_8 || st_mop != (ld_mop & MO_SIZE)) {
2078 goto fail;
2079 }
2080 st_src = B7_4;
2081
2082#undef NEXT_INSN
2083
2084 /*
2085 * Emit the operation.
2086 */
2087 tcg_gen_insn_start(pc, ctx->envflags);
2088 switch (op_opc) {
2089 case -1:
2090 /* No operation found. Look for exchange pattern. */
2091 if (st_src == ld_dst || mv_src >= 0) {
2092 goto fail;
2093 }
2094 tcg_gen_atomic_xchg_i32(REG(ld_dst), REG(ld_adr), REG(st_src),
2095 ctx->memidx, ld_mop);
2096 break;
2097
2098 case INDEX_op_add_i32:
2099 if (op_dst != st_src) {
2100 goto fail;
2101 }
2102 if (op_dst == ld_dst && st_mop == MO_UL) {
2103 tcg_gen_atomic_add_fetch_i32(REG(ld_dst), REG(ld_adr),
2104 op_arg, ctx->memidx, ld_mop);
2105 } else {
2106 tcg_gen_atomic_fetch_add_i32(REG(ld_dst), REG(ld_adr),
2107 op_arg, ctx->memidx, ld_mop);
2108 if (op_dst != ld_dst) {
2109 /* Note that mop sizes < 4 cannot use add_fetch
2110 because it won't carry into the higher bits. */
2111 tcg_gen_add_i32(REG(op_dst), REG(ld_dst), op_arg);
2112 }
2113 }
2114 break;
2115
2116 case INDEX_op_and_i32:
2117 if (op_dst != st_src) {
2118 goto fail;
2119 }
2120 if (op_dst == ld_dst) {
2121 tcg_gen_atomic_and_fetch_i32(REG(ld_dst), REG(ld_adr),
2122 op_arg, ctx->memidx, ld_mop);
2123 } else {
2124 tcg_gen_atomic_fetch_and_i32(REG(ld_dst), REG(ld_adr),
2125 op_arg, ctx->memidx, ld_mop);
2126 tcg_gen_and_i32(REG(op_dst), REG(ld_dst), op_arg);
2127 }
2128 break;
2129
2130 case INDEX_op_or_i32:
2131 if (op_dst != st_src) {
2132 goto fail;
2133 }
2134 if (op_dst == ld_dst) {
2135 tcg_gen_atomic_or_fetch_i32(REG(ld_dst), REG(ld_adr),
2136 op_arg, ctx->memidx, ld_mop);
2137 } else {
2138 tcg_gen_atomic_fetch_or_i32(REG(ld_dst), REG(ld_adr),
2139 op_arg, ctx->memidx, ld_mop);
2140 tcg_gen_or_i32(REG(op_dst), REG(ld_dst), op_arg);
2141 }
2142 break;
2143
2144 case INDEX_op_xor_i32:
2145 if (op_dst != st_src) {
2146 goto fail;
2147 }
2148 if (op_dst == ld_dst) {
2149 tcg_gen_atomic_xor_fetch_i32(REG(ld_dst), REG(ld_adr),
2150 op_arg, ctx->memidx, ld_mop);
2151 } else {
2152 tcg_gen_atomic_fetch_xor_i32(REG(ld_dst), REG(ld_adr),
2153 op_arg, ctx->memidx, ld_mop);
2154 tcg_gen_xor_i32(REG(op_dst), REG(ld_dst), op_arg);
2155 }
2156 break;
2157
2158 case INDEX_op_setcond_i32:
2159 if (st_src == ld_dst) {
2160 goto fail;
2161 }
2162 tcg_gen_atomic_cmpxchg_i32(REG(ld_dst), REG(ld_adr), op_arg,
2163 REG(st_src), ctx->memidx, ld_mop);
2164 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(ld_dst), op_arg);
2165 if (mt_dst >= 0) {
2166 tcg_gen_mov_i32(REG(mt_dst), cpu_sr_t);
2167 }
2168 break;
2169
2170 default:
2171 g_assert_not_reached();
2172 }
2173
2174 /* If op_src is not a valid register, then op_arg was a constant. */
2175 if (op_src < 0) {
2176 tcg_temp_free_i32(op_arg);
2177 }
2178
2179 /* The entire region has been translated. */
2180 ctx->envflags &= ~GUSA_MASK;
2181 ctx->pc = pc_end;
2182 return max_insns;
2183
2184 fail:
4bfa602b
RH
2185 qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n",
2186 pc, pc_end);
2187
2188 /* Restart with the EXCLUSIVE bit set, within a TB run via
2189 cpu_exec_step_atomic holding the exclusive lock. */
2190 tcg_gen_insn_start(pc, ctx->envflags);
2191 ctx->envflags |= GUSA_EXCLUSIVE;
2192 gen_save_cpu_state(ctx, false);
2193 gen_helper_exclusive(cpu_env);
2194 ctx->bstate = BS_EXCP;
2195
2196 /* We're not executing an instruction, but we must report one for the
2197 purposes of accounting within the TB. We might as well report the
2198 entire region consumed via ctx->pc so that it's immediately available
2199 in the disassembly dump. */
2200 ctx->pc = pc_end;
2201 return 1;
fdf9b3e8 2202}
4bfa602b 2203#endif
fdf9b3e8 2204
4e5e1215 2205void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
fdf9b3e8 2206{
4e5e1215 2207 SuperHCPU *cpu = sh_env_get_cpu(env);
ed2803da 2208 CPUState *cs = CPU(cpu);
fdf9b3e8
FB
2209 DisasContext ctx;
2210 target_ulong pc_start;
2e70f6ef
PB
2211 int num_insns;
2212 int max_insns;
fdf9b3e8
FB
2213
2214 pc_start = tb->pc;
fdf9b3e8 2215 ctx.pc = pc_start;
a6215749 2216 ctx.tbflags = (uint32_t)tb->flags;
e1933d14 2217 ctx.envflags = tb->flags & TB_FLAG_ENVFLAGS_MASK;
823029f9 2218 ctx.bstate = BS_NONE;
a6215749 2219 ctx.memidx = (ctx.tbflags & (1u << SR_MD)) == 0 ? 1 : 0;
9854bc46
PB
2220 /* We don't know if the delayed pc came from a dynamic or static branch,
2221 so assume it is a dynamic branch. */
823029f9 2222 ctx.delayed_pc = -1; /* use delayed pc from env pointer */
fdf9b3e8 2223 ctx.tb = tb;
ed2803da 2224 ctx.singlestep_enabled = cs->singlestep_enabled;
71968fa6 2225 ctx.features = env->features;
a6215749 2226 ctx.has_movcal = (ctx.tbflags & TB_FLAG_PENDING_MOVCA);
3a3bb8d2
RH
2227 ctx.gbank = ((ctx.tbflags & (1 << SR_MD)) &&
2228 (ctx.tbflags & (1 << SR_RB))) * 0x10;
5c13bad9 2229 ctx.fbank = ctx.tbflags & FPSCR_FR ? 0x10 : 0;
fdf9b3e8 2230
2e70f6ef 2231 max_insns = tb->cflags & CF_COUNT_MASK;
190ce7fb 2232 if (max_insns == 0) {
2e70f6ef 2233 max_insns = CF_COUNT_MASK;
190ce7fb 2234 }
4448a836
RH
2235 max_insns = MIN(max_insns, TCG_MAX_INSNS);
2236
2237 /* Since the ISA is fixed-width, we can bound by the number
2238 of instructions remaining on the page. */
2239 num_insns = -(ctx.pc | TARGET_PAGE_MASK) / 2;
2240 max_insns = MIN(max_insns, num_insns);
2241
2242 /* Single stepping means just that. */
2243 if (ctx.singlestep_enabled || singlestep) {
2244 max_insns = 1;
190ce7fb
RH
2245 }
2246
cd42d5b2 2247 gen_tb_start(tb);
4448a836
RH
2248 num_insns = 0;
2249
4bfa602b
RH
2250#ifdef CONFIG_USER_ONLY
2251 if (ctx.tbflags & GUSA_MASK) {
2252 num_insns = decode_gusa(&ctx, env, &max_insns);
2253 }
2254#endif
2255
4448a836
RH
2256 while (ctx.bstate == BS_NONE
2257 && num_insns < max_insns
2258 && !tcg_op_buf_full()) {
a6215749 2259 tcg_gen_insn_start(ctx.pc, ctx.envflags);
959082fc 2260 num_insns++;
667b8e29 2261
b933066a
RH
2262 if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
2263 /* We have hit a breakpoint - make sure PC is up-to-date */
ac9707ea 2264 gen_save_cpu_state(&ctx, true);
b933066a 2265 gen_helper_debug(cpu_env);
63205665 2266 ctx.bstate = BS_EXCP;
522a0d4e
RH
2267 /* The address covered by the breakpoint must be included in
2268 [tb->pc, tb->pc + tb->size) in order to for it to be
2269 properly cleared -- thus we increment the PC here so that
2270 the logic setting tb->size below does the right thing. */
2271 ctx.pc += 2;
b933066a
RH
2272 break;
2273 }
2274
959082fc 2275 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
2e70f6ef 2276 gen_io_start();
667b8e29
RH
2277 }
2278
485d0035 2279 ctx.opcode = cpu_lduw_code(env, ctx.pc);
fdf9b3e8
FB
2280 decode_opc(&ctx);
2281 ctx.pc += 2;
fdf9b3e8 2282 }
4448a836 2283 if (tb->cflags & CF_LAST_IO) {
2e70f6ef 2284 gen_io_end();
4448a836 2285 }
4bfa602b
RH
2286
2287 if (ctx.tbflags & GUSA_EXCLUSIVE) {
2288 /* Ending the region of exclusivity. Clear the bits. */
2289 ctx.envflags &= ~GUSA_MASK;
2290 }
2291
ed2803da 2292 if (cs->singlestep_enabled) {
ac9707ea 2293 gen_save_cpu_state(&ctx, true);
485d0035 2294 gen_helper_debug(cpu_env);
823029f9
TS
2295 } else {
2296 switch (ctx.bstate) {
2297 case BS_STOP:
ac9707ea 2298 gen_save_cpu_state(&ctx, true);
0fc37a8b
AJ
2299 tcg_gen_exit_tb(0);
2300 break;
823029f9 2301 case BS_NONE:
ac9707ea 2302 gen_save_cpu_state(&ctx, false);
823029f9
TS
2303 gen_goto_tb(&ctx, 0, ctx.pc);
2304 break;
2305 case BS_EXCP:
63205665 2306 /* fall through */
823029f9
TS
2307 case BS_BRANCH:
2308 default:
2309 break;
2310 }
fdf9b3e8 2311 }
823029f9 2312
806f352d 2313 gen_tb_end(tb, num_insns);
0a7df5da 2314
4e5e1215
RH
2315 tb->size = ctx.pc - pc_start;
2316 tb->icount = num_insns;
fdf9b3e8
FB
2317
2318#ifdef DEBUG_DISAS
4910e6e4
RH
2319 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
2320 && qemu_log_in_addr_range(pc_start)) {
1ee73216 2321 qemu_log_lock();
93fcfe39 2322 qemu_log("IN:\n"); /* , lookup_symbol(pc_start)); */
d49190c4 2323 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
93fcfe39 2324 qemu_log("\n");
1ee73216 2325 qemu_log_unlock();
fdf9b3e8 2326 }
fdf9b3e8 2327#endif
fdf9b3e8
FB
2328}
2329
bad729e2
RH
2330void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb,
2331 target_ulong *data)
d2856f1a 2332{
bad729e2
RH
2333 env->pc = data[0];
2334 env->flags = data[1];
ac9707ea
AJ
2335 /* Theoretically delayed_pc should also be restored. In practice the
2336 branch instruction is re-executed after exception, so the delayed
2337 branch target will be recomputed. */
d2856f1a 2338}