summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Guillen Fandos2021-07-05 18:19:19 +0200
committerDavid Guillen Fandos2021-07-05 18:19:19 +0200
commit0ca87a4807b4d26baef3b7813e1b948b88dddf79 (patch)
tree8b714783abf6a46e3511a68ee8a0d31b602f6124
parent3d874ec5e3d5675ae9513264d857a3c6c9d2417c (diff)
downloadpicogpsp-0ca87a4807b4d26baef3b7813e1b948b88dddf79.tar.gz
picogpsp-0ca87a4807b4d26baef3b7813e1b948b88dddf79.tar.bz2
picogpsp-0ca87a4807b4d26baef3b7813e1b948b88dddf79.zip
Fix conditional ARM instructions at the end of a translation block
This fixes issue #133 The explanation is as follows. Most blocks end on an inconditional jump/branch, but there's two cases where this doesn't happen: translation gates and when we hit MAX_EXITS. These are very uncommon cases and therefore more prone to hidden bugs. When this happens, the last instruction emits a conditional jump (via arm_conditional_block_header macro) which is patched by a later instruction via generate_branch_patch_conditional. Typically the last unconditional branch will trigger the patching condition (which is aproximately condition != last_condition), but in these two cases it might not happen, leaving an unpatched branch. This makes x86 and ARM dynarecs crash in interesting ways (although it might not crash depending on $stuff and make the bug even harder to track).
-rw-r--r--cpu_threaded.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/cpu_threaded.c b/cpu_threaded.c
index 557b197..2d61b4a 100644
--- a/cpu_threaded.c
+++ b/cpu_threaded.c
@@ -3115,6 +3115,12 @@ s32 translate_block_arm(u32 pc, translation_region_type
generate_cycle_update();
}
}
+
+ /* This can happen if the last instruction is *not* inconditional */
+ if ((last_condition & 0x0F) != 0x0E) {
+ generate_branch_patch_conditional(backpatch_address, translation_ptr);
+ }
+
for(i = 0; i < translation_gate_targets; i++)
{
if(pc == translation_gate_target_pc[i])