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