blob: 410b59ef53eccfa6a3a990a1bc8a8441e1eb0633 [file] [log] [blame]
Robert Sloan4c22c5f2019-03-01 15:53:37 -08001#!/usr/bin/env perl
2# Copyright (c) 2019, Google Inc.
3#
4# Permission to use, copy, modify, and/or distribute this software for any
5# purpose with or without fee is hereby granted, provided that the above
6# copyright notice and this permission notice appear in all copies.
7#
8# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
16# This file defines helper functions for crypto/test/abi_test.h on aarch64. See
17# that header for details on how to use this.
18#
19# For convenience, this file is linked into libcrypto, where consuming builds
20# already support architecture-specific sources. The static linker should drop
21# this code in non-test binaries. This includes a shared library build of
22# libcrypto, provided --gc-sections (ELF), -dead_strip (iOS), or equivalent is
23# used.
24#
25# References:
26#
27# AAPCS64: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
28# iOS ARM64: https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html
29
30use strict;
31
32my $flavour = shift;
33my $output = shift;
34if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
35
36$0 =~ m/(.*[\/\\])[^\/\\]+$/;
37my $dir = $1;
38my $xlate;
39( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
40( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
41die "can't locate arm-xlate.pl";
42
43open OUT, "| \"$^X\" \"$xlate\" $flavour \"$output\"";
44*STDOUT = *OUT;
45
46my ($func, $state, $argv, $argc) = ("x0", "x1", "x2", "x3");
47my $code = <<____;
48.text
49
50// abi_test_trampoline loads callee-saved registers from |state|, calls |func|
51// with |argv|, then saves the callee-saved registers into |state|. It returns
52// the result of |func|. The |unwind| argument is unused.
53// uint64_t abi_test_trampoline(void (*func)(...), CallerState *state,
54// const uint64_t *argv, size_t argc,
55// uint64_t unwind);
56.type abi_test_trampoline, %function
57.globl abi_test_trampoline
58.align 4
59abi_test_trampoline:
60.Labi_test_trampoline_begin:
61 // Stack layout (low to high addresses)
62 // x29,x30 (16 bytes)
63 // d8-d15 (64 bytes)
64 // x19-x28 (80 bytes)
65 // $state (8 bytes)
66 // padding (8 bytes)
67 stp x29, x30, [sp, #-176]!
68 mov x29, sp
69
70 // Saved callee-saved registers and |state|.
71 stp d8, d9, [sp, #16]
72 stp d10, d11, [sp, #32]
73 stp d12, d13, [sp, #48]
74 stp d14, d15, [sp, #64]
75 stp x19, x20, [sp, #80]
76 stp x21, x22, [sp, #96]
77 stp x23, x24, [sp, #112]
78 stp x25, x26, [sp, #128]
79 stp x27, x28, [sp, #144]
80 str $state, [sp, #160]
81
82 // Load registers from |state|, with the exception of x29. x29 is the
83 // frame pointer and also callee-saved, but AAPCS64 allows platforms to
84 // mandate that x29 always point to a frame. iOS64 does so, which means
85 // we cannot fill x29 with entropy without violating ABI rules
86 // ourselves. x29 is tested separately below.
87 ldp d8, d9, [$state], #16
88 ldp d10, d11, [$state], #16
89 ldp d12, d13, [$state], #16
90 ldp d14, d15, [$state], #16
91 ldp x19, x20, [$state], #16
92 ldp x21, x22, [$state], #16
93 ldp x23, x24, [$state], #16
94 ldp x25, x26, [$state], #16
95 ldp x27, x28, [$state], #16
96
97 // Move parameters into temporary registers.
98 mov x9, $func
99 mov x10, $argv
100 mov x11, $argc
101
102 // Load parameters into registers.
103 cbz x11, .Largs_done
104 ldr x0, [x10], #8
105 subs x11, x11, #1
106 b.eq .Largs_done
107 ldr x1, [x10], #8
108 subs x11, x11, #1
109 b.eq .Largs_done
110 ldr x2, [x10], #8
111 subs x11, x11, #1
112 b.eq .Largs_done
113 ldr x3, [x10], #8
114 subs x11, x11, #1
115 b.eq .Largs_done
116 ldr x4, [x10], #8
117 subs x11, x11, #1
118 b.eq .Largs_done
119 ldr x5, [x10], #8
120 subs x11, x11, #1
121 b.eq .Largs_done
122 ldr x6, [x10], #8
123 subs x11, x11, #1
124 b.eq .Largs_done
125 ldr x7, [x10], #8
126
127.Largs_done:
128 blr x9
129
130 // Reload |state| and store registers.
131 ldr $state, [sp, #160]
132 stp d8, d9, [$state], #16
133 stp d10, d11, [$state], #16
134 stp d12, d13, [$state], #16
135 stp d14, d15, [$state], #16
136 stp x19, x20, [$state], #16
137 stp x21, x22, [$state], #16
138 stp x23, x24, [$state], #16
139 stp x25, x26, [$state], #16
140 stp x27, x28, [$state], #16
141
142 // |func| is required to preserve x29, the frame pointer. We cannot load
143 // random values into x29 (see comment above), so compare it against the
144 // expected value and zero the field of |state| if corrupted.
145 mov x9, sp
146 cmp x29, x9
147 b.eq .Lx29_ok
148 str xzr, [$state]
149
150.Lx29_ok:
151 // Restore callee-saved registers.
152 ldp d8, d9, [sp, #16]
153 ldp d10, d11, [sp, #32]
154 ldp d12, d13, [sp, #48]
155 ldp d14, d15, [sp, #64]
156 ldp x19, x20, [sp, #80]
157 ldp x21, x22, [sp, #96]
158 ldp x23, x24, [sp, #112]
159 ldp x25, x26, [sp, #128]
160 ldp x27, x28, [sp, #144]
161
162 ldp x29, x30, [sp], #176
163 ret
164.size abi_test_trampoline,.-abi_test_trampoline
165____
166
167# abi_test_clobber_* zeros the corresponding register. These are used to test
168# the ABI-testing framework.
169foreach (0..29) {
170 # x18 is the platform register and off limits.
171 next if ($_ == 18);
172 $code .= <<____;
173.type abi_test_clobber_x$_, %function
174.globl abi_test_clobber_x$_
175.align 4
176abi_test_clobber_x$_:
177 mov x$_, xzr
178 ret
179.size abi_test_clobber_x$_,.-abi_test_clobber_x$_
180____
181}
182foreach (0..31) {
183 $code .= <<____;
184.type abi_test_clobber_d$_, %function
185.globl abi_test_clobber_d$_
186.align 4
187abi_test_clobber_d$_:
188 fmov d$_, xzr
189 ret
190.size abi_test_clobber_d$_,.-abi_test_clobber_d$_
191____
192}
193
194# abi_test_clobber_v*_upper clobbers only the upper half of v*. AAPCS64 only
195# requires the lower half (d*) be preserved.
196foreach (8..15) {
197 $code .= <<____;
198.type abi_test_clobber_v${_}_upper, %function
199.globl abi_test_clobber_v${_}_upper
200.align 4
201abi_test_clobber_v${_}_upper:
202 fmov v${_}.d[1], xzr
203 ret
204.size abi_test_clobber_v${_}_upper,.-abi_test_clobber_v${_}_upper
205____
206}
207
208print $code;
Pete Bentley0c61efe2019-08-13 09:32:23 +0100209close STDOUT or die "error closing STDOUT";