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