all repos — mgba @ fc7aec557b4ec3f44c370a30a99116081551dd0d

mGBA Game Boy Advance Emulator

Count cycles for load/store singles
Jeffrey Pfau jeffrey@endrift.com
Sat, 04 May 2013 23:57:12 -0700
commit

fc7aec557b4ec3f44c370a30a99116081551dd0d

parent

738b3dc44e1d8f7eb3179b0b07c85bae7dc4123b

M src/arm/arm.csrc/arm/arm.c

@@ -100,9 +100,6 @@ cpu->privilegeMode = MODE_SYSTEM;

cpu->cpsr.packed = MODE_SYSTEM; cpu->spsr.packed = 0; - cpu->cycles = 0; - cpu->nextEvent = 0; - cpu->shifterOperand = 0; cpu->shifterCarryOut = 0;

@@ -110,6 +107,9 @@ cpu->executionMode = MODE_THUMB;

_ARMSetMode(cpu, MODE_ARM); ARM_WRITE_PC; + + cpu->cycles = 0; + cpu->nextEvent = 0; cpu->board->reset(cpu->board); }
M src/arm/arm.hsrc/arm/arm.h

@@ -67,15 +67,15 @@ int32_t packed;

}; struct ARMMemory { - int32_t (*load32)(struct ARMMemory*, uint32_t address); - int16_t (*load16)(struct ARMMemory*, uint32_t address); - uint16_t (*loadU16)(struct ARMMemory*, uint32_t address); - int8_t (*load8)(struct ARMMemory*, uint32_t address); - uint8_t (*loadU8)(struct ARMMemory*, uint32_t address); + int32_t (*load32)(struct ARMMemory*, uint32_t address, int* cycleCounter); + int16_t (*load16)(struct ARMMemory*, uint32_t address, int* cycleCounter); + uint16_t (*loadU16)(struct ARMMemory*, uint32_t address, int* cycleCounter); + int8_t (*load8)(struct ARMMemory*, uint32_t address, int* cycleCounter); + uint8_t (*loadU8)(struct ARMMemory*, uint32_t address, int* cycleCounter); - void (*store32)(struct ARMMemory*, uint32_t address, int32_t value); - void (*store16)(struct ARMMemory*, uint32_t address, int16_t value); - void (*store8)(struct ARMMemory*, uint32_t address, int8_t value); + void (*store32)(struct ARMMemory*, uint32_t address, int32_t value, int* cycleCounter); + void (*store16)(struct ARMMemory*, uint32_t address, int16_t value, int* cycleCounter); + void (*store8)(struct ARMMemory*, uint32_t address, int8_t value, int* cycleCounter); uint32_t* activeRegion; uint32_t activeMask;
M src/arm/isa-arm.csrc/arm/isa-arm.c

@@ -358,8 +358,8 @@ }

#define DEFINE_INSTRUCTION_ARM(NAME, BODY) \ static void _ARMInstruction ## NAME (struct ARMCore* cpu, uint32_t opcode) { \ - BODY; \ cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; \ + BODY; \ } #define DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, S_BODY, SHIFTER, BODY) \

@@ -643,48 +643,48 @@ // End multiply definitions

// Begin load/store definitions -DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDR, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, address); ARM_LOAD_POST_BODY;) -DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDRB, cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, address); ARM_LOAD_POST_BODY;) -DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRH, cpu->gprs[rd] = cpu->memory->loadU16(cpu->memory, address); ARM_LOAD_POST_BODY;) -DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSB, cpu->gprs[rd] = cpu->memory->load8(cpu->memory, address); ARM_LOAD_POST_BODY;) -DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSH, cpu->gprs[rd] = cpu->memory->load16(cpu->memory, address); ARM_LOAD_POST_BODY;) -DEFINE_LOAD_STORE_INSTRUCTION_ARM(STR, cpu->memory->store32(cpu->memory, address, cpu->gprs[rd])) -DEFINE_LOAD_STORE_INSTRUCTION_ARM(STRB, cpu->memory->store8(cpu->memory, address, cpu->gprs[rd])) -DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(STRH, cpu->memory->store16(cpu->memory, address, cpu->gprs[rd])) +DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDR, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, address, &cpu->cycles); ARM_LOAD_POST_BODY;) +DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDRB, cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, address, &cpu->cycles); ARM_LOAD_POST_BODY;) +DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRH, cpu->gprs[rd] = cpu->memory->loadU16(cpu->memory, address, &cpu->cycles); ARM_LOAD_POST_BODY;) +DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSB, cpu->gprs[rd] = cpu->memory->load8(cpu->memory, address, &cpu->cycles); ARM_LOAD_POST_BODY;) +DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSH, cpu->gprs[rd] = cpu->memory->load16(cpu->memory, address, &cpu->cycles); ARM_LOAD_POST_BODY;) +DEFINE_LOAD_STORE_INSTRUCTION_ARM(STR, cpu->memory->store32(cpu->memory, address, cpu->gprs[rd], &cpu->cycles)) +DEFINE_LOAD_STORE_INSTRUCTION_ARM(STRB, cpu->memory->store8(cpu->memory, address, cpu->gprs[rd], &cpu->cycles)) +DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(STRH, cpu->memory->store16(cpu->memory, address, cpu->gprs[rd], &cpu->cycles)) DEFINE_LOAD_STORE_T_INSTRUCTION_ARM(LDRBT, enum PrivilegeMode priv = cpu->privilegeMode; ARMSetPrivilegeMode(cpu, MODE_USER); - cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, address); + cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, address, &cpu->cycles); ARMSetPrivilegeMode(cpu, priv); ARM_LOAD_POST_BODY;) DEFINE_LOAD_STORE_T_INSTRUCTION_ARM(LDRT, enum PrivilegeMode priv = cpu->privilegeMode; ARMSetPrivilegeMode(cpu, MODE_USER); - cpu->gprs[rd] = cpu->memory->load32(cpu->memory, address); + cpu->gprs[rd] = cpu->memory->load32(cpu->memory, address, &cpu->cycles); ARMSetPrivilegeMode(cpu, priv); ARM_LOAD_POST_BODY;) DEFINE_LOAD_STORE_T_INSTRUCTION_ARM(STRBT, enum PrivilegeMode priv = cpu->privilegeMode; ARMSetPrivilegeMode(cpu, MODE_USER); - cpu->memory->store32(cpu->memory, address, cpu->gprs[rd]); + cpu->memory->store32(cpu->memory, address, cpu->gprs[rd], &cpu->cycles); ARMSetPrivilegeMode(cpu, priv);) DEFINE_LOAD_STORE_T_INSTRUCTION_ARM(STRT, enum PrivilegeMode priv = cpu->privilegeMode; ARMSetPrivilegeMode(cpu, MODE_USER); - cpu->memory->store8(cpu->memory, address, cpu->gprs[rd]); + cpu->memory->store8(cpu->memory, address, cpu->gprs[rd], &cpu->cycles); ARMSetPrivilegeMode(cpu, priv);) DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(LDM, - cpu->gprs[i] = cpu->memory->load32(cpu->memory, addr);, + cpu->gprs[i] = cpu->memory->load32(cpu->memory, addr, 0);, if (rs & 0x8000) { ARM_WRITE_PC; }) -DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(STM, cpu->memory->store32(cpu->memory, addr, cpu->gprs[i]);, ) +DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(STM, cpu->memory->store32(cpu->memory, addr, cpu->gprs[i], 0);, ) DEFINE_INSTRUCTION_ARM(SWP, ARM_STUB) DEFINE_INSTRUCTION_ARM(SWPB, ARM_STUB)
M src/arm/isa-inlines.hsrc/arm/isa-inlines.h

