summaryrefslogtreecommitdiff
path: root/gcc/ada/sigtramp-qnx.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sigtramp-qnx.c')
-rw-r--r--gcc/ada/sigtramp-qnx.c273
1 files changed, 273 insertions, 0 deletions
diff --git a/gcc/ada/sigtramp-qnx.c b/gcc/ada/sigtramp-qnx.c
new file mode 100644
index 00000000000..6e70534c08c
--- /dev/null
+++ b/gcc/ada/sigtramp-qnx.c
@@ -0,0 +1,273 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * S I G T R A M P *
+ * *
+ * Asm Implementation File *
+ * *
+ * Copyright (C) 2017, Free Software Foundation, Inc. *
+ * *
+ * GNAT is free software; you can redistribute it and/or modify it under *
+ * terms of the GNU General Public License as published by the Free Soft- *
+ * ware Foundation; either version 3, or (at your option) any later ver- *
+ * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
+ * or FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * In particular, you can freely distribute your programs built with the *
+ * GNAT Pro compiler, including any required library run-time units, using *
+ * any licensing terms of your choosing. See the AdaCore Software License *
+ * for full details. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc. *
+ * *
+ ****************************************************************************/
+
+/**********************************************
+ * QNX version of the __gnat_sigtramp service *
+ **********************************************/
+
+#include <ucontext.h>
+
+#include "sigtramp.h"
+/* See sigtramp.h for a general explanation of functionality. */
+
+extern void __gnat_sigtramp_common
+ (int signo, void *siginfo, void *sigcontext,
+ __sigtramphandler_t * handler);
+
+void __gnat_sigtramp (int signo, void *si, void *sc,
+ __sigtramphandler_t * handler)
+ __attribute__((optimize(2)));
+
+void __gnat_sigtramp (int signo, void *si, void *ucontext,
+ __sigtramphandler_t * handler)
+{
+ struct sigcontext *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
+
+ __gnat_sigtramp_common (signo, si, mcontext, handler);
+}
+
+/* asm string construction helpers. */
+
+#define STR(TEXT) #TEXT
+/* stringify expanded TEXT, surrounding it with double quotes. */
+
+#define S(E) STR(E)
+/* stringify E, which will resolve as text but may contain macros
+ still to be expanded. */
+
+/* asm (TEXT) outputs <tab>TEXT. These facilitate the output of
+ multiline contents: */
+#define TAB(S) "\t" S
+#define CR(S) S "\n"
+
+#undef TCR
+#define TCR(S) TAB(CR(S))
+
+/* Trampoline body block
+ --------------------- */
+
+#define COMMON_CFI(REG) \
+ ".cfi_offset " S(REGNO_##REG) "," S(REG_OFFSET_##REG)
+
+#ifdef __x86_64__
+/*****************************************
+ * x86-64 *
+ *****************************************/
+
+// CFI register numbers
+#define REGNO_RAX 0
+#define REGNO_RDX 1
+#define REGNO_RCX 2
+#define REGNO_RBX 3
+#define REGNO_RSI 4
+#define REGNO_RDI 5
+#define REGNO_RBP 6
+#define REGNO_RSP 7
+#define REGNO_R8 8
+#define REGNO_R9 9
+#define REGNO_R10 10
+#define REGNO_R11 11
+#define REGNO_R12 12
+#define REGNO_R13 13
+#define REGNO_R14 14
+#define REGNO_R15 15 /* Used as CFA */
+#define REGNO_RPC 16 /* aka %rip */
+
+// Registers offset from the regset structure
+#define REG_OFFSET_RDI 0x00
+#define REG_OFFSET_RSI 0x08
+#define REG_OFFSET_RDX 0x10
+#define REG_OFFSET_R10 0x18
+#define REG_OFFSET_R8 0x20
+#define REG_OFFSET_R9 0x28
+#define REG_OFFSET_RAX 0x30
+#define REG_OFFSET_RBX 0x38
+#define REG_OFFSET_RBP 0x40
+#define REG_OFFSET_RCX 0x48
+#define REG_OFFSET_R11 0x50
+#define REG_OFFSET_R12 0x58
+#define REG_OFFSET_R13 0x60
+#define REG_OFFSET_R14 0x68
+#define REG_OFFSET_R15 0x70
+#define REG_OFFSET_RPC 0x78 /* RIP */
+#define REG_OFFSET_RSP 0x90
+
+#define CFI_COMMON_REGS \
+CR("# CFI for common registers\n") \
+TCR(COMMON_CFI(RSP)) \
+TCR(COMMON_CFI(R15)) \
+TCR(COMMON_CFI(R14)) \
+TCR(COMMON_CFI(R13)) \
+TCR(COMMON_CFI(R12)) \
+TCR(COMMON_CFI(R11)) \
+TCR(COMMON_CFI(RCX)) \
+TCR(COMMON_CFI(RBP)) \
+TCR(COMMON_CFI(RBX)) \
+TCR(COMMON_CFI(RAX)) \
+TCR(COMMON_CFI(R9)) \
+TCR(COMMON_CFI(R8)) \
+TCR(COMMON_CFI(R10)) \
+TCR(COMMON_CFI(RSI)) \
+TCR(COMMON_CFI(RDI)) \
+TCR(COMMON_CFI(RDX)) \
+TCR(COMMON_CFI(RPC)) \
+TCR(".cfi_return_column " S(REGNO_RPC))
+
+#define SIGTRAMP_BODY \
+TCR(".cfi_def_cfa 15, 0") \
+CFI_COMMON_REGS \
+CR("") \
+TCR("# Allocate frame and save the non-volatile") \
+TCR("# registers we're going to modify") \
+TCR("subq $8, %rsp") \
+TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
+TCR("movq %rdx, %r15") \
+TCR("# Call the real handler. The signo, siginfo and sigcontext") \
+TCR("# arguments are the same as those we received") \
+TCR("call *%rcx") \
+TCR("# This part should never be executed") \
+TCR("addq $8, %rsp") \
+TCR("ret")
+#endif
+
+#ifdef __aarch64__
+/*****************************************
+ * Aarch64 *
+ *****************************************/
+
+/* CFA reg: any callee saved register will do */
+#define CFA_REG 19
+
+/* General purpose registers */
+#define REG_OFFSET_GR(n) (n * 8)
+#define REGNO_GR(n) n
+
+/* point to the ELR value of the mcontext registers list */
+#define REG_OFFSET_ELR (32 * 8)
+#define REGNO_PC 30
+
+#define CFI_DEF_CFA \
+ TCR(".cfi_def_cfa " S(CFA_REG) ", 0")
+
+#define CFI_COMMON_REGS \
+ CR("# CFI for common registers\n") \
+ TCR(COMMON_CFI(GR(0))) \
+ TCR(COMMON_CFI(GR(1))) \
+ TCR(COMMON_CFI(GR(2))) \
+ TCR(COMMON_CFI(GR(3))) \
+ TCR(COMMON_CFI(GR(4))) \
+ TCR(COMMON_CFI(GR(5))) \
+ TCR(COMMON_CFI(GR(6))) \
+ TCR(COMMON_CFI(GR(7))) \
+ TCR(COMMON_CFI(GR(8))) \
+ TCR(COMMON_CFI(GR(9))) \
+ TCR(COMMON_CFI(GR(10))) \
+ TCR(COMMON_CFI(GR(11))) \
+ TCR(COMMON_CFI(GR(12))) \
+ TCR(COMMON_CFI(GR(13))) \
+ TCR(COMMON_CFI(GR(14))) \
+ TCR(COMMON_CFI(GR(15))) \
+ TCR(COMMON_CFI(GR(16))) \
+ TCR(COMMON_CFI(GR(17))) \
+ TCR(COMMON_CFI(GR(18))) \
+ TCR(COMMON_CFI(GR(19))) \
+ TCR(COMMON_CFI(GR(20))) \
+ TCR(COMMON_CFI(GR(21))) \
+ TCR(COMMON_CFI(GR(22))) \
+ TCR(COMMON_CFI(GR(23))) \
+ TCR(COMMON_CFI(GR(24))) \
+ TCR(COMMON_CFI(GR(25))) \
+ TCR(COMMON_CFI(GR(26))) \
+ TCR(COMMON_CFI(GR(27))) \
+ TCR(COMMON_CFI(GR(28))) \
+ TCR(COMMON_CFI(GR(29))) \
+ TCR(".cfi_offset " S(REGNO_PC) "," S(REG_OFFSET_ELR)) \
+ TCR(".cfi_return_column " S(REGNO_PC))
+
+#define SIGTRAMP_BODY \
+ CFI_DEF_CFA \
+ CFI_COMMON_REGS \
+ TCR("# Push FP and LR on stack") \
+ TCR("stp x29, x30, [sp, #-16]!") \
+ TCR("# Push register used to hold the CFA on stack") \
+ TCR("str x" S(CFA_REG) ", [sp, #-8]!") \
+ TCR("# Set the CFA: x2 value") \
+ TCR("mov x" S(CFA_REG) ", x2") \
+ TCR("# Call the handler") \
+ TCR("blr x3") \
+ TCR("# Release our frame and return (should never get here!).") \
+ TCR("ldr x" S(CFA_REG) " , [sp], 8") \
+ TCR("ldp x29, x30, [sp], 16") \
+ TCR("ret")
+
+#endif /* AARCH64 */
+
+/* Symbol definition block
+ ----------------------- */
+
+#if defined (__x86_64__) || defined (__aarch64__)
+#define FUNC_ALIGN TCR(".p2align 4,,15")
+#else
+#define FUNC_ALIGN
+#endif
+
+#define SIGTRAMP_START(SYM) \
+CR("# " S(SYM) " cfi trampoline") \
+TCR(".type " S(SYM) ", @function") \
+CR("") \
+FUNC_ALIGN \
+CR(S(SYM) ":") \
+TCR(".cfi_startproc") \
+TCR(".cfi_signal_frame")
+
+/* Symbol termination block
+ ------------------------ */
+
+#define SIGTRAMP_END(SYM) \
+CR(".cfi_endproc") \
+TCR(".size " S(SYM) ", .-" S(SYM))
+
+/*----------------------------
+ -- And now, the real code --
+ ---------------------------- */
+
+/* Text section start. The compiler isn't aware of that switch. */
+
+asm (".text\n"
+ TCR(".align 2"));
+
+/* sigtramp stub for common registers. */
+
+#define TRAMP_COMMON __gnat_sigtramp_common
+
+asm (SIGTRAMP_START(TRAMP_COMMON));
+asm (SIGTRAMP_BODY);
+asm (SIGTRAMP_END(TRAMP_COMMON));