[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