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.pl370
1 files changed, 370 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..4bdb3fe180
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/x86nasm.pl
@@ -0,0 +1,370 @@
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 local $tmp;
225 $tmp=<<___;
226%ifdef __omf__
227section code use32 class=code
228%else
229section .text
230%endif
231___
232 push(@out,$tmp);
233 }
234
235sub main'function_begin
236 {
237 my($func,$extra)=@_;
238
239 push(@labels,$func);
240 my($tmp)=<<"EOF";
241global _$func
242_$func:
243 push ebp
244 push ebx
245 push esi
246 push edi
247EOF
248 push(@out,$tmp);
249 $stack=20;
250 }
251
252sub main'function_begin_B
253 {
254 my($func,$extra)=@_;
255 my($tmp)=<<"EOF";
256global _$func
257_$func:
258EOF
259 push(@out,$tmp);
260 $stack=4;
261 }
262
263sub main'function_end
264 {
265 my($func)=@_;
266
267 my($tmp)=<<"EOF";
268 pop edi
269 pop esi
270 pop ebx
271 pop ebp
272 ret
273EOF
274 push(@out,$tmp);
275 $stack=0;
276 %label=();
277 }
278
279sub main'function_end_B
280 {
281 $stack=0;
282 %label=();
283 }
284
285sub main'function_end_A
286 {
287 my($func)=@_;
288
289 my($tmp)=<<"EOF";
290 pop edi
291 pop esi
292 pop ebx
293 pop ebp
294 ret
295EOF
296 push(@out,$tmp);
297 }
298
299sub main'file_end
300 {
301 }
302
303sub main'wparam
304 {
305 my($num)=@_;
306
307 return(&main'DWP($stack+$num*4,"esp","",0));
308 }
309
310sub main'swtmp
311 {
312 return(&main'DWP($_[0]*4,"esp","",0));
313 }
314
315# Should use swtmp, which is above esp. Linix can trash the stack above esp
316#sub main'wtmp
317# {
318# my($num)=@_;
319#
320# return(&main'DWP(-(($num+1)*4),"esp","",0));
321# }
322
323sub main'comment
324 {
325 foreach (@_)
326 {
327 push(@out,"\t; $_\n");
328 }
329 }
330
331sub main'label
332 {
333 if (!defined($label{$_[0]}))
334 {
335 $label{$_[0]}="\$${label}${_[0]}";
336 $label++;
337 }
338 return($label{$_[0]});
339 }
340
341sub main'set_label
342 {
343 if (!defined($label{$_[0]}))
344 {
345 $label{$_[0]}="\$${label}${_[0]}";
346 $label++;
347 }
348 push(@out,"$label{$_[0]}:\n");
349 }
350
351sub main'data_word
352 {
353 push(@out,"\tDD\t$_[0]\n");
354 }
355
356sub out1p
357 {
358 my($name,$p1)=@_;
359 my($l,$t);
360
361 push(@out,"\t$name\t ".&conv($p1)."\n");
362 }
363
364sub main'picmeup
365 {
366 local($dst,$sym)=@_;
367 &main'lea($dst,&main'DWP($sym));
368 }
369
370sub main'blindpop { &out1("pop",@_); }