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