PR rtl-optimization/82913
[official-gcc.git] / gcc / ada / sigtramp-qnx.c
blob6e70534c08c5f6b2745fd3d0d19e8195868c5aaf
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * S I G T R A M P *
6 * *
7 * Asm Implementation File *
8 * *
9 * Copyright (C) 2017, Free Software Foundation, Inc. *
10 * *
11 * GNAT is free software; you can redistribute it and/or modify it under *
12 * terms of the GNU General Public License as published by the Free Soft- *
13 * ware Foundation; either version 3, or (at your option) any later ver- *
14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE. *
17 * *
18 * As a special exception under Section 7 of GPL version 3, you are granted *
19 * additional permissions described in the GCC Runtime Library Exception, *
20 * version 3.1, as published by the Free Software Foundation. *
21 * *
22 * In particular, you can freely distribute your programs built with the *
23 * GNAT Pro compiler, including any required library run-time units, using *
24 * any licensing terms of your choosing. See the AdaCore Software License *
25 * for full details. *
26 * *
27 * GNAT was originally developed by the GNAT team at New York University. *
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
29 * *
30 ****************************************************************************/
32 /**********************************************
33 * QNX version of the __gnat_sigtramp service *
34 **********************************************/
36 #include <ucontext.h>
38 #include "sigtramp.h"
39 /* See sigtramp.h for a general explanation of functionality. */
41 extern void __gnat_sigtramp_common
42 (int signo, void *siginfo, void *sigcontext,
43 __sigtramphandler_t * handler);
45 void __gnat_sigtramp (int signo, void *si, void *sc,
46 __sigtramphandler_t * handler)
47 __attribute__((optimize(2)));
49 void __gnat_sigtramp (int signo, void *si, void *ucontext,
50 __sigtramphandler_t * handler)
52 struct sigcontext *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
54 __gnat_sigtramp_common (signo, si, mcontext, handler);
57 /* asm string construction helpers. */
59 #define STR(TEXT) #TEXT
60 /* stringify expanded TEXT, surrounding it with double quotes. */
62 #define S(E) STR(E)
63 /* stringify E, which will resolve as text but may contain macros
64 still to be expanded. */
66 /* asm (TEXT) outputs <tab>TEXT. These facilitate the output of
67 multiline contents: */
68 #define TAB(S) "\t" S
69 #define CR(S) S "\n"
71 #undef TCR
72 #define TCR(S) TAB(CR(S))
74 /* Trampoline body block
75 --------------------- */
77 #define COMMON_CFI(REG) \
78 ".cfi_offset " S(REGNO_##REG) "," S(REG_OFFSET_##REG)
80 #ifdef __x86_64__
81 /*****************************************
82 * x86-64 *
83 *****************************************/
85 // CFI register numbers
86 #define REGNO_RAX 0
87 #define REGNO_RDX 1
88 #define REGNO_RCX 2
89 #define REGNO_RBX 3
90 #define REGNO_RSI 4
91 #define REGNO_RDI 5
92 #define REGNO_RBP 6
93 #define REGNO_RSP 7
94 #define REGNO_R8 8
95 #define REGNO_R9 9
96 #define REGNO_R10 10
97 #define REGNO_R11 11
98 #define REGNO_R12 12
99 #define REGNO_R13 13
100 #define REGNO_R14 14
101 #define REGNO_R15 15 /* Used as CFA */
102 #define REGNO_RPC 16 /* aka %rip */
104 // Registers offset from the regset structure
105 #define REG_OFFSET_RDI 0x00
106 #define REG_OFFSET_RSI 0x08
107 #define REG_OFFSET_RDX 0x10
108 #define REG_OFFSET_R10 0x18
109 #define REG_OFFSET_R8 0x20
110 #define REG_OFFSET_R9 0x28
111 #define REG_OFFSET_RAX 0x30
112 #define REG_OFFSET_RBX 0x38
113 #define REG_OFFSET_RBP 0x40
114 #define REG_OFFSET_RCX 0x48
115 #define REG_OFFSET_R11 0x50
116 #define REG_OFFSET_R12 0x58
117 #define REG_OFFSET_R13 0x60
118 #define REG_OFFSET_R14 0x68
119 #define REG_OFFSET_R15 0x70
120 #define REG_OFFSET_RPC 0x78 /* RIP */
121 #define REG_OFFSET_RSP 0x90
123 #define CFI_COMMON_REGS \
124 CR("# CFI for common registers\n") \
125 TCR(COMMON_CFI(RSP)) \
126 TCR(COMMON_CFI(R15)) \
127 TCR(COMMON_CFI(R14)) \
128 TCR(COMMON_CFI(R13)) \
129 TCR(COMMON_CFI(R12)) \
130 TCR(COMMON_CFI(R11)) \
131 TCR(COMMON_CFI(RCX)) \
132 TCR(COMMON_CFI(RBP)) \
133 TCR(COMMON_CFI(RBX)) \
134 TCR(COMMON_CFI(RAX)) \
135 TCR(COMMON_CFI(R9)) \
136 TCR(COMMON_CFI(R8)) \
137 TCR(COMMON_CFI(R10)) \
138 TCR(COMMON_CFI(RSI)) \
139 TCR(COMMON_CFI(RDI)) \
140 TCR(COMMON_CFI(RDX)) \
141 TCR(COMMON_CFI(RPC)) \
142 TCR(".cfi_return_column " S(REGNO_RPC))
144 #define SIGTRAMP_BODY \
145 TCR(".cfi_def_cfa 15, 0") \
146 CFI_COMMON_REGS \
147 CR("") \
148 TCR("# Allocate frame and save the non-volatile") \
149 TCR("# registers we're going to modify") \
150 TCR("subq $8, %rsp") \
151 TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
152 TCR("movq %rdx, %r15") \
153 TCR("# Call the real handler. The signo, siginfo and sigcontext") \
154 TCR("# arguments are the same as those we received") \
155 TCR("call *%rcx") \
156 TCR("# This part should never be executed") \
157 TCR("addq $8, %rsp") \
158 TCR("ret")
159 #endif
161 #ifdef __aarch64__
162 /*****************************************
163 * Aarch64 *
164 *****************************************/
166 /* CFA reg: any callee saved register will do */
167 #define CFA_REG 19
169 /* General purpose registers */
170 #define REG_OFFSET_GR(n) (n * 8)
171 #define REGNO_GR(n) n
173 /* point to the ELR value of the mcontext registers list */
174 #define REG_OFFSET_ELR (32 * 8)
175 #define REGNO_PC 30
177 #define CFI_DEF_CFA \
178 TCR(".cfi_def_cfa " S(CFA_REG) ", 0")
180 #define CFI_COMMON_REGS \
181 CR("# CFI for common registers\n") \
182 TCR(COMMON_CFI(GR(0))) \
183 TCR(COMMON_CFI(GR(1))) \
184 TCR(COMMON_CFI(GR(2))) \
185 TCR(COMMON_CFI(GR(3))) \
186 TCR(COMMON_CFI(GR(4))) \
187 TCR(COMMON_CFI(GR(5))) \
188 TCR(COMMON_CFI(GR(6))) \
189 TCR(COMMON_CFI(GR(7))) \
190 TCR(COMMON_CFI(GR(8))) \
191 TCR(COMMON_CFI(GR(9))) \
192 TCR(COMMON_CFI(GR(10))) \
193 TCR(COMMON_CFI(GR(11))) \
194 TCR(COMMON_CFI(GR(12))) \
195 TCR(COMMON_CFI(GR(13))) \
196 TCR(COMMON_CFI(GR(14))) \
197 TCR(COMMON_CFI(GR(15))) \
198 TCR(COMMON_CFI(GR(16))) \
199 TCR(COMMON_CFI(GR(17))) \
200 TCR(COMMON_CFI(GR(18))) \
201 TCR(COMMON_CFI(GR(19))) \
202 TCR(COMMON_CFI(GR(20))) \
203 TCR(COMMON_CFI(GR(21))) \
204 TCR(COMMON_CFI(GR(22))) \
205 TCR(COMMON_CFI(GR(23))) \
206 TCR(COMMON_CFI(GR(24))) \
207 TCR(COMMON_CFI(GR(25))) \
208 TCR(COMMON_CFI(GR(26))) \
209 TCR(COMMON_CFI(GR(27))) \
210 TCR(COMMON_CFI(GR(28))) \
211 TCR(COMMON_CFI(GR(29))) \
212 TCR(".cfi_offset " S(REGNO_PC) "," S(REG_OFFSET_ELR)) \
213 TCR(".cfi_return_column " S(REGNO_PC))
215 #define SIGTRAMP_BODY \
216 CFI_DEF_CFA \
217 CFI_COMMON_REGS \
218 TCR("# Push FP and LR on stack") \
219 TCR("stp x29, x30, [sp, #-16]!") \
220 TCR("# Push register used to hold the CFA on stack") \
221 TCR("str x" S(CFA_REG) ", [sp, #-8]!") \
222 TCR("# Set the CFA: x2 value") \
223 TCR("mov x" S(CFA_REG) ", x2") \
224 TCR("# Call the handler") \
225 TCR("blr x3") \
226 TCR("# Release our frame and return (should never get here!).") \
227 TCR("ldr x" S(CFA_REG) " , [sp], 8") \
228 TCR("ldp x29, x30, [sp], 16") \
229 TCR("ret")
231 #endif /* AARCH64 */
233 /* Symbol definition block
234 ----------------------- */
236 #if defined (__x86_64__) || defined (__aarch64__)
237 #define FUNC_ALIGN TCR(".p2align 4,,15")
238 #else
239 #define FUNC_ALIGN
240 #endif
242 #define SIGTRAMP_START(SYM) \
243 CR("# " S(SYM) " cfi trampoline") \
244 TCR(".type " S(SYM) ", @function") \
245 CR("") \
246 FUNC_ALIGN \
247 CR(S(SYM) ":") \
248 TCR(".cfi_startproc") \
249 TCR(".cfi_signal_frame")
251 /* Symbol termination block
252 ------------------------ */
254 #define SIGTRAMP_END(SYM) \
255 CR(".cfi_endproc") \
256 TCR(".size " S(SYM) ", .-" S(SYM))
258 /*----------------------------
259 -- And now, the real code --
260 ---------------------------- */
262 /* Text section start. The compiler isn't aware of that switch. */
264 asm (".text\n"
265 TCR(".align 2"));
267 /* sigtramp stub for common registers. */
269 #define TRAMP_COMMON __gnat_sigtramp_common
271 asm (SIGTRAMP_START(TRAMP_COMMON));
272 asm (SIGTRAMP_BODY);
273 asm (SIGTRAMP_END(TRAMP_COMMON));