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