//#define DO_SINGLE_STEP
//#define PPC_DEBUG_DISAS
+#ifdef USE_DIRECT_JUMP
+#define TBPARAM(x)
+#else
+#define TBPARAM(x) (long)(x)
+#endif
+
enum {
#define DEF(s, n, copy_size) INDEX_op_ ## s,
#include "opc.h"
#define RET_PRIVREG(ctx) \
RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
-#define RET_MTMSR(ctx) \
-RET_EXCP((ctx), EXCP_MTMSR, 0)
-
+/* Stop translation */
static inline void RET_STOP (DisasContext *ctx)
{
- RET_EXCP(ctx, EXCP_MTMSR, 0);
+ gen_op_update_nip((ctx)->nip);
+ ctx->exception = EXCP_MTMSR;
}
+/* No need to update nip here, as execution flow will change */
static inline void RET_CHG_FLOW (DisasContext *ctx)
{
- gen_op_raise_exception_err(EXCP_MTMSR, 0);
ctx->exception = EXCP_MTMSR;
}
/*** Branch ***/
+static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
+{
+ TranslationBlock *tb;
+ tb = ctx->tb;
+ if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
+ if (n == 0)
+ gen_op_goto_tb0(TBPARAM(tb));
+ else
+ gen_op_goto_tb1(TBPARAM(tb));
+ gen_op_set_T1(dest);
+ gen_op_b_T1();
+ gen_op_set_T0((long)tb + n);
+ gen_op_exit_tb();
+ } else {
+ gen_op_set_T1(dest);
+ gen_op_b_T1();
+ gen_op_set_T0(0);
+ gen_op_exit_tb();
+ }
+}
+
/* b ba bl bla */
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
{
if (LK(ctx->opcode)) {
gen_op_setlr(ctx->nip);
}
- gen_op_b((long)ctx->tb, target);
+ gen_goto_tb(ctx, 0, target);
ctx->exception = EXCP_BRANCH;
}
case 4:
case 6:
if (type == BCOND_IM) {
- gen_op_b((long)ctx->tb, target);
+ gen_goto_tb(ctx, 0, target);
} else {
gen_op_b_T1();
}
}
}
if (type == BCOND_IM) {
- gen_op_btest((long)ctx->tb, target, ctx->nip);
+ int l1 = gen_new_label();
+ gen_op_jz_T0(l1);
+ gen_goto_tb(ctx, 0, target);
+ gen_set_label(l1);
+ gen_goto_tb(ctx, 1, ctx->nip);
} else {
gen_op_btest_T1(ctx->nip);
}
gen_op_store_T0_gpr(rD(ctx->opcode));
} else {
/* Privilege exception */
+ if (loglevel) {
+ fprintf(logfile, "Trying to read priviledged spr %d %03x\n",
+ sprn, sprn);
+ }
printf("Trying to read priviledged spr %d %03x\n", sprn, sprn);
RET_PRIVREG(ctx);
}
} else {
/* Not defined */
+ if (loglevel) {
+ fprintf(logfile, "Trying to read invalid spr %d %03x\n",
+ sprn, sprn);
+ }
printf("Trying to read invalid spr %d %03x\n", sprn, sprn);
RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
}
RET_PRIVREG(ctx);
return;
}
+ gen_op_update_nip((ctx)->nip);
gen_op_load_gpr_T0(rS(ctx->opcode));
gen_op_store_msr();
/* Must stop the translation as machine state (may have) changed */
- RET_MTMSR(ctx);
+ RET_CHG_FLOW(ctx);
#endif
}
(*write_cb)(ctx, sprn);
} else {
/* Privilege exception */
+ if (loglevel) {
+ fprintf(logfile, "Trying to write priviledged spr %d %03x\n",
+ sprn, sprn);
+ }
printf("Trying to write priviledged spr %d %03x\n", sprn, sprn);
RET_PRIVREG(ctx);
}
} else {
/* Not defined */
+ if (loglevel) {
+ fprintf(logfile, "Trying to write invalid spr %d %03x\n",
+ sprn, sprn);
+ }
printf("Trying to write invalid spr %d %03x\n", sprn, sprn);
RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
}
}
gen_op_load_gpr_T0(rS(ctx->opcode));
gen_op_store_sr(SR(ctx->opcode));
+ RET_STOP(ctx);
#endif
}
gen_op_load_gpr_T0(rS(ctx->opcode));
gen_op_load_gpr_T1(rB(ctx->opcode));
gen_op_store_srin();
+ RET_STOP(ctx);
#endif
}
return;
}
gen_op_tlbia();
- RET_MTMSR(ctx);
+ RET_STOP(ctx);
#endif
}
}
gen_op_load_gpr_T0(rB(ctx->opcode));
gen_op_tlbie();
- RET_MTMSR(ctx);
+ RET_STOP(ctx);
#endif
}
/* This has no effect: it should ensure that all previous
* tlbie have completed
*/
- RET_MTMSR(ctx);
+ RET_STOP(ctx);
#endif
}
gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
gen_opparam_ptr = gen_opparam_buf;
+ nb_gen_labels = 0;
ctx.nip = pc_start;
ctx.tb = tb;
ctx.exception = EXCP_NONE;
#endif
}
if (ctx.exception == EXCP_NONE) {
- gen_op_b((unsigned long)ctx.tb, ctx.nip);
+ gen_goto_tb(&ctx, 0, ctx.nip);
} else if (ctx.exception != EXCP_BRANCH) {
gen_op_set_T0(0);
}
}
if (loglevel & CPU_LOG_TB_IN_ASM) {
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
- target_disas(logfile, pc_start, ctx.nip - pc_start, 0);
+ target_disas(logfile, pc_start, ctx.nip - pc_start, msr_le);
fprintf(logfile, "\n");
}
if (loglevel & CPU_LOG_TB_OP) {