• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env perl
2# Copyright 2019 The BoringSSL Authors
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	@ Save parameters and all callee-saved registers. For convenience, we
68	@ save r9 on iOS even though it's volatile.
69	vstmdb	sp!, {d8-d15}
70	stmdb	sp!, {r0-r11,lr}
71
72	@ Reserve stack space for six (10-4) stack parameters, plus an extra 4
73	@ bytes to keep it 8-byte-aligned (see AAPCS, section 5.3).
74	sub     sp, sp, #28
75
76	@ Every register in AAPCS is either non-volatile or a parameter (except
77	@ r9 on iOS), so this code, by the actual call, loses all its scratch
78	@ registers. First fill in stack parameters while there are registers
79	@ to spare.
80	cmp	$argc, #4
81	bls	.Lstack_args_done
82	mov	r4, sp				@ r4 is the output pointer.
83	add	r5, $argv, $argc, lsl #2	@ Set r5 to the end of argv.
84	add	$argv, $argv, #16		@ Skip four arguments.
85.Lstack_args_loop:
86	ldr	r6, [$argv], #4
87	cmp	$argv, r5
88	str	r6, [r4], #4
89	bne	.Lstack_args_loop
90
91.Lstack_args_done:
92	@ Load registers from |$state|.
93	vldmia	$state!, {d8-d15}
94#if defined(__APPLE__)
95	@ r9 is not volatile on iOS.
96	ldmia	$state!, {r4-r8,r10-r11}
97#else
98	ldmia	$state!, {r4-r11}
99#endif
100
101	@ Load register parameters. This uses up our remaining registers, so we
102	@ repurpose lr as scratch space.
103	ldr	$argc, [sp, #40]	@ Reload argc.
104	ldr	lr, [sp, #36]		@ Load argv into lr.
105	cmp	$argc, #3
106	bhi	.Larg_r3
107	beq	.Larg_r2
108	cmp	$argc, #1
109	bhi	.Larg_r1
110	beq	.Larg_r0
111	b	.Largs_done
112
113.Larg_r3:
114	ldr	r3, [lr, #12]	@ argv[3]
115.Larg_r2:
116	ldr	r2, [lr, #8]	@ argv[2]
117.Larg_r1:
118	ldr	r1, [lr, #4]	@ argv[1]
119.Larg_r0:
120	ldr	r0, [lr]	@ argv[0]
121.Largs_done:
122
123	@ With every other register in use, load the function pointer into lr
124	@ and call the function.
125	ldr	lr, [sp, #28]
126	blx	lr
127
128	@ r1-r3 are free for use again. The trampoline only supports
129	@ single-return functions. Pass r4-r11 to the caller.
130	ldr	$state, [sp, #32]
131	vstmia	$state!, {d8-d15}
132#if defined(__APPLE__)
133	@ r9 is not volatile on iOS.
134	stmia	$state!, {r4-r8,r10-r11}
135#else
136	stmia	$state!, {r4-r11}
137#endif
138
139	@ Unwind the stack and restore registers.
140	add	sp, sp, #44		@ 44 = 28+16
141	ldmia	sp!, {r4-r11,lr}	@ Skip r0-r3 (see +16 above).
142	vldmia	sp!, {d8-d15}
143
144	bx	lr
145.size	abi_test_trampoline,.-abi_test_trampoline
146____
147
148# abi_test_clobber_* zeros the corresponding register. These are used to test
149# the ABI-testing framework.
150foreach (0..12) {
151  # This loop skips r13 (sp), r14 (lr, implicitly clobbered by every call), and
152  # r15 (pc).
153  $code .= <<____;
154.type	abi_test_clobber_r$_, %function
155.globl	abi_test_clobber_r$_
156.align	4
157abi_test_clobber_r$_:
158	mov	r$_, #0
159	bx	lr
160.size	abi_test_clobber_r$_,.-abi_test_clobber_r$_
161____
162}
163
164foreach (0..15) {
165  my $lo = "s".(2*$_);
166  my $hi = "s".(2*$_+1);
167  $code .= <<____;
168.type	abi_test_clobber_d$_, %function
169.globl	abi_test_clobber_d$_
170.align	4
171abi_test_clobber_d$_:
172	mov	r0, #0
173	vmov	$lo, r0
174	vmov	$hi, r0
175	bx	lr
176.size	abi_test_clobber_d$_,.-abi_test_clobber_d$_
177____
178}
179
180print $code;
181close STDOUT or die "error closing STDOUT: $!";
182