diff options
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/exec.h | 6 | ||||
-rw-r--r-- | target-ppc/helper.c | 27 | ||||
-rw-r--r-- | target-ppc/op.c | 34 | ||||
-rw-r--r-- | target-ppc/op_helper.c | 105 | ||||
-rw-r--r-- | target-ppc/op_template.h | 5 | ||||
-rw-r--r-- | target-ppc/translate.c | 247 |
6 files changed, 274 insertions, 150 deletions
diff --git a/target-ppc/exec.h b/target-ppc/exec.h index edb73ef056..6377907683 100644 --- a/target-ppc/exec.h +++ b/target-ppc/exec.h @@ -135,6 +135,8 @@ void do_sraw(void); void do_fctiw (void); void do_fctiwz (void); +void do_fnmadd (void); +void do_fnmsub (void); void do_fnmadds (void); void do_fnmsubs (void); void do_fsqrt (void); @@ -147,7 +149,11 @@ void do_fcmpo (void); void do_fabs (void); void do_fnabs (void); +void do_check_reservation (void); void do_icbi (void); +void do_store_sr (uint32_t srnum); +void do_store_ibat (int ul, int nr); +void do_store_dbat (int ul, int nr); void do_tlbia (void); void do_tlbie (void); diff --git a/target-ppc/helper.c b/target-ppc/helper.c index e8b776b075..ef3e22d66d 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -28,9 +28,6 @@ //#define DEBUG_EXCEPTIONS extern FILE *stdout, *stderr; -void abort (void); - -/*****************************************************************************/ /*****************************************************************************/ /* PPC MMU emulation */ @@ -365,7 +362,8 @@ int get_physical_address (CPUState *env, uint32_t *physical, int *prot, fprintf(logfile, "%s\n", __func__); } - if ((access_type == ACCESS_CODE && msr_ir == 0) || msr_dr == 0) { + if ((access_type == ACCESS_CODE && msr_ir == 0) || + (access_type != ACCESS_CODE && msr_dr == 0)) { /* No address translation */ *physical = address & ~0xFFF; *prot = PAGE_READ | PAGE_WRITE; @@ -441,12 +439,15 @@ void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr) index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); tlb_addrr = env->tlb_read[is_user][index].address; tlb_addrw = env->tlb_write[is_user][index].address; -#if 0 - printf("%s 1 %p %p idx=%d addr=0x%08lx tbl_addr=0x%08lx 0x%08lx " +#if 1 + if (loglevel) { + fprintf(logfile, + "%s 1 %p %p idx=%d addr=0x%08lx tbl_addr=0x%08lx 0x%08lx " "(0x%08lx 0x%08lx)\n", __func__, env, &env->tlb_read[is_user][index], index, addr, tlb_addrr, tlb_addrw, addr & TARGET_PAGE_MASK, tlb_addrr & (TARGET_PAGE_MASK | TLB_INVALID_MASK)); + } #endif } ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, is_user, 1); @@ -631,11 +632,14 @@ uint32_t _load_msr (CPUState *env) void _store_msr (CPUState *env, uint32_t value) { +#if 0 // TRY if (((value >> MSR_IR) & 0x01) != msr_ir || - ((value >> MSR_DR) & 0x01) != msr_dr) { + ((value >> MSR_DR) & 0x01) != msr_dr) + { /* Flush all tlb when changing translation mode or privilege level */ tlb_flush(env, 1); } +#endif msr_pow = (value >> MSR_POW) & 0x03; msr_ile = (value >> MSR_ILE) & 0x01; msr_ee = (value >> MSR_EE) & 0x01; @@ -699,13 +703,8 @@ void do_interrupt (CPUState *env) goto store_next; case EXCP_MACHINE_CHECK: if (msr_me == 0) { - printf("Machine check exception while not allowed !\n"); - if (loglevel) { - fprintf(logfile, - "Machine check exception while not allowed !\n"); + cpu_abort(env, "Machine check exception while not allowed\n"); } - abort(); - } msr_me = 0; break; case EXCP_DSI: @@ -801,7 +800,7 @@ void do_interrupt (CPUState *env) env->fpscr[7] |= 0x4; break; case EXCP_INVAL: - printf("Invalid instruction at 0x%08x\n", env->nip); + // printf("Invalid instruction at 0x%08x\n", env->nip); msr |= 0x00080000; break; case EXCP_PRIV: diff --git a/target-ppc/op.c b/target-ppc/op.c index 38eae7f74a..f439a81dfb 100644 --- a/target-ppc/op.c +++ b/target-ppc/op.c @@ -242,10 +242,7 @@ PPC_OP(load_srin) PPC_OP(store_srin) { -#if defined (DEBUG_OP) - dump_store_sr(T1 >> 28); -#endif - regs->sr[T1 >> 28] = T0; + do_store_sr(T1 >> 28); RETURN(); } @@ -402,10 +399,7 @@ PPC_OP(load_ibat) PPC_OP(store_ibat) { -#if defined (DEBUG_OP) - dump_store_ibat(PARAM(1), PARAM(2)); -#endif - regs->IBAT[PARAM(1)][PARAM(2)] = T0; + do_store_ibat(PARAM(1), PARAM(2)); } PPC_OP(load_dbat) @@ -415,10 +409,7 @@ PPC_OP(load_dbat) PPC_OP(store_dbat) { -#if defined (DEBUG_OP) - dump_store_dbat(PARAM(1), PARAM(2)); -#endif - regs->DBAT[PARAM(1)][PARAM(2)] = T0; + do_store_dbat(PARAM(1), PARAM(2)); } /* FPSCR */ @@ -1344,9 +1335,7 @@ PPC_OP(fmsubs) /* fnmadd - fnmadd. - fnmadds - fnmadds. */ PPC_OP(fnmadd) { - FT0 *= FT1; - FT0 += FT2; - FT0 = -FT0; + do_fnmadd(); RETURN(); } @@ -1360,9 +1349,7 @@ PPC_OP(fnmadds) /* fnmsub - fnmsub. */ PPC_OP(fnmsub) { - FT0 *= FT1; - FT0 -= FT2; - FT0 = -FT0; + do_fnmsub(); RETURN(); } @@ -1444,11 +1431,22 @@ PPC_OP(fneg) #include "op_mem.h" #endif +/* Special op to check and maybe clear reservation */ +PPC_OP(check_reservation) +{ + do_check_reservation(); + RETURN(); +} + /* Return from interrupt */ PPC_OP(rfi) { regs->nip = regs->spr[SRR0] & ~0x00000003; +#if 1 // TRY + T0 = regs->spr[SRR1] & ~0xFFF00000; +#else T0 = regs->spr[SRR1] & ~0xFFFF0000; +#endif do_store_msr(); #if defined (DEBUG_OP) dump_rfi(); diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 3ddda1e335..d761a8d2b1 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -127,11 +127,14 @@ void do_load_msr (void) 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; @@ -157,14 +160,18 @@ void do_sraw (void) 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 */ @@ -267,14 +274,24 @@ void do_fctiwz (void) 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) @@ -307,7 +324,6 @@ void do_fsel (void) void do_fcmpu (void) { - env->fpscr[4] &= ~0x1; if (isnan(FT0) || isnan(FT1)) { T0 = 0x01; env->fpscr[4] |= 0x1; @@ -319,7 +335,7 @@ void do_fcmpu (void) } else { T0 = 0x02; } - env->fpscr[3] |= T0; + env->fpscr[3] = T0; } void do_fcmpo (void) @@ -343,7 +359,7 @@ void do_fcmpo (void) } else { T0 = 0x02; } - env->fpscr[3] |= T0; + env->fpscr[3] = T0; } void do_fabs (void) @@ -359,6 +375,12 @@ void do_fnabs (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 */ @@ -377,6 +399,69 @@ void do_tlbie (void) 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; @@ -389,7 +474,7 @@ void dump_state (void) 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 } diff --git a/target-ppc/op_template.h b/target-ppc/op_template.h index 5ba4dfcbea..338b7aa239 100644 --- a/target-ppc/op_template.h +++ b/target-ppc/op_template.h @@ -175,10 +175,7 @@ void OPPROTO glue(op_load_sr, REG)(void) void OPPROTO glue(op_store_sr, REG)(void) { -#if defined (DEBUG_OP) - dump_store_sr(REG); -#endif - env->sr[REG] = T0; + do_store_sr(REG); RETURN(); } #endif diff --git a/target-ppc/translate.c b/target-ppc/translate.c index c6e45416b7..1489c462f5 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -28,8 +28,6 @@ #include "disas.h" //#define DO_SINGLE_STEP -//#define DO_STEP_FLUSH -//#define DEBUG_DISAS //#define PPC_DEBUG_DISAS enum { @@ -639,7 +637,7 @@ GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) } 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)); } @@ -654,7 +652,7 @@ GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) } 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)); } @@ -682,25 +680,29 @@ GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 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: @@ -1268,12 +1270,16 @@ GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER) /* 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)); } @@ -1931,7 +1937,6 @@ GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC) /* 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: @@ -2007,135 +2012,135 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) 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(); @@ -2146,6 +2151,11 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) case DECR: gen_op_store_decr(); break; +#if 0 + case HID0: + gen_op_store_hid0(); + break; +#endif default: gen_op_store_spr(sprn); break; @@ -2236,6 +2246,7 @@ GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE) gen_op_add(); } op_dcbz(); + gen_op_check_reservation(); } /* icbi */ @@ -2302,10 +2313,6 @@ GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT) } 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 } @@ -2322,7 +2329,6 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) gen_op_load_gpr_T0(rS(ctx->opcode)); gen_op_load_gpr_T1(rB(ctx->opcode)); gen_op_store_srin(); - gen_op_tlbia(); #endif } @@ -2341,6 +2347,7 @@ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT) return; } gen_op_tlbia(); + RET_MTMSR(ctx); #endif } @@ -2356,6 +2363,7 @@ GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM) } gen_op_load_gpr_T0(rB(ctx->opcode)); gen_op_tlbie(); + RET_MTMSR(ctx); #endif } @@ -2372,6 +2380,7 @@ GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM) /* This has no effect: it should ensure that all previous * tlbie have completed */ + RET_MTMSR(ctx); #endif } @@ -2692,59 +2701,78 @@ static void init_spr_rights (uint32_t pvr) 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) { @@ -2789,23 +2817,23 @@ static void init_spr_rights (uint32_t pvr) /* 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); } } @@ -2941,10 +2969,9 @@ CPUPPCState *cpu_ppc_init(void) 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 @@ -2953,22 +2980,34 @@ CPUPPCState *cpu_ppc_init(void) // 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... */ @@ -3047,26 +3086,26 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, } } /* 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", @@ -3074,11 +3113,11 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, 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 @@ -3126,7 +3165,6 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, } 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); @@ -3143,6 +3181,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, fprintf(logfile, "\n"); } #endif + env->access_type = ACCESS_INT; return 0; } |