diff options
Diffstat (limited to 'gcc/ada/sigtramp-qnx.c')
-rw-r--r-- | gcc/ada/sigtramp-qnx.c | 273 |
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)); |