mirror of https://github.com/mgba-emu/mgba.git
ARM: CP15 improvements
This commit is contained in:
parent
8bfad3f7be
commit
60d49b4860
|
@ -5,9 +5,9 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "arm.h"
|
||||
|
||||
#include "isa-arm.h"
|
||||
#include "isa-inlines.h"
|
||||
#include "isa-thumb.h"
|
||||
#include "arm/isa-arm.h"
|
||||
#include "arm/isa-inlines.h"
|
||||
#include "arm/isa-thumb.h"
|
||||
|
||||
static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode);
|
||||
|
||||
|
|
|
@ -127,6 +127,7 @@ struct ARMInterruptHandler {
|
|||
void (*bkpt16)(struct ARMCore* cpu, int immediate);
|
||||
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);
|
||||
|
||||
void (*hitStub)(struct ARMCore* cpu, uint32_t opcode);
|
||||
};
|
||||
|
@ -163,6 +164,25 @@ DECL_BIT(ARMControlReg, L2, 26);
|
|||
|
||||
DECL_BITFIELD(ARMCoprocessorAccess, uint32_t);
|
||||
|
||||
DECL_BITFIELD(ARMCacheability, uint32_t);
|
||||
DECL_BIT(ARMCacheability, 0, 0);
|
||||
DECL_BIT(ARMCacheability, 1, 1);
|
||||
DECL_BIT(ARMCacheability, 2, 2);
|
||||
DECL_BIT(ARMCacheability, 3, 3);
|
||||
DECL_BIT(ARMCacheability, 4, 4);
|
||||
DECL_BIT(ARMCacheability, 5, 5);
|
||||
DECL_BIT(ARMCacheability, 6, 6);
|
||||
DECL_BIT(ARMCacheability, 7, 7);
|
||||
|
||||
DECL_BITFIELD(ARMProtection, uint32_t);
|
||||
DECL_BIT(ARMProtection, Enable, 0);
|
||||
DECL_BITS(ARMProtection, Size, 1, 5);
|
||||
DECL_BITS(ARMProtection, Base, 12, 20);
|
||||
|
||||
DECL_BITFIELD(ARMTCMControl, uint32_t);
|
||||
DECL_BITS(ARMTCMControl, VirtualSize, 1, 5);
|
||||
DECL_BITS(ARMTCMControl, Base, 12, 20);
|
||||
|
||||
struct ARMCP15 {
|
||||
struct {
|
||||
ARMCPUID cpuid;
|
||||
|
@ -176,8 +196,20 @@ struct ARMCP15 {
|
|||
uint32_t c1;
|
||||
ARMCoprocessorAccess cpAccess;
|
||||
} r1;
|
||||
|
||||
uint32_t (*write)(struct ARMCore*, int crn, int crm, int opcode1, int opcode2, uint32_t value);
|
||||
struct {
|
||||
ARMCacheability d;
|
||||
ARMCacheability i;
|
||||
} r2;
|
||||
struct {
|
||||
ARMCacheability d;
|
||||
} r3;
|
||||
struct {
|
||||
ARMProtection region[8];
|
||||
} r6;
|
||||
struct {
|
||||
ARMTCMControl d;
|
||||
ARMTCMControl i;
|
||||
} r9;
|
||||
};
|
||||
|
||||
struct ARMCore {
|
||||
|
|
|
@ -636,8 +636,8 @@ DEFINE_INSTRUCTION_ARM(BX,
|
|||
DEFINE_COPROCESSOR_INSTRUCTION(MRC, ARM_STUB)
|
||||
|
||||
DEFINE_COPROCESSOR_INSTRUCTION(MCR,
|
||||
if (cp == 15) {
|
||||
cpu->cp15.write(cpu, crn, crm, op1, op2, cpu->gprs[rd]);
|
||||
if (cp == 15 && cpu->irqh.writeCP15) {
|
||||
cpu->irqh.writeCP15(cpu, crn, crm, op1, op2, cpu->gprs[rd]);
|
||||
} else {
|
||||
ARM_STUB;
|
||||
})
|
||||
|
|
99
src/ds/ds.c
99
src/ds/ds.c
|
@ -42,9 +42,9 @@ static void DS7InterruptHandlerInit(struct ARMInterruptHandler* irqh);
|
|||
|
||||
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 void DS9InterruptHandlerInit(struct ARMInterruptHandler* irqh);
|
||||
|
||||
|
||||
static void DSProcessEvents(struct ARMCore* cpu);
|
||||
static void DSHitStub(struct ARMCore* cpu, uint32_t opcode);
|
||||
static void DSIllegal(struct ARMCore* cpu, uint32_t opcode);
|
||||
|
@ -108,6 +108,7 @@ void DS7InterruptHandlerInit(struct ARMInterruptHandler* irqh) {
|
|||
irqh->swi32 = NULL;
|
||||
irqh->hitIllegal = DSIllegal;
|
||||
irqh->readCPSR = DS7TestIRQ;
|
||||
irqh->writeCP15 = NULL;
|
||||
irqh->hitStub = DSHitStub;
|
||||
irqh->bkpt16 = DSBreakpoint;
|
||||
irqh->bkpt32 = DSBreakpoint;
|
||||
|
@ -120,6 +121,7 @@ void DS9InterruptHandlerInit(struct ARMInterruptHandler* irqh) {
|
|||
irqh->swi32 = NULL;
|
||||
irqh->hitIllegal = DSIllegal;
|
||||
irqh->readCPSR = DS9TestIRQ;
|
||||
irqh->writeCP15 = DS9WriteCP15;
|
||||
irqh->hitStub = DSHitStub;
|
||||
irqh->bkpt16 = DSBreakpoint;
|
||||
irqh->bkpt32 = DSBreakpoint;
|
||||
|
@ -356,3 +358,98 @@ void DS9TestIRQ(struct ARMCore* cpu) {
|
|||
cpu->nextEvent = cpu->cycles;
|
||||
}
|
||||
}
|
||||
|
||||
static void _writeSysControl(struct ARMCore* cpu, int crm, int opcode2, uint32_t value) {
|
||||
mLOG(DS, STUB, "CP15 system control write: CRm: %i, Op2: %i, Value: 0x%08X", crm, opcode2, value);
|
||||
}
|
||||
|
||||
static void _writeCacheControl(struct ARMCore* cpu, int crm, int opcode2, uint32_t value) {
|
||||
mLOG(DS, STUB, "CP15 cache control control write: CRm: %i, Op2: %i, Value: 0x%08X", crm, opcode2, value);
|
||||
switch (opcode2) {
|
||||
case 0:
|
||||
cpu->cp15.r2.d = value;
|
||||
break;
|
||||
case 1:
|
||||
cpu->cp15.r2.i = value;
|
||||
break;
|
||||
default:
|
||||
mLOG(DS, GAME_ERROR, "CP15 cache control control bad op2: %i", opcode2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _writeWriteBufferControl(struct ARMCore* cpu, int crm, int opcode2, uint32_t value) {
|
||||
mLOG(DS, STUB, "CP15 write buffer control write: CRm: %i, Op2: %i, Value: 0x%08X", crm, opcode2, value);
|
||||
switch (opcode2) {
|
||||
case 0:
|
||||
cpu->cp15.r3.d = value;
|
||||
break;
|
||||
default:
|
||||
mLOG(DS, GAME_ERROR, "CP15 cache control control bad op2: %i", opcode2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _writeAccessControl(struct ARMCore* cpu, int crm, int opcode2, uint32_t value) {
|
||||
mLOG(DS, STUB, "CP15 access control write: CRm: %i, Op2: %i, Value: 0x%08X", crm, opcode2, value);
|
||||
}
|
||||
|
||||
static void _writeRegionConfiguration(struct ARMCore* cpu, int crm, int opcode2, uint32_t value) {
|
||||
cpu->cp15.r6.region[crm] = value;
|
||||
uint32_t base = ARMProtectionGetBase(value) << 12;
|
||||
uint32_t size = 2 << ARMProtectionGetSize(value);
|
||||
mLOG(DS, STUB, "CP15 region configuration write: Region: %i, Insn: %i, Base: %08X, Size: %08X", crm, opcode2, base, size);
|
||||
}
|
||||
|
||||
static void _writeCache(struct ARMCore* cpu, int crm, int opcode2, uint32_t value) {
|
||||
mLOG(DS, STUB, "CP15 cache write: CRm: %i, Op2: %i, Value: 0x%08X", crm, opcode2, value);
|
||||
}
|
||||
|
||||
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);
|
||||
switch (opcode2) {
|
||||
case 0:
|
||||
cpu->cp15.r9.d = value;
|
||||
break;
|
||||
case 1:
|
||||
cpu->cp15.r9.i = value;
|
||||
break;
|
||||
default:
|
||||
mLOG(DS, GAME_ERROR, "CP15 TCM control bad op2: %i", opcode2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DS9WriteCP15(struct ARMCore* cpu, int crn, int crm, int opcode1, int opcode2, uint32_t value) {
|
||||
switch (crn) {
|
||||
default:
|
||||
mLOG(DS, STUB, "CP15 unknown write: CRn: %i, CRm: %i, Op1: %i, Op2: %i, Value: 0x%08X", crn, crm, opcode1, opcode2, value);
|
||||
break;
|
||||
case 0:
|
||||
mLOG(DS, GAME_ERROR, "Attempted to write to read-only cp15 register");
|
||||
ARMRaiseUndefined(cpu);
|
||||
break;
|
||||
case 1:
|
||||
_writeSysControl(cpu, crm, opcode2, value);
|
||||
break;
|
||||
case 2:
|
||||
_writeCacheControl(cpu, crm, opcode2, value);
|
||||
break;
|
||||
case 3:
|
||||
_writeWriteBufferControl(cpu, crm, opcode2, value);
|
||||
break;
|
||||
case 5:
|
||||
_writeAccessControl(cpu, crm, opcode2, value);
|
||||
break;
|
||||
case 6:
|
||||
_writeRegionConfiguration(cpu, crm, opcode2, value);
|
||||
break;
|
||||
case 7:
|
||||
_writeCache(cpu, crm, opcode2, value);
|
||||
break;
|
||||
case 9:
|
||||
_writeTCMControl(cpu, crm, opcode2, value);
|
||||
break;
|
||||
}}
|
||||
|
|
Loading…
Reference in New Issue