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