mirror of
https://github.com/xemu-project/xemu.git
synced 2025-02-16 01:59:58 +00:00
PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@861 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
85c4adf65f
commit
4b3686faee
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user