• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
124