blob: 30f510e75a526192f68bded9cb36bc6f5d1facdf [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 32-bit
17# ARM. See 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# AAPCS: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf
28# iOS ARMv6: https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html
29# iOS ARMv7: https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv7FunctionCallingConventions.html
30# Linux: http://sourcery.mentor.com/sgpp/lite/arm/portal/kbattach142/arm_gnu_linux_%20abi.pdf
31
32use strict;
33
34my $flavour = shift;
35my $output = shift;
36if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
37
38$0 =~ m/(.*[\/\\])[^\/\\]+$/;
39my $dir = $1;
40my $xlate;
41( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
42( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
43die "can't locate arm-xlate.pl";
44
45open OUT, "| \"$^X\" \"$xlate\" $flavour \"$output\"";
46*STDOUT = *OUT;
47
48my ($func, $state, $argv, $argc) = ("r0", "r1", "r2", "r3");
49my $code = <<____;
50.syntax unified
51
52.arch armv7-a
53.fpu vfp
54
55.text
56
57@ abi_test_trampoline loads callee-saved registers from |state|, calls |func|
58@ with |argv|, then saves the callee-saved registers into |state|. It returns
59@ the result of |func|. The |unwind| argument is unused.
60@ uint32_t abi_test_trampoline(void (*func)(...), CallerState *state,
61@ const uint32_t *argv, size_t argc,
62@ int unwind);
63.type abi_test_trampoline, %function
64.globl abi_test_trampoline
65.align 4
66abi_test_trampoline:
67.Labi_test_trampoline_begin:
68 @ Save parameters and all callee-saved registers. For convenience, we
69 @ save r9 on iOS even though it's volatile.
70 vstmdb sp!, {d8-d15}
71 stmdb sp!, {r0-r11,lr}
72
73 @ Reserve stack space for six (10-4) stack parameters, plus an extra 4
74 @ bytes to keep it 8-byte-aligned (see AAPCS, section 5.3).
75 sub sp, sp, #28
76
77 @ Every register in AAPCS is either non-volatile or a parameter (except
78 @ r9 on iOS), so this code, by the actual call, loses all its scratch
79 @ registers. First fill in stack parameters while there are registers
80 @ to spare.
81 cmp $argc, #4
82 bls .Lstack_args_done
83 mov r4, sp @ r4 is the output pointer.
84 add r5, $argv, $argc, lsl #2 @ Set r5 to the end of argv.
85 add $argv, $argv, #16 @ Skip four arguments.
86.Lstack_args_loop:
87 ldr r6, [$argv], #4
88 cmp $argv, r5
89 str r6, [r4], #4
90 bne .Lstack_args_loop
91
92.Lstack_args_done:
93 @ Load registers from |$state|.
94 vldmia $state!, {d8-d15}
95#if defined(__APPLE__)
96 @ r9 is not volatile on iOS.
97 ldmia $state!, {r4-r8,r10-r11}
98#else
99 ldmia $state!, {r4-r11}
100#endif
101
102 @ Load register parameters. This uses up our remaining registers, so we
103 @ repurpose lr as scratch space.
104 ldr $argc, [sp, #40] @ Reload argc.
105 ldr lr, [sp, #36] @ Load argv into lr.
106 cmp $argc, #3
107 bhi .Larg_r3
108 beq .Larg_r2
109 cmp $argc, #1
110 bhi .Larg_r1
111 beq .Larg_r0
112 b .Largs_done
113
114.Larg_r3:
115 ldr r3, [lr, #12] @ argv[3]
116.Larg_r2:
117 ldr r2, [lr, #8] @ argv[2]
118.Larg_r1:
119 ldr r1, [lr, #4] @ argv[1]
120.Larg_r0:
121 ldr r0, [lr] @ argv[0]
122.Largs_done:
123
124 @ With every other register in use, load the function pointer into lr
125 @ and call the function.
126 ldr lr, [sp, #28]
127 blx lr
128
129 @ r1-r3 are free for use again. The trampoline only supports
130 @ single-return functions. Pass r4-r11 to the caller.
131 ldr $state, [sp, #32]
132 vstmia $state!, {d8-d15}
133#if defined(__APPLE__)
134 @ r9 is not volatile on iOS.
135 stmia $state!, {r4-r8,r10-r11}
136#else
137 stmia $state!, {r4-r11}
138#endif
139
140 @ Unwind the stack and restore registers.
141 add sp, sp, #44 @ 44 = 28+16
142 ldmia sp!, {r4-r11,lr} @ Skip r0-r3 (see +16 above).
143 vldmia sp!, {d8-d15}
144
145 bx lr
146.size abi_test_trampoline,.-abi_test_trampoline
147____
148
149# abi_test_clobber_* zeros the corresponding register. These are used to test
150# the ABI-testing framework.
151foreach (0..12) {
152 # This loop skips r13 (sp), r14 (lr, implicitly clobbered by every call), and
153 # r15 (pc).
154 $code .= <<____;
155.type abi_test_clobber_r$_, %function
156.globl abi_test_clobber_r$_
157.align 4
158abi_test_clobber_r$_:
159 mov r$_, #0
160 bx lr
161.size abi_test_clobber_r$_,.-abi_test_clobber_r$_
162____
163}
164
165foreach (0..15) {
166 my $lo = "s".(2*$_);
167 my $hi = "s".(2*$_+1);
168 $code .= <<____;
169.type abi_test_clobber_d$_, %function
170.globl abi_test_clobber_d$_
171.align 4
172abi_test_clobber_d$_:
173 mov r0, #0
174 vmov $lo, r0
175 vmov $hi, r0
176 bx lr
177.size abi_test_clobber_d$_,.-abi_test_clobber_d$_
178____
179}
180
181print $code;
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000182close STDOUT;