• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/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;
182close STDOUT;
183