4 * Copyright (c) 2005 Samuel Tardieu
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.
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.
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
28 #define SH4_DEBUG_DISAS
29 //#define SH4_SINGLE_STEP
36 typedef struct DisasContext {
37 struct TranslationBlock *tb;
46 int singlestep_enabled;
50 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
53 BS_STOP = 1, /* We want to stop translation for any reason */
54 BS_BRANCH = 2, /* We reached a branch condition */
55 BS_EXCP = 3, /* We reached an exception condition */
58 #ifdef CONFIG_USER_ONLY
60 #define GEN_OP_LD(width, reg) \
61 void gen_op_ld##width##_T0_##reg (DisasContext *ctx) { \
62 gen_op_ld##width##_T0_##reg##_raw(); \
64 #define GEN_OP_ST(width, reg) \
65 void gen_op_st##width##_##reg##_T1 (DisasContext *ctx) { \
66 gen_op_st##width##_##reg##_T1_raw(); \
71 #define GEN_OP_LD(width, reg) \
72 void gen_op_ld##width##_T0_##reg (DisasContext *ctx) { \
73 if (ctx->memidx) gen_op_ld##width##_T0_##reg##_kernel(); \
74 else gen_op_ld##width##_T0_##reg##_user();\
76 #define GEN_OP_ST(width, reg) \
77 void gen_op_st##width##_##reg##_T1 (DisasContext *ctx) { \
78 if (ctx->memidx) gen_op_st##width##_##reg##_T1_kernel(); \
79 else gen_op_st##width##_##reg##_T1_user();\
97 void cpu_dump_state(CPUState * env, FILE * f,
98 int (*cpu_fprintf) (FILE * f, const char *fmt, ...),
102 cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
103 env->pc, env->sr, env->pr, env->fpscr);
104 for (i = 0; i < 24; i += 4) {
105 cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
106 i, env->gregs[i], i + 1, env->gregs[i + 1],
107 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
109 if (env->flags & DELAY_SLOT) {
110 cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
112 } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
113 cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
118 void cpu_sh4_reset(CPUSH4State * env)
120 #if defined(CONFIG_USER_ONLY)
121 env->sr = SR_FD; /* FD - kernel does lazy fpu context switch */
123 env->sr = 0x700000F0; /* MD, RB, BL, I3-I0 */
126 env->pc = 0xA0000000;
127 #if defined(CONFIG_USER_ONLY)
128 env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
129 set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
131 env->fpscr = 0x00040001; /* CPU reset value according to SH4 manual */
132 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
137 CPUSH4State *cpu_sh4_init(const char *cpu_model)
141 env = qemu_mallocz(sizeof(CPUSH4State));
150 static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
152 TranslationBlock *tb;
155 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
156 !ctx->singlestep_enabled) {
157 /* Use a direct jump if in same page and singlestep not enabled */
159 gen_op_movl_imm_PC(dest);
160 tcg_gen_exit_tb((long) tb + n);
162 gen_op_movl_imm_PC(dest);
163 if (ctx->singlestep_enabled)
169 static void gen_jump(DisasContext * ctx)
171 if (ctx->delayed_pc == (uint32_t) - 1) {
172 /* Target is not statically known, it comes necessarily from a
173 delayed jump as immediate jump are conditinal jumps */
174 gen_op_movl_delayed_pc_PC();
175 if (ctx->singlestep_enabled)
179 gen_goto_tb(ctx, 0, ctx->delayed_pc);
183 /* Immediate conditional jump (bt or bf) */
184 static void gen_conditional_jump(DisasContext * ctx,
185 target_ulong ift, target_ulong ifnott)
189 l1 = gen_new_label();
191 gen_goto_tb(ctx, 0, ifnott);
193 gen_goto_tb(ctx, 1, ift);
196 /* Delayed conditional jump (bt or bf) */
197 static void gen_delayed_conditional_jump(DisasContext * ctx)
201 l1 = gen_new_label();
203 gen_goto_tb(ctx, 1, ctx->pc + 2);
208 #define B3_0 (ctx->opcode & 0xf)
209 #define B6_4 ((ctx->opcode >> 4) & 0x7)
210 #define B7_4 ((ctx->opcode >> 4) & 0xf)
211 #define B7_0 (ctx->opcode & 0xff)
212 #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
213 #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
214 (ctx->opcode & 0xfff))
215 #define B11_8 ((ctx->opcode >> 8) & 0xf)
216 #define B15_12 ((ctx->opcode >> 12) & 0xf)
218 #define REG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB) ? \
221 #define ALTREG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) != (SR_MD | SR_RB) \
224 #define FREG(x) (ctx->fpscr & FPSCR_FR ? (x) ^ 0x10 : (x))
225 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
226 #define XREG(x) (ctx->fpscr & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x))
227 #define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */
229 #define CHECK_NOT_DELAY_SLOT \
230 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
231 {gen_op_raise_slot_illegal_instruction (); ctx->bstate = BS_EXCP; \
234 void _decode_opc(DisasContext * ctx)
237 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
239 switch (ctx->opcode) {
240 case 0x0019: /* div0u */
243 case 0x000b: /* rts */
244 CHECK_NOT_DELAY_SLOT gen_op_rts();
245 ctx->flags |= DELAY_SLOT;
246 ctx->delayed_pc = (uint32_t) - 1;
248 case 0x0028: /* clrmac */
251 case 0x0048: /* clrs */
254 case 0x0008: /* clrt */
257 case 0x0038: /* ldtlb */
258 assert(0); /* XXXXX */
260 case 0x002b: /* rte */
261 CHECK_NOT_DELAY_SLOT gen_op_rte();
262 ctx->flags |= DELAY_SLOT;
263 ctx->delayed_pc = (uint32_t) - 1;
265 case 0x0058: /* sets */
268 case 0x0018: /* sett */
271 case 0xfbfb: /* frchg */
273 ctx->bstate = BS_STOP;
275 case 0xf3fb: /* fschg */
277 ctx->bstate = BS_STOP;
279 case 0x0009: /* nop */
281 case 0x001b: /* sleep */
282 assert(0); /* XXXXX */
286 switch (ctx->opcode & 0xf000) {
287 case 0x1000: /* mov.l Rm,@(disp,Rn) */
288 gen_op_movl_rN_T0(REG(B7_4));
289 gen_op_movl_rN_T1(REG(B11_8));
290 gen_op_addl_imm_T1(B3_0 * 4);
291 gen_op_stl_T0_T1(ctx);
293 case 0x5000: /* mov.l @(disp,Rm),Rn */
294 gen_op_movl_rN_T0(REG(B7_4));
295 gen_op_addl_imm_T0(B3_0 * 4);
296 gen_op_ldl_T0_T0(ctx);
297 gen_op_movl_T0_rN(REG(B11_8));
299 case 0xe000: /* mov.l #imm,Rn */
300 gen_op_movl_imm_rN(B7_0s, REG(B11_8));
302 case 0x9000: /* mov.w @(disp,PC),Rn */
303 gen_op_movl_imm_T0(ctx->pc + 4 + B7_0 * 2);
304 gen_op_ldw_T0_T0(ctx);
305 gen_op_movl_T0_rN(REG(B11_8));
307 case 0xd000: /* mov.l @(disp,PC),Rn */
308 gen_op_movl_imm_T0((ctx->pc + 4 + B7_0 * 4) & ~3);
309 gen_op_ldl_T0_T0(ctx);
310 gen_op_movl_T0_rN(REG(B11_8));
312 case 0x7000: /* add.l #imm,Rn */
313 gen_op_add_imm_rN(B7_0s, REG(B11_8));
315 case 0xa000: /* bra disp */
317 gen_op_bra(ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2);
318 ctx->flags |= DELAY_SLOT;
320 case 0xb000: /* bsr disp */
322 gen_op_bsr(ctx->pc + 4, ctx->delayed_pc =
323 ctx->pc + 4 + B11_0s * 2);
324 ctx->flags |= DELAY_SLOT;
328 switch (ctx->opcode & 0xf00f) {
329 case 0x6003: /* mov Rm,Rn */
330 gen_op_movl_rN_T0(REG(B7_4));
331 gen_op_movl_T0_rN(REG(B11_8));
333 case 0x2000: /* mov.b Rm,@Rn */
334 gen_op_movl_rN_T0(REG(B7_4));
335 gen_op_movl_rN_T1(REG(B11_8));
336 gen_op_stb_T0_T1(ctx);
338 case 0x2001: /* mov.w Rm,@Rn */
339 gen_op_movl_rN_T0(REG(B7_4));
340 gen_op_movl_rN_T1(REG(B11_8));
341 gen_op_stw_T0_T1(ctx);
343 case 0x2002: /* mov.l Rm,@Rn */
344 gen_op_movl_rN_T0(REG(B7_4));
345 gen_op_movl_rN_T1(REG(B11_8));
346 gen_op_stl_T0_T1(ctx);
348 case 0x6000: /* mov.b @Rm,Rn */
349 gen_op_movl_rN_T0(REG(B7_4));
350 gen_op_ldb_T0_T0(ctx);
351 gen_op_movl_T0_rN(REG(B11_8));
353 case 0x6001: /* mov.w @Rm,Rn */
354 gen_op_movl_rN_T0(REG(B7_4));
355 gen_op_ldw_T0_T0(ctx);
356 gen_op_movl_T0_rN(REG(B11_8));
358 case 0x6002: /* mov.l @Rm,Rn */
359 gen_op_movl_rN_T0(REG(B7_4));
360 gen_op_ldl_T0_T0(ctx);
361 gen_op_movl_T0_rN(REG(B11_8));
363 case 0x2004: /* mov.b Rm,@-Rn */
364 gen_op_dec1_rN(REG(B11_8));
365 gen_op_movl_rN_T0(REG(B7_4));
366 gen_op_movl_rN_T1(REG(B11_8));
367 gen_op_stb_T0_T1(ctx);
369 case 0x2005: /* mov.w Rm,@-Rn */
370 gen_op_dec2_rN(REG(B11_8));
371 gen_op_movl_rN_T0(REG(B7_4));
372 gen_op_movl_rN_T1(REG(B11_8));
373 gen_op_stw_T0_T1(ctx);
375 case 0x2006: /* mov.l Rm,@-Rn */
376 gen_op_dec4_rN(REG(B11_8));
377 gen_op_movl_rN_T0(REG(B7_4));
378 gen_op_movl_rN_T1(REG(B11_8));
379 gen_op_stl_T0_T1(ctx);
381 case 0x6004: /* mov.b @Rm+,Rn */
382 gen_op_movl_rN_T0(REG(B7_4));
383 gen_op_ldb_T0_T0(ctx);
384 gen_op_movl_T0_rN(REG(B11_8));
385 gen_op_inc1_rN(REG(B7_4));
387 case 0x6005: /* mov.w @Rm+,Rn */
388 gen_op_movl_rN_T0(REG(B7_4));
389 gen_op_ldw_T0_T0(ctx);
390 gen_op_movl_T0_rN(REG(B11_8));
391 gen_op_inc2_rN(REG(B7_4));
393 case 0x6006: /* mov.l @Rm+,Rn */
394 gen_op_movl_rN_T0(REG(B7_4));
395 gen_op_ldl_T0_T0(ctx);
396 gen_op_movl_T0_rN(REG(B11_8));
397 gen_op_inc4_rN(REG(B7_4));
399 case 0x0004: /* mov.b Rm,@(R0,Rn) */
400 gen_op_movl_rN_T0(REG(B7_4));
401 gen_op_movl_rN_T1(REG(B11_8));
402 gen_op_add_rN_T1(REG(0));
403 gen_op_stb_T0_T1(ctx);
405 case 0x0005: /* mov.w Rm,@(R0,Rn) */
406 gen_op_movl_rN_T0(REG(B7_4));
407 gen_op_movl_rN_T1(REG(B11_8));
408 gen_op_add_rN_T1(REG(0));
409 gen_op_stw_T0_T1(ctx);
411 case 0x0006: /* mov.l Rm,@(R0,Rn) */
412 gen_op_movl_rN_T0(REG(B7_4));
413 gen_op_movl_rN_T1(REG(B11_8));
414 gen_op_add_rN_T1(REG(0));
415 gen_op_stl_T0_T1(ctx);
417 case 0x000c: /* mov.b @(R0,Rm),Rn */
418 gen_op_movl_rN_T0(REG(B7_4));
419 gen_op_add_rN_T0(REG(0));
420 gen_op_ldb_T0_T0(ctx);
421 gen_op_movl_T0_rN(REG(B11_8));
423 case 0x000d: /* mov.w @(R0,Rm),Rn */
424 gen_op_movl_rN_T0(REG(B7_4));
425 gen_op_add_rN_T0(REG(0));
426 gen_op_ldw_T0_T0(ctx);
427 gen_op_movl_T0_rN(REG(B11_8));
429 case 0x000e: /* mov.l @(R0,Rm),Rn */
430 gen_op_movl_rN_T0(REG(B7_4));
431 gen_op_add_rN_T0(REG(0));
432 gen_op_ldl_T0_T0(ctx);
433 gen_op_movl_T0_rN(REG(B11_8));
435 case 0x6008: /* swap.b Rm,Rn */
436 gen_op_movl_rN_T0(REG(B7_4));
438 gen_op_movl_T0_rN(REG(B11_8));
440 case 0x6009: /* swap.w Rm,Rn */
441 gen_op_movl_rN_T0(REG(B7_4));
443 gen_op_movl_T0_rN(REG(B11_8));
445 case 0x200d: /* xtrct Rm,Rn */
446 gen_op_movl_rN_T0(REG(B7_4));
447 gen_op_movl_rN_T1(REG(B11_8));
448 gen_op_xtrct_T0_T1();
449 gen_op_movl_T1_rN(REG(B11_8));
451 case 0x300c: /* add Rm,Rn */
452 gen_op_movl_rN_T0(REG(B7_4));
453 gen_op_add_T0_rN(REG(B11_8));
455 case 0x300e: /* addc Rm,Rn */
456 gen_op_movl_rN_T0(REG(B7_4));
457 gen_op_movl_rN_T1(REG(B11_8));
459 gen_op_movl_T1_rN(REG(B11_8));
461 case 0x300f: /* addv Rm,Rn */
462 gen_op_movl_rN_T0(REG(B7_4));
463 gen_op_movl_rN_T1(REG(B11_8));
465 gen_op_movl_T1_rN(REG(B11_8));
467 case 0x2009: /* and Rm,Rn */
468 gen_op_movl_rN_T0(REG(B7_4));
469 gen_op_and_T0_rN(REG(B11_8));
471 case 0x3000: /* cmp/eq Rm,Rn */
472 gen_op_movl_rN_T0(REG(B7_4));
473 gen_op_movl_rN_T1(REG(B11_8));
474 gen_op_cmp_eq_T0_T1();
476 case 0x3003: /* cmp/ge Rm,Rn */
477 gen_op_movl_rN_T0(REG(B7_4));
478 gen_op_movl_rN_T1(REG(B11_8));
479 gen_op_cmp_ge_T0_T1();
481 case 0x3007: /* cmp/gt Rm,Rn */
482 gen_op_movl_rN_T0(REG(B7_4));
483 gen_op_movl_rN_T1(REG(B11_8));
484 gen_op_cmp_gt_T0_T1();
486 case 0x3006: /* cmp/hi Rm,Rn */
487 gen_op_movl_rN_T0(REG(B7_4));
488 gen_op_movl_rN_T1(REG(B11_8));
489 gen_op_cmp_hi_T0_T1();
491 case 0x3002: /* cmp/hs Rm,Rn */
492 gen_op_movl_rN_T0(REG(B7_4));
493 gen_op_movl_rN_T1(REG(B11_8));
494 gen_op_cmp_hs_T0_T1();
496 case 0x200c: /* cmp/str Rm,Rn */
497 gen_op_movl_rN_T0(REG(B7_4));
498 gen_op_movl_rN_T1(REG(B11_8));
499 gen_op_cmp_str_T0_T1();
501 case 0x2007: /* div0s Rm,Rn */
502 gen_op_movl_rN_T0(REG(B7_4));
503 gen_op_movl_rN_T1(REG(B11_8));
504 gen_op_div0s_T0_T1();
505 gen_op_movl_T1_rN(REG(B11_8));
507 case 0x3004: /* div1 Rm,Rn */
508 gen_op_movl_rN_T0(REG(B7_4));
509 gen_op_movl_rN_T1(REG(B11_8));
511 gen_op_movl_T1_rN(REG(B11_8));
513 case 0x300d: /* dmuls.l Rm,Rn */
514 gen_op_movl_rN_T0(REG(B7_4));
515 gen_op_movl_rN_T1(REG(B11_8));
516 gen_op_dmulsl_T0_T1();
518 case 0x3005: /* dmulu.l Rm,Rn */
519 gen_op_movl_rN_T0(REG(B7_4));
520 gen_op_movl_rN_T1(REG(B11_8));
521 gen_op_dmulul_T0_T1();
523 case 0x600e: /* exts.b Rm,Rn */
524 gen_op_movb_rN_T0(REG(B7_4));
525 gen_op_movl_T0_rN(REG(B11_8));
527 case 0x600f: /* exts.w Rm,Rn */
528 gen_op_movw_rN_T0(REG(B7_4));
529 gen_op_movl_T0_rN(REG(B11_8));
531 case 0x600c: /* extu.b Rm,Rn */
532 gen_op_movub_rN_T0(REG(B7_4));
533 gen_op_movl_T0_rN(REG(B11_8));
535 case 0x600d: /* extu.w Rm,Rn */
536 gen_op_movuw_rN_T0(REG(B7_4));
537 gen_op_movl_T0_rN(REG(B11_8));
539 case 0x000f: /* mac.l @Rm+,@Rn- */
540 gen_op_movl_rN_T0(REG(B11_8));
541 gen_op_ldl_T0_T0(ctx);
543 gen_op_movl_rN_T1(REG(B7_4));
544 gen_op_ldl_T0_T0(ctx);
546 gen_op_inc4_rN(REG(B7_4));
547 gen_op_inc4_rN(REG(B11_8));
549 case 0x400f: /* mac.w @Rm+,@Rn+ */
550 gen_op_movl_rN_T0(REG(B11_8));
551 gen_op_ldl_T0_T0(ctx);
553 gen_op_movl_rN_T1(REG(B7_4));
554 gen_op_ldl_T0_T0(ctx);
556 gen_op_inc2_rN(REG(B7_4));
557 gen_op_inc2_rN(REG(B11_8));
559 case 0x0007: /* mul.l Rm,Rn */
560 gen_op_movl_rN_T0(REG(B7_4));
561 gen_op_movl_rN_T1(REG(B11_8));
564 case 0x200f: /* muls.w Rm,Rn */
565 gen_op_movw_rN_T0(REG(B7_4));
566 gen_op_movw_rN_T1(REG(B11_8));
567 gen_op_mulsw_T0_T1();
569 case 0x200e: /* mulu.w Rm,Rn */
570 gen_op_movuw_rN_T0(REG(B7_4));
571 gen_op_movuw_rN_T1(REG(B11_8));
572 gen_op_muluw_T0_T1();
574 case 0x600b: /* neg Rm,Rn */
575 gen_op_movl_rN_T0(REG(B7_4));
577 gen_op_movl_T0_rN(REG(B11_8));
579 case 0x600a: /* negc Rm,Rn */
580 gen_op_movl_rN_T0(REG(B7_4));
582 gen_op_movl_T0_rN(REG(B11_8));
584 case 0x6007: /* not Rm,Rn */
585 gen_op_movl_rN_T0(REG(B7_4));
587 gen_op_movl_T0_rN(REG(B11_8));
589 case 0x200b: /* or Rm,Rn */
590 gen_op_movl_rN_T0(REG(B7_4));
591 gen_op_or_T0_rN(REG(B11_8));
593 case 0x400c: /* shad Rm,Rn */
594 gen_op_movl_rN_T0(REG(B7_4));
595 gen_op_movl_rN_T1(REG(B11_8));
597 gen_op_movl_T1_rN(REG(B11_8));
599 case 0x400d: /* shld Rm,Rn */
600 gen_op_movl_rN_T0(REG(B7_4));
601 gen_op_movl_rN_T1(REG(B11_8));
603 gen_op_movl_T1_rN(REG(B11_8));
605 case 0x3008: /* sub Rm,Rn */
606 gen_op_movl_rN_T0(REG(B7_4));
607 gen_op_sub_T0_rN(REG(B11_8));
609 case 0x300a: /* subc Rm,Rn */
610 gen_op_movl_rN_T0(REG(B7_4));
611 gen_op_movl_rN_T1(REG(B11_8));
613 gen_op_movl_T1_rN(REG(B11_8));
615 case 0x300b: /* subv Rm,Rn */
616 gen_op_movl_rN_T0(REG(B7_4));
617 gen_op_movl_rN_T1(REG(B11_8));
619 gen_op_movl_T1_rN(REG(B11_8));
621 case 0x2008: /* tst Rm,Rn */
622 gen_op_movl_rN_T0(REG(B7_4));
623 gen_op_movl_rN_T1(REG(B11_8));
626 case 0x200a: /* xor Rm,Rn */
627 gen_op_movl_rN_T0(REG(B7_4));
628 gen_op_xor_T0_rN(REG(B11_8));
630 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
631 if (ctx->fpscr & FPSCR_SZ) {
632 if (ctx->opcode & 0x0110)
633 break; /* illegal instruction */
634 gen_op_fmov_drN_DT0(DREG(B7_4));
635 gen_op_fmov_DT0_drN(DREG(B11_8));
637 gen_op_fmov_frN_FT0(FREG(B7_4));
638 gen_op_fmov_FT0_frN(FREG(B11_8));
641 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
642 if (ctx->fpscr & FPSCR_SZ) {
643 if (ctx->opcode & 0x0010)
644 break; /* illegal instruction */
645 gen_op_fmov_drN_DT0(DREG(B7_4));
646 gen_op_movl_rN_T1(REG(B11_8));
647 gen_op_stfq_DT0_T1(ctx);
649 gen_op_fmov_frN_FT0(FREG(B7_4));
650 gen_op_movl_rN_T1(REG(B11_8));
651 gen_op_stfl_FT0_T1(ctx);
654 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
655 if (ctx->fpscr & FPSCR_SZ) {
656 if (ctx->opcode & 0x0100)
657 break; /* illegal instruction */
658 gen_op_movl_rN_T0(REG(B7_4));
659 gen_op_ldfq_T0_DT0(ctx);
660 gen_op_fmov_DT0_drN(DREG(B11_8));
662 gen_op_movl_rN_T0(REG(B7_4));
663 gen_op_ldfl_T0_FT0(ctx);
664 gen_op_fmov_FT0_frN(FREG(B11_8));
667 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
668 if (ctx->fpscr & FPSCR_SZ) {
669 if (ctx->opcode & 0x0100)
670 break; /* illegal instruction */
671 gen_op_movl_rN_T0(REG(B7_4));
672 gen_op_ldfq_T0_DT0(ctx);
673 gen_op_fmov_DT0_drN(DREG(B11_8));
674 gen_op_inc8_rN(REG(B7_4));
676 gen_op_movl_rN_T0(REG(B7_4));
677 gen_op_ldfl_T0_FT0(ctx);
678 gen_op_fmov_FT0_frN(FREG(B11_8));
679 gen_op_inc4_rN(REG(B7_4));
682 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
683 if (ctx->fpscr & FPSCR_SZ) {
684 if (ctx->opcode & 0x0100)
685 break; /* illegal instruction */
686 gen_op_dec8_rN(REG(B11_8));
687 gen_op_fmov_drN_DT0(DREG(B7_4));
688 gen_op_movl_rN_T1(REG(B11_8));
689 gen_op_stfq_DT0_T1(ctx);
691 gen_op_dec4_rN(REG(B11_8));
692 gen_op_fmov_frN_FT0(FREG(B7_4));
693 gen_op_movl_rN_T1(REG(B11_8));
694 gen_op_stfl_FT0_T1(ctx);
697 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
698 if (ctx->fpscr & FPSCR_SZ) {
699 if (ctx->opcode & 0x0100)
700 break; /* illegal instruction */
701 gen_op_movl_rN_T0(REG(B7_4));
702 gen_op_add_rN_T0(REG(0));
703 gen_op_ldfq_T0_DT0(ctx);
704 gen_op_fmov_DT0_drN(DREG(B11_8));
706 gen_op_movl_rN_T0(REG(B7_4));
707 gen_op_add_rN_T0(REG(0));
708 gen_op_ldfl_T0_FT0(ctx);
709 gen_op_fmov_FT0_frN(FREG(B11_8));
712 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
713 if (ctx->fpscr & FPSCR_SZ) {
714 if (ctx->opcode & 0x0010)
715 break; /* illegal instruction */
716 gen_op_fmov_drN_DT0(DREG(B7_4));
717 gen_op_movl_rN_T1(REG(B11_8));
718 gen_op_add_rN_T1(REG(0));
719 gen_op_stfq_DT0_T1(ctx);
721 gen_op_fmov_frN_FT0(FREG(B7_4));
722 gen_op_movl_rN_T1(REG(B11_8));
723 gen_op_add_rN_T1(REG(0));
724 gen_op_stfl_FT0_T1(ctx);
727 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
728 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
729 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
730 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
731 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
732 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
733 if (ctx->fpscr & FPSCR_PR) {
734 if (ctx->opcode & 0x0110)
735 break; /* illegal instruction */
736 gen_op_fmov_drN_DT1(DREG(B7_4));
737 gen_op_fmov_drN_DT0(DREG(B11_8));
740 gen_op_fmov_frN_FT1(FREG(B7_4));
741 gen_op_fmov_frN_FT0(FREG(B11_8));
744 switch (ctx->opcode & 0xf00f) {
745 case 0xf000: /* fadd Rm,Rn */
746 ctx->fpscr & FPSCR_PR ? gen_op_fadd_DT() : gen_op_fadd_FT();
748 case 0xf001: /* fsub Rm,Rn */
749 ctx->fpscr & FPSCR_PR ? gen_op_fsub_DT() : gen_op_fsub_FT();
751 case 0xf002: /* fmul Rm,Rn */
752 ctx->fpscr & FPSCR_PR ? gen_op_fmul_DT() : gen_op_fmul_FT();
754 case 0xf003: /* fdiv Rm,Rn */
755 ctx->fpscr & FPSCR_PR ? gen_op_fdiv_DT() : gen_op_fdiv_FT();
757 case 0xf004: /* fcmp/eq Rm,Rn */
759 case 0xf005: /* fcmp/gt Rm,Rn */
763 if (ctx->fpscr & FPSCR_PR) {
764 gen_op_fmov_DT0_drN(DREG(B11_8));
767 gen_op_fmov_FT0_frN(FREG(B11_8));
772 switch (ctx->opcode & 0xff00) {
773 case 0xc900: /* and #imm,R0 */
774 gen_op_and_imm_rN(B7_0, REG(0));
776 case 0xcd00: /* and.b #imm,@(R0+GBR) */
777 gen_op_movl_rN_T0(REG(0));
778 gen_op_addl_GBR_T0();
780 gen_op_ldb_T0_T0(ctx);
781 gen_op_and_imm_T0(B7_0);
782 gen_op_stb_T0_T1(ctx);
784 case 0x8b00: /* bf label */
786 gen_conditional_jump(ctx, ctx->pc + 2,
787 ctx->pc + 4 + B7_0s * 2);
788 ctx->bstate = BS_BRANCH;
790 case 0x8f00: /* bf/s label */
792 gen_op_bf_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
793 ctx->flags |= DELAY_SLOT_CONDITIONAL;
795 case 0x8900: /* bt label */
797 gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2,
799 ctx->bstate = BS_BRANCH;
801 case 0x8d00: /* bt/s label */
803 gen_op_bt_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
804 ctx->flags |= DELAY_SLOT_CONDITIONAL;
806 case 0x8800: /* cmp/eq #imm,R0 */
807 gen_op_movl_rN_T0(REG(0));
808 gen_op_cmp_eq_imm_T0(B7_0s);
810 case 0xc400: /* mov.b @(disp,GBR),R0 */
812 gen_op_addl_imm_T0(B7_0);
813 gen_op_ldb_T0_T0(ctx);
814 gen_op_movl_T0_rN(REG(0));
816 case 0xc500: /* mov.w @(disp,GBR),R0 */
818 gen_op_addl_imm_T0(B7_0);
819 gen_op_ldw_T0_T0(ctx);
820 gen_op_movl_T0_rN(REG(0));
822 case 0xc600: /* mov.l @(disp,GBR),R0 */
824 gen_op_addl_imm_T0(B7_0);
825 gen_op_ldl_T0_T0(ctx);
826 gen_op_movl_T0_rN(REG(0));
828 case 0xc000: /* mov.b R0,@(disp,GBR) */
830 gen_op_addl_imm_T0(B7_0);
832 gen_op_movl_rN_T0(REG(0));
833 gen_op_stb_T0_T1(ctx);
835 case 0xc100: /* mov.w R0,@(disp,GBR) */
837 gen_op_addl_imm_T0(B7_0);
839 gen_op_movl_rN_T0(REG(0));
840 gen_op_stw_T0_T1(ctx);
842 case 0xc200: /* mov.l R0,@(disp,GBR) */
844 gen_op_addl_imm_T0(B7_0);
846 gen_op_movl_rN_T0(REG(0));
847 gen_op_stl_T0_T1(ctx);
849 case 0x8000: /* mov.b R0,@(disp,Rn) */
850 gen_op_movl_rN_T0(REG(0));
851 gen_op_movl_rN_T1(REG(B7_4));
852 gen_op_addl_imm_T1(B3_0);
853 gen_op_stb_T0_T1(ctx);
855 case 0x8100: /* mov.w R0,@(disp,Rn) */
856 gen_op_movl_rN_T0(REG(0));
857 gen_op_movl_rN_T1(REG(B7_4));
858 gen_op_addl_imm_T1(B3_0 * 2);
859 gen_op_stw_T0_T1(ctx);
861 case 0x8400: /* mov.b @(disp,Rn),R0 */
862 gen_op_movl_rN_T0(REG(B7_4));
863 gen_op_addl_imm_T0(B3_0);
864 gen_op_ldb_T0_T0(ctx);
865 gen_op_movl_T0_rN(REG(0));
867 case 0x8500: /* mov.w @(disp,Rn),R0 */
868 gen_op_movl_rN_T0(REG(B7_4));
869 gen_op_addl_imm_T0(B3_0 * 2);
870 gen_op_ldw_T0_T0(ctx);
871 gen_op_movl_T0_rN(REG(0));
873 case 0xc700: /* mova @(disp,PC),R0 */
874 gen_op_movl_imm_rN(((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3,
877 case 0xcb00: /* or #imm,R0 */
878 gen_op_or_imm_rN(B7_0, REG(0));
880 case 0xcf00: /* or.b #imm,@(R0+GBR) */
881 gen_op_movl_rN_T0(REG(0));
882 gen_op_addl_GBR_T0();
884 gen_op_ldb_T0_T0(ctx);
885 gen_op_or_imm_T0(B7_0);
886 gen_op_stb_T0_T1(ctx);
888 case 0xc300: /* trapa #imm */
889 CHECK_NOT_DELAY_SLOT gen_op_movl_imm_PC(ctx->pc);
891 ctx->bstate = BS_BRANCH;
893 case 0xc800: /* tst #imm,R0 */
894 gen_op_tst_imm_rN(B7_0, REG(0));
896 case 0xcc00: /* tst #imm,@(R0+GBR) */
897 gen_op_movl_rN_T0(REG(0));
898 gen_op_addl_GBR_T0();
899 gen_op_ldb_T0_T0(ctx);
900 gen_op_tst_imm_T0(B7_0);
902 case 0xca00: /* xor #imm,R0 */
903 gen_op_xor_imm_rN(B7_0, REG(0));
905 case 0xce00: /* xor.b #imm,@(R0+GBR) */
906 gen_op_movl_rN_T0(REG(0));
907 gen_op_addl_GBR_T0();
909 gen_op_ldb_T0_T0(ctx);
910 gen_op_xor_imm_T0(B7_0);
911 gen_op_stb_T0_T1(ctx);
915 switch (ctx->opcode & 0xf08f) {
916 case 0x408e: /* ldc Rm,Rn_BANK */
917 gen_op_movl_rN_rN(REG(B11_8), ALTREG(B6_4));
919 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
920 gen_op_movl_rN_T0(REG(B11_8));
921 gen_op_ldl_T0_T0(ctx);
922 gen_op_movl_T0_rN(ALTREG(B6_4));
923 gen_op_inc4_rN(REG(B11_8));
925 case 0x0082: /* stc Rm_BANK,Rn */
926 gen_op_movl_rN_rN(ALTREG(B6_4), REG(B11_8));
928 case 0x4083: /* stc.l Rm_BANK,@-Rn */
929 gen_op_dec4_rN(REG(B11_8));
930 gen_op_movl_rN_T1(REG(B11_8));
931 gen_op_movl_rN_T0(ALTREG(B6_4));
932 gen_op_stl_T0_T1(ctx);
936 switch (ctx->opcode & 0xf0ff) {
937 case 0x0023: /* braf Rn */
938 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
939 gen_op_braf_T0(ctx->pc + 4);
940 ctx->flags |= DELAY_SLOT;
941 ctx->delayed_pc = (uint32_t) - 1;
943 case 0x0003: /* bsrf Rn */
944 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
945 gen_op_bsrf_T0(ctx->pc + 4);
946 ctx->flags |= DELAY_SLOT;
947 ctx->delayed_pc = (uint32_t) - 1;
949 case 0x4015: /* cmp/pl Rn */
950 gen_op_movl_rN_T0(REG(B11_8));
953 case 0x4011: /* cmp/pz Rn */
954 gen_op_movl_rN_T0(REG(B11_8));
957 case 0x4010: /* dt Rn */
958 gen_op_dt_rN(REG(B11_8));
960 case 0x402b: /* jmp @Rn */
961 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
963 ctx->flags |= DELAY_SLOT;
964 ctx->delayed_pc = (uint32_t) - 1;
966 case 0x400b: /* jsr @Rn */
967 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
968 gen_op_jsr_T0(ctx->pc + 4);
969 ctx->flags |= DELAY_SLOT;
970 ctx->delayed_pc = (uint32_t) - 1;
972 #define LDST(reg,ldnum,ldpnum,ldop,stnum,stpnum,stop,extrald) \
974 gen_op_movl_rN_T0 (REG(B11_8)); \
975 gen_op_##ldop##_T0_##reg (); \
979 gen_op_movl_rN_T0 (REG(B11_8)); \
980 gen_op_ldl_T0_T0 (ctx); \
981 gen_op_inc4_rN (REG(B11_8)); \
982 gen_op_##ldop##_T0_##reg (); \
986 gen_op_##stop##_##reg##_T0 (); \
987 gen_op_movl_T0_rN (REG(B11_8)); \
990 gen_op_##stop##_##reg##_T0 (); \
991 gen_op_dec4_rN (REG(B11_8)); \
992 gen_op_movl_rN_T1 (REG(B11_8)); \
993 gen_op_stl_T0_T1 (ctx); \
995 LDST(sr, 0x400e, 0x4007, ldc, 0x0002, 0x4003, stc, ctx->bstate =
997 LDST(gbr, 0x401e, 0x4017, ldc, 0x0012, 0x4013, stc,)
998 LDST(vbr, 0x402e, 0x4027, ldc, 0x0022, 0x4023, stc,)
999 LDST(ssr, 0x403e, 0x4037, ldc, 0x0032, 0x4033, stc,)
1000 LDST(spc, 0x404e, 0x4047, ldc, 0x0042, 0x4043, stc,)
1001 LDST(dbr, 0x40fa, 0x40f6, ldc, 0x00fa, 0x40f2, stc,)
1002 LDST(mach, 0x400a, 0x4006, lds, 0x000a, 0x4002, sts,)
1003 LDST(macl, 0x401a, 0x4016, lds, 0x001a, 0x4012, sts,)
1004 LDST(pr, 0x402a, 0x4026, lds, 0x002a, 0x4022, sts,)
1005 LDST(fpul, 0x405a, 0x4056, lds, 0x005a, 0x4052, sts,)
1006 LDST(fpscr, 0x406a, 0x4066, lds, 0x006a, 0x4062, sts, ctx->bstate =
1008 case 0x00c3: /* movca.l R0,@Rm */
1009 gen_op_movl_rN_T0(REG(0));
1010 gen_op_movl_rN_T1(REG(B11_8));
1011 gen_op_stl_T0_T1(ctx);
1013 case 0x0029: /* movt Rn */
1014 gen_op_movt_rN(REG(B11_8));
1016 case 0x0093: /* ocbi @Rn */
1017 gen_op_movl_rN_T0(REG(B11_8));
1018 gen_op_ldl_T0_T0(ctx);
1020 case 0x00a2: /* ocbp @Rn */
1021 gen_op_movl_rN_T0(REG(B11_8));
1022 gen_op_ldl_T0_T0(ctx);
1024 case 0x00b3: /* ocbwb @Rn */
1025 gen_op_movl_rN_T0(REG(B11_8));
1026 gen_op_ldl_T0_T0(ctx);
1028 case 0x0083: /* pref @Rn */
1030 case 0x4024: /* rotcl Rn */
1031 gen_op_rotcl_Rn(REG(B11_8));
1033 case 0x4025: /* rotcr Rn */
1034 gen_op_rotcr_Rn(REG(B11_8));
1036 case 0x4004: /* rotl Rn */
1037 gen_op_rotl_Rn(REG(B11_8));
1039 case 0x4005: /* rotr Rn */
1040 gen_op_rotr_Rn(REG(B11_8));
1042 case 0x4000: /* shll Rn */
1043 case 0x4020: /* shal Rn */
1044 gen_op_shal_Rn(REG(B11_8));
1046 case 0x4021: /* shar Rn */
1047 gen_op_shar_Rn(REG(B11_8));
1049 case 0x4001: /* shlr Rn */
1050 gen_op_shlr_Rn(REG(B11_8));
1052 case 0x4008: /* shll2 Rn */
1053 gen_op_shll2_Rn(REG(B11_8));
1055 case 0x4018: /* shll8 Rn */
1056 gen_op_shll8_Rn(REG(B11_8));
1058 case 0x4028: /* shll16 Rn */
1059 gen_op_shll16_Rn(REG(B11_8));
1061 case 0x4009: /* shlr2 Rn */
1062 gen_op_shlr2_Rn(REG(B11_8));
1064 case 0x4019: /* shlr8 Rn */
1065 gen_op_shlr8_Rn(REG(B11_8));
1067 case 0x4029: /* shlr16 Rn */
1068 gen_op_shlr16_Rn(REG(B11_8));
1070 case 0x401b: /* tas.b @Rn */
1071 gen_op_tasb_rN(REG(B11_8));
1073 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1074 gen_op_movl_fpul_FT0();
1075 gen_op_fmov_FT0_frN(FREG(B11_8));
1077 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1078 gen_op_fmov_frN_FT0(FREG(B11_8));
1079 gen_op_movl_FT0_fpul();
1081 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
1082 if (ctx->fpscr & FPSCR_PR) {
1083 if (ctx->opcode & 0x0100)
1084 break; /* illegal instruction */
1086 gen_op_fmov_DT0_drN(DREG(B11_8));
1090 gen_op_fmov_FT0_frN(FREG(B11_8));
1093 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1094 if (ctx->fpscr & FPSCR_PR) {
1095 if (ctx->opcode & 0x0100)
1096 break; /* illegal instruction */
1097 gen_op_fmov_drN_DT0(DREG(B11_8));
1101 gen_op_fmov_frN_FT0(FREG(B11_8));
1105 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
1106 if (!(ctx->fpscr & FPSCR_PR)) {
1107 gen_op_movl_imm_T0(0);
1108 gen_op_fmov_T0_frN(FREG(B11_8));
1112 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
1113 if (!(ctx->fpscr & FPSCR_PR)) {
1114 gen_op_movl_imm_T0(0x3f800000);
1115 gen_op_fmov_T0_frN(FREG(B11_8));
1121 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1122 ctx->opcode, ctx->pc);
1123 gen_op_raise_illegal_instruction();
1124 ctx->bstate = BS_EXCP;
1127 void decode_opc(DisasContext * ctx)
1129 uint32_t old_flags = ctx->flags;
1133 if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
1134 if (ctx->flags & DELAY_SLOT_CLEARME) {
1135 gen_op_store_flags(0);
1138 ctx->bstate = BS_BRANCH;
1139 if (old_flags & DELAY_SLOT_CONDITIONAL) {
1140 gen_delayed_conditional_jump(ctx);
1141 } else if (old_flags & DELAY_SLOT) {
1149 gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
1153 target_ulong pc_start;
1154 static uint16_t *gen_opc_end;
1158 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1160 ctx.flags = (uint32_t)tb->flags;
1161 ctx.bstate = BS_NONE;
1163 ctx.fpscr = env->fpscr;
1164 ctx.memidx = (env->sr & SR_MD) ? 1 : 0;
1165 /* We don't know if the delayed pc came from a dynamic or static branch,
1166 so assume it is a dynamic branch. */
1167 ctx.delayed_pc = -1; /* use delayed pc from env pointer */
1169 ctx.singlestep_enabled = env->singlestep_enabled;
1172 if (loglevel & CPU_LOG_TB_CPU) {
1174 "------------------------------------------------\n");
1175 cpu_dump_state(env, logfile, fprintf, 0);
1180 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1181 if (env->nb_breakpoints > 0) {
1182 for (i = 0; i < env->nb_breakpoints; i++) {
1183 if (ctx.pc == env->breakpoints[i]) {
1184 /* We have hit a breakpoint - make sure PC is up-to-date */
1185 gen_op_movl_imm_PC(ctx.pc);
1187 ctx.bstate = BS_EXCP;
1193 i = gen_opc_ptr - gen_opc_buf;
1197 gen_opc_instr_start[ii++] = 0;
1199 gen_opc_pc[ii] = ctx.pc;
1200 gen_opc_hflags[ii] = ctx.flags;
1201 gen_opc_instr_start[ii] = 1;
1204 fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
1207 ctx.opcode = lduw_code(ctx.pc);
1210 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1212 if (env->singlestep_enabled)
1214 #ifdef SH4_SINGLE_STEP
1218 if (env->singlestep_enabled) {
1221 switch (ctx.bstate) {
1223 /* gen_op_interrupt_restart(); */
1227 gen_op_store_flags(ctx.flags | DELAY_SLOT_CLEARME);
1229 gen_goto_tb(&ctx, 0, ctx.pc);
1232 /* gen_op_interrupt_restart(); */
1241 *gen_opc_ptr = INDEX_op_end;
1243 i = gen_opc_ptr - gen_opc_buf;
1246 gen_opc_instr_start[ii++] = 0;
1248 tb->size = ctx.pc - pc_start;
1252 #ifdef SH4_DEBUG_DISAS
1253 if (loglevel & CPU_LOG_TB_IN_ASM)
1254 fprintf(logfile, "\n");
1256 if (loglevel & CPU_LOG_TB_IN_ASM) {
1257 fprintf(logfile, "IN:\n"); /* , lookup_symbol(pc_start)); */
1258 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1259 fprintf(logfile, "\n");
1265 int gen_intermediate_code(CPUState * env, struct TranslationBlock *tb)
1267 return gen_intermediate_code_internal(env, tb, 0);
1270 int gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
1272 return gen_intermediate_code_internal(env, tb, 1);