void do_store_msr (void)
{
+#if 1 // TRY
if (((T0 >> MSR_IR) & 0x01) != msr_ir ||
- ((T0 >> MSR_DR) & 0x01) != msr_dr) {
- /* Flush all tlb when changing translation mode or privilege level */
+ ((T0 >> MSR_DR) & 0x01) != msr_dr ||
+ ((T0 >> MSR_PR) & 0x01) != msr_pr)
+ {
do_tlbia();
}
+#endif
msr_pow = (T0 >> MSR_POW) & 0x03;
msr_ile = (T0 >> MSR_ILE) & 0x01;
msr_ee = (T0 >> MSR_EE) & 0x01;
xer_ca = 0;
if (T1 & 0x20) {
ret = (-1) * (T0 >> 31);
- if (ret < 0)
+ if (ret < 0 && (T0 & ~0x80000000) != 0)
xer_ca = 1;
+#if 1 // TRY
+ } else if (T1 == 0) {
+ ret = T0;
+#endif
} else {
ret = (int32_t)T0 >> (T1 & 0x1f);
if (ret < 0 && ((int32_t)T0 & ((1 << T1) - 1)) != 0)
xer_ca = 1;
}
- (int32_t)T0 = ret;
+ T0 = ret;
}
/* Floating point operations helpers */
fesetround(cround);
}
+void do_fnmadd (void)
+{
+ FT0 = -((FT0 * FT1) + FT2);
+}
+
+void do_fnmsub (void)
+{
+ FT0 = -((FT0 * FT1) - FT2);
+}
+
void do_fnmadds (void)
{
- FTS0 = -((FTS0 * FTS1) + FTS2);
+ FT0 = -((FTS0 * FTS1) + FTS2);
}
void do_fnmsubs (void)
{
- FTS0 = -((FTS0 * FTS1) - FTS2);
+ FT0 = -((FTS0 * FTS1) - FTS2);
}
void do_fsqrt (void)
void do_fcmpu (void)
{
- env->fpscr[4] &= ~0x1;
if (isnan(FT0) || isnan(FT1)) {
T0 = 0x01;
env->fpscr[4] |= 0x1;
} else {
T0 = 0x02;
}
- env->fpscr[3] |= T0;
+ env->fpscr[3] = T0;
}
void do_fcmpo (void)
} else {
T0 = 0x02;
}
- env->fpscr[3] |= T0;
+ env->fpscr[3] = T0;
}
void do_fabs (void)
/* Instruction cache invalidation helper */
#define ICACHE_LINE_SIZE 32
+void do_check_reservation (void)
+{
+ if ((env->reserve & ~(ICACHE_LINE_SIZE - 1)) == T0)
+ env->reserve = -1;
+}
+
void do_icbi (void)
{
/* Invalidate one cache line */
tlb_flush_page(env, T0);
}
+void do_store_sr (uint32_t srnum)
+{
+#if defined (DEBUG_OP)
+ dump_store_sr(srnum);
+#endif
+#if 0 // TRY
+ {
+ uint32_t base, page;
+
+ base = srnum << 28;
+ for (page = base; page != base + 0x100000000; page += 0x1000)
+ tlb_flush_page(env, page);
+ }
+#else
+ tlb_flush(env, 1);
+#endif
+ env->sr[srnum] = T0;
+}
+
+/* For BATs, we may not invalidate any TLBs if the change is only on
+ * protection bits for user mode.
+ */
+void do_store_ibat (int ul, int nr)
+{
+#if defined (DEBUG_OP)
+ dump_store_ibat(ul, nr);
+#endif
+#if 0 // TRY
+ {
+ uint32_t base, length, page;
+
+ base = env->IBAT[0][nr];
+ length = (((base >> 2) & 0x000007FF) + 1) << 17;
+ base &= 0xFFFC0000;
+ for (page = base; page != base + length; page += 0x1000)
+ tlb_flush_page(env, page);
+ }
+#else
+ tlb_flush(env, 1);
+#endif
+ env->IBAT[ul][nr] = T0;
+}
+
+void do_store_dbat (int ul, int nr)
+{
+#if defined (DEBUG_OP)
+ dump_store_dbat(ul, nr);
+#endif
+#if 0 // TRY
+ {
+ uint32_t base, length, page;
+ base = env->DBAT[0][nr];
+ length = (((base >> 2) & 0x000007FF) + 1) << 17;
+ base &= 0xFFFC0000;
+ for (page = base; page != base + length; page += 0x1000)
+ tlb_flush_page(env, page);
+ }
+#else
+ tlb_flush(env, 1);
+#endif
+ env->DBAT[ul][nr] = T0;
+}
+
/*****************************************************************************/
/* Special helpers for debug */
extern FILE *stdout;
void dump_rfi (void)
{
#if 0
- printf("Return from interrupt %d => 0x%08x\n", pos, env->nip);
+ printf("Return from interrupt => 0x%08x\n", env->nip);
// cpu_ppc_dump_state(env, stdout, 0);
#endif
}
#include "disas.h"
//#define DO_SINGLE_STEP
-//#define DO_STEP_FLUSH
-//#define DEBUG_DISAS
//#define PPC_DEBUG_DISAS
enum {
}
gen_op_load_gpr_T0(rS(ctx->opcode));
if (uimm != 0)
- gen_op_xori(UIMM(ctx->opcode));
+ gen_op_xori(uimm);
gen_op_store_T0_gpr(rA(ctx->opcode));
}
}
gen_op_load_gpr_T0(rS(ctx->opcode));
if (uimm != 0)
- gen_op_xori(UIMM(ctx->opcode) << 16);
+ gen_op_xori(uimm << 16);
gen_op_store_T0_gpr(rA(ctx->opcode));
}
mb = MB(ctx->opcode);
me = ME(ctx->opcode);
gen_op_load_gpr_T0(rS(ctx->opcode));
+#if 1 // TRY
+ if (sh == 0) {
+ gen_op_andi_(MASK(mb, me));
+ goto store;
+ }
+#endif
if (mb == 0) {
if (me == 31) {
gen_op_rotlwi(sh);
goto store;
+#if 0
} else if (me == (31 - sh)) {
gen_op_slwi(sh);
goto store;
- } else if (sh == 0) {
- gen_op_andi_(MASK(0, me));
- goto store;
+#endif
}
} else if (me == 31) {
+#if 0
if (sh == (32 - mb)) {
gen_op_srwi(mb);
goto store;
- } else if (sh == 0) {
- gen_op_andi_(MASK(mb, 31));
- goto store;
}
+#endif
}
gen_op_rlwinm(sh, MASK(mb, me));
store:
/* stswi */
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
{
+ int nb = NB(ctx->opcode);
+
if (rA(ctx->opcode) == 0) {
gen_op_set_T0(0);
} else {
gen_op_load_gpr_T0(rA(ctx->opcode));
}
- gen_op_set_T1(NB(ctx->opcode));
+ if (nb == 0)
+ nb = 32;
+ gen_op_set_T1(nb);
op_ldsts(stsw, rS(ctx->opcode));
}
/* We need to update the time base before reading it */
switch (sprn) {
case V_TBL:
- /* TBL is still in T0 */
gen_op_load_tbl();
break;
case V_TBU:
break;
case IBAT0U:
gen_op_store_ibat(0, 0);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT1U:
gen_op_store_ibat(0, 1);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT2U:
gen_op_store_ibat(0, 2);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT3U:
gen_op_store_ibat(0, 3);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT4U:
gen_op_store_ibat(0, 4);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT5U:
gen_op_store_ibat(0, 5);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT6U:
gen_op_store_ibat(0, 6);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT7U:
gen_op_store_ibat(0, 7);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT0L:
gen_op_store_ibat(1, 0);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT1L:
gen_op_store_ibat(1, 1);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT2L:
gen_op_store_ibat(1, 2);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT3L:
gen_op_store_ibat(1, 3);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT4L:
gen_op_store_ibat(1, 4);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT5L:
gen_op_store_ibat(1, 5);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT6L:
gen_op_store_ibat(1, 6);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case IBAT7L:
gen_op_store_ibat(1, 7);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT0U:
gen_op_store_dbat(0, 0);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT1U:
gen_op_store_dbat(0, 1);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT2U:
gen_op_store_dbat(0, 2);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT3U:
gen_op_store_dbat(0, 3);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT4U:
gen_op_store_dbat(0, 4);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT5U:
gen_op_store_dbat(0, 5);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT6U:
gen_op_store_dbat(0, 6);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT7U:
gen_op_store_dbat(0, 7);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT0L:
gen_op_store_dbat(1, 0);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT1L:
gen_op_store_dbat(1, 1);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT2L:
gen_op_store_dbat(1, 2);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT3L:
gen_op_store_dbat(1, 3);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT4L:
gen_op_store_dbat(1, 4);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT5L:
gen_op_store_dbat(1, 5);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT6L:
gen_op_store_dbat(1, 6);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case DBAT7L:
gen_op_store_dbat(1, 7);
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case SDR1:
gen_op_store_sdr1();
- gen_op_tlbia();
+ RET_MTMSR(ctx);
break;
case O_TBL:
gen_op_store_tbl();
case DECR:
gen_op_store_decr();
break;
+#if 0
+ case HID0:
+ gen_op_store_hid0();
+ break;
+#endif
default:
gen_op_store_spr(sprn);
break;
gen_op_add();
}
op_dcbz();
+ gen_op_check_reservation();
}
/* icbi */
}
gen_op_load_gpr_T0(rS(ctx->opcode));
gen_op_store_sr(SR(ctx->opcode));
-#if 0
- gen_op_tlbia();
- RET_MTMSR(ctx);
-#endif
#endif
}
gen_op_load_gpr_T0(rS(ctx->opcode));
gen_op_load_gpr_T1(rB(ctx->opcode));
gen_op_store_srin();
- gen_op_tlbia();
#endif
}
return;
}
gen_op_tlbia();
+ RET_MTMSR(ctx);
#endif
}
}
gen_op_load_gpr_T0(rB(ctx->opcode));
gen_op_tlbie();
+ RET_MTMSR(ctx);
#endif
}
/* This has no effect: it should ensure that all previous
* tlbie have completed
*/
+ RET_MTMSR(ctx);
#endif
}
spr_set_rights(DBAT3U, SPR_SR | SPR_SW);
/* DBAT3L (SPR 543) */
spr_set_rights(DBAT3L, SPR_SR | SPR_SW);
- /* DABR (SPR 1013) */
- spr_set_rights(DABR, SPR_SR | SPR_SW);
/* FPECR (SPR 1022) */
spr_set_rights(FPECR, SPR_SR | SPR_SW);
- /* PIR (SPR 1023) */
+ /* Special registers for PPC 604 */
+ if ((pvr & 0xFFFF0000) == 0x00040000) {
+ /* IABR */
+ spr_set_rights(IABR , SPR_SR | SPR_SW);
+ /* DABR (SPR 1013) */
+ spr_set_rights(DABR, SPR_SR | SPR_SW);
+ /* HID0 */
+ spr_set_rights(HID0, SPR_SR | SPR_SW);
+ /* PIR */
spr_set_rights(PIR, SPR_SR | SPR_SW);
+ /* PMC1 */
+ spr_set_rights(PMC1, SPR_SR | SPR_SW);
+ /* PMC2 */
+ spr_set_rights(PMC2, SPR_SR | SPR_SW);
+ /* MMCR0 */
+ spr_set_rights(MMCR0, SPR_SR | SPR_SW);
+ /* SIA */
+ spr_set_rights(SIA, SPR_SR | SPR_SW);
+ /* SDA */
+ spr_set_rights(SDA, SPR_SR | SPR_SW);
+ }
/* Special registers for MPC740/745/750/755 (aka G3) & IBM 750 */
if ((pvr & 0xFFFF0000) == 0x00080000 ||
(pvr & 0xFFFF0000) == 0x70000000) {
/* HID0 */
- spr_set_rights(SPR_ENCODE(1008), SPR_SR | SPR_SW);
+ spr_set_rights(HID0, SPR_SR | SPR_SW);
/* HID1 */
- spr_set_rights(SPR_ENCODE(1009), SPR_SR | SPR_SW);
+ spr_set_rights(HID1, SPR_SR | SPR_SW);
/* IABR */
- spr_set_rights(SPR_ENCODE(1010), SPR_SR | SPR_SW);
+ spr_set_rights(IABR, SPR_SR | SPR_SW);
/* ICTC */
- spr_set_rights(SPR_ENCODE(1019), SPR_SR | SPR_SW);
+ spr_set_rights(ICTC, SPR_SR | SPR_SW);
/* L2CR */
- spr_set_rights(SPR_ENCODE(1017), SPR_SR | SPR_SW);
+ spr_set_rights(L2CR, SPR_SR | SPR_SW);
/* MMCR0 */
- spr_set_rights(SPR_ENCODE(952), SPR_SR | SPR_SW);
+ spr_set_rights(MMCR0, SPR_SR | SPR_SW);
/* MMCR1 */
- spr_set_rights(SPR_ENCODE(956), SPR_SR | SPR_SW);
+ spr_set_rights(MMCR1, SPR_SR | SPR_SW);
/* PMC1 */
- spr_set_rights(SPR_ENCODE(953), SPR_SR | SPR_SW);
+ spr_set_rights(PMC1, SPR_SR | SPR_SW);
/* PMC2 */
- spr_set_rights(SPR_ENCODE(954), SPR_SR | SPR_SW);
+ spr_set_rights(PMC2, SPR_SR | SPR_SW);
/* PMC3 */
- spr_set_rights(SPR_ENCODE(957), SPR_SR | SPR_SW);
+ spr_set_rights(PMC3, SPR_SR | SPR_SW);
/* PMC4 */
- spr_set_rights(SPR_ENCODE(958), SPR_SR | SPR_SW);
+ spr_set_rights(PMC4, SPR_SR | SPR_SW);
/* SIA */
- spr_set_rights(SPR_ENCODE(955), SPR_SR | SPR_SW);
+ spr_set_rights(SIA, SPR_SR | SPR_SW);
+ /* SDA */
+ spr_set_rights(SDA, SPR_SR | SPR_SW);
/* THRM1 */
- spr_set_rights(SPR_ENCODE(1020), SPR_SR | SPR_SW);
+ spr_set_rights(THRM1, SPR_SR | SPR_SW);
/* THRM2 */
- spr_set_rights(SPR_ENCODE(1021), SPR_SR | SPR_SW);
+ spr_set_rights(THRM2, SPR_SR | SPR_SW);
/* THRM3 */
- spr_set_rights(SPR_ENCODE(1022), SPR_SR | SPR_SW);
+ spr_set_rights(THRM3, SPR_SR | SPR_SW);
/* UMMCR0 */
- spr_set_rights(SPR_ENCODE(936), SPR_UR | SPR_UW);
+ spr_set_rights(UMMCR0, SPR_UR | SPR_UW);
/* UMMCR1 */
- spr_set_rights(SPR_ENCODE(940), SPR_UR | SPR_UW);
+ spr_set_rights(UMMCR1, SPR_UR | SPR_UW);
/* UPMC1 */
- spr_set_rights(SPR_ENCODE(937), SPR_UR | SPR_UW);
+ spr_set_rights(UPMC1, SPR_UR | SPR_UW);
/* UPMC2 */
- spr_set_rights(SPR_ENCODE(938), SPR_UR | SPR_UW);
+ spr_set_rights(UPMC2, SPR_UR | SPR_UW);
/* UPMC3 */
- spr_set_rights(SPR_ENCODE(941), SPR_UR | SPR_UW);
+ spr_set_rights(UPMC3, SPR_UR | SPR_UW);
/* UPMC4 */
- spr_set_rights(SPR_ENCODE(942), SPR_UR | SPR_UW);
+ spr_set_rights(UPMC4, SPR_UR | SPR_UW);
/* USIA */
- spr_set_rights(SPR_ENCODE(939), SPR_UR | SPR_UW);
+ spr_set_rights(USIA, SPR_UR | SPR_UW);
}
/* MPC755 has special registers */
if (pvr == 0x00083100) {
/* DBAT7L */
spr_set_rights(DBAT7L, SPR_SR | SPR_SW);
/* DMISS */
- spr_set_rights(SPR_ENCODE(976), SPR_SR | SPR_SW);
+ spr_set_rights(DMISS, SPR_SR | SPR_SW);
/* DCMP */
- spr_set_rights(SPR_ENCODE(977), SPR_SR | SPR_SW);
+ spr_set_rights(DCMP, SPR_SR | SPR_SW);
/* DHASH1 */
- spr_set_rights(SPR_ENCODE(978), SPR_SR | SPR_SW);
+ spr_set_rights(DHASH1, SPR_SR | SPR_SW);
/* DHASH2 */
- spr_set_rights(SPR_ENCODE(979), SPR_SR | SPR_SW);
+ spr_set_rights(DHASH2, SPR_SR | SPR_SW);
/* IMISS */
- spr_set_rights(SPR_ENCODE(980), SPR_SR | SPR_SW);
+ spr_set_rights(IMISS, SPR_SR | SPR_SW);
/* ICMP */
- spr_set_rights(SPR_ENCODE(981), SPR_SR | SPR_SW);
+ spr_set_rights(ICMP, SPR_SR | SPR_SW);
/* RPA */
- spr_set_rights(SPR_ENCODE(982), SPR_SR | SPR_SW);
+ spr_set_rights(RPA, SPR_SR | SPR_SW);
/* HID2 */
- spr_set_rights(SPR_ENCODE(1011), SPR_SR | SPR_SW);
+ spr_set_rights(HID2, SPR_SR | SPR_SW);
/* L2PM */
- spr_set_rights(SPR_ENCODE(1016), SPR_SR | SPR_SW);
+ spr_set_rights(L2PM, SPR_SR | SPR_SW);
}
}
cpu_exec_init();
- env = malloc(sizeof(CPUPPCState));
+ env = qemu_mallocz(sizeof(CPUPPCState));
if (!env)
return NULL;
- memset(env, 0, sizeof(CPUPPCState));
#if !defined(CONFIG_USER_ONLY) && defined (USE_OPEN_FIRMWARE)
setup_machine(env, 0);
#else
// env->spr[PVR] = 0x00083100; /* MPC755 (G3 embedded) */
// env->spr[PVR] = 0x00070100; /* IBM 750FX */
#endif
- if (create_ppc_proc(ppc_opcodes, env->spr[PVR]) < 0)
- return NULL;
- init_spr_rights(env->spr[PVR]);
tlb_flush(env, 1);
#if defined (DO_SINGLE_STEP)
/* Single step trace mode */
msr_se = 1;
#endif
+ msr_fp = 1; /* Allow floating point exceptions */
+ msr_me = 1; /* Allow machine check exceptions */
#if defined(CONFIG_USER_ONLY)
msr_pr = 1;
+ cpu_ppc_register(env, 0x00080000);
+#else
+ env->nip = 0xFFFFFFFC;
#endif
env->access_type = ACCESS_INT;
return env;
}
+int cpu_ppc_register (CPUPPCState *env, uint32_t pvr)
+{
+ env->spr[PVR] = pvr;
+ if (create_ppc_proc(ppc_opcodes, env->spr[PVR]) < 0)
+ return -1;
+ init_spr_rights(env->spr[PVR]);
+
+ return 0;
+}
+
void cpu_ppc_close(CPUPPCState *env)
{
/* Should also remove all opcode tables... */
}
}
/* Is opcode *REALLY* valid ? */
- if ((ctx.opcode & handler->inval) != 0) {
- if (loglevel > 0) {
if (handler->handler == &gen_invalid) {
+ if (loglevel > 0) {
fprintf(logfile, "invalid/unsupported opcode: "
- "%02x -%02x - %02x (%08x) 0x%08x\n",
+ "%02x - %02x - %02x (%08x) 0x%08x %d\n",
opc1(ctx.opcode), opc2(ctx.opcode),
- opc3(ctx.opcode), ctx.opcode, ctx.nip - 4);
+ opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
+ } else {
+ printf("invalid/unsupported opcode: "
+ "%02x - %02x - %02x (%08x) 0x%08x %d\n",
+ opc1(ctx.opcode), opc2(ctx.opcode),
+ opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
+ }
} else {
+ if ((ctx.opcode & handler->inval) != 0) {
+ if (loglevel > 0) {
fprintf(logfile, "invalid bits: %08x for opcode: "
"%02x -%02x - %02x (0x%08x) (0x%08x)\n",
ctx.opcode & handler->inval, opc1(ctx.opcode),
opc2(ctx.opcode), opc3(ctx.opcode),
ctx.opcode, ctx.nip - 4);
- }
- } else {
- if (handler->handler == &gen_invalid) {
- printf("invalid/unsupported opcode: "
- "%02x -%02x - %02x (%08x) 0x%08x\n",
- opc1(ctx.opcode), opc2(ctx.opcode),
- opc3(ctx.opcode), ctx.opcode, ctx.nip - 4);
} else {
printf("invalid bits: %08x for opcode: "
"%02x -%02x - %02x (0x%08x) (0x%08x)\n",
opc2(ctx.opcode), opc3(ctx.opcode),
ctx.opcode, ctx.nip - 4);
}
+ RET_INVAL(ctxp);
+ break;
}
- (*gen_invalid)(&ctx);
- } else {
- (*(handler->handler))(&ctx);
}
+ (*(handler->handler))(&ctx);
/* Check trace mode exceptions */
if ((msr_be && ctx.exception == EXCP_BRANCH) ||
/* Check in single step trace mode
} else {
tb->size = ctx.nip - pc_start;
}
- env->access_type = ACCESS_INT;
#ifdef DEBUG_DISAS
if (loglevel & CPU_LOG_TB_CPU) {
fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
fprintf(logfile, "\n");
}
#endif
+ env->access_type = ACCESS_INT;
return 0;
}