summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Guillen Fandos2021-04-27 19:05:00 +0200
committerDavid G. F2021-04-27 18:39:46 +0200
commitd83f8fbd25562dcebf26e0e71d346bc41820e239 (patch)
tree00a5aeec46adc303c7cbcfd180cdde356b8a6526
parentff48af07b08c0870ea950335fec338a828f88c27 (diff)
downloadpicogpsp-d83f8fbd25562dcebf26e0e71d346bc41820e239.tar.gz
picogpsp-d83f8fbd25562dcebf26e0e71d346bc41820e239.tar.bz2
picogpsp-d83f8fbd25562dcebf26e0e71d346bc41820e239.zip
Fix Vita port and likely some Linux/Android hidden issues
Using an invalid SP makes Vita crash (for an unkown reason) and makes things like C signal handlers crash (luckily Retroarch doesn't use them). It is also a violation of the ABI and not a great idea. Recycled some little used registers to free SP. Perf should be roughly the same.
-rw-r--r--arm/arm_emit.h18
-rw-r--r--arm/arm_stub.S13
2 files changed, 15 insertions, 16 deletions
diff --git a/arm/arm_emit.h b/arm/arm_emit.h
index a6951c2..1432617 100644
--- a/arm/arm_emit.h
+++ b/arm/arm_emit.h
@@ -67,9 +67,10 @@ void execute_store_u32_safe(u32 address, u32 source);
#define reg_a1 ARMREG_R1
#define reg_a2 ARMREG_R2
+/* scratch0 is shared with flags, be careful! */
#define reg_s0 ARMREG_R9
-#define reg_base ARMREG_SP
-#define reg_flags ARMREG_R11
+#define reg_base ARMREG_R11
+#define reg_flags ARMREG_R9
#define reg_cycles ARMREG_R12
@@ -110,6 +111,7 @@ void execute_store_u32_safe(u32 address, u32 source);
#define reg_x5 ARMREG_R8
#define mem_reg (~0U)
+#define save1_reg 21
/*
@@ -1415,7 +1417,6 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address)
#define arm_block_memory_adjust_pc_load() \
if(reg_list & 0x8000) \
{ \
- generate_mov(reg_a0, reg_rv); \
generate_indirect_branch_arm(); \
} \
@@ -1463,12 +1464,14 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address)
arm_block_memory_offset_##offset_type(); \
arm_block_memory_writeback_##access_type(writeback_type); \
ARM_BIC_REG_IMM(0, reg_s0, reg_s0, 0x03, 0); \
+ generate_store_reg(reg_s0, save1_reg); \
\
for(i = 0; i < 16; i++) \
{ \
if((reg_list >> i) & 0x01) \
{ \
cycle_count++; \
+ generate_load_reg(reg_s0, save1_reg); \
generate_add_reg_reg_imm(reg_a0, reg_s0, offset, 0); \
if(reg_list & ~((2 << i) - 1)) \
{ \
@@ -1493,12 +1496,12 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address)
generate_load_reg(reg_a0, rn); \
generate_function_call(execute_load_##type); \
write32((pc + 8)); \
- generate_mov(reg_s0, reg_rv); \
+ generate_mov(reg_a2, reg_rv); \
generate_load_reg(reg_a0, rn); \
generate_load_reg(reg_a1, rm); \
+ generate_store_reg(reg_a2, rd); \
generate_function_call(execute_store_##type); \
write32((pc + 4)); \
- generate_store_reg(reg_s0, rd); \
} \
@@ -1729,13 +1732,14 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address)
#define thumb_block_memory_extra_down() \
#define thumb_block_memory_extra_pop_pc() \
+ generate_load_reg(reg_s0, save1_reg); \
generate_add_reg_reg_imm(reg_a0, reg_s0, (bit_count[reg_list] * 4), 0); \
generate_function_call(execute_load_u32); \
write32((pc + 4)); \
- generate_mov(reg_a0, reg_rv); \
generate_indirect_branch_cycle_update(thumb) \
#define thumb_block_memory_extra_push_lr(base_reg) \
+ generate_load_reg(reg_s0, save1_reg); \
generate_add_reg_reg_imm(reg_a0, reg_s0, (bit_count[reg_list] * 4), 0); \
generate_load_reg(reg_a1, REG_LR); \
generate_function_call(execute_store_u32_safe) \
@@ -1782,12 +1786,14 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address)
ARM_BIC_REG_IMM(0, reg_s0, reg_s0, 0x03, 0); \
thumb_block_address_preadjust_##pre_op(); \
thumb_block_address_postadjust_##post_op(base_reg); \
+ generate_store_reg(reg_s0, save1_reg); \
\
for(i = 0; i < 8; i++) \
{ \
if((reg_list >> i) & 0x01) \
{ \
cycle_count++; \
+ generate_load_reg(reg_s0, save1_reg); \
generate_add_reg_reg_imm(reg_a0, reg_s0, offset, 0); \
if(reg_list & ~((2 << i) - 1)) \
{ \
diff --git a/arm/arm_stub.S b/arm/arm_stub.S
index b8651cf..944d36a 100644
--- a/arm/arm_stub.S
+++ b/arm/arm_stub.S
@@ -45,15 +45,14 @@ _##symbol:
#define CHANGED_PC_STATUS (31 * 4)
#define COMPLETED_FRAME (32 * 4)
#define OAM_UPDATED (33 * 4)
-#define MAIN_THREAD_SP (34 * 4)
#define reg_a0 r0
#define reg_a1 r1
#define reg_a2 r2
#define reg_s0 r9
-#define reg_base sp
-#define reg_flags r11
+#define reg_base r11
+#define reg_flags r9
#define reg_cycles r12
@@ -151,11 +150,9 @@ _##symbol:
@ registers which are important to the dynarec.
#define call_c_function(function) ;\
- ldr sp, [reg_base, #MAIN_THREAD_SP] ;\
stmdb sp!, { call_c_saved_regs } ;\
bl function ;\
ldmia sp!, { call_c_saved_regs } ;\
- ldr sp, =reg ;\
@ Jumps to PC (ARM or Thumb modes)
@ This is really two functions/routines in one
@@ -483,9 +480,7 @@ defsymbl(execute_arm_translate)
@ save the registers to be able to return later
stmdb sp!, { r4, r5, r6, r7, r8, r9, r10, r11, r12, lr }
- ldr r1, =reg @ reg to r1
- str sp, [r1, #MAIN_THREAD_SP] @ store the current sp
- ldr sp, =reg @ reg_base = sp (loading addr)
+ ldr reg_base, =reg @ init base_reg
mvn reg_cycles, r0 @ load cycle counter
@@ -515,8 +510,6 @@ defsymbl(execute_arm_translate)
@ Epilogue to return to the main thread (whatever called execute_arm_translate)
return_to_main:
- @ restore the stack pointer
- ldr sp, [reg_base, #MAIN_THREAD_SP]
@ restore the saved regs and return
ldmia sp!, { r4, r5, r6, r7, r8, r9, r10, r11, r12, lr }
bx lr