|
|
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
17: * License along with this library; if not, write to the Free Software
18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19: */
20: #include <stdarg.h>
21: #include <stdlib.h>
22: #include <stdio.h>
23: #include <string.h>
24: #include <inttypes.h>
25: #include <assert.h>
26:
27: #define DEBUG_DISAS
28: #define SH4_DEBUG_DISAS
29: //#define SH4_SINGLE_STEP
30:
31: #include "cpu.h"
32: #include "exec-all.h"
33: #include "disas.h"
34:
35: enum {
36: #define DEF(s, n, copy_size) INDEX_op_ ## s,
37: #include "opc.h"
38: #undef DEF
39: NB_OPS,
40: };
41:
42: #ifdef USE_DIRECT_JUMP
43: #define TBPARAM(x)
44: #else
45: #define TBPARAM(x) ((long)(x))
46: #endif
47:
48: static uint16_t *gen_opc_ptr;
49: static uint32_t *gen_opparam_ptr;
50:
51: #include "gen-op.h"
52:
53: typedef struct DisasContext {
54: struct TranslationBlock *tb;
55: target_ulong pc;
56: uint32_t sr;
1.1.1.2 root 57: uint32_t fpscr;
1.1 root 58: uint16_t opcode;
59: uint32_t flags;
1.1.1.3 ! root 60: int bstate;
1.1 root 61: int memidx;
62: uint32_t delayed_pc;
63: int singlestep_enabled;
64: } DisasContext;
65:
1.1.1.3 ! root 66: enum {
! 67: BS_NONE = 0, /* We go out of the TB without reaching a branch or an
! 68: * exception condition
! 69: */
! 70: BS_STOP = 1, /* We want to stop translation for any reason */
! 71: BS_BRANCH = 2, /* We reached a branch condition */
! 72: BS_EXCP = 3, /* We reached an exception condition */
! 73: };
! 74:
1.1 root 75: #ifdef CONFIG_USER_ONLY
76:
1.1.1.2 root 77: #define GEN_OP_LD(width, reg) \
78: void gen_op_ld##width##_T0_##reg (DisasContext *ctx) { \
79: gen_op_ld##width##_T0_##reg##_raw(); \
1.1 root 80: }
1.1.1.2 root 81: #define GEN_OP_ST(width, reg) \
82: void gen_op_st##width##_##reg##_T1 (DisasContext *ctx) { \
83: gen_op_st##width##_##reg##_T1_raw(); \
1.1 root 84: }
85:
86: #else
87:
1.1.1.2 root 88: #define GEN_OP_LD(width, reg) \
89: void gen_op_ld##width##_T0_##reg (DisasContext *ctx) { \
90: if (ctx->memidx) gen_op_ld##width##_T0_##reg##_kernel(); \
91: else gen_op_ld##width##_T0_##reg##_user();\
1.1 root 92: }
1.1.1.2 root 93: #define GEN_OP_ST(width, reg) \
94: void gen_op_st##width##_##reg##_T1 (DisasContext *ctx) { \
95: if (ctx->memidx) gen_op_st##width##_##reg##_T1_kernel(); \
96: else gen_op_st##width##_##reg##_T1_user();\
1.1 root 97: }
98:
99: #endif
100:
1.1.1.2 root 101: GEN_OP_LD(ub, T0)
102: GEN_OP_LD(b, T0)
103: GEN_OP_ST(b, T0)
104: GEN_OP_LD(uw, T0)
105: GEN_OP_LD(w, T0)
106: GEN_OP_ST(w, T0)
107: GEN_OP_LD(l, T0)
108: GEN_OP_ST(l, T0)
109: GEN_OP_LD(fl, FT0)
110: GEN_OP_ST(fl, FT0)
111: GEN_OP_LD(fq, DT0)
112: GEN_OP_ST(fq, DT0)
1.1 root 113:
114: void cpu_dump_state(CPUState * env, FILE * f,
115: int (*cpu_fprintf) (FILE * f, const char *fmt, ...),
116: int flags)
117: {
118: int i;
1.1.1.2 root 119: cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
120: env->pc, env->sr, env->pr, env->fpscr);
1.1 root 121: for (i = 0; i < 24; i += 4) {
122: cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
123: i, env->gregs[i], i + 1, env->gregs[i + 1],
124: i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
125: }
126: if (env->flags & DELAY_SLOT) {
127: cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
128: env->delayed_pc);
129: } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
130: cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
131: env->delayed_pc);
132: }
133: }
134:
135: void cpu_sh4_reset(CPUSH4State * env)
136: {
1.1.1.2 root 137: #if defined(CONFIG_USER_ONLY)
1.1.1.3 ! root 138: env->sr = SR_FD; /* FD - kernel does lazy fpu context switch */
1.1.1.2 root 139: #else
1.1 root 140: env->sr = 0x700000F0; /* MD, RB, BL, I3-I0 */
1.1.1.2 root 141: #endif
1.1 root 142: env->vbr = 0;
143: env->pc = 0xA0000000;
1.1.1.3 ! root 144: #if defined(CONFIG_USER_ONLY)
! 145: env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
! 146: set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
! 147: #else
! 148: env->fpscr = 0x00040001; /* CPU reset value according to SH4 manual */
! 149: set_float_rounding_mode(float_round_to_zero, &env->fp_status);
! 150: #endif
1.1 root 151: env->mmucr = 0;
152: }
153:
1.1.1.3 ! root 154: CPUSH4State *cpu_sh4_init(const char *cpu_model)
1.1 root 155: {
156: CPUSH4State *env;
157:
158: env = qemu_mallocz(sizeof(CPUSH4State));
159: if (!env)
160: return NULL;
161: cpu_exec_init(env);
162: cpu_sh4_reset(env);
163: tlb_flush(env, 1);
164: return env;
165: }
166:
167: static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
168: {
169: TranslationBlock *tb;
170: tb = ctx->tb;
171:
172: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
173: !ctx->singlestep_enabled) {
174: /* Use a direct jump if in same page and singlestep not enabled */
175: if (n == 0)
176: gen_op_goto_tb0(TBPARAM(tb));
177: else
178: gen_op_goto_tb1(TBPARAM(tb));
179: gen_op_movl_imm_T0((long) tb + n);
180: } else {
181: gen_op_movl_imm_T0(0);
182: }
183: gen_op_movl_imm_PC(dest);
184: if (ctx->singlestep_enabled)
185: gen_op_debug();
186: gen_op_exit_tb();
187: }
188:
189: static void gen_jump(DisasContext * ctx)
190: {
191: if (ctx->delayed_pc == (uint32_t) - 1) {
192: /* Target is not statically known, it comes necessarily from a
193: delayed jump as immediate jump are conditinal jumps */
194: gen_op_movl_delayed_pc_PC();
195: gen_op_movl_imm_T0(0);
196: if (ctx->singlestep_enabled)
197: gen_op_debug();
198: gen_op_exit_tb();
199: } else {
200: gen_goto_tb(ctx, 0, ctx->delayed_pc);
201: }
202: }
203:
204: /* Immediate conditional jump (bt or bf) */
205: static void gen_conditional_jump(DisasContext * ctx,
206: target_ulong ift, target_ulong ifnott)
207: {
208: int l1;
209:
210: l1 = gen_new_label();
211: gen_op_jT(l1);
212: gen_goto_tb(ctx, 0, ifnott);
213: gen_set_label(l1);
214: gen_goto_tb(ctx, 1, ift);
215: }
216:
217: /* Delayed conditional jump (bt or bf) */
218: static void gen_delayed_conditional_jump(DisasContext * ctx)
219: {
220: int l1;
221:
222: l1 = gen_new_label();
1.1.1.2 root 223: gen_op_jdelayed(l1);
1.1.1.3 ! root 224: gen_goto_tb(ctx, 1, ctx->pc + 2);
1.1 root 225: gen_set_label(l1);
1.1.1.2 root 226: gen_jump(ctx);
1.1 root 227: }
228:
229: #define B3_0 (ctx->opcode & 0xf)
230: #define B6_4 ((ctx->opcode >> 4) & 0x7)
231: #define B7_4 ((ctx->opcode >> 4) & 0xf)
232: #define B7_0 (ctx->opcode & 0xff)
233: #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
234: #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
235: (ctx->opcode & 0xfff))
236: #define B11_8 ((ctx->opcode >> 8) & 0xf)
237: #define B15_12 ((ctx->opcode >> 12) & 0xf)
238:
239: #define REG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB) ? \
240: (x) + 16 : (x))
241:
242: #define ALTREG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) != (SR_MD | SR_RB) \
243: ? (x) + 16 : (x))
244:
1.1.1.2 root 245: #define FREG(x) (ctx->fpscr & FPSCR_FR ? (x) ^ 0x10 : (x))
1.1.1.3 ! root 246: #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
1.1.1.2 root 247: #define XREG(x) (ctx->fpscr & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x))
1.1.1.3 ! root 248: #define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */
1.1.1.2 root 249:
1.1 root 250: #define CHECK_NOT_DELAY_SLOT \
251: if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
1.1.1.3 ! root 252: {gen_op_raise_slot_illegal_instruction (); ctx->bstate = BS_EXCP; \
1.1 root 253: return;}
254:
1.1.1.3 ! root 255: void _decode_opc(DisasContext * ctx)
1.1 root 256: {
257: #if 0
258: fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
259: #endif
260: switch (ctx->opcode) {
261: case 0x0019: /* div0u */
262: gen_op_div0u();
263: return;
264: case 0x000b: /* rts */
265: CHECK_NOT_DELAY_SLOT gen_op_rts();
266: ctx->flags |= DELAY_SLOT;
267: ctx->delayed_pc = (uint32_t) - 1;
268: return;
269: case 0x0028: /* clrmac */
270: gen_op_clrmac();
271: return;
272: case 0x0048: /* clrs */
273: gen_op_clrs();
274: return;
275: case 0x0008: /* clrt */
276: gen_op_clrt();
277: return;
278: case 0x0038: /* ldtlb */
279: assert(0); /* XXXXX */
280: return;
1.1.1.3 ! root 281: case 0x002b: /* rte */
1.1 root 282: CHECK_NOT_DELAY_SLOT gen_op_rte();
283: ctx->flags |= DELAY_SLOT;
284: ctx->delayed_pc = (uint32_t) - 1;
285: return;
286: case 0x0058: /* sets */
287: gen_op_sets();
288: return;
289: case 0x0018: /* sett */
290: gen_op_sett();
291: return;
292: case 0xfbfb: /* frchg */
1.1.1.2 root 293: gen_op_frchg();
1.1.1.3 ! root 294: ctx->bstate = BS_STOP;
1.1 root 295: return;
296: case 0xf3fb: /* fschg */
1.1.1.2 root 297: gen_op_fschg();
1.1.1.3 ! root 298: ctx->bstate = BS_STOP;
1.1 root 299: return;
300: case 0x0009: /* nop */
301: return;
302: case 0x001b: /* sleep */
303: assert(0); /* XXXXX */
304: return;
305: }
306:
307: switch (ctx->opcode & 0xf000) {
308: case 0x1000: /* mov.l Rm,@(disp,Rn) */
309: gen_op_movl_rN_T0(REG(B7_4));
310: gen_op_movl_rN_T1(REG(B11_8));
311: gen_op_addl_imm_T1(B3_0 * 4);
312: gen_op_stl_T0_T1(ctx);
313: return;
314: case 0x5000: /* mov.l @(disp,Rm),Rn */
315: gen_op_movl_rN_T0(REG(B7_4));
316: gen_op_addl_imm_T0(B3_0 * 4);
317: gen_op_ldl_T0_T0(ctx);
318: gen_op_movl_T0_rN(REG(B11_8));
319: return;
320: case 0xe000: /* mov.l #imm,Rn */
321: gen_op_movl_imm_rN(B7_0s, REG(B11_8));
322: return;
323: case 0x9000: /* mov.w @(disp,PC),Rn */
324: gen_op_movl_imm_T0(ctx->pc + 4 + B7_0 * 2);
325: gen_op_ldw_T0_T0(ctx);
326: gen_op_movl_T0_rN(REG(B11_8));
327: return;
328: case 0xd000: /* mov.l @(disp,PC),Rn */
329: gen_op_movl_imm_T0((ctx->pc + 4 + B7_0 * 4) & ~3);
330: gen_op_ldl_T0_T0(ctx);
331: gen_op_movl_T0_rN(REG(B11_8));
332: return;
333: case 0x7000: /* add.l #imm,Rn */
334: gen_op_add_imm_rN(B7_0s, REG(B11_8));
335: return;
336: case 0xa000: /* bra disp */
337: CHECK_NOT_DELAY_SLOT
338: gen_op_bra(ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2);
339: ctx->flags |= DELAY_SLOT;
340: return;
341: case 0xb000: /* bsr disp */
342: CHECK_NOT_DELAY_SLOT
343: gen_op_bsr(ctx->pc + 4, ctx->delayed_pc =
344: ctx->pc + 4 + B11_0s * 2);
345: ctx->flags |= DELAY_SLOT;
346: return;
347: }
348:
349: switch (ctx->opcode & 0xf00f) {
350: case 0x6003: /* mov Rm,Rn */
351: gen_op_movl_rN_T0(REG(B7_4));
352: gen_op_movl_T0_rN(REG(B11_8));
353: return;
354: case 0x2000: /* mov.b Rm,@Rn */
355: gen_op_movl_rN_T0(REG(B7_4));
356: gen_op_movl_rN_T1(REG(B11_8));
357: gen_op_stb_T0_T1(ctx);
358: return;
359: case 0x2001: /* mov.w Rm,@Rn */
360: gen_op_movl_rN_T0(REG(B7_4));
361: gen_op_movl_rN_T1(REG(B11_8));
362: gen_op_stw_T0_T1(ctx);
363: return;
364: case 0x2002: /* mov.l Rm,@Rn */
365: gen_op_movl_rN_T0(REG(B7_4));
366: gen_op_movl_rN_T1(REG(B11_8));
367: gen_op_stl_T0_T1(ctx);
368: return;
369: case 0x6000: /* mov.b @Rm,Rn */
370: gen_op_movl_rN_T0(REG(B7_4));
371: gen_op_ldb_T0_T0(ctx);
372: gen_op_movl_T0_rN(REG(B11_8));
373: return;
374: case 0x6001: /* mov.w @Rm,Rn */
375: gen_op_movl_rN_T0(REG(B7_4));
376: gen_op_ldw_T0_T0(ctx);
377: gen_op_movl_T0_rN(REG(B11_8));
378: return;
379: case 0x6002: /* mov.l @Rm,Rn */
380: gen_op_movl_rN_T0(REG(B7_4));
381: gen_op_ldl_T0_T0(ctx);
382: gen_op_movl_T0_rN(REG(B11_8));
383: return;
384: case 0x2004: /* mov.b Rm,@-Rn */
385: gen_op_dec1_rN(REG(B11_8));
386: gen_op_movl_rN_T0(REG(B7_4));
387: gen_op_movl_rN_T1(REG(B11_8));
388: gen_op_stb_T0_T1(ctx);
389: return;
390: case 0x2005: /* mov.w Rm,@-Rn */
391: gen_op_dec2_rN(REG(B11_8));
392: gen_op_movl_rN_T0(REG(B7_4));
393: gen_op_movl_rN_T1(REG(B11_8));
394: gen_op_stw_T0_T1(ctx);
395: return;
396: case 0x2006: /* mov.l Rm,@-Rn */
397: gen_op_dec4_rN(REG(B11_8));
398: gen_op_movl_rN_T0(REG(B7_4));
399: gen_op_movl_rN_T1(REG(B11_8));
400: gen_op_stl_T0_T1(ctx);
401: return;
1.1.1.2 root 402: case 0x6004: /* mov.b @Rm+,Rn */
1.1 root 403: gen_op_movl_rN_T0(REG(B7_4));
404: gen_op_ldb_T0_T0(ctx);
405: gen_op_movl_T0_rN(REG(B11_8));
406: gen_op_inc1_rN(REG(B7_4));
407: return;
408: case 0x6005: /* mov.w @Rm+,Rn */
409: gen_op_movl_rN_T0(REG(B7_4));
410: gen_op_ldw_T0_T0(ctx);
411: gen_op_movl_T0_rN(REG(B11_8));
412: gen_op_inc2_rN(REG(B7_4));
413: return;
414: case 0x6006: /* mov.l @Rm+,Rn */
415: gen_op_movl_rN_T0(REG(B7_4));
416: gen_op_ldl_T0_T0(ctx);
417: gen_op_movl_T0_rN(REG(B11_8));
418: gen_op_inc4_rN(REG(B7_4));
419: return;
420: case 0x0004: /* mov.b Rm,@(R0,Rn) */
421: gen_op_movl_rN_T0(REG(B7_4));
422: gen_op_movl_rN_T1(REG(B11_8));
423: gen_op_add_rN_T1(REG(0));
424: gen_op_stb_T0_T1(ctx);
425: return;
426: case 0x0005: /* mov.w Rm,@(R0,Rn) */
427: gen_op_movl_rN_T0(REG(B7_4));
428: gen_op_movl_rN_T1(REG(B11_8));
429: gen_op_add_rN_T1(REG(0));
430: gen_op_stw_T0_T1(ctx);
431: return;
432: case 0x0006: /* mov.l Rm,@(R0,Rn) */
433: gen_op_movl_rN_T0(REG(B7_4));
434: gen_op_movl_rN_T1(REG(B11_8));
435: gen_op_add_rN_T1(REG(0));
436: gen_op_stl_T0_T1(ctx);
437: return;
438: case 0x000c: /* mov.b @(R0,Rm),Rn */
439: gen_op_movl_rN_T0(REG(B7_4));
440: gen_op_add_rN_T0(REG(0));
441: gen_op_ldb_T0_T0(ctx);
442: gen_op_movl_T0_rN(REG(B11_8));
443: return;
444: case 0x000d: /* mov.w @(R0,Rm),Rn */
445: gen_op_movl_rN_T0(REG(B7_4));
446: gen_op_add_rN_T0(REG(0));
447: gen_op_ldw_T0_T0(ctx);
448: gen_op_movl_T0_rN(REG(B11_8));
449: return;
450: case 0x000e: /* mov.l @(R0,Rm),Rn */
451: gen_op_movl_rN_T0(REG(B7_4));
452: gen_op_add_rN_T0(REG(0));
453: gen_op_ldl_T0_T0(ctx);
454: gen_op_movl_T0_rN(REG(B11_8));
455: return;
456: case 0x6008: /* swap.b Rm,Rn */
457: gen_op_movl_rN_T0(REG(B7_4));
458: gen_op_swapb_T0();
459: gen_op_movl_T0_rN(REG(B11_8));
460: return;
461: case 0x6009: /* swap.w Rm,Rn */
462: gen_op_movl_rN_T0(REG(B7_4));
463: gen_op_swapw_T0();
464: gen_op_movl_T0_rN(REG(B11_8));
465: return;
466: case 0x200d: /* xtrct Rm,Rn */
467: gen_op_movl_rN_T0(REG(B7_4));
468: gen_op_movl_rN_T1(REG(B11_8));
469: gen_op_xtrct_T0_T1();
470: gen_op_movl_T1_rN(REG(B11_8));
471: return;
472: case 0x300c: /* add Rm,Rn */
473: gen_op_movl_rN_T0(REG(B7_4));
474: gen_op_add_T0_rN(REG(B11_8));
475: return;
476: case 0x300e: /* addc Rm,Rn */
477: gen_op_movl_rN_T0(REG(B7_4));
478: gen_op_movl_rN_T1(REG(B11_8));
479: gen_op_addc_T0_T1();
480: gen_op_movl_T1_rN(REG(B11_8));
481: return;
482: case 0x300f: /* addv Rm,Rn */
483: gen_op_movl_rN_T0(REG(B7_4));
484: gen_op_movl_rN_T1(REG(B11_8));
485: gen_op_addv_T0_T1();
486: gen_op_movl_T1_rN(REG(B11_8));
487: return;
488: case 0x2009: /* and Rm,Rn */
489: gen_op_movl_rN_T0(REG(B7_4));
490: gen_op_and_T0_rN(REG(B11_8));
491: return;
492: case 0x3000: /* cmp/eq Rm,Rn */
493: gen_op_movl_rN_T0(REG(B7_4));
494: gen_op_movl_rN_T1(REG(B11_8));
495: gen_op_cmp_eq_T0_T1();
496: return;
497: case 0x3003: /* cmp/ge Rm,Rn */
498: gen_op_movl_rN_T0(REG(B7_4));
499: gen_op_movl_rN_T1(REG(B11_8));
500: gen_op_cmp_ge_T0_T1();
501: return;
502: case 0x3007: /* cmp/gt Rm,Rn */
503: gen_op_movl_rN_T0(REG(B7_4));
504: gen_op_movl_rN_T1(REG(B11_8));
505: gen_op_cmp_gt_T0_T1();
506: return;
507: case 0x3006: /* cmp/hi Rm,Rn */
508: gen_op_movl_rN_T0(REG(B7_4));
509: gen_op_movl_rN_T1(REG(B11_8));
510: gen_op_cmp_hi_T0_T1();
511: return;
512: case 0x3002: /* cmp/hs Rm,Rn */
513: gen_op_movl_rN_T0(REG(B7_4));
514: gen_op_movl_rN_T1(REG(B11_8));
515: gen_op_cmp_hs_T0_T1();
516: return;
517: case 0x200c: /* cmp/str Rm,Rn */
518: gen_op_movl_rN_T0(REG(B7_4));
519: gen_op_movl_rN_T1(REG(B11_8));
520: gen_op_cmp_str_T0_T1();
521: return;
522: case 0x2007: /* div0s Rm,Rn */
523: gen_op_movl_rN_T0(REG(B7_4));
524: gen_op_movl_rN_T1(REG(B11_8));
525: gen_op_div0s_T0_T1();
526: gen_op_movl_T1_rN(REG(B11_8));
527: return;
528: case 0x3004: /* div1 Rm,Rn */
529: gen_op_movl_rN_T0(REG(B7_4));
530: gen_op_movl_rN_T1(REG(B11_8));
531: gen_op_div1_T0_T1();
532: gen_op_movl_T1_rN(REG(B11_8));
533: return;
534: case 0x300d: /* dmuls.l Rm,Rn */
535: gen_op_movl_rN_T0(REG(B7_4));
536: gen_op_movl_rN_T1(REG(B11_8));
537: gen_op_dmulsl_T0_T1();
538: return;
539: case 0x3005: /* dmulu.l Rm,Rn */
540: gen_op_movl_rN_T0(REG(B7_4));
541: gen_op_movl_rN_T1(REG(B11_8));
542: gen_op_dmulul_T0_T1();
543: return;
544: case 0x600e: /* exts.b Rm,Rn */
545: gen_op_movb_rN_T0(REG(B7_4));
546: gen_op_movl_T0_rN(REG(B11_8));
547: return;
548: case 0x600f: /* exts.w Rm,Rn */
549: gen_op_movw_rN_T0(REG(B7_4));
550: gen_op_movl_T0_rN(REG(B11_8));
551: return;
552: case 0x600c: /* extu.b Rm,Rn */
553: gen_op_movub_rN_T0(REG(B7_4));
554: gen_op_movl_T0_rN(REG(B11_8));
555: return;
556: case 0x600d: /* extu.w Rm,Rn */
557: gen_op_movuw_rN_T0(REG(B7_4));
558: gen_op_movl_T0_rN(REG(B11_8));
559: return;
560: case 0x000f: /* mac.l @Rm+,@Rn- */
561: gen_op_movl_rN_T0(REG(B11_8));
562: gen_op_ldl_T0_T0(ctx);
563: gen_op_movl_T0_T1();
564: gen_op_movl_rN_T1(REG(B7_4));
565: gen_op_ldl_T0_T0(ctx);
566: gen_op_macl_T0_T1();
567: gen_op_inc4_rN(REG(B7_4));
568: gen_op_inc4_rN(REG(B11_8));
569: return;
570: case 0x400f: /* mac.w @Rm+,@Rn+ */
571: gen_op_movl_rN_T0(REG(B11_8));
572: gen_op_ldl_T0_T0(ctx);
573: gen_op_movl_T0_T1();
574: gen_op_movl_rN_T1(REG(B7_4));
575: gen_op_ldl_T0_T0(ctx);
576: gen_op_macw_T0_T1();
577: gen_op_inc2_rN(REG(B7_4));
578: gen_op_inc2_rN(REG(B11_8));
579: return;
580: case 0x0007: /* mul.l Rm,Rn */
581: gen_op_movl_rN_T0(REG(B7_4));
582: gen_op_movl_rN_T1(REG(B11_8));
583: gen_op_mull_T0_T1();
584: return;
585: case 0x200f: /* muls.w Rm,Rn */
586: gen_op_movw_rN_T0(REG(B7_4));
587: gen_op_movw_rN_T1(REG(B11_8));
588: gen_op_mulsw_T0_T1();
589: return;
590: case 0x200e: /* mulu.w Rm,Rn */
591: gen_op_movuw_rN_T0(REG(B7_4));
592: gen_op_movuw_rN_T1(REG(B11_8));
593: gen_op_muluw_T0_T1();
594: return;
595: case 0x600b: /* neg Rm,Rn */
596: gen_op_movl_rN_T0(REG(B7_4));
597: gen_op_neg_T0();
598: gen_op_movl_T0_rN(REG(B11_8));
599: return;
600: case 0x600a: /* negc Rm,Rn */
601: gen_op_movl_rN_T0(REG(B7_4));
602: gen_op_negc_T0();
603: gen_op_movl_T0_rN(REG(B11_8));
604: return;
605: case 0x6007: /* not Rm,Rn */
606: gen_op_movl_rN_T0(REG(B7_4));
607: gen_op_not_T0();
608: gen_op_movl_T0_rN(REG(B11_8));
609: return;
610: case 0x200b: /* or Rm,Rn */
611: gen_op_movl_rN_T0(REG(B7_4));
612: gen_op_or_T0_rN(REG(B11_8));
613: return;
614: case 0x400c: /* shad Rm,Rn */
615: gen_op_movl_rN_T0(REG(B7_4));
616: gen_op_movl_rN_T1(REG(B11_8));
617: gen_op_shad_T0_T1();
618: gen_op_movl_T1_rN(REG(B11_8));
619: return;
620: case 0x400d: /* shld Rm,Rn */
621: gen_op_movl_rN_T0(REG(B7_4));
622: gen_op_movl_rN_T1(REG(B11_8));
623: gen_op_shld_T0_T1();
624: gen_op_movl_T1_rN(REG(B11_8));
625: return;
626: case 0x3008: /* sub Rm,Rn */
627: gen_op_movl_rN_T0(REG(B7_4));
628: gen_op_sub_T0_rN(REG(B11_8));
629: return;
630: case 0x300a: /* subc Rm,Rn */
631: gen_op_movl_rN_T0(REG(B7_4));
632: gen_op_movl_rN_T1(REG(B11_8));
633: gen_op_subc_T0_T1();
634: gen_op_movl_T1_rN(REG(B11_8));
635: return;
636: case 0x300b: /* subv Rm,Rn */
637: gen_op_movl_rN_T0(REG(B7_4));
638: gen_op_movl_rN_T1(REG(B11_8));
639: gen_op_subv_T0_T1();
640: gen_op_movl_T1_rN(REG(B11_8));
641: return;
642: case 0x2008: /* tst Rm,Rn */
643: gen_op_movl_rN_T0(REG(B7_4));
644: gen_op_movl_rN_T1(REG(B11_8));
645: gen_op_tst_T0_T1();
646: return;
647: case 0x200a: /* xor Rm,Rn */
648: gen_op_movl_rN_T0(REG(B7_4));
649: gen_op_xor_T0_rN(REG(B11_8));
650: return;
1.1.1.3 ! root 651: case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
! 652: if (ctx->fpscr & FPSCR_SZ) {
1.1.1.2 root 653: if (ctx->opcode & 0x0110)
654: break; /* illegal instruction */
1.1.1.3 ! root 655: gen_op_fmov_drN_DT0(DREG(B7_4));
! 656: gen_op_fmov_DT0_drN(DREG(B11_8));
1.1.1.2 root 657: } else {
658: gen_op_fmov_frN_FT0(FREG(B7_4));
659: gen_op_fmov_FT0_frN(FREG(B11_8));
660: }
661: return;
1.1.1.3 ! root 662: case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
! 663: if (ctx->fpscr & FPSCR_SZ) {
1.1.1.2 root 664: if (ctx->opcode & 0x0010)
665: break; /* illegal instruction */
1.1.1.3 ! root 666: gen_op_fmov_drN_DT0(DREG(B7_4));
1.1.1.2 root 667: gen_op_movl_rN_T1(REG(B11_8));
668: gen_op_stfq_DT0_T1(ctx);
669: } else {
670: gen_op_fmov_frN_FT0(FREG(B7_4));
671: gen_op_movl_rN_T1(REG(B11_8));
672: gen_op_stfl_FT0_T1(ctx);
673: }
674: return;
1.1.1.3 ! root 675: case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
! 676: if (ctx->fpscr & FPSCR_SZ) {
1.1.1.2 root 677: if (ctx->opcode & 0x0100)
678: break; /* illegal instruction */
679: gen_op_movl_rN_T0(REG(B7_4));
680: gen_op_ldfq_T0_DT0(ctx);
1.1.1.3 ! root 681: gen_op_fmov_DT0_drN(DREG(B11_8));
1.1.1.2 root 682: } else {
683: gen_op_movl_rN_T0(REG(B7_4));
684: gen_op_ldfl_T0_FT0(ctx);
1.1.1.3 ! root 685: gen_op_fmov_FT0_frN(FREG(B11_8));
1.1.1.2 root 686: }
687: return;
1.1.1.3 ! root 688: case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
! 689: if (ctx->fpscr & FPSCR_SZ) {
1.1.1.2 root 690: if (ctx->opcode & 0x0100)
691: break; /* illegal instruction */
692: gen_op_movl_rN_T0(REG(B7_4));
693: gen_op_ldfq_T0_DT0(ctx);
1.1.1.3 ! root 694: gen_op_fmov_DT0_drN(DREG(B11_8));
1.1.1.2 root 695: gen_op_inc8_rN(REG(B7_4));
696: } else {
697: gen_op_movl_rN_T0(REG(B7_4));
698: gen_op_ldfl_T0_FT0(ctx);
1.1.1.3 ! root 699: gen_op_fmov_FT0_frN(FREG(B11_8));
1.1.1.2 root 700: gen_op_inc4_rN(REG(B7_4));
701: }
702: return;
1.1.1.3 ! root 703: case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
! 704: if (ctx->fpscr & FPSCR_SZ) {
1.1.1.2 root 705: if (ctx->opcode & 0x0100)
706: break; /* illegal instruction */
707: gen_op_dec8_rN(REG(B11_8));
1.1.1.3 ! root 708: gen_op_fmov_drN_DT0(DREG(B7_4));
1.1.1.2 root 709: gen_op_movl_rN_T1(REG(B11_8));
710: gen_op_stfq_DT0_T1(ctx);
711: } else {
712: gen_op_dec4_rN(REG(B11_8));
713: gen_op_fmov_frN_FT0(FREG(B7_4));
714: gen_op_movl_rN_T1(REG(B11_8));
715: gen_op_stfl_FT0_T1(ctx);
716: }
717: return;
1.1.1.3 ! root 718: case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
! 719: if (ctx->fpscr & FPSCR_SZ) {
1.1.1.2 root 720: if (ctx->opcode & 0x0100)
721: break; /* illegal instruction */
722: gen_op_movl_rN_T0(REG(B7_4));
723: gen_op_add_rN_T0(REG(0));
724: gen_op_ldfq_T0_DT0(ctx);
1.1.1.3 ! root 725: gen_op_fmov_DT0_drN(DREG(B11_8));
1.1.1.2 root 726: } else {
727: gen_op_movl_rN_T0(REG(B7_4));
728: gen_op_add_rN_T0(REG(0));
729: gen_op_ldfl_T0_FT0(ctx);
1.1.1.3 ! root 730: gen_op_fmov_FT0_frN(FREG(B11_8));
1.1.1.2 root 731: }
732: return;
1.1.1.3 ! root 733: case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
! 734: if (ctx->fpscr & FPSCR_SZ) {
1.1.1.2 root 735: if (ctx->opcode & 0x0010)
736: break; /* illegal instruction */
1.1.1.3 ! root 737: gen_op_fmov_drN_DT0(DREG(B7_4));
1.1.1.2 root 738: gen_op_movl_rN_T1(REG(B11_8));
739: gen_op_add_rN_T1(REG(0));
740: gen_op_stfq_DT0_T1(ctx);
741: } else {
742: gen_op_fmov_frN_FT0(FREG(B7_4));
743: gen_op_movl_rN_T1(REG(B11_8));
744: gen_op_add_rN_T1(REG(0));
745: gen_op_stfl_FT0_T1(ctx);
746: }
747: return;
1.1.1.3 ! root 748: case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
! 749: case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
! 750: case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
! 751: case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
! 752: case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
! 753: case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
! 754: if (ctx->fpscr & FPSCR_PR) {
! 755: if (ctx->opcode & 0x0110)
! 756: break; /* illegal instruction */
! 757: gen_op_fmov_drN_DT1(DREG(B7_4));
! 758: gen_op_fmov_drN_DT0(DREG(B11_8));
! 759: }
! 760: else {
! 761: gen_op_fmov_frN_FT1(FREG(B7_4));
! 762: gen_op_fmov_frN_FT0(FREG(B11_8));
! 763: }
! 764:
! 765: switch (ctx->opcode & 0xf00f) {
! 766: case 0xf000: /* fadd Rm,Rn */
! 767: ctx->fpscr & FPSCR_PR ? gen_op_fadd_DT() : gen_op_fadd_FT();
! 768: break;
! 769: case 0xf001: /* fsub Rm,Rn */
! 770: ctx->fpscr & FPSCR_PR ? gen_op_fsub_DT() : gen_op_fsub_FT();
! 771: break;
! 772: case 0xf002: /* fmul Rm,Rn */
! 773: ctx->fpscr & FPSCR_PR ? gen_op_fmul_DT() : gen_op_fmul_FT();
! 774: break;
! 775: case 0xf003: /* fdiv Rm,Rn */
! 776: ctx->fpscr & FPSCR_PR ? gen_op_fdiv_DT() : gen_op_fdiv_FT();
! 777: break;
! 778: case 0xf004: /* fcmp/eq Rm,Rn */
! 779: return;
! 780: case 0xf005: /* fcmp/gt Rm,Rn */
! 781: return;
! 782: }
! 783:
! 784: if (ctx->fpscr & FPSCR_PR) {
! 785: gen_op_fmov_DT0_drN(DREG(B11_8));
! 786: }
! 787: else {
! 788: gen_op_fmov_FT0_frN(FREG(B11_8));
! 789: }
! 790: return;
1.1 root 791: }
792:
793: switch (ctx->opcode & 0xff00) {
794: case 0xc900: /* and #imm,R0 */
795: gen_op_and_imm_rN(B7_0, REG(0));
796: return;
797: case 0xcd00: /* and.b #imm,@(R0+GBR) */
798: gen_op_movl_rN_T0(REG(0));
799: gen_op_addl_GBR_T0();
800: gen_op_movl_T0_T1();
801: gen_op_ldb_T0_T0(ctx);
802: gen_op_and_imm_T0(B7_0);
803: gen_op_stb_T0_T1(ctx);
804: return;
805: case 0x8b00: /* bf label */
806: CHECK_NOT_DELAY_SLOT
807: gen_conditional_jump(ctx, ctx->pc + 2,
808: ctx->pc + 4 + B7_0s * 2);
1.1.1.3 ! root 809: ctx->bstate = BS_BRANCH;
1.1 root 810: return;
811: case 0x8f00: /* bf/s label */
812: CHECK_NOT_DELAY_SLOT
813: gen_op_bf_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
814: ctx->flags |= DELAY_SLOT_CONDITIONAL;
815: return;
816: case 0x8900: /* bt label */
817: CHECK_NOT_DELAY_SLOT
818: gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2,
819: ctx->pc + 2);
1.1.1.3 ! root 820: ctx->bstate = BS_BRANCH;
1.1 root 821: return;
822: case 0x8d00: /* bt/s label */
823: CHECK_NOT_DELAY_SLOT
824: gen_op_bt_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
825: ctx->flags |= DELAY_SLOT_CONDITIONAL;
826: return;
827: case 0x8800: /* cmp/eq #imm,R0 */
828: gen_op_movl_rN_T0(REG(0));
829: gen_op_cmp_eq_imm_T0(B7_0s);
830: return;
831: case 0xc400: /* mov.b @(disp,GBR),R0 */
832: gen_op_stc_gbr_T0();
833: gen_op_addl_imm_T0(B7_0);
834: gen_op_ldb_T0_T0(ctx);
835: gen_op_movl_T0_rN(REG(0));
836: return;
837: case 0xc500: /* mov.w @(disp,GBR),R0 */
838: gen_op_stc_gbr_T0();
839: gen_op_addl_imm_T0(B7_0);
840: gen_op_ldw_T0_T0(ctx);
841: gen_op_movl_T0_rN(REG(0));
842: return;
843: case 0xc600: /* mov.l @(disp,GBR),R0 */
844: gen_op_stc_gbr_T0();
845: gen_op_addl_imm_T0(B7_0);
846: gen_op_ldl_T0_T0(ctx);
847: gen_op_movl_T0_rN(REG(0));
848: return;
849: case 0xc000: /* mov.b R0,@(disp,GBR) */
850: gen_op_stc_gbr_T0();
851: gen_op_addl_imm_T0(B7_0);
852: gen_op_movl_T0_T1();
853: gen_op_movl_rN_T0(REG(0));
854: gen_op_stb_T0_T1(ctx);
855: return;
856: case 0xc100: /* mov.w R0,@(disp,GBR) */
857: gen_op_stc_gbr_T0();
858: gen_op_addl_imm_T0(B7_0);
859: gen_op_movl_T0_T1();
860: gen_op_movl_rN_T0(REG(0));
861: gen_op_stw_T0_T1(ctx);
862: return;
863: case 0xc200: /* mov.l R0,@(disp,GBR) */
864: gen_op_stc_gbr_T0();
865: gen_op_addl_imm_T0(B7_0);
866: gen_op_movl_T0_T1();
867: gen_op_movl_rN_T0(REG(0));
868: gen_op_stl_T0_T1(ctx);
869: return;
870: case 0x8000: /* mov.b R0,@(disp,Rn) */
871: gen_op_movl_rN_T0(REG(0));
872: gen_op_movl_rN_T1(REG(B7_4));
873: gen_op_addl_imm_T1(B3_0);
874: gen_op_stb_T0_T1(ctx);
875: return;
876: case 0x8100: /* mov.w R0,@(disp,Rn) */
877: gen_op_movl_rN_T0(REG(0));
878: gen_op_movl_rN_T1(REG(B7_4));
879: gen_op_addl_imm_T1(B3_0 * 2);
880: gen_op_stw_T0_T1(ctx);
881: return;
882: case 0x8400: /* mov.b @(disp,Rn),R0 */
1.1.1.3 ! root 883: gen_op_movl_rN_T0(REG(B7_4));
! 884: gen_op_addl_imm_T0(B3_0);
! 885: gen_op_ldb_T0_T0(ctx);
! 886: gen_op_movl_T0_rN(REG(0));
1.1 root 887: return;
888: case 0x8500: /* mov.w @(disp,Rn),R0 */
889: gen_op_movl_rN_T0(REG(B7_4));
890: gen_op_addl_imm_T0(B3_0 * 2);
891: gen_op_ldw_T0_T0(ctx);
892: gen_op_movl_T0_rN(REG(0));
893: return;
894: case 0xc700: /* mova @(disp,PC),R0 */
895: gen_op_movl_imm_rN(((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3,
896: REG(0));
897: return;
898: case 0xcb00: /* or #imm,R0 */
899: gen_op_or_imm_rN(B7_0, REG(0));
900: return;
901: case 0xcf00: /* or.b #imm,@(R0+GBR) */
902: gen_op_movl_rN_T0(REG(0));
903: gen_op_addl_GBR_T0();
904: gen_op_movl_T0_T1();
905: gen_op_ldb_T0_T0(ctx);
906: gen_op_or_imm_T0(B7_0);
907: gen_op_stb_T0_T1(ctx);
908: return;
909: case 0xc300: /* trapa #imm */
910: CHECK_NOT_DELAY_SLOT gen_op_movl_imm_PC(ctx->pc);
911: gen_op_trapa(B7_0);
1.1.1.3 ! root 912: ctx->bstate = BS_BRANCH;
1.1 root 913: return;
914: case 0xc800: /* tst #imm,R0 */
915: gen_op_tst_imm_rN(B7_0, REG(0));
916: return;
917: case 0xcc00: /* tst #imm,@(R0+GBR) */
918: gen_op_movl_rN_T0(REG(0));
919: gen_op_addl_GBR_T0();
920: gen_op_ldb_T0_T0(ctx);
921: gen_op_tst_imm_T0(B7_0);
922: return;
923: case 0xca00: /* xor #imm,R0 */
924: gen_op_xor_imm_rN(B7_0, REG(0));
925: return;
926: case 0xce00: /* xor.b #imm,@(R0+GBR) */
927: gen_op_movl_rN_T0(REG(0));
928: gen_op_addl_GBR_T0();
929: gen_op_movl_T0_T1();
930: gen_op_ldb_T0_T0(ctx);
931: gen_op_xor_imm_T0(B7_0);
932: gen_op_stb_T0_T1(ctx);
933: return;
934: }
935:
936: switch (ctx->opcode & 0xf08f) {
937: case 0x408e: /* ldc Rm,Rn_BANK */
938: gen_op_movl_rN_rN(REG(B11_8), ALTREG(B6_4));
939: return;
940: case 0x4087: /* ldc.l @Rm+,Rn_BANK */
941: gen_op_movl_rN_T0(REG(B11_8));
942: gen_op_ldl_T0_T0(ctx);
943: gen_op_movl_T0_rN(ALTREG(B6_4));
944: gen_op_inc4_rN(REG(B11_8));
945: return;
946: case 0x0082: /* stc Rm_BANK,Rn */
947: gen_op_movl_rN_rN(ALTREG(B6_4), REG(B11_8));
948: return;
949: case 0x4083: /* stc.l Rm_BANK,@-Rn */
950: gen_op_dec4_rN(REG(B11_8));
951: gen_op_movl_rN_T1(REG(B11_8));
952: gen_op_movl_rN_T0(ALTREG(B6_4));
953: gen_op_stl_T0_T1(ctx);
954: return;
955: }
956:
957: switch (ctx->opcode & 0xf0ff) {
958: case 0x0023: /* braf Rn */
959: CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
960: gen_op_braf_T0(ctx->pc + 4);
961: ctx->flags |= DELAY_SLOT;
962: ctx->delayed_pc = (uint32_t) - 1;
963: return;
964: case 0x0003: /* bsrf Rn */
965: CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
966: gen_op_bsrf_T0(ctx->pc + 4);
967: ctx->flags |= DELAY_SLOT;
968: ctx->delayed_pc = (uint32_t) - 1;
969: return;
970: case 0x4015: /* cmp/pl Rn */
971: gen_op_movl_rN_T0(REG(B11_8));
972: gen_op_cmp_pl_T0();
973: return;
974: case 0x4011: /* cmp/pz Rn */
975: gen_op_movl_rN_T0(REG(B11_8));
976: gen_op_cmp_pz_T0();
977: return;
978: case 0x4010: /* dt Rn */
979: gen_op_dt_rN(REG(B11_8));
980: return;
981: case 0x402b: /* jmp @Rn */
982: CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
983: gen_op_jmp_T0();
984: ctx->flags |= DELAY_SLOT;
985: ctx->delayed_pc = (uint32_t) - 1;
986: return;
987: case 0x400b: /* jsr @Rn */
988: CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
989: gen_op_jsr_T0(ctx->pc + 4);
990: ctx->flags |= DELAY_SLOT;
991: ctx->delayed_pc = (uint32_t) - 1;
992: return;
993: #define LDST(reg,ldnum,ldpnum,ldop,stnum,stpnum,stop,extrald) \
994: case ldnum: \
995: gen_op_movl_rN_T0 (REG(B11_8)); \
996: gen_op_##ldop##_T0_##reg (); \
997: extrald \
998: return; \
999: case ldpnum: \
1000: gen_op_movl_rN_T0 (REG(B11_8)); \
1001: gen_op_ldl_T0_T0 (ctx); \
1002: gen_op_inc4_rN (REG(B11_8)); \
1003: gen_op_##ldop##_T0_##reg (); \
1004: extrald \
1005: return; \
1006: case stnum: \
1007: gen_op_##stop##_##reg##_T0 (); \
1008: gen_op_movl_T0_rN (REG(B11_8)); \
1009: return; \
1010: case stpnum: \
1011: gen_op_##stop##_##reg##_T0 (); \
1012: gen_op_dec4_rN (REG(B11_8)); \
1013: gen_op_movl_rN_T1 (REG(B11_8)); \
1014: gen_op_stl_T0_T1 (ctx); \
1015: return;
1.1.1.3 ! root 1016: LDST(sr, 0x400e, 0x4007, ldc, 0x0002, 0x4003, stc, ctx->bstate =
! 1017: BS_STOP;)
1.1.1.2 root 1018: LDST(gbr, 0x401e, 0x4017, ldc, 0x0012, 0x4013, stc,)
1019: LDST(vbr, 0x402e, 0x4027, ldc, 0x0022, 0x4023, stc,)
1020: LDST(ssr, 0x403e, 0x4037, ldc, 0x0032, 0x4033, stc,)
1021: LDST(spc, 0x404e, 0x4047, ldc, 0x0042, 0x4043, stc,)
1022: LDST(dbr, 0x40fa, 0x40f6, ldc, 0x00fa, 0x40f2, stc,)
1023: LDST(mach, 0x400a, 0x4006, lds, 0x000a, 0x4002, sts,)
1024: LDST(macl, 0x401a, 0x4016, lds, 0x001a, 0x4012, sts,)
1025: LDST(pr, 0x402a, 0x4026, lds, 0x002a, 0x4022, sts,)
1.1.1.3 ! root 1026: LDST(fpul, 0x405a, 0x4056, lds, 0x005a, 0x4052, sts,)
! 1027: LDST(fpscr, 0x406a, 0x4066, lds, 0x006a, 0x4062, sts, ctx->bstate =
! 1028: BS_STOP;)
1.1 root 1029: case 0x00c3: /* movca.l R0,@Rm */
1030: gen_op_movl_rN_T0(REG(0));
1031: gen_op_movl_rN_T1(REG(B11_8));
1032: gen_op_stl_T0_T1(ctx);
1033: return;
1034: case 0x0029: /* movt Rn */
1035: gen_op_movt_rN(REG(B11_8));
1036: return;
1037: case 0x0093: /* ocbi @Rn */
1038: gen_op_movl_rN_T0(REG(B11_8));
1039: gen_op_ldl_T0_T0(ctx);
1040: return;
1041: case 0x00a2: /* ocbp @Rn */
1042: gen_op_movl_rN_T0(REG(B11_8));
1043: gen_op_ldl_T0_T0(ctx);
1044: return;
1045: case 0x00b3: /* ocbwb @Rn */
1046: gen_op_movl_rN_T0(REG(B11_8));
1047: gen_op_ldl_T0_T0(ctx);
1048: return;
1049: case 0x0083: /* pref @Rn */
1050: return;
1051: case 0x4024: /* rotcl Rn */
1052: gen_op_rotcl_Rn(REG(B11_8));
1053: return;
1054: case 0x4025: /* rotcr Rn */
1055: gen_op_rotcr_Rn(REG(B11_8));
1056: return;
1057: case 0x4004: /* rotl Rn */
1058: gen_op_rotl_Rn(REG(B11_8));
1059: return;
1060: case 0x4005: /* rotr Rn */
1061: gen_op_rotr_Rn(REG(B11_8));
1062: return;
1063: case 0x4000: /* shll Rn */
1064: case 0x4020: /* shal Rn */
1065: gen_op_shal_Rn(REG(B11_8));
1066: return;
1067: case 0x4021: /* shar Rn */
1068: gen_op_shar_Rn(REG(B11_8));
1069: return;
1070: case 0x4001: /* shlr Rn */
1071: gen_op_shlr_Rn(REG(B11_8));
1072: return;
1073: case 0x4008: /* shll2 Rn */
1074: gen_op_shll2_Rn(REG(B11_8));
1075: return;
1076: case 0x4018: /* shll8 Rn */
1077: gen_op_shll8_Rn(REG(B11_8));
1078: return;
1079: case 0x4028: /* shll16 Rn */
1080: gen_op_shll16_Rn(REG(B11_8));
1081: return;
1082: case 0x4009: /* shlr2 Rn */
1083: gen_op_shlr2_Rn(REG(B11_8));
1084: return;
1085: case 0x4019: /* shlr8 Rn */
1086: gen_op_shlr8_Rn(REG(B11_8));
1087: return;
1088: case 0x4029: /* shlr16 Rn */
1089: gen_op_shlr16_Rn(REG(B11_8));
1090: return;
1091: case 0x401b: /* tas.b @Rn */
1092: gen_op_tasb_rN(REG(B11_8));
1093: return;
1.1.1.3 ! root 1094: case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1.1.1.2 root 1095: gen_op_movl_fpul_FT0();
1096: gen_op_fmov_FT0_frN(FREG(B11_8));
1097: return;
1.1.1.3 ! root 1098: case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1.1.1.2 root 1099: gen_op_fmov_frN_FT0(FREG(B11_8));
1100: gen_op_movl_FT0_fpul();
1101: return;
1.1.1.3 ! root 1102: case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
! 1103: if (ctx->fpscr & FPSCR_PR) {
! 1104: if (ctx->opcode & 0x0100)
! 1105: break; /* illegal instruction */
! 1106: gen_op_float_DT();
! 1107: gen_op_fmov_DT0_drN(DREG(B11_8));
! 1108: }
! 1109: else {
! 1110: gen_op_float_FT();
! 1111: gen_op_fmov_FT0_frN(FREG(B11_8));
! 1112: }
! 1113: return;
! 1114: case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
! 1115: if (ctx->fpscr & FPSCR_PR) {
! 1116: if (ctx->opcode & 0x0100)
! 1117: break; /* illegal instruction */
! 1118: gen_op_fmov_drN_DT0(DREG(B11_8));
! 1119: gen_op_ftrc_DT();
! 1120: }
! 1121: else {
! 1122: gen_op_fmov_frN_FT0(FREG(B11_8));
! 1123: gen_op_ftrc_FT();
! 1124: }
! 1125: return;
! 1126: case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
! 1127: if (!(ctx->fpscr & FPSCR_PR)) {
! 1128: gen_op_movl_imm_T0(0);
! 1129: gen_op_fmov_T0_frN(FREG(B11_8));
! 1130: return;
! 1131: }
! 1132: break;
! 1133: case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
! 1134: if (!(ctx->fpscr & FPSCR_PR)) {
! 1135: gen_op_movl_imm_T0(0x3f800000);
! 1136: gen_op_fmov_T0_frN(FREG(B11_8));
! 1137: return;
! 1138: }
! 1139: break;
1.1 root 1140: }
1141:
1142: fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1143: ctx->opcode, ctx->pc);
1144: gen_op_raise_illegal_instruction();
1.1.1.3 ! root 1145: ctx->bstate = BS_EXCP;
! 1146: }
! 1147:
! 1148: void decode_opc(DisasContext * ctx)
! 1149: {
! 1150: uint32_t old_flags = ctx->flags;
! 1151:
! 1152: _decode_opc(ctx);
! 1153:
! 1154: if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
! 1155: if (ctx->flags & DELAY_SLOT_CLEARME) {
! 1156: gen_op_store_flags(0);
! 1157: }
! 1158: ctx->flags = 0;
! 1159: ctx->bstate = BS_BRANCH;
! 1160: if (old_flags & DELAY_SLOT_CONDITIONAL) {
! 1161: gen_delayed_conditional_jump(ctx);
! 1162: } else if (old_flags & DELAY_SLOT) {
! 1163: gen_jump(ctx);
! 1164: }
! 1165:
! 1166: }
1.1 root 1167: }
1168:
1.1.1.3 ! root 1169: static inline int
! 1170: gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
! 1171: int search_pc)
1.1 root 1172: {
1173: DisasContext ctx;
1174: target_ulong pc_start;
1175: static uint16_t *gen_opc_end;
1.1.1.2 root 1176: int i, ii;
1.1 root 1177:
1178: pc_start = tb->pc;
1179: gen_opc_ptr = gen_opc_buf;
1180: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1181: gen_opparam_ptr = gen_opparam_buf;
1182: ctx.pc = pc_start;
1.1.1.3 ! root 1183: ctx.flags = (uint32_t)tb->flags;
! 1184: ctx.bstate = BS_NONE;
1.1 root 1185: ctx.sr = env->sr;
1.1.1.2 root 1186: ctx.fpscr = env->fpscr;
1.1 root 1187: ctx.memidx = (env->sr & SR_MD) ? 1 : 0;
1.1.1.2 root 1188: /* We don't know if the delayed pc came from a dynamic or static branch,
1189: so assume it is a dynamic branch. */
1.1.1.3 ! root 1190: ctx.delayed_pc = -1; /* use delayed pc from env pointer */
1.1 root 1191: ctx.tb = tb;
1192: ctx.singlestep_enabled = env->singlestep_enabled;
1193: nb_gen_labels = 0;
1194:
1195: #ifdef DEBUG_DISAS
1196: if (loglevel & CPU_LOG_TB_CPU) {
1197: fprintf(logfile,
1198: "------------------------------------------------\n");
1199: cpu_dump_state(env, logfile, fprintf, 0);
1200: }
1201: #endif
1202:
1.1.1.2 root 1203: ii = -1;
1.1.1.3 ! root 1204: while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1.1 root 1205: if (env->nb_breakpoints > 0) {
1206: for (i = 0; i < env->nb_breakpoints; i++) {
1207: if (ctx.pc == env->breakpoints[i]) {
1208: /* We have hit a breakpoint - make sure PC is up-to-date */
1209: gen_op_movl_imm_PC(ctx.pc);
1210: gen_op_debug();
1.1.1.3 ! root 1211: ctx.bstate = BS_EXCP;
1.1 root 1212: break;
1213: }
1214: }
1215: }
1.1.1.2 root 1216: if (search_pc) {
1217: i = gen_opc_ptr - gen_opc_buf;
1218: if (ii < i) {
1219: ii++;
1220: while (ii < i)
1221: gen_opc_instr_start[ii++] = 0;
1222: }
1223: gen_opc_pc[ii] = ctx.pc;
1.1.1.3 ! root 1224: gen_opc_hflags[ii] = ctx.flags;
1.1.1.2 root 1225: gen_opc_instr_start[ii] = 1;
1226: }
1.1 root 1227: #if 0
1228: fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
1229: fflush(stderr);
1230: #endif
1231: ctx.opcode = lduw_code(ctx.pc);
1232: decode_opc(&ctx);
1233: ctx.pc += 2;
1234: if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1235: break;
1236: if (env->singlestep_enabled)
1237: break;
1238: #ifdef SH4_SINGLE_STEP
1239: break;
1240: #endif
1241: }
1242: if (env->singlestep_enabled) {
1.1.1.3 ! root 1243: gen_op_debug();
! 1244: } else {
! 1245: switch (ctx.bstate) {
! 1246: case BS_STOP:
! 1247: /* gen_op_interrupt_restart(); */
! 1248: /* fall through */
! 1249: case BS_NONE:
! 1250: if (ctx.flags) {
! 1251: gen_op_store_flags(ctx.flags | DELAY_SLOT_CLEARME);
! 1252: }
! 1253: gen_goto_tb(&ctx, 0, ctx.pc);
! 1254: break;
! 1255: case BS_EXCP:
! 1256: /* gen_op_interrupt_restart(); */
! 1257: gen_op_movl_imm_T0(0);
! 1258: gen_op_exit_tb();
! 1259: break;
! 1260: case BS_BRANCH:
! 1261: default:
! 1262: break;
! 1263: }
1.1 root 1264: }
1.1.1.3 ! root 1265:
1.1 root 1266: *gen_opc_ptr = INDEX_op_end;
1.1.1.2 root 1267: if (search_pc) {
1268: i = gen_opc_ptr - gen_opc_buf;
1269: ii++;
1270: while (ii <= i)
1271: gen_opc_instr_start[ii++] = 0;
1272: } else {
1273: tb->size = ctx.pc - pc_start;
1274: }
1.1 root 1275:
1276: #ifdef DEBUG_DISAS
1277: #ifdef SH4_DEBUG_DISAS
1278: if (loglevel & CPU_LOG_TB_IN_ASM)
1279: fprintf(logfile, "\n");
1280: #endif
1281: if (loglevel & CPU_LOG_TB_IN_ASM) {
1282: fprintf(logfile, "IN:\n"); /* , lookup_symbol(pc_start)); */
1283: target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1284: fprintf(logfile, "\n");
1285: }
1286: if (loglevel & CPU_LOG_TB_OP) {
1287: fprintf(logfile, "OP:\n");
1288: dump_ops(gen_opc_buf, gen_opparam_buf);
1289: fprintf(logfile, "\n");
1290: }
1291: #endif
1292: return 0;
1293: }
1294:
1295: int gen_intermediate_code(CPUState * env, struct TranslationBlock *tb)
1296: {
1297: return gen_intermediate_code_internal(env, tb, 0);
1298: }
1299:
1300: int gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
1301: {
1302: return gen_intermediate_code_internal(env, tb, 1);
1303: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.