@@ -56,11 +56,15 @@ #define ARM_STUB cpu->board->hitStub(cpu->board, opcode)

#define ARM_WRITE_PC \ cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM) + WORD_SIZE_ARM; \ - cpu->memory->setActiveRegion(cpu->memory, cpu->gprs[ARM_PC]); + cpu->memory->setActiveRegion(cpu->memory, cpu->gprs[ARM_PC]); \ + cpu->memory->loadU16(cpu->memory, cpu->gprs[ARM_PC], &cpu->cycles); \ + cpu->cycles += 2 + cpu->memory->activePrefetchCycles32; #define THUMB_WRITE_PC \ cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_THUMB) + WORD_SIZE_THUMB; \ - cpu->memory->setActiveRegion(cpu->memory, cpu->gprs[ARM_PC]); + cpu->memory->setActiveRegion(cpu->memory, cpu->gprs[ARM_PC]); \ + cpu->memory->load32(cpu->memory, cpu->gprs[ARM_PC], &cpu->cycles); \ + cpu->cycles += 2 + cpu->memory->activePrefetchCycles16; static inline int _ARMModeHasSPSR(enum PrivilegeMode mode) { return mode != MODE_SYSTEM && mode != MODE_USER;
M src/arm/isa-thumb.csrc/arm/isa-thumb.c

@@ -94,8 +94,8 @@ EMITTER(PREFIX ## 1F, 31, __VA_ARGS__) \

#define DEFINE_INSTRUCTION_THUMB(NAME, BODY) \ static void _ThumbInstruction ## NAME (struct ARMCore* cpu, uint16_t opcode) { \ - BODY; \ cpu->cycles += 1 + cpu->memory->activePrefetchCycles16; \ + BODY; \ } #define DEFINE_IMMEDIATE_5_INSTRUCTION_EX_THUMB(NAME, IMMEDIATE, BODY) \

@@ -141,12 +141,12 @@ cpu->gprs[rd] = cpu->gprs[rm] >> immediate;

} THUMB_NEUTRAL_S( , , cpu->gprs[rd]);) -DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LDR1, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, cpu->gprs[rm] + immediate * 4)) -DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LDRB1, cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, cpu->gprs[rm] + immediate)) -DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LDRH1, cpu->gprs[rd] = cpu->memory->loadU16(cpu->memory, cpu->gprs[rm] + immediate * 2)) -DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(STR1, cpu->memory->store32(cpu->memory, cpu->gprs[rm] + immediate * 4, cpu->gprs[rd])) -DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(STRB1, cpu->memory->store8(cpu->memory, cpu->gprs[rm] + immediate, cpu->gprs[rd])) -DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(STRH1, cpu->memory->store16(cpu->memory, cpu->gprs[rm] + immediate * 2, cpu->gprs[rd])) +DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LDR1, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, cpu->gprs[rm] + immediate * 4, &cpu->cycles)) +DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LDRB1, cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, cpu->gprs[rm] + immediate, &cpu->cycles)) +DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LDRH1, cpu->gprs[rd] = cpu->memory->loadU16(cpu->memory, cpu->gprs[rm] + immediate * 2, &cpu->cycles)) +DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(STR1, cpu->memory->store32(cpu->memory, cpu->gprs[rm] + immediate * 4, cpu->gprs[rd], &cpu->cycles)) +DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(STRB1, cpu->memory->store8(cpu->memory, cpu->gprs[rm] + immediate, cpu->gprs[rd], &cpu->cycles)) +DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(STRH1, cpu->memory->store16(cpu->memory, cpu->gprs[rm] + immediate * 2, cpu->gprs[rd], &cpu->cycles)) #define DEFINE_DATA_FORM_1_INSTRUCTION_EX_THUMB(NAME, RM, BODY) \ DEFINE_INSTRUCTION_THUMB(NAME, \

@@ -313,9 +313,9 @@

#define DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(NAME, BODY) \ COUNT_3(DEFINE_IMMEDIATE_WITH_REGISTER_EX_THUMB, NAME ## _R, BODY) -DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR3, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, (cpu->gprs[ARM_PC] & 0xFFFFFFFC) + immediate)) -DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR4, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, cpu->gprs[ARM_SP] + immediate)) -DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(STR3, cpu->memory->store32(cpu->memory, cpu->gprs[ARM_SP] + immediate, cpu->gprs[rd])) +DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR3, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, (cpu->gprs[ARM_PC] & 0xFFFFFFFC) + immediate, &cpu->cycles)) +DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR4, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, cpu->gprs[ARM_SP] + immediate, &cpu->cycles)) +DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(STR3, cpu->memory->store32(cpu->memory, cpu->gprs[ARM_SP] + immediate, cpu->gprs[rd], &cpu->cycles)) DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD5, cpu->gprs[rd] = (cpu->gprs[ARM_PC] & 0xFFFFFFFC) + immediate) DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD6, cpu->gprs[rd] = cpu->gprs[ARM_SP] + immediate)

@@ -330,14 +330,14 @@

#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, BODY) \ COUNT_3(DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB, NAME ## _R, BODY) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm])) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm])) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, cpu->gprs[rd] = cpu->memory->loadU16(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm])) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, cpu->gprs[rd] = cpu->memory->load8(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm])) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, cpu->gprs[rd] = cpu->memory->load16(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm])) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, cpu->memory->store32(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd])) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, cpu->memory->store8(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd])) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, cpu->memory->store16(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd])) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, cpu->gprs[rd] = cpu->memory->load32(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], &cpu->cycles)) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, cpu->gprs[rd] = cpu->memory->loadU8(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], &cpu->cycles)) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, cpu->gprs[rd] = cpu->memory->loadU16(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], &cpu->cycles)) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, cpu->gprs[rd] = cpu->memory->load8(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], &cpu->cycles)) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, cpu->gprs[rd] = cpu->memory->load16(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], &cpu->cycles)) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, cpu->memory->store32(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd], &cpu->cycles)) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, cpu->memory->store8(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd], &cpu->cycles)) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, cpu->memory->store16(cpu->memory, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd], &cpu->cycles)) #define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, ADDRESS, LOOP, BODY, OP, PRE_BODY, POST_BODY, WRITEBACK) \ DEFINE_INSTRUCTION_THUMB(NAME, \

@@ -361,13 +361,13 @@ #define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME, BODY, WRITEBACK) \

COUNT_3(DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB, NAME ## _R, cpu->gprs[rn], (m = 0x01, i = 0; i < 8; m <<= 1, ++i), BODY, +=, , , WRITEBACK) DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDMIA, - cpu->gprs[i] = cpu->memory->load32(cpu->memory, address), + cpu->gprs[i] = cpu->memory->load32(cpu->memory, address, 0), if (!((1 << rn) & rs)) { cpu->gprs[rn] = address; }) DEFINE_LOAD_STORE_MULTIPLE_THUMB(STMIA, - cpu->memory->store32(cpu->memory, address, cpu->gprs[i]), + cpu->memory->store32(cpu->memory, address, cpu->gprs[i], 0), cpu->gprs[rn] = address) #define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \

@@ -400,7 +400,7 @@ DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP,

opcode & 0x00FF, cpu->gprs[ARM_SP], (m = 0x01, i = 0; i < 8; m <<= 1, ++i), - cpu->gprs[i] = cpu->memory->load32(cpu->memory, address), + cpu->gprs[i] = cpu->memory->load32(cpu->memory, address, 0), +=, , , cpu->gprs[ARM_SP] = address)

@@ -409,10 +409,10 @@ DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR,

opcode & 0x00FF, cpu->gprs[ARM_SP], (m = 0x01, i = 0; i < 8; m <<= 1, ++i), - cpu->gprs[i] = cpu->memory->load32(cpu->memory, address), + cpu->gprs[i] = cpu->memory->load32(cpu->memory, address, 0), +=, , - cpu->gprs[ARM_PC] = cpu->memory->load32(cpu->memory, address) & 0xFFFFFFFE; + cpu->gprs[ARM_PC] = cpu->memory->load32(cpu->memory, address, 0) & 0xFFFFFFFE; address += 4;, cpu->gprs[ARM_SP] = address; THUMB_WRITE_PC;)

@@ -421,7 +421,7 @@ DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH,

opcode & 0x00FF, cpu->gprs[ARM_SP] - 4, (m = 0x80, i = 7; m; m >>= 1, --i), - cpu->memory->store32(cpu->memory, address, cpu->gprs[i]), + cpu->memory->store32(cpu->memory, address, cpu->gprs[i], 0), -=, , , cpu->gprs[ARM_SP] = address + 4)

@@ -430,9 +430,9 @@ DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR,

