1#!/usr/bin/env perl 2# Copyright (c) 2018, 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 x86. See 17# 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 (Mac), or equivalent is 23# used. 24# 25# References: 26# 27# SysV ABI: https://uclibc.org/docs/psABI-i386.pdf 28# Win32 ABI: https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions?view=vs-2017 29 30use strict; 31 32$0 =~ m/(.*[\/\\])[^\/\\]+$/; 33my $dir = $1; 34push(@INC, "${dir}", "${dir}../../perlasm"); 35require "x86asm.pl"; 36 37my $output = pop; 38open STDOUT, ">$output"; 39 40&asm_init($ARGV[0]); 41 42# abi_test_trampoline loads callee-saved registers from |state|, calls |func| 43# with |argv|, then saves the callee-saved registers into |state|. It returns 44# the result of |func|. |unwind| is ignored. 45# uint32_t abi_test_trampoline(void (*func)(...), CallerState *state, 46# const uint32_t *argv, size_t argc, 47# int unwind); 48&function_begin("abi_test_trampoline") 49 # Load registers from |state|. Note |function_begin| (as opposed to 50 # |function_begin_B|) automatically saves all callee-saved registers, so we 51 # may freely clobber them. 52 &mov("ecx", &wparam(1)); 53 &mov("esi", &DWP(4*0, "ecx")); 54 &mov("edi", &DWP(4*1, "ecx")); 55 &mov("ebx", &DWP(4*2, "ecx")); 56 &mov("ebp", &DWP(4*3, "ecx")); 57 58 # Use a fixed stack allocation so |wparam| continues to work. abi_test.h 59 # supports at most 10 arguments. The SysV ABI requires a 16-byte-aligned 60 # stack on process entry, so round up to 3 (mod 4). 61 &stack_push(11); 62 63 # Copy parameters to stack. 64 &mov("eax", &wparam(2)); 65 &xor("ecx", "ecx"); 66&set_label("loop"); 67 &cmp("ecx", &wparam(3)); 68 &jae(&label("loop_done")); 69 &mov("edx", &DWP(0, "eax", "ecx", 4)); 70 &mov(&DWP(0, "esp", "ecx", 4), "edx"); 71 &add("ecx", 1); 72 &jmp(&label("loop")); 73 74&set_label("loop_done"); 75 &call_ptr(&wparam(0)); 76 77 &stack_pop(11); 78 79 # Save registers back into |state|. 80 &mov("ecx", &wparam(1)); 81 &mov(&DWP(4*0, "ecx"), "esi"); 82 &mov(&DWP(4*1, "ecx"), "edi"); 83 &mov(&DWP(4*2, "ecx"), "ebx"); 84 &mov(&DWP(4*3, "ecx"), "ebp"); 85&function_end("abi_test_trampoline") 86 87# abi_test_get_and_clear_direction_flag clears the direction flag. If the flag 88# was previously set, it returns one. Otherwise, it returns zero. 89# int abi_test_get_and_clear_direction_flag(void); 90&function_begin_B("abi_test_get_and_clear_direction_flag"); 91 &pushf(); 92 &pop("eax"); 93 &and("eax", 0x400); 94 &shr("eax", 10); 95 &cld(); 96 &ret(); 97&function_end_B("abi_test_get_and_clear_direction_flag"); 98 99# abi_test_set_direction_flag sets the direction flag. 100# void abi_test_set_direction_flag(void); 101&function_begin_B("abi_test_set_direction_flag"); 102 &std(); 103 &ret(); 104&function_end_B("abi_test_set_direction_flag"); 105 106# abi_test_clobber_* zeros the corresponding register. These are used to test 107# the ABI-testing framework. 108foreach ("eax", "ebx", "ecx", "edx", "edi", "esi", "ebp") { 109&function_begin_B("abi_test_clobber_$_"); 110 &xor($_, $_); 111 &ret(); 112&function_end_B("abi_test_clobber_$_"); 113} 114foreach (0..7) { 115&function_begin_B("abi_test_clobber_xmm$_"); 116 &pxor("xmm$_", "xmm$_"); 117 &ret(); 118&function_end_B("abi_test_clobber_xmm$_"); 119} 120 121&asm_finish(); 122 123close STDOUT or die "error closing STDOUT: $!"; 124