summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/perlasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/perlasm')
-rw-r--r--src/lib/libcrypto/perlasm/alpha.pl434
-rw-r--r--src/lib/libcrypto/perlasm/x86ms.pl365
-rw-r--r--src/lib/libcrypto/perlasm/x86nasm.pl342
-rw-r--r--src/lib/libcrypto/perlasm/x86unix.pl544
4 files changed, 1685 insertions, 0 deletions
diff --git a/src/lib/libcrypto/perlasm/alpha.pl b/src/lib/libcrypto/perlasm/alpha.pl
new file mode 100644
index 0000000000..3dac571743
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/alpha.pl
@@ -0,0 +1,434 @@
1#!/usr/local/bin/perl
2
3package alpha;
4use Carp qw(croak cluck);
5
6$label="100";
7
8$n_debug=0;
9$smear_regs=1;
10$reg_alloc=1;
11
12$align="3";
13$com_start="#";
14
15sub main'asm_init_output { @out=(); }
16sub main'asm_get_output { return(@out); }
17sub main'get_labels { return(@labels); }
18sub main'external_label { push(@labels,@_); }
19
20# General registers
21
22%regs=( 'r0', '$0',
23 'r1', '$1',
24 'r2', '$2',
25 'r3', '$3',
26 'r4', '$4',
27 'r5', '$5',
28 'r6', '$6',
29 'r7', '$7',
30 'r8', '$8',
31 'r9', '$22',
32 'r10', '$23',
33 'r11', '$24',
34 'r12', '$25',
35 'r13', '$27',
36 'r14', '$28',
37 'r15', '$21', # argc == 5
38 'r16', '$20', # argc == 4
39 'r17', '$19', # argc == 3
40 'r18', '$18', # argc == 2
41 'r19', '$17', # argc == 1
42 'r20', '$16', # argc == 0
43 'r21', '$9', # save 0
44 'r22', '$10', # save 1
45 'r23', '$11', # save 2
46 'r24', '$12', # save 3
47 'r25', '$13', # save 4
48 'r26', '$14', # save 5
49
50 'a0', '$16',
51 'a1', '$17',
52 'a2', '$18',
53 'a3', '$19',
54 'a4', '$20',
55 'a5', '$21',
56
57 's0', '$9',
58 's1', '$10',
59 's2', '$11',
60 's3', '$12',
61 's4', '$13',
62 's5', '$14',
63 'zero', '$31',
64 'sp', '$30',
65 );
66
67$main'reg_s0="r21";
68$main'reg_s1="r22";
69$main'reg_s2="r23";
70$main'reg_s3="r24";
71$main'reg_s4="r25";
72$main'reg_s5="r26";
73
74@reg=( '$0', '$1' ,'$2' ,'$3' ,'$4' ,'$5' ,'$6' ,'$7' ,'$8',
75 '$22','$23','$24','$25','$20','$21','$27','$28');
76
77
78sub main'sub { &out3("subq",@_); }
79sub main'add { &out3("addq",@_); }
80sub main'mov { &out3("bis",$_[0],$_[0],$_[1]); }
81sub main'or { &out3("bis",@_); }
82sub main'bis { &out3("bis",@_); }
83sub main'br { &out1("br",@_); }
84sub main'ld { &out2("ldq",@_); }
85sub main'st { &out2("stq",@_); }
86sub main'cmpult { &out3("cmpult",@_); }
87sub main'cmplt { &out3("cmplt",@_); }
88sub main'bgt { &out2("bgt",@_); }
89sub main'ble { &out2("ble",@_); }
90sub main'blt { &out2("blt",@_); }
91sub main'mul { &out3("mulq",@_); }
92sub main'muh { &out3("umulh",@_); }
93
94$main'QWS=8;
95
96sub main'asm_add
97 {
98 push(@out,@_);
99 }
100
101sub main'asm_finish
102 {
103 &main'file_end();
104 print &main'asm_get_output();
105 }
106
107sub main'asm_init
108 {
109 ($type,$fn)=@_;
110 $filename=$fn;
111
112 &main'asm_init_output();
113 &main'comment("Don't even think of reading this code");
114 &main'comment("It was automatically generated by $filename");
115 &main'comment("Which is a perl program used to generate the alpha assember.");
116 &main'comment("eric <eay\@cryptsoft.com>");
117 &main'comment("");
118
119 $filename =~ s/\.pl$//;
120 &main'file($filename);
121 }
122
123sub conv
124 {
125 local($r)=@_;
126 local($v);
127
128 return($regs{$r}) if defined($regs{$r});
129 return($r);
130 }
131
132sub main'QWPw
133 {
134 local($off,$reg)=@_;
135
136 return(&main'QWP($off*8,$reg));
137 }
138
139sub main'QWP
140 {
141 local($off,$reg)=@_;
142
143 $ret="$off(".&conv($reg).")";
144 return($ret);
145 }
146
147sub out3
148 {
149 local($name,$p1,$p2,$p3)=@_;
150
151 $p1=&conv($p1);
152 $p2=&conv($p2);
153 $p3=&conv($p3);
154 push(@out,"\t$name\t");
155 $l=length($p1)+1;
156 push(@out,$p1.",");
157 $ll=3-($l+9)/8;
158 $tmp1=sprintf("\t" x $ll);
159 push(@out,$tmp1);
160
161 $l=length($p2)+1;
162 push(@out,$p2.",");
163 $ll=3-($l+9)/8;
164 $tmp1=sprintf("\t" x $ll);
165 push(@out,$tmp1);
166
167 push(@out,&conv($p3)."\n");
168 }
169
170sub out2
171 {
172 local($name,$p1,$p2,$p3)=@_;
173
174 $p1=&conv($p1);
175 $p2=&conv($p2);
176 push(@out,"\t$name\t");
177 $l=length($p1)+1;
178 push(@out,$p1.",");
179 $ll=3-($l+9)/8;
180 $tmp1=sprintf("\t" x $ll);
181 push(@out,$tmp1);
182
183 push(@out,&conv($p2)."\n");
184 }
185
186sub out1
187 {
188 local($name,$p1)=@_;
189
190 $p1=&conv($p1);
191 push(@out,"\t$name\t".$p1."\n");
192 }
193
194sub out0
195 {
196 push(@out,"\t$_[0]\n");
197 }
198
199sub main'file
200 {
201 local($file)=@_;
202
203 local($tmp)=<<"EOF";
204 # DEC Alpha assember
205 # Generated from perl scripts contains in SSLeay
206 .file 1 "$file.s"
207 .set noat
208EOF
209 push(@out,$tmp);
210 }
211
212sub main'function_begin
213 {
214 local($func)=@_;
215
216print STDERR "$func\n";
217 local($tmp)=<<"EOF";
218 .text
219 .align $align
220 .globl $func
221 .ent $func
222${func}:
223${func}..ng:
224 .frame \$30,0,\$26,0
225 .prologue 0
226EOF
227 push(@out,$tmp);
228 $stack=0;
229 }
230
231sub main'function_end
232 {
233 local($func)=@_;
234
235 local($tmp)=<<"EOF";
236 ret \$31,(\$26),1
237 .end $func
238EOF
239 push(@out,$tmp);
240 $stack=0;
241 %label=();
242 }
243
244sub main'function_end_A
245 {
246 local($func)=@_;
247
248 local($tmp)=<<"EOF";
249 ret \$31,(\$26),1
250EOF
251 push(@out,$tmp);
252 }
253
254sub main'function_end_B
255 {
256 local($func)=@_;
257
258 $func=$under.$func;
259
260 push(@out,"\t.end $func\n");
261 $stack=0;
262 %label=();
263 }
264
265sub main'wparam
266 {
267 local($num)=@_;
268
269 if ($num < 6)
270 {
271 $num=20-$num;
272 return("r$num");
273 }
274 else
275 { return(&main'QWP($stack+$num*8,"sp")); }
276 }
277
278sub main'stack_push
279 {
280 local($num)=@_;
281 $stack+=$num*8;
282 &main'sub("sp",$num*8,"sp");
283 }
284
285sub main'stack_pop
286 {
287 local($num)=@_;
288 $stack-=$num*8;
289 &main'add("sp",$num*8,"sp");
290 }
291
292sub main'swtmp
293 {
294 return(&main'QWP(($_[0])*8,"sp"));
295 }
296
297# Should use swtmp, which is above sp. Linix can trash the stack above esp
298#sub main'wtmp
299# {
300# local($num)=@_;
301#
302# return(&main'QWP(-($num+1)*4,"esp","",0));
303# }
304
305sub main'comment
306 {
307 foreach (@_)
308 {
309 if (/^\s*$/)
310 { push(@out,"\n"); }
311 else
312 { push(@out,"\t$com_start $_ $com_end\n"); }
313 }
314 }
315
316sub main'label
317 {
318 if (!defined($label{$_[0]}))
319 {
320 $label{$_[0]}=$label;
321 $label++;
322 }
323 return('$'.$label{$_[0]});
324 }
325
326sub main'set_label
327 {
328 if (!defined($label{$_[0]}))
329 {
330 $label{$_[0]}=$label;
331 $label++;
332 }
333# push(@out,".align $align\n") if ($_[1] != 0);
334 push(@out,'$'."$label{$_[0]}:\n");
335 }
336
337sub main'file_end
338 {
339 }
340
341sub main'data_word
342 {
343 push(@out,"\t.long $_[0]\n");
344 }
345
346@pool_free=();
347@pool_taken=();
348$curr_num=0;
349$max=0;
350
351sub main'init_pool
352 {
353 local($args)=@_;
354 local($i);
355
356 @pool_free=();
357 for ($i=(14+(6-$args)); $i >= 0; $i--)
358 {
359 push(@pool_free,"r$i");
360 }
361 print STDERR "START :register pool:@pool_free\n";
362 $curr_num=$max=0;
363 }
364
365sub main'fin_pool
366 {
367 printf STDERR "END %2d:register pool:@pool_free\n",$max;
368 }
369
370sub main'GR
371 {
372 local($r)=@_;
373 local($i,@n,$_);
374
375 foreach (@pool_free)
376 {
377 if ($r ne $_)
378 { push(@n,$_); }
379 else
380 {
381 $curr_num++;
382 $max=$curr_num if ($curr_num > $max);
383 }
384 }
385 @pool_free=@n;
386print STDERR "GR:@pool_free\n" if $reg_alloc;
387 return(@_);
388 }
389
390sub main'NR
391 {
392 local($num)=@_;
393 local(@ret);
394
395 $num=1 if $num == 0;
396 ($#pool_free >= ($num-1)) || croak "out of registers: want $num, have @pool_free";
397 while ($num > 0)
398 {
399 push(@ret,pop @pool_free);
400 $curr_num++;
401 $max=$curr_num if ($curr_num > $max);
402 $num--
403 }
404 print STDERR "nr @ret\n" if $n_debug;
405print STDERR "NR:@pool_free\n" if $reg_alloc;
406 return(@ret);
407
408 }
409
410sub main'FR
411 {
412 local(@r)=@_;
413 local(@a,$v,$w);
414
415 print STDERR "fr @r\n" if $n_debug;
416# cluck "fr @r";
417 for $w (@pool_free)
418 {
419 foreach $v (@r)
420 {
421 croak "double register free of $v (@pool_free)" if $w eq $v;
422 }
423 }
424 foreach $v (@r)
425 {
426 croak "bad argument to FR" if ($v !~ /^r\d+$/);
427 if ($smear_regs)
428 { unshift(@pool_free,$v); }
429 else { push(@pool_free,$v); }
430 $curr_num--;
431 }
432print STDERR "FR:@pool_free\n" if $reg_alloc;
433 }
4341;
diff --git a/src/lib/libcrypto/perlasm/x86ms.pl b/src/lib/libcrypto/perlasm/x86ms.pl
new file mode 100644
index 0000000000..206452341d
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/x86ms.pl
@@ -0,0 +1,365 @@
1#!/usr/local/bin/perl
2
3package x86ms;
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); }
30sub main'external_label { push(@labels,@_); }
31
32sub main'LB
33 {
34 (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
35 return($lb{$_[0]});
36 }
37
38sub main'HB
39 {
40 (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
41 return($hb{$_[0]});
42 }
43
44sub main'BP
45 {
46 &get_mem("BYTE",@_);
47 }
48
49sub main'DWP
50 {
51 &get_mem("DWORD",@_);
52 }
53
54sub main'BC
55 {
56 return @_;
57 }
58
59sub main'DWC
60 {
61 return @_;
62 }
63
64sub main'stack_push
65 {
66 local($num)=@_;
67 $stack+=$num*4;
68 &main'sub("esp",$num*4);
69 }
70
71sub main'stack_pop
72 {
73 local($num)=@_;
74 $stack-=$num*4;
75 &main'add("esp",$num*4);
76 }
77
78sub get_mem
79 {
80 local($size,$addr,$reg1,$reg2,$idx)=@_;
81 local($t,$post);
82 local($ret)="$size PTR ";
83
84 $addr =~ s/^\s+//;
85 if ($addr =~ /^(.+)\+(.+)$/)
86 {
87 $reg2=&conv($1);
88 $addr="_$2";
89 }
90 elsif ($addr =~ /^[_a-zA-Z]/)
91 {
92 $addr="_$addr";
93 }
94
95 $reg1="$regs{$reg1}" if defined($regs{$reg1});
96 $reg2="$regs{$reg2}" if defined($regs{$reg2});
97 if (($addr ne "") && ($addr ne 0))
98 {
99 if ($addr !~ /^-/)
100 { $ret.=$addr; }
101 else { $post=$addr; }
102 }
103 if ($reg2 ne "")
104 {
105 $t="";
106 $t="*$idx" if ($idx != 0);
107 $reg1="+".$reg1 if ("$reg1$post" ne "");
108 $ret.="[$reg2$t$reg1$post]";
109 }
110 else
111 {
112 $ret.="[$reg1$post]"
113 }
114 return($ret);
115 }
116
117sub main'mov { &out2("mov",@_); }
118sub main'movb { &out2("mov",@_); }
119sub main'and { &out2("and",@_); }
120sub main'or { &out2("or",@_); }
121sub main'shl { &out2("shl",@_); }
122sub main'shr { &out2("shr",@_); }
123sub main'xor { &out2("xor",@_); }
124sub main'xorb { &out2("xor",@_); }
125sub main'add { &out2("add",@_); }
126sub main'adc { &out2("adc",@_); }
127sub main'sub { &out2("sub",@_); }
128sub main'rotl { &out2("rol",@_); }
129sub main'rotr { &out2("ror",@_); }
130sub main'exch { &out2("xchg",@_); }
131sub main'cmp { &out2("cmp",@_); }
132sub main'lea { &out2("lea",@_); }
133sub main'mul { &out1("mul",@_); }
134sub main'div { &out1("div",@_); }
135sub main'dec { &out1("dec",@_); }
136sub main'inc { &out1("inc",@_); }
137sub main'jmp { &out1("jmp",@_); }
138sub main'jmp_ptr { &out1p("jmp",@_); }
139sub main'je { &out1("je",@_); }
140sub main'jle { &out1("jle",@_); }
141sub main'jz { &out1("jz",@_); }
142sub main'jge { &out1("jge",@_); }
143sub main'jl { &out1("jl",@_); }
144sub main'jb { &out1("jb",@_); }
145sub main'jc { &out1("jc",@_); }
146sub main'jnc { &out1("jnc",@_); }
147sub main'jnz { &out1("jnz",@_); }
148sub main'jne { &out1("jne",@_); }
149sub main'jno { &out1("jno",@_); }
150sub main'push { &out1("push",@_); $stack+=4; }
151sub main'pop { &out1("pop",@_); $stack-=4; }
152sub main'bswap { &out1("bswap",@_); &using486(); }
153sub main'not { &out1("not",@_); }
154sub main'call { &out1("call",'_'.$_[0]); }
155sub main'ret { &out0("ret"); }
156sub main'nop { &out0("nop"); }
157
158sub out2
159 {
160 local($name,$p1,$p2)=@_;
161 local($l,$t);
162
163 push(@out,"\t$name\t");
164 $t=&conv($p1).",";
165 $l=length($t);
166 push(@out,$t);
167 $l=4-($l+9)/8;
168 push(@out,"\t" x $l);
169 push(@out,&conv($p2));
170 push(@out,"\n");
171 }
172
173sub out0
174 {
175 local($name)=@_;
176
177 push(@out,"\t$name\n");
178 }
179
180sub out1
181 {
182 local($name,$p1)=@_;
183 local($l,$t);
184
185 push(@out,"\t$name\t".&conv($p1)."\n");
186 }
187
188sub conv
189 {
190 local($p)=@_;
191
192 $p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
193 return $p;
194 }
195
196sub using486
197 {
198 return if $using486;
199 $using486++;
200 grep(s/\.386/\.486/,@out);
201 }
202
203sub main'file
204 {
205 local($file)=@_;
206
207 local($tmp)=<<"EOF";
208 TITLE $file.asm
209 .386
210.model FLAT
211EOF
212 push(@out,$tmp);
213 }
214
215sub main'function_begin
216 {
217 local($func,$extra)=@_;
218
219 push(@labels,$func);
220
221 local($tmp)=<<"EOF";
222_TEXT SEGMENT
223PUBLIC _$func
224$extra
225_$func PROC NEAR
226 push ebp
227 push ebx
228 push esi
229 push edi
230EOF
231 push(@out,$tmp);
232 $stack=20;
233 }
234
235sub main'function_begin_B
236 {
237 local($func,$extra)=@_;
238
239 local($tmp)=<<"EOF";
240_TEXT SEGMENT
241PUBLIC _$func
242$extra
243_$func PROC NEAR
244EOF
245 push(@out,$tmp);
246 $stack=4;
247 }
248
249sub main'function_end
250 {
251 local($func)=@_;
252
253 local($tmp)=<<"EOF";
254 pop edi
255 pop esi
256 pop ebx
257 pop ebp
258 ret
259_$func ENDP
260_TEXT ENDS
261EOF
262 push(@out,$tmp);
263 $stack=0;
264 %label=();
265 }
266
267sub main'function_end_B
268 {
269 local($func)=@_;
270
271 local($tmp)=<<"EOF";
272_$func ENDP
273_TEXT ENDS
274EOF
275 push(@out,$tmp);
276 $stack=0;
277 %label=();
278 }
279
280sub main'function_end_A
281 {
282 local($func)=@_;
283
284 local($tmp)=<<"EOF";
285 pop edi
286 pop esi
287 pop ebx
288 pop ebp
289 ret
290EOF
291 push(@out,$tmp);
292 }
293
294sub main'file_end
295 {
296 push(@out,"END\n");
297 }
298
299sub main'wparam
300 {
301 local($num)=@_;
302
303 return(&main'DWP($stack+$num*4,"esp","",0));
304 }
305
306sub main'swtmp
307 {
308 return(&main'DWP($_[0]*4,"esp","",0));
309 }
310
311# Should use swtmp, which is above esp. Linix can trash the stack above esp
312#sub main'wtmp
313# {
314# local($num)=@_;
315#
316# return(&main'DWP(-(($num+1)*4),"esp","",0));
317# }
318
319sub main'comment
320 {
321 foreach (@_)
322 {
323 push(@out,"\t; $_\n");
324 }
325 }
326
327sub main'label
328 {
329 if (!defined($label{$_[0]}))
330 {
331 $label{$_[0]}="\$${label}${_[0]}";
332 $label++;
333 }
334 return($label{$_[0]});
335 }
336
337sub main'set_label
338 {
339 if (!defined($label{$_[0]}))
340 {
341 $label{$_[0]}="${label}${_[0]}";
342 $label++;
343 }
344 if((defined $_[2]) && ($_[2] == 1))
345 {
346 push(@out,"$label{$_[0]}::\n");
347 }
348 else
349 {
350 push(@out,"$label{$_[0]}:\n");
351 }
352 }
353
354sub main'data_word
355 {
356 push(@out,"\tDD\t$_[0]\n");
357 }
358
359sub out1p
360 {
361 local($name,$p1)=@_;
362 local($l,$t);
363
364 push(@out,"\t$name\t ".&conv($p1)."\n");
365 }
diff --git a/src/lib/libcrypto/perlasm/x86nasm.pl b/src/lib/libcrypto/perlasm/x86nasm.pl
new file mode 100644
index 0000000000..519d8a5867
--- /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 use32\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 }
diff --git a/src/lib/libcrypto/perlasm/x86unix.pl b/src/lib/libcrypto/perlasm/x86unix.pl
new file mode 100644
index 0000000000..9ceabf0705
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/x86unix.pl
@@ -0,0 +1,544 @@
1#!/usr/local/bin/perl
2
3package x86unix;
4
5$label="L000";
6$const="";
7$constl=0;
8
9$align=($main'aout)?"4":"16";
10$under=($main'aout)?"_":"";
11$com_start=($main'sol)?"/":"#";
12
13sub main'asm_init_output { @out=(); }
14sub main'asm_get_output { return(@out); }
15sub main'get_labels { return(@labels); }
16sub main'external_label { push(@labels,@_); }
17
18if ($main'cpp)
19 {
20 $align="ALIGN";
21 $under="";
22 $com_start='/*';
23 $com_end='*/';
24 }
25
26%lb=( 'eax', '%al',
27 'ebx', '%bl',
28 'ecx', '%cl',
29 'edx', '%dl',
30 'ax', '%al',
31 'bx', '%bl',
32 'cx', '%cl',
33 'dx', '%dl',
34 );
35
36%hb=( 'eax', '%ah',
37 'ebx', '%bh',
38 'ecx', '%ch',
39 'edx', '%dh',
40 'ax', '%ah',
41 'bx', '%bh',
42 'cx', '%ch',
43 'dx', '%dh',
44 );
45
46%regs=( 'eax', '%eax',
47 'ebx', '%ebx',
48 'ecx', '%ecx',
49 'edx', '%edx',
50 'esi', '%esi',
51 'edi', '%edi',
52 'ebp', '%ebp',
53 'esp', '%esp',
54 );
55
56%reg_val=(
57 'eax', 0x00,
58 'ebx', 0x03,
59 'ecx', 0x01,
60 'edx', 0x02,
61 'esi', 0x06,
62 'edi', 0x07,
63 'ebp', 0x05,
64 'esp', 0x04,
65 );
66
67sub main'LB
68 {
69 (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
70 return($lb{$_[0]});
71 }
72
73sub main'HB
74 {
75 (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
76 return($hb{$_[0]});
77 }
78
79sub main'DWP
80 {
81 local($addr,$reg1,$reg2,$idx)=@_;
82
83 $ret="";
84 $addr =~ s/(^|[+ \t])([A-Za-z_]+[A-Za-z0-9_]+)($|[+ \t])/$1$under$2$3/;
85 $reg1="$regs{$reg1}" if defined($regs{$reg1});
86 $reg2="$regs{$reg2}" if defined($regs{$reg2});
87 $ret.=$addr if ($addr ne "") && ($addr ne 0);
88 if ($reg2 ne "")
89 {
90 if($idx ne "")
91 { $ret.="($reg1,$reg2,$idx)"; }
92 else
93 { $ret.="($reg1,$reg2)"; }
94 }
95 else
96 { $ret.="($reg1)" }
97 return($ret);
98 }
99
100sub main'BP
101 {
102 return(&main'DWP(@_));
103 }
104
105sub main'BC
106 {
107 return @_;
108 }
109
110sub main'DWC
111 {
112 return @_;
113 }
114
115#sub main'BP
116# {
117# local($addr,$reg1,$reg2,$idx)=@_;
118#
119# $ret="";
120#
121# $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/;
122# $reg1="$regs{$reg1}" if defined($regs{$reg1});
123# $reg2="$regs{$reg2}" if defined($regs{$reg2});
124# $ret.=$addr if ($addr ne "") && ($addr ne 0);
125# if ($reg2 ne "")
126# { $ret.="($reg1,$reg2,$idx)"; }
127# else
128# { $ret.="($reg1)" }
129# return($ret);
130# }
131
132sub main'mov { &out2("movl",@_); }
133sub main'movb { &out2("movb",@_); }
134sub main'and { &out2("andl",@_); }
135sub main'or { &out2("orl",@_); }
136sub main'shl { &out2("sall",@_); }
137sub main'shr { &out2("shrl",@_); }
138sub main'xor { &out2("xorl",@_); }
139sub main'xorb { &out2("xorb",@_); }
140sub main'add { &out2("addl",@_); }
141sub main'adc { &out2("adcl",@_); }
142sub main'sub { &out2("subl",@_); }
143sub main'rotl { &out2("roll",@_); }
144sub main'rotr { &out2("rorl",@_); }
145sub main'exch { &out2("xchg",@_); }
146sub main'cmp { &out2("cmpl",@_); }
147sub main'lea { &out2("leal",@_); }
148sub main'mul { &out1("mull",@_); }
149sub main'div { &out1("divl",@_); }
150sub main'jmp { &out1("jmp",@_); }
151sub main'jmp_ptr { &out1p("jmp",@_); }
152sub main'je { &out1("je",@_); }
153sub main'jle { &out1("jle",@_); }
154sub main'jne { &out1("jne",@_); }
155sub main'jnz { &out1("jnz",@_); }
156sub main'jz { &out1("jz",@_); }
157sub main'jge { &out1("jge",@_); }
158sub main'jl { &out1("jl",@_); }
159sub main'jb { &out1("jb",@_); }
160sub main'jc { &out1("jc",@_); }
161sub main'jnc { &out1("jnc",@_); }
162sub main'jno { &out1("jno",@_); }
163sub main'dec { &out1("decl",@_); }
164sub main'inc { &out1("incl",@_); }
165sub main'push { &out1("pushl",@_); $stack+=4; }
166sub main'pop { &out1("popl",@_); $stack-=4; }
167sub main'pushf { &out0("pushf"); $stack+=4; }
168sub main'popf { &out0("popf"); $stack-=4; }
169sub main'not { &out1("notl",@_); }
170sub main'call { &out1("call",$under.$_[0]); }
171sub main'ret { &out0("ret"); }
172sub main'nop { &out0("nop"); }
173
174# The bswapl instruction is new for the 486. Emulate if i386.
175sub main'bswap
176 {
177 if ($main'i386)
178 {
179 &main'comment("bswapl @_");
180 &main'exch(main'HB(@_),main'LB(@_));
181 &main'rotr(@_,16);
182 &main'exch(main'HB(@_),main'LB(@_));
183 }
184 else
185 {
186 &out1("bswapl",@_);
187 }
188 }
189
190sub out2
191 {
192 local($name,$p1,$p2)=@_;
193 local($l,$ll,$t);
194 local(%special)=( "roll",0xD1C0,"rorl",0xD1C8,
195 "rcll",0xD1D0,"rcrl",0xD1D8,
196 "shll",0xD1E0,"shrl",0xD1E8,
197 "sarl",0xD1F8);
198
199 if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1))
200 {
201 $op=$special{$name}|$reg_val{$p1};
202 $tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
203 $tmp2=sprintf(".byte %d\t",$op &0xff);
204 push(@out,$tmp1);
205 push(@out,$tmp2);
206
207 $p2=&conv($p2);
208 $p1=&conv($p1);
209 &main'comment("$name $p2 $p1");
210 return;
211 }
212
213 push(@out,"\t$name\t");
214 $t=&conv($p2).",";
215 $l=length($t);
216 push(@out,$t);
217 $ll=4-($l+9)/8;
218 $tmp1=sprintf("\t" x $ll);
219 push(@out,$tmp1);
220 push(@out,&conv($p1)."\n");
221 }
222
223sub out1
224 {
225 local($name,$p1)=@_;
226 local($l,$t);
227 local(%special)=("bswapl",0x0FC8);
228
229 if ((defined($special{$name})) && defined($regs{$p1}))
230 {
231 $op=$special{$name}|$reg_val{$p1};
232 $tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
233 $tmp2=sprintf(".byte %d\t",$op &0xff);
234 push(@out,$tmp1);
235 push(@out,$tmp2);
236
237 $p2=&conv($p2);
238 $p1=&conv($p1);
239 &main'comment("$name $p2 $p1");
240 return;
241 }
242
243 push(@out,"\t$name\t".&conv($p1)."\n");
244 }
245
246sub out1p
247 {
248 local($name,$p1)=@_;
249 local($l,$t);
250
251 push(@out,"\t$name\t*".&conv($p1)."\n");
252 }
253
254sub out0
255 {
256 push(@out,"\t$_[0]\n");
257 }
258
259sub conv
260 {
261 local($p)=@_;
262
263# $p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
264
265 $p=$regs{$p} if (defined($regs{$p}));
266
267 $p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/;
268 $p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/;
269 return $p;
270 }
271
272sub main'file
273 {
274 local($file)=@_;
275
276 local($tmp)=<<"EOF";
277 .file "$file.s"
278 .version "01.01"
279gcc2_compiled.:
280EOF
281 push(@out,$tmp);
282 }
283
284sub main'function_begin
285 {
286 local($func)=@_;
287
288 &main'external_label($func);
289 $func=$under.$func;
290
291 local($tmp)=<<"EOF";
292.text
293 .align $align
294.globl $func
295EOF
296 push(@out,$tmp);
297 if ($main'cpp)
298 { $tmp=push(@out,"\tTYPE($func,\@function)\n"); }
299 elsif ($main'gaswin)
300 { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
301 else { $tmp=push(@out,"\t.type\t$func,\@function\n"); }
302 push(@out,"$func:\n");
303 $tmp=<<"EOF";
304 pushl %ebp
305 pushl %ebx
306 pushl %esi
307 pushl %edi
308
309EOF
310 push(@out,$tmp);
311 $stack=20;
312 }
313
314sub main'function_begin_B
315 {
316 local($func,$extra)=@_;
317
318 &main'external_label($func);
319 $func=$under.$func;
320
321 local($tmp)=<<"EOF";
322.text
323 .align $align
324.globl $func
325EOF
326 push(@out,$tmp);
327 if ($main'cpp)
328 { push(@out,"\tTYPE($func,\@function)\n"); }
329 elsif ($main'gaswin)
330 { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
331 else { push(@out,"\t.type $func,\@function\n"); }
332 push(@out,"$func:\n");
333 $stack=4;
334 }
335
336sub main'function_end
337 {
338 local($func)=@_;
339
340 $func=$under.$func;
341
342 local($tmp)=<<"EOF";
343 popl %edi
344 popl %esi
345 popl %ebx
346 popl %ebp
347 ret
348.${func}_end:
349EOF
350 push(@out,$tmp);
351
352 if ($main'cpp)
353 { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); }
354 elsif ($main'gaswin)
355 { $tmp=push(@out,"\t.align 4\n"); }
356 else { push(@out,"\t.size\t$func,.${func}_end-$func\n"); }
357 push(@out,".ident \"$func\"\n");
358 $stack=0;
359 %label=();
360 }
361
362sub main'function_end_A
363 {
364 local($func)=@_;
365
366 local($tmp)=<<"EOF";
367 popl %edi
368 popl %esi
369 popl %ebx
370 popl %ebp
371 ret
372EOF
373 push(@out,$tmp);
374 }
375
376sub main'function_end_B
377 {
378 local($func)=@_;
379
380 $func=$under.$func;
381
382 push(@out,".L_${func}_end:\n");
383 if ($main'cpp)
384 { push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); }
385 elsif ($main'gaswin)
386 { push(@out,"\t.align 4\n"); }
387 else { push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); }
388 push(@out,".ident \"desasm.pl\"\n");
389 $stack=0;
390 %label=();
391 }
392
393sub main'wparam
394 {
395 local($num)=@_;
396
397 return(&main'DWP($stack+$num*4,"esp","",0));
398 }
399
400sub main'stack_push
401 {
402 local($num)=@_;
403 $stack+=$num*4;
404 &main'sub("esp",$num*4);
405 }
406
407sub main'stack_pop
408 {
409 local($num)=@_;
410 $stack-=$num*4;
411 &main'add("esp",$num*4);
412 }
413
414sub main'swtmp
415 {
416 return(&main'DWP($_[0]*4,"esp","",0));
417 }
418
419# Should use swtmp, which is above esp. Linix can trash the stack above esp
420#sub main'wtmp
421# {
422# local($num)=@_;
423#
424# return(&main'DWP(-($num+1)*4,"esp","",0));
425# }
426
427sub main'comment
428 {
429 foreach (@_)
430 {
431 if (/^\s*$/)
432 { push(@out,"\n"); }
433 else
434 { push(@out,"\t$com_start $_ $com_end\n"); }
435 }
436 }
437
438sub main'label
439 {
440 if (!defined($label{$_[0]}))
441 {
442 $label{$_[0]}=".${label}${_[0]}";
443 $label++;
444 }
445 return($label{$_[0]});
446 }
447
448sub main'set_label
449 {
450 if (!defined($label{$_[0]}))
451 {
452 $label{$_[0]}=".${label}${_[0]}";
453 $label++;
454 }
455 push(@out,".align $align\n") if ($_[1] != 0);
456 push(@out,"$label{$_[0]}:\n");
457 }
458
459sub main'file_end
460 {
461 if ($const ne "")
462 {
463 push(@out,".section .rodata\n");
464 push(@out,$const);
465 $const="";
466 }
467 }
468
469sub main'data_word
470 {
471 push(@out,"\t.long $_[0]\n");
472 }
473
474# debug output functions: puts, putx, printf
475
476sub main'puts
477 {
478 &pushvars();
479 &main'push('$Lstring' . ++$constl);
480 &main'call('puts');
481 $stack-=4;
482 &main'add("esp",4);
483 &popvars();
484
485 $const .= "Lstring$constl:\n\t.string \"@_[0]\"\n";
486 }
487
488sub main'putx
489 {
490 &pushvars();
491 &main'push($_[0]);
492 &main'push('$Lstring' . ++$constl);
493 &main'call('printf');
494 &main'add("esp",8);
495 $stack-=8;
496 &popvars();
497
498 $const .= "Lstring$constl:\n\t.string \"\%X\"\n";
499 }
500
501sub main'printf
502 {
503 $ostack = $stack;
504 &pushvars();
505 for ($i = @_ - 1; $i >= 0; $i--)
506 {
507 if ($i == 0) # change this to support %s format strings
508 {
509 &main'push('$Lstring' . ++$constl);
510 $const .= "Lstring$constl:\n\t.string \"@_[$i]\"\n";
511 }
512 else
513 {
514 if ($_[$i] =~ /([0-9]*)\(%esp\)/)
515 {
516 &main'push(($1 + $stack - $ostack) . '(%esp)');
517 }
518 else
519 {
520 &main'push($_[$i]);
521 }
522 }
523 }
524 &main'call('printf');
525 $stack-=4*@_;
526 &main'add("esp",4*@_);
527 &popvars();
528 }
529
530sub pushvars
531 {
532 &main'pushf();
533 &main'push("edx");
534 &main'push("ecx");
535 &main'push("eax");
536 }
537
538sub popvars
539 {
540 &main'pop("eax");
541 &main'pop("ecx");
542 &main'pop("edx");
543 &main'popf();
544 }