#ifndef COSMOPOLITAN_LIBC_CALLS_UCONTEXT_H_
#define COSMOPOLITAN_LIBC_CALLS_UCONTEXT_H_
#include "libc/calls/struct/sigaltstack.h"
#include "libc/calls/struct/sigset.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_

#define REG_R8      REG_R8
#define REG_R9      REG_R9
#define REG_R10     REG_R10
#define REG_R11     REG_R11
#define REG_R12     REG_R12
#define REG_R13     REG_R13
#define REG_R14     REG_R14
#define REG_R15     REG_R15
#define REG_RDI     REG_RDI
#define REG_RSI     REG_RSI
#define REG_RBP     REG_RBP
#define REG_RBX     REG_RBX
#define REG_RDX     REG_RDX
#define REG_RAX     REG_RAX
#define REG_RCX     REG_RCX
#define REG_RSP     REG_RSP
#define REG_RIP     REG_RIP
#define REG_EFL     REG_EFL
#define REG_CSGSFS  REG_CSGSFS
#define REG_ERR     REG_ERR
#define REG_TRAPNO  REG_TRAPNO
#define REG_OLDMASK REG_OLDMASK
#define REG_CR2     REG_CR2

enum GeneralRegister {
  REG_R8,
  REG_R9,
  REG_R10,
  REG_R11,
  REG_R12,
  REG_R13,
  REG_R14,
  REG_R15,
  REG_RDI,
  REG_RSI,
  REG_RBP,
  REG_RBX,
  REG_RDX,
  REG_RAX,
  REG_RCX,
  REG_RSP,
  REG_RIP,
  REG_EFL,
  REG_CSGSFS,
  REG_ERR,
  REG_TRAPNO,
  REG_OLDMASK,
  REG_CR2
};

struct XmmRegister {
  uint64_t u64[2];
};

struct FpuStackEntry {
  uint16_t significand[4];
  uint16_t exponent;
  uint16_t padding[3];
};

struct thatispacked FpuState {
  uint16_t cwd;
  uint16_t swd;
  uint16_t ftw;
  uint16_t fop;
  uint64_t rip;
  uint64_t rdp;
  uint32_t mxcsr;
  uint32_t mxcr_mask;
  struct FpuStackEntry st[8];
  struct XmmRegister xmm[16];
  uint32_t __padding[24];
};

typedef uint64_t greg_t;
typedef greg_t gregset_t[23];
typedef struct FpuState *fpregset_t;

struct MachineContext {
  union {
    struct {
      uint64_t r8;
      uint64_t r9;
      uint64_t r10;
      uint64_t r11;
      uint64_t r12;
      uint64_t r13;
      uint64_t r14;
      uint64_t r15;
      uint64_t rdi;
      uint64_t rsi;
      uint64_t rbp;
      uint64_t rbx;
      uint64_t rdx;
      uint64_t rax;
      uint64_t rcx;
      uint64_t rsp;
      uint64_t rip;
      uint64_t eflags;
      uint16_t cs;
      uint16_t gs;
      uint16_t fs;
      uint16_t __pad0;
      uint64_t err;
      uint64_t trapno;
      uint64_t oldmask;
      uint64_t cr2;
    };
    gregset_t gregs;
  };
  struct FpuState *fpregs;
  uint64_t __pad1[8];
};

typedef struct MachineContext mcontext_t;

struct ucontext {
  uint64_t uc_flags;
  struct ucontext *uc_link;
  stack_t uc_stack;
  mcontext_t uc_mcontext; /* use this */
  sigset_t uc_sigmask;
  struct FpuState __fpustate; /* for cosmo on non-linux */
};

typedef struct ucontext ucontext_t;

COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_UCONTEXT_H_ */
