238 lines
6.8 KiB
C
238 lines
6.8 KiB
C
#ifndef GBACPU_H
|
|
#define GBACPU_H
|
|
|
|
extern int armExecute();
|
|
extern int thumbExecute();
|
|
|
|
#if defined(__i386__) || defined(__x86_64__)
|
|
#define INSN_REGPARM __attribute__((regparm(1)))
|
|
#else
|
|
#define INSN_REGPARM /*nothing*/
|
|
#endif
|
|
|
|
#ifdef __GNUC__
|
|
#define LIKELY(x) __builtin_expect(!!(x), 1)
|
|
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
|
|
#else
|
|
#define LIKELY(x) (x)
|
|
#define UNLIKELY(x) (x)
|
|
#endif
|
|
|
|
#define UPDATE_REG(address, value) \
|
|
{ \
|
|
WRITE16LE(((uint16_t*)&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 uint32_t mastercode;
|
|
extern bool busPrefetch;
|
|
extern bool busPrefetchEnable;
|
|
extern uint32_t busPrefetchCount;
|
|
extern int cpuNextEvent;
|
|
extern bool holdState;
|
|
extern uint32_t cpuPrefetch[2];
|
|
extern int cpuTotalTicks;
|
|
extern uint8_t memoryWait[16];
|
|
extern uint8_t memoryWait32[16];
|
|
extern uint8_t memoryWaitSeq[16];
|
|
extern uint8_t memoryWaitSeq32[16];
|
|
extern uint8_t cpuBitsSet[256];
|
|
extern uint8_t 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(uint32_t 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(uint32_t 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(uint32_t 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(uint32_t 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(uint32_t address) // THUMB NON SEQ
|
|
{
|
|
int addr = (address >> 24) & 15;
|
|
|
|
if ((addr >= 0x08) && (addr <= 0x0D)) {
|
|
if (busPrefetchCount & 0x1) {
|
|
if (busPrefetchCount & 0x2) {
|
|
busPrefetchCount = ((busPrefetchCount & 0xFF) >> 2) | (busPrefetchCount & 0xFFFFFF00);
|
|
return 0;
|
|
}
|
|
busPrefetchCount = ((busPrefetchCount & 0xFF) >> 1) | (busPrefetchCount & 0xFFFFFF00);
|
|
return memoryWaitSeq[addr] - 1;
|
|
} else {
|
|
busPrefetchCount = 0;
|
|
return memoryWait[addr];
|
|
}
|
|
} else {
|
|
busPrefetchCount = 0;
|
|
return memoryWait[addr];
|
|
}
|
|
}
|
|
|
|
inline int codeTicksAccess32(uint32_t address) // ARM NON SEQ
|
|
{
|
|
int addr = (address >> 24) & 15;
|
|
|
|
if ((addr >= 0x08) && (addr <= 0x0D)) {
|
|
if (busPrefetchCount & 0x1) {
|
|
if (busPrefetchCount & 0x2) {
|
|
busPrefetchCount = ((busPrefetchCount & 0xFF) >> 2) | (busPrefetchCount & 0xFFFFFF00);
|
|
return 0;
|
|
}
|
|
busPrefetchCount = ((busPrefetchCount & 0xFF) >> 1) | (busPrefetchCount & 0xFFFFFF00);
|
|
return memoryWaitSeq[addr] - 1;
|
|
} else {
|
|
busPrefetchCount = 0;
|
|
return memoryWait32[addr];
|
|
}
|
|
} else {
|
|
busPrefetchCount = 0;
|
|
return memoryWait32[addr];
|
|
}
|
|
}
|
|
|
|
inline int codeTicksAccessSeq16(uint32_t address) // THUMB SEQ
|
|
{
|
|
int addr = (address >> 24) & 15;
|
|
|
|
if ((addr >= 0x08) && (addr <= 0x0D)) {
|
|
if (busPrefetchCount & 0x1) {
|
|
busPrefetchCount = ((busPrefetchCount & 0xFF) >> 1) | (busPrefetchCount & 0xFFFFFF00);
|
|
return 0;
|
|
} else if (busPrefetchCount > 0xFF) {
|
|
busPrefetchCount = 0;
|
|
return memoryWait[addr];
|
|
} else
|
|
return memoryWaitSeq[addr];
|
|
} else {
|
|
busPrefetchCount = 0;
|
|
return memoryWaitSeq[addr];
|
|
}
|
|
}
|
|
|
|
inline int codeTicksAccessSeq32(uint32_t address) // ARM SEQ
|
|
{
|
|
int addr = (address >> 24) & 15;
|
|
|
|
if ((addr >= 0x08) && (addr <= 0x0D)) {
|
|
if (busPrefetchCount & 0x1) {
|
|
if (busPrefetchCount & 0x2) {
|
|
busPrefetchCount = ((busPrefetchCount & 0xFF) >> 2) | (busPrefetchCount & 0xFFFFFF00);
|
|
return 0;
|
|
}
|
|
busPrefetchCount = ((busPrefetchCount & 0xFF) >> 1) | (busPrefetchCount & 0xFFFFFF00);
|
|
return memoryWaitSeq[addr];
|
|
} else if (busPrefetchCount > 0xFF) {
|
|
busPrefetchCount = 0;
|
|
return memoryWait32[addr];
|
|
} else
|
|
return memoryWaitSeq32[addr];
|
|
} else {
|
|
return memoryWaitSeq32[addr];
|
|
}
|
|
}
|
|
|
|
// Emulates the Cheat System (m) code
|
|
inline void cpuMasterCodeCheck()
|
|
{
|
|
if ((mastercode) && (mastercode == armNextPC)) {
|
|
uint32_t joy = 0;
|
|
if (systemReadJoypads())
|
|
joy = systemReadJoypad(-1);
|
|
uint32_t ext = (joy >> 10);
|
|
cpuTotalTicks += cheatsCheckKeys(P1 ^ 0x3FF, ext);
|
|
}
|
|
}
|
|
|
|
#endif // GBACPU_H
|