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