all repos — mgba @ 915b04ddeda40d1b466d52f9e009d158206740b1

mGBA Game Boy Advance Emulator

Add support for PowerPC to the memory and CPU interfaces
Jeffrey Pfau jeffrey@endrift.com
Sat, 26 Oct 2013 01:53:13 -0400
commit

915b04ddeda40d1b466d52f9e009d158206740b1

parent

07115ca65553f741e19bb7d824a2981e703eb4ab

4 files changed, 53 insertions(+), 27 deletions(-)

jump to
M src/arm/arm.hsrc/arm/arm.h

@@ -3,6 +3,18 @@ #define ARM_H

#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 @@ unsigned v : 1;

unsigned c : 1; unsigned z : 1; unsigned n : 1; +#endif }; int32_t packed;
M src/arm/isa-arm.csrc/arm/isa-arm.c

@@ -186,7 +186,8 @@

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)]; }
M src/arm/isa-thumb.csrc/arm/isa-thumb.c

@@ -7,7 +7,8 @@

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); }
M src/gba/gba-memory.csrc/gba/gba-memory.c

@@ -127,7 +127,7 @@ switch (address & ~OFFSET_MASK) {

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 @@ value = gbaMemory->biosPrefetch;

} 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 @@ 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]; + LOAD_32(value, address & (SIZE_CART0 - 1), gbaMemory->rom); } break; case BASE_CART_SRAM:

@@ -201,7 +201,7 @@ switch (address & ~OFFSET_MASK) {

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 @@ value = gbaMemory->biosPrefetch;

} 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 @@ case BASE_CART1_EX:

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 @@ wait = gbaMemory->waitstates16[address >> BASE_OFFSET];

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 @@ int wait = 0;

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 @@ int wait = 0;

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: