mirror of https://github.com/mgba-emu/mgba.git
Count cycles for load/store singles
This commit is contained in:
parent
738b3dc44e
commit
fc7aec557b
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue