2009-01-10 03:41:39 +01:00
|
|
|
#ifndef GBACPU_H
|
|
|
|
#define GBACPU_H
|
2008-09-23 01:00:10 +02:00
|
|
|
|
|
|
|
extern int armExecute();
|
|
|
|
extern int thumbExecute();
|
|
|
|
|
|
|
|
#ifdef __GNUC__
|
2009-03-04 07:53:25 +01:00
|
|
|
# define INSN_REGPARM /*nothing*/
|
|
|
|
//# define INSN_REGPARM __attribute__((regparm(1)))
|
2008-09-23 01:00:10 +02:00
|
|
|
# define LIKELY(x) __builtin_expect(!!(x),1)
|
|
|
|
# define UNLIKELY(x) __builtin_expect(!!(x),0)
|
|
|
|
#else
|
|
|
|
# define INSN_REGPARM /*nothing*/
|
|
|
|
# define LIKELY(x) (x)
|
|
|
|
# define UNLIKELY(x) (x)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define UPDATE_REG(address, value)\
|
|
|
|
{\
|
|
|
|
WRITE16LE(((u16 *)&ioMem[address]),value);\
|
|
|
|
}\
|
|
|
|
|
|
|
|
#define ARM_PREFETCH \
|
|
|
|
{\
|
|
|
|
cpuPrefetch[0] = CPUReadMemoryQuick(armNextPC);\
|
|
|
|
cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC+4);\
|
|
|
|
}
|
|
|
|
|
|
|
|
#define THUMB_PREFETCH \
|
|
|
|
{\
|
|
|
|
cpuPrefetch[0] = CPUReadHalfWordQuick(armNextPC);\
|
|
|
|
cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC+2);\
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ARM_PREFETCH_NEXT \
|
|
|
|
cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC+4);
|
|
|
|
|
|
|
|
#define THUMB_PREFETCH_NEXT\
|
|
|
|
cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC+2);
|
|
|
|
|
|
|
|
|
|
|
|
extern int SWITicks;
|
|
|
|
extern u32 mastercode;
|
|
|
|
extern bool busPrefetch;
|
|
|
|
extern bool busPrefetchEnable;
|
|
|
|
extern u32 busPrefetchCount;
|
|
|
|
extern int cpuNextEvent;
|
|
|
|
extern bool holdState;
|
|
|
|
extern u32 cpuPrefetch[2];
|
|
|
|
extern int cpuTotalTicks;
|
|
|
|
extern u8 memoryWait[16];
|
|
|
|
extern u8 memoryWait32[16];
|
|
|
|
extern u8 memoryWaitSeq[16];
|
|
|
|
extern u8 memoryWaitSeq32[16];
|
|
|
|
extern u8 cpuBitsSet[256];
|
|
|
|
extern u8 cpuLowestBitSet[256];
|
|
|
|
extern void CPUSwitchMode(int mode, bool saveState, bool breakLoop);
|
|
|
|
extern void CPUSwitchMode(int mode, bool saveState);
|
|
|
|
extern void CPUUpdateCPSR();
|
|
|
|
extern void CPUUpdateFlags(bool breakLoop);
|
|
|
|
extern void CPUUpdateFlags();
|
|
|
|
extern void CPUUndefinedException();
|
|
|
|
extern void CPUSoftwareInterrupt();
|
|
|
|
extern void CPUSoftwareInterrupt(int comment);
|
|
|
|
|
|
|
|
|
|
|
|
// Waitstates when accessing data
|
|
|
|
inline int dataTicksAccess16(u32 address) // DATA 8/16bits NON SEQ
|
|
|
|
{
|
|
|
|
int addr = (address>>24)&15;
|
|
|
|
int value = memoryWait[addr];
|
|
|
|
|
|
|
|
if ((addr>=0x08) || (addr < 0x02))
|
|
|
|
{
|
|
|
|
busPrefetchCount=0;
|
|
|
|
busPrefetch=false;
|
|
|
|
}
|
|
|
|
else if (busPrefetch)
|
|
|
|
{
|
|
|
|
int waitState = value;
|
|
|
|
if (!waitState)
|
|
|
|
waitState = 1;
|
|
|
|
busPrefetchCount = ((busPrefetchCount+1)<<waitState) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int dataTicksAccess32(u32 address) // DATA 32bits NON SEQ
|
|
|
|
{
|
|
|
|
int addr = (address>>24)&15;
|
|
|
|
int value = memoryWait32[addr];
|
|
|
|
|
|
|
|
if ((addr>=0x08) || (addr < 0x02))
|
|
|
|
{
|
|
|
|
busPrefetchCount=0;
|
|
|
|
busPrefetch=false;
|
|
|
|
}
|
|
|
|
else if (busPrefetch)
|
|
|
|
{
|
|
|
|
int waitState = value;
|
|
|
|
if (!waitState)
|
|
|
|
waitState = 1;
|
|
|
|
busPrefetchCount = ((busPrefetchCount+1)<<waitState) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int dataTicksAccessSeq16(u32 address)// DATA 8/16bits SEQ
|
|
|
|
{
|
|
|
|
int addr = (address>>24)&15;
|
|
|
|
int value = memoryWaitSeq[addr];
|
|
|
|
|
|
|
|
if ((addr>=0x08) || (addr < 0x02))
|
|
|
|
{
|
|
|
|
busPrefetchCount=0;
|
|
|
|
busPrefetch=false;
|
|
|
|
}
|
|
|
|
else if (busPrefetch)
|
|
|
|
{
|
|
|
|
int waitState = value;
|
|
|
|
if (!waitState)
|
|
|
|
waitState = 1;
|
|
|
|
busPrefetchCount = ((busPrefetchCount+1)<<waitState) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int dataTicksAccessSeq32(u32 address)// DATA 32bits SEQ
|
|
|
|
{
|
|
|
|
int addr = (address>>24)&15;
|
|
|
|
int value = memoryWaitSeq32[addr];
|
|
|
|
|
|
|
|
if ((addr>=0x08) || (addr < 0x02))
|
|
|
|
{
|
|
|
|
busPrefetchCount=0;
|
|
|
|
busPrefetch=false;
|
|
|
|
}
|
|
|
|
else if (busPrefetch)
|
|
|
|
{
|
|
|
|
int waitState = value;
|
|
|
|
if (!waitState)
|
|
|
|
waitState = 1;
|
|
|
|
busPrefetchCount = ((busPrefetchCount+1)<<waitState) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Waitstates when executing opcode
|
|
|
|
inline int codeTicksAccess16(u32 address) // THUMB NON SEQ
|
|
|
|
{
|
|
|
|
int addr = (address>>24)&15;
|
|
|
|
|
2010-01-24 19:26:31 +01:00
|
|
|
if (unsigned(addr - 0x08) <= (0x0D - 0x08))
|
2008-09-23 01:00:10 +02:00
|
|
|
{
|
|
|
|
if (busPrefetchCount&0x1)
|
|
|
|
{
|
|
|
|
if (busPrefetchCount&0x2)
|
|
|
|
{
|
|
|
|
busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00);
|
|
|
|
return memoryWaitSeq[addr]-1;
|
|
|
|
}
|
|
|
|
}
|
2010-01-24 19:26:31 +01:00
|
|
|
busPrefetchCount = 0;
|
|
|
|
return memoryWait[addr];
|
2008-09-23 01:00:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline int codeTicksAccess32(u32 address) // ARM NON SEQ
|
|
|
|
{
|
|
|
|
int addr = (address>>24)&15;
|
|
|
|
|
2010-01-24 19:26:31 +01:00
|
|
|
if (unsigned(addr - 0x08) <= (0x0D - 0x08))
|
2008-09-23 01:00:10 +02:00
|
|
|
{
|
|
|
|
if (busPrefetchCount&0x1)
|
|
|
|
{
|
|
|
|
if (busPrefetchCount&0x2)
|
|
|
|
{
|
|
|
|
busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00);
|
|
|
|
return memoryWaitSeq[addr] - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
busPrefetchCount = 0;
|
|
|
|
return memoryWait32[addr];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int codeTicksAccessSeq16(u32 address) // THUMB SEQ
|
|
|
|
{
|
|
|
|
int addr = (address>>24)&15;
|
|
|
|
|
2010-01-24 19:26:31 +01:00
|
|
|
if (unsigned(addr - 0x08) <= (0x0D - 0x08))
|
2008-09-23 01:00:10 +02:00
|
|
|
{
|
|
|
|
if (busPrefetchCount&0x1)
|
|
|
|
{
|
|
|
|
busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (busPrefetchCount>0xFF)
|
|
|
|
{
|
|
|
|
busPrefetchCount=0;
|
|
|
|
return memoryWait[addr];
|
|
|
|
}
|
|
|
|
}
|
2010-01-24 19:26:31 +01:00
|
|
|
else{
|
2008-09-23 01:00:10 +02:00
|
|
|
busPrefetchCount = 0;
|
|
|
|
}
|
2010-01-24 19:26:31 +01:00
|
|
|
return memoryWaitSeq[addr];
|
2008-09-23 01:00:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline int codeTicksAccessSeq32(u32 address) // ARM SEQ
|
|
|
|
{
|
|
|
|
int addr = (address>>24)&15;
|
|
|
|
|
2010-01-24 19:26:31 +01:00
|
|
|
if (unsigned(addr - 0x08) <= (0x0D - 0x08)){
|
|
|
|
if (busPrefetchCount&0x1){
|
|
|
|
if (busPrefetchCount&0x2){
|
2008-09-23 01:00:10 +02:00
|
|
|
busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00);
|
|
|
|
return memoryWaitSeq[addr];
|
|
|
|
}
|
|
|
|
else
|
2010-01-24 19:26:31 +01:00
|
|
|
if (busPrefetchCount>0xFF){
|
2008-09-23 01:00:10 +02:00
|
|
|
busPrefetchCount=0;
|
|
|
|
return memoryWait32[addr];
|
|
|
|
}
|
|
|
|
}
|
2010-01-24 19:26:31 +01:00
|
|
|
return memoryWaitSeq32[addr];
|
2008-09-23 01:00:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Emulates the Cheat System (m) code
|
|
|
|
inline void cpuMasterCodeCheck()
|
|
|
|
{
|
|
|
|
if((mastercode) && (mastercode == armNextPC))
|
|
|
|
{
|
|
|
|
u32 joy = 0;
|
|
|
|
if(systemReadJoypads())
|
|
|
|
joy = systemReadJoypad(-1);
|
|
|
|
u32 ext = (joy >> 10);
|
|
|
|
cpuTotalTicks += cheatsCheckKeys(P1^0x3FF, ext);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-10 03:41:39 +01:00
|
|
|
#endif // GBACPU_H
|