[dynarec] "Fix" ARM-mode STM instruction writeback

Move writeback to the end of the instruction (instead of the start).
This is also wrong but fixes some common cases (ie. push sp).
This commit is contained in:
David Guillen Fandos 2023-11-21 23:35:07 +01:00
parent ebbcdc852e
commit 904eaa2fa7
4 changed files with 51 additions and 39 deletions

View File

@ -1379,12 +1379,13 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address, u32 store_mask)
generate_load_reg_pc(reg_a1, i, 8); \
generate_function_call(execute_aligned_store32) \
#define arm_block_memory_final_load() \
#define arm_block_memory_final_load(writeback_type) \
arm_block_memory_load() \
#define arm_block_memory_final_store() \
#define arm_block_memory_final_store(writeback_type) \
generate_load_pc(reg_a2, (pc + 4)); \
generate_load_reg(reg_a1, i) \
arm_block_memory_writeback_post_store(writeback_type); \
generate_function_call(execute_store_u32); \
#define arm_block_memory_adjust_pc_store() \
@ -1417,13 +1418,14 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address, u32 store_mask)
// Only emit writeback if the register is not in the list
#define arm_block_memory_writeback_load(writeback_type) \
#define arm_block_memory_writeback_pre_load(writeback_type) \
if(!((reg_list >> rn) & 0x01)) \
{ \
arm_block_memory_writeback_##writeback_type(); \
} \
#define arm_block_memory_writeback_store(writeback_type) \
#define arm_block_memory_writeback_pre_store(writeback_type)
#define arm_block_memory_writeback_post_store(writeback_type) \
arm_block_memory_writeback_##writeback_type() \
#define arm_block_memory(access_type, offset_type, writeback_type, s_bit) \
@ -1434,7 +1436,7 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address, u32 store_mask)
u32 base_reg = arm_to_a64_reg[rn]; \
\
arm_block_memory_offset_##offset_type(); \
arm_block_memory_writeback_##access_type(writeback_type); \
arm_block_memory_writeback_pre_##access_type(writeback_type); \
\
{ \
aa64_emit_andi(reg_save0, reg_save0, 30, 29); /* clear 2 LSB */ \
@ -1452,7 +1454,7 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address, u32 store_mask)
} \
else \
{ \
arm_block_memory_final_##access_type(); \
arm_block_memory_final_##access_type(writeback_type); \
break; \
} \
} \

View File

@ -1485,11 +1485,12 @@ static void trace_instruction(u32 pc, u32 mode)
arm_generate_load_reg_pc(reg_a1, i, 8); \
generate_store_call_u32_safe() \
#define arm_block_memory_final_load() \
#define arm_block_memory_final_load(writeback_type) \
arm_block_memory_load() \
#define arm_block_memory_final_store() \
#define arm_block_memory_final_store(writeback_type) \
arm_generate_load_reg_pc(reg_a1, i, 12); \
arm_block_memory_writeback_post_store(writeback_type); \
generate_store_call_u32(); \
write32((pc + 4)) \
@ -1513,28 +1514,30 @@ static void trace_instruction(u32 pc, u32 mode)
generate_add_imm(reg_s0, 4, 0) \
#define arm_block_memory_writeback_down() \
arm_generate_load_reg(reg_a0, rn); \
generate_sub_imm(reg_a0, (word_bit_count(reg_list) * 4), 0); \
arm_generate_store_reg(reg_a0, rn) \
arm_generate_load_reg(reg_a2, rn); \
generate_sub_imm(reg_a2, (word_bit_count(reg_list) * 4), 0); \
arm_generate_store_reg(reg_a2, rn) \
#define arm_block_memory_writeback_up() \
arm_generate_load_reg(reg_a0, rn); \
generate_add_imm(reg_a0, (word_bit_count(reg_list) * 4), 0); \
arm_generate_store_reg(reg_a0, rn) \
arm_generate_load_reg(reg_a2, rn); \
generate_add_imm(reg_a2, (word_bit_count(reg_list) * 4), 0); \
arm_generate_store_reg(reg_a2, rn) \
#define arm_block_memory_writeback_no()
/* Only emit writeback if the register is not in the list */
#define arm_block_memory_writeback_load(writeback_type) \
#define arm_block_memory_writeback_pre_load(writeback_type) \
if(!((reg_list >> rn) & 0x01)) \
{ \
arm_block_memory_writeback_##writeback_type(); \
} \
#define arm_block_memory_writeback_store(writeback_type) \
#define arm_block_memory_writeback_post_store(writeback_type) \
arm_block_memory_writeback_##writeback_type() \
#define arm_block_memory_writeback_pre_store(writeback_type)
#define arm_block_memory(access_type, offset_type, writeback_type, s_bit) \
{ \
arm_decode_block_trans(); \
@ -1543,7 +1546,7 @@ static void trace_instruction(u32 pc, u32 mode)
\
arm_generate_load_reg(reg_s0, rn); \
arm_block_memory_offset_##offset_type(); \
arm_block_memory_writeback_##access_type(writeback_type); \
arm_block_memory_writeback_pre_##access_type(writeback_type); \
ARM_BIC_REG_IMM(0, reg_s0, reg_s0, 0x03, 0); \
arm_generate_store_reg(reg_s0, REG_SAVE); \
\
@ -1561,7 +1564,7 @@ static void trace_instruction(u32 pc, u32 mode)
} \
else \
{ \
arm_block_memory_final_##access_type(); \
arm_block_memory_final_##access_type(writeback_type); \
break; \
} \
} \

View File

@ -1309,13 +1309,14 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address)
generate_load_reg_pc(reg_a1, i, 8); \
generate_function_call_swap_delay(execute_aligned_store32) \
#define arm_block_memory_final_load() \
#define arm_block_memory_final_load(writeback_type) \
arm_block_memory_load() \
#define arm_block_memory_final_store() \
#define arm_block_memory_final_store(writeback_type) \
generate_load_pc(reg_a2, (pc + 4)); \
mips_emit_jal(mips_absolute_offset(execute_store_u32)); \
generate_load_reg(reg_a1, i) \
generate_load_reg(reg_a1, i); \
arm_block_memory_writeback_post_store(writeback_type); \
generate_function_call_swap_delay(execute_store_u32); \
#define arm_block_memory_adjust_pc_store() \
@ -1366,13 +1367,15 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address)
// Only emit writeback if the register is not in the list
#define arm_block_memory_writeback_load(writeback_type) \
#define arm_block_memory_writeback_post_load(writeback_type)
#define arm_block_memory_writeback_pre_load(writeback_type) \
if(!((reg_list >> rn) & 0x01)) \
{ \
arm_block_memory_writeback_##writeback_type(); \
} \
#define arm_block_memory_writeback_store(writeback_type) \
#define arm_block_memory_writeback_pre_store(writeback_type)
#define arm_block_memory_writeback_post_store(writeback_type) \
arm_block_memory_writeback_##writeback_type() \
#define arm_block_memory(access_type, offset_type, writeback_type, s_bit) \
@ -1383,7 +1386,7 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address)
u32 base_reg = arm_to_mips_reg[rn]; \
\
arm_block_memory_offset_##offset_type(); \
arm_block_memory_writeback_##access_type(writeback_type); \
arm_block_memory_writeback_pre_##access_type(writeback_type); \
\
if(rn == REG_SP) \
{ \
@ -1409,6 +1412,7 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address)
} \
} \
\
arm_block_memory_writeback_post_##access_type(writeback_type); \
arm_block_memory_sp_adjust_pc_##access_type(); \
} \
else \
@ -1428,7 +1432,7 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address)
} \
else \
{ \
arm_block_memory_final_##access_type(); \
arm_block_memory_final_##access_type(writeback_type); \
break; \
} \
} \

View File

@ -1504,11 +1504,12 @@ u32 execute_store_cpsr_body()
generate_load_reg_pc(a1, i, 8); \
generate_function_call(execute_store_aligned_u32) \
#define arm_block_memory_final_load() \
#define arm_block_memory_final_load(writeback_type) \
arm_block_memory_load() \
#define arm_block_memory_final_store() \
#define arm_block_memory_final_store(writeback_type) \
generate_load_reg_pc(a1, i, 12); \
arm_block_memory_writeback_post_store(writeback_type); \
generate_store_reg_i32(pc + 4, REG_PC); \
generate_function_call(execute_store_u32) \
@ -1532,26 +1533,28 @@ u32 execute_store_cpsr_body()
generate_add_imm(a0, 4) \
#define arm_block_memory_writeback_down() \
generate_load_reg(a0, rn) \
generate_add_imm(a0, -(word_bit_count(reg_list) * 4)); \
generate_store_reg(a0, rn) \
generate_load_reg(a2, rn) \
generate_add_imm(a2, -(word_bit_count(reg_list) * 4)); \
generate_store_reg(a2, rn) \
#define arm_block_memory_writeback_up() \
generate_load_reg(a0, rn); \
generate_add_imm(a0, (word_bit_count(reg_list) * 4)); \
generate_store_reg(a0, rn) \
generate_load_reg(a2, rn); \
generate_add_imm(a2, (word_bit_count(reg_list) * 4)); \
generate_store_reg(a2, rn) \
#define arm_block_memory_writeback_no()
// Only emit writeback if the register is not in the list
#define arm_block_memory_writeback_load(writeback_type) \
#define arm_block_memory_writeback_pre_load(writeback_type) \
if(!((reg_list >> rn) & 0x01)) \
{ \
arm_block_memory_writeback_##writeback_type(); \
} \
#define arm_block_memory_writeback_store(writeback_type) \
#define arm_block_memory_writeback_pre_store(writeback_type) \
#define arm_block_memory_writeback_post_store(writeback_type) \
arm_block_memory_writeback_##writeback_type() \
#define arm_block_memory(access_type, offset_type, writeback_type, s_bit) \
@ -1564,14 +1567,14 @@ u32 execute_store_cpsr_body()
arm_block_memory_offset_##offset_type(); \
generate_and_imm(a0, ~0x03); \
generate_store_reg(a0, REG_SAVE3); \
arm_block_memory_writeback_##access_type(writeback_type); \
arm_block_memory_writeback_pre_##access_type(writeback_type); \
\
for(i = 0; i < 16; i++) \
{ \
if((reg_list >> i) & 0x01) \
{ \
cycle_count++; \
generate_load_reg(a0, REG_SAVE3); \
generate_load_reg(a0, REG_SAVE3); \
generate_add_imm(a0, offset) \
if(reg_list & ~((2 << i) - 1)) \
{ \
@ -1580,7 +1583,7 @@ u32 execute_store_cpsr_body()
} \
else \
{ \
arm_block_memory_final_##access_type(); \
arm_block_memory_final_##access_type(writeback_type); \
} \
} \
} \