opcode & 0x00FF, cpu->gprs[ARM_SP] - 4, (m = 0x80, i = 7; m; m >>= 1, --i), - cpu->memory->store32(cpu->memory, address, cpu->gprs[i]), + cpu->memory->store32(cpu->memory, address, cpu->gprs[i], 0), -=, - cpu->memory->store32(cpu->memory, address, cpu->gprs[ARM_LR]); + cpu->memory->store32(cpu->memory, address, cpu->gprs[ARM_LR], 0); address -= 4;, , cpu->gprs[ARM_SP] = address + 4)
M src/debugger/debugger.csrc/debugger/debugger.c

@@ -127,10 +127,10 @@

static inline void _printLine(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode) { // TODO: write a disassembler if (mode == MODE_ARM) { - uint32_t instruction = debugger->cpu->memory->load32(debugger->cpu->memory, address); + uint32_t instruction = debugger->cpu->memory->load32(debugger->cpu->memory, address, 0); printf("%08X\n", instruction); } else { - uint16_t instruction = debugger->cpu->memory->loadU16(debugger->cpu->memory, address); + uint16_t instruction = debugger->cpu->memory->loadU16(debugger->cpu->memory, address, 0); printf("%04X\n", instruction); } }

@@ -167,7 +167,7 @@ printf("%s\n", ERROR_MISSING_ARGS);

return; } uint32_t address = dv->intValue; - uint8_t value = debugger->cpu->memory->loadU8(debugger->cpu->memory, address); + uint8_t value = debugger->cpu->memory->loadU8(debugger->cpu->memory, address, 0); printf(" 0x%02X\n", value); }

@@ -177,7 +177,7 @@ printf("%s\n", ERROR_MISSING_ARGS);

return; } uint32_t address = dv->intValue; - uint16_t value = debugger->cpu->memory->loadU16(debugger->cpu->memory, address); + uint16_t value = debugger->cpu->memory->loadU16(debugger->cpu->memory, address, 0); printf(" 0x%04X\n", value); }

@@ -187,7 +187,7 @@ printf("%s\n", ERROR_MISSING_ARGS);

return; } uint32_t address = dv->intValue; - uint32_t value = debugger->cpu->memory->load32(debugger->cpu->memory, address); + uint32_t value = debugger->cpu->memory->load32(debugger->cpu->memory, address, 0); printf(" 0x%08X\n", value); }
M src/gba/gba-bios.csrc/gba/gba-bios.c

@@ -27,16 +27,16 @@ if (fill) {

if (wordsize == 4) { source &= 0xFFFFFFFC; dest &= 0xFFFFFFFC; - int32_t word = GBALoad32(&gba->memory.d, source); + int32_t word = GBALoad32(&gba->memory.d, source, 0); for (i = 0; i < count; ++i) { - GBAStore32(&gba->memory.d, dest + (i << 2), word); + GBAStore32(&gba->memory.d, dest + (i << 2), word, 0); } } else { source &= 0xFFFFFFFE; dest &= 0xFFFFFFFE; - uint16_t word = GBALoad16(&gba->memory.d, source); + uint16_t word = GBALoad16(&gba->memory.d, source, 0); for (i = 0; i < count; ++i) { - GBAStore16(&gba->memory.d, dest + (i << 1), word); + GBAStore16(&gba->memory.d, dest + (i << 1), word, 0); } } } else {

@@ -44,15 +44,15 @@ if (wordsize == 4) {

source &= 0xFFFFFFFC; dest &= 0xFFFFFFFC; for (i = 0; i < count; ++i) { - int32_t word = GBALoad32(&gba->memory.d, source + (i << 2)); - GBAStore32(&gba->memory.d, dest + (i << 2), word); + int32_t word = GBALoad32(&gba->memory.d, source + (i << 2), 0); + GBAStore32(&gba->memory.d, dest + (i << 2), word, 0); } } else { source &= 0xFFFFFFFE; dest &= 0xFFFFFFFE; for (i = 0; i < count; ++i) { - uint16_t word = GBALoad16(&gba->memory.d, source + (i << 1)); - GBAStore16(&gba->memory.d, dest + (i << 1), word); + uint16_t word = GBALoad16(&gba->memory.d, source + (i << 1), 0); + GBAStore16(&gba->memory.d, dest + (i << 1), word, 0); } } }

@@ -66,14 +66,14 @@ int count = mode & 0x000FFFFF;

count = ((count + 7) >> 3) << 3; int i; if (mode & 0x01000000) { - int32_t word = GBALoad32(&gba->memory.d, source); + int32_t word = GBALoad32(&gba->memory.d, source, 0); for (i = 0; i < count; ++i) { - GBAStore32(&gba->memory.d, dest + (i << 2), word); + GBAStore32(&gba->memory.d, dest + (i << 2), word, 0); } } else { for (i = 0; i < count; ++i) { - int32_t word = GBALoad32(&gba->memory.d, source + (i << 2)); - GBAStore32(&gba->memory.d, dest + (i << 2), word); + int32_t word = GBALoad32(&gba->memory.d, source + (i << 2), 0); + GBAStore32(&gba->memory.d, dest + (i << 2), word, 0); } } }

