master: Resolve more potential issues in arch_do_displaced_inst

stassats via Sbcl-commits <[email protected]> Wed, 20 May 2026 23:46:04 +0000
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  f716ffe01c181bbea195e4a3dc06e50503f5bc39 (commit)
      from  eb1a8630eba871a92f7316fa37126d2996c77999 (commit)

- Log -----------------------------------------------------------------
commit f716ffe01c181bbea195e4a3dc06e50503f5bc39
Author: Stas Boukarev <[email protected]>
Date:   Thu May 21 02:39:40 2026 +0300

    Resolve more potential issues in arch_do_displaced_inst
    
    Update the link register.
    Handle CBZ on 32-bit registers.
---
 src/runtime/arm64-arch.c | 32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/src/runtime/arm64-arch.c b/src/runtime/arm64-arch.c
index 330e46a34..97ad75565 100644
--- a/src/runtime/arm64-arch.c
+++ b/src/runtime/arm64-arch.c
@@ -147,20 +147,27 @@ void arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst)
     if ((orig_inst >> 24) == 0b01010100) {
         // Cond branch
         if (condition_holds(context, orig_inst & 0b1111))
-            next_pc += sign_extend((orig_inst >> 5) & ~(1 << 19), 19);
+            next_pc += sign_extend((orig_inst >> 5) & (1 << 19)-1, 19);
         else
             next_pc += 1;
     }
-    else if (((orig_inst >> 26) & 0b11111) == 0b000101)
+    else if (((orig_inst >> 26) & 0b11111) == 0b000101) {
         // Uncond branch: B, BL
-        next_pc += sign_extend(orig_inst & ~(1 << 26), 26);
+        if ((orig_inst >> 31) & 1) { // BL
+            *os_context_register_addr(context, reg_LR) = (uword_t)(pc + 1);
+        }
+        next_pc += sign_extend(orig_inst & (1 << 26)-1, 26);
+    }
     else if (((orig_inst >> 25) & 0b1111111) == 0b1101011) {
         int rt;
         // Uncond branch register
         switch ((orig_inst >> 21) & 0b1111) {
         case 0b00: // BR
+            rt = (orig_inst >> 5) & 0b11111;
+            break;
         case 0b01: // BLR
             rt = (orig_inst >> 5) & 0b11111;
+            *os_context_register_addr(context, reg_LR) = (uword_t)(pc + 1);
             break;
         case 0b10: // RET
             rt = reg_LR;
@@ -172,22 +179,27 @@ void arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst)
         next_pc = (unsigned int*)*os_context_register_addr(context, rt);
     }
     else if (((orig_inst >> 25) & 0b111111) == 0b011010) {
-        // Compare branch imm
+        // CBZ
         bool op = (orig_inst >> 24) & 0b1;
-        int offset = sign_extend((orig_inst >> 5) & ~(1 << 19), 19);
+        int size = (orig_inst >> 31) & 0b1;
+        int offset = sign_extend((orig_inst >> 5) & (1 << 19)-1, 19);
         int rt = orig_inst & 0b11111;
-        if ((!*os_context_register_addr(context, rt)) ^ op)
+        uword_t val = (*os_context_register_addr(context, rt));
+        if (!size) {
+            val &= 0xFFFFFFFF;
+        }
+        if ((!val) ^ op)
             next_pc += offset;
         else
             next_pc += 1;
     }
     else if (((orig_inst >> 25) & 0b111111) == 0b011011) {
-        // Test branch imm
+        // TBZ
         bool b5 = (orig_inst >> 31) & 0b1;
         bool op = (orig_inst >> 24) & 0b1;
-        bool b40 = (orig_inst >> 19) & 0b11111;
+        int b40 = (orig_inst >> 19) & 0b11111;
         int bit_pos = (b5 << 5) | b40;
-        int offset = sign_extend((orig_inst >> 5) & ~(1 << 14), 14);
+        int offset = sign_extend((orig_inst >> 5) & (1 << 14)-1, 14);
         int rt = orig_inst & 0b11111;
         if (((*os_context_register_addr(context, rt) >> bit_pos) & 0b1) ^ op)
             next_pc += offset;
@@ -198,7 +210,7 @@ void arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst)
         // LDR (literal)
         int opc = (orig_inst >> 30) & 0b11;
         int rt = orig_inst & 0b11111;
-        int offset = sign_extend((orig_inst >> 5) & ~(1 << 19), 19);
+        int offset = sign_extend((orig_inst >> 5) & (1 << 19)-1, 19);
         unsigned int *new_pc = (pc + offset);
 
         if (opc == 0b01)

-----------------------------------------------------------------------


hooks/post-receive
-- 
SBCL