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