blob: d8b98a33c66970d7c695488ba46258ed116f8ad8 [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// -------------------------------------------------------------------------
48// 0-1 sigmask signal mask (not used with _setjmp / _longjmp)
Elliott Hughes9fb536d2014-12-05 12:17:25 -080049// 2 core_base base of core registers (x19-x30, sp)
50// 28 float_base base of float registers (d8-d15)
Elliott Hughes7b78e812014-12-05 22:57:55 -080051// 44 magic magic number
52// 45- reserved reserved entries (room to grow)
Elliott Hughes9fb536d2014-12-05 12:17:25 -080053// 64
54//
Elliott Hughes9fb536d2014-12-05 12:17:25 -080055// NOTE: The instructions that load/store core/vfp registers expect 8-byte
56// alignment. Contrary to the previous setjmp header for ARM we do not
57// need to save status/control registers for VFP (it is not a
58// requirement for setjmp).
Elliott Hughes9fb536d2014-12-05 12:17:25 -080059
Elliott Hughes7b78e812014-12-05 22:57:55 -080060#define _JB_SIGMASK 0
61#define _JB_CORE_BASE (_JB_SIGMASK + 2)
Elliott Hughes9fb536d2014-12-05 12:17:25 -080062#define _JB_FLOAT_BASE (_JB_CORE_BASE + (31-19+1)*2)
Elliott Hughes7b78e812014-12-05 22:57:55 -080063#define _JB_MAGIC (_JB_FLOAT_BASE + 16*2)
Elliott Hughes9fb536d2014-12-05 12:17:25 -080064
65.L_setjmp_magic_signal_mask_n: .word 0x53657200
66.L_setjmp_magic_signal_mask_y: .word 0x53657201
Serban Constantinescue2104882013-09-26 11:37:10 +010067
68ENTRY(setjmp)
Elliott Hughes9fb536d2014-12-05 12:17:25 -080069 mov w1, #1
70 b sigsetjmp
Serban Constantinescue2104882013-09-26 11:37:10 +010071END(setjmp)
72
Elliott Hughes9fb536d2014-12-05 12:17:25 -080073ENTRY(_setjmp)
74 mov w1, #0
75 b sigsetjmp
76END(_setjmp)
Serban Constantinescue2104882013-09-26 11:37:10 +010077
Elliott Hughes9fb536d2014-12-05 12:17:25 -080078// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
79ENTRY(sigsetjmp)
80 // Do we need to save the signal mask?
81 ldr w9, .L_setjmp_magic_signal_mask_n
82 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 -080092 ldr w9, .L_setjmp_magic_signal_mask_y
Serban Constantinescue2104882013-09-26 11:37:10 +010093
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800941:
95 // Save magic number.
96 str w9, [x0, #(_JB_MAGIC * 4)]
Serban Constantinescue2104882013-09-26 11:37:10 +010097
Elliott Hughes9fb536d2014-12-05 12:17:25 -080098 // Save core registers.
99 mov x10, sp
100 stp x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
101 stp x28, x29, [x0, #(_JB_CORE_BASE * 4 + 16 * 1)]
102 stp x26, x27, [x0, #(_JB_CORE_BASE * 4 + 16 * 2)]
103 stp x24, x25, [x0, #(_JB_CORE_BASE * 4 + 16 * 3)]
104 stp x22, x23, [x0, #(_JB_CORE_BASE * 4 + 16 * 4)]
105 stp x20, x21, [x0, #(_JB_CORE_BASE * 4 + 16 * 5)]
106 str x19, [x0, #(_JB_CORE_BASE * 4 + 16 * 6)]
107
108 // Save floating point registers.
109 stp d14, d15, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 0)]
110 stp d12, d13, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 1)]
111 stp d10, d11, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 2)]
112 stp d8, d9, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 3)]
113
114 mov w0, wzr
115 ret
116END(sigsetjmp)
117
118// void siglongjmp(sigjmp_buf env, int value);
119ENTRY(siglongjmp)
120 // Check magic.
121 ldr w10, [x0, #(_JB_MAGIC * 4)]
122 ldr w9, .L_setjmp_magic_signal_mask_n
123 cmp w9, w10
124 b.eq 1f
125 ldr w9, .L_setjmp_magic_signal_mask_y
126 cmp w9, w10
127 b.ne longjmperror
128
129 // Restore signal mask.
130 stp x0, x30, [sp, #-16]!
Elliott Hughes7b78e812014-12-05 22:57:55 -0800131 mov x19, x1 // Save 'value'.
132 mov x2, x0
133 mov x0, #2 // SIG_SETMASK
134 add x1, x2, #(_JB_SIGMASK * 4) // new_mask.
135 mov x2, #0 // NULL.
136 bl sigprocmask
137 mov x1, x19 // Restore 'value'.
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800138 ldp x0, x30, [sp], #16
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800139
1401:
141 // Restore core registers.
142 ldp x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
143 mov sp, x10
144 ldp x28, x29, [x0, #(_JB_CORE_BASE * 4 + 16 * 1)]
145 ldp x26, x27, [x0, #(_JB_CORE_BASE * 4 + 16 * 2)]
146 ldp x24, x25, [x0, #(_JB_CORE_BASE * 4 + 16 * 3)]
147 ldp x22, x23, [x0, #(_JB_CORE_BASE * 4 + 16 * 4)]
148 ldp x20, x21, [x0, #(_JB_CORE_BASE * 4 + 16 * 5)]
149 ldr x19, [x0, #(_JB_CORE_BASE * 4 + 16 * 6)]
150
151 // Restore floating point registers.
152 ldp d14, d15, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 0)]
153 ldp d12, d13, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 1)]
154 ldp d10, d11, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 2)]
155 ldp d8, d9, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 3)]
156
157 // Validate sp (sp mod 16 = 0) and lr (lr mod 4 = 0).
158 tst x30, #3
159 b.ne longjmperror
160 mov x10, sp
161 tst x10, #15
162 b.ne longjmperror
163
164 // Set return value.
165 cmp w1, wzr
166 csinc w0, w1, wzr, ne
167 ret
168END(siglongjmp)
169
170 .globl longjmp
171 .equ longjmp, siglongjmp
172 .globl _longjmp
173 .equ _longjmp, siglongjmp