ARM: Implement MCR

This commit is contained in:
Vicki Pfau 2017-01-30 12:17:08 -08:00
parent 20296e7f0e
commit 7ff9c0af5b
3 changed files with 33 additions and 2 deletions

View File

@ -112,6 +112,7 @@ struct ARMInterruptHandler {
void (*bkpt32)(struct ARMCore* cpu, int immediate);
void (*readCPSR)(struct ARMCore* cpu);
void (*writeCP15)(struct ARMCore*, int crn, int crm, int opcode1, int opcode2, uint32_t value);
uint32_t (*readCP15)(struct ARMCore*, int crn, int crm, int opcode1, int opcode2);
void (*hitStub)(struct ARMCore* cpu, uint32_t opcode);
};

View File

@ -687,7 +687,12 @@ DEFINE_INSTRUCTION_ARM(BLX2,
UNUSED(crm); \
BODY;)
DEFINE_COPROCESSOR_INSTRUCTION(MRC, ARM_STUB)
DEFINE_COPROCESSOR_INSTRUCTION(MRC,
if (cp == 15 && cpu->irqh.readCP15) {
cpu->gprs[rd] = cpu->irqh.readCP15(cpu, crn, crm, op1, op2);
} else {
ARM_STUB;
})
DEFINE_COPROCESSOR_INSTRUCTION(MCR,
if (cp == 15 && cpu->irqh.writeCP15) {

View File

@ -46,6 +46,7 @@ static void DS7ProcessEvents(struct ARMCore* cpu);
static void DS9Reset(struct ARMCore* cpu);
static void DS9TestIRQ(struct ARMCore* cpu);
static void DS9WriteCP15(struct ARMCore* cpu, int crn, int crm, int opcode1, int opcode2, uint32_t value);
static uint32_t DS9ReadCP15(struct ARMCore* cpu, int crn, int crm, int opcode1, int opcode2);
static void DS9InterruptHandlerInit(struct ARMInterruptHandler* irqh);
static void DS9ProcessEvents(struct ARMCore* cpu);
@ -154,6 +155,7 @@ void DS7InterruptHandlerInit(struct ARMInterruptHandler* irqh) {
irqh->hitIllegal = DSIllegal;
irqh->readCPSR = DS7TestIRQ;
irqh->writeCP15 = NULL;
irqh->readCP15 = NULL;
irqh->hitStub = DSHitStub;
irqh->bkpt16 = DSBreakpoint;
irqh->bkpt32 = DSBreakpoint;
@ -167,6 +169,7 @@ void DS9InterruptHandlerInit(struct ARMInterruptHandler* irqh) {
irqh->hitIllegal = DSIllegal;
irqh->readCPSR = DS9TestIRQ;
irqh->writeCP15 = DS9WriteCP15;
irqh->readCP15 = DS9ReadCP15;
irqh->hitStub = DSHitStub;
irqh->bkpt16 = DSBreakpoint;
irqh->bkpt32 = DSBreakpoint;
@ -522,7 +525,7 @@ static void _writeCache(struct ARMCore* cpu, int crm, int opcode2, uint32_t valu
static void _writeTCMControl(struct ARMCore* cpu, int crm, int opcode2, uint32_t value) {
uint32_t base = ARMTCMControlGetBase(value) << 12;
uint32_t size = 512 << ARMTCMControlGetVirtualSize(value);
mLOG(DS, STUB, "CP15 TCM control write: CRm: %i, Op2: %i, Base: %08X, Size: %08X", crm, opcode2, base, size);
mLOG(DS, DEBUG, "CP15 TCM control write: CRm: %i, Op2: %i, Base: %08X, Size: %08X", crm, opcode2, base, size);
switch (opcode2) {
case 0:
cpu->cp15.r9.d = value;
@ -569,6 +572,28 @@ void DS9WriteCP15(struct ARMCore* cpu, int crn, int crm, int opcode1, int opcode
}
}
static uint32_t _readTCMControl(struct ARMCore* cpu, int crm, int opcode2) {
switch (opcode2) {
case 0:
return cpu->cp15.r9.d;
case 1:
return cpu->cp15.r9.i;
default:
mLOG(DS, GAME_ERROR, "CP15 TCM control bad op2: %i", opcode2);
return 0;
}
}
uint32_t DS9ReadCP15(struct ARMCore* cpu, int crn, int crm, int opcode1, int opcode2) {
switch (crn) {
default:
mLOG(DS, STUB, "CP15 unknown read: CRn: %i, CRm: %i, Op1: %i, Op2: %i", crn, crm, opcode1, opcode2);
return 0;
case 9:
return _readTCMControl(cpu, crm, opcode2);
}
}
void DSWriteIE(struct ARMCore* cpu, uint16_t* io, uint32_t value) {
if (io[DS_REG_IME >> 1] && (value & io[DS_REG_IF_LO >> 1] || (value >> 16) & io[DS_REG_IF_HI >> 1])) {
ARMRaiseIRQ(cpu);