|
|
1.1 root 1: /*
2: * SH4 translation
3: *
4: * Copyright (c) 2005 Samuel Tardieu
5: *
6: * This library is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU Lesser General Public
8: * License as published by the Free Software Foundation; either
9: * version 2 of the License, or (at your option) any later version.
10: *
11: * This library is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
17: * License along with this library; if not, 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;
57: uint16_t opcode;
58: uint32_t flags;
59: int memidx;
60: uint32_t delayed_pc;
61: int singlestep_enabled;
62: } DisasContext;
63:
64: #ifdef CONFIG_USER_ONLY
65:
66: #define GEN_OP_LD(width) \
67: void gen_op_ld##width##_T0_T0 (DisasContext *ctx) { \
68: gen_op_ld##width##_T0_T0_raw(); \
69: }
70: #define GEN_OP_ST(width) \
71: void gen_op_st##width##_T0_T1 (DisasContext *ctx) { \
72: gen_op_st##width##_T0_T1_raw(); \
73: }
74:
75: #else
76:
77: #define GEN_OP_LD(width) \
78: void gen_op_ld##width##_T0_T0 (DisasContext *ctx) { \
79: if (ctx->memidx) gen_op_ld##width##_T0_T0_kernel(); \
80: else gen_op_ld##width##_T0_T0_user();\
81: }
82: #define GEN_OP_ST(width) \
83: void gen_op_st##width##_T0_T1 (DisasContext *ctx) { \
84: if (ctx->memidx) gen_op_st##width##_T0_T1_kernel(); \
85: else gen_op_st##width##_T0_T1_user();\
86: }
87:
88: #endif
89:
90: GEN_OP_LD(ub)
91: GEN_OP_LD(b)
92: GEN_OP_ST(b)
93: GEN_OP_LD(uw)
94: GEN_OP_LD(w)
95: GEN_OP_ST(w)
96: GEN_OP_LD(l)
97: GEN_OP_ST(l)
98:
99: void cpu_dump_state(CPUState * env, FILE * f,
100: int (*cpu_fprintf) (FILE * f, const char *fmt, ...),
101: int flags)
102: {
103: int i;
104: cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x\n",
105: env->pc, env->sr, env->pr);
106: for (i = 0; i < 24; i += 4) {
107: cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
108: i, env->gregs[i], i + 1, env->gregs[i + 1],
109: i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
110: }
111: if (env->flags & DELAY_SLOT) {
112: cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
113: env->delayed_pc);
114: } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
115: cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
116: env->delayed_pc);
117: }
118: }
119:
120: void cpu_sh4_reset(CPUSH4State * env)
121: {
122: env->sr = 0x700000F0; /* MD, RB, BL, I3-I0 */
123: env->vbr = 0;
124: env->pc = 0xA0000000;
125: env->fpscr = 0x00040001;
126: env->mmucr = 0;
127: }
128:
129: CPUSH4State *cpu_sh4_init(void)
130: {
131: CPUSH4State *env;
132:
133: env = qemu_mallocz(sizeof(CPUSH4State));
134: if (!env)
135: return NULL;
136: cpu_exec_init(env);
137: cpu_sh4_reset(env);
138: tlb_flush(env, 1);
139: return env;
140: }
141:
142: #ifdef CONFIG_USER_ONLY
143: target_ulong cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
144: {
145: return addr;
146: }
147: #else
148: target_ulong cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
149: {
150: target_ulong physical;
151: int prot;
152:
153: get_physical_address(env, &physical, &prot, addr, PAGE_READ, 0);
154: return physical;
155: }
156: #endif
157:
158: static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
159: {
160: TranslationBlock *tb;
161: tb = ctx->tb;
162:
163: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
164: !ctx->singlestep_enabled) {
165: /* Use a direct jump if in same page and singlestep not enabled */
166: if (n == 0)
167: gen_op_goto_tb0(TBPARAM(tb));
168: else
169: gen_op_goto_tb1(TBPARAM(tb));
170: gen_op_movl_imm_T0((long) tb + n);
171: } else {
172: gen_op_movl_imm_T0(0);
173: }
174: gen_op_movl_imm_PC(dest);
175: if (ctx->singlestep_enabled)
176: gen_op_debug();
177: gen_op_exit_tb();
178: }
179:
180: /* Jump to pc after an exception */
181: static void gen_jump_exception(DisasContext * ctx)
182: {
183: gen_op_movl_imm_T0(0);
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();
223: gen_op_jTT2(l1);
224: gen_goto_tb(ctx, 0, ctx->pc);
225: gen_set_label(l1);
226: gen_goto_tb(ctx, 1, ctx->delayed_pc);
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:
245: #define CHECK_NOT_DELAY_SLOT \
246: if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
247: {gen_op_raise_slot_illegal_instruction (); ctx->flags |= BRANCH_EXCEPTION; \
248: return;}
249:
250: void decode_opc(DisasContext * ctx)
251: {
252: #if 0
253: fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
254: #endif
255: switch (ctx->opcode) {
256: case 0x0019: /* div0u */
257: printf("div0u\n");
258: gen_op_div0u();
259: return;
260: case 0x000b: /* rts */
261: CHECK_NOT_DELAY_SLOT gen_op_rts();
262: ctx->flags |= DELAY_SLOT;
263: ctx->delayed_pc = (uint32_t) - 1;
264: return;
265: case 0x0028: /* clrmac */
266: gen_op_clrmac();
267: return;
268: case 0x0048: /* clrs */
269: gen_op_clrs();
270: return;
271: case 0x0008: /* clrt */
272: gen_op_clrt();
273: return;
274: case 0x0038: /* ldtlb */
275: assert(0); /* XXXXX */
276: return;
277: case 0x004b: /* rte */
278: CHECK_NOT_DELAY_SLOT gen_op_rte();
279: ctx->flags |= DELAY_SLOT;
280: ctx->delayed_pc = (uint32_t) - 1;
281: return;
282: case 0x0058: /* sets */
283: gen_op_sets();
284: return;
285: case 0x0018: /* sett */
286: gen_op_sett();
287: return;
288: case 0xfbfb: /* frchg */
289: assert(0); /* XXXXX */
290: return;
291: case 0xf3fb: /* fschg */
292: assert(0); /* XXXXX */
293: return;
294: case 0x0009: /* nop */
295: return;
296: case 0x001b: /* sleep */
297: assert(0); /* XXXXX */
298: return;
299: }
300:
301: switch (ctx->opcode & 0xf000) {
302: case 0x1000: /* mov.l Rm,@(disp,Rn) */
303: gen_op_movl_rN_T0(REG(B7_4));
304: gen_op_movl_rN_T1(REG(B11_8));
305: gen_op_addl_imm_T1(B3_0 * 4);
306: gen_op_stl_T0_T1(ctx);
307: return;
308: case 0x5000: /* mov.l @(disp,Rm),Rn */
309: gen_op_movl_rN_T0(REG(B7_4));
310: gen_op_addl_imm_T0(B3_0 * 4);
311: gen_op_ldl_T0_T0(ctx);
312: gen_op_movl_T0_rN(REG(B11_8));
313: return;
314: case 0xe000: /* mov.l #imm,Rn */
315: gen_op_movl_imm_rN(B7_0s, REG(B11_8));
316: return;
317: case 0x9000: /* mov.w @(disp,PC),Rn */
318: gen_op_movl_imm_T0(ctx->pc + 4 + B7_0 * 2);
319: gen_op_ldw_T0_T0(ctx);
320: gen_op_movl_T0_rN(REG(B11_8));
321: return;
322: case 0xd000: /* mov.l @(disp,PC),Rn */
323: gen_op_movl_imm_T0((ctx->pc + 4 + B7_0 * 4) & ~3);
324: gen_op_ldl_T0_T0(ctx);
325: gen_op_movl_T0_rN(REG(B11_8));
326: return;
327: case 0x7000: /* add.l #imm,Rn */
328: gen_op_add_imm_rN(B7_0s, REG(B11_8));
329: return;
330: case 0xa000: /* bra disp */
331: CHECK_NOT_DELAY_SLOT
332: gen_op_bra(ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2);
333: ctx->flags |= DELAY_SLOT;
334: return;
335: case 0xb000: /* bsr disp */
336: CHECK_NOT_DELAY_SLOT
337: gen_op_bsr(ctx->pc + 4, ctx->delayed_pc =
338: ctx->pc + 4 + B11_0s * 2);
339: ctx->flags |= DELAY_SLOT;
340: return;
341: }
342:
343: switch (ctx->opcode & 0xf00f) {
344: case 0x6003: /* mov Rm,Rn */
345: gen_op_movl_rN_T0(REG(B7_4));
346: gen_op_movl_T0_rN(REG(B11_8));
347: return;
348: case 0x2000: /* mov.b Rm,@Rn */
349: gen_op_movl_rN_T0(REG(B7_4));
350: gen_op_movl_rN_T1(REG(B11_8));
351: gen_op_stb_T0_T1(ctx);
352: return;
353: case 0x2001: /* mov.w Rm,@Rn */
354: gen_op_movl_rN_T0(REG(B7_4));
355: gen_op_movl_rN_T1(REG(B11_8));
356: gen_op_stw_T0_T1(ctx);
357: return;
358: case 0x2002: /* mov.l Rm,@Rn */
359: gen_op_movl_rN_T0(REG(B7_4));
360: gen_op_movl_rN_T1(REG(B11_8));
361: gen_op_stl_T0_T1(ctx);
362: return;
363: case 0x6000: /* mov.b @Rm,Rn */
364: gen_op_movl_rN_T0(REG(B7_4));
365: gen_op_ldb_T0_T0(ctx);
366: gen_op_movl_T0_rN(REG(B11_8));
367: return;
368: case 0x6001: /* mov.w @Rm,Rn */
369: gen_op_movl_rN_T0(REG(B7_4));
370: gen_op_ldw_T0_T0(ctx);
371: gen_op_movl_T0_rN(REG(B11_8));
372: return;
373: case 0x6002: /* mov.l @Rm,Rn */
374: gen_op_movl_rN_T0(REG(B7_4));
375: gen_op_ldl_T0_T0(ctx);
376: gen_op_movl_T0_rN(REG(B11_8));
377: return;
378: case 0x2004: /* mov.b Rm,@-Rn */
379: gen_op_dec1_rN(REG(B11_8));
380: gen_op_movl_rN_T0(REG(B7_4));
381: gen_op_movl_rN_T1(REG(B11_8));
382: gen_op_stb_T0_T1(ctx);
383: return;
384: case 0x2005: /* mov.w Rm,@-Rn */
385: gen_op_dec2_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_stw_T0_T1(ctx);
389: return;
390: case 0x2006: /* mov.l Rm,@-Rn */
391: gen_op_dec4_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_stl_T0_T1(ctx);
395: return;
396: case 0x6004: /* mov.l @Rm+,Rn */
397: gen_op_movl_rN_T0(REG(B7_4));
398: gen_op_ldb_T0_T0(ctx);
399: gen_op_movl_T0_rN(REG(B11_8));
400: gen_op_inc1_rN(REG(B7_4));
401: return;
402: case 0x6005: /* mov.w @Rm+,Rn */
403: gen_op_movl_rN_T0(REG(B7_4));
404: gen_op_ldw_T0_T0(ctx);
405: gen_op_movl_T0_rN(REG(B11_8));
406: gen_op_inc2_rN(REG(B7_4));
407: return;
408: case 0x6006: /* mov.l @Rm+,Rn */
409: gen_op_movl_rN_T0(REG(B7_4));
410: gen_op_ldl_T0_T0(ctx);
411: gen_op_movl_T0_rN(REG(B11_8));
412: gen_op_inc4_rN(REG(B7_4));
413: return;
414: case 0x0004: /* mov.b Rm,@(R0,Rn) */
415: gen_op_movl_rN_T0(REG(B7_4));
416: gen_op_movl_rN_T1(REG(B11_8));
417: gen_op_add_rN_T1(REG(0));
418: gen_op_stb_T0_T1(ctx);
419: return;
420: case 0x0005: /* mov.w 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_stw_T0_T1(ctx);
425: return;
426: case 0x0006: /* mov.l 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_stl_T0_T1(ctx);
431: return;
432: case 0x000c: /* mov.b @(R0,Rm),Rn */
433: gen_op_movl_rN_T0(REG(B7_4));
434: gen_op_add_rN_T0(REG(0));
435: gen_op_ldb_T0_T0(ctx);
436: gen_op_movl_T0_rN(REG(B11_8));
437: return;
438: case 0x000d: /* mov.w @(R0,Rm),Rn */
439: gen_op_movl_rN_T0(REG(B7_4));
440: gen_op_add_rN_T0(REG(0));
441: gen_op_ldw_T0_T0(ctx);
442: gen_op_movl_T0_rN(REG(B11_8));
443: return;
444: case 0x000e: /* mov.l @(R0,Rm),Rn */
445: gen_op_movl_rN_T0(REG(B7_4));
446: gen_op_add_rN_T0(REG(0));
447: gen_op_ldl_T0_T0(ctx);
448: gen_op_movl_T0_rN(REG(B11_8));
449: return;
450: case 0x6008: /* swap.b Rm,Rn */
451: gen_op_movl_rN_T0(REG(B7_4));
452: gen_op_swapb_T0();
453: gen_op_movl_T0_rN(REG(B11_8));
454: return;
455: case 0x6009: /* swap.w Rm,Rn */
456: gen_op_movl_rN_T0(REG(B7_4));
457: gen_op_swapw_T0();
458: gen_op_movl_T0_rN(REG(B11_8));
459: return;
460: case 0x200d: /* xtrct Rm,Rn */
461: gen_op_movl_rN_T0(REG(B7_4));
462: gen_op_movl_rN_T1(REG(B11_8));
463: gen_op_xtrct_T0_T1();
464: gen_op_movl_T1_rN(REG(B11_8));
465: return;
466: case 0x300c: /* add Rm,Rn */
467: gen_op_movl_rN_T0(REG(B7_4));
468: gen_op_add_T0_rN(REG(B11_8));
469: return;
470: case 0x300e: /* addc Rm,Rn */
471: gen_op_movl_rN_T0(REG(B7_4));
472: gen_op_movl_rN_T1(REG(B11_8));
473: gen_op_addc_T0_T1();
474: gen_op_movl_T1_rN(REG(B11_8));
475: return;
476: case 0x300f: /* addv Rm,Rn */
477: gen_op_movl_rN_T0(REG(B7_4));
478: gen_op_movl_rN_T1(REG(B11_8));
479: gen_op_addv_T0_T1();
480: gen_op_movl_T1_rN(REG(B11_8));
481: return;
482: case 0x2009: /* and Rm,Rn */
483: gen_op_movl_rN_T0(REG(B7_4));
484: gen_op_and_T0_rN(REG(B11_8));
485: return;
486: case 0x3000: /* cmp/eq Rm,Rn */
487: gen_op_movl_rN_T0(REG(B7_4));
488: gen_op_movl_rN_T1(REG(B11_8));
489: gen_op_cmp_eq_T0_T1();
490: return;
491: case 0x3003: /* cmp/ge Rm,Rn */
492: gen_op_movl_rN_T0(REG(B7_4));
493: gen_op_movl_rN_T1(REG(B11_8));
494: gen_op_cmp_ge_T0_T1();
495: return;
496: case 0x3007: /* cmp/gt Rm,Rn */
497: gen_op_movl_rN_T0(REG(B7_4));
498: gen_op_movl_rN_T1(REG(B11_8));
499: gen_op_cmp_gt_T0_T1();
500: return;
501: case 0x3006: /* cmp/hi Rm,Rn */
502: gen_op_movl_rN_T0(REG(B7_4));
503: gen_op_movl_rN_T1(REG(B11_8));
504: gen_op_cmp_hi_T0_T1();
505: return;
506: case 0x3002: /* cmp/hs Rm,Rn */
507: gen_op_movl_rN_T0(REG(B7_4));
508: gen_op_movl_rN_T1(REG(B11_8));
509: gen_op_cmp_hs_T0_T1();
510: return;
511: case 0x200c: /* cmp/str Rm,Rn */
512: gen_op_movl_rN_T0(REG(B7_4));
513: gen_op_movl_rN_T1(REG(B11_8));
514: gen_op_cmp_str_T0_T1();
515: return;
516: case 0x2007: /* div0s Rm,Rn */
517: printf("div0s\n");
518: gen_op_movl_rN_T0(REG(B7_4));
519: gen_op_movl_rN_T1(REG(B11_8));
520: gen_op_div0s_T0_T1();
521: gen_op_movl_T1_rN(REG(B11_8));
522: return;
523: case 0x3004: /* div1 Rm,Rn */
524: gen_op_movl_rN_T0(REG(B7_4));
525: gen_op_movl_rN_T1(REG(B11_8));
526: gen_op_div1_T0_T1();
527: gen_op_movl_T1_rN(REG(B11_8));
528: return;
529: case 0x300d: /* dmuls.l Rm,Rn */
530: gen_op_movl_rN_T0(REG(B7_4));
531: gen_op_movl_rN_T1(REG(B11_8));
532: gen_op_dmulsl_T0_T1();
533: return;
534: case 0x3005: /* dmulu.l Rm,Rn */
535: gen_op_movl_rN_T0(REG(B7_4));
536: gen_op_movl_rN_T1(REG(B11_8));
537: gen_op_dmulul_T0_T1();
538: return;
539: case 0x600e: /* exts.b Rm,Rn */
540: gen_op_movb_rN_T0(REG(B7_4));
541: gen_op_movl_T0_rN(REG(B11_8));
542: return;
543: case 0x600f: /* exts.w Rm,Rn */
544: gen_op_movw_rN_T0(REG(B7_4));
545: gen_op_movl_T0_rN(REG(B11_8));
546: return;
547: case 0x600c: /* extu.b Rm,Rn */
548: gen_op_movub_rN_T0(REG(B7_4));
549: gen_op_movl_T0_rN(REG(B11_8));
550: return;
551: case 0x600d: /* extu.w Rm,Rn */
552: gen_op_movuw_rN_T0(REG(B7_4));
553: gen_op_movl_T0_rN(REG(B11_8));
554: return;
555: case 0x000f: /* mac.l @Rm+,@Rn- */
556: gen_op_movl_rN_T0(REG(B11_8));
557: gen_op_ldl_T0_T0(ctx);
558: gen_op_movl_T0_T1();
559: gen_op_movl_rN_T1(REG(B7_4));
560: gen_op_ldl_T0_T0(ctx);
561: gen_op_macl_T0_T1();
562: gen_op_inc4_rN(REG(B7_4));
563: gen_op_inc4_rN(REG(B11_8));
564: return;
565: case 0x400f: /* mac.w @Rm+,@Rn+ */
566: gen_op_movl_rN_T0(REG(B11_8));
567: gen_op_ldl_T0_T0(ctx);
568: gen_op_movl_T0_T1();
569: gen_op_movl_rN_T1(REG(B7_4));
570: gen_op_ldl_T0_T0(ctx);
571: gen_op_macw_T0_T1();
572: gen_op_inc2_rN(REG(B7_4));
573: gen_op_inc2_rN(REG(B11_8));
574: return;
575: case 0x0007: /* mul.l Rm,Rn */
576: gen_op_movl_rN_T0(REG(B7_4));
577: gen_op_movl_rN_T1(REG(B11_8));
578: gen_op_mull_T0_T1();
579: return;
580: case 0x200f: /* muls.w Rm,Rn */
581: gen_op_movw_rN_T0(REG(B7_4));
582: gen_op_movw_rN_T1(REG(B11_8));
583: gen_op_mulsw_T0_T1();
584: return;
585: case 0x200e: /* mulu.w Rm,Rn */
586: gen_op_movuw_rN_T0(REG(B7_4));
587: gen_op_movuw_rN_T1(REG(B11_8));
588: gen_op_muluw_T0_T1();
589: return;
590: case 0x600b: /* neg Rm,Rn */
591: gen_op_movl_rN_T0(REG(B7_4));
592: gen_op_neg_T0();
593: gen_op_movl_T0_rN(REG(B11_8));
594: return;
595: case 0x600a: /* negc Rm,Rn */
596: gen_op_movl_rN_T0(REG(B7_4));
597: gen_op_negc_T0();
598: gen_op_movl_T0_rN(REG(B11_8));
599: return;
600: case 0x6007: /* not Rm,Rn */
601: gen_op_movl_rN_T0(REG(B7_4));
602: gen_op_not_T0();
603: gen_op_movl_T0_rN(REG(B11_8));
604: return;
605: case 0x200b: /* or Rm,Rn */
606: gen_op_movl_rN_T0(REG(B7_4));
607: gen_op_or_T0_rN(REG(B11_8));
608: return;
609: case 0x400c: /* shad Rm,Rn */
610: gen_op_movl_rN_T0(REG(B7_4));
611: gen_op_movl_rN_T1(REG(B11_8));
612: gen_op_shad_T0_T1();
613: gen_op_movl_T1_rN(REG(B11_8));
614: return;
615: case 0x400d: /* shld Rm,Rn */
616: gen_op_movl_rN_T0(REG(B7_4));
617: gen_op_movl_rN_T1(REG(B11_8));
618: gen_op_shld_T0_T1();
619: gen_op_movl_T1_rN(REG(B11_8));
620: return;
621: case 0x3008: /* sub Rm,Rn */
622: gen_op_movl_rN_T0(REG(B7_4));
623: gen_op_sub_T0_rN(REG(B11_8));
624: return;
625: case 0x300a: /* subc Rm,Rn */
626: gen_op_movl_rN_T0(REG(B7_4));
627: gen_op_movl_rN_T1(REG(B11_8));
628: gen_op_subc_T0_T1();
629: gen_op_movl_T1_rN(REG(B11_8));
630: return;
631: case 0x300b: /* subv Rm,Rn */
632: gen_op_movl_rN_T0(REG(B7_4));
633: gen_op_movl_rN_T1(REG(B11_8));
634: gen_op_subv_T0_T1();
635: gen_op_movl_T1_rN(REG(B11_8));
636: return;
637: case 0x2008: /* tst Rm,Rn */
638: gen_op_movl_rN_T0(REG(B7_4));
639: gen_op_movl_rN_T1(REG(B11_8));
640: gen_op_tst_T0_T1();
641: return;
642: case 0x200a: /* xor Rm,Rn */
643: gen_op_movl_rN_T0(REG(B7_4));
644: gen_op_xor_T0_rN(REG(B11_8));
645: return;
646: }
647:
648: switch (ctx->opcode & 0xff00) {
649: case 0xc900: /* and #imm,R0 */
650: gen_op_and_imm_rN(B7_0, REG(0));
651: return;
652: case 0xcd00: /* and.b #imm,@(R0+GBR) */
653: gen_op_movl_rN_T0(REG(0));
654: gen_op_addl_GBR_T0();
655: gen_op_movl_T0_T1();
656: gen_op_ldb_T0_T0(ctx);
657: gen_op_and_imm_T0(B7_0);
658: gen_op_stb_T0_T1(ctx);
659: return;
660: case 0x8b00: /* bf label */
661: CHECK_NOT_DELAY_SLOT
662: gen_conditional_jump(ctx, ctx->pc + 2,
663: ctx->pc + 4 + B7_0s * 2);
664: ctx->flags |= BRANCH_CONDITIONAL;
665: return;
666: case 0x8f00: /* bf/s label */
667: CHECK_NOT_DELAY_SLOT
668: gen_op_bf_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
669: ctx->flags |= DELAY_SLOT_CONDITIONAL;
670: return;
671: case 0x8900: /* bt label */
672: CHECK_NOT_DELAY_SLOT
673: gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2,
674: ctx->pc + 2);
675: ctx->flags |= BRANCH_CONDITIONAL;
676: return;
677: case 0x8d00: /* bt/s label */
678: CHECK_NOT_DELAY_SLOT
679: gen_op_bt_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
680: ctx->flags |= DELAY_SLOT_CONDITIONAL;
681: return;
682: case 0x8800: /* cmp/eq #imm,R0 */
683: gen_op_movl_rN_T0(REG(0));
684: gen_op_cmp_eq_imm_T0(B7_0s);
685: return;
686: case 0xc400: /* mov.b @(disp,GBR),R0 */
687: gen_op_stc_gbr_T0();
688: gen_op_addl_imm_T0(B7_0);
689: gen_op_ldb_T0_T0(ctx);
690: gen_op_movl_T0_rN(REG(0));
691: return;
692: case 0xc500: /* mov.w @(disp,GBR),R0 */
693: gen_op_stc_gbr_T0();
694: gen_op_addl_imm_T0(B7_0);
695: gen_op_ldw_T0_T0(ctx);
696: gen_op_movl_T0_rN(REG(0));
697: return;
698: case 0xc600: /* mov.l @(disp,GBR),R0 */
699: gen_op_stc_gbr_T0();
700: gen_op_addl_imm_T0(B7_0);
701: gen_op_ldl_T0_T0(ctx);
702: gen_op_movl_T0_rN(REG(0));
703: return;
704: case 0xc000: /* mov.b R0,@(disp,GBR) */
705: gen_op_stc_gbr_T0();
706: gen_op_addl_imm_T0(B7_0);
707: gen_op_movl_T0_T1();
708: gen_op_movl_rN_T0(REG(0));
709: gen_op_stb_T0_T1(ctx);
710: return;
711: case 0xc100: /* mov.w R0,@(disp,GBR) */
712: gen_op_stc_gbr_T0();
713: gen_op_addl_imm_T0(B7_0);
714: gen_op_movl_T0_T1();
715: gen_op_movl_rN_T0(REG(0));
716: gen_op_stw_T0_T1(ctx);
717: return;
718: case 0xc200: /* mov.l R0,@(disp,GBR) */
719: gen_op_stc_gbr_T0();
720: gen_op_addl_imm_T0(B7_0);
721: gen_op_movl_T0_T1();
722: gen_op_movl_rN_T0(REG(0));
723: gen_op_stl_T0_T1(ctx);
724: return;
725: case 0x8000: /* mov.b R0,@(disp,Rn) */
726: gen_op_movl_rN_T0(REG(0));
727: gen_op_movl_rN_T1(REG(B7_4));
728: gen_op_addl_imm_T1(B3_0);
729: gen_op_stb_T0_T1(ctx);
730: return;
731: case 0x8100: /* mov.w R0,@(disp,Rn) */
732: gen_op_movl_rN_T0(REG(0));
733: gen_op_movl_rN_T1(REG(B7_4));
734: gen_op_addl_imm_T1(B3_0 * 2);
735: gen_op_stw_T0_T1(ctx);
736: return;
737: case 0x8400: /* mov.b @(disp,Rn),R0 */
738: gen_op_movl_rN_T0(REG(0));
739: gen_op_movl_rN_T1(REG(B7_4));
740: gen_op_addl_imm_T1(B3_0);
741: gen_op_stb_T0_T1(ctx);
742: return;
743: case 0x8500: /* mov.w @(disp,Rn),R0 */
744: gen_op_movl_rN_T0(REG(B7_4));
745: gen_op_addl_imm_T0(B3_0 * 2);
746: gen_op_ldw_T0_T0(ctx);
747: gen_op_movl_T0_rN(REG(0));
748: return;
749: case 0xc700: /* mova @(disp,PC),R0 */
750: gen_op_movl_imm_rN(((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3,
751: REG(0));
752: return;
753: case 0xcb00: /* or #imm,R0 */
754: gen_op_or_imm_rN(B7_0, REG(0));
755: return;
756: case 0xcf00: /* or.b #imm,@(R0+GBR) */
757: gen_op_movl_rN_T0(REG(0));
758: gen_op_addl_GBR_T0();
759: gen_op_movl_T0_T1();
760: gen_op_ldb_T0_T0(ctx);
761: gen_op_or_imm_T0(B7_0);
762: gen_op_stb_T0_T1(ctx);
763: return;
764: case 0xc300: /* trapa #imm */
765: CHECK_NOT_DELAY_SLOT gen_op_movl_imm_PC(ctx->pc);
766: gen_op_trapa(B7_0);
767: ctx->flags |= BRANCH;
768: return;
769: case 0xc800: /* tst #imm,R0 */
770: gen_op_tst_imm_rN(B7_0, REG(0));
771: return;
772: case 0xcc00: /* tst #imm,@(R0+GBR) */
773: gen_op_movl_rN_T0(REG(0));
774: gen_op_addl_GBR_T0();
775: gen_op_ldb_T0_T0(ctx);
776: gen_op_tst_imm_T0(B7_0);
777: return;
778: case 0xca00: /* xor #imm,R0 */
779: gen_op_xor_imm_rN(B7_0, REG(0));
780: return;
781: case 0xce00: /* xor.b #imm,@(R0+GBR) */
782: gen_op_movl_rN_T0(REG(0));
783: gen_op_addl_GBR_T0();
784: gen_op_movl_T0_T1();
785: gen_op_ldb_T0_T0(ctx);
786: gen_op_xor_imm_T0(B7_0);
787: gen_op_stb_T0_T1(ctx);
788: return;
789: }
790:
791: switch (ctx->opcode & 0xf08f) {
792: case 0x408e: /* ldc Rm,Rn_BANK */
793: gen_op_movl_rN_rN(REG(B11_8), ALTREG(B6_4));
794: return;
795: case 0x4087: /* ldc.l @Rm+,Rn_BANK */
796: gen_op_movl_rN_T0(REG(B11_8));
797: gen_op_ldl_T0_T0(ctx);
798: gen_op_movl_T0_rN(ALTREG(B6_4));
799: gen_op_inc4_rN(REG(B11_8));
800: return;
801: case 0x0082: /* stc Rm_BANK,Rn */
802: gen_op_movl_rN_rN(ALTREG(B6_4), REG(B11_8));
803: return;
804: case 0x4083: /* stc.l Rm_BANK,@-Rn */
805: gen_op_dec4_rN(REG(B11_8));
806: gen_op_movl_rN_T1(REG(B11_8));
807: gen_op_movl_rN_T0(ALTREG(B6_4));
808: gen_op_stl_T0_T1(ctx);
809: return;
810: }
811:
812: switch (ctx->opcode & 0xf0ff) {
813: case 0x0023: /* braf Rn */
814: CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
815: gen_op_braf_T0(ctx->pc + 4);
816: ctx->flags |= DELAY_SLOT;
817: ctx->delayed_pc = (uint32_t) - 1;
818: return;
819: case 0x0003: /* bsrf Rn */
820: CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
821: gen_op_bsrf_T0(ctx->pc + 4);
822: ctx->flags |= DELAY_SLOT;
823: ctx->delayed_pc = (uint32_t) - 1;
824: return;
825: case 0x4015: /* cmp/pl Rn */
826: gen_op_movl_rN_T0(REG(B11_8));
827: gen_op_cmp_pl_T0();
828: return;
829: case 0x4011: /* cmp/pz Rn */
830: gen_op_movl_rN_T0(REG(B11_8));
831: gen_op_cmp_pz_T0();
832: return;
833: case 0x4010: /* dt Rn */
834: gen_op_dt_rN(REG(B11_8));
835: return;
836: case 0x402b: /* jmp @Rn */
837: CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
838: gen_op_jmp_T0();
839: ctx->flags |= DELAY_SLOT;
840: ctx->delayed_pc = (uint32_t) - 1;
841: return;
842: case 0x400b: /* jsr @Rn */
843: CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
844: gen_op_jsr_T0(ctx->pc + 4);
845: ctx->flags |= DELAY_SLOT;
846: ctx->delayed_pc = (uint32_t) - 1;
847: return;
848: #define LDST(reg,ldnum,ldpnum,ldop,stnum,stpnum,stop,extrald) \
849: case ldnum: \
850: gen_op_movl_rN_T0 (REG(B11_8)); \
851: gen_op_##ldop##_T0_##reg (); \
852: extrald \
853: return; \
854: case ldpnum: \
855: gen_op_movl_rN_T0 (REG(B11_8)); \
856: gen_op_ldl_T0_T0 (ctx); \
857: gen_op_inc4_rN (REG(B11_8)); \
858: gen_op_##ldop##_T0_##reg (); \
859: extrald \
860: return; \
861: case stnum: \
862: gen_op_##stop##_##reg##_T0 (); \
863: gen_op_movl_T0_rN (REG(B11_8)); \
864: return; \
865: case stpnum: \
866: gen_op_##stop##_##reg##_T0 (); \
867: gen_op_dec4_rN (REG(B11_8)); \
868: gen_op_movl_rN_T1 (REG(B11_8)); \
869: gen_op_stl_T0_T1 (ctx); \
870: return;
871: LDST(sr, 0x400e, 0x4007, ldc, 0x0002, 0x4003, stc, ctx->flags |=
872: MODE_CHANGE;
873: )
874: LDST(gbr, 0x401e, 0x4017, ldc, 0x0012, 0x4013, stc,)
875: LDST(vbr, 0x402e, 0x4027, ldc, 0x0022, 0x4023, stc,)
876: LDST(ssr, 0x403e, 0x4037, ldc, 0x0032, 0x4033, stc,)
877: LDST(spc, 0x404e, 0x4047, ldc, 0x0042, 0x4043, stc,)
878: LDST(dbr, 0x40fa, 0x40f6, ldc, 0x00fa, 0x40f2, stc,)
879: LDST(mach, 0x400a, 0x4006, lds, 0x000a, 0x4002, sts,)
880: LDST(macl, 0x401a, 0x4016, lds, 0x001a, 0x4012, sts,)
881: LDST(pr, 0x402a, 0x4026, lds, 0x002a, 0x4022, sts,)
882: case 0x00c3: /* movca.l R0,@Rm */
883: gen_op_movl_rN_T0(REG(0));
884: gen_op_movl_rN_T1(REG(B11_8));
885: gen_op_stl_T0_T1(ctx);
886: return;
887: case 0x0029: /* movt Rn */
888: gen_op_movt_rN(REG(B11_8));
889: return;
890: case 0x0093: /* ocbi @Rn */
891: gen_op_movl_rN_T0(REG(B11_8));
892: gen_op_ldl_T0_T0(ctx);
893: return;
894: case 0x00a2: /* ocbp @Rn */
895: gen_op_movl_rN_T0(REG(B11_8));
896: gen_op_ldl_T0_T0(ctx);
897: return;
898: case 0x00b3: /* ocbwb @Rn */
899: gen_op_movl_rN_T0(REG(B11_8));
900: gen_op_ldl_T0_T0(ctx);
901: return;
902: case 0x0083: /* pref @Rn */
903: return;
904: case 0x4024: /* rotcl Rn */
905: gen_op_rotcl_Rn(REG(B11_8));
906: return;
907: case 0x4025: /* rotcr Rn */
908: gen_op_rotcr_Rn(REG(B11_8));
909: return;
910: case 0x4004: /* rotl Rn */
911: gen_op_rotl_Rn(REG(B11_8));
912: return;
913: case 0x4005: /* rotr Rn */
914: gen_op_rotr_Rn(REG(B11_8));
915: return;
916: case 0x4000: /* shll Rn */
917: case 0x4020: /* shal Rn */
918: gen_op_shal_Rn(REG(B11_8));
919: return;
920: case 0x4021: /* shar Rn */
921: gen_op_shar_Rn(REG(B11_8));
922: return;
923: case 0x4001: /* shlr Rn */
924: gen_op_shlr_Rn(REG(B11_8));
925: return;
926: case 0x4008: /* shll2 Rn */
927: gen_op_shll2_Rn(REG(B11_8));
928: return;
929: case 0x4018: /* shll8 Rn */
930: gen_op_shll8_Rn(REG(B11_8));
931: return;
932: case 0x4028: /* shll16 Rn */
933: gen_op_shll16_Rn(REG(B11_8));
934: return;
935: case 0x4009: /* shlr2 Rn */
936: gen_op_shlr2_Rn(REG(B11_8));
937: return;
938: case 0x4019: /* shlr8 Rn */
939: gen_op_shlr8_Rn(REG(B11_8));
940: return;
941: case 0x4029: /* shlr16 Rn */
942: gen_op_shlr16_Rn(REG(B11_8));
943: return;
944: case 0x401b: /* tas.b @Rn */
945: gen_op_tasb_rN(REG(B11_8));
946: return;
947: }
948:
949: fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
950: ctx->opcode, ctx->pc);
951: gen_op_raise_illegal_instruction();
952: ctx->flags |= BRANCH_EXCEPTION;
953: }
954:
955: int gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
956: int search_pc)
957: {
958: DisasContext ctx;
959: target_ulong pc_start;
960: static uint16_t *gen_opc_end;
961: uint32_t old_flags;
962: int i;
963:
964: pc_start = tb->pc;
965: gen_opc_ptr = gen_opc_buf;
966: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
967: gen_opparam_ptr = gen_opparam_buf;
968: ctx.pc = pc_start;
969: ctx.flags = env->flags;
970: old_flags = 0;
971: ctx.sr = env->sr;
972: ctx.memidx = (env->sr & SR_MD) ? 1 : 0;
973: ctx.delayed_pc = env->delayed_pc;
974: ctx.tb = tb;
975: ctx.singlestep_enabled = env->singlestep_enabled;
976: nb_gen_labels = 0;
977:
978: #ifdef DEBUG_DISAS
979: if (loglevel & CPU_LOG_TB_CPU) {
980: fprintf(logfile,
981: "------------------------------------------------\n");
982: cpu_dump_state(env, logfile, fprintf, 0);
983: }
984: #endif
985:
986: while ((old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) == 0 &&
987: (ctx.flags & (BRANCH | BRANCH_CONDITIONAL | MODE_CHANGE |
988: BRANCH_EXCEPTION)) == 0 &&
989: gen_opc_ptr < gen_opc_end && ctx.sr == env->sr) {
990: old_flags = ctx.flags;
991: if (env->nb_breakpoints > 0) {
992: for (i = 0; i < env->nb_breakpoints; i++) {
993: if (ctx.pc == env->breakpoints[i]) {
994: /* We have hit a breakpoint - make sure PC is up-to-date */
995: gen_op_movl_imm_PC(ctx.pc);
996: gen_op_debug();
997: ctx.flags |= BRANCH_EXCEPTION;
998: break;
999: }
1000: }
1001: }
1002: #if 0
1003: fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
1004: fflush(stderr);
1005: #endif
1006: ctx.opcode = lduw_code(ctx.pc);
1007: decode_opc(&ctx);
1008: ctx.pc += 2;
1009: if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1010: break;
1011: if (env->singlestep_enabled)
1012: break;
1013: #ifdef SH4_SINGLE_STEP
1014: break;
1015: #endif
1016: }
1017:
1018: switch (old_flags & (DELAY_SLOT_CONDITIONAL | DELAY_SLOT)) {
1019: case DELAY_SLOT_CONDITIONAL:
1020: gen_op_clr_delay_slot_conditional();
1021: gen_delayed_conditional_jump(&ctx);
1022: break;
1023: case DELAY_SLOT:
1024: gen_op_clr_delay_slot();
1025: gen_jump(&ctx);
1026: break;
1027: case 0:
1028: if (ctx.flags & BRANCH_EXCEPTION) {
1029: gen_jump_exception(&ctx);
1030: } else if ((ctx.flags & (BRANCH | BRANCH_CONDITIONAL)) == 0) {
1031: gen_goto_tb(&ctx, 0, ctx.pc);
1032: }
1033: break;
1034: default:
1035: /* Both cannot be set at the same time */
1036: assert(0);
1037: }
1038:
1039: if (env->singlestep_enabled) {
1040: gen_op_debug();
1041: }
1042: *gen_opc_ptr = INDEX_op_end;
1043: tb->size = ctx.pc - pc_start;
1044:
1045: #ifdef DEBUG_DISAS
1046: #ifdef SH4_DEBUG_DISAS
1047: if (loglevel & CPU_LOG_TB_IN_ASM)
1048: fprintf(logfile, "\n");
1049: #endif
1050: if (loglevel & CPU_LOG_TB_IN_ASM) {
1051: fprintf(logfile, "IN:\n"); /* , lookup_symbol(pc_start)); */
1052: target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1053: fprintf(logfile, "\n");
1054: }
1055: if (loglevel & CPU_LOG_TB_OP) {
1056: fprintf(logfile, "OP:\n");
1057: dump_ops(gen_opc_buf, gen_opparam_buf);
1058: fprintf(logfile, "\n");
1059: }
1060: #endif
1061: return 0;
1062: }
1063:
1064: int gen_intermediate_code(CPUState * env, struct TranslationBlock *tb)
1065: {
1066: return gen_intermediate_code_internal(env, tb, 0);
1067: }
1068:
1069: int gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
1070: {
1071: assert(0);
1072: return gen_intermediate_code_internal(env, tb, 1);
1073: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.