mirror of
https://github.com/SerenityOS/serenity.git
synced 2026-11-07 04:29:30 -10:00
LibC: Implement setjmp and longjmp for aarch64
This implementation is based on the riscv64 version.
This commit is contained in:
1 parent
c5d713864b
commit
cc6d0fb858
2 files changed
+70
-11
No files matched your search
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user