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.pl380
-rw-r--r--src/lib/libcrypto/perlasm/x86nasm.pl362
-rw-r--r--src/lib/libcrypto/perlasm/x86unix.pl628
5 files changed, 1812 insertions, 2 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 ea54a1edc5..60233f80e8 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 }
@@ -90,7 +96,7 @@ $tmp
90#ifdef OUT 96#ifdef OUT
91#define OK 1 97#define OK 1
92#define ALIGN 4 98#define ALIGN 4
93#if defined(__CYGWIN__) || defined(__DJGPP__) || defined(__MINGW32__) 99#if defined(__CYGWIN__) || defined(__DJGPP__)
94#undef SIZE 100#undef SIZE
95#undef TYPE 101#undef TYPE
96#define SIZE(a,b) 102#define SIZE(a,b)
diff --git a/src/lib/libcrypto/perlasm/x86ms.pl b/src/lib/libcrypto/perlasm/x86ms.pl
new file mode 100644
index 0000000000..b6bd744057
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/x86ms.pl
@@ -0,0 +1,380 @@
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"); }
163sub main'movz { &out2("movzx",@_); }
164
165sub out2
166 {
167 local($name,$p1,$p2)=@_;
168 local($l,$t);
169
170 push(@out,"\t$name\t");
171 $t=&conv($p1).",";
172 $l=length($t);
173 push(@out,$t);
174 $l=4-($l+9)/8;
175 push(@out,"\t" x $l);
176 push(@out,&conv($p2));
177 push(@out,"\n");
178 }
179
180sub out0
181 {
182 local($name)=@_;
183
184 push(@out,"\t$name\n");
185 }
186
187sub out1
188 {
189 local($name,$p1)=@_;
190 local($l,$t);
191
192 push(@out,"\t$name\t".&conv($p1)."\n");
193 }
194
195sub conv
196 {
197 local($p)=@_;
198
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 local($file)=@_;
213
214 local($tmp)=<<"EOF";
215 TITLE $file.asm
216 .386
217.model FLAT
218EOF
219 push(@out,$tmp);
220 }
221
222sub main'function_begin
223 {
224 local($func,$extra)=@_;
225
226 push(@labels,$func);
227
228 local($tmp)=<<"EOF";
229_TEXT SEGMENT
230PUBLIC _$func
231$extra
232_$func PROC NEAR
233 push ebp
234 push ebx
235 push esi
236 push edi
237EOF
238 push(@out,$tmp);
239 $stack=20;
240 }
241
242sub main'function_begin_B
243 {
244 local($func,$extra)=@_;
245
246 local($tmp)=<<"EOF";
247_TEXT SEGMENT
248PUBLIC _$func
249$extra
250_$func PROC NEAR
251EOF
252 push(@out,$tmp);
253 $stack=4;
254 }
255
256sub main'function_end
257 {
258 local($func)=@_;
259
260 local($tmp)=<<"EOF";
261 pop edi
262 pop esi
263 pop ebx
264 pop ebp
265 ret
266_$func ENDP
267_TEXT ENDS
268EOF
269 push(@out,$tmp);
270 $stack=0;
271 %label=();
272 }
273
274sub main'function_end_B
275 {
276 local($func)=@_;
277
278 local($tmp)=<<"EOF";
279_$func ENDP
280_TEXT ENDS
281EOF
282 push(@out,$tmp);
283 $stack=0;
284 %label=();
285 }
286
287sub main'function_end_A
288 {
289 local($func)=@_;
290
291 local($tmp)=<<"EOF";
292 pop edi
293 pop esi
294 pop ebx
295 pop ebp
296 ret
297EOF
298 push(@out,$tmp);
299 }
300
301sub main'file_end
302 {
303 push(@out,"END\n");
304 }
305
306sub main'wparam
307 {
308 local($num)=@_;
309
310 return(&main'DWP($stack+$num*4,"esp","",0));
311 }
312
313sub main'swtmp
314 {
315 return(&main'DWP($_[0]*4,"esp","",0));
316 }
317
318# Should use swtmp, which is above esp. Linix can trash the stack above esp
319#sub main'wtmp
320# {
321# local($num)=@_;
322#
323# return(&main'DWP(-(($num+1)*4),"esp","",0));
324# }
325
326sub main'comment
327 {
328 foreach (@_)
329 {
330 push(@out,"\t; $_\n");
331 }
332 }
333
334sub main'label
335 {
336 if (!defined($label{$_[0]}))
337 {
338 $label{$_[0]}="\$${label}${_[0]}";
339 $label++;
340 }
341 return($label{$_[0]});
342 }
343
344sub main'set_label
345 {
346 if (!defined($label{$_[0]}))
347 {
348 $label{$_[0]}="\$${label}${_[0]}";
349 $label++;
350 }
351 if((defined $_[2]) && ($_[2] == 1))
352 {
353 push(@out,"$label{$_[0]}::\n");
354 }
355 else
356 {
357 push(@out,"$label{$_[0]}:\n");
358 }
359 }
360
361sub main'data_word
362 {
363 push(@out,"\tDD\t$_[0]\n");
364 }
365
366sub out1p
367 {
368 local($name,$p1)=@_;
369 local($l,$t);
370
371 push(@out,"\t$name\t ".&conv($p1)."\n");
372 }
373
374sub main'picmeup
375 {
376 local($dst,$sym)=@_;
377 &main'lea($dst,&main'DWP($sym));
378 }
379
380sub 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..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",@_); }
diff --git a/src/lib/libcrypto/perlasm/x86unix.pl b/src/lib/libcrypto/perlasm/x86unix.pl
new file mode 100644
index 0000000000..b61425e951
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/x86unix.pl
@@ -0,0 +1,628 @@
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($_[0]=~/%[a-d][lh]/?"addb":"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($_[0]=~/%[a-d][lh]/?"xchgb":"xchgl",@_); }
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($_[0]=~/%[a-d][hl]/?"incb":"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"); }
182sub main'test { &out2("testl",@_); }
183sub main'movz { &out2("movzbl",@_); }
184sub main'neg { &out1("negl",@_); }
185
186# The bswapl instruction is new for the 486. Emulate if i386.
187sub main'bswap
188 {
189 if ($main'i386)
190 {
191 &main'comment("bswapl @_");
192 &main'exch(main'HB(@_),main'LB(@_));
193 &main'rotr(@_,16);
194 &main'exch(main'HB(@_),main'LB(@_));
195 }
196 else
197 {
198 &out1("bswapl",@_);
199 }
200 }
201
202sub out2
203 {
204 local($name,$p1,$p2)=@_;
205 local($l,$ll,$t);
206 local(%special)=( "roll",0xD1C0,"rorl",0xD1C8,
207 "rcll",0xD1D0,"rcrl",0xD1D8,
208 "shll",0xD1E0,"shrl",0xD1E8,
209 "sarl",0xD1F8);
210
211 if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1))
212 {
213 $op=$special{$name}|$reg_val{$p1};
214 $tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
215 $tmp2=sprintf(".byte %d\t",$op &0xff);
216 push(@out,$tmp1);
217 push(@out,$tmp2);
218
219 $p2=&conv($p2);
220 $p1=&conv($p1);
221 &main'comment("$name $p2 $p1");
222 return;
223 }
224
225 push(@out,"\t$name\t");
226 $t=&conv($p2).",";
227 $l=length($t);
228 push(@out,$t);
229 $ll=4-($l+9)/8;
230 $tmp1=sprintf("\t" x $ll);
231 push(@out,$tmp1);
232 push(@out,&conv($p1)."\n");
233 }
234
235sub out1
236 {
237 local($name,$p1)=@_;
238 local($l,$t);
239 local(%special)=("bswapl",0x0FC8);
240
241 if ((defined($special{$name})) && defined($regs{$p1}))
242 {
243 $op=$special{$name}|$reg_val{$p1};
244 $tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
245 $tmp2=sprintf(".byte %d\t",$op &0xff);
246 push(@out,$tmp1);
247 push(@out,$tmp2);
248
249 $p2=&conv($p2);
250 $p1=&conv($p1);
251 &main'comment("$name $p2 $p1");
252 return;
253 }
254
255 push(@out,"\t$name\t".&conv($p1)."\n");
256 }
257
258sub out1p
259 {
260 local($name,$p1)=@_;
261 local($l,$t);
262
263 push(@out,"\t$name\t*".&conv($p1)."\n");
264 }
265
266sub out0
267 {
268 push(@out,"\t$_[0]\n");
269 }
270
271sub conv
272 {
273 local($p)=@_;
274
275# $p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
276
277 $p=$regs{$p} if (defined($regs{$p}));
278
279 $p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/;
280 $p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/;
281 return $p;
282 }
283
284sub main'file
285 {
286 local($file)=@_;
287
288 if ($main'openbsd)
289 { push(@out,"#include <machine/asm.h>\n"); return; }
290
291 local($tmp)=<<"EOF";
292 .file "$file.s"
293 .version "01.01"
294gcc2_compiled.:
295EOF
296 push(@out,$tmp);
297 }
298
299sub main'function_begin
300 {
301 local($func)=@_;
302
303 &main'external_label($func);
304 $func=$under.$func;
305
306 if ($main'openbsd)
307 { push (@out, "\nENTRY($func)\n"); goto skip; }
308
309 local($tmp)=<<"EOF";
310.text
311 .align $align
312.globl $func
313EOF
314 push(@out,$tmp);
315 if ($main'cpp)
316 { $tmp=push(@out,"\tTYPE($func,\@function)\n"); }
317 elsif ($main'gaswin)
318 { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
319 else { $tmp=push(@out,"\t.type\t$func,\@function\n"); }
320 push(@out,"$func:\n");
321skip:
322 $tmp=<<"EOF";
323 pushl %ebp
324 pushl %ebx
325 pushl %esi
326 pushl %edi
327
328EOF
329 push(@out,$tmp);
330 $stack=20;
331 }
332
333sub main'function_begin_B
334 {
335 local($func,$extra)=@_;
336
337 &main'external_label($func);
338 $func=$under.$func;
339
340 if ($main'openbsd)
341 { push(@out, "\nENTRY($func)\n"); goto skip; }
342
343 local($tmp)=<<"EOF";
344.text
345 .align $align
346.globl $func
347EOF
348 push(@out,$tmp);
349 if ($main'cpp)
350 { push(@out,"\tTYPE($func,\@function)\n"); }
351 elsif ($main'gaswin)
352 { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
353 else { push(@out,"\t.type $func,\@function\n"); }
354 push(@out,"$func:\n");
355skip:
356 $stack=4;
357 }
358
359sub main'function_end
360 {
361 local($func)=@_;
362
363 $func=$under.$func;
364
365 local($tmp)=<<"EOF";
366 popl %edi
367 popl %esi
368 popl %ebx
369 popl %ebp
370 ret
371.L_${func}_end:
372EOF
373 push(@out,$tmp);
374
375 if ($main'cpp)
376 { push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); }
377 elsif ($main'gaswin)
378 { $tmp=push(@out,"\t.align 4\n"); }
379 else { push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); }
380 push(@out,".ident \"$func\"\n");
381 $stack=0;
382 %label=();
383 }
384
385sub main'function_end_A
386 {
387 local($func)=@_;
388
389 local($tmp)=<<"EOF";
390 popl %edi
391 popl %esi
392 popl %ebx
393 popl %ebp
394 ret
395EOF
396 push(@out,$tmp);
397 }
398
399sub main'function_end_B
400 {
401 local($func)=@_;
402
403 $func=$under.$func;
404
405 push(@out,".L_${func}_end:\n");
406 if ($main'cpp)
407 { push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); }
408 elsif ($main'gaswin)
409 { push(@out,"\t.align 4\n"); }
410 else { push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); }
411 push(@out,".ident \"desasm.pl\"\n");
412 $stack=0;
413 %label=();
414 }
415
416sub main'wparam
417 {
418 local($num)=@_;
419
420 return(&main'DWP($stack+$num*4,"esp","",0));
421 }
422
423sub main'stack_push
424 {
425 local($num)=@_;
426 $stack+=$num*4;
427 &main'sub("esp",$num*4);
428 }
429
430sub main'stack_pop
431 {
432 local($num)=@_;
433 $stack-=$num*4;
434 &main'add("esp",$num*4);
435 }
436
437sub main'swtmp
438 {
439 return(&main'DWP($_[0]*4,"esp","",0));
440 }
441
442# Should use swtmp, which is above esp. Linix can trash the stack above esp
443#sub main'wtmp
444# {
445# local($num)=@_;
446#
447# return(&main'DWP(-($num+1)*4,"esp","",0));
448# }
449
450sub main'comment
451 {
452 if (!$main'openbsd && $main'elf)
453 # GNU and SVR4 as'es use different comment delimiters,
454 { # so we just skip comments...
455 push(@out,"\n");
456 return;
457 }
458 foreach (@_)
459 {
460 if (/^\s*$/)
461 { push(@out,"\n"); }
462 else
463 { push(@out,"\t$com_start $_ $com_end\n"); }
464 }
465 }
466
467sub main'public_label
468 {
469 $label{$_[0]}="${under}${_[0]}" if (!defined($label{$_[0]}));
470 push(@out,".globl\t$label{$_[0]}\n");
471 }
472
473sub main'label
474 {
475 if (!defined($label{$_[0]}))
476 {
477 $label{$_[0]}=".${label}${_[0]}";
478 $label++;
479 }
480 return($label{$_[0]});
481 }
482
483sub main'set_label
484 {
485 if (!defined($label{$_[0]}))
486 {
487 $label{$_[0]}=".${label}${_[0]}";
488 $label++;
489 }
490 if ($main'openbsd)
491 { push(@out,"_ALIGN_TEXT\n") if ($_[1] != 0); }
492 else
493 { push(@out,".align $align\n") if ($_[1] != 0); }
494 push(@out,"$label{$_[0]}:\n");
495 }
496
497sub main'file_end
498 {
499 if ($const ne "")
500 {
501 push(@out,".section .rodata\n");
502 push(@out,$const);
503 $const="";
504 }
505 }
506
507sub main'data_word
508 {
509 push(@out,"\t.long\t".join(',',@_)."\n");
510 }
511
512# debug output functions: puts, putx, printf
513
514sub main'puts
515 {
516 &pushvars();
517 &main'push('$Lstring' . ++$constl);
518 &main'call('puts');
519 $stack-=4;
520 &main'add("esp",4);
521 &popvars();
522
523 $const .= "Lstring$constl:\n\t.string \"@_[0]\"\n";
524 }
525
526sub main'putx
527 {
528 &pushvars();
529 &main'push($_[0]);
530 &main'push('$Lstring' . ++$constl);
531 &main'call('printf');
532 &main'add("esp",8);
533 $stack-=8;
534 &popvars();
535
536 $const .= "Lstring$constl:\n\t.string \"\%X\"\n";
537 }
538
539sub main'printf
540 {
541 $ostack = $stack;
542 &pushvars();
543 for ($i = @_ - 1; $i >= 0; $i--)
544 {
545 if ($i == 0) # change this to support %s format strings
546 {
547 &main'push('$Lstring' . ++$constl);
548 $const .= "Lstring$constl:\n\t.string \"@_[$i]\"\n";
549 }
550 else
551 {
552 if ($_[$i] =~ /([0-9]*)\(%esp\)/)
553 {
554 &main'push(($1 + $stack - $ostack) . '(%esp)');
555 }
556 else
557 {
558 &main'push($_[$i]);
559 }
560 }
561 }
562 &main'call('printf');
563 $stack-=4*@_;
564 &main'add("esp",4*@_);
565 &popvars();
566 }
567
568sub pushvars
569 {
570 &main'pushf();
571 &main'push("edx");
572 &main'push("ecx");
573 &main'push("eax");
574 }
575
576sub popvars
577 {
578 &main'pop("eax");
579 &main'pop("ecx");
580 &main'pop("edx");
581 &main'popf();
582 }
583
584sub main'picmeup
585 {
586 local($dst,$sym)=@_;
587 if ($main'cpp)
588 {
589 local($tmp)=<<___;
590#if (defined(ELF) || defined(SOL)) && defined(PIC)
591 .align 8
592 call 1f
5931: popl $regs{$dst}
594 addl \$_GLOBAL_OFFSET_TABLE_+[.-1b],$regs{$dst}
595 movl $sym\@GOT($regs{$dst}),$regs{$dst}
596#else
597 leal $sym,$regs{$dst}
598#endif
599___
600 push(@out,$tmp);
601 }
602 elsif ($main'openbsd)
603 {
604 push(@out, "#ifdef PIC\n");
605 push(@out, "\tPIC_PROLOGUE\n");
606 &main'mov($dst,"PIC_GOT($sym)");
607 push(@out, "\tPIC_EPILOGUE\n");
608 push(@out, "#else\n");
609 &main'lea($dst,&main'DWP($sym));
610 push(@out, "#endif\n");
611 }
612 elsif ($main'pic && ($main'elf || $main'aout))
613 {
614 push(@out,"\t.align\t8\n");
615 &main'call(&main'label("PIC_me_up"));
616 &main'set_label("PIC_me_up");
617 &main'blindpop($dst);
618 &main'add($dst,"\$$under"."_GLOBAL_OFFSET_TABLE_+[.-".
619 &main'label("PIC_me_up") . "]");
620 &main'mov($dst,&main'DWP($sym."\@GOT",$dst));
621 }
622 else
623 {
624 &main'lea($dst,&main'DWP($sym));
625 }
626 }
627
628sub main'blindpop { &out1("popl",@_); }