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