@@ -94,13 +94,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 = GBALoad32(&gba->memory.d, offset) / 256.f; - oy = GBALoad32(&gba->memory.d, offset + 4) / 256.f; - cx = GBALoad16(&gba->memory.d, offset + 8); - cy = GBALoad16(&gba->memory.d, offset + 10); - sx = GBALoad16(&gba->memory.d, offset + 12) / 256.f; - sy = GBALoad16(&gba->memory.d, offset + 14) / 256.f; - theta = (GBALoadU16(&gba->memory.d, offset + 16) >> 8) / 128.f * M_PI; + ox = GBALoad32(&gba->memory.d, offset, 0) / 256.f; + oy = GBALoad32(&gba->memory.d, offset + 4, 0) / 256.f; + cx = GBALoad16(&gba->memory.d, offset + 8, 0); + cy = GBALoad16(&gba->memory.d, offset + 10, 0); + sx = GBALoad16(&gba->memory.d, offset + 12, 0) / 256.f; + sy = GBALoad16(&gba->memory.d, offset + 14, 0) / 256.f; + theta = (GBALoadU16(&gba->memory.d, offset + 16, 0) >> 8) / 128.f * M_PI; offset += 20; // Rotation a = d = cosf(theta);

@@ -113,12 +113,12 @@ d *= sy;

// Translate rx = ox - (a * cx + b * cy); ry = oy - (c * cx + d * cy); - GBAStore16(&gba->memory.d, destination, a * 256); - GBAStore16(&gba->memory.d, destination + 2, b * 256); - GBAStore16(&gba->memory.d, destination + 4, c * 256); - GBAStore16(&gba->memory.d, destination + 6, d * 256); - GBAStore32(&gba->memory.d, destination + 8, rx * 256); - GBAStore32(&gba->memory.d, destination + 12, ry * 256); + GBAStore16(&gba->memory.d, destination, a * 256, 0); + GBAStore16(&gba->memory.d, destination + 2, b * 256, 0); + GBAStore16(&gba->memory.d, destination + 4, c * 256, 0); + GBAStore16(&gba->memory.d, destination + 6, d * 256, 0); + GBAStore32(&gba->memory.d, destination + 8, rx * 256, 0); + GBAStore32(&gba->memory.d, destination + 12, ry * 256, 0); destination += 16; } }

@@ -134,9 +134,9 @@ float a, b, c, d;

while (i--) { // [ sx 0 ] [ cos(theta) -sin(theta) ] [ A B ] // [ 0 sy ] * [ sin(theta) cos(theta) ] = [ C D ] - sx = GBALoad16(&gba->memory.d, offset) / 256.f; - sy = GBALoad16(&gba->memory.d, offset + 2) / 256.f; - theta = (GBALoadU16(&gba->memory.d, offset + 4) >> 8) / 128.f * M_PI; + sx = GBALoad16(&gba->memory.d, offset, 0) / 256.f; + sy = GBALoad16(&gba->memory.d, offset + 2, 0) / 256.f; + theta = (GBALoadU16(&gba->memory.d, offset + 4, 0) >> 8) / 128.f * M_PI; offset += 6; // Rotation a = d = cosf(theta);

@@ -146,16 +146,16 @@ a *= sx;

b *= -sx; c *= sy; d *= sy; - GBAStore16(&gba->memory.d, destination, a * 256); - GBAStore16(&gba->memory.d, destination + diff, b * 256); - GBAStore16(&gba->memory.d, destination + diff * 2, c * 256); - GBAStore16(&gba->memory.d, destination + diff * 3, d * 256); + GBAStore16(&gba->memory.d, destination, a * 256, 0); + GBAStore16(&gba->memory.d, destination + diff, b * 256, 0); + GBAStore16(&gba->memory.d, destination + diff * 2, c * 256, 0); + GBAStore16(&gba->memory.d, destination + diff * 3, d * 256, 0); destination += diff * 4; } } static void _MidiKey2Freq(struct GBA* gba) { - uint32_t key = GBALoad32(&gba->memory.d, gba->cpu.gprs[0] + 4); + uint32_t key = GBALoad32(&gba->memory.d, 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); }

@@ -246,7 +246,7 @@ GBASwi16(board, immediate >> 16);

} static void _unLz77(struct GBAMemory* memory, uint32_t source, uint8_t* dest) { - int remaining = (GBALoad32(&memory->d, source) & 0xFFFFFF00) >> 8; + int remaining = (GBALoad32(&memory->d, source, 0) & 0xFFFFFF00) >> 8; // We assume the signature byte (0x10) is correct int blockheader; uint32_t sPointer = source + 4;

@@ -259,7 +259,7 @@ while (remaining > 0) {

if (blocksRemaining) { if (blockheader & 0x80) { // Compressed - block = GBALoadU8(&memory->d, sPointer) | (GBALoadU8(&memory->d, sPointer + 1) << 8); + block = GBALoadU8(&memory->d, sPointer, 0) | (GBALoadU8(&memory->d, sPointer + 1, 0) << 8); sPointer += 2; disp = dPointer - (((block & 0x000F) << 8) | ((block & 0xFF00) >> 8)) - 1; bytes = ((block & 0x00F0) >> 4) + 3;

@@ -271,14 +271,14 @@ ++dPointer;

} } else { // Uncompressed - *dPointer = GBALoadU8(&memory->d, sPointer++); + *dPointer = GBALoadU8(&memory->d, sPointer++, 0); ++dPointer; --remaining; } blockheader <<= 1; --blocksRemaining; } else { - blockheader = GBALoadU8(&memory->d, sPointer++); + blockheader = GBALoadU8(&memory->d, sPointer++, 0); blocksRemaining = 8; } }
M src/gba/gba-memory.csrc/gba/gba-memory.c

@@ -12,7 +12,9 @@

static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t region); static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 }; +static const char GBA_BASE_WAITSTATES_32[16] = { 0, 0, 4, 0, 0, 0, 0, 0, 7, 7, 9, 9, 13, 13, 9 }; static const char GBA_BASE_WAITSTATES_SEQ[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4 }; +static const char GBA_BASE_WAITSTATES_SEQ_32[16] = { 0, 0, 4, 0, 0, 0, 0, 0, 5, 5, 9, 9, 17, 17, 9 }; static const char GBA_ROM_WAITSTATES[] = { 4, 3, 2, 8 }; static const char GBA_ROM_WAITSTATES_SEQ[] = { 2, 1, 4, 1, 8, 1 }; static const int DMA_OFFSET[] = { 1, -1, 0, 1 };

@@ -46,14 +48,18 @@ int i;

for (i = 0; i < 16; ++i) { memory->waitstates16[i] = GBA_BASE_WAITSTATES[i]; memory->waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i]; - memory->waitstates32[i] = GBA_BASE_WAITSTATES[i] + GBA_BASE_WAITSTATES_SEQ[i] + 1; - memory->waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ[i] + GBA_BASE_WAITSTATES_SEQ[i] + 1; + memory->waitstatesPrefetch16[i] = GBA_BASE_WAITSTATES_SEQ[i]; + memory->waitstates32[i] = GBA_BASE_WAITSTATES_32[i]; + memory->waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i]; + memory->waitstatesPrefetch32[i] = GBA_BASE_WAITSTATES_SEQ_32[i]; } for (; i < 256; ++i) { memory->waitstates16[i] = 0; memory->waitstatesSeq16[i] = 0; + memory->waitstatesPrefetch16[i] = 0; memory->waitstates32[i] = 0; memory->waitstatesSeq32[i] = 0; + memory->waitstatesPrefetch32[i] = 0; } memory->activeRegion = 0;

