[arm] Fix usermode "movs pc" causing invalid CPU state
A missing usermode check (present in MIPS and x86) causes user-mode returns to attempt returning into another CPU mode, which causes a bunch of issues, mainly going into an invalid CPU state and corrupting some registers. This fixes a couple of games only (Colin McRae Rally 2, TOCA World Touring, Starsky & Hutch ...)
This commit is contained in:
parent
53ac0814de
commit
90170e3389
1 changed files with 6 additions and 3 deletions
|
@ -337,8 +337,10 @@ defsymbl(execute_store_cpsr)
|
||||||
|
|
||||||
defsymbl(execute_spsr_restore)
|
defsymbl(execute_spsr_restore)
|
||||||
save_flags()
|
save_flags()
|
||||||
add r1, reg_base, #SPSR_RAM_OFF @ r1 = spsr
|
|
||||||
ldr r2, [reg_base, #CPU_MODE] @ r2 = cpu_mode
|
ldr r2, [reg_base, #CPU_MODE] @ r2 = cpu_mode
|
||||||
|
cmp r2, #0 @ if usermode already, do not change
|
||||||
|
beq 2f @ just a regular indirect jump really
|
||||||
|
add r1, reg_base, #SPSR_RAM_OFF @ r1 = spsr
|
||||||
ldr r1, [r1, r2, lsl #2] @ r1 = spsr[cpu_mode] (new cpsr)
|
ldr r1, [r1, r2, lsl #2] @ r1 = spsr[cpu_mode] (new cpsr)
|
||||||
str r1, [reg_base, #REG_CPSR] @ update cpsr
|
str r1, [reg_base, #REG_CPSR] @ update cpsr
|
||||||
mov reg_flags, r1 @ also, update shadow flags
|
mov reg_flags, r1 @ also, update shadow flags
|
||||||
|
@ -349,14 +351,15 @@ defsymbl(execute_spsr_restore)
|
||||||
|
|
||||||
ldr r1, [reg_base, #REG_CPSR] @ r1 = cpsr
|
ldr r1, [reg_base, #REG_CPSR] @ r1 = cpsr
|
||||||
tst r1, #0x20 @ see if Thumb mode is set
|
tst r1, #0x20 @ see if Thumb mode is set
|
||||||
bne 2f @ if so handle it
|
bne 1f @ if so handle it
|
||||||
|
|
||||||
load_registers_arm() @ restore ARM registers
|
load_registers_arm() @ restore ARM registers
|
||||||
|
2:
|
||||||
call_c_function(block_lookup_address_arm)
|
call_c_function(block_lookup_address_arm)
|
||||||
restore_flags()
|
restore_flags()
|
||||||
bx r0
|
bx r0
|
||||||
|
|
||||||
2:
|
1:
|
||||||
load_registers_thumb() @ load Thumb registers
|
load_registers_thumb() @ load Thumb registers
|
||||||
call_c_function(block_lookup_address_thumb)
|
call_c_function(block_lookup_address_thumb)
|
||||||
restore_flags()
|
restore_flags()
|
||||||
|
|
Loading…
Add table
Reference in a new issue