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