@@ -73,8 +79,8 @@

static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) { struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; - memory->activePrefetchCycles32 = gbaMemory->waitstates32[address >> BASE_OFFSET]; - memory->activePrefetchCycles16 = gbaMemory->waitstates16[address >> BASE_OFFSET]; + memory->activePrefetchCycles32 = gbaMemory->waitstatesPrefetch32[address >> BASE_OFFSET]; + memory->activePrefetchCycles16 = gbaMemory->waitstatesPrefetch16[address >> BASE_OFFSET]; gbaMemory->activeRegion = address >> BASE_OFFSET; switch (address & ~OFFSET_MASK) { case BASE_BIOS:

@@ -105,15 +111,17 @@ break;

} } -int32_t GBALoad32(struct ARMMemory* memory, uint32_t address) { +int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter) { struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; uint32_t value = 0; + int wait = 0; switch (address & ~OFFSET_MASK) { case BASE_BIOS: break; case BASE_WORKING_RAM: value = gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2]; + wait = gbaMemory->waitstates32[REGION_WORKING_RAM]; break; case BASE_WORKING_IRAM: value = gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2];

@@ -136,6 +144,7 @@ case BASE_CART1:

case BASE_CART1_EX: case BASE_CART2: case BASE_CART2_EX: + wait = gbaMemory->waitstates32[address >> BASE_OFFSET]; if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) { value = gbaMemory->rom[(address & (SIZE_CART0 - 1)) >> 2]; }

@@ -146,146 +155,98 @@ default:

break; } + + if (cycleCounter) { + *cycleCounter += wait; + } // Unaligned 32-bit loads are "rotated" so they make some semblance of sense int rotate = (address & 3) << 3; return (value >> rotate) | (value << (32 - rotate)); } -int16_t GBALoad16(struct ARMMemory* memory, uint32_t address) { - struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; - - switch (address & ~OFFSET_MASK) { - case BASE_BIOS: - break; - case BASE_WORKING_RAM: - return ((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1]; - case BASE_WORKING_IRAM: - return ((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1]; - case BASE_IO: - return GBAIORead(gbaMemory->p, address & (SIZE_IO - 1)); - case BASE_PALETTE_RAM: - return gbaMemory->p->video.palette[(address & (SIZE_PALETTE_RAM - 1)) >> 1]; - case BASE_VRAM: - return gbaMemory->p->video.vram[(address & 0x0001FFFF) >> 1]; - case BASE_OAM: - return gbaMemory->p->video.oam.raw[(address & (SIZE_OAM - 1)) >> 1]; - case BASE_CART0: - case BASE_CART0_EX: - case BASE_CART1: - case BASE_CART1_EX: - case BASE_CART2: - if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) { - return ((int16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1]; - } - case BASE_CART2_EX: - if (gbaMemory->savedata.type == SAVEDATA_EEPROM) { - return GBASavedataReadEEPROM(&gbaMemory->savedata); - } else if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) { - return ((uint16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1]; - } - case BASE_CART_SRAM: - break; - default: - break; - } - - return 0; +uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address, int* cycleCounter) { + return GBALoad16(memory, address, cycleCounter); } -uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address) { +int16_t GBALoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter) { struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + int16_t value = 0; + int wait = 0; switch (address & ~OFFSET_MASK) { case BASE_BIOS: break; case BASE_WORKING_RAM: - return ((uint16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1]; + value = ((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1]; + wait = gbaMemory->waitstates16[REGION_WORKING_RAM]; + break; case BASE_WORKING_IRAM: - return ((uint16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1]; + value = ((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1]; + break; case BASE_IO: - return GBAIORead(gbaMemory->p, address & (SIZE_IO - 1)); + value = GBAIORead(gbaMemory->p, address & (SIZE_IO - 1)); + break; case BASE_PALETTE_RAM: - return gbaMemory->p->video.palette[(address & (SIZE_PALETTE_RAM - 1)) >> 1]; + value = gbaMemory->p->video.palette[(address & (SIZE_PALETTE_RAM - 1)) >> 1]; + break; case BASE_VRAM: - return gbaMemory->p->video.vram[(address & 0x0001FFFF) >> 1]; + value = gbaMemory->p->video.vram[(address & 0x0001FFFF) >> 1]; + break; case BASE_OAM: - return gbaMemory->p->video.oam.raw[(address & (SIZE_OAM - 1)) >> 1]; + value = gbaMemory->p->video.oam.raw[(address & (SIZE_OAM - 1)) >> 1]; + break; case BASE_CART0: case BASE_CART0_EX: case BASE_CART1: case BASE_CART1_EX: case BASE_CART2: + wait = gbaMemory->waitstates16[address >> BASE_OFFSET]; if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) { - return ((uint16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1]; + value = ((int16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1]; } + break; case BASE_CART2_EX: + wait = gbaMemory->waitstates16[address >> BASE_OFFSET]; if (gbaMemory->savedata.type == SAVEDATA_EEPROM) { - return GBASavedataReadEEPROM(&gbaMemory->savedata); + value = GBASavedataReadEEPROM(&gbaMemory->savedata); } else if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) { - return ((uint16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1]; + value = ((uint16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1]; } + break; case BASE_CART_SRAM: break; default: break; } - return 0; + if (cycleCounter) { + *cycleCounter += wait; + } + return value; } -int8_t GBALoad8(struct ARMMemory* memory, uint32_t address) { - struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; - - switch (address & ~OFFSET_MASK) { - case BASE_BIOS: - break; - case BASE_WORKING_RAM: - return ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)]; - case BASE_WORKING_IRAM: - return ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)]; - case BASE_IO: - break; - case BASE_PALETTE_RAM: - break; - case BASE_VRAM: - break; - case BASE_OAM: - break; - case BASE_CART0: - case BASE_CART0_EX: - case BASE_CART1: - case BASE_CART1_EX: - case BASE_CART2: - case BASE_CART2_EX: - if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) { - return ((int8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)]; - } - case BASE_CART_SRAM: - if (gbaMemory->savedata.type == SAVEDATA_NONE) { - GBASavedataInitSRAM(&gbaMemory->savedata); - } - return gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)]; - default: - break; - } - - return 0; +uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address, int* cycleCounter) { + return GBALoad8(memory, address, cycleCounter); } -uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address) { +int8_t GBALoad8(struct ARMMemory* memory, uint32_t address, int* cycleCounter) { struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + int8_t value = 0; + int wait = 0; switch (address & ~OFFSET_MASK) { case BASE_BIOS: break; case BASE_WORKING_RAM: - return ((uint8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)]; + value = ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)]; + wait = gbaMemory->waitstates16[REGION_WORKING_RAM]; break; case BASE_WORKING_IRAM: - return ((uint8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)]; + value = ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)]; break; case BASE_IO: - return (GBAIORead(gbaMemory->p, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF; + value = (GBAIORead(gbaMemory->p, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF; + break; case BASE_PALETTE_RAM: break; case BASE_VRAM:

@@ -298,27 +259,35 @@ case BASE_CART1:

case BASE_CART1_EX: case BASE_CART2: case BASE_CART2_EX: + wait = gbaMemory->waitstates16[address >> BASE_OFFSET]; if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) { - return ((uint8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)]; + value = ((int8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)]; } + break; case BASE_CART_SRAM: + wait = gbaMemory->waitstates16[address >> BASE_OFFSET]; if (gbaMemory->savedata.type == SAVEDATA_NONE) { GBASavedataInitSRAM(&gbaMemory->savedata); } - return gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)]; + value = gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)]; default: break; } - return 0; + if (cycleCounter) { + *cycleCounter += wait; + } + return value; } -void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value) { +void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value, int* cycleCounter) { struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + int wait = 0; switch (address & ~OFFSET_MASK) { case BASE_WORKING_RAM: gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2] = value; + wait = gbaMemory->waitstates32[REGION_WORKING_RAM]; break; case BASE_WORKING_IRAM: gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2] = value;

@@ -346,14 +315,20 @@ break;

default: break; } + + if (cycleCounter) { + *cycleCounter += wait; + } } -void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value) { +void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value, int* cycleCounter) { struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + int wait = 0; switch (address & ~OFFSET_MASK) { case BASE_WORKING_RAM: ((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1] = value; + wait = gbaMemory->waitstates16[REGION_WORKING_RAM]; break; case BASE_WORKING_IRAM: ((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1] = value;

@@ -386,14 +361,20 @@ break;

default: break; } + + if (cycleCounter) { + *cycleCounter += wait; + } } -void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value) { +void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value, int* cycleCounter) { struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + int wait = 0; switch (address & ~OFFSET_MASK) { case BASE_WORKING_RAM: ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)] = value; + wait = gbaMemory->waitstates16[REGION_WORKING_RAM]; break; case BASE_WORKING_IRAM: ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;

@@ -421,10 +402,15 @@ GBASavedataWriteFlash(&gbaMemory->savedata, value);

} else if (gbaMemory->savedata.type == SAVEDATA_SRAM) { gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value; } + wait = gbaMemory->waitstates16[REGION_CART_SRAM]; break; default: break; } + + if (cycleCounter) { + *cycleCounter += wait; + } } void GBAAdjustWaitstates(struct GBAMemory* memory, uint16_t parameters) {

@@ -436,7 +422,6 @@ int ws1seq = (parameters & 0x0080) >> 7;

int ws2 = (parameters & 0x0300) >> 8; int ws2seq = (parameters & 0x0400) >> 10; int prefetch = parameters & 0x4000; - (void)(prefetch); memory->waitstates16[REGION_CART_SRAM] = GBA_ROM_WAITSTATES[sram]; memory->waitstatesSeq16[REGION_CART_SRAM] = GBA_ROM_WAITSTATES[sram];

@@ -455,9 +440,27 @@ memory->waitstates32[REGION_CART0] = memory->waitstates32[REGION_CART0_EX] = memory->waitstates16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];

memory->waitstates32[REGION_CART1] = memory->waitstates32[REGION_CART1_EX] = memory->waitstates16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1]; memory->waitstates32[REGION_CART2] = memory->waitstates32[REGION_CART2_EX] = memory->waitstates16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2]; - memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0 + 1] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1; - memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1 + 1] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1; - memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2 + 1] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1; + memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1; + memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1; + memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1; + + if (!prefetch) { + memory->waitstatesPrefetch16[REGION_CART0] = memory->waitstatesPrefetch16[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0]; + memory->waitstatesPrefetch16[REGION_CART1] = memory->waitstatesPrefetch16[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1]; + memory->waitstatesPrefetch16[REGION_CART2] = memory->waitstatesPrefetch16[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2]; + + memory->waitstatesPrefetch32[REGION_CART0] = memory->waitstatesPrefetch32[REGION_CART0_EX] = memory->waitstatesSeq32[REGION_CART0]; + memory->waitstatesPrefetch32[REGION_CART1] = memory->waitstatesPrefetch32[REGION_CART1_EX] = memory->waitstatesSeq32[REGION_CART1]; + memory->waitstatesPrefetch32[REGION_CART2] = memory->waitstatesPrefetch32[REGION_CART2_EX] = memory->waitstatesSeq32[REGION_CART2]; + } else { + memory->waitstatesPrefetch16[REGION_CART0] = memory->waitstatesPrefetch16[REGION_CART0_EX] = 0; + memory->waitstatesPrefetch16[REGION_CART1] = memory->waitstatesPrefetch16[REGION_CART1_EX] = 0; + memory->waitstatesPrefetch16[REGION_CART2] = memory->waitstatesPrefetch16[REGION_CART2_EX] = 0; + + memory->waitstatesPrefetch32[REGION_CART0] = memory->waitstatesPrefetch32[REGION_CART0_EX] = 0; + memory->waitstatesPrefetch32[REGION_CART1] = memory->waitstatesPrefetch32[REGION_CART1_EX] = 0; + memory->waitstatesPrefetch32[REGION_CART2] = memory->waitstatesPrefetch32[REGION_CART2_EX] = 0; + } memory->d.activePrefetchCycles32 = memory->waitstates32[memory->activeRegion]; memory->d.activePrefetchCycles16 = memory->waitstates16[memory->activeRegion];

@@ -615,8 +618,8 @@ int32_t word;

source &= 0xFFFFFFFC; dest &= 0xFFFFFFFC; while (wordsRemaining--) { - word = GBALoad32(&memory->d, source); - GBAStore32(&memory->d, dest, word); + word = GBALoad32(&memory->d, source, 0); + GBAStore32(&memory->d, dest, word, 0); source += sourceOffset; dest += destOffset; }

@@ -625,7 +628,7 @@ uint16_t word;

if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) { while (wordsRemaining--) { word = GBASavedataReadEEPROM(&memory->savedata); - GBAStore16(&memory->d, dest, word); + GBAStore16(&memory->d, dest, word, 0); source += sourceOffset; dest += destOffset; }

@@ -634,7 +637,7 @@ if (memory->savedata.type != SAVEDATA_EEPROM) {

GBASavedataInitEEPROM(&memory->savedata); } while (wordsRemaining) { - word = GBALoadU16(&memory->d, source); + word = GBALoadU16(&memory->d, source, 0); GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining); source += sourceOffset; dest += destOffset;

@@ -642,8 +645,8 @@ --wordsRemaining;

} } else { while (wordsRemaining--) { - word = GBALoadU16(&memory->d, source); - GBAStore16(&memory->d, dest, word); + word = GBALoadU16(&memory->d, source, 0); + GBAStore16(&memory->d, dest, word, 0); source += sourceOffset; dest += destOffset; }
M src/gba/gba-memory.hsrc/gba/gba-memory.h

@@ -119,6 +119,8 @@ char waitstates32[256];

char waitstates16[256]; char waitstatesSeq32[256]; char waitstatesSeq16[256]; + char waitstatesPrefetch32[256]; + char waitstatesPrefetch16[256]; int activeRegion; struct GBADMA dma[4];

@@ -126,15 +128,15 @@ };

int32_t GBAMemoryProcessEvents(struct GBAMemory* memory, int32_t cycles); -int32_t GBALoad32(struct ARMMemory* memory, uint32_t address); -int16_t GBALoad16(struct ARMMemory* memory, uint32_t address); -uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address); -int8_t GBALoad8(struct ARMMemory* memory, uint32_t address); -uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address); +int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter); +int16_t GBALoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter); +uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address, int* cycleCounter); +int8_t GBALoad8(struct ARMMemory* memory, uint32_t address, int* cycleCounter); +uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address, int* cycleCounter); -void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value); -void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value); -void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value); +void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value, int* cycleCounter); +void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value, int* cycleCounter); +void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value, int* cycleCounter); void GBAAdjustWaitstates(struct GBAMemory* memory, uint16_t parameters);