diff options
author | djm <> | 2010-10-01 22:54:21 +0000 |
---|---|---|
committer | djm <> | 2010-10-01 22:54:21 +0000 |
commit | 829fd51d4f8dde4a7f3bf54754f3c1d1a502f5e2 (patch) | |
tree | e03b9f1bd051e844b971936729e9df549a209130 /src/lib/libcrypto/perlasm/x86asm.pl | |
parent | e6b755d2a53d3cac7a344dfdd6bf7c951cac754c (diff) | |
download | openbsd-829fd51d4f8dde4a7f3bf54754f3c1d1a502f5e2.tar.gz openbsd-829fd51d4f8dde4a7f3bf54754f3c1d1a502f5e2.tar.bz2 openbsd-829fd51d4f8dde4a7f3bf54754f3c1d1a502f5e2.zip |
import OpenSSL-1.0.0a
Diffstat (limited to 'src/lib/libcrypto/perlasm/x86asm.pl')
-rw-r--r-- | src/lib/libcrypto/perlasm/x86asm.pl | 317 |
1 files changed, 197 insertions, 120 deletions
diff --git a/src/lib/libcrypto/perlasm/x86asm.pl b/src/lib/libcrypto/perlasm/x86asm.pl index 5979122158..28080caaa6 100644 --- a/src/lib/libcrypto/perlasm/x86asm.pl +++ b/src/lib/libcrypto/perlasm/x86asm.pl | |||
@@ -1,130 +1,207 @@ | |||
1 | #!/usr/local/bin/perl | 1 | #!/usr/bin/env perl |
2 | 2 | ||
3 | # require 'x86asm.pl'; | 3 | # require 'x86asm.pl'; |
4 | # &asm_init("cpp","des-586.pl"); | 4 | # &asm_init(<flavor>,"des-586.pl"[,$i386only]); |
5 | # XXX | 5 | # &function_begin("foo"); |
6 | # XXX | 6 | # ... |
7 | # main'asm_finish | 7 | # &function_end("foo"); |
8 | 8 | # &asm_finish | |
9 | sub main'asm_finish | 9 | |
10 | { | 10 | $out=(); |
11 | &file_end(); | 11 | $i386=0; |
12 | &asm_finish_cpp() if $cpp; | 12 | |
13 | print &asm_get_output(); | 13 | # AUTOLOAD is this context has quite unpleasant side effect, namely |
14 | } | 14 | # that typos in function calls effectively go to assembler output, |
15 | 15 | # but on the pros side we don't have to implement one subroutine per | |
16 | sub main'asm_init | 16 | # each opcode... |
17 | { | 17 | sub ::AUTOLOAD |
18 | ($type,$fn,$i386)=@_; | 18 | { my $opcode = $AUTOLOAD; |
19 | $filename=$fn; | 19 | |
20 | 20 | die "more than 4 arguments passed to $opcode" if ($#_>3); | |
21 | $elf=$cpp=$coff=$aout=$win32=$netware=$mwerks=0; | 21 | |
22 | if ( ($type eq "elf")) | 22 | $opcode =~ s/.*:://; |
23 | { $elf=1; require "x86unix.pl"; } | 23 | if ($opcode =~ /^push/) { $stack+=4; } |
24 | elsif ( ($type eq "a.out")) | 24 | elsif ($opcode =~ /^pop/) { $stack-=4; } |
25 | { $aout=1; require "x86unix.pl"; } | 25 | |
26 | elsif ( ($type eq "coff" or $type eq "gaswin")) | 26 | &generic($opcode,@_) or die "undefined subroutine \&$AUTOLOAD"; |
27 | { $coff=1; require "x86unix.pl"; } | 27 | } |
28 | elsif ( ($type eq "cpp")) | 28 | |
29 | { $cpp=1; require "x86unix.pl"; } | 29 | sub ::emit |
30 | elsif ( ($type eq "win32")) | 30 | { my $opcode=shift; |
31 | { $win32=1; require "x86ms.pl"; } | 31 | |
32 | elsif ( ($type eq "win32n")) | 32 | if ($#_==-1) { push(@out,"\t$opcode\n"); } |
33 | { $win32=1; require "x86nasm.pl"; } | 33 | else { push(@out,"\t$opcode\t".join(',',@_)."\n"); } |
34 | elsif ( ($type eq "nw-nasm")) | 34 | } |
35 | { $netware=1; require "x86nasm.pl"; } | 35 | |
36 | elsif ( ($type eq "nw-mwasm")) | 36 | sub ::LB |
37 | { $netware=1; $mwerks=1; require "x86nasm.pl"; } | 37 | { $_[0] =~ m/^e?([a-d])x$/o or die "$_[0] does not have a 'low byte'"; |
38 | else | 38 | $1."l"; |
39 | { | 39 | } |
40 | print STDERR <<"EOF"; | 40 | sub ::HB |
41 | { $_[0] =~ m/^e?([a-d])x$/o or die "$_[0] does not have a 'high byte'"; | ||
42 | $1."h"; | ||
43 | } | ||
44 | sub ::stack_push{ my $num=$_[0]*4; $stack+=$num; &sub("esp",$num); } | ||
45 | sub ::stack_pop { my $num=$_[0]*4; $stack-=$num; &add("esp",$num); } | ||
46 | sub ::blindpop { &pop($_[0]); $stack+=4; } | ||
47 | sub ::wparam { &DWP($stack+4*$_[0],"esp"); } | ||
48 | sub ::swtmp { &DWP(4*$_[0],"esp"); } | ||
49 | |||
50 | sub ::bswap | ||
51 | { if ($i386) # emulate bswap for i386 | ||
52 | { &comment("bswap @_"); | ||
53 | &xchg(&HB(@_),&LB(@_)); | ||
54 | &ror (@_,16); | ||
55 | &xchg(&HB(@_),&LB(@_)); | ||
56 | } | ||
57 | else | ||
58 | { &generic("bswap",@_); } | ||
59 | } | ||
60 | # These are made-up opcodes introduced over the years essentially | ||
61 | # by ignorance, just alias them to real ones... | ||
62 | sub ::movb { &mov(@_); } | ||
63 | sub ::xorb { &xor(@_); } | ||
64 | sub ::rotl { &rol(@_); } | ||
65 | sub ::rotr { &ror(@_); } | ||
66 | sub ::exch { &xchg(@_); } | ||
67 | sub ::halt { &hlt; } | ||
68 | sub ::movz { &movzx(@_); } | ||
69 | sub ::pushf { &pushfd; } | ||
70 | sub ::popf { &popfd; } | ||
71 | |||
72 | # 3 argument instructions | ||
73 | sub ::movq | ||
74 | { my($p1,$p2,$optimize)=@_; | ||
75 | |||
76 | if ($optimize && $p1=~/^mm[0-7]$/ && $p2=~/^mm[0-7]$/) | ||
77 | # movq between mmx registers can sink Intel CPUs | ||
78 | { &::pshufw($p1,$p2,0xe4); } | ||
79 | else | ||
80 | { &::generic("movq",@_); } | ||
81 | } | ||
82 | |||
83 | # label management | ||
84 | $lbdecor="L"; # local label decoration, set by package | ||
85 | $label="000"; | ||
86 | |||
87 | sub ::islabel # see is argument is a known label | ||
88 | { my $i; | ||
89 | foreach $i (values %label) { return $i if ($i eq $_[0]); } | ||
90 | $label{$_[0]}; # can be undef | ||
91 | } | ||
92 | |||
93 | sub ::label # instantiate a function-scope label | ||
94 | { if (!defined($label{$_[0]})) | ||
95 | { $label{$_[0]}="${lbdecor}${label}${_[0]}"; $label++; } | ||
96 | $label{$_[0]}; | ||
97 | } | ||
98 | |||
99 | sub ::LABEL # instantiate a file-scope label | ||
100 | { $label{$_[0]}=$_[1] if (!defined($label{$_[0]})); | ||
101 | $label{$_[0]}; | ||
102 | } | ||
103 | |||
104 | sub ::static_label { &::LABEL($_[0],$lbdecor.$_[0]); } | ||
105 | |||
106 | sub ::set_label_B { push(@out,"@_:\n"); } | ||
107 | sub ::set_label | ||
108 | { my $label=&::label($_[0]); | ||
109 | &::align($_[1]) if ($_[1]>1); | ||
110 | &::set_label_B($label); | ||
111 | $label; | ||
112 | } | ||
113 | |||
114 | sub ::wipe_labels # wipes function-scope labels | ||
115 | { foreach $i (keys %label) | ||
116 | { delete $label{$i} if ($label{$i} =~ /^\Q${lbdecor}\E[0-9]{3}/); } | ||
117 | } | ||
118 | |||
119 | # subroutine management | ||
120 | sub ::function_begin | ||
121 | { &function_begin_B(@_); | ||
122 | $stack=4; | ||
123 | &push("ebp"); | ||
124 | &push("ebx"); | ||
125 | &push("esi"); | ||
126 | &push("edi"); | ||
127 | } | ||
128 | |||
129 | sub ::function_end | ||
130 | { &pop("edi"); | ||
131 | &pop("esi"); | ||
132 | &pop("ebx"); | ||
133 | &pop("ebp"); | ||
134 | &ret(); | ||
135 | &function_end_B(@_); | ||
136 | $stack=0; | ||
137 | &wipe_labels(); | ||
138 | } | ||
139 | |||
140 | sub ::function_end_A | ||
141 | { &pop("edi"); | ||
142 | &pop("esi"); | ||
143 | &pop("ebx"); | ||
144 | &pop("ebp"); | ||
145 | &ret(); | ||
146 | $stack+=16; # readjust esp as if we didn't pop anything | ||
147 | } | ||
148 | |||
149 | sub ::asciz | ||
150 | { my @str=unpack("C*",shift); | ||
151 | push @str,0; | ||
152 | while ($#str>15) { | ||
153 | &data_byte(@str[0..15]); | ||
154 | foreach (0..15) { shift @str; } | ||
155 | } | ||
156 | &data_byte(@str) if (@str); | ||
157 | } | ||
158 | |||
159 | sub ::asm_finish | ||
160 | { &file_end(); | ||
161 | print @out; | ||
162 | } | ||
163 | |||
164 | sub ::asm_init | ||
165 | { my ($type,$fn,$cpu)=@_; | ||
166 | |||
167 | $filename=$fn; | ||
168 | $i386=$cpu; | ||
169 | |||
170 | $elf=$cpp=$coff=$aout=$macosx=$win32=$netware=$mwerks=0; | ||
171 | if (($type eq "elf")) | ||
172 | { $elf=1; require "x86gas.pl"; } | ||
173 | elsif (($type eq "a\.out")) | ||
174 | { $aout=1; require "x86gas.pl"; } | ||
175 | elsif (($type eq "coff" or $type eq "gaswin")) | ||
176 | { $coff=1; require "x86gas.pl"; } | ||
177 | elsif (($type eq "win32n")) | ||
178 | { $win32=1; require "x86nasm.pl"; } | ||
179 | elsif (($type eq "nw-nasm")) | ||
180 | { $netware=1; require "x86nasm.pl"; } | ||
181 | #elsif (($type eq "nw-mwasm")) | ||
182 | #{ $netware=1; $mwerks=1; require "x86nasm.pl"; } | ||
183 | elsif (($type eq "win32")) | ||
184 | { $win32=1; require "x86masm.pl"; } | ||
185 | elsif (($type eq "macosx")) | ||
186 | { $aout=1; $macosx=1; require "x86gas.pl"; } | ||
187 | else | ||
188 | { print STDERR <<"EOF"; | ||
41 | Pick one target type from | 189 | Pick one target type from |
42 | elf - Linux, FreeBSD, Solaris x86, etc. | 190 | elf - Linux, FreeBSD, Solaris x86, etc. |
43 | a.out - OpenBSD, DJGPP, etc. | 191 | a.out - DJGPP, elder OpenBSD, etc. |
44 | coff - GAS/COFF such as Win32 targets | 192 | coff - GAS/COFF such as Win32 targets |
45 | win32 - Windows 95/Windows NT | ||
46 | win32n - Windows 95/Windows NT NASM format | 193 | win32n - Windows 95/Windows NT NASM format |
47 | nw-nasm - NetWare NASM format | 194 | nw-nasm - NetWare NASM format |
48 | nw-mwasm- NetWare Metrowerks Assembler | 195 | macosx - Mac OS X |
49 | EOF | 196 | EOF |
50 | exit(1); | 197 | exit(1); |
51 | } | 198 | } |
52 | 199 | ||
53 | $pic=0; | 200 | $pic=0; |
54 | for (@ARGV) { $pic=1 if (/\-[fK]PIC/i); } | 201 | for (@ARGV) { $pic=1 if (/\-[fK]PIC/i); } |
55 | 202 | ||
56 | &asm_init_output(); | 203 | $filename =~ s/\.pl$//; |
57 | 204 | &file($filename); | |
58 | &comment("Don't even think of reading this code"); | 205 | } |
59 | &comment("It was automatically generated by $filename"); | ||
60 | &comment("Which is a perl program used to generate the x86 assember for"); | ||
61 | &comment("any of ELF, a.out, COFF, Win32, ..."); | ||
62 | &comment("eric <eay\@cryptsoft.com>"); | ||
63 | &comment(""); | ||
64 | |||
65 | $filename =~ s/\.pl$//; | ||
66 | &file($filename); | ||
67 | } | ||
68 | |||
69 | sub asm_finish_cpp | ||
70 | { | ||
71 | return unless $cpp; | ||
72 | |||
73 | local($tmp,$i); | ||
74 | foreach $i (&get_labels()) | ||
75 | { | ||
76 | $tmp.="#define $i _$i\n"; | ||
77 | } | ||
78 | print <<"EOF"; | ||
79 | /* Run the C pre-processor over this file with one of the following defined | ||
80 | * ELF - elf object files, | ||
81 | * OUT - a.out object files, | ||
82 | * BSDI - BSDI style a.out object files | ||
83 | * SOL - Solaris style elf | ||
84 | */ | ||
85 | |||
86 | #define TYPE(a,b) .type a,b | ||
87 | #define SIZE(a,b) .size a,b | ||
88 | |||
89 | #if defined(OUT) || (defined(BSDI) && !defined(ELF)) | ||
90 | $tmp | ||
91 | #endif | ||
92 | |||
93 | #ifdef OUT | ||
94 | #define OK 1 | ||
95 | #define ALIGN 4 | ||
96 | #if defined(__CYGWIN__) || defined(__DJGPP__) || (__MINGW32__) | ||
97 | #undef SIZE | ||
98 | #undef TYPE | ||
99 | #define SIZE(a,b) | ||
100 | #define TYPE(a,b) .def a; .scl 2; .type 32; .endef | ||
101 | #endif /* __CYGWIN || __DJGPP */ | ||
102 | #endif | ||
103 | |||
104 | #if defined(BSDI) && !defined(ELF) | ||
105 | #define OK 1 | ||
106 | #define ALIGN 4 | ||
107 | #undef SIZE | ||
108 | #undef TYPE | ||
109 | #define SIZE(a,b) | ||
110 | #define TYPE(a,b) | ||
111 | #endif | ||
112 | |||
113 | #if defined(ELF) || defined(SOL) | ||
114 | #define OK 1 | ||
115 | #define ALIGN 16 | ||
116 | #endif | ||
117 | |||
118 | #ifndef OK | ||
119 | You need to define one of | ||
120 | ELF - elf systems - linux-elf, NetBSD and DG-UX | ||
121 | OUT - a.out systems - linux-a.out and FreeBSD | ||
122 | SOL - solaris systems, which are elf with strange comment lines | ||
123 | BSDI - a.out with a very primative version of as. | ||
124 | #endif | ||
125 | |||
126 | /* Let the Assembler begin :-) */ | ||
127 | EOF | ||
128 | } | ||
129 | 206 | ||
130 | 1; | 207 | 1; |