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