Count cycles for load/store singles

This commit is contained in:
Jeffrey Pfau 2013-05-04 23:57:12 -07:00
parent 738b3dc44e
commit fc7aec557b
9 changed files with 228 additions and 219 deletions

View File

@ -100,9 +100,6 @@ void ARMReset(struct ARMCore* cpu) {
cpu->cpsr.packed = MODE_SYSTEM;
cpu->spsr.packed = 0;
cpu->cycles = 0;
cpu->nextEvent = 0;
cpu->shifterOperand = 0;
cpu->shifterCarryOut = 0;
@ -111,6 +108,9 @@ void ARMReset(struct ARMCore* cpu) {
ARM_WRITE_PC;
cpu->cycles = 0;
cpu->nextEvent = 0;
cpu->board->reset(cpu->board);
}

View File

@ -67,15 +67,15 @@ union PSR {
};
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;

View File

@ -358,8 +358,8 @@ void ARMStep(struct ARMCore* cpu) {
#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 @@ DEFINE_MULTIPLY_INSTRUCTION_ARM(UMULL,
// 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)

View File

@ -56,11 +56,15 @@
#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;

View File

@ -94,8 +94,8 @@ void ThumbStep(struct ARMCore* cpu) {
#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 @@ DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(ASR1,
}
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_INSTRUCTION_WITH_HIGH_THUMB(MOV3,
#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_IMMEDIATE_WITH_REGISTER_THUMB(ADD6, cpu->gprs[rd] = cpu->gprs[ARM_SP] + i
#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_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, cpu->memory->store16(cpu->memory, c
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)

View File

@ -127,10 +127,10 @@ static void _printHex(struct ARMDebugger* debugger, struct DebugVector* dv) {
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 @@ static void _readByte(struct ARMDebugger* debugger, struct DebugVector* dv) {
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 @@ static void _readHalfword(struct ARMDebugger* debugger, struct DebugVector* dv)
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 @@ static void _readWord(struct ARMDebugger* debugger, struct DebugVector* dv) {
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);
}

View File

@ -27,16 +27,16 @@ static void _CpuSet(struct GBA* gba) {
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 @@ static void _CpuSet(struct GBA* gba) {
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 @@ static void _FastCpuSet(struct GBA* gba) {
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 @@ static void _BgAffineSet(struct GBA* gba) {
// [ 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 @@ static void _BgAffineSet(struct GBA* gba) {
// 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 @@ static void _ObjAffineSet(struct GBA* gba) {
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 @@ static void _ObjAffineSet(struct GBA* gba) {
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 @@ void GBASwi32(struct ARMBoard* board, int immediate) {
}
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 @@ static void _unLz77(struct GBAMemory* memory, uint32_t source, uint8_t* dest) {
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 @@ static void _unLz77(struct GBAMemory* memory, uint32_t source, uint8_t* dest) {
}
} 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;
}
}

View File

@ -12,7 +12,9 @@ static const char* GBA_CANNOT_MMAP = "Could not map memory";
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 @@ void GBAMemoryInit(struct GBAMemory* memory) {
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 @@ void GBAMemoryDeinit(struct GBAMemory* memory) {
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 @@ static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) {
}
}
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 @@ int32_t GBALoad32(struct ARMMemory* memory, uint32_t address) {
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,104 +155,97 @@ int32_t GBALoad32(struct ARMMemory* memory, uint32_t address) {
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) {
uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
return GBALoad16(memory, address, cycleCounter);
}
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 ((int16_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 ((int16_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 ((int16_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;
}
uint16_t GBALoadU16(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 ((uint16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1];
case BASE_WORKING_IRAM:
return ((uint16_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 ((uint16_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;
if (cycleCounter) {
*cycleCounter += wait;
}
return 0;
return value;
}
int8_t GBALoad8(struct ARMMemory* memory, uint32_t address) {
uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
return GBALoad8(memory, address, cycleCounter);
}
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 ((int8_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 ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
value = ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
break;
case BASE_IO:
value = (GBAIORead(gbaMemory->p, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
break;
case BASE_PALETTE_RAM:
break;
@ -257,68 +259,35 @@ int8_t GBALoad8(struct ARMMemory* memory, uint32_t address) {
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 ((int8_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;
}
uint8_t GBALoadU8(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 ((uint8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)];
break;
case BASE_WORKING_IRAM:
return ((uint8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
break;
case BASE_IO:
return (GBAIORead(gbaMemory->p, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
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 ((uint8_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;
if (cycleCounter) {
*cycleCounter += wait;
}
return 0;
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 @@ void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value) {
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 @@ void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value) {
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 @@ void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t 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 @@ void GBAAdjustWaitstates(struct GBAMemory* memory, uint16_t parameters) {
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 @@ void GBAAdjustWaitstates(struct GBAMemory* memory, uint16_t parameters) {
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 @@ void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* in
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 @@ void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* in
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 @@ void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* in
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 @@ void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* in
}
} 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;
}

View File

@ -119,6 +119,8 @@ struct GBAMemory {
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 @@ struct GBAMemory {
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);