- fix OP_MCR (fix a delay boot M&L:PiT and SPP on x64 PGO build);
This commit is contained in:
mtabachenko 2013-08-09 23:08:13 +00:00
parent 8184770cd5
commit 243cadb4cd
3 changed files with 44 additions and 218 deletions

View File

@ -2513,7 +2513,9 @@ void NDS_Reset()
// only ARM9 have co-processor
reconstruct(&cp15);
cp15.reset(&NDS_ARM9);
MMU.ARM9_RW_MODE = BIT7(cp15.ctrl);
NDS_ARM9.intVector = 0xFFFF0000 * (BIT13(cp15.ctrl));
NDS_ARM9.LDTBit = !BIT15(cp15.ctrl); //TBit
resetUserInput();

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2011 DeSmuME team
Copyright (C) 2006-2013 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -24,67 +24,11 @@
armcp15_t cp15;
bool armcp15_t::reset(armcpu_t * c)
{
//printf("CP15 Reset\n");
cpu = c;
IDCode = 0x41059461;
cacheType = 0x0F0D2112;
TCMSize = 0x00140180;
ctrl = 0x00012078;
DCConfig = 0x0;
ICConfig = 0x0;
writeBuffCtrl = 0x0;
und = 0x0;
DaccessPerm = 0x22222222;
IaccessPerm = 0x22222222;
protectBaseSize0 = 0x0;
protectBaseSize1 = 0x0;
protectBaseSize2 = 0x0;
protectBaseSize3 = 0x0;
protectBaseSize4 = 0x0;
protectBaseSize5 = 0x0;
protectBaseSize6 = 0x0;
protectBaseSize7 = 0x0;
cacheOp = 0x0;
DcacheLock = 0x0;
IcacheLock = 0x0;
ITCMRegion = 0x0C;
DTCMRegion = 0x0080000A;
processID = 0;
MMU.ARM9_RW_MODE = BIT7(ctrl);
cpu->intVector = 0xFFFF0000 * (BIT13(ctrl));
cpu->LDTBit = !BIT15(ctrl); //TBit
/* preset calculated regionmasks */
for (u8 i=0;i<8;i++) {
regionWriteMask_USR[i] = 0 ;
regionWriteMask_SYS[i] = 0 ;
regionReadMask_USR[i] = 0 ;
regionReadMask_SYS[i] = 0 ;
regionExecuteMask_USR[i] = 0 ;
regionExecuteMask_SYS[i] = 0 ;
regionWriteSet_USR[i] = 0 ;
regionWriteSet_SYS[i] = 0 ;
regionReadSet_USR[i] = 0 ;
regionReadSet_SYS[i] = 0 ;
regionExecuteSet_USR[i] = 0 ;
regionExecuteSet_SYS[i] = 0 ;
} ;
return true;
}
#define ACCESSTYPE(val,n) (((val) >> (4*n)) & 0x0F)
#define SIZEIDENTIFIER(val) ((((val) >> 1) & 0x1F))
#define SIZEBINARY(val) (1 << (SIZEIDENTIFIER(val)+1))
#define MASKFROMREG(val) (~((SIZEBINARY(val)-1) | 0x3F))
#define SETFROMREG(val) ((val) & MASKFROMREG(val))
#define CP15_ACCESSTYPE(val, n) (((val) >> (4*n)) & 0x0F)
/* sets the precalculated regions to mask,set for the affected accesstypes */
void armcp15_t::setSingleRegionAccess(u32 dAccess,u32 iAccess,unsigned char num, u32 mask,u32 set) {
void armcp15_t::setSingleRegionAccess(u8 num, u32 mask, u32 set) {
switch (ACCESSTYPE(dAccess,num)) {
switch (CP15_ACCESSTYPE(DaccessPerm, num)) {
case 4: /* UNP */
case 7: /* UNP */
case 8: /* UNP */
@ -156,7 +100,7 @@ void armcp15_t::setSingleRegionAccess(u32 dAccess,u32 iAccess,unsigned char num,
regionReadSet_SYS[num] = set ;
break ;
}
switch (ACCESSTYPE(iAccess,num)) {
switch (CP15_ACCESSTYPE(IaccessPerm, num)) {
case 4: /* UNP */
case 7: /* UNP */
case 8: /* UNP */
@ -195,16 +139,16 @@ void armcp15_t::maskPrecalc()
{
#define precalc(num) { \
u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */ \
if (BIT_N(protectBaseSize##num,0)) /* if region is enabled */ \
if (BIT_N(protectBaseSize[num],0)) /* if region is enabled */ \
{ /* reason for this define: naming includes var */ \
mask = MASKFROMREG(protectBaseSize##num) ; \
set = SETFROMREG(protectBaseSize##num) ; \
if (SIZEIDENTIFIER(protectBaseSize##num)==0x1F) \
mask = CP15_MASKFROMREG(protectBaseSize[num]) ; \
set = CP15_SETFROMREG(protectBaseSize[num]) ; \
if (CP15_SIZEIDENTIFIER(protectBaseSize[num])==0x1F) \
{ /* for the 4GB region, u32 suffers wraparound */ \
mask = 0 ; set = 0 ; /* (x & 0) == 0 is allways true (enabled) */ \
} \
} \
setSingleRegionAccess(DaccessPerm,IaccessPerm,num,mask,set) ; \
setSingleRegionAccess(num, mask, set) ; \
}
precalc(0) ;
precalc(1) ;
@ -267,12 +211,7 @@ BOOL armcp15_t::store(u8 CRd, u8 adr)
BOOL armcp15_t::moveCP2ARM(u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
{
if (!cpu)
{
printf("ERROR: cp15 don\'t allocated\n");
return FALSE;
}
if(cpu->CPSR.bits.mode == USR) return FALSE;
if(NDS_ARM9.CPSR.bits.mode == USR) return FALSE;
switch(CRn)
{
@ -345,34 +284,10 @@ BOOL armcp15_t::moveCP2ARM(u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
case 6:
if((opcode1==0) && (opcode2==0))
{
switch(CRm)
if (CRm < 8)
{
case 0:
*R = protectBaseSize0;
*R = protectBaseSize[CRm];
return TRUE;
case 1:
*R = protectBaseSize1;
return TRUE;
case 2:
*R = protectBaseSize2;
return TRUE;
case 3:
*R = protectBaseSize3;
return TRUE;
case 4:
*R = protectBaseSize4;
return TRUE;
case 5:
*R = protectBaseSize5;
return TRUE;
case 6:
*R = protectBaseSize6;
return TRUE;
case 7:
*R = protectBaseSize7;
return TRUE;
default:
return FALSE;
}
}
return FALSE;
@ -416,12 +331,7 @@ BOOL armcp15_t::moveCP2ARM(u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
BOOL armcp15_t::moveARM2CP(u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
{
if (!cpu)
{
printf("ERROR: cp15 don\'t allocated\n");
return FALSE;
}
if(cpu->CPSR.bits.mode == USR) return FALSE;
if(NDS_ARM9.CPSR.bits.mode == USR) return FALSE;
switch(CRn)
{
@ -433,8 +343,8 @@ BOOL armcp15_t::moveARM2CP(u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
ctrl = (val & 0x000FF085) | 0x00000078;
MMU.ARM9_RW_MODE = BIT7(val);
//zero 31-jan-2010: change from 0x0FFF0000 to 0xFFFF0000 per gbatek
cpu->intVector = 0xFFFF0000 * (BIT13(val));
cpu->LDTBit = !BIT15(val); //TBit
NDS_ARM9.intVector = 0xFFFF0000 * (BIT13(val));
NDS_ARM9.LDTBit = !BIT15(val); //TBit
//LOG("CP15: ARMtoCP ctrl %08X (val %08X)\n", ctrl, val);
return TRUE;
}
@ -484,42 +394,11 @@ BOOL armcp15_t::moveARM2CP(u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
case 6:
if((opcode1==0) && (opcode2==0))
{
switch(CRm)
if (CRm < 8)
{
case 0:
protectBaseSize0 = val;
protectBaseSize[CRm] = val;
maskPrecalc();
return TRUE;
case 1:
protectBaseSize1 = val;
maskPrecalc();
return TRUE;
case 2:
protectBaseSize2 = val;
maskPrecalc();
return TRUE;
case 3:
protectBaseSize3 = val;
maskPrecalc();
return TRUE;
case 4:
protectBaseSize4 = val;
maskPrecalc();
return TRUE;
case 5:
protectBaseSize5 = val;
maskPrecalc();
return TRUE;
case 6:
protectBaseSize6 = val;
maskPrecalc();
return TRUE;
case 7:
protectBaseSize7 = val;
maskPrecalc();
return TRUE;
default:
return FALSE;
}
}
return FALSE;
@ -527,8 +406,8 @@ BOOL armcp15_t::moveARM2CP(u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
if((CRm==0)&&(opcode1==0)&&((opcode2==4)))
{
//CP15wait4IRQ;
cpu->waitIRQ = TRUE;
cpu->halt_IE_and_IF = TRUE;
NDS_ARM9.waitIRQ = TRUE;
NDS_ARM9.halt_IE_and_IF = TRUE;
//IME set deliberately omitted: only SWI sets IME to 1
return TRUE;
}
@ -585,14 +464,7 @@ void armcp15_t::saveone(EMUFILE* os)
write32le(und,os);
write32le(DaccessPerm,os);
write32le(IaccessPerm,os);
write32le(protectBaseSize0,os);
write32le(protectBaseSize1,os);
write32le(protectBaseSize2,os);
write32le(protectBaseSize3,os);
write32le(protectBaseSize4,os);
write32le(protectBaseSize5,os);
write32le(protectBaseSize6,os);
write32le(protectBaseSize7,os);
for(int i=0;i<8;i++) write32le(protectBaseSize[i],os);
write32le(cacheOp,os);
write32le(DcacheLock,os);
write32le(IcacheLock,os);
@ -628,14 +500,7 @@ bool armcp15_t::loadone(EMUFILE* is)
if(!read32le(&und,is)) return false;
if(!read32le(&DaccessPerm,is)) return false;
if(!read32le(&IaccessPerm,is)) return false;
if(!read32le(&protectBaseSize0,is)) return false;
if(!read32le(&protectBaseSize1,is)) return false;
if(!read32le(&protectBaseSize2,is)) return false;
if(!read32le(&protectBaseSize3,is)) return false;
if(!read32le(&protectBaseSize4,is)) return false;
if(!read32le(&protectBaseSize5,is)) return false;
if(!read32le(&protectBaseSize6,is)) return false;
if(!read32le(&protectBaseSize7,is)) return false;
for(int i=0;i<8;i++) if(!read32le(&protectBaseSize[i],is)) return false;
if(!read32le(&cacheOp,is)) return false;
if(!read32le(&DcacheLock,is)) return false;
if(!read32le(&IcacheLock,is)) return false;
@ -660,31 +525,3 @@ bool armcp15_t::loadone(EMUFILE* is)
return true;
}
/* precalculate region masks/sets from cp15 register ----- JIT */
void maskPrecalc()
{
#define precalc(num) { \
u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */ \
if (BIT_N(cp15.protectBaseSize##num,0)) /* if region is enabled */ \
{ /* reason for this define: naming includes var */ \
mask = MASKFROMREG(cp15.protectBaseSize##num) ; \
set = SETFROMREG(cp15.protectBaseSize##num) ; \
if (SIZEIDENTIFIER(cp15.protectBaseSize##num)==0x1F) \
{ /* for the 4GB region, u32 suffers wraparound */ \
mask = 0 ; set = 0 ; /* (x & 0) == 0 is allways true (enabled) */ \
} \
} \
cp15.setSingleRegionAccess(cp15.DaccessPerm,cp15.IaccessPerm,num,mask,set) ; \
}
precalc(0) ;
precalc(1) ;
precalc(2) ;
precalc(3) ;
precalc(4) ;
precalc(5) ;
precalc(6) ;
precalc(7) ;
#undef precalc
}

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2010 DeSmuME team
Copyright (C) 2006-2013 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -32,6 +32,11 @@
#define CP15_ACCESS_EXECUSR CP15_ACCESS_EXECUTE
#define CP15_ACCESS_EXECSYS 5
#define CP15_SIZEBINARY(val) (1 << (CP15_SIZEIDENTIFIER(val)+1))
#define CP15_SIZEIDENTIFIER(val) ((((val) >> 1) & 0x1F))
#define CP15_MASKFROMREG(val) (~((CP15_SIZEBINARY(val)-1) | 0x3F))
#define CP15_SETFROMREG(val) ((val) & CP15_MASKFROMREG(val))
struct armcp15_t
{
public:
@ -45,14 +50,7 @@ public:
u32 und;
u32 DaccessPerm;
u32 IaccessPerm;
u32 protectBaseSize0;
u32 protectBaseSize1;
u32 protectBaseSize2;
u32 protectBaseSize3;
u32 protectBaseSize4;
u32 protectBaseSize5;
u32 protectBaseSize6;
u32 protectBaseSize7;
u32 protectBaseSize[8];
u32 cacheOp;
u32 DcacheLock;
u32 IcacheLock;
@ -77,41 +75,32 @@ public:
u32 regionExecuteSet_USR[8] ;
u32 regionExecuteSet_SYS[8] ;
armcpu_t *cpu;
void setSingleRegionAccess(u32 dAccess,u32 iAccess,unsigned char num, u32 mask,u32 set);
void setSingleRegionAccess(u8 num, u32 mask, u32 set);
void maskPrecalc();
public:
armcp15_t() : IDCode(0),
cacheType(0),
TCMSize(0),
ctrl(0),
armcp15_t() : IDCode(0x41059461),
cacheType(0x0F0D2112),
TCMSize(0x00140180),
ctrl(0x00012078),
DCConfig(0),
ICConfig(0),
writeBuffCtrl(0),
und(0),
DaccessPerm(0),
IaccessPerm(0),
protectBaseSize0(0),
protectBaseSize1(0),
protectBaseSize2(0),
protectBaseSize3(0),
protectBaseSize4(0),
protectBaseSize5(0),
protectBaseSize6(0),
protectBaseSize7(0),
DaccessPerm(0x22222222),
IaccessPerm(0x22222222),
cacheOp(0),
DcacheLock(0),
IcacheLock(0),
ITCMRegion(0),
DTCMRegion(0),
ITCMRegion(0x0C),
DTCMRegion(0x0080000A),
processID(0),
RAM_TAG(0),
testState(0),
cacheDbg(0),
cpu(NULL)
cacheDbg(0)
{
//printf("CP15 Reset\n");
memset(&protectBaseSize[0], 0, sizeof(protectBaseSize));
memset(&regionWriteMask_USR[0], 0, sizeof(regionWriteMask_USR));
memset(&regionWriteMask_SYS[0], 0, sizeof(regionWriteMask_SYS));
memset(&regionReadMask_USR[0], 0, sizeof(regionReadMask_USR));
@ -125,7 +114,6 @@ public:
memset(&regionExecuteSet_USR[0], 0, sizeof(regionExecuteSet_USR));
memset(&regionExecuteSet_SYS[0], 0, sizeof(regionExecuteSet_SYS));
}
bool reset(armcpu_t * c);
BOOL dataProcess(u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
BOOL load(u8 CRd, u8 adr);
BOOL store(u8 CRd, u8 adr);
@ -138,5 +126,4 @@ public:
};
extern armcp15_t cp15;
void maskPrecalc();
#endif /* __CP15_H__*/