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.pl342
1 files changed, 342 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..b4da364bbf
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/x86nasm.pl
@@ -0,0 +1,342 @@
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)="[";
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 $reg1="$regs{$reg1}" if defined($regs{$reg1});
102 $reg2="$regs{$reg2}" if defined($regs{$reg2});
103 if (($addr ne "") && ($addr ne 0))
104 {
105 if ($addr !~ /^-/)
106 { $ret.="${addr}+"; }
107 else { $post=$addr; }
108 }
109 if ($reg2 ne "")
110 {
111 $t="";
112 $t="*$idx" if ($idx != 0);
113 $reg1="+".$reg1 if ("$reg1$post" ne "");
114 $ret.="$reg2$t$reg1$post]";
115 }
116 else
117 {
118 $ret.="$reg1$post]"
119 }
120 return($ret);
121 }
122
123sub main'mov { &out2("mov",@_); }
124sub main'movb { &out2("mov",@_); }
125sub main'and { &out2("and",@_); }
126sub main'or { &out2("or",@_); }
127sub main'shl { &out2("shl",@_); }
128sub main'shr { &out2("shr",@_); }
129sub main'xor { &out2("xor",@_); }
130sub main'xorb { &out2("xor",@_); }
131sub main'add { &out2("add",@_); }
132sub main'adc { &out2("adc",@_); }
133sub main'sub { &out2("sub",@_); }
134sub main'rotl { &out2("rol",@_); }
135sub main'rotr { &out2("ror",@_); }
136sub main'exch { &out2("xchg",@_); }
137sub main'cmp { &out2("cmp",@_); }
138sub main'lea { &out2("lea",@_); }
139sub main'mul { &out1("mul",@_); }
140sub main'div { &out1("div",@_); }
141sub main'dec { &out1("dec",@_); }
142sub main'inc { &out1("inc",@_); }
143sub main'jmp { &out1("jmp",@_); }
144sub main'jmp_ptr { &out1p("jmp",@_); }
145
146# This is a bit of a kludge: declare all branches as NEAR.
147sub main'je { &out1("je NEAR",@_); }
148sub main'jle { &out1("jle NEAR",@_); }
149sub main'jz { &out1("jz NEAR",@_); }
150sub main'jge { &out1("jge NEAR",@_); }
151sub main'jl { &out1("jl NEAR",@_); }
152sub main'jb { &out1("jb NEAR",@_); }
153sub main'jc { &out1("jc NEAR",@_); }
154sub main'jnc { &out1("jnc NEAR",@_); }
155sub main'jnz { &out1("jnz NEAR",@_); }
156sub main'jne { &out1("jne NEAR",@_); }
157sub main'jno { &out1("jno NEAR",@_); }
158
159sub main'push { &out1("push",@_); $stack+=4; }
160sub main'pop { &out1("pop",@_); $stack-=4; }
161sub main'bswap { &out1("bswap",@_); &using486(); }
162sub main'not { &out1("not",@_); }
163sub main'call { &out1("call",'_'.$_[0]); }
164sub main'ret { &out0("ret"); }
165sub main'nop { &out0("nop"); }
166
167sub out2
168 {
169 my($name,$p1,$p2)=@_;
170 my($l,$t);
171
172 push(@out,"\t$name\t");
173 $t=&conv($p1).",";
174 $l=length($t);
175 push(@out,$t);
176 $l=4-($l+9)/8;
177 push(@out,"\t" x $l);
178 push(@out,&conv($p2));
179 push(@out,"\n");
180 }
181
182sub out0
183 {
184 my($name)=@_;
185
186 push(@out,"\t$name\n");
187 }
188
189sub out1
190 {
191 my($name,$p1)=@_;
192 my($l,$t);
193 push(@out,"\t$name\t".&conv($p1)."\n");
194 }
195
196sub conv
197 {
198 my($p)=@_;
199 $p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
200 return $p;
201 }
202
203sub using486
204 {
205 return if $using486;
206 $using486++;
207 grep(s/\.386/\.486/,@out);
208 }
209
210sub main'file
211 {
212 push(@out, "segment .text\n");
213 }
214
215sub main'function_begin
216 {
217 my($func,$extra)=@_;
218
219 push(@labels,$func);
220 my($tmp)=<<"EOF";
221global _$func
222_$func:
223 push ebp
224 push ebx
225 push esi
226 push edi
227EOF
228 push(@out,$tmp);
229 $stack=20;
230 }
231
232sub main'function_begin_B
233 {
234 my($func,$extra)=@_;
235 my($tmp)=<<"EOF";
236global _$func
237_$func:
238EOF
239 push(@out,$tmp);
240 $stack=4;
241 }
242
243sub main'function_end
244 {
245 my($func)=@_;
246
247 my($tmp)=<<"EOF";
248 pop edi
249 pop esi
250 pop ebx
251 pop ebp
252 ret
253EOF
254 push(@out,$tmp);
255 $stack=0;
256 %label=();
257 }
258
259sub main'function_end_B
260 {
261 $stack=0;
262 %label=();
263 }
264
265sub main'function_end_A
266 {
267 my($func)=@_;
268
269 my($tmp)=<<"EOF";
270 pop edi
271 pop esi
272 pop ebx
273 pop ebp
274 ret
275EOF
276 push(@out,$tmp);
277 }
278
279sub main'file_end
280 {
281 }
282
283sub main'wparam
284 {
285 my($num)=@_;
286
287 return(&main'DWP($stack+$num*4,"esp","",0));
288 }
289
290sub main'swtmp
291 {
292 return(&main'DWP($_[0]*4,"esp","",0));
293 }
294
295# Should use swtmp, which is above esp. Linix can trash the stack above esp
296#sub main'wtmp
297# {
298# my($num)=@_;
299#
300# return(&main'DWP(-(($num+1)*4),"esp","",0));
301# }
302
303sub main'comment
304 {
305 foreach (@_)
306 {
307 push(@out,"\t; $_\n");
308 }
309 }
310
311sub main'label
312 {
313 if (!defined($label{$_[0]}))
314 {
315 $label{$_[0]}="\$${label}${_[0]}";
316 $label++;
317 }
318 return($label{$_[0]});
319 }
320
321sub main'set_label
322 {
323 if (!defined($label{$_[0]}))
324 {
325 $label{$_[0]}="${label}${_[0]}";
326 $label++;
327 }
328 push(@out,"$label{$_[0]}:\n");
329 }
330
331sub main'data_word
332 {
333 push(@out,"\tDD\t$_[0]\n");
334 }
335
336sub out1p
337 {
338 my($name,$p1)=@_;
339 my($l,$t);
340
341 push(@out,"\t$name\t ".&conv($p1)."\n");
342 }