Skip to content

Commit

Permalink
Fixed issues on LDM/STM instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
gdkchan committed Jan 6, 2017
1 parent fe23e93 commit 567067b
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 87 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ Module.symvers
Mkfile.old
dkms.conf

#GBA ROMs
# GBA ROMs
*.gba
*.bin
*.bin
134 changes: 81 additions & 53 deletions arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ static void arm_bank_to_regs(int8_t mode) {
case ARM_SYS:
arm_r.r[13] = arm_r.r13_usr;
arm_r.r[14] = arm_r.r14_usr;
break;
break;

case ARM_FIQ:
arm_r.r[8] = arm_r.r8_fiq;
arm_r.r[9] = arm_r.r9_fiq;
Expand All @@ -45,27 +46,32 @@ static void arm_bank_to_regs(int8_t mode) {
arm_r.r[12] = arm_r.r12_fiq;
arm_r.r[13] = arm_r.r13_fiq;
arm_r.r[14] = arm_r.r14_fiq;
break;
break;

case ARM_IRQ:
arm_r.r[13] = arm_r.r13_irq;
arm_r.r[14] = arm_r.r14_irq;
break;
break;

case ARM_SVC:
arm_r.r[13] = arm_r.r13_svc;
arm_r.r[14] = arm_r.r14_svc;
break;
break;

case ARM_MON:
arm_r.r[13] = arm_r.r13_mon;
arm_r.r[14] = arm_r.r14_mon;
break;
break;

case ARM_ABT:
arm_r.r[13] = arm_r.r13_abt;
arm_r.r[14] = arm_r.r14_abt;
break;
break;

case ARM_UND:
arm_r.r[13] = arm_r.r13_und;
arm_r.r[14] = arm_r.r14_und;
break;
break;
}
}

Expand All @@ -83,7 +89,8 @@ static void arm_regs_to_bank(int8_t mode) {
case ARM_SYS:
arm_r.r13_usr = arm_r.r[13];
arm_r.r14_usr = arm_r.r[14];
break;
break;

case ARM_FIQ:
arm_r.r8_fiq = arm_r.r[8];
arm_r.r9_fiq = arm_r.r[9];
Expand All @@ -92,27 +99,32 @@ static void arm_regs_to_bank(int8_t mode) {
arm_r.r12_fiq = arm_r.r[12];
arm_r.r13_fiq = arm_r.r[13];
arm_r.r14_fiq = arm_r.r[14];
break;
break;

case ARM_IRQ:
arm_r.r13_irq = arm_r.r[13];
arm_r.r14_irq = arm_r.r[14];
break;
break;

case ARM_SVC:
arm_r.r13_svc = arm_r.r[13];
arm_r.r14_svc = arm_r.r[14];
break;
break;

case ARM_MON:
arm_r.r13_mon = arm_r.r[13];
arm_r.r14_mon = arm_r.r[14];
break;
break;

case ARM_ABT:
arm_r.r13_abt = arm_r.r[13];
arm_r.r14_abt = arm_r.r[14];
break;
break;

case ARM_UND:
arm_r.r13_und = arm_r.r[13];
arm_r.r14_und = arm_r.r[14];
break;
break;
}
}

Expand Down Expand Up @@ -1302,70 +1314,70 @@ typedef enum {
DWORD = 8
} arm_size_e;

#define ARM_MEMIO_STORE 0
#define ARM_MEMIO_LOAD 1

static void arm_memio_mult(arm_memio_t op, bool load) {
static void arm_memio_ldm(arm_memio_t op) {
uint8_t i;

arm_r.r[op.rn] += op.disp;

for (i = 0; i < 16; i++) {
if (op.regs & (1 << i)) {
if (load)
arm_r.r[i] = arm_read_s(op.addr);
else
arm_write_s(op.addr, arm_r.r[i]);
arm_r.r[i] = arm_read_s(op.addr);

op.addr += 4;
}
}

if (load && op.regs & (1 << 15)) {
if (op.regs & 0x8000) {
arm_r15_align();
arm_load_pipe();
}

arm_r.r[op.rn] += op.disp;
}

static void arm_memio_ldm(arm_memio_t op) {
arm_memio_mult(op, ARM_MEMIO_LOAD);

arm_cycles++;
}

static void arm_memio_ldm_usr(arm_memio_t op) {
bool pc = (arm_op >> 15) & 1;
bool w = (arm_op >> 21) & 1;
if (arm_op & 0x8000) {
arm_memio_ldm(op);

arm_spsr_to_cpsr();

if (!(pc || w)) {
arm_check_irq();
} else {
int8_t mode = arm_r.cpsr & 0x1f;

arm_mode_set(ARM_USR);

arm_memio_mult(op, ARM_MEMIO_LOAD);
arm_memio_ldm(op);

arm_mode_set(mode);
} else {
arm_memio_mult(op, ARM_MEMIO_LOAD);

arm_spsr_to_cpsr();

arm_check_irq();
}

arm_cycles++;
}

static void arm_memio_stm(arm_memio_t op) {
arm_memio_mult(op, ARM_MEMIO_STORE);
bool first = true;
uint8_t i;

for (i = 0; i < 16; i++) {
if (op.regs & (1 << i)) {
arm_write_s(op.addr, arm_r.r[i]);

if (first) {
arm_r.r[op.rn] += op.disp;

first = false;
}

op.addr += 4;
}
}
}

static void arm_memio_stm_usr(arm_memio_t op) {
int8_t mode = arm_r.cpsr & 0x1f;

arm_mode_set(ARM_USR);

arm_memio_mult(op, ARM_MEMIO_STORE);
arm_memio_stm(op);

arm_mode_set(mode);
}
Expand Down Expand Up @@ -1957,7 +1969,7 @@ static void t16_b_imm8() {
imm <<= 24;
imm >>= 23;

uint8_t cond = (arm_op >> 8) & 0xf;
int8_t cond = (arm_op >> 8) & 0xf;

if (arm_cond(cond)) {
arm_access_bus(arm_r.r[15], ARM_HWORD_SZ, SEQUENTIAL);
Expand Down Expand Up @@ -3111,15 +3123,36 @@ void arm_uninit() {

#define ARM_COND_UNCOND 0b1111

static void t16_inc_r15() {
if (pipe_reload)
pipe_reload = false;
else
arm_r.r[15] += 2;
}

static void arm_inc_r15() {
if (pipe_reload)
pipe_reload = false;
else
arm_r.r[15] += 4;
}

void arm_exec(uint32_t target_cycles) {
while (arm_cycles < target_cycles) {
uint32_t cycles = arm_cycles;

arm_op = arm_pipe[0];

arm_op = arm_pipe[0];
arm_pipe[0] = arm_pipe[1];

if (arm_in_thumb()) {
arm_pipe[1] = arm_fetchh(SEQUENTIAL);

thumb_proc[arm_op >> 5]();

t16_inc_r15();
} else {
arm_pipe[1] = arm_fetch(SEQUENTIAL);

uint32_t proc;

proc = (arm_op >> 16) & 0xff0;
Expand All @@ -3131,18 +3164,13 @@ void arm_exec(uint32_t target_cycles) {
arm_proc[1][proc]();
else if (arm_cond(cond))
arm_proc[0][proc]();
}

if (!pipe_reload) {
arm_pipe[0] = arm_pipe[1];
arm_pipe[1] = arm_fetch_s();
arm_inc_r15();
}

if (tmr_enb) tick_timers(arm_cycles - cycles);

if (int_halt) arm_cycles = target_cycles;

pipe_reload = false;
if (int_halt) arm_cycles = target_cycles;
}

arm_cycles -= target_cycles;
Expand Down
65 changes: 35 additions & 30 deletions arm_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,74 +53,79 @@ void arm_access_bus(uint32_t address, uint8_t size, access_type_e at) {
}

//Memory read
static void arm_read_bios(uint32_t address) {
if ((address | arm_r.r[15]) < 0x4000) arm_bus = bios[address & 0x3fff];
static uint8_t arm_read_bios(uint32_t address) {
if ((address | arm_r.r[15]) < 0x4000)
return bios[address & 0x3fff];
else
return 0;
}

static void arm_read_wram(uint32_t address) {
arm_bus = wram[address & 0x3ffff];
static uint8_t arm_read_wram(uint32_t address) {
return wram[address & 0x3ffff];
}

static void arm_read_iwram(uint32_t address) {
arm_bus = iwram[address & 0x7fff];
static uint8_t arm_read_iwram(uint32_t address) {
return iwram[address & 0x7fff];
}

static void arm_read_pram(uint32_t address) {
arm_bus = pram[address & 0x3ff];
static uint8_t arm_read_pram(uint32_t address) {
return pram[address & 0x3ff];
}

static void arm_read_vram(uint32_t address) {
arm_bus = vram[address & (address & 0x10000 ? 0x17fff : 0x1ffff)];
static uint8_t arm_read_vram(uint32_t address) {
return vram[address & (address & 0x10000 ? 0x17fff : 0x1ffff)];
}

static void arm_read_oam(uint32_t address) {
arm_bus = oam[address & 0x3ff];
static uint8_t arm_read_oam(uint32_t address) {
return oam[address & 0x3ff];
}

static void arm_read_rom(uint32_t address) {
arm_bus = rom[address & 0x1ffffff];
static uint8_t arm_read_rom(uint32_t address) {
return rom[address & 0x1ffffff];
}

static void arm_read_flash(uint32_t address) {
static uint8_t arm_read_flash(uint32_t address) {
if (flash_id_mode) {
//This is the Flash ROM ID, we return Sanyo ID code
switch (address) {
case 0x0e000000: arm_bus = 0x62; break;
case 0x0e000001: arm_bus = 0x13; break;
case 0x0e000000: return 0x62;
case 0x0e000001: return 0x13;
}
} else {
arm_bus = flash[flash_bank | (address & 0xffff)];
return flash[flash_bank | (address & 0xffff)];
}

return 0;
}

static uint8_t arm_read_(uint32_t address) {
switch (address >> 24) {
case 0x0: arm_read_bios(address); break;
case 0x2: arm_read_wram(address); break;
case 0x3: arm_read_iwram(address); break;
case 0x4: arm_bus = io_read(address); break;
case 0x5: arm_read_pram(address); break;
case 0x6: arm_read_vram(address); break;
case 0x7: arm_read_oam(address); break;
case 0x0: return arm_read_bios(address);
case 0x2: return arm_read_wram(address);
case 0x3: return arm_read_iwram(address);
case 0x4: return io_read(address);
case 0x5: return arm_read_pram(address);
case 0x6: return arm_read_vram(address);
case 0x7: return arm_read_oam(address);

case 0x8:
case 0x9:
arm_read_rom(address); break;
return arm_read_rom(address);

case 0xa:
case 0xb:
arm_read_rom(address); break;
return arm_read_rom(address);

case 0xc:
case 0xd:
arm_read_rom(address); break;
return arm_read_rom(address);

case 0xe:
case 0xf:
arm_read_flash(address); break;
return arm_read_flash(address);
}

return arm_bus;
return 0;
}

static uint8_t arm_readb(uint32_t address) {
Expand Down
2 changes: 0 additions & 2 deletions arm_mem.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ typedef enum {

void arm_access_bus(uint32_t address, uint8_t size, access_type_e at);

uint8_t arm_bus;

uint8_t arm_readb_n(uint32_t address);
uint32_t arm_readh_n(uint32_t address);
uint32_t arm_read_n(uint32_t address);
Expand Down

0 comments on commit 567067b

Please sign in to comment.