blob: d1747e43586543921af62eec433e3b413c9274f8 [file] [log] [blame]
Serban Constantinescue2104882013-09-26 11:37:10 +01001/*
2 * Copyright (C) 2013 The Android Open Source Project
Elliott Hughes54a74942014-01-03 16:40:37 -08003 * All rights reserved.
Serban Constantinescue2104882013-09-26 11:37:10 +01004 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
Elliott Hughes851e68a2014-02-19 16:53:20 -080029#include <private/bionic_asm.h>
Serban Constantinescue2104882013-09-26 11:37:10 +010030
Elliott Hughes9fb536d2014-12-05 12:17:25 -080031// According to AARCH64 PCS document we need to save the following
32// registers:
33//
34// Core x19 - x30, sp (see section 5.1.1)
35// VFP d8 - d15 (see section 5.1.2)
36//
37// NOTE: All the registers saved here will have 64bit vales (except FPSR).
38// AAPCS mandates that the higher part of q registers do not need to
39// be saved by the callee.
Elliott Hughes9fb536d2014-12-05 12:17:25 -080040
41// The structure of jmp_buf for AArch64:
42//
43// NOTE: _JBLEN is the size of jmp_buf in longs(64bit on AArch64)! The table
44// below computes the offsets in words(32bit).
45//
Elliott Hughes7b78e812014-12-05 22:57:55 -080046// word name description
47// -------------------------------------------------------------------------
Elliott Hughes75096222014-12-08 16:01:20 -080048// 0 sigflag 0 => signal mask not valid
49// 1 unused unused (for alignment)
50// 2-3 sigmask signal mask (not used with _setjmp / _longjmp)
51// 4 core_base base of core registers (x19-x30, sp)
52// 30 float_base base of float registers (d8-d15)
53// 46- reserved reserved entries (room to grow)
Elliott Hughes9fb536d2014-12-05 12:17:25 -080054// 64
55//
Elliott Hughes9fb536d2014-12-05 12:17:25 -080056// NOTE: The instructions that load/store core/vfp registers expect 8-byte
57// alignment. Contrary to the previous setjmp header for ARM we do not
58// need to save status/control registers for VFP (it is not a
59// requirement for setjmp).
Elliott Hughes9fb536d2014-12-05 12:17:25 -080060
Elliott Hughes75096222014-12-08 16:01:20 -080061#define _JB_SIGFLAG 0
62#define _JB_SIGMASK (_JB_SIGFLAG + 2)
Elliott Hughes7b78e812014-12-05 22:57:55 -080063#define _JB_CORE_BASE (_JB_SIGMASK + 2)
Elliott Hughes9fb536d2014-12-05 12:17:25 -080064#define _JB_FLOAT_BASE (_JB_CORE_BASE + (31-19+1)*2)
Serban Constantinescue2104882013-09-26 11:37:10 +010065
66ENTRY(setjmp)
Elliott Hughes9fb536d2014-12-05 12:17:25 -080067 mov w1, #1
68 b sigsetjmp
Serban Constantinescue2104882013-09-26 11:37:10 +010069END(setjmp)
70
Elliott Hughes9fb536d2014-12-05 12:17:25 -080071ENTRY(_setjmp)
72 mov w1, #0
73 b sigsetjmp
74END(_setjmp)
Serban Constantinescue2104882013-09-26 11:37:10 +010075
Elliott Hughes9fb536d2014-12-05 12:17:25 -080076// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
77ENTRY(sigsetjmp)
Elliott Hughes75096222014-12-08 16:01:20 -080078 // Record whether or not we're saving the signal mask.
79 str w1, [x0, #(_JB_SIGFLAG * 4)]
80
Elliott Hughes9fb536d2014-12-05 12:17:25 -080081 // Do we need to save the signal mask?
Elliott Hughes9fb536d2014-12-05 12:17:25 -080082 cbz w1, 1f
Serban Constantinescue2104882013-09-26 11:37:10 +010083
Elliott Hughes7b78e812014-12-05 22:57:55 -080084 // Save current signal mask.
Elliott Hughes9fb536d2014-12-05 12:17:25 -080085 stp x0, x30, [sp, #-16]!
Elliott Hughes7b78e812014-12-05 22:57:55 -080086 // The 'how' argument is ignored if new_mask is NULL.
87 mov x1, #0 // NULL.
88 add x2, x0, #(_JB_SIGMASK * 4) // old_mask.
89 bl sigprocmask
Elliott Hughes9fb536d2014-12-05 12:17:25 -080090 ldp x0, x30, [sp], #16
Serban Constantinescue2104882013-09-26 11:37:10 +010091
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800921:
Elliott Hughes9fb536d2014-12-05 12:17:25 -080093 // Save core registers.
94 mov x10, sp
95 stp x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
96 stp x28, x29, [x0, #(_JB_CORE_BASE * 4 + 16 * 1)]
97 stp x26, x27, [x0, #(_JB_CORE_BASE * 4 + 16 * 2)]
98 stp x24, x25, [x0, #(_JB_CORE_BASE * 4 + 16 * 3)]
99 stp x22, x23, [x0, #(_JB_CORE_BASE * 4 + 16 * 4)]
100 stp x20, x21, [x0, #(_JB_CORE_BASE * 4 + 16 * 5)]
101 str x19, [x0, #(_JB_CORE_BASE * 4 + 16 * 6)]
102
103 // Save floating point registers.
104 stp d14, d15, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 0)]
105 stp d12, d13, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 1)]
106 stp d10, d11, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 2)]
107 stp d8, d9, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 3)]
108
Elliott Hughes75096222014-12-08 16:01:20 -0800109 mov w0, #0
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800110 ret
111END(sigsetjmp)
112
113// void siglongjmp(sigjmp_buf env, int value);
114ENTRY(siglongjmp)
Elliott Hughes75096222014-12-08 16:01:20 -0800115 // Do we need to restore the signal mask?
116 ldr w9, [x0, #(_JB_SIGFLAG * 4)]
117 cbz w9, 1f
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800118
119 // Restore signal mask.
120 stp x0, x30, [sp, #-16]!
Elliott Hughes7b78e812014-12-05 22:57:55 -0800121 mov x19, x1 // Save 'value'.
122 mov x2, x0
123 mov x0, #2 // SIG_SETMASK
124 add x1, x2, #(_JB_SIGMASK * 4) // new_mask.
125 mov x2, #0 // NULL.
126 bl sigprocmask
127 mov x1, x19 // Restore 'value'.
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800128 ldp x0, x30, [sp], #16
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800129
1301:
131 // Restore core registers.
132 ldp x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
133 mov sp, x10
134 ldp x28, x29, [x0, #(_JB_CORE_BASE * 4 + 16 * 1)]
135 ldp x26, x27, [x0, #(_JB_CORE_BASE * 4 + 16 * 2)]
136 ldp x24, x25, [x0, #(_JB_CORE_BASE * 4 + 16 * 3)]
137 ldp x22, x23, [x0, #(_JB_CORE_BASE * 4 + 16 * 4)]
138 ldp x20, x21, [x0, #(_JB_CORE_BASE * 4 + 16 * 5)]
139 ldr x19, [x0, #(_JB_CORE_BASE * 4 + 16 * 6)]
140
141 // Restore floating point registers.
142 ldp d14, d15, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 0)]
143 ldp d12, d13, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 1)]
144 ldp d10, d11, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 2)]
145 ldp d8, d9, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 3)]
146
147 // Validate sp (sp mod 16 = 0) and lr (lr mod 4 = 0).
148 tst x30, #3
149 b.ne longjmperror
150 mov x10, sp
151 tst x10, #15
152 b.ne longjmperror
153
154 // Set return value.
155 cmp w1, wzr
156 csinc w0, w1, wzr, ne
157 ret
158END(siglongjmp)
159
160 .globl longjmp
161 .equ longjmp, siglongjmp
162 .globl _longjmp
163 .equ _longjmp, siglongjmp