mirror of https://github.com/mgba-emu/mgba.git
Add support for PowerPC to the memory and CPU interfaces
This commit is contained in:
parent
07115ca655
commit
915b04dded
|
@ -3,6 +3,18 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __POWERPC__
|
||||
#define LOAD_32(DEST, ADDR, ARR) asm("lwbrx %0, %1, %2" : "=r"(DEST) : "r"(ADDR), "r"(ARR))
|
||||
#define LOAD_16(DEST, ADDR, ARR) asm("lhbrx %0, %1, %2" : "=r"(DEST) : "r"(ADDR), "r"(ARR))
|
||||
#define STORE_32(SRC, ADDR, ARR) asm("stwbrx %0, %1, %2" : : "r"(SRC), "r"(ADDR), "r"(ARR))
|
||||
#define STORE_16(SRC, ADDR, ARR) asm("sthbrx %0, %1, %2" : : "r"(SRC), "r"(ADDR), "r"(ARR))
|
||||
#else
|
||||
#define LOAD_32(DEST, ADDR, ARR) DEST = ((uint32_t*) ARR)[(ADDR) >> 2]
|
||||
#define LOAD_16(DEST, ADDR, ARR) DEST = ((uint16_t*) ARR)[(ADDR) >> 1]
|
||||
#define STORE_32(SRC, ADDR, ARR) ((uint32_t*) ARR)[(ADDR) >> 2] = SRC
|
||||
#define STORE_16(SRC, ADDR, ARR) ((uint16_t*) ARR)[(ADDR) >> 1] = SRC
|
||||
#endif
|
||||
|
||||
enum {
|
||||
ARM_SP = 13,
|
||||
ARM_LR = 14,
|
||||
|
@ -52,6 +64,17 @@ struct ARMCore;
|
|||
|
||||
union PSR {
|
||||
struct {
|
||||
#ifdef __POWERPC__
|
||||
unsigned n : 1;
|
||||
unsigned z : 1;
|
||||
unsigned c : 1;
|
||||
unsigned v : 1;
|
||||
unsigned : 20;
|
||||
unsigned i : 1;
|
||||
unsigned f : 1;
|
||||
enum ExecutionMode t : 1;
|
||||
enum PrivilegeMode priv : 5;
|
||||
#else
|
||||
enum PrivilegeMode priv : 5;
|
||||
enum ExecutionMode t : 1;
|
||||
unsigned f : 1;
|
||||
|
@ -61,6 +84,7 @@ union PSR {
|
|||
unsigned c : 1;
|
||||
unsigned z : 1;
|
||||
unsigned n : 1;
|
||||
#endif
|
||||
};
|
||||
|
||||
int32_t packed;
|
||||
|
|
|
@ -186,7 +186,8 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) {
|
|||
static const ARMInstruction _armTable[0x1000];
|
||||
|
||||
static ARMInstruction _ARMLoadInstructionARM(struct ARMMemory* memory, uint32_t address, uint32_t* opcodeOut) {
|
||||
uint32_t opcode = memory->activeRegion[(address & memory->activeMask) >> 2];
|
||||
uint32_t opcode;
|
||||
LOAD_32(opcode, address & memory->activeMask, memory->activeRegion);
|
||||
*opcodeOut = opcode;
|
||||
return _armTable[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)];
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ static const ThumbInstruction _thumbTable[0x400];
|
|||
void ThumbStep(struct ARMCore* cpu) {
|
||||
cpu->currentPC = cpu->gprs[ARM_PC] - WORD_SIZE_THUMB;
|
||||
cpu->gprs[ARM_PC] += WORD_SIZE_THUMB;
|
||||
uint16_t opcode = ((uint16_t*) cpu->memory->activeRegion)[(cpu->currentPC & cpu->memory->activeMask) >> 1];
|
||||
uint16_t opcode;
|
||||
LOAD_16(opcode, cpu->currentPC & cpu->memory->activeMask, cpu->memory->activeRegion);
|
||||
ThumbInstruction instruction = _thumbTable[opcode >> 6];
|
||||
instruction(cpu, opcode);
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter)
|
|||
case BASE_BIOS:
|
||||
if (gbaMemory->p->cpu.currentPC >> BASE_OFFSET == REGION_BIOS) {
|
||||
if (address < SIZE_BIOS) {
|
||||
value = gbaMemory->bios[address >> 2];
|
||||
LOAD_32(value, address, gbaMemory->bios);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
|
@ -136,23 +136,23 @@ int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter)
|
|||
}
|
||||
break;
|
||||
case BASE_WORKING_RAM:
|
||||
value = gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2];
|
||||
LOAD_32(value, address & (SIZE_WORKING_RAM - 1), gbaMemory->wram);
|
||||
wait = gbaMemory->waitstates32[REGION_WORKING_RAM];
|
||||
break;
|
||||
case BASE_WORKING_IRAM:
|
||||
value = gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2];
|
||||
LOAD_32(value, address & (SIZE_WORKING_IRAM - 1), gbaMemory->iwram);
|
||||
break;
|
||||
case BASE_IO:
|
||||
value = GBAIORead(gbaMemory->p, (address & (SIZE_IO - 1)) & ~2) | (GBAIORead(gbaMemory->p, (address & (SIZE_IO - 1)) | 2) << 16);
|
||||
break;
|
||||
case BASE_PALETTE_RAM:
|
||||
value = ((int32_t*) gbaMemory->p->video.palette)[(address & (SIZE_PALETTE_RAM - 1)) >> 2];
|
||||
LOAD_32(value, address & (SIZE_PALETTE_RAM - 1), gbaMemory->p->video.palette);
|
||||
break;
|
||||
case BASE_VRAM:
|
||||
value = ((int32_t*) gbaMemory->p->video.renderer->vram)[(address & 0x0001FFFF) >> 2];
|
||||
LOAD_32(value, address & 0x0001FFFF, gbaMemory->p->video.renderer->vram);
|
||||
break;
|
||||
case BASE_OAM:
|
||||
value = ((int32_t*) gbaMemory->p->video.oam.raw)[(address & (SIZE_OAM - 1)) >> 2];
|
||||
LOAD_32(value, address & (SIZE_OAM - 1), gbaMemory->p->video.oam.raw);
|
||||
break;
|
||||
case BASE_CART0:
|
||||
case BASE_CART0_EX:
|
||||
|
@ -162,7 +162,7 @@ int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter)
|
|||
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];
|
||||
LOAD_32(value, address & (SIZE_CART0 - 1), gbaMemory->rom);
|
||||
}
|
||||
break;
|
||||
case BASE_CART_SRAM:
|
||||
|
@ -201,7 +201,7 @@ int16_t GBALoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter)
|
|||
case BASE_BIOS:
|
||||
if (gbaMemory->p->cpu.currentPC >> BASE_OFFSET == REGION_BIOS) {
|
||||
if (address < SIZE_BIOS) {
|
||||
value = ((int16_t*) gbaMemory->bios)[address >> 1];
|
||||
LOAD_16(value, address, gbaMemory->bios);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
|
@ -210,23 +210,23 @@ int16_t GBALoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter)
|
|||
}
|
||||
break;
|
||||
case BASE_WORKING_RAM:
|
||||
value = ((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1];
|
||||
LOAD_16(value, address & (SIZE_WORKING_RAM - 1), gbaMemory->wram);
|
||||
wait = gbaMemory->waitstates16[REGION_WORKING_RAM];
|
||||
break;
|
||||
case BASE_WORKING_IRAM:
|
||||
value = ((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1];
|
||||
LOAD_16(value, address & (SIZE_WORKING_IRAM - 1), gbaMemory->iwram);
|
||||
break;
|
||||
case BASE_IO:
|
||||
value = GBAIORead(gbaMemory->p, address & (SIZE_IO - 1));
|
||||
break;
|
||||
case BASE_PALETTE_RAM:
|
||||
value = gbaMemory->p->video.palette[(address & (SIZE_PALETTE_RAM - 1)) >> 1];
|
||||
LOAD_16(value, address & (SIZE_PALETTE_RAM - 1), gbaMemory->p->video.palette);
|
||||
break;
|
||||
case BASE_VRAM:
|
||||
value = gbaMemory->p->video.renderer->vram[(address & 0x0001FFFF) >> 1];
|
||||
LOAD_16(value, address & 0x0001FFFF, gbaMemory->p->video.renderer->vram);
|
||||
break;
|
||||
case BASE_OAM:
|
||||
value = gbaMemory->p->video.oam.raw[(address & (SIZE_OAM - 1)) >> 1];
|
||||
LOAD_16(value, address & (SIZE_OAM - 1), gbaMemory->p->video.oam.raw);
|
||||
break;
|
||||
case BASE_CART0:
|
||||
case BASE_CART0_EX:
|
||||
|
@ -235,7 +235,7 @@ int16_t GBALoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter)
|
|||
case BASE_CART2:
|
||||
wait = gbaMemory->waitstates16[address >> BASE_OFFSET];
|
||||
if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) {
|
||||
value = ((int16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1];
|
||||
LOAD_16(value, address & (SIZE_CART0 - 1), gbaMemory->rom);
|
||||
}
|
||||
break;
|
||||
case BASE_CART2_EX:
|
||||
|
@ -243,7 +243,7 @@ int16_t GBALoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter)
|
|||
if (gbaMemory->savedata.type == SAVEDATA_EEPROM) {
|
||||
value = GBASavedataReadEEPROM(&gbaMemory->savedata);
|
||||
} else if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) {
|
||||
value = ((uint16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1];
|
||||
LOAD_16(value, address & (SIZE_CART0 - 1), gbaMemory->rom);
|
||||
}
|
||||
break;
|
||||
case BASE_CART_SRAM:
|
||||
|
@ -342,27 +342,27 @@ void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value, int*
|
|||
|
||||
switch (address & ~OFFSET_MASK) {
|
||||
case BASE_WORKING_RAM:
|
||||
gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2] = value;
|
||||
STORE_32(value, address & (SIZE_WORKING_RAM - 1), gbaMemory->wram);
|
||||
wait = gbaMemory->waitstates32[REGION_WORKING_RAM];
|
||||
break;
|
||||
case BASE_WORKING_IRAM:
|
||||
gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2] = value;
|
||||
STORE_32(value, address & (SIZE_WORKING_IRAM - 1), gbaMemory->iwram);
|
||||
break;
|
||||
case BASE_IO:
|
||||
GBAIOWrite32(gbaMemory->p, address & (SIZE_IO - 1), value);
|
||||
break;
|
||||
case BASE_PALETTE_RAM:
|
||||
((int32_t*) gbaMemory->p->video.palette)[(address & (SIZE_PALETTE_RAM - 1)) >> 2] = value;
|
||||
STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gbaMemory->p->video.palette);
|
||||
gbaMemory->p->video.renderer->writePalette(gbaMemory->p->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16);
|
||||
gbaMemory->p->video.renderer->writePalette(gbaMemory->p->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
|
||||
break;
|
||||
case BASE_VRAM:
|
||||
if ((address & OFFSET_MASK) < SIZE_VRAM - 2) {
|
||||
((int32_t*) gbaMemory->p->video.renderer->vram)[(address & 0x0001FFFF) >> 2] = value;
|
||||
STORE_32(value, address & 0x0001FFFF, gbaMemory->p->video.renderer->vram);
|
||||
}
|
||||
break;
|
||||
case BASE_OAM:
|
||||
((int32_t*) gbaMemory->p->video.oam.raw)[(address & (SIZE_OAM - 1)) >> 2] = value;
|
||||
STORE_32(value, address & (SIZE_OAM - 1), gbaMemory->p->video.oam.raw);
|
||||
gbaMemory->p->video.renderer->writeOAM(gbaMemory->p->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
|
||||
gbaMemory->p->video.renderer->writeOAM(gbaMemory->p->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
|
||||
break;
|
||||
|
@ -388,26 +388,26 @@ void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value, int*
|
|||
|
||||
switch (address & ~OFFSET_MASK) {
|
||||
case BASE_WORKING_RAM:
|
||||
((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1] = value;
|
||||
STORE_16(value, address & (SIZE_WORKING_RAM - 1), gbaMemory->wram);
|
||||
wait = gbaMemory->waitstates16[REGION_WORKING_RAM];
|
||||
break;
|
||||
case BASE_WORKING_IRAM:
|
||||
((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1] = value;
|
||||
STORE_16(value, address & (SIZE_WORKING_IRAM - 1), gbaMemory->iwram);
|
||||
break;
|
||||
case BASE_IO:
|
||||
GBAIOWrite(gbaMemory->p, address & (SIZE_IO - 1), value);
|
||||
break;
|
||||
case BASE_PALETTE_RAM:
|
||||
gbaMemory->p->video.palette[(address & (SIZE_PALETTE_RAM - 1)) >> 1] = value;
|
||||
STORE_16(value, address & (SIZE_PALETTE_RAM - 1), gbaMemory->p->video.palette);
|
||||
gbaMemory->p->video.renderer->writePalette(gbaMemory->p->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
|
||||
break;
|
||||
case BASE_VRAM:
|
||||
if ((address & OFFSET_MASK) < SIZE_VRAM) {
|
||||
gbaMemory->p->video.renderer->vram[(address & 0x0001FFFF) >> 1] = value;
|
||||
STORE_16(value, address & 0x0001FFFF, gbaMemory->p->video.renderer->vram);
|
||||
}
|
||||
break;
|
||||
case BASE_OAM:
|
||||
gbaMemory->p->video.oam.raw[(address & (SIZE_OAM - 1)) >> 1] = value;
|
||||
STORE_16(value, address & (SIZE_OAM - 1), gbaMemory->p->video.oam.raw);
|
||||
gbaMemory->p->video.renderer->writeOAM(gbaMemory->p->video.renderer, (address & (SIZE_OAM - 1)) >> 1);
|
||||
break;
|
||||
case BASE_CART0:
|
||||
|
|
Loading…
Reference in New Issue