Redo component model/type punning
jump to
@@ -65,8 +65,20 @@ }
} void ARMInit(struct ARMCore* cpu) { - // TODO: Remove + cpu->master->init(cpu, cpu->master); + int i; + for (i = 0; i < cpu->numComponents; ++i) { + cpu->components[i]->init(cpu, cpu->components[i]); + } } + +void ARMSetComponents(struct ARMCore* cpu, struct ARMComponent* master, int extra, struct ARMComponent** extras) { + // TODO: Call init/deinit + cpu->master = master; + cpu->numComponents = extra; + cpu->components = extras; +} + void ARMReset(struct ARMCore* cpu) { int i;@@ -101,7 +113,7 @@
cpu->cycles = 0; cpu->nextEvent = 0; - cpu->board.reset(cpu); + cpu->irqh.reset(cpu); } void ARMRaiseIRQ(struct ARMCore* cpu) {@@ -264,6 +276,6 @@ } else {
ARMStep(cpu); } if (cpu->cycles >= cpu->nextEvent) { - cpu->board.processEvents(cpu); + cpu->irqh.processEvents(cpu); } }
@@ -99,15 +99,21 @@ void (*setActiveRegion)(struct ARMCore*, uint32_t address);
int (*waitMultiple)(struct ARMCore*, uint32_t startAddress, int count); }; -struct ARMBoard { - void (*reset)(struct ARMCore* board); - void (*processEvents)(struct ARMCore* board); - void (*swi16)(struct ARMCore* board, int immediate); - void (*swi32)(struct ARMCore* board, int immediate); - void (*hitIllegal)(struct ARMCore* board, uint32_t opcode); - void (*readCPSR)(struct ARMCore* board); +struct ARMInterruptHandler { + void (*reset)(struct ARMCore* cpu); + void (*processEvents)(struct ARMCore* cpu); + void (*swi16)(struct ARMCore* cpu, int immediate); + void (*swi32)(struct ARMCore* cpu, int immediate); + void (*hitIllegal)(struct ARMCore* cpu, uint32_t opcode); + void (*readCPSR)(struct ARMCore* cpu); + + void (*hitStub)(struct ARMCore* cpu, uint32_t opcode); +}; - void (*hitStub)(struct ARMCore* board, uint32_t opcode); +struct ARMComponent { + long id; + void (*init)(struct ARMCore* cpu, struct ARMComponent* component); + void (*deinit)(struct ARMComponent* component); }; struct ARMCore {@@ -130,15 +136,16 @@ enum ExecutionMode executionMode;
enum PrivilegeMode privilegeMode; struct ARMMemory memory; - struct ARMBoard board; + struct ARMInterruptHandler irqh; - int64_t absoluteCycles; - int32_t lastCycles; + struct ARMComponent* master; + + int numComponents; + struct ARMComponent** components; }; void ARMInit(struct ARMCore* cpu); -void ARMAssociateMemory(struct ARMCore* cpu, struct ARMMemory* memory); -void ARMAssociateBoard(struct ARMCore* cpu, struct ARMBoard* board); +void ARMSetComponents(struct ARMCore* cpu, struct ARMComponent* master, int extra, struct ARMComponent** extras); void ARMReset(struct ARMCore* cpu); void ARMSetPrivilegeMode(struct ARMCore*, enum PrivilegeMode);
@@ -702,7 +702,7 @@ int32_t mask = (c ? 0x000000FF : 0) | (f ? 0xFF000000 : 0);
mask &= PSR_USER_MASK | PSR_PRIV_MASK | PSR_STATE_MASK; cpu->spsr.packed = (cpu->spsr.packed & ~mask) | (operand & mask);) -DEFINE_INSTRUCTION_ARM(SWI, cpu->board.swi32(cpu, opcode & 0xFFFFFF)) +DEFINE_INSTRUCTION_ARM(SWI, cpu->irqh.swi32(cpu, opcode & 0xFFFFFF)) #define DECLARE_INSTRUCTION_ARM(EMITTER, NAME) \ EMITTER ## NAME
@@ -65,8 +65,8 @@ } else { \
cpu->cycles += 4; \ } -#define ARM_STUB cpu->board.hitStub(cpu, opcode) -#define ARM_ILL cpu->board.hitIllegal(cpu, opcode) +#define ARM_STUB cpu->irqh.hitStub(cpu, opcode) +#define ARM_ILL cpu->irqh.hitIllegal(cpu, opcode) #define ARM_WRITE_PC \ cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM) + WORD_SIZE_ARM; \@@ -100,7 +100,7 @@
static inline void _ARMReadCPSR(struct ARMCore* cpu) { _ARMSetMode(cpu, cpu->cpsr.t); ARMSetPrivilegeMode(cpu, cpu->cpsr.priv); - cpu->board.readCPSR(cpu); + cpu->irqh.readCPSR(cpu); } #endif
@@ -469,7 +469,7 @@ } else {
ARM_WRITE_PC; }) -DEFINE_INSTRUCTION_THUMB(SWI, cpu->board.swi16(cpu, opcode & 0xFF)) +DEFINE_INSTRUCTION_THUMB(SWI, cpu->irqh.swi16(cpu, opcode & 0xFF)) #define DECLARE_INSTRUCTION_THUMB(EMITTER, NAME) \ EMITTER ## NAME
@@ -604,6 +604,7 @@ el_end(cliDebugger->elstate);
} void CLIDebuggerCreate(struct CLIDebugger* debugger) { + ARMDebuggerCreate(&debugger->d); debugger->d.init = _cliDebuggerInit; debugger->d.deinit = _cliDebuggerDeinit; debugger->d.paused = _commandLine;
@@ -21,7 +21,16 @@ }
} } -void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) { +static void ARMDebuggerInit(struct ARMCore*, struct ARMComponent*); +static void ARMDebuggerDeinit(struct ARMComponent*); + +void ARMDebuggerCreate(struct ARMDebugger* debugger) { + debugger->d.init = ARMDebuggerInit; + debugger->d.deinit = ARMDebuggerDeinit; +} + +void ARMDebuggerInit(struct ARMCore* cpu, struct ARMComponent* component) { + struct ARMDebugger* debugger = (struct ARMDebugger*) component; debugger->cpu = cpu; debugger->state = DEBUGGER_RUNNING; debugger->breakpoints = 0;@@ -33,8 +42,8 @@ debugger->init(debugger);
} } -void ARMDebuggerDeinit(struct ARMDebugger* debugger) { - // TODO: actually call this +void ARMDebuggerDeinit(struct ARMComponent* component) { + struct ARMDebugger* debugger = (struct ARMDebugger*) component; debugger->deinit(debugger); }
@@ -40,6 +40,7 @@ DEBUGGER_LOG_ERROR = 0x08
}; struct ARMDebugger { + struct ARMComponent d; enum DebuggerState state; struct ARMCore* cpu;@@ -55,8 +56,7 @@ __attribute__((format (printf, 3, 4)))
void (*log)(struct ARMDebugger*, enum DebuggerLogLevel, const char* format, ...); }; -void ARMDebuggerInit(struct ARMDebugger*, struct ARMCore*); -void ARMDebuggerDeinit(struct ARMDebugger*); +void ARMDebuggerCreate(struct ARMDebugger*); void ARMDebuggerRun(struct ARMDebugger*); void ARMDebuggerEnter(struct ARMDebugger*, enum DebuggerEntryReason); void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address);
@@ -420,6 +420,7 @@ return parsed;
} void GDBStubCreate(struct GDBStub* stub) { + ARMDebuggerCreate(&stub->d); stub->socket = -1; stub->connection = -1; stub->d.init = 0;
@@ -12,15 +12,16 @@ static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest);
static void _unRl(struct GBA* gba, uint32_t source, uint8_t* dest); static void _RegisterRamReset(struct GBA* gba) { - uint32_t registers = gba->cpu.gprs[0]; + uint32_t registers = gba->cpu->gprs[0]; (void)(registers); GBALog(gba, GBA_LOG_STUB, "RegisterRamReset unimplemented"); } static void _CpuSet(struct GBA* gba) { - uint32_t source = gba->cpu.gprs[0]; - uint32_t dest = gba->cpu.gprs[1]; - uint32_t mode = gba->cpu.gprs[2]; + struct ARMCore* cpu = gba->cpu; + uint32_t source = cpu->gprs[0]; + uint32_t dest = cpu->gprs[1]; + uint32_t mode = cpu->gprs[2]; int count = mode & 0x000FFFFF; int fill = mode & 0x01000000; int wordsize = (mode & 0x04000000) ? 4 : 2;@@ -29,18 +30,18 @@ if (fill) {
if (wordsize == 4) { source &= 0xFFFFFFFC; dest &= 0xFFFFFFFC; - int32_t word = gba->cpu.memory.load32(&gba->cpu, source, &gba->cpu.cycles); + int32_t word = cpu->memory.load32(cpu, source, &cpu->cycles); for (i = 0; i < count; ++i) { - gba->cpu.memory.store32(&gba->cpu, dest + (i << 2), word, &gba->cpu.cycles); - gba->cpu.board.processEvents(&gba->cpu); + cpu->memory.store32(cpu, dest + (i << 2), word, &cpu->cycles); + cpu->irqh.processEvents(cpu); } } else { source &= 0xFFFFFFFE; dest &= 0xFFFFFFFE; - uint16_t word = gba->cpu.memory.load16(&gba->cpu, source, &gba->cpu.cycles); + uint16_t word = cpu->memory.load16(cpu, source, &cpu->cycles); for (i = 0; i < count; ++i) { - gba->cpu.memory.store16(&gba->cpu, dest + (i << 1), word, &gba->cpu.cycles); - gba->cpu.board.processEvents(&gba->cpu); + cpu->memory.store16(cpu, dest + (i << 1), word, &cpu->cycles); + cpu->irqh.processEvents(cpu); } } } else {@@ -48,68 +49,70 @@ if (wordsize == 4) {
source &= 0xFFFFFFFC; dest &= 0xFFFFFFFC; for (i = 0; i < count; ++i) { - int32_t word = gba->cpu.memory.load32(&gba->cpu, source + (i << 2), &gba->cpu.cycles); - gba->cpu.memory.store32(&gba->cpu, dest + (i << 2), word, &gba->cpu.cycles); - gba->cpu.board.processEvents(&gba->cpu); + int32_t word = cpu->memory.load32(cpu, source + (i << 2), &cpu->cycles); + cpu->memory.store32(cpu, dest + (i << 2), word, &cpu->cycles); + cpu->irqh.processEvents(cpu); } } else { source &= 0xFFFFFFFE; dest &= 0xFFFFFFFE; for (i = 0; i < count; ++i) { - uint16_t word = gba->cpu.memory.load16(&gba->cpu, source + (i << 1), &gba->cpu.cycles); - gba->cpu.memory.store16(&gba->cpu, dest + (i << 1), word, &gba->cpu.cycles); - gba->cpu.board.processEvents(&gba->cpu); + uint16_t word = cpu->memory.load16(cpu, source + (i << 1), &cpu->cycles); + cpu->memory.store16(cpu, dest + (i << 1), word, &cpu->cycles); + cpu->irqh.processEvents(cpu); } } } } static void _FastCpuSet(struct GBA* gba) { - uint32_t source = gba->cpu.gprs[0] & 0xFFFFFFFC; - uint32_t dest = gba->cpu.gprs[1] & 0xFFFFFFFC; - uint32_t mode = gba->cpu.gprs[2]; + struct ARMCore* cpu = gba->cpu; + uint32_t source = cpu->gprs[0] & 0xFFFFFFFC; + uint32_t dest = cpu->gprs[1] & 0xFFFFFFFC; + uint32_t mode = cpu->gprs[2]; int count = mode & 0x000FFFFF; - int storeCycles = gba->cpu.memory.waitMultiple(&gba->cpu, dest, 4); + int storeCycles = cpu->memory.waitMultiple(cpu, dest, 4); count = ((count + 7) >> 3) << 3; int i; if (mode & 0x01000000) { - int32_t word = gba->cpu.memory.load32(&gba->cpu, source, &gba->cpu.cycles); + int32_t word = cpu->memory.load32(cpu, source, &cpu->cycles); for (i = 0; i < count; i += 4) { - gba->cpu.memory.store32(&gba->cpu, dest + ((i + 0) << 2), word, 0); - gba->cpu.memory.store32(&gba->cpu, dest + ((i + 1) << 2), word, 0); - gba->cpu.memory.store32(&gba->cpu, dest + ((i + 2) << 2), word, 0); - gba->cpu.memory.store32(&gba->cpu, dest + ((i + 3) << 2), word, 0); - gba->cpu.cycles += storeCycles; - gba->cpu.board.processEvents(&gba->cpu); + cpu->memory.store32(cpu, dest + ((i + 0) << 2), word, 0); + cpu->memory.store32(cpu, dest + ((i + 1) << 2), word, 0); + cpu->memory.store32(cpu, dest + ((i + 2) << 2), word, 0); + cpu->memory.store32(cpu, dest + ((i + 3) << 2), word, 0); + cpu->cycles += storeCycles; + cpu->irqh.processEvents(cpu); } } else { - int loadCycles = gba->cpu.memory.waitMultiple(&gba->cpu, source, 4); + int loadCycles = cpu->memory.waitMultiple(cpu, source, 4); for (i = 0; i < count; i += 4) { - int32_t word0 = gba->cpu.memory.load32(&gba->cpu, source + ((i + 0) << 2), 0); - int32_t word1 = gba->cpu.memory.load32(&gba->cpu, source + ((i + 1) << 2), 0); - int32_t word2 = gba->cpu.memory.load32(&gba->cpu, source + ((i + 2) << 2), 0); - int32_t word3 = gba->cpu.memory.load32(&gba->cpu, source + ((i + 3) << 2), 0); - gba->cpu.cycles += loadCycles; - gba->cpu.board.processEvents(&gba->cpu); - gba->cpu.memory.store32(&gba->cpu, dest + ((i + 0) << 2), word0, 0); - gba->cpu.memory.store32(&gba->cpu, dest + ((i + 1) << 2), word1, 0); - gba->cpu.memory.store32(&gba->cpu, dest + ((i + 2) << 2), word2, 0); - gba->cpu.memory.store32(&gba->cpu, dest + ((i + 3) << 2), word3, 0); - gba->cpu.cycles += storeCycles; - gba->cpu.board.processEvents(&gba->cpu); + int32_t word0 = cpu->memory.load32(cpu, source + ((i + 0) << 2), 0); + int32_t word1 = cpu->memory.load32(cpu, source + ((i + 1) << 2), 0); + int32_t word2 = cpu->memory.load32(cpu, source + ((i + 2) << 2), 0); + int32_t word3 = cpu->memory.load32(cpu, source + ((i + 3) << 2), 0); + cpu->cycles += loadCycles; + cpu->irqh.processEvents(cpu); + cpu->memory.store32(cpu, dest + ((i + 0) << 2), word0, 0); + cpu->memory.store32(cpu, dest + ((i + 1) << 2), word1, 0); + cpu->memory.store32(cpu, dest + ((i + 2) << 2), word2, 0); + cpu->memory.store32(cpu, dest + ((i + 3) << 2), word3, 0); + cpu->cycles += storeCycles; + cpu->irqh.processEvents(cpu); } } } static void _BgAffineSet(struct GBA* gba) { - int i = gba->cpu.gprs[2]; + struct ARMCore* cpu = gba->cpu; + int i = cpu->gprs[2]; float ox, oy; float cx, cy; float sx, sy; float theta; - int offset = gba->cpu.gprs[0]; - int destination = gba->cpu.gprs[1]; - int diff = gba->cpu.gprs[3]; + int offset = cpu->gprs[0]; + int destination = cpu->gprs[1]; + int diff = cpu->gprs[3]; (void)(diff); // Are we supposed to use this? float a, b, c, d; float rx, ry;@@ -117,13 +120,13 @@ while (i--) {
// [ sx 0 0 ] [ cos(theta) -sin(theta) 0 ] [ 1 0 cx - ox ] [ A B rx ] // [ 0 sy 0 ] * [ sin(theta) cos(theta) 0 ] * [ 0 1 cy - oy ] = [ C D ry ] // [ 0 0 1 ] [ 0 0 1 ] [ 0 0 1 ] [ 0 0 1 ] - ox = gba->cpu.memory.load32(&gba->cpu, offset, 0) / 256.f; - oy = gba->cpu.memory.load32(&gba->cpu, offset + 4, 0) / 256.f; - cx = gba->cpu.memory.load16(&gba->cpu, offset + 8, 0); - cy = gba->cpu.memory.load16(&gba->cpu, offset + 10, 0); - sx = gba->cpu.memory.load16(&gba->cpu, offset + 12, 0) / 256.f; - sy = gba->cpu.memory.load16(&gba->cpu, offset + 14, 0) / 256.f; - theta = (gba->cpu.memory.loadU16(&gba->cpu, offset + 16, 0) >> 8) / 128.f * M_PI; + ox = cpu->memory.load32(cpu, offset, 0) / 256.f; + oy = cpu->memory.load32(cpu, offset + 4, 0) / 256.f; + cx = cpu->memory.load16(cpu, offset + 8, 0); + cy = cpu->memory.load16(cpu, offset + 10, 0); + sx = cpu->memory.load16(cpu, offset + 12, 0) / 256.f; + sy = cpu->memory.load16(cpu, offset + 14, 0) / 256.f; + theta = (cpu->memory.loadU16(cpu, offset + 16, 0) >> 8) / 128.f * M_PI; offset += 20; // Rotation a = d = cosf(theta);@@ -136,30 +139,31 @@ d *= sy;
// Translate rx = ox - (a * cx + b * cy); ry = oy - (c * cx + d * cy); - gba->cpu.memory.store16(&gba->cpu, destination, a * 256, 0); - gba->cpu.memory.store16(&gba->cpu, destination + 2, b * 256, 0); - gba->cpu.memory.store16(&gba->cpu, destination + 4, c * 256, 0); - gba->cpu.memory.store16(&gba->cpu, destination + 6, d * 256, 0); - gba->cpu.memory.store32(&gba->cpu, destination + 8, rx * 256, 0); - gba->cpu.memory.store32(&gba->cpu, destination + 12, ry * 256, 0); + cpu->memory.store16(cpu, destination, a * 256, 0); + cpu->memory.store16(cpu, destination + 2, b * 256, 0); + cpu->memory.store16(cpu, destination + 4, c * 256, 0); + cpu->memory.store16(cpu, destination + 6, d * 256, 0); + cpu->memory.store32(cpu, destination + 8, rx * 256, 0); + cpu->memory.store32(cpu, destination + 12, ry * 256, 0); destination += 16; } } static void _ObjAffineSet(struct GBA* gba) { - int i = gba->cpu.gprs[2]; + struct ARMCore* cpu = gba->cpu; + int i = cpu->gprs[2]; float sx, sy; float theta; - int offset = gba->cpu.gprs[0]; - int destination = gba->cpu.gprs[1]; - int diff = gba->cpu.gprs[3]; + int offset = cpu->gprs[0]; + int destination = cpu->gprs[1]; + int diff = cpu->gprs[3]; float a, b, c, d; while (i--) { // [ sx 0 ] [ cos(theta) -sin(theta) ] [ A B ] // [ 0 sy ] * [ sin(theta) cos(theta) ] = [ C D ] - sx = gba->cpu.memory.load16(&gba->cpu, offset, 0) / 256.f; - sy = gba->cpu.memory.load16(&gba->cpu, offset + 2, 0) / 256.f; - theta = (gba->cpu.memory.loadU16(&gba->cpu, offset + 4, 0) >> 8) / 128.f * M_PI; + sx = cpu->memory.load16(cpu, offset, 0) / 256.f; + sy = cpu->memory.load16(cpu, offset + 2, 0) / 256.f; + theta = (cpu->memory.loadU16(cpu, offset + 4, 0) >> 8) / 128.f * M_PI; offset += 6; // Rotation a = d = cosf(theta);@@ -169,23 +173,24 @@ a *= sx;
b *= -sx; c *= sy; d *= sy; - gba->cpu.memory.store16(&gba->cpu, destination, a * 256, 0); - gba->cpu.memory.store16(&gba->cpu, destination + diff, b * 256, 0); - gba->cpu.memory.store16(&gba->cpu, destination + diff * 2, c * 256, 0); - gba->cpu.memory.store16(&gba->cpu, destination + diff * 3, d * 256, 0); + cpu->memory.store16(cpu, destination, a * 256, 0); + cpu->memory.store16(cpu, destination + diff, b * 256, 0); + cpu->memory.store16(cpu, destination + diff * 2, c * 256, 0); + cpu->memory.store16(cpu, destination + diff * 3, d * 256, 0); destination += diff * 4; } } static void _MidiKey2Freq(struct GBA* gba) { - uint32_t key = gba->cpu.memory.load32(&gba->cpu, gba->cpu.gprs[0] + 4, 0); - gba->cpu.gprs[0] = key / powf(2, (180.f - gba->cpu.gprs[1] - gba->cpu.gprs[2] / 256.f) / 12.f); + struct ARMCore* cpu = gba->cpu; + uint32_t key = cpu->memory.load32(cpu, cpu->gprs[0] + 4, 0); + cpu->gprs[0] = key / powf(2, (180.f - cpu->gprs[1] - cpu->gprs[2] / 256.f) / 12.f); } void GBASwi16(struct ARMCore* cpu, int immediate) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; if (gba->memory.fullBios) { - ARMRaiseSWI(&gba->cpu); + ARMRaiseSWI(cpu); return; } switch (immediate) {@@ -197,39 +202,39 @@ GBAHalt(gba);
break; case 0x05: // VBlankIntrWait - gba->cpu.gprs[0] = 1; - gba->cpu.gprs[1] = 1; + cpu->gprs[0] = 1; + cpu->gprs[1] = 1; // Fall through: case 0x04: // IntrWait gba->memory.io[REG_IME >> 1] = 1; - if (!gba->cpu.gprs[0] && gba->memory.io[REG_IF >> 1] & gba->cpu.gprs[1]) { + if (!cpu->gprs[0] && gba->memory.io[REG_IF >> 1] & cpu->gprs[1]) { break; } gba->memory.io[REG_IF >> 1] = 0; - ARMRaiseSWI(&gba->cpu); + ARMRaiseSWI(cpu); break; case 0x6: { - div_t result = div(gba->cpu.gprs[0], gba->cpu.gprs[1]); - gba->cpu.gprs[0] = result.quot; - gba->cpu.gprs[1] = result.rem; - gba->cpu.gprs[3] = abs(result.quot); + div_t result = div(cpu->gprs[0], cpu->gprs[1]); + cpu->gprs[0] = result.quot; + cpu->gprs[1] = result.rem; + cpu->gprs[3] = abs(result.quot); } break; case 0x7: { - div_t result = div(gba->cpu.gprs[1], gba->cpu.gprs[0]); - gba->cpu.gprs[0] = result.quot; - gba->cpu.gprs[1] = result.rem; - gba->cpu.gprs[3] = abs(result.quot); + div_t result = div(cpu->gprs[1], cpu->gprs[0]); + cpu->gprs[0] = result.quot; + cpu->gprs[1] = result.rem; + cpu->gprs[3] = abs(result.quot); } break; case 0x8: - gba->cpu.gprs[0] = sqrt(gba->cpu.gprs[0]); + cpu->gprs[0] = sqrt(cpu->gprs[0]); break; case 0xA: - gba->cpu.gprs[0] = atan2f(gba->cpu.gprs[1] / 16384.f, gba->cpu.gprs[0] / 16384.f) / (2 * M_PI) * 0x10000; + cpu->gprs[0] = atan2f(cpu->gprs[1] / 16384.f, cpu->gprs[0] / 16384.f) / (2 * M_PI) * 0x10000; break; case 0xB: _CpuSet(gba);@@ -238,7 +243,7 @@ case 0xC:
_FastCpuSet(gba); break; case 0xD: - gba->cpu.gprs[0] = GBAChecksum(gba->memory.bios, SIZE_BIOS); + cpu->gprs[0] = GBAChecksum(gba->memory.bios, SIZE_BIOS); case 0xE: _BgAffineSet(gba); break;@@ -247,19 +252,19 @@ _ObjAffineSet(gba);
break; case 0x11: case 0x12: - if (gba->cpu.gprs[0] < BASE_WORKING_RAM) { + if (cpu->gprs[0] < BASE_WORKING_RAM) { GBALog(gba, GBA_LOG_GAME_ERROR, "Bad LZ77 source"); break; } - switch (gba->cpu.gprs[1] >> BASE_OFFSET) { + switch (cpu->gprs[1] >> BASE_OFFSET) { case REGION_WORKING_RAM: - _unLz77(gba, gba->cpu.gprs[0], &((uint8_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 1))]); + _unLz77(gba, cpu->gprs[0], &((uint8_t*) gba->memory.wram)[(cpu->gprs[1] & (SIZE_WORKING_RAM - 1))]); break; case REGION_WORKING_IRAM: - _unLz77(gba, gba->cpu.gprs[0], &((uint8_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 1))]); + _unLz77(gba, cpu->gprs[0], &((uint8_t*) gba->memory.iwram)[(cpu->gprs[1] & (SIZE_WORKING_IRAM - 1))]); break; case REGION_VRAM: - _unLz77(gba, gba->cpu.gprs[0], &((uint8_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFF)]); + _unLz77(gba, cpu->gprs[0], &((uint8_t*) gba->video.renderer->vram)[(cpu->gprs[1] & 0x0001FFFF)]); break; default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad LZ77 destination");@@ -267,19 +272,19 @@ break;
} break; case 0x13: - if (gba->cpu.gprs[0] < BASE_WORKING_RAM) { + if (cpu->gprs[0] < BASE_WORKING_RAM) { GBALog(gba, GBA_LOG_GAME_ERROR, "Bad Huffman source"); break; } - switch (gba->cpu.gprs[1] >> BASE_OFFSET) { + switch (cpu->gprs[1] >> BASE_OFFSET) { case REGION_WORKING_RAM: - _unHuffman(gba, gba->cpu.gprs[0], &((uint32_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 3)) >> 2]); + _unHuffman(gba, cpu->gprs[0], &((uint32_t*) gba->memory.wram)[(cpu->gprs[1] & (SIZE_WORKING_RAM - 3)) >> 2]); break; case REGION_WORKING_IRAM: - _unHuffman(gba, gba->cpu.gprs[0], &((uint32_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 3)) >> 2]); + _unHuffman(gba, cpu->gprs[0], &((uint32_t*) gba->memory.iwram)[(cpu->gprs[1] & (SIZE_WORKING_IRAM - 3)) >> 2]); break; case REGION_VRAM: - _unHuffman(gba, gba->cpu.gprs[0], &((uint32_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFC) >> 2]); + _unHuffman(gba, cpu->gprs[0], &((uint32_t*) gba->video.renderer->vram)[(cpu->gprs[1] & 0x0001FFFC) >> 2]); break; default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad Huffman destination");@@ -288,19 +293,19 @@ }
break; case 0x14: case 0x15: - if (gba->cpu.gprs[0] < BASE_WORKING_RAM) { + if (cpu->gprs[0] < BASE_WORKING_RAM) { GBALog(gba, GBA_LOG_GAME_ERROR, "Bad RL source"); break; } - switch (gba->cpu.gprs[1] >> BASE_OFFSET) { + switch (cpu->gprs[1] >> BASE_OFFSET) { case REGION_WORKING_RAM: - _unRl(gba, gba->cpu.gprs[0], &((uint8_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 1))]); + _unRl(gba, cpu->gprs[0], &((uint8_t*) gba->memory.wram)[(cpu->gprs[1] & (SIZE_WORKING_RAM - 1))]); break; case REGION_WORKING_IRAM: - _unRl(gba, gba->cpu.gprs[0], &((uint8_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 1))]); + _unRl(gba, cpu->gprs[0], &((uint8_t*) gba->memory.iwram)[(cpu->gprs[1] & (SIZE_WORKING_IRAM - 1))]); break; case REGION_VRAM: - _unRl(gba, gba->cpu.gprs[0], &((uint8_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFF)]); + _unRl(gba, cpu->gprs[0], &((uint8_t*) gba->video.renderer->vram)[(cpu->gprs[1] & 0x0001FFFF)]); break; default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad RL destination");@@ -329,7 +334,8 @@ return sum;
} static void _unLz77(struct GBA* gba, uint32_t source, uint8_t* dest) { - int remaining = (gba->cpu.memory.load32(&gba->cpu, source, 0) & 0xFFFFFF00) >> 8; + struct ARMCore* cpu = gba->cpu; + int remaining = (cpu->memory.load32(cpu, source, 0) & 0xFFFFFF00) >> 8; // We assume the signature byte (0x10) is correct int blockheader; uint32_t sPointer = source + 4;@@ -342,7 +348,7 @@ while (remaining > 0) {
if (blocksRemaining) { if (blockheader & 0x80) { // Compressed - block = gba->cpu.memory.loadU8(&gba->cpu, sPointer, 0) | (gba->cpu.memory.loadU8(&gba->cpu, sPointer + 1, 0) << 8); + block = cpu->memory.loadU8(cpu, sPointer, 0) | (cpu->memory.loadU8(cpu, sPointer + 1, 0) << 8); sPointer += 2; disp = dPointer - (((block & 0x000F) << 8) | ((block & 0xFF00) >> 8)) - 1; bytes = ((block & 0x00F0) >> 4) + 3;@@ -354,22 +360,23 @@ ++dPointer;
} } else { // Uncompressed - *dPointer = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); + *dPointer = cpu->memory.loadU8(cpu, sPointer++, 0); ++dPointer; --remaining; } blockheader <<= 1; --blocksRemaining; } else { - blockheader = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); + blockheader = cpu->memory.loadU8(cpu, sPointer++, 0); blocksRemaining = 8; } } } static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t* dest) { + struct ARMCore* cpu = gba->cpu; source = source & 0xFFFFFFFC; - uint32_t header = gba->cpu.memory.load32(&gba->cpu, source, 0); + uint32_t header = cpu->memory.load32(cpu, source, 0); int remaining = header >> 8; int bits = header & 0xF; if (32 % bits) {@@ -380,7 +387,7 @@ int padding = (4 - remaining) & 0x3;
remaining &= 0xFFFFFFFC; // We assume the signature byte (0x20) is correct //var tree = []; - int treesize = (gba->cpu.memory.loadU8(&gba->cpu, source + 4, 0) << 1) + 1; + int treesize = (cpu->memory.loadU8(cpu, source + 4, 0) << 1) + 1; int block = 0; uint32_t treeBase = source + 5; uint32_t sPointer = source + 5 + treesize;@@ -397,28 +404,28 @@ } node;
int bitsRemaining; int readBits; int bitsSeen = 0; - node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0); + node.packed = cpu->memory.load8(cpu, nPointer, 0); while (remaining > 0) { - uint32_t bitstream = gba->cpu.memory.load32(&gba->cpu, sPointer, 0); + uint32_t bitstream = cpu->memory.load32(cpu, sPointer, 0); sPointer += 4; for (bitsRemaining = 32; bitsRemaining > 0; --bitsRemaining, bitstream <<= 1) { uint32_t next = (nPointer & ~1) + node.offset * 2 + 2; if (bitstream & 0x80000000) { // Go right if (node.rTerm) { - readBits = gba->cpu.memory.load8(&gba->cpu, next + 1, 0); + readBits = cpu->memory.load8(cpu, next + 1, 0); } else { nPointer = next + 1; - node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0); + node.packed = cpu->memory.load8(cpu, nPointer, 0); continue; } } else { // Go left if (node.lTerm) { - readBits = gba->cpu.memory.load8(&gba->cpu, next, 0); + readBits = cpu->memory.load8(cpu, next, 0); } else { nPointer = next; - node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0); + node.packed = cpu->memory.load8(cpu, nPointer, 0); continue; } }@@ -426,7 +433,7 @@
block |= (readBits & ((1 << bits) - 1)) << bitsSeen; bitsSeen += bits; nPointer = treeBase; - node.packed = gba->cpu.memory.load8(&gba->cpu, nPointer, 0); + node.packed = cpu->memory.load8(cpu, nPointer, 0); if (bitsSeen == 32) { bitsSeen = 0; *dPointer = block;@@ -443,8 +450,9 @@ }
} static void _unRl(struct GBA* gba, uint32_t source, uint8_t* dest) { + struct ARMCore* cpu = gba->cpu; source = source & 0xFFFFFFFC; - int remaining = (gba->cpu.memory.load32(&gba->cpu, source, 0) & 0xFFFFFF00) >> 8; + int remaining = (cpu->memory.load32(cpu, source, 0) & 0xFFFFFF00) >> 8; int padding = (4 - remaining) & 0x3; // We assume the signature byte (0x30) is correct int blockheader;@@ -452,12 +460,12 @@ int block;
uint32_t sPointer = source + 4; uint8_t* dPointer = dest; while (remaining > 0) { - blockheader = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); + blockheader = cpu->memory.loadU8(cpu, sPointer++, 0); if (blockheader & 0x80) { // Compressed blockheader &= 0x7F; blockheader += 3; - block = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); + block = cpu->memory.loadU8(cpu, sPointer++, 0); while (blockheader-- && remaining) { --remaining; *dPointer = block;@@ -468,7 +476,7 @@ // Uncompressed
blockheader++; while (blockheader-- && remaining) { --remaining; - *dPointer = gba->cpu.memory.loadU8(&gba->cpu, sPointer++, 0); + *dPointer = cpu->memory.loadU8(cpu, sPointer++, 0); ++dPointer; } }
@@ -19,14 +19,15 @@ static const char GBA_ROM_WAITSTATES_SEQ[] = { 2, 1, 4, 1, 8, 1 };
static const int DMA_OFFSET[] = { 1, -1, 0, 1 }; void GBAMemoryInit(struct GBA* gba) { - gba->cpu.memory.load32 = GBALoad32; - gba->cpu.memory.load16 = GBALoad16; - gba->cpu.memory.loadU16 = GBALoadU16; - gba->cpu.memory.load8 = GBALoad8; - gba->cpu.memory.loadU8 = GBALoadU8; - gba->cpu.memory.store32 = GBAStore32; - gba->cpu.memory.store16 = GBAStore16; - gba->cpu.memory.store8 = GBAStore8; + struct ARMCore* cpu = gba->cpu; + cpu->memory.load32 = GBALoad32; + cpu->memory.load16 = GBALoad16; + cpu->memory.loadU16 = GBALoadU16; + cpu->memory.load8 = GBALoad8; + cpu->memory.loadU8 = GBALoadU8; + cpu->memory.store32 = GBAStore32; + cpu->memory.store16 = GBAStore16; + cpu->memory.store8 = GBAStore8; gba->memory.bios = (uint32_t*) hleBios; gba->memory.fullBios = 0;@@ -69,13 +70,13 @@ gba->memory.waitstatesPrefetch32[i] = 0;
} gba->memory.activeRegion = -1; - gba->cpu.memory.activeRegion = 0; - gba->cpu.memory.activeMask = 0; - gba->cpu.memory.setActiveRegion = GBASetActiveRegion; - gba->cpu.memory.activePrefetchCycles32 = 0; - gba->cpu.memory.activePrefetchCycles16 = 0; + cpu->memory.activeRegion = 0; + cpu->memory.activeMask = 0; + cpu->memory.setActiveRegion = GBASetActiveRegion; + cpu->memory.activePrefetchCycles32 = 0; + cpu->memory.activePrefetchCycles16 = 0; gba->memory.biosPrefetch = 0; - gba->cpu.memory.waitMultiple = GBAWaitMultiple; + cpu->memory.waitMultiple = GBAWaitMultiple; } void GBAMemoryDeinit(struct GBA* gba) {@@ -85,7 +86,7 @@ GBASavedataDeinit(&gba->memory.savedata);
} static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int newRegion = address >> BASE_OFFSET;@@ -131,7 +132,7 @@ }
} int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; uint32_t value = 0; int wait = 0;@@ -185,9 +186,9 @@ break;
default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); if (cpu->executionMode == MODE_ARM) { - value = cpu->memory.load32(&gba->cpu, cpu->currentPC + WORD_SIZE_ARM * 2, 0); + value = cpu->memory.load32(cpu, cpu->currentPC + WORD_SIZE_ARM * 2, 0); } else { - value = cpu->memory.load16(&gba->cpu, cpu->currentPC + WORD_SIZE_THUMB * 2, 0); + value = cpu->memory.load16(cpu, cpu->currentPC + WORD_SIZE_THUMB * 2, 0); value |= value << 16; } break;@@ -207,7 +208,7 @@ return GBALoad16(cpu, address, cycleCounter);
} int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; uint16_t value = 0; int wait = 0;@@ -267,7 +268,7 @@ GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load16: 0x%08X", address);
break; default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address); - value = cpu->memory.load16(&gba->cpu, cpu->currentPC + (cpu->executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0); + value = cpu->memory.load16(cpu, cpu->currentPC + (cpu->executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0); break; }@@ -284,7 +285,7 @@ return GBALoad8(cpu, address, cycleCounter);
} int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int8_t value = 0; int wait = 0;@@ -356,7 +357,7 @@ return value;
} void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int wait = 0;@@ -404,7 +405,7 @@ }
} void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int wait = 0;@@ -461,7 +462,7 @@ }
} void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int wait = 0;@@ -521,7 +522,7 @@ }
} static int GBAWaitMultiple(struct ARMCore* cpu, uint32_t startAddress, int count) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int wait = 1 + memory->waitstates32[startAddress >> BASE_OFFSET]; wait += (1 + memory->waitstatesSeq32[startAddress >> BASE_OFFSET]) * (count - 1);@@ -530,6 +531,7 @@ }
void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) { struct GBAMemory* memory = &gba->memory; + struct ARMCore* cpu = gba->cpu; int sram = parameters & 0x0003; int ws0 = (parameters & 0x000C) >> 2; int ws0seq = (parameters & 0x0010) >> 4;@@ -578,10 +580,10 @@ memory->waitstatesPrefetch32[REGION_CART1] = memory->waitstatesPrefetch32[REGION_CART1_EX] = 0;
memory->waitstatesPrefetch32[REGION_CART2] = memory->waitstatesPrefetch32[REGION_CART2_EX] = 0; } - gba->cpu.memory.activePrefetchCycles32 = memory->waitstatesPrefetch32[memory->activeRegion]; - gba->cpu.memory.activePrefetchCycles16 = memory->waitstatesPrefetch16[memory->activeRegion]; - gba->cpu.memory.activeNonseqCycles32 = memory->waitstates32[memory->activeRegion]; - gba->cpu.memory.activeNonseqCycles16 = memory->waitstates16[memory->activeRegion]; + cpu->memory.activePrefetchCycles32 = memory->waitstatesPrefetch32[memory->activeRegion]; + cpu->memory.activePrefetchCycles16 = memory->waitstatesPrefetch16[memory->activeRegion]; + cpu->memory.activeNonseqCycles32 = memory->waitstates32[memory->activeRegion]; + cpu->memory.activeNonseqCycles16 = memory->waitstates16[memory->activeRegion]; } void GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address) {@@ -620,9 +622,10 @@ return currentDma->packed;
}; void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) { + struct ARMCore* cpu = gba->cpu; switch (info->timing) { case DMA_TIMING_NOW: - info->nextEvent = gba->cpu.cycles; + info->nextEvent = cpu->cycles; GBAMemoryUpdateDMAs(gba, 0); break; case DMA_TIMING_HBLANK:@@ -695,6 +698,7 @@
void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) { int i; struct GBAMemory* memory = &gba->memory; + struct ARMCore* cpu = gba->cpu; memory->activeDMA = -1; memory->nextDMA = INT_MAX; for (i = 3; i >= 0; --i) {@@ -707,13 +711,14 @@ memory->nextDMA = dma->nextEvent;
} } } - if (memory->nextDMA < gba->cpu.nextEvent) { - gba->cpu.nextEvent = memory->nextDMA; + if (memory->nextDMA < cpu->nextEvent) { + cpu->nextEvent = memory->nextDMA; } } void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) { struct GBAMemory* memory = &gba->memory; + struct ARMCore* cpu = gba->cpu; uint32_t width = info->width ? 4 : 2; int sourceOffset = DMA_OFFSET[info->srcControl] * width; int destOffset = DMA_OFFSET[info->dstControl] * width;@@ -744,8 +749,8 @@ }
if (width == 4) { int32_t word; - word = gba->cpu.memory.load32(&gba->cpu, source, 0); - gba->cpu.memory.store32(&gba->cpu, dest, word, 0); + word = cpu->memory.load32(cpu, source, 0); + cpu->memory.store32(cpu, dest, word, 0); source += sourceOffset; dest += destOffset; --wordsRemaining;@@ -753,7 +758,7 @@ } else {
uint16_t word; if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) { word = GBASavedataReadEEPROM(&memory->savedata); - gba->cpu.memory.store16(&gba->cpu, dest, word, 0); + cpu->memory.store16(cpu, dest, word, 0); source += sourceOffset; dest += destOffset; --wordsRemaining;@@ -761,14 +766,14 @@ } else if (destRegion == REGION_CART2_EX) {
if (memory->savedata.type == SAVEDATA_NONE) { GBASavedataInitEEPROM(&memory->savedata); } - word = gba->cpu.memory.load16(&gba->cpu, source, 0); + word = cpu->memory.load16(cpu, source, 0); GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining); source += sourceOffset; dest += destOffset; --wordsRemaining; } else { - word = gba->cpu.memory.load16(&gba->cpu, source, 0); - gba->cpu.memory.store16(&gba->cpu, dest, word, 0); + word = cpu->memory.load16(cpu, source, 0); + cpu->memory.store16(cpu, dest, word, 0); source += sourceOffset; dest += destOffset; --wordsRemaining;@@ -804,7 +809,7 @@ if (memory->dma[i].nextEvent != INT_MAX) {
memory->dma[i].nextEvent += cycles; } } - gba->cpu.cycles += cycles; + cpu->cycles += cycles; } void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state) {
@@ -16,13 +16,13 @@ state->biosChecksum = gba->biosChecksum;
state->id = ((struct GBACartridge*) gba->memory.rom)->id; memcpy(state->title, ((struct GBACartridge*) gba->memory.rom)->title, sizeof(state->title)); - memcpy(state->cpu.gprs, gba->cpu.gprs, sizeof(state->cpu.gprs)); - state->cpu.cpsr = gba->cpu.cpsr; - state->cpu.spsr = gba->cpu.spsr; - state->cpu.cycles = gba->cpu.cycles; - state->cpu.nextEvent = gba->cpu.nextEvent; - memcpy(state->cpu.bankedRegisters, gba->cpu.bankedRegisters, 6 * 7 * sizeof(int32_t)); - memcpy(state->cpu.bankedSPSRs, gba->cpu.bankedSPSRs, 6 * sizeof(int32_t)); + memcpy(state->cpu.gprs, gba->cpu->gprs, sizeof(state->cpu.gprs)); + state->cpu.cpsr = gba->cpu->cpsr; + state->cpu.spsr = gba->cpu->spsr; + state->cpu.cycles = gba->cpu->cycles; + state->cpu.nextEvent = gba->cpu->nextEvent; + memcpy(state->cpu.bankedRegisters, gba->cpu->bankedRegisters, 6 * 7 * sizeof(int32_t)); + memcpy(state->cpu.bankedSPSRs, gba->cpu->bankedSPSRs, 6 * sizeof(int32_t)); GBAMemorySerialize(&gba->memory, state); GBAIOSerialize(gba, state);@@ -43,16 +43,16 @@ if (state->id != ((struct GBACartridge*) gba->memory.rom)->id || memcmp(state->title, ((struct GBACartridge*) gba->memory.rom)->title, sizeof(state->title))) {
GBALog(gba, GBA_LOG_WARN, "Savestate is for a different game"); return; } - memcpy(gba->cpu.gprs, state->cpu.gprs, sizeof(gba->cpu.gprs)); - gba->cpu.cpsr = state->cpu.cpsr; - gba->cpu.spsr = state->cpu.spsr; - gba->cpu.cycles = state->cpu.cycles; - gba->cpu.nextEvent = state->cpu.nextEvent; - memcpy(gba->cpu.bankedRegisters, state->cpu.bankedRegisters, 6 * 7 * sizeof(int32_t)); - memcpy(gba->cpu.bankedSPSRs, state->cpu.bankedSPSRs, 6 * sizeof(int32_t)); - gba->cpu.executionMode = gba->cpu.cpsr.t ? MODE_THUMB : MODE_ARM; - gba->cpu.privilegeMode = gba->cpu.cpsr.priv; - gba->cpu.memory.setActiveRegion(&gba->cpu, gba->cpu.gprs[ARM_PC]); + memcpy(gba->cpu->gprs, state->cpu.gprs, sizeof(gba->cpu->gprs)); + gba->cpu->cpsr = state->cpu.cpsr; + gba->cpu->spsr = state->cpu.spsr; + gba->cpu->cycles = state->cpu.cycles; + gba->cpu->nextEvent = state->cpu.nextEvent; + memcpy(gba->cpu->bankedRegisters, state->cpu.bankedRegisters, 6 * 7 * sizeof(int32_t)); + memcpy(gba->cpu->bankedSPSRs, state->cpu.bankedSPSRs, 6 * sizeof(int32_t)); + gba->cpu->executionMode = gba->cpu->cpsr.t ? MODE_THUMB : MODE_ARM; + gba->cpu->privilegeMode = gba->cpu->cpsr.priv; + gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]); GBAMemoryDeserialize(&gba->memory, state); GBAIODeserialize(gba, state);
@@ -51,9 +51,17 @@ InitOnceExecuteOnce(&_contextOnce, _createTLS, NULL, 0);
#endif struct GBA gba; + struct ARMCore cpu; struct GBAThread* threadContext = context; + struct ARMComponent* components[1] = {}; + int numComponents = 0; char* savedata = 0; + if (threadContext->debugger) { + components[numComponents] = &threadContext->debugger->d; + ++numComponents; + } + #if !defined(_WIN32) && defined(USE_PTHREADS) sigset_t signals; sigemptyset(&signals);@@ -61,7 +69,10 @@ pthread_sigmask(SIG_SETMASK, &signals, 0);
#endif gba.logHandler = threadContext->logHandler; - GBAInit(&gba); + GBACreate(&gba); + ARMSetComponents(&cpu, &gba.d, numComponents, components); + ARMInit(&cpu); + ARMReset(&cpu); threadContext->gba = &gba; gba.sync = &threadContext->sync; #ifdef USE_PTHREADS@@ -124,7 +135,7 @@ _changeState(threadContext, THREAD_EXITING, 0);
} } else { while (threadContext->state == THREAD_RUNNING) { - ARMRun(&gba.cpu); + ARMRun(&cpu); } } MutexLock(&threadContext->stateMutex);@@ -143,7 +154,7 @@ threadContext->cleanCallback(threadContext);
} threadContext->gba = 0; - GBADeinit(&gba); + GBADestroy(&gba); ConditionWake(&threadContext->sync.videoFrameAvailableCond); ConditionWake(&threadContext->sync.audioRequiredCond);
@@ -37,6 +37,7 @@ struct GBAThread {
// Output enum ThreadState state; struct GBA* gba; + struct ARMCore* cpu; // Input struct GBAVideoRenderer* renderer;
@@ -207,10 +207,10 @@ void GBAVideoDeserialize(struct GBAVideo* video, struct GBASerializedState* state) {
memcpy(video->renderer->vram, state->vram, SIZE_VRAM); int i; for (i = 0; i < SIZE_OAM; i += 2) { - GBAStore16(&video->p->cpu, BASE_OAM | i, state->oam[i >> 1], 0); + GBAStore16(video->p->cpu, BASE_OAM | i, state->oam[i >> 1], 0); } for (i = 0; i < SIZE_PALETTE_RAM; i += 2) { - GBAStore16(&video->p->cpu, BASE_PALETTE_RAM | i, state->pram[i >> 1], 0); + GBAStore16(video->p->cpu, BASE_PALETTE_RAM | i, state->pram[i >> 1], 0); } union GBARegisterDISPSTAT dispstat; dispstat.packed = state->io[REG_DISPSTAT >> 1];
@@ -7,11 +7,10 @@ #include "gba-thread.h"
#include "util/memory.h" -#include "debugger/debugger.h" - #include <sys/stat.h> const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000; +const uint32_t GBA_COMPONENT_MAGIC = 0x1000000; enum { SP_BASE_SYSTEM = 0x03FFFF00,@@ -91,6 +90,8 @@
{ { 0, 0, 0, 0 }, 0, 0 } }; +static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component); +static void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh); static void GBAProcessEvents(struct ARMCore* cpu); static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles); static void GBAHitStub(struct ARMCore* cpu, uint32_t opcode);@@ -98,14 +99,19 @@ static void GBAIllegal(struct ARMCore* cpu, uint32_t opcode);
static void _checkOverrides(struct GBA* gba, uint32_t code); -void GBAInit(struct GBA* gba) { +void GBACreate(struct GBA* gba) { + gba->d.id = GBA_COMPONENT_MAGIC; + gba->d.init = GBAInit; +} + +static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component) { + struct GBA* gba = (struct GBA*) component; + gba->cpu = cpu; gba->debugger = 0; gba->savefile = 0; - ARMInit(&gba->cpu); - + GBAInterruptHandlerInit(&cpu->irqh); GBAMemoryInit(gba); - GBABoardInit(&gba->cpu.board); gba->video.p = gba; GBAVideoInit(&gba->video);@@ -129,27 +135,25 @@
gba->logLevel = GBA_LOG_INFO | GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL; gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS); - - ARMReset(&gba->cpu); } -void GBADeinit(struct GBA* gba) { +void GBADestroy(struct GBA* gba) { GBAMemoryDeinit(gba); GBAVideoDeinit(&gba->video); GBAAudioDeinit(&gba->audio); } -void GBABoardInit(struct ARMBoard* board) { - board->reset = GBABoardReset; - board->processEvents = GBAProcessEvents; - board->swi16 = GBASwi16; - board->swi32 = GBASwi32; - board->hitIllegal = GBAIllegal; - board->readCPSR = GBATestIRQ; - board->hitStub = GBAHitStub; +void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh) { + irqh->reset = GBAReset; + irqh->processEvents = GBAProcessEvents; + irqh->swi16 = GBASwi16; + irqh->swi32 = GBASwi32; + irqh->hitIllegal = GBAIllegal; + irqh->readCPSR = GBATestIRQ; + irqh->hitStub = GBAHitStub; } -void GBABoardReset(struct ARMCore* cpu) { +void GBAReset(struct ARMCore* cpu) { ARMSetPrivilegeMode(cpu, MODE_IRQ); cpu->gprs[ARM_SP] = SP_BASE_IRQ; ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);@@ -160,7 +164,7 @@ }
static void GBAProcessEvents(struct ARMCore* cpu) { do { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; int32_t cycles = cpu->cycles; int32_t nextEvent = INT_MAX; int32_t testEvent;@@ -346,12 +350,10 @@ return nextEvent;
} void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger) { - ARMDebuggerInit(debugger, &gba->cpu); gba->debugger = debugger; } void GBADetachDebugger(struct GBA* gba) { - ARMDebuggerDeinit(gba->debugger); gba->debugger = 0; }@@ -382,8 +384,8 @@ } else {
GBALog(gba, GBA_LOG_WARN, "BIOS checksum incorrect"); } gba->biosChecksum = checksum; - if ((gba->cpu.gprs[ARM_PC] >> BASE_OFFSET) == BASE_BIOS) { - gba->cpu.memory.setActiveRegion(&gba->cpu, gba->cpu.gprs[ARM_PC]); + if ((gba->cpu->gprs[ARM_PC] >> BASE_OFFSET) == BASE_BIOS) { + gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]); } // TODO: error check }@@ -391,7 +393,7 @@
void GBATimerUpdateRegister(struct GBA* gba, int timer) { struct GBATimer* currentTimer = &gba->timers[timer]; if (currentTimer->enable && !currentTimer->countUp) { - gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((gba->cpu.cycles - currentTimer->lastEvent) >> currentTimer->prescaleBits); + gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((gba->cpu->cycles - currentTimer->lastEvent) >> currentTimer->prescaleBits); } }@@ -425,7 +427,7 @@ int wasEnabled = currentTimer->enable;
currentTimer->enable = !!(control & 0x0080); if (!wasEnabled && currentTimer->enable) { if (!currentTimer->countUp) { - currentTimer->nextEvent = gba->cpu.cycles + currentTimer->overflowInterval; + currentTimer->nextEvent = gba->cpu->cycles + currentTimer->overflowInterval; } else { currentTimer->nextEvent = INT_MAX; }@@ -434,7 +436,7 @@ currentTimer->oldReload = currentTimer->reload;
gba->timersEnabled |= 1 << timer; } else if (wasEnabled && !currentTimer->enable) { if (!currentTimer->countUp) { - gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((gba->cpu.cycles - currentTimer->lastEvent) >> oldPrescale); + gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((gba->cpu->cycles - currentTimer->lastEvent) >> oldPrescale); } gba->timersEnabled &= ~(1 << timer); } else if (currentTimer->prescaleBits != oldPrescale && !currentTimer->countUp) {@@ -442,8 +444,8 @@ // FIXME: this might be before present
currentTimer->nextEvent = currentTimer->lastEvent + currentTimer->overflowInterval; } - if (currentTimer->nextEvent < gba->cpu.nextEvent) { - gba->cpu.nextEvent = currentTimer->nextEvent; + if (currentTimer->nextEvent < gba->cpu->nextEvent) { + gba->cpu->nextEvent = currentTimer->nextEvent; } };@@ -457,36 +459,36 @@ GBALog(gba, GBA_LOG_STUB, "Gamepak interrupts not implemented");
} if (gba->memory.io[REG_IME >> 1] && value & gba->memory.io[REG_IF >> 1]) { - ARMRaiseIRQ(&gba->cpu); + ARMRaiseIRQ(gba->cpu); } } void GBAWriteIME(struct GBA* gba, uint16_t value) { if (value && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) { - ARMRaiseIRQ(&gba->cpu); + ARMRaiseIRQ(gba->cpu); } } void GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq) { gba->memory.io[REG_IF >> 1] |= 1 << irq; - gba->cpu.halted = 0; + gba->cpu->halted = 0; if (gba->memory.io[REG_IME >> 1] && (gba->memory.io[REG_IE >> 1] & 1 << irq)) { - ARMRaiseIRQ(&gba->cpu); + ARMRaiseIRQ(gba->cpu); } } void GBATestIRQ(struct ARMCore* cpu) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; if (gba->memory.io[REG_IME >> 1] && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) { gba->springIRQ = 1; - gba->cpu.nextEvent = 0; + gba->cpu->nextEvent = 0; } } void GBAHalt(struct GBA* gba) { - gba->cpu.nextEvent = 0; - gba->cpu.halted = 1; + gba->cpu->nextEvent = 0; + gba->cpu->halted = 1; } static void _GBAVLog(struct GBA* gba, enum GBALogLevel level, const char* format, va_list args) {@@ -524,7 +526,7 @@
void GBADebuggerLogShim(struct ARMDebugger* debugger, enum DebuggerLogLevel level, const char* format, ...) { struct GBA* gba = 0; if (debugger->cpu) { - gba = (struct GBA*) debugger->cpu; + gba = (struct GBA*) debugger->cpu->master; } enum GBALogLevel gbaLevel;@@ -560,7 +562,7 @@ GBALog(gba, level, "Stub opcode: %08x", opcode);
} void GBAIllegal(struct ARMCore* cpu, uint32_t opcode) { - struct GBA* gba = (struct GBA*) cpu; + struct GBA* gba = (struct GBA*) cpu->master; GBALog(gba, GBA_LOG_WARN, "Illegal opcode: %08x", opcode); if (gba->debugger) { ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP);
@@ -65,7 +65,9 @@ struct GBA;
typedef void (*GBALogHandler)(struct GBA*, enum GBALogLevel, const char* format, va_list args); struct GBA { - struct ARMCore cpu; + struct ARMComponent d; + + struct ARMCore* cpu; struct GBAMemory memory; struct GBAVideo video; struct GBAAudio audio;@@ -116,11 +118,11 @@ uint8_t checksum;
// And ROM data... }; -void GBAInit(struct GBA* gba); -void GBADeinit(struct GBA* gba); +void GBACreate(struct GBA* gba); +void GBADestroy(struct GBA* gba); -void GBABoardInit(struct ARMBoard* board); -void GBABoardReset(struct ARMCore* cpu); +void GBABInterruptHandlerInit(struct ARMInterruptHandler* board); +void GBAReset(struct ARMCore* cpu); void GBATimerUpdateRegister(struct GBA* gba, int timer); void GBATimerWriteTMCNT_LO(struct GBA* gba, int timer, uint16_t value);