kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

aarch64.c (2188B)


      1 /*
      2  * lib/coro/aarch64.c -- AArch64 (AAPCS) implementations of
      3  *   setjmp / longjmp                       (<setjmp.h>)
      4  *   __kit_coro_ctx_init / __kit_coro_switch / trampoline   (<kit/coro.h>)
      5  *
      6  * All three primitives sit on one per-target context layout:
      7  *
      8  *   regs[0..9]    x19-x28
      9  *   regs[10..11]  fp (x29), lr (x30)
     10  *   regs[12]      sp
     11  *   fp_regs[0..7] d8-d15  (low 64 bits of v8-v15; AAPCS only mandates
     12  *                          the lower 64 bits be preserved)
     13  *
     14  * sizeof = 176 (alignof-16 padded), 16-byte aligned. Fits in the
     15  * 256-byte storage carved out by jmp_buf and coro_ctx.
     16  *
     17  * The assembly primitives live in aarch64_elf.s / aarch64_macho.s so this
     18  * translation unit stays plain C and does not require file-scope asm support.
     19  */
     20 
     21 #include <kit/coro.h>
     22 #include <setjmp.h>
     23 #include <stddef.h>
     24 #include <stdint.h>
     25 
     26 struct __kit_arm64_ctx {
     27   uintptr_t regs[13];
     28   uint64_t fp_regs[8];
     29 } __attribute__((aligned(16)));
     30 
     31 _Static_assert(sizeof(struct __kit_arm64_ctx) == 176, "layout");
     32 _Static_assert(_Alignof(struct __kit_arm64_ctx) == 16, "align");
     33 _Static_assert(offsetof(struct __kit_arm64_ctx, fp_regs) == 104, "fp off");
     34 _Static_assert(sizeof(struct __kit_arm64_ctx) <= sizeof(coro_ctx),
     35                "fits coro_ctx");
     36 _Static_assert(sizeof(struct __kit_arm64_ctx) <= sizeof(jmp_buf),
     37                "fits jmp_buf");
     38 _Static_assert(_Alignof(coro_ctx) >= _Alignof(struct __kit_arm64_ctx),
     39                "align coro_ctx");
     40 
     41 extern void __kit_coro_trampoline(void);
     42 
     43 void __kit_coro_ctx_init(coro_ctx* ctx, void* stack_base, size_t stack_len,
     44                          void (*entry)(uintptr_t)) {
     45   struct __kit_arm64_ctx* c = (struct __kit_arm64_ctx*)ctx;
     46 
     47   /* AArch64 stacks grow down; align top to 16. */
     48   uintptr_t top = (uintptr_t)stack_base + stack_len;
     49   top &= ~(uintptr_t)(CORO_STACK_ALIGN - 1);
     50 
     51   for (size_t i = 0; i < sizeof(*c) / sizeof(uintptr_t); ++i)
     52     ((uintptr_t*)c)[i] = 0;
     53 
     54   c->regs[0] = (uintptr_t)entry;                  /* x19 -- entry fn */
     55   c->regs[10] = 0;                                /* fp */
     56   c->regs[11] = (uintptr_t)__kit_coro_trampoline; /* lr */
     57   c->regs[12] = top;                              /* sp */
     58 }