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