1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "asm.h"
6#include "setjmp_impl.h"
7#include <zircon/tls.h>
8
9ENTRY(setjmp)
10
11    // Move the jmp_buf pointer to a temporary register.
12    // We'll use x0 as a scratch register since we clobber it on return anyway.
13    mov x16, x0
14
15    // Load the manglers into temporary registers.
16    // We'll be sure that by return these registers don't
17    // contain the raw manglers, so those values never leak.
18    adrp x0, __setjmp_manglers
19    add x0, x0, #:lo12:__setjmp_manglers
20    ldp x1, x2, [x0, #8*JB_PC]
21    ldp x3, x4, [x0, #8*JB_FP]
22
23    // Get the thread pointer, where the unsafe SP is stored.
24    mrs x0, TPIDR_EL0
25    ldr x0, [x0, #ZX_TLS_UNSAFE_SP_OFFSET]
26
27    // Store all the vanilla callee-saves registers.
28    stp x19, x20, [x16, #8*JB_X(19)]
29    stp x21, x22, [x16, #8*JB_X(21)]
30    stp x23, x24, [x16, #8*JB_X(23)]
31    stp x25, x26, [x16, #8*JB_X(25)]
32    stp x27, x28, [x16, #8*JB_X(27)]
33    stp  d8,  d9, [x16, #8*JB_D(8)]
34    stp d10, d11, [x16, #8*JB_D(10)]
35    stp d12, d13, [x16, #8*JB_D(12)]
36    stp d14, d15, [x16, #8*JB_D(14)]
37
38    eor x4, x4, x0       // Mangled unsafe SP.
39    eor x1, x1, x30      // Mangled PC (LR).
40    eor x3, x3, x29      // Mangled FP.
41    mov x0, sp
42    eor x2, x2, x0       // Mangled SP.
43
44.ifne JB_SP - JB_PC - 1
45.error "JB_SP expected to follow JB_PC immediately"
46.endif
47    stp x1, x2, [x16, #8*JB_PC]
48.ifne JB_USP - JB_FP - 1
49.error "JB_USP expected to follow JB_FP immediately"
50.endif
51    stp x3, x4, [x16, #8*JB_FP]
52
53    mov w0, wzr
54    ret
55
56END(setjmp)
57
58ALIAS(setjmp, _setjmp)
59WEAK_ALIAS(setjmp, sigsetjmp)
60