|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- #!/usr/bin/env perl
- # Copyright (c) 2019, Google Inc.
- #
- # Permission to use, copy, modify, and/or distribute this software for any
- # purpose with or without fee is hereby granted, provided that the above
- # copyright notice and this permission notice appear in all copies.
- #
- # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- # This file defines helper functions for crypto/test/abi_test.h on aarch64. See
- # that header for details on how to use this.
- #
- # For convenience, this file is linked into libcrypto, where consuming builds
- # already support architecture-specific sources. The static linker should drop
- # this code in non-test binaries. This includes a shared library build of
- # libcrypto, provided --gc-sections (ELF), -dead_strip (iOS), or equivalent is
- # used.
- #
- # References:
- #
- # AAPCS64: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
- # iOS ARM64: https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html
-
- use strict;
-
- my $flavour = shift;
- my $output = shift;
- if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
-
- $0 =~ m/(.*[\/\\])[^\/\\]+$/;
- my $dir = $1;
- my $xlate;
- ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
- ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
- die "can't locate arm-xlate.pl";
-
- open OUT, "| \"$^X\" \"$xlate\" $flavour \"$output\"";
- *STDOUT = *OUT;
-
- my ($func, $state, $argv, $argc) = ("x0", "x1", "x2", "x3");
- my $code = <<____;
- .text
-
- // abi_test_trampoline loads callee-saved registers from |state|, calls |func|
- // with |argv|, then saves the callee-saved registers into |state|. It returns
- // the result of |func|. The |unwind| argument is unused.
- // uint64_t abi_test_trampoline(void (*func)(...), CallerState *state,
- // const uint64_t *argv, size_t argc,
- // uint64_t unwind);
- .type abi_test_trampoline, %function
- .globl abi_test_trampoline
- .align 4
- abi_test_trampoline:
- .Labi_test_trampoline_begin:
- // Stack layout (low to high addresses)
- // x29,x30 (16 bytes)
- // d8-d15 (64 bytes)
- // x19-x28 (80 bytes)
- // $state (8 bytes)
- // padding (8 bytes)
- stp x29, x30, [sp, #-176]!
- mov x29, sp
-
- // Saved callee-saved registers and |state|.
- stp d8, d9, [sp, #16]
- stp d10, d11, [sp, #32]
- stp d12, d13, [sp, #48]
- stp d14, d15, [sp, #64]
- stp x19, x20, [sp, #80]
- stp x21, x22, [sp, #96]
- stp x23, x24, [sp, #112]
- stp x25, x26, [sp, #128]
- stp x27, x28, [sp, #144]
- str $state, [sp, #160]
-
- // Load registers from |state|, with the exception of x29. x29 is the
- // frame pointer and also callee-saved, but AAPCS64 allows platforms to
- // mandate that x29 always point to a frame. iOS64 does so, which means
- // we cannot fill x29 with entropy without violating ABI rules
- // ourselves. x29 is tested separately below.
- ldp d8, d9, [$state], #16
- ldp d10, d11, [$state], #16
- ldp d12, d13, [$state], #16
- ldp d14, d15, [$state], #16
- ldp x19, x20, [$state], #16
- ldp x21, x22, [$state], #16
- ldp x23, x24, [$state], #16
- ldp x25, x26, [$state], #16
- ldp x27, x28, [$state], #16
-
- // Move parameters into temporary registers.
- mov x9, $func
- mov x10, $argv
- mov x11, $argc
-
- // Load parameters into registers.
- cbz x11, .Largs_done
- ldr x0, [x10], #8
- subs x11, x11, #1
- b.eq .Largs_done
- ldr x1, [x10], #8
- subs x11, x11, #1
- b.eq .Largs_done
- ldr x2, [x10], #8
- subs x11, x11, #1
- b.eq .Largs_done
- ldr x3, [x10], #8
- subs x11, x11, #1
- b.eq .Largs_done
- ldr x4, [x10], #8
- subs x11, x11, #1
- b.eq .Largs_done
- ldr x5, [x10], #8
- subs x11, x11, #1
- b.eq .Largs_done
- ldr x6, [x10], #8
- subs x11, x11, #1
- b.eq .Largs_done
- ldr x7, [x10], #8
-
- .Largs_done:
- blr x9
-
- // Reload |state| and store registers.
- ldr $state, [sp, #160]
- stp d8, d9, [$state], #16
- stp d10, d11, [$state], #16
- stp d12, d13, [$state], #16
- stp d14, d15, [$state], #16
- stp x19, x20, [$state], #16
- stp x21, x22, [$state], #16
- stp x23, x24, [$state], #16
- stp x25, x26, [$state], #16
- stp x27, x28, [$state], #16
-
- // |func| is required to preserve x29, the frame pointer. We cannot load
- // random values into x29 (see comment above), so compare it against the
- // expected value and zero the field of |state| if corrupted.
- mov x9, sp
- cmp x29, x9
- b.eq .Lx29_ok
- str xzr, [$state]
-
- .Lx29_ok:
- // Restore callee-saved registers.
- ldp d8, d9, [sp, #16]
- ldp d10, d11, [sp, #32]
- ldp d12, d13, [sp, #48]
- ldp d14, d15, [sp, #64]
- ldp x19, x20, [sp, #80]
- ldp x21, x22, [sp, #96]
- ldp x23, x24, [sp, #112]
- ldp x25, x26, [sp, #128]
- ldp x27, x28, [sp, #144]
-
- ldp x29, x30, [sp], #176
- ret
- .size abi_test_trampoline,.-abi_test_trampoline
- ____
-
- # abi_test_clobber_* zeros the corresponding register. These are used to test
- # the ABI-testing framework.
- foreach (0..29) {
- # x18 is the platform register and off limits.
- next if ($_ == 18);
- $code .= <<____;
- .type abi_test_clobber_x$_, %function
- .globl abi_test_clobber_x$_
- .align 4
- abi_test_clobber_x$_:
- mov x$_, xzr
- ret
- .size abi_test_clobber_x$_,.-abi_test_clobber_x$_
- ____
- }
- foreach (0..31) {
- $code .= <<____;
- .type abi_test_clobber_d$_, %function
- .globl abi_test_clobber_d$_
- .align 4
- abi_test_clobber_d$_:
- fmov d$_, xzr
- ret
- .size abi_test_clobber_d$_,.-abi_test_clobber_d$_
- ____
- }
-
- # abi_test_clobber_v*_upper clobbers only the upper half of v*. AAPCS64 only
- # requires the lower half (d*) be preserved.
- foreach (8..15) {
- $code .= <<____;
- .type abi_test_clobber_v${_}_upper, %function
- .globl abi_test_clobber_v${_}_upper
- .align 4
- abi_test_clobber_v${_}_upper:
- fmov v${_}.d[1], xzr
- ret
- .size abi_test_clobber_v${_}_upper,.-abi_test_clobber_v${_}_upper
- ____
- }
-
- print $code;
- close STDOUT;
|