summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/perlasm/x86nasm.pl
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/perlasm/x86nasm.pl')
-rw-r--r--src/lib/libcrypto/perlasm/x86nasm.pl362
1 files changed, 362 insertions, 0 deletions
diff --git a/src/lib/libcrypto/perlasm/x86nasm.pl b/src/lib/libcrypto/perlasm/x86nasm.pl
new file mode 100644
index 0000000000..5009acb4b3
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/x86nasm.pl
@@ -0,0 +1,362 @@
1#!/usr/local/bin/perl
2
3package x86nasm;
4
5$label="L000";
6
7%lb=( 'eax', 'al',
8 'ebx', 'bl',
9 'ecx', 'cl',
10 'edx', 'dl',
11 'ax', 'al',
12 'bx', 'bl',
13 'cx', 'cl',
14 'dx', 'dl',
15 );
16
17%hb=( 'eax', 'ah',
18 'ebx', 'bh',
19 'ecx', 'ch',
20 'edx', 'dh',
21 'ax', 'ah',
22 'bx', 'bh',
23 'cx', 'ch',
24 'dx', 'dh',
25 );
26
27sub main'asm_init_output { @out=(); }
28sub main'asm_get_output { return(@out); }
29sub main'get_labels { return(@labels); }
30
31sub main'external_label
32{
33 push(@labels,@_);
34 foreach (@_) {
35 push(@out, "extern\t_$_\n");
36 }
37}
38
39sub main'LB
40 {
41 (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
42 return($lb{$_[0]});
43 }
44
45sub main'HB
46 {
47 (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
48 return($hb{$_[0]});
49 }
50
51sub main'BP
52 {
53 &get_mem("BYTE",@_);
54 }
55
56sub main'DWP
57 {
58 &get_mem("DWORD",@_);
59 }
60
61sub main'BC
62 {
63 return "BYTE @_";
64 }
65
66sub main'DWC
67 {
68 return "DWORD @_";
69 }
70
71sub main'stack_push
72 {
73 my($num)=@_;
74 $stack+=$num*4;
75 &main'sub("esp",$num*4);
76 }
77
78sub main'stack_pop
79 {
80 my($num)=@_;
81 $stack-=$num*4;
82 &main'add("esp",$num*4);
83 }
84
85sub get_mem
86 {
87 my($size,$addr,$reg1,$reg2,$idx)=@_;
88 my($t,$post);
89 my($ret)="$size [";
90 $addr =~ s/^\s+//;
91 if ($addr =~ /^(.+)\+(.+)$/)
92 {
93 $reg2=&conv($1);
94 $addr="_$2";
95 }
96 elsif ($addr =~ /^[_a-zA-Z]/)
97 {
98 $addr="_$addr";
99 }
100
101 if ($addr =~ /^.+\-.+$/) { $addr="($addr)"; }
102
103 $reg1="$regs{$reg1}" if defined($regs{$reg1});
104 $reg2="$regs{$reg2}" if defined($regs{$reg2});
105 if (($addr ne "") && ($addr ne 0))
106 {
107 if ($addr !~ /^-/)
108 { $ret.="${addr}+"; }
109 else { $post=$addr; }
110 }
111 if ($reg2 ne "")
112 {
113 $t="";
114 $t="*$idx" if ($idx != 0);
115 $reg1="+".$reg1 if ("$reg1$post" ne "");
116 $ret.="$reg2$t$reg1$post]";
117 }
118 else
119 {
120 $ret.="$reg1$post]"
121 }
122 $ret =~ s/\+\]/]/; # in case $addr was the only argument
123 return($ret);
124 }
125
126sub main'mov { &out2("mov",@_); }
127sub main'movb { &out2("mov",@_); }
128sub main'and { &out2("and",@_); }
129sub main'or { &out2("or",@_); }
130sub main'shl { &out2("shl",@_); }
131sub main'shr { &out2("shr",@_); }
132sub main'xor { &out2("xor",@_); }
133sub main'xorb { &out2("xor",@_); }
134sub main'add { &out2("add",@_); }
135sub main'adc { &out2("adc",@_); }
136sub main'sub { &out2("sub",@_); }
137sub main'rotl { &out2("rol",@_); }
138sub main'rotr { &out2("ror",@_); }
139sub main'exch { &out2("xchg",@_); }
140sub main'cmp { &out2("cmp",@_); }
141sub main'lea { &out2("lea",@_); }
142sub main'mul { &out1("mul",@_); }
143sub main'div { &out1("div",@_); }
144sub main'dec { &out1("dec",@_); }
145sub main'inc { &out1("inc",@_); }
146sub main'jmp { &out1("jmp",@_); }
147sub main'jmp_ptr { &out1p("jmp",@_); }
148
149# This is a bit of a kludge: declare all branches as NEAR.
150sub main'je { &out1("je NEAR",@_); }
151sub main'jle { &out1("jle NEAR",@_); }
152sub main'jz { &out1("jz NEAR",@_); }
153sub main'jge { &out1("jge NEAR",@_); }
154sub main'jl { &out1("jl NEAR",@_); }
155sub main'ja { &out1("ja NEAR",@_); }
156sub main'jae { &out1("jae NEAR",@_); }
157sub main'jb { &out1("jb NEAR",@_); }
158sub main'jbe { &out1("jbe NEAR",@_); }
159sub main'jc { &out1("jc NEAR",@_); }
160sub main'jnc { &out1("jnc NEAR",@_); }
161sub main'jnz { &out1("jnz NEAR",@_); }
162sub main'jne { &out1("jne NEAR",@_); }
163sub main'jno { &out1("jno NEAR",@_); }
164
165sub main'push { &out1("push",@_); $stack+=4; }
166sub main'pop { &out1("pop",@_); $stack-=4; }
167sub main'bswap { &out1("bswap",@_); &using486(); }
168sub main'not { &out1("not",@_); }
169sub main'call { &out1("call",($_[0]=~/^\$L/?'':'_').$_[0]); }
170sub main'ret { &out0("ret"); }
171sub main'nop { &out0("nop"); }
172sub main'movz { &out2("movzx",@_); }
173
174sub out2
175 {
176 my($name,$p1,$p2)=@_;
177 my($l,$t);
178
179 push(@out,"\t$name\t");
180 if ($name eq "lea")
181 {
182 $p1 =~ s/^[^\[]*\[/\[/;
183 $p2 =~ s/^[^\[]*\[/\[/;
184 }
185 $t=&conv($p1).",";
186 $l=length($t);
187 push(@out,$t);
188 $l=4-($l+9)/8;
189 push(@out,"\t" x $l);
190 push(@out,&conv($p2));
191 push(@out,"\n");
192 }
193
194sub out0
195 {
196 my($name)=@_;
197
198 push(@out,"\t$name\n");
199 }
200
201sub out1
202 {
203 my($name,$p1)=@_;
204 my($l,$t);
205 push(@out,"\t$name\t".&conv($p1)."\n");
206 }
207
208sub conv
209 {
210 my($p)=@_;
211 $p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
212 return $p;
213 }
214
215sub using486
216 {
217 return if $using486;
218 $using486++;
219 grep(s/\.386/\.486/,@out);
220 }
221
222sub main'file
223 {
224 push(@out, "segment .text use32\n");
225 }
226
227sub main'function_begin
228 {
229 my($func,$extra)=@_;
230
231 push(@labels,$func);
232 my($tmp)=<<"EOF";
233global _$func
234_$func:
235 push ebp
236 push ebx
237 push esi
238 push edi
239EOF
240 push(@out,$tmp);
241 $stack=20;
242 }
243
244sub main'function_begin_B
245 {
246 my($func,$extra)=@_;
247 my($tmp)=<<"EOF";
248global _$func
249_$func:
250EOF
251 push(@out,$tmp);
252 $stack=4;
253 }
254
255sub main'function_end
256 {
257 my($func)=@_;
258
259 my($tmp)=<<"EOF";
260 pop edi
261 pop esi
262 pop ebx
263 pop ebp
264 ret
265EOF
266 push(@out,$tmp);
267 $stack=0;
268 %label=();
269 }
270
271sub main'function_end_B
272 {
273 $stack=0;
274 %label=();
275 }
276
277sub main'function_end_A
278 {
279 my($func)=@_;
280
281 my($tmp)=<<"EOF";
282 pop edi
283 pop esi
284 pop ebx
285 pop ebp
286 ret
287EOF
288 push(@out,$tmp);
289 }
290
291sub main'file_end
292 {
293 }
294
295sub main'wparam
296 {
297 my($num)=@_;
298
299 return(&main'DWP($stack+$num*4,"esp","",0));
300 }
301
302sub main'swtmp
303 {
304 return(&main'DWP($_[0]*4,"esp","",0));
305 }
306
307# Should use swtmp, which is above esp. Linix can trash the stack above esp
308#sub main'wtmp
309# {
310# my($num)=@_;
311#
312# return(&main'DWP(-(($num+1)*4),"esp","",0));
313# }
314
315sub main'comment
316 {
317 foreach (@_)
318 {
319 push(@out,"\t; $_\n");
320 }
321 }
322
323sub main'label
324 {
325 if (!defined($label{$_[0]}))
326 {
327 $label{$_[0]}="\$${label}${_[0]}";
328 $label++;
329 }
330 return($label{$_[0]});
331 }
332
333sub main'set_label
334 {
335 if (!defined($label{$_[0]}))
336 {
337 $label{$_[0]}="\$${label}${_[0]}";
338 $label++;
339 }
340 push(@out,"$label{$_[0]}:\n");
341 }
342
343sub main'data_word
344 {
345 push(@out,"\tDD\t$_[0]\n");
346 }
347
348sub out1p
349 {
350 my($name,$p1)=@_;
351 my($l,$t);
352
353 push(@out,"\t$name\t ".&conv($p1)."\n");
354 }
355
356sub main'picmeup
357 {
358 local($dst,$sym)=@_;
359 &main'lea($dst,&main'DWP($sym));
360 }
361
362sub main'blindpop { &out1("pop",@_); }