Fix SWI handling (disable IRQs)
This introduced a potential race condition between the start of a SWI and the BIOS handling the exception by returning to system mode. During this ~10 instruction window, having an IRQ that issues a SWI causes bad behaviour that results in crashes or other weirdness. Fixes a couple of games and potentially many weird and obscure bugs here and there (hard to reproduce sometimes).
This commit is contained in:
parent
ed89923fda
commit
3cab8596b8
|
@ -410,7 +410,7 @@ defsymbl(execute_swi_##mode) ;\
|
|||
add r1, reg_base, #SPSR_RAM_OFF /* r1 = spsr */;\
|
||||
str r0, [r1, #(MODE_SUPERVISOR * 4)] /* spsr[MODE_SUPERVISOR] = cpsr */;\
|
||||
bic r0, r0, #0x3F /* clear mode flag in r0 */;\
|
||||
orr r0, r0, #0x13 /* set to supervisor mode */;\
|
||||
orr r0, r0, #(0x13 | 0x80) /* supervisor mode + disable IRQ */;\
|
||||
str r0, [reg_base, #REG_CPSR] /* update cpsr */;\
|
||||
;\
|
||||
mov r0, #MODE_SUPERVISOR ;\
|
||||
|
|
6
cpu.c
6
cpu.c
|
@ -3197,7 +3197,8 @@ arm_loop:
|
|||
spsr[MODE_SUPERVISOR] = reg[REG_CPSR];
|
||||
reg[REG_PC] = 0x00000008;
|
||||
arm_update_pc();
|
||||
reg[REG_CPSR] = (reg[REG_CPSR] & ~0x1F) | 0x13;
|
||||
// Move to ARM mode, Supervisor mode and disable IRQs
|
||||
reg[REG_CPSR] = (reg[REG_CPSR] & ~0x3F) | 0x13 | 0x80;
|
||||
set_cpu_mode(MODE_SUPERVISOR);
|
||||
break;
|
||||
}
|
||||
|
@ -3682,7 +3683,8 @@ thumb_loop:
|
|||
spsr[MODE_SUPERVISOR] = reg[REG_CPSR];
|
||||
reg[REG_PC] = 0x00000008;
|
||||
thumb_update_pc();
|
||||
reg[REG_CPSR] = (reg[REG_CPSR] & ~0x3F) | 0x13;
|
||||
// Move to ARM mode, Supervisor mode and disable IRQs
|
||||
reg[REG_CPSR] = (reg[REG_CPSR] & ~0x3F) | 0x13 | 0x80;
|
||||
set_cpu_mode(MODE_SUPERVISOR);
|
||||
collapse_flags();
|
||||
goto arm_loop;
|
||||
|
|
|
@ -409,7 +409,7 @@ defsymbl(execute_swi)
|
|||
sw $2, SUPERVISOR_SPSR($16) # save cpsr in SUPERVISOR_CPSR
|
||||
srl $2, $2, 6 # zero out bottom 6 bits of CPSR
|
||||
sll $2, $2, 6
|
||||
ori $2, 0x13 # set mode to supervisor
|
||||
ori $2, (0x13 | 0x80) # mode supervisor + disable IRQs
|
||||
sw $2, REG_CPSR($16) # write back CPSR
|
||||
save_registers
|
||||
li $4, 3 # 3 is supervisor mode
|
||||
|
|
|
@ -2179,7 +2179,8 @@ static void function_cc execute_swi(u32 pc)
|
|||
bios_read_protect = 0xe3a02004;
|
||||
reg_mode[MODE_SUPERVISOR][6] = pc;
|
||||
spsr[MODE_SUPERVISOR] = reg[REG_CPSR];
|
||||
reg[REG_CPSR] = (reg[REG_CPSR] & ~0x3F) | 0x13;
|
||||
// Move to ARM mode, supervisor mode, disable IRQs
|
||||
reg[REG_CPSR] = (reg[REG_CPSR] & ~0x3F) | 0x13 | 0x80;
|
||||
set_cpu_mode(MODE_SUPERVISOR);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue