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