diff --git a/src/arm.c b/src/arm.c index b78381ac4..91b29026d 100644 --- a/src/arm.c +++ b/src/arm.c @@ -4,17 +4,16 @@ #define ARM_ROR(I, ROTATE) (((I) >> ROTATE) | (I << (32 - ROTATE))) static inline void _ARMSetMode(struct ARMCore*, enum ExecutionMode); -static void _ARMSetPrivilegeMode(struct ARMCore*, enum PrivilegeMode); static ARMInstruction _ARMLoadInstructionARM(struct ARMMemory*, uint32_t address, uint32_t* opcodeOut); static ARMInstruction _ARMLoadInstructionThumb(struct ARMMemory*, uint32_t address, uint32_t* opcodeOut); static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode); static inline void _ARMReadCPSR(struct ARMCore* cpu) { _ARMSetMode(cpu, cpu->cpsr.t); - _ARMSetPrivilegeMode(cpu, cpu->cpsr.priv); + ARMSetPrivilegeMode(cpu, cpu->cpsr.priv); } -static void _ARMSetPrivilegeMode(struct ARMCore* cpu, enum PrivilegeMode mode) { +void ARMSetPrivilegeMode(struct ARMCore* cpu, enum PrivilegeMode mode) { if (mode == cpu->privilegeMode) { // Not switching modes after all return; @@ -127,6 +126,20 @@ static ARMInstruction _ARMLoadInstructionThumb(struct ARMMemory* memory, uint32_ } void ARMInit(struct ARMCore* cpu) { + cpu->memory = 0; + cpu->board = 0; +} + +void ARMAssociateMemory(struct ARMCore* cpu, struct ARMMemory* memory) { + cpu->memory = memory; +} + +void ARMAssociateBoard(struct ARMCore* cpu, struct ARMBoard* board) { + cpu->board = board; + board->cpu = cpu; +} + +void ARMReset(struct ARMCore* cpu) { int i; for (i = 0; i < 16; ++i) { cpu->gprs[i] = 0; @@ -150,15 +163,10 @@ void ARMInit(struct ARMCore* cpu) { cpu->shifterOperand = 0; cpu->shifterCarryOut = 0; - cpu->memory = 0; - cpu->board = 0; - cpu->executionMode = MODE_THUMB; _ARMSetMode(cpu, MODE_ARM); -} -void ARMAssociateMemory(struct ARMCore* cpu, struct ARMMemory* memory) { - cpu->memory = memory; + cpu->board->reset(cpu->board); } void ARMStep(struct ARMCore* cpu) { diff --git a/src/arm.h b/src/arm.h index 031a497bc..8916c8306 100644 --- a/src/arm.h +++ b/src/arm.h @@ -80,7 +80,8 @@ struct ARMMemory { }; struct ARMBoard { - // TODO + struct ARMCore* cpu; + void (*reset)(struct ARMBoard* board); }; struct ARMCore { @@ -108,7 +109,10 @@ struct ARMCore { void ARMInit(struct ARMCore* cpu); void ARMAssociateMemory(struct ARMCore* cpu, struct ARMMemory* memory); +void ARMAssociateBoard(struct ARMCore* cpu, struct ARMBoard* board); +void ARMReset(struct ARMCore* cpu); void ARMStep(struct ARMCore* cpu); +void ARMSetPrivilegeMode(struct ARMCore*, enum PrivilegeMode); #endif diff --git a/src/gba.c b/src/gba.c index fc42574c0..be010a7ed 100644 --- a/src/gba.c +++ b/src/gba.c @@ -14,6 +14,11 @@ void GBAInit(struct GBA* gba) { gba->memory.p = gba; GBAMemoryInit(&gba->memory); ARMAssociateMemory(&gba->cpu, &gba->memory.d); + + GBABoardInit(&gba->board); + ARMAssociateBoard(&gba->cpu, &gba->board.d); + + ARMReset(&gba->cpu); } void GBADeinit(struct GBA* gba) { @@ -47,6 +52,20 @@ void GBAMemoryDeinit(struct GBAMemory* memory) { munmap(memory->iwram, SIZE_WORKING_IRAM); } +void GBABoardInit(struct GBABoard* board) { + board->d.reset = GBABoardReset; +} + +void GBABoardReset(struct ARMBoard* board) { + struct ARMCore* cpu = board->cpu; + ARMSetPrivilegeMode(cpu, MODE_IRQ); + cpu->gprs[ARM_SP] = SP_BASE_IRQ; + ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR); + cpu->gprs[ARM_SP] = SP_BASE_SUPERVISOR; + ARMSetPrivilegeMode(cpu, MODE_SYSTEM); + cpu->gprs[ARM_SP] = SP_BASE_SYSTEM; +} + void GBALoadROM(struct GBA* gba, int fd) { gba->memory.rom = mmap(0, SIZE_CART0, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0); // TODO: error check diff --git a/src/gba.h b/src/gba.h index 0f8cc9830..77700c634 100644 --- a/src/gba.h +++ b/src/gba.h @@ -41,6 +41,7 @@ enum GBAMemoryBase { BASE_CART2_EX = 0x0D000000, BASE_CART_SRAM = 0x0E000000 }; + enum { SIZE_BIOS = 0x00004000, SIZE_WORKING_RAM = 0x00040000, @@ -58,6 +59,12 @@ enum { SIZE_CART_EEPROM = 0x00002000 }; +enum { + SP_BASE_SYSTEM = 0x03FFFF00, + SP_BASE_IRQ = 0x03FFFFA0, + SP_BASE_SUPERVISOR = 0x03FFFFE0 +}; + enum { OFFSET_MASK = 0x00FFFFFF }; @@ -73,7 +80,7 @@ struct GBAMemory { }; struct GBABoard { - struct ARMBoard board; + struct ARMBoard d; }; struct GBA { @@ -91,6 +98,9 @@ void GBADeinit(struct GBA* gba); void GBAMemoryInit(struct GBAMemory* memory); void GBAMemoryDeinit(struct GBAMemory* memory); +void GBABoardInit(struct GBABoard* board); +void GBABoardReset(struct ARMBoard* board); + void GBALoadROM(struct GBA* gba, int fd); int32_t GBALoad32(struct ARMMemory* memory, uint32_t address);