Skip to content

Commit 19417e9

Browse files
committed
crates/asm: fix aarch64 stack alignment and add bcmp/memcmp
aarch64 logical instructions encode register 31 as xzr, not sp, so `and sp, sp, #-16` is an invalid operand. Use a temp register (x9) to align the stack instead. Also add bcmp and memcmp implementations needed for -static linking without libc (riscv64 codegen emits calls to bcmp for byte comparisons).
1 parent 09f784f commit 19417e9

1 file changed

Lines changed: 34 additions & 4 deletions

File tree

crates/asm/src/lib.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,33 @@ pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 {
5555
s
5656
}
5757

58+
/// Compares two byte sequences.
59+
///
60+
/// # Safety
61+
///
62+
/// `s1` and `s2` must be valid pointers to memory of at least `n` bytes.
63+
#[unsafe(no_mangle)]
64+
pub unsafe extern "C" fn bcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
65+
for i in 0..n {
66+
let a = unsafe { *s1.add(i) };
67+
let b = unsafe { *s2.add(i) };
68+
if a != b {
69+
return i32::from(a) - i32::from(b);
70+
}
71+
}
72+
0
73+
}
74+
75+
/// Compares two byte sequences.
76+
///
77+
/// # Safety
78+
///
79+
/// `s1` and `s2` must be valid pointers to memory of at least `n` bytes.
80+
#[unsafe(no_mangle)]
81+
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
82+
unsafe { bcmp(s1, s2, n) }
83+
}
84+
5885
/// Calculates the length of a null-terminated string.
5986
///
6087
/// # Safety
@@ -198,13 +225,16 @@ mod entry {
198225
// Move stack pointer to first argument register
199226
"mov x0, sp",
200227
// Align stack to 16-byte boundary (AArch64 ABI requirement)
201-
"and sp, sp, -16",
228+
// Note: `and sp, sp, #imm` is invalid because logical instructions
229+
// encode register 31 as xzr, not sp. Use a temp register instead.
230+
"mov x9, sp",
231+
"and x9, x9, #-16",
232+
"mov sp, x9",
202233
// Call into Rust code
203234
"bl {entry_rust}",
204-
// Move return code to syscall argument
205-
"mov x0, x0",
235+
// Return code is already in x0 from entry_rust
206236
// Exit syscall
207-
"mov x8, 93", // SYS_exit
237+
"mov x8, #93", // SYS_exit
208238
"svc #0",
209239
entry_rust = sym super::entry_rust,
210240
);

0 commit comments

Comments
 (0)