1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * Asm Implementation File *
9 * Copyright (C) 2011, Free Software Foundation, Inc. *
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. *
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. *
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 *
27 * GNAT was originally developed by the GNAT team at New York University. *
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
30 ****************************************************************************/
32 /**********************************************************
33 * PowerPC-VxWorks version of the __gnat_sigtramp service *
34 **********************************************************/
39 #include <arch/../regs.h>
42 /* ----------------------
43 -- General comments --
44 ----------------------
46 Stubs are generated from toplevel asms and .cfi directives, much simpler
47 to use and check for correctness than manual encodings of CFI byte
48 sequences. The general idea is to establish CFA as sigcontext->sc_pregs
49 and state where to find the registers as offsets from there.
51 As of today, we support a single stub, providing CFI info for common
52 registers (GPRs, LR, ...). We might need variants with support for floating
53 point or altivec registers as well at some point.
55 Checking which variant should apply and getting at sc_pregs is simpler
56 to express in C (we can't use offsetof in toplevel asms and hardcoding
57 constants is not workable with the flurry of VxWorks variants), so this
58 is the choice for our toplevel interface. */
60 /* -----------------------------------------
61 -- Protypes for our internal asm stubs --
62 -----------------------------------------
64 SC_PREGS is always expected to be SIGCONTEXT->sc_pregs. Eventhough our
65 symbols will remain local, the prototype claims "extern" and not
66 "static" to prevent compiler complaints about a symbol used but never
69 /* sigtramp stub providing CFI info for common registers. */
71 extern void __gnat_sigtramp_common
72 (int signo, void *siginfo, void *sigcontext,
73 sighandler_t * handler, void * sc_pregs);
76 /* -------------------------------------
77 -- Common interface implementation --
78 -------------------------------------
80 We enforce optimization to minimize the overhead of the extra layer. */
82 void __gnat_sigtramp (int signo, void *si, void *sc,
83 sighandler_t * handler)
84 __attribute__((optimize(2)));
86 void __gnat_sigtramp (int signo, void *si, void *sc,
87 sighandler_t * handler)
89 struct sigcontext * sctx = (struct sigcontext *) sc;
91 __gnat_sigtramp_common (signo, si, sctx, handler, sctx->sc_pregs);
95 /* ---------------------------
96 -- And now the asm stubs --
97 ---------------------------
99 They all have a common structure with blocks of asm sequences queued one
100 after the others. Typically:
106 CFI_COMMON_REGISTERS,
110 asm code to establish frame, setup the cfa reg value,
111 call the real signal handler, ...
116 /*--------------------------------
117 -- Misc constants and helpers --
118 -------------------------------- */
120 /* REGNO constants, dwarf column numbers for registers of interest. */
125 #define REGNO_GR(N) (N)
127 #define REGNO_PC 67 /* ARG_POINTER_REGNUM */
129 /* asm string contruction helpers. */
131 #define STR(TEXT) #TEXT
132 /* stringify expanded TEXT, surrounding it with double quotes. */
135 /* stringify E, which will resolve as text but may contain macros
136 still to be expanded. */
138 /* asm (TEXT) outputs <tab>TEXT. These facilitate the output of
140 #define TAB(S) "\t" S
142 #define TCR(S) TAB(CR(S))
144 /*------------------------------
145 -- Stub construction blocks --
146 ------------------------------ */
150 Only non-volatile registers are suitable for a CFA base. We use r14
151 here and set it to the value we need in stub body that follows. */
153 #define CFI_DEF_CFA \
154 CR(".cfi_def_cfa 14, 0")
156 /* Register location blocks
157 ------------------------
158 Rules to find registers of interest from the CFA. This should
159 comprise all the non-volatile registers relevant to the interrupted
162 #define COMMON_CFI(REG) \
163 ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG)
165 #define CFI_COMMON_REGS \
166 CR("# CFI for common registers\n") \
167 TCR(COMMON_CFI(GR(1))) \
168 TCR(COMMON_CFI(GR(14))) \
169 TCR(COMMON_CFI(GR(15))) \
170 TCR(COMMON_CFI(GR(16))) \
171 TCR(COMMON_CFI(GR(17))) \
172 TCR(COMMON_CFI(GR(18))) \
173 TCR(COMMON_CFI(GR(19))) \
174 TCR(COMMON_CFI(GR(20))) \
175 TCR(COMMON_CFI(GR(21))) \
176 TCR(COMMON_CFI(GR(22))) \
177 TCR(COMMON_CFI(GR(23))) \
178 TCR(COMMON_CFI(GR(24))) \
179 TCR(COMMON_CFI(GR(25))) \
180 TCR(COMMON_CFI(GR(26))) \
181 TCR(COMMON_CFI(GR(27))) \
182 TCR(COMMON_CFI(GR(28))) \
183 TCR(COMMON_CFI(GR(29))) \
184 TCR(COMMON_CFI(GR(30))) \
185 TCR(COMMON_CFI(GR(31))) \
186 TCR(COMMON_CFI(LR)) \
187 TCR(COMMON_CFI(CR)) \
188 TCR(COMMON_CFI(PC)) \
189 TCR(".cfi_return_column " S(REGNO_PC))
191 /* Trampoline body block
192 --------------------- */
194 #define SIGTRAMP_BODY \
196 TCR("# Allocate frame and save the non-volatile") \
197 TCR("# registers we're going to modify") \
198 TCR("stwu %r1,-16(%r1)") \
200 TCR("stw %r0,20(%r1)") \
201 TCR("stw %r14,8(%r1)") \
203 TCR("# Setup r14 = sc_pregs, that we'll retrieve as our CFA value") \
204 TCR("mr %r14, %r7") \
206 TCR("# Call the real handler. The signo, siginfo and sigcontext") \
207 TCR("# arguments are the same as those we received in r3, r4 and r5") \
211 TCR("# Restore our callee-saved items, release our frame and return") \
212 TCR("lwz %r14,8(%r1)") \
213 TCR("lwz %r0,20(%r1)") \
216 TCR("addi %r1,%r1,16") \
219 /* Symbol definition block
220 ----------------------- */
222 #define SIGTRAMP_START(SYM) \
223 CR("# " S(SYM) " cfi trampoline") \
224 TCR(".type " S(SYM) ", @function") \
227 TCR(".cfi_startproc") \
228 TCR(".cfi_signal_frame")
230 /* Symbol termination block
231 ------------------------ */
233 #define SIGTRAMP_END(SYM) \
235 TCR(".size " S(SYM) ", .-" S(SYM))
237 /*----------------------------
238 -- And now, the real code --
239 ---------------------------- */
241 /* Text section start. The compiler isn't aware of that switch. */
246 /* sigtramp stub for common registers. */
248 #define TRAMP_COMMON __gnat_sigtramp_common
250 asm (SIGTRAMP_START(TRAMP_COMMON));
252 asm (CFI_COMMON_REGS);
254 asm (SIGTRAMP_END(TRAMP_COMMON));