LibC: Implement setjmp and longjmp for aarch64

This implementation is based on the riscv64 version.
This commit is contained in:
Sönke Holz committed 2025-06-21 12:55:20 +02:00
1 parent c5d713864b
commit cc6d0fb858
2 files changed
+70 -11

No files matched your search

+65 -8
View File
@@ -1,26 +1,83 @@
/*
* Copyright (c) 2021, Nico Weber <thakis@chromium.org>
* Copyright (c) 2025, Sönke Holz <sholz8530@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
//
// /!\ Read setjmp.h before modifying this file!
//
#define DID_SAVE_SIGNAL_MASK_SLOT (21 * 8)
#define SAVED_SIGNAL_MASK_SLOT (21 * 8 + 4)
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/setjmp.html
// int setjmp(jmp_buf env)
// int _setjmp(jmp_buf env)
.global _setjmp
.global setjmp
_setjmp:
setjmp:
# FIXME: Possibly incomplete.
mov x1, #0 // Set savemask argument to 0
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigsetjmp.html
// int sigsetjmp(sigjmp_buf env, int savemask)
.global sigsetjmp
sigsetjmp:
str w1, [x0, #DID_SAVE_SIGNAL_MASK_SLOT] // Store savemask into did_save_signal_mask
str wzr, [x0, #SAVED_SIGNAL_MASK_SLOT] // Clear saved_signal_mask
cbz w1, .Lsaveregs
stp x0, lr, [sp, #-16]! // Prepare ABI-compliant call to sigprocmask
add x2, x0, #SAVED_SIGNAL_MASK_SLOT // Set argument oldset
mov x1, #0 // Set argument set
mov x0, #0 // Set argument how
bl sigprocmask
ldp x0, lr, [sp], #16
.Lsaveregs:
stp x19, x20, [x0, #(0 * 8)] // Save registers
stp x21, x22, [x0, #(2 * 8)]
stp x23, x24, [x0, #(4 * 8)]
stp x25, x26, [x0, #(6 * 8)]
stp x27, x28, [x0, #(8 * 8)]
stp x29, x30, [x0, #(10 * 8)]
stp d8, d9, [x0, #(12 * 8)]
stp d10, d11, [x0, #(14 * 8)]
stp d12, d13, [x0, #(16 * 8)]
stp d14, d15, [x0, #(18 * 8)]
mov x1, sp
str x1, [x0, #(20 * 8)]
mov x0, #0
ret
.global _longjmp
.global longjmp
_longjmp:
longjmp:
# FIXME: Possibly incomplete.
ret
ldp x19, x20, [x0, #(0 * 8)] // Restore registers
ldp x21, x22, [x0, #(2 * 8)]
ldp x23, x24, [x0, #(4 * 8)]
ldp x25, x26, [x0, #(6 * 8)]
ldp x27, x28, [x0, #(8 * 8)]
ldp x29, x30, [x0, #(10 * 8)]
.global _sigsetjmp
.global sigsetjmp
_sigsetjmp:
sigsetjmp:
# FIXME: Possibly incomplete.
ldp d8, d9, [x0, #(12 * 8)]
ldp d10, d11, [x0, #(14 * 8)]
ldp d12, d13, [x0, #(16 * 8)]
ldp d14, d15, [x0, #(18 * 8)]
ldr x2, [x0, #(20 * 8)]
mov sp, x2
mov x0, x1
cbnz x0, .Lnonzero
mov x0, #1
.Lnonzero:
ret
+5 -3
View File
@@ -29,8 +29,10 @@ struct __jmp_buf {
uint64_t rsp;
uint64_t rip;
#elif defined(__aarch64__)
// FIXME: This is likely incorrect.
uint64_t regs[22];
uint64_t x19_to_x29[11];
uint64_t lr;
uint64_t d8_to_d15[8];
uint64_t sp;
#elif defined(__riscv) && __riscv_xlen == 64
uint64_t s[12];
uint64_t fs[12];
@@ -53,7 +55,7 @@ typedef struct __jmp_buf sigjmp_buf[1];
# if defined(__x86_64__)
static_assert(sizeof(struct __jmp_buf) == 72, "struct __jmp_buf unsynchronized with x86_64/setjmp.S");
# elif defined(__aarch64__)
static_assert(sizeof(struct __jmp_buf) == 184, "struct __jmp_buf unsynchronized with aarch64/setjmp.S");
static_assert(sizeof(struct __jmp_buf) == 176, "struct __jmp_buf unsynchronized with aarch64/setjmp.S");
# elif defined(__riscv) && __riscv_xlen == 64
static_assert(sizeof(struct __jmp_buf) == 216, "struct __jmp_buf unsynchronized with riscv64/setjmp.S");
# else