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/x86asm.pl10
-rw-r--r--src/lib/libcrypto/perlasm/x86ms.pl379
-rw-r--r--src/lib/libcrypto/perlasm/x86nasm.pl356
-rw-r--r--src/lib/libcrypto/perlasm/x86unix.pl619
5 files changed, 1795 insertions, 3 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/x86asm.pl b/src/lib/libcrypto/perlasm/x86asm.pl
index bef2667079..7c675e3ced 100644
--- a/src/lib/libcrypto/perlasm/x86asm.pl
+++ b/src/lib/libcrypto/perlasm/x86asm.pl
@@ -18,9 +18,13 @@ sub main'asm_init
18 ($type,$fn,$i386)=@_; 18 ($type,$fn,$i386)=@_;
19 $filename=$fn; 19 $filename=$fn;
20 20
21 $elf=$cpp=$sol=$aout=$win32=$gaswin=0; 21 $elf=$cpp=$sol=$aout=$win32=$gaswin=$openbsd=0;
22 if ( ($type eq "elf")) 22 if ( ($type eq "elf"))
23 { $elf=1; require "x86unix.pl"; } 23 { $elf=1; require "x86unix.pl"; }
24 elsif ( ($type eq "openbsd-elf"))
25 { $openbsd=$elf=1; require "x86unix.pl"; }
26 elsif ( ($type eq "openbsd-a.out"))
27 { $openbsd=1; require "x86unix.pl"; }
24 elsif ( ($type eq "a.out")) 28 elsif ( ($type eq "a.out"))
25 { $aout=1; require "x86unix.pl"; } 29 { $aout=1; require "x86unix.pl"; }
26 elsif ( ($type eq "gaswin")) 30 elsif ( ($type eq "gaswin"))
@@ -43,6 +47,8 @@ Pick one target type from
43 cpp - format so x86unix.cpp can be used 47 cpp - format so x86unix.cpp can be used
44 win32 - Windows 95/Windows NT 48 win32 - Windows 95/Windows NT
45 win32n - Windows 95/Windows NT NASM format 49 win32n - Windows 95/Windows NT NASM format
50 openbsd-elf - OpenBSD elf
51 openbsd-a.out - OpenBSD a.out
46EOF 52EOF
47 exit(1); 53 exit(1);
48 } 54 }
@@ -124,6 +130,4 @@ BSDI - a.out with a very primative version of as.
124EOF 130EOF
125 } 131 }
126 132
127sub main'align() {} # swallow align statements in 0.9.7 context
128
1291; 1331;
diff --git a/src/lib/libcrypto/perlasm/x86ms.pl b/src/lib/libcrypto/perlasm/x86ms.pl
new file mode 100644
index 0000000000..fbb4afb9bd
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/x86ms.pl
@@ -0,0 +1,379 @@
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 if ($addr =~ /^.+\-.+$/) { $addr="($addr)"; }
96
97 $reg1="$regs{$reg1}" if defined($regs{$reg1});
98 $reg2="$regs{$reg2}" if defined($regs{$reg2});
99 if (($addr ne "") && ($addr ne 0))
100 {
101 if ($addr !~ /^-/)
102 { $ret.=$addr; }
103 else { $post=$addr; }
104 }
105 if ($reg2 ne "")
106 {
107 $t="";
108 $t="*$idx" if ($idx != 0);
109 $reg1="+".$reg1 if ("$reg1$post" ne "");
110 $ret.="[$reg2$t$reg1$post]";
111 }
112 else
113 {
114 $ret.="[$reg1$post]"
115 }
116 $ret =~ s/\[\]//; # in case $addr was the only argument
117 return($ret);
118 }
119
120sub main'mov { &out2("mov",@_); }
121sub main'movb { &out2("mov",@_); }
122sub main'and { &out2("and",@_); }
123sub main'or { &out2("or",@_); }
124sub main'shl { &out2("shl",@_); }
125sub main'shr { &out2("shr",@_); }
126sub main'xor { &out2("xor",@_); }
127sub main'xorb { &out2("xor",@_); }
128sub main'add { &out2("add",@_); }
129sub main'adc { &out2("adc",@_); }
130sub main'sub { &out2("sub",@_); }
131sub main'rotl { &out2("rol",@_); }
132sub main'rotr { &out2("ror",@_); }
133sub main'exch { &out2("xchg",@_); }
134sub main'cmp { &out2("cmp",@_); }
135sub main'lea { &out2("lea",@_); }
136sub main'mul { &out1("mul",@_); }
137sub main'div { &out1("div",@_); }
138sub main'dec { &out1("dec",@_); }
139sub main'inc { &out1("inc",@_); }
140sub main'jmp { &out1("jmp",@_); }
141sub main'jmp_ptr { &out1p("jmp",@_); }
142sub main'je { &out1("je",@_); }
143sub main'jle { &out1("jle",@_); }
144sub main'jz { &out1("jz",@_); }
145sub main'jge { &out1("jge",@_); }
146sub main'jl { &out1("jl",@_); }
147sub main'ja { &out1("ja",@_); }
148sub main'jae { &out1("jae",@_); }
149sub main'jb { &out1("jb",@_); }
150sub main'jbe { &out1("jbe",@_); }
151sub main'jc { &out1("jc",@_); }
152sub main'jnc { &out1("jnc",@_); }
153sub main'jnz { &out1("jnz",@_); }
154sub main'jne { &out1("jne",@_); }
155sub main'jno { &out1("jno",@_); }
156sub main'push { &out1("push",@_); $stack+=4; }
157sub main'pop { &out1("pop",@_); $stack-=4; }
158sub main'bswap { &out1("bswap",@_); &using486(); }
159sub main'not { &out1("not",@_); }
160sub main'call { &out1("call",($_[0]=~/^\$L/?'':'_').$_[0]); }
161sub main'ret { &out0("ret"); }
162sub main'nop { &out0("nop"); }
163
164sub out2
165 {
166 local($name,$p1,$p2)=@_;
167 local($l,$t);
168
169 push(@out,"\t$name\t");
170 $t=&conv($p1).",";
171 $l=length($t);
172 push(@out,$t);
173 $l=4-($l+9)/8;
174 push(@out,"\t" x $l);
175 push(@out,&conv($p2));
176 push(@out,"\n");
177 }
178
179sub out0
180 {
181 local($name)=@_;
182
183 push(@out,"\t$name\n");
184 }
185
186sub out1
187 {
188 local($name,$p1)=@_;
189 local($l,$t);
190
191 push(@out,"\t$name\t".&conv($p1)."\n");
192 }
193
194sub conv
195 {
196 local($p)=@_;
197
198 $p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
199 return $p;
200 }
201
202sub using486
203 {
204 return if $using486;
205 $using486++;
206 grep(s/\.386/\.486/,@out);
207 }
208
209sub main'file
210 {
211 local($file)=@_;
212
213 local($tmp)=<<"EOF";
214 TITLE $file.asm
215 .386
216.model FLAT
217EOF
218 push(@out,$tmp);
219 }
220
221sub main'function_begin
222 {
223 local($func,$extra)=@_;
224
225 push(@labels,$func);
226
227 local($tmp)=<<"EOF";
228_TEXT SEGMENT
229PUBLIC _$func
230$extra
231_$func PROC NEAR
232 push ebp
233 push ebx
234 push esi
235 push edi
236EOF
237 push(@out,$tmp);
238 $stack=20;
239 }
240
241sub main'function_begin_B
242 {
243 local($func,$extra)=@_;
244
245 local($tmp)=<<"EOF";
246_TEXT SEGMENT
247PUBLIC _$func
248$extra
249_$func PROC NEAR
250EOF
251 push(@out,$tmp);
252 $stack=4;
253 }
254
255sub main'function_end
256 {
257 local($func)=@_;
258
259 local($tmp)=<<"EOF";
260 pop edi
261 pop esi
262 pop ebx
263 pop ebp
264 ret
265_$func ENDP
266_TEXT ENDS
267EOF
268 push(@out,$tmp);
269 $stack=0;
270 %label=();
271 }
272
273sub main'function_end_B
274 {
275 local($func)=@_;
276
277 local($tmp)=<<"EOF";
278_$func ENDP
279_TEXT ENDS
280EOF
281 push(@out,$tmp);
282 $stack=0;
283 %label=();
284 }
285
286sub main'function_end_A
287 {
288 local($func)=@_;
289
290 local($tmp)=<<"EOF";
291 pop edi
292 pop esi
293 pop ebx
294 pop ebp
295 ret
296EOF
297 push(@out,$tmp);
298 }
299
300sub main'file_end
301 {
302 push(@out,"END\n");
303 }
304
305sub main'wparam
306 {
307 local($num)=@_;
308
309 return(&main'DWP($stack+$num*4,"esp","",0));
310 }
311
312sub main'swtmp
313 {
314 return(&main'DWP($_[0]*4,"esp","",0));
315 }
316
317# Should use swtmp, which is above esp. Linix can trash the stack above esp
318#sub main'wtmp
319# {
320# local($num)=@_;
321#
322# return(&main'DWP(-(($num+1)*4),"esp","",0));
323# }
324
325sub main'comment
326 {
327 foreach (@_)
328 {
329 push(@out,"\t; $_\n");
330 }
331 }
332
333sub main'label
334 {
335 if (!defined($label{$_[0]}))
336 {
337 $label{$_[0]}="\$${label}${_[0]}";
338 $label++;
339 }
340 return($label{$_[0]});
341 }
342
343sub main'set_label
344 {
345 if (!defined($label{$_[0]}))
346 {
347 $label{$_[0]}="\$${label}${_[0]}";
348 $label++;
349 }
350 if((defined $_[2]) && ($_[2] == 1))
351 {
352 push(@out,"$label{$_[0]}::\n");
353 }
354 else
355 {
356 push(@out,"$label{$_[0]}:\n");
357 }
358 }
359
360sub main'data_word
361 {
362 push(@out,"\tDD\t$_[0]\n");
363 }
364
365sub out1p
366 {
367 local($name,$p1)=@_;
368 local($l,$t);
369
370 push(@out,"\t$name\t ".&conv($p1)."\n");
371 }
372
373sub main'picmeup
374 {
375 local($dst,$sym)=@_;
376 &main'lea($dst,&main'DWP($sym));
377 }
378
379sub main'blindpop { &out1("pop",@_); }
diff --git a/src/lib/libcrypto/perlasm/x86nasm.pl b/src/lib/libcrypto/perlasm/x86nasm.pl
new file mode 100644
index 0000000000..30346af4ea
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/x86nasm.pl
@@ -0,0 +1,356 @@
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 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"); }
172
173sub out2
174 {
175 my($name,$p1,$p2)=@_;
176 my($l,$t);
177
178 push(@out,"\t$name\t");
179 $t=&conv($p1).",";
180 $l=length($t);
181 push(@out,$t);
182 $l=4-($l+9)/8;
183 push(@out,"\t" x $l);
184 push(@out,&conv($p2));
185 push(@out,"\n");
186 }
187
188sub out0
189 {
190 my($name)=@_;
191
192 push(@out,"\t$name\n");
193 }
194
195sub out1
196 {
197 my($name,$p1)=@_;
198 my($l,$t);
199 push(@out,"\t$name\t".&conv($p1)."\n");
200 }
201
202sub conv
203 {
204 my($p)=@_;
205 $p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
206 return $p;
207 }
208
209sub using486
210 {
211 return if $using486;
212 $using486++;
213 grep(s/\.386/\.486/,@out);
214 }
215
216sub main'file
217 {
218 push(@out, "segment .text use32\n");
219 }
220
221sub main'function_begin
222 {
223 my($func,$extra)=@_;
224
225 push(@labels,$func);
226 my($tmp)=<<"EOF";
227global _$func
228_$func:
229 push ebp
230 push ebx
231 push esi
232 push edi
233EOF
234 push(@out,$tmp);
235 $stack=20;
236 }
237
238sub main'function_begin_B
239 {
240 my($func,$extra)=@_;
241 my($tmp)=<<"EOF";
242global _$func
243_$func:
244EOF
245 push(@out,$tmp);
246 $stack=4;
247 }
248
249sub main'function_end
250 {
251 my($func)=@_;
252
253 my($tmp)=<<"EOF";
254 pop edi
255 pop esi
256 pop ebx
257 pop ebp
258 ret
259EOF
260 push(@out,$tmp);
261 $stack=0;
262 %label=();
263 }
264
265sub main'function_end_B
266 {
267 $stack=0;
268 %label=();
269 }
270
271sub main'function_end_A
272 {
273 my($func)=@_;
274
275 my($tmp)=<<"EOF";
276 pop edi
277 pop esi
278 pop ebx
279 pop ebp
280 ret
281EOF
282 push(@out,$tmp);
283 }
284
285sub main'file_end
286 {
287 }
288
289sub main'wparam
290 {
291 my($num)=@_;
292
293 return(&main'DWP($stack+$num*4,"esp","",0));
294 }
295
296sub main'swtmp
297 {
298 return(&main'DWP($_[0]*4,"esp","",0));
299 }
300
301# Should use swtmp, which is above esp. Linix can trash the stack above esp
302#sub main'wtmp
303# {
304# my($num)=@_;
305#
306# return(&main'DWP(-(($num+1)*4),"esp","",0));
307# }
308
309sub main'comment
310 {
311 foreach (@_)
312 {
313 push(@out,"\t; $_\n");
314 }
315 }
316
317sub main'label
318 {
319 if (!defined($label{$_[0]}))
320 {
321 $label{$_[0]}="\$${label}${_[0]}";
322 $label++;
323 }
324 return($label{$_[0]});
325 }
326
327sub main'set_label
328 {
329 if (!defined($label{$_[0]}))
330 {
331 $label{$_[0]}="\$${label}${_[0]}";
332 $label++;
333 }
334 push(@out,"$label{$_[0]}:\n");
335 }
336
337sub main'data_word
338 {
339 push(@out,"\tDD\t$_[0]\n");
340 }
341
342sub out1p
343 {
344 my($name,$p1)=@_;
345 my($l,$t);
346
347 push(@out,"\t$name\t ".&conv($p1)."\n");
348 }
349
350sub main'picmeup
351 {
352 local($dst,$sym)=@_;
353 &main'lea($dst,&main'DWP($sym));
354 }
355
356sub main'blindpop { &out1("pop",@_); }
diff --git a/src/lib/libcrypto/perlasm/x86unix.pl b/src/lib/libcrypto/perlasm/x86unix.pl
new file mode 100644
index 0000000000..53ad5f4927
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/x86unix.pl
@@ -0,0 +1,619 @@
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'openbsd)
19 {
20 $com_start='/*';
21 $com_end='*/';
22 }
23
24if ($main'cpp)
25 {
26 $align="ALIGN";
27 $under="";
28 $com_start='/*';
29 $com_end='*/';
30 }
31
32%lb=( 'eax', '%al',
33 'ebx', '%bl',
34 'ecx', '%cl',
35 'edx', '%dl',
36 'ax', '%al',
37 'bx', '%bl',
38 'cx', '%cl',
39 'dx', '%dl',
40 );
41
42%hb=( 'eax', '%ah',
43 'ebx', '%bh',
44 'ecx', '%ch',
45 'edx', '%dh',
46 'ax', '%ah',
47 'bx', '%bh',
48 'cx', '%ch',
49 'dx', '%dh',
50 );
51
52%regs=( 'eax', '%eax',
53 'ebx', '%ebx',
54 'ecx', '%ecx',
55 'edx', '%edx',
56 'esi', '%esi',
57 'edi', '%edi',
58 'ebp', '%ebp',
59 'esp', '%esp',
60 );
61
62%reg_val=(
63 'eax', 0x00,
64 'ebx', 0x03,
65 'ecx', 0x01,
66 'edx', 0x02,
67 'esi', 0x06,
68 'edi', 0x07,
69 'ebp', 0x05,
70 'esp', 0x04,
71 );
72
73sub main'LB
74 {
75 (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
76 return($lb{$_[0]});
77 }
78
79sub main'HB
80 {
81 (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
82 return($hb{$_[0]});
83 }
84
85sub main'DWP
86 {
87 local($addr,$reg1,$reg2,$idx)=@_;
88
89 $ret="";
90 $addr =~ s/(^|[+ \t])([A-Za-z_]+[A-Za-z0-9_]+)($|[+ \t])/$1$under$2$3/;
91 $reg1="$regs{$reg1}" if defined($regs{$reg1});
92 $reg2="$regs{$reg2}" if defined($regs{$reg2});
93 $ret.=$addr if ($addr ne "") && ($addr ne 0);
94 if ($reg2 ne "")
95 {
96 if($idx ne "" && $idx != 0)
97 { $ret.="($reg1,$reg2,$idx)"; }
98 else
99 { $ret.="($reg1,$reg2)"; }
100 }
101 elsif ($reg1 ne "")
102 { $ret.="($reg1)" }
103 return($ret);
104 }
105
106sub main'BP
107 {
108 return(&main'DWP(@_));
109 }
110
111sub main'BC
112 {
113 return @_;
114 }
115
116sub main'DWC
117 {
118 return @_;
119 }
120
121#sub main'BP
122# {
123# local($addr,$reg1,$reg2,$idx)=@_;
124#
125# $ret="";
126#
127# $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/;
128# $reg1="$regs{$reg1}" if defined($regs{$reg1});
129# $reg2="$regs{$reg2}" if defined($regs{$reg2});
130# $ret.=$addr if ($addr ne "") && ($addr ne 0);
131# if ($reg2 ne "")
132# { $ret.="($reg1,$reg2,$idx)"; }
133# else
134# { $ret.="($reg1)" }
135# return($ret);
136# }
137
138sub main'mov { &out2("movl",@_); }
139sub main'movb { &out2("movb",@_); }
140sub main'and { &out2("andl",@_); }
141sub main'or { &out2("orl",@_); }
142sub main'shl { &out2("sall",@_); }
143sub main'shr { &out2("shrl",@_); }
144sub main'xor { &out2("xorl",@_); }
145sub main'xorb { &out2("xorb",@_); }
146sub main'add { &out2("addl",@_); }
147sub main'adc { &out2("adcl",@_); }
148sub main'sub { &out2("subl",@_); }
149sub main'rotl { &out2("roll",@_); }
150sub main'rotr { &out2("rorl",@_); }
151sub main'exch { &out2("xchg",@_); }
152sub main'cmp { &out2("cmpl",@_); }
153sub main'lea { &out2("leal",@_); }
154sub main'mul { &out1("mull",@_); }
155sub main'div { &out1("divl",@_); }
156sub main'jmp { &out1("jmp",@_); }
157sub main'jmp_ptr { &out1p("jmp",@_); }
158sub main'je { &out1("je",@_); }
159sub main'jle { &out1("jle",@_); }
160sub main'jne { &out1("jne",@_); }
161sub main'jnz { &out1("jnz",@_); }
162sub main'jz { &out1("jz",@_); }
163sub main'jge { &out1("jge",@_); }
164sub main'jl { &out1("jl",@_); }
165sub main'ja { &out1("ja",@_); }
166sub main'jae { &out1("jae",@_); }
167sub main'jb { &out1("jb",@_); }
168sub main'jbe { &out1("jbe",@_); }
169sub main'jc { &out1("jc",@_); }
170sub main'jnc { &out1("jnc",@_); }
171sub main'jno { &out1("jno",@_); }
172sub main'dec { &out1("decl",@_); }
173sub main'inc { &out1("incl",@_); }
174sub main'push { &out1("pushl",@_); $stack+=4; }
175sub main'pop { &out1("popl",@_); $stack-=4; }
176sub main'pushf { &out0("pushf"); $stack+=4; }
177sub main'popf { &out0("popf"); $stack-=4; }
178sub main'not { &out1("notl",@_); }
179sub main'call { &out1("call",($_[0]=~/^\.L/?'':$under).$_[0]); }
180sub main'ret { &out0("ret"); }
181sub main'nop { &out0("nop"); }
182
183# The bswapl instruction is new for the 486. Emulate if i386.
184sub main'bswap
185 {
186 if ($main'i386)
187 {
188 &main'comment("bswapl @_");
189 &main'exch(main'HB(@_),main'LB(@_));
190 &main'rotr(@_,16);
191 &main'exch(main'HB(@_),main'LB(@_));
192 }
193 else
194 {
195 &out1("bswapl",@_);
196 }
197 }
198
199sub out2
200 {
201 local($name,$p1,$p2)=@_;
202 local($l,$ll,$t);
203 local(%special)=( "roll",0xD1C0,"rorl",0xD1C8,
204 "rcll",0xD1D0,"rcrl",0xD1D8,
205 "shll",0xD1E0,"shrl",0xD1E8,
206 "sarl",0xD1F8);
207
208 if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1))
209 {
210 $op=$special{$name}|$reg_val{$p1};
211 $tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
212 $tmp2=sprintf(".byte %d\t",$op &0xff);
213 push(@out,$tmp1);
214 push(@out,$tmp2);
215
216 $p2=&conv($p2);
217 $p1=&conv($p1);
218 &main'comment("$name $p2 $p1");
219 return;
220 }
221
222 push(@out,"\t$name\t");
223 $t=&conv($p2).",";
224 $l=length($t);
225 push(@out,$t);
226 $ll=4-($l+9)/8;
227 $tmp1=sprintf("\t" x $ll);
228 push(@out,$tmp1);
229 push(@out,&conv($p1)."\n");
230 }
231
232sub out1
233 {
234 local($name,$p1)=@_;
235 local($l,$t);
236 local(%special)=("bswapl",0x0FC8);
237
238 if ((defined($special{$name})) && defined($regs{$p1}))
239 {
240 $op=$special{$name}|$reg_val{$p1};
241 $tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
242 $tmp2=sprintf(".byte %d\t",$op &0xff);
243 push(@out,$tmp1);
244 push(@out,$tmp2);
245
246 $p2=&conv($p2);
247 $p1=&conv($p1);
248 &main'comment("$name $p2 $p1");
249 return;
250 }
251
252 push(@out,"\t$name\t".&conv($p1)."\n");
253 }
254
255sub out1p
256 {
257 local($name,$p1)=@_;
258 local($l,$t);
259
260 push(@out,"\t$name\t*".&conv($p1)."\n");
261 }
262
263sub out0
264 {
265 push(@out,"\t$_[0]\n");
266 }
267
268sub conv
269 {
270 local($p)=@_;
271
272# $p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
273
274 $p=$regs{$p} if (defined($regs{$p}));
275
276 $p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/;
277 $p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/;
278 return $p;
279 }
280
281sub main'file
282 {
283 local($file)=@_;
284
285 if ($main'openbsd)
286 { push(@out,"#include <machine/asm.h>\n"); return; }
287
288 local($tmp)=<<"EOF";
289 .file "$file.s"
290 .version "01.01"
291gcc2_compiled.:
292EOF
293 push(@out,$tmp);
294 }
295
296sub main'function_begin
297 {
298 local($func)=@_;
299
300 &main'external_label($func);
301 $func=$under.$func;
302
303 if ($main'openbsd)
304 { push (@out, "\nENTRY($func)\n"); goto skip; }
305
306 local($tmp)=<<"EOF";
307.text
308 .align $align
309.globl $func
310EOF
311 push(@out,$tmp);
312 if ($main'cpp)
313 { $tmp=push(@out,"\tTYPE($func,\@function)\n"); }
314 elsif ($main'gaswin)
315 { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
316 else { $tmp=push(@out,"\t.type\t$func,\@function\n"); }
317 push(@out,"$func:\n");
318skip:
319 $tmp=<<"EOF";
320 pushl %ebp
321 pushl %ebx
322 pushl %esi
323 pushl %edi
324
325EOF
326 push(@out,$tmp);
327 $stack=20;
328 }
329
330sub main'function_begin_B
331 {
332 local($func,$extra)=@_;
333
334 &main'external_label($func);
335 $func=$under.$func;
336
337 if ($main'openbsd)
338 { push(@out, "\nENTRY($func)\n"); goto skip; }
339
340 local($tmp)=<<"EOF";
341.text
342 .align $align
343.globl $func
344EOF
345 push(@out,$tmp);
346 if ($main'cpp)
347 { push(@out,"\tTYPE($func,\@function)\n"); }
348 elsif ($main'gaswin)
349 { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
350 else { push(@out,"\t.type $func,\@function\n"); }
351 push(@out,"$func:\n");
352skip:
353 $stack=4;
354 }
355
356sub main'function_end
357 {
358 local($func)=@_;
359
360 $func=$under.$func;
361
362 local($tmp)=<<"EOF";
363 popl %edi
364 popl %esi
365 popl %ebx
366 popl %ebp
367 ret
368.L_${func}_end:
369EOF
370 push(@out,$tmp);
371
372 if ($main'cpp)
373 { push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); }
374 elsif ($main'gaswin)
375 { $tmp=push(@out,"\t.align 4\n"); }
376 else { push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); }
377 push(@out,".ident \"$func\"\n");
378 $stack=0;
379 %label=();
380 }
381
382sub main'function_end_A
383 {
384 local($func)=@_;
385
386 local($tmp)=<<"EOF";
387 popl %edi
388 popl %esi
389 popl %ebx
390 popl %ebp
391 ret
392EOF
393 push(@out,$tmp);
394 }
395
396sub main'function_end_B
397 {
398 local($func)=@_;
399
400 $func=$under.$func;
401
402 push(@out,".L_${func}_end:\n");
403 if ($main'cpp)
404 { push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); }
405 elsif ($main'gaswin)
406 { push(@out,"\t.align 4\n"); }
407 else { push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); }
408 push(@out,".ident \"desasm.pl\"\n");
409 $stack=0;
410 %label=();
411 }
412
413sub main'wparam
414 {
415 local($num)=@_;
416
417 return(&main'DWP($stack+$num*4,"esp","",0));
418 }
419
420sub main'stack_push
421 {
422 local($num)=@_;
423 $stack+=$num*4;
424 &main'sub("esp",$num*4);
425 }
426
427sub main'stack_pop
428 {
429 local($num)=@_;
430 $stack-=$num*4;
431 &main'add("esp",$num*4);
432 }
433
434sub main'swtmp
435 {
436 return(&main'DWP($_[0]*4,"esp","",0));
437 }
438
439# Should use swtmp, which is above esp. Linix can trash the stack above esp
440#sub main'wtmp
441# {
442# local($num)=@_;
443#
444# return(&main'DWP(-($num+1)*4,"esp","",0));
445# }
446
447sub main'comment
448 {
449 if (!$main'openbsd && $main'elf)
450 # GNU and SVR4 as'es use different comment delimiters,
451 { # so we just skip comments...
452 push(@out,"\n");
453 return;
454 }
455 foreach (@_)
456 {
457 if (/^\s*$/)
458 { push(@out,"\n"); }
459 else
460 { push(@out,"\t$com_start $_ $com_end\n"); }
461 }
462 }
463
464sub main'label
465 {
466 if (!defined($label{$_[0]}))
467 {
468 $label{$_[0]}=".${label}${_[0]}";
469 $label++;
470 }
471 return($label{$_[0]});
472 }
473
474sub main'set_label
475 {
476 if (!defined($label{$_[0]}))
477 {
478 $label{$_[0]}=".${label}${_[0]}";
479 $label++;
480 }
481 if ($main'openbsd)
482 { push(@out,"_ALIGN_TEXT\n") if ($_[1] != 0); }
483 else
484 { push(@out,".align $align\n") if ($_[1] != 0); }
485 push(@out,"$label{$_[0]}:\n");
486 }
487
488sub main'file_end
489 {
490 if ($const ne "")
491 {
492 push(@out,".section .rodata\n");
493 push(@out,$const);
494 $const="";
495 }
496 }
497
498sub main'data_word
499 {
500 push(@out,"\t.long $_[0]\n");
501 }
502
503# debug output functions: puts, putx, printf
504
505sub main'puts
506 {
507 &pushvars();
508 &main'push('$Lstring' . ++$constl);
509 &main'call('puts');
510 $stack-=4;
511 &main'add("esp",4);
512 &popvars();
513
514 $const .= "Lstring$constl:\n\t.string \"@_[0]\"\n";
515 }
516
517sub main'putx
518 {
519 &pushvars();
520 &main'push($_[0]);
521 &main'push('$Lstring' . ++$constl);
522 &main'call('printf');
523 &main'add("esp",8);
524 $stack-=8;
525 &popvars();
526
527 $const .= "Lstring$constl:\n\t.string \"\%X\"\n";
528 }
529
530sub main'printf
531 {
532 $ostack = $stack;
533 &pushvars();
534 for ($i = @_ - 1; $i >= 0; $i--)
535 {
536 if ($i == 0) # change this to support %s format strings
537 {
538 &main'push('$Lstring' . ++$constl);
539 $const .= "Lstring$constl:\n\t.string \"@_[$i]\"\n";
540 }
541 else
542 {
543 if ($_[$i] =~ /([0-9]*)\(%esp\)/)
544 {
545 &main'push(($1 + $stack - $ostack) . '(%esp)');
546 }
547 else
548 {
549 &main'push($_[$i]);
550 }
551 }
552 }
553 &main'call('printf');
554 $stack-=4*@_;
555 &main'add("esp",4*@_);
556 &popvars();
557 }
558
559sub pushvars
560 {
561 &main'pushf();
562 &main'push("edx");
563 &main'push("ecx");
564 &main'push("eax");
565 }
566
567sub popvars
568 {
569 &main'pop("eax");
570 &main'pop("ecx");
571 &main'pop("edx");
572 &main'popf();
573 }
574
575sub main'picmeup
576 {
577 local($dst,$sym)=@_;
578 if ($main'cpp)
579 {
580 local($tmp)=<<___;
581#if (defined(ELF) || defined(SOL)) && defined(PIC)
582 .align 8
583 call 1f
5841: popl $regs{$dst}
585 addl \$_GLOBAL_OFFSET_TABLE_+[.-1b],$regs{$dst}
586 movl $sym\@GOT($regs{$dst}),$regs{$dst}
587#else
588 leal $sym,$regs{$dst}
589#endif
590___
591 push(@out,$tmp);
592 }
593 elsif ($main'openbsd)
594 {
595 push(@out, "#ifdef PIC\n");
596 push(@out, "\tPIC_PROLOGUE\n");
597 &main'mov($dst,"PIC_GOT($sym)");
598 push(@out, "\tPIC_EPILOGUE\n");
599 push(@out, "#else\n");
600 &main'lea($dst,&main'DWP($sym));
601 push(@out, "#endif\n");
602 }
603 elsif ($main'pic && ($main'elf || $main'aout))
604 {
605 push(@out,"\t.align\t8\n");
606 &main'call(&main'label("PIC_me_up"));
607 &main'set_label("PIC_me_up");
608 &main'blindpop($dst);
609 &main'add($dst,"\$$under"."_GLOBAL_OFFSET_TABLE_+[.-".
610 &main'label("PIC_me_up") . "]");
611 &main'mov($dst,&main'DWP($sym."\@GOT",$dst));
612 }
613 else
614 {
615 &main'lea($dst,&main'DWP($sym));
616 }
617 }
618
619sub main'blindpop { &out1("popl",@_); }