#ifndef UAPI_COMPEL_ASM_SIGFRAME_H__
#define UAPI_COMPEL_ASM_SIGFRAME_H__

#include <compel/asm/infect-types.h>

/* Copied from the Linux kernel header arch/arm/include/asm/sigcontext.h */

struct rt_sigcontext {
	unsigned long trap_no;
	unsigned long error_code;
	unsigned long oldmask;
	unsigned long arm_r0;
	unsigned long arm_r1;
	unsigned long arm_r2;
	unsigned long arm_r3;
	unsigned long arm_r4;
	unsigned long arm_r5;
	unsigned long arm_r6;
	unsigned long arm_r7;
	unsigned long arm_r8;
	unsigned long arm_r9;
	unsigned long arm_r10;
	unsigned long arm_fp;
	unsigned long arm_ip;
	unsigned long arm_sp;
	unsigned long arm_lr;
	unsigned long arm_pc;
	unsigned long arm_cpsr;
	unsigned long fault_address;
};

/* Copied from the Linux kernel header arch/arm/include/asm/ucontext.h */

#define VFP_MAGIC	 0x56465001
#define VFP_STORAGE_SIZE sizeof(struct vfp_sigframe)

struct vfp_sigframe {
	unsigned long magic;
	unsigned long size;
	struct user_vfp ufp;
	struct user_vfp_exc ufp_exc;
};

typedef struct vfp_sigframe fpu_state_t;

struct aux_sigframe {
	/*
	struct crunch_sigframe  crunch;
	struct iwmmxt_sigframe  iwmmxt;
	*/

	struct vfp_sigframe vfp;
	unsigned long end_magic;
} __attribute__((aligned(8)));

#include <compel/sigframe-common.h>

struct sigframe {
	struct rt_ucontext uc;
	unsigned long retcode[2];
};

struct rt_sigframe {
	struct rt_siginfo info;
	struct sigframe sig;
};

/* clang-format off */
#define ARCH_RT_SIGRETURN(new_sp, rt_sigframe)				\
	asm volatile(							\
		     "mov sp, %0				    \n"	\
		     "mov r7,  #"__stringify(__NR_rt_sigreturn)"  \n" \
		     "svc #0					    \n"	\
		     :							\
		     : "r"(new_sp)					\
		     : "memory")
/* clang-format on */

#define RT_SIGFRAME_UC(rt_sigframe)	      (&rt_sigframe->sig.uc)
#define RT_SIGFRAME_REGIP(rt_sigframe)	      (rt_sigframe)->sig.uc.uc_mcontext.arm_ip
#define RT_SIGFRAME_HAS_FPU(rt_sigframe)      1
#define RT_SIGFRAME_AUX_SIGFRAME(rt_sigframe) ((struct aux_sigframe *)&(rt_sigframe)->sig.uc.uc_regspace)
#define RT_SIGFRAME_FPU(rt_sigframe)	      (&RT_SIGFRAME_AUX_SIGFRAME(rt_sigframe)->vfp)
#define RT_SIGFRAME_OFFSET(rt_sigframe)	      0

#define rt_sigframe_erase_sigset(sigframe)	memset(&sigframe->sig.uc.uc_sigmask, 0, sizeof(k_rtsigset_t))
#define rt_sigframe_copy_sigset(sigframe, from) memcpy(&sigframe->sig.uc.uc_sigmask, from, sizeof(k_rtsigset_t))

#endif /* UAPI_COMPEL_ASM_SIGFRAME_H__ */
