xref: /onnv-gate/usr/src/common/openssl/crypto/perlasm/x86unix.pl (revision 2139:6243c3338933)
10Sstevel@tonic-gate#!/usr/local/bin/perl
20Sstevel@tonic-gate
3*2139Sjp161948package x86unix;	# GAS actually...
40Sstevel@tonic-gate
50Sstevel@tonic-gate$label="L000";
60Sstevel@tonic-gate$const="";
70Sstevel@tonic-gate$constl=0;
80Sstevel@tonic-gate
90Sstevel@tonic-gate$align=($main'aout)?"4":"16";
10*2139Sjp161948$under=($main'aout or $main'coff)?"_":"";
11*2139Sjp161948$dot=($main'aout)?"":".";
12*2139Sjp161948$com_start="#" if ($main'aout or $main'coff);
130Sstevel@tonic-gate
140Sstevel@tonic-gatesub main'asm_init_output { @out=(); }
150Sstevel@tonic-gatesub main'asm_get_output { return(@out); }
160Sstevel@tonic-gatesub main'get_labels { return(@labels); }
170Sstevel@tonic-gatesub main'external_label { push(@labels,@_); }
180Sstevel@tonic-gate
190Sstevel@tonic-gateif ($main'cpp)
200Sstevel@tonic-gate	{
210Sstevel@tonic-gate	$align="ALIGN";
220Sstevel@tonic-gate	$under="";
230Sstevel@tonic-gate	$com_start='/*';
240Sstevel@tonic-gate	$com_end='*/';
250Sstevel@tonic-gate	}
260Sstevel@tonic-gate
270Sstevel@tonic-gate%lb=(	'eax',	'%al',
280Sstevel@tonic-gate	'ebx',	'%bl',
290Sstevel@tonic-gate	'ecx',	'%cl',
300Sstevel@tonic-gate	'edx',	'%dl',
310Sstevel@tonic-gate	'ax',	'%al',
320Sstevel@tonic-gate	'bx',	'%bl',
330Sstevel@tonic-gate	'cx',	'%cl',
340Sstevel@tonic-gate	'dx',	'%dl',
350Sstevel@tonic-gate	);
360Sstevel@tonic-gate
370Sstevel@tonic-gate%hb=(	'eax',	'%ah',
380Sstevel@tonic-gate	'ebx',	'%bh',
390Sstevel@tonic-gate	'ecx',	'%ch',
400Sstevel@tonic-gate	'edx',	'%dh',
410Sstevel@tonic-gate	'ax',	'%ah',
420Sstevel@tonic-gate	'bx',	'%bh',
430Sstevel@tonic-gate	'cx',	'%ch',
440Sstevel@tonic-gate	'dx',	'%dh',
450Sstevel@tonic-gate	);
460Sstevel@tonic-gate
470Sstevel@tonic-gate%regs=(	'eax',	'%eax',
480Sstevel@tonic-gate	'ebx',	'%ebx',
490Sstevel@tonic-gate	'ecx',	'%ecx',
500Sstevel@tonic-gate	'edx',	'%edx',
510Sstevel@tonic-gate	'esi',	'%esi',
520Sstevel@tonic-gate	'edi',	'%edi',
530Sstevel@tonic-gate	'ebp',	'%ebp',
540Sstevel@tonic-gate	'esp',	'%esp',
55*2139Sjp161948
56*2139Sjp161948	'mm0',	'%mm0',
57*2139Sjp161948	'mm1',	'%mm1',
58*2139Sjp161948	'mm2',	'%mm2',
59*2139Sjp161948	'mm3',	'%mm3',
60*2139Sjp161948	'mm4',	'%mm4',
61*2139Sjp161948	'mm5',	'%mm5',
62*2139Sjp161948	'mm6',	'%mm6',
63*2139Sjp161948	'mm7',	'%mm7',
64*2139Sjp161948
65*2139Sjp161948	'xmm0',	'%xmm0',
66*2139Sjp161948	'xmm1',	'%xmm1',
67*2139Sjp161948	'xmm2',	'%xmm2',
68*2139Sjp161948	'xmm3',	'%xmm3',
69*2139Sjp161948	'xmm4',	'%xmm4',
70*2139Sjp161948	'xmm5',	'%xmm5',
71*2139Sjp161948	'xmm6',	'%xmm6',
72*2139Sjp161948	'xmm7',	'%xmm7',
730Sstevel@tonic-gate	);
740Sstevel@tonic-gate
750Sstevel@tonic-gate%reg_val=(
760Sstevel@tonic-gate	'eax',	0x00,
770Sstevel@tonic-gate	'ebx',	0x03,
780Sstevel@tonic-gate	'ecx',	0x01,
790Sstevel@tonic-gate	'edx',	0x02,
800Sstevel@tonic-gate	'esi',	0x06,
810Sstevel@tonic-gate	'edi',	0x07,
820Sstevel@tonic-gate	'ebp',	0x05,
830Sstevel@tonic-gate	'esp',	0x04,
840Sstevel@tonic-gate	);
850Sstevel@tonic-gate
860Sstevel@tonic-gatesub main'LB
870Sstevel@tonic-gate	{
880Sstevel@tonic-gate	(defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
890Sstevel@tonic-gate	return($lb{$_[0]});
900Sstevel@tonic-gate	}
910Sstevel@tonic-gate
920Sstevel@tonic-gatesub main'HB
930Sstevel@tonic-gate	{
940Sstevel@tonic-gate	(defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
950Sstevel@tonic-gate	return($hb{$_[0]});
960Sstevel@tonic-gate	}
970Sstevel@tonic-gate
980Sstevel@tonic-gatesub main'DWP
990Sstevel@tonic-gate	{
1000Sstevel@tonic-gate	local($addr,$reg1,$reg2,$idx)=@_;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate	$ret="";
1030Sstevel@tonic-gate	$addr =~ s/(^|[+ \t])([A-Za-z_]+[A-Za-z0-9_]+)($|[+ \t])/$1$under$2$3/;
1040Sstevel@tonic-gate	$reg1="$regs{$reg1}" if defined($regs{$reg1});
1050Sstevel@tonic-gate	$reg2="$regs{$reg2}" if defined($regs{$reg2});
1060Sstevel@tonic-gate	$ret.=$addr if ($addr ne "") && ($addr ne 0);
1070Sstevel@tonic-gate	if ($reg2 ne "")
1080Sstevel@tonic-gate		{
1090Sstevel@tonic-gate		if($idx ne "" && $idx != 0)
1100Sstevel@tonic-gate		    { $ret.="($reg1,$reg2,$idx)"; }
1110Sstevel@tonic-gate		else
1120Sstevel@tonic-gate		    { $ret.="($reg1,$reg2)"; }
1130Sstevel@tonic-gate	        }
1140Sstevel@tonic-gate	elsif ($reg1 ne "")
1150Sstevel@tonic-gate		{ $ret.="($reg1)" }
1160Sstevel@tonic-gate	return($ret);
1170Sstevel@tonic-gate	}
1180Sstevel@tonic-gate
119*2139Sjp161948sub main'QWP
120*2139Sjp161948	{
121*2139Sjp161948	return(&main'DWP(@_));
122*2139Sjp161948	}
123*2139Sjp161948
1240Sstevel@tonic-gatesub main'BP
1250Sstevel@tonic-gate	{
1260Sstevel@tonic-gate	return(&main'DWP(@_));
1270Sstevel@tonic-gate	}
1280Sstevel@tonic-gate
1290Sstevel@tonic-gatesub main'BC
1300Sstevel@tonic-gate	{
1310Sstevel@tonic-gate	return @_;
1320Sstevel@tonic-gate	}
1330Sstevel@tonic-gate
1340Sstevel@tonic-gatesub main'DWC
1350Sstevel@tonic-gate	{
1360Sstevel@tonic-gate	return @_;
1370Sstevel@tonic-gate	}
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate#sub main'BP
1400Sstevel@tonic-gate#	{
1410Sstevel@tonic-gate#	local($addr,$reg1,$reg2,$idx)=@_;
1420Sstevel@tonic-gate#
1430Sstevel@tonic-gate#	$ret="";
1440Sstevel@tonic-gate#
1450Sstevel@tonic-gate#	$addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/;
1460Sstevel@tonic-gate#	$reg1="$regs{$reg1}" if defined($regs{$reg1});
1470Sstevel@tonic-gate#	$reg2="$regs{$reg2}" if defined($regs{$reg2});
1480Sstevel@tonic-gate#	$ret.=$addr if ($addr ne "") && ($addr ne 0);
1490Sstevel@tonic-gate#	if ($reg2 ne "")
1500Sstevel@tonic-gate#		{ $ret.="($reg1,$reg2,$idx)"; }
1510Sstevel@tonic-gate#	else
1520Sstevel@tonic-gate#		{ $ret.="($reg1)" }
1530Sstevel@tonic-gate#	return($ret);
1540Sstevel@tonic-gate#	}
1550Sstevel@tonic-gate
1560Sstevel@tonic-gatesub main'mov	{ &out2("movl",@_); }
1570Sstevel@tonic-gatesub main'movb	{ &out2("movb",@_); }
1580Sstevel@tonic-gatesub main'and	{ &out2("andl",@_); }
1590Sstevel@tonic-gatesub main'or	{ &out2("orl",@_); }
1600Sstevel@tonic-gatesub main'shl	{ &out2("sall",@_); }
1610Sstevel@tonic-gatesub main'shr	{ &out2("shrl",@_); }
1620Sstevel@tonic-gatesub main'xor	{ &out2("xorl",@_); }
1630Sstevel@tonic-gatesub main'xorb	{ &out2("xorb",@_); }
164*2139Sjp161948sub main'add	{ &out2($_[0]=~/%[a-d][lh]/?"addb":"addl",@_); }
1650Sstevel@tonic-gatesub main'adc	{ &out2("adcl",@_); }
1660Sstevel@tonic-gatesub main'sub	{ &out2("subl",@_); }
167*2139Sjp161948sub main'sbb	{ &out2("sbbl",@_); }
1680Sstevel@tonic-gatesub main'rotl	{ &out2("roll",@_); }
1690Sstevel@tonic-gatesub main'rotr	{ &out2("rorl",@_); }
170*2139Sjp161948sub main'exch	{ &out2($_[0]=~/%[a-d][lh]/?"xchgb":"xchgl",@_); }
1710Sstevel@tonic-gatesub main'cmp	{ &out2("cmpl",@_); }
1720Sstevel@tonic-gatesub main'lea	{ &out2("leal",@_); }
1730Sstevel@tonic-gatesub main'mul	{ &out1("mull",@_); }
1740Sstevel@tonic-gatesub main'div	{ &out1("divl",@_); }
1750Sstevel@tonic-gatesub main'jmp	{ &out1("jmp",@_); }
1760Sstevel@tonic-gatesub main'jmp_ptr { &out1p("jmp",@_); }
1770Sstevel@tonic-gatesub main'je	{ &out1("je",@_); }
1780Sstevel@tonic-gatesub main'jle	{ &out1("jle",@_); }
1790Sstevel@tonic-gatesub main'jne	{ &out1("jne",@_); }
1800Sstevel@tonic-gatesub main'jnz	{ &out1("jnz",@_); }
1810Sstevel@tonic-gatesub main'jz	{ &out1("jz",@_); }
1820Sstevel@tonic-gatesub main'jge	{ &out1("jge",@_); }
1830Sstevel@tonic-gatesub main'jl	{ &out1("jl",@_); }
1840Sstevel@tonic-gatesub main'ja	{ &out1("ja",@_); }
1850Sstevel@tonic-gatesub main'jae	{ &out1("jae",@_); }
1860Sstevel@tonic-gatesub main'jb	{ &out1("jb",@_); }
1870Sstevel@tonic-gatesub main'jbe	{ &out1("jbe",@_); }
1880Sstevel@tonic-gatesub main'jc	{ &out1("jc",@_); }
1890Sstevel@tonic-gatesub main'jnc	{ &out1("jnc",@_); }
1900Sstevel@tonic-gatesub main'jno	{ &out1("jno",@_); }
1910Sstevel@tonic-gatesub main'dec	{ &out1("decl",@_); }
192*2139Sjp161948sub main'inc	{ &out1($_[0]=~/%[a-d][hl]/?"incb":"incl",@_); }
1930Sstevel@tonic-gatesub main'push	{ &out1("pushl",@_); $stack+=4; }
1940Sstevel@tonic-gatesub main'pop	{ &out1("popl",@_); $stack-=4; }
195*2139Sjp161948sub main'pushf	{ &out0("pushfl"); $stack+=4; }
196*2139Sjp161948sub main'popf	{ &out0("popfl"); $stack-=4; }
1970Sstevel@tonic-gatesub main'not	{ &out1("notl",@_); }
198*2139Sjp161948sub main'call	{	my $pre=$under;
199*2139Sjp161948			foreach $i (%label)
200*2139Sjp161948			{ if ($label{$i} eq $_[0]) { $pre=''; last; } }
201*2139Sjp161948			&out1("call",$pre.$_[0]);
202*2139Sjp161948		}
2030Sstevel@tonic-gatesub main'ret	{ &out0("ret"); }
2040Sstevel@tonic-gatesub main'nop	{ &out0("nop"); }
205*2139Sjp161948sub main'test	{ &out2("testl",@_); }
206*2139Sjp161948sub main'bt	{ &out2("btl",@_); }
207*2139Sjp161948sub main'leave	{ &out0("leave"); }
208*2139Sjp161948sub main'cpuid	{ &out0(".byte\t0x0f,0xa2"); }
209*2139Sjp161948sub main'rdtsc	{ &out0(".byte\t0x0f,0x31"); }
210*2139Sjp161948sub main'halt	{ &out0("hlt"); }
211*2139Sjp161948sub main'movz	{ &out2("movzbl",@_); }
212*2139Sjp161948sub main'neg	{ &out1("negl",@_); }
213*2139Sjp161948sub main'cld	{ &out0("cld"); }
214*2139Sjp161948
215*2139Sjp161948# SSE2
216*2139Sjp161948sub main'emms	{ &out0("emms"); }
217*2139Sjp161948sub main'movd	{ &out2("movd",@_); }
218*2139Sjp161948sub main'movq	{ &out2("movq",@_); }
219*2139Sjp161948sub main'movdqu	{ &out2("movdqu",@_); }
220*2139Sjp161948sub main'movdqa	{ &out2("movdqa",@_); }
221*2139Sjp161948sub main'movdq2q{ &out2("movdq2q",@_); }
222*2139Sjp161948sub main'movq2dq{ &out2("movq2dq",@_); }
223*2139Sjp161948sub main'paddq	{ &out2("paddq",@_); }
224*2139Sjp161948sub main'pmuludq{ &out2("pmuludq",@_); }
225*2139Sjp161948sub main'psrlq	{ &out2("psrlq",@_); }
226*2139Sjp161948sub main'psllq	{ &out2("psllq",@_); }
227*2139Sjp161948sub main'pxor	{ &out2("pxor",@_); }
228*2139Sjp161948sub main'por	{ &out2("por",@_); }
229*2139Sjp161948sub main'pand	{ &out2("pand",@_); }
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate# The bswapl instruction is new for the 486. Emulate if i386.
2320Sstevel@tonic-gatesub main'bswap
2330Sstevel@tonic-gate	{
2340Sstevel@tonic-gate	if ($main'i386)
2350Sstevel@tonic-gate		{
2360Sstevel@tonic-gate		&main'comment("bswapl @_");
2370Sstevel@tonic-gate		&main'exch(main'HB(@_),main'LB(@_));
2380Sstevel@tonic-gate		&main'rotr(@_,16);
2390Sstevel@tonic-gate		&main'exch(main'HB(@_),main'LB(@_));
2400Sstevel@tonic-gate		}
2410Sstevel@tonic-gate	else
2420Sstevel@tonic-gate		{
2430Sstevel@tonic-gate		&out1("bswapl",@_);
2440Sstevel@tonic-gate		}
2450Sstevel@tonic-gate	}
2460Sstevel@tonic-gate
2470Sstevel@tonic-gatesub out2
2480Sstevel@tonic-gate	{
2490Sstevel@tonic-gate	local($name,$p1,$p2)=@_;
2500Sstevel@tonic-gate	local($l,$ll,$t);
2510Sstevel@tonic-gate	local(%special)=(	"roll",0xD1C0,"rorl",0xD1C8,
2520Sstevel@tonic-gate				"rcll",0xD1D0,"rcrl",0xD1D8,
2530Sstevel@tonic-gate				"shll",0xD1E0,"shrl",0xD1E8,
2540Sstevel@tonic-gate				"sarl",0xD1F8);
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate	if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1))
2570Sstevel@tonic-gate		{
2580Sstevel@tonic-gate		$op=$special{$name}|$reg_val{$p1};
2590Sstevel@tonic-gate		$tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
2600Sstevel@tonic-gate		$tmp2=sprintf(".byte %d\t",$op     &0xff);
2610Sstevel@tonic-gate		push(@out,$tmp1);
2620Sstevel@tonic-gate		push(@out,$tmp2);
2630Sstevel@tonic-gate
2640Sstevel@tonic-gate		$p2=&conv($p2);
2650Sstevel@tonic-gate		$p1=&conv($p1);
2660Sstevel@tonic-gate		&main'comment("$name $p2 $p1");
2670Sstevel@tonic-gate		return;
2680Sstevel@tonic-gate		}
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate	push(@out,"\t$name\t");
2710Sstevel@tonic-gate	$t=&conv($p2).",";
2720Sstevel@tonic-gate	$l=length($t);
2730Sstevel@tonic-gate	push(@out,$t);
2740Sstevel@tonic-gate	$ll=4-($l+9)/8;
2750Sstevel@tonic-gate	$tmp1=sprintf("\t" x $ll);
2760Sstevel@tonic-gate	push(@out,$tmp1);
2770Sstevel@tonic-gate	push(@out,&conv($p1)."\n");
2780Sstevel@tonic-gate	}
2790Sstevel@tonic-gate
2800Sstevel@tonic-gatesub out1
2810Sstevel@tonic-gate	{
2820Sstevel@tonic-gate	local($name,$p1)=@_;
2830Sstevel@tonic-gate	local($l,$t);
2840Sstevel@tonic-gate	local(%special)=("bswapl",0x0FC8);
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate	if ((defined($special{$name})) && defined($regs{$p1}))
2870Sstevel@tonic-gate		{
2880Sstevel@tonic-gate		$op=$special{$name}|$reg_val{$p1};
2890Sstevel@tonic-gate		$tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
2900Sstevel@tonic-gate		$tmp2=sprintf(".byte %d\t",$op     &0xff);
2910Sstevel@tonic-gate		push(@out,$tmp1);
2920Sstevel@tonic-gate		push(@out,$tmp2);
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate		$p2=&conv($p2);
2950Sstevel@tonic-gate		$p1=&conv($p1);
2960Sstevel@tonic-gate		&main'comment("$name $p2 $p1");
2970Sstevel@tonic-gate		return;
2980Sstevel@tonic-gate		}
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate	push(@out,"\t$name\t".&conv($p1)."\n");
3010Sstevel@tonic-gate	}
3020Sstevel@tonic-gate
3030Sstevel@tonic-gatesub out1p
3040Sstevel@tonic-gate	{
3050Sstevel@tonic-gate	local($name,$p1)=@_;
3060Sstevel@tonic-gate	local($l,$t);
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate	push(@out,"\t$name\t*".&conv($p1)."\n");
3090Sstevel@tonic-gate	}
3100Sstevel@tonic-gate
3110Sstevel@tonic-gatesub out0
3120Sstevel@tonic-gate	{
3130Sstevel@tonic-gate	push(@out,"\t$_[0]\n");
3140Sstevel@tonic-gate	}
3150Sstevel@tonic-gate
3160Sstevel@tonic-gatesub conv
3170Sstevel@tonic-gate	{
3180Sstevel@tonic-gate	local($p)=@_;
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate#	$p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate	$p=$regs{$p} if (defined($regs{$p}));
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate	$p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/;
3250Sstevel@tonic-gate	$p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/;
3260Sstevel@tonic-gate	return $p;
3270Sstevel@tonic-gate	}
3280Sstevel@tonic-gate
3290Sstevel@tonic-gatesub main'file
3300Sstevel@tonic-gate	{
3310Sstevel@tonic-gate	local($file)=@_;
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate	local($tmp)=<<"EOF";
3340Sstevel@tonic-gate	.file	"$file.s"
3350Sstevel@tonic-gateEOF
3360Sstevel@tonic-gate	push(@out,$tmp);
3370Sstevel@tonic-gate	}
3380Sstevel@tonic-gate
3390Sstevel@tonic-gatesub main'function_begin
3400Sstevel@tonic-gate	{
3410Sstevel@tonic-gate	local($func)=@_;
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate	&main'external_label($func);
3440Sstevel@tonic-gate	$func=$under.$func;
3450Sstevel@tonic-gate
3460Sstevel@tonic-gate	local($tmp)=<<"EOF";
3470Sstevel@tonic-gate.text
348*2139Sjp161948.globl	$func
3490Sstevel@tonic-gateEOF
3500Sstevel@tonic-gate	push(@out,$tmp);
3510Sstevel@tonic-gate	if ($main'cpp)
352*2139Sjp161948		{ $tmp=push(@out,"TYPE($func,\@function)\n"); }
353*2139Sjp161948	elsif ($main'coff)
354*2139Sjp161948		{ $tmp=push(@out,".def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
355*2139Sjp161948	elsif ($main'aout and !$main'pic)
356*2139Sjp161948		{ }
357*2139Sjp161948	else	{ $tmp=push(@out,".type\t$func,\@function\n"); }
358*2139Sjp161948	push(@out,".align\t$align\n");
3590Sstevel@tonic-gate	push(@out,"$func:\n");
3600Sstevel@tonic-gate	$tmp=<<"EOF";
3610Sstevel@tonic-gate	pushl	%ebp
3620Sstevel@tonic-gate	pushl	%ebx
3630Sstevel@tonic-gate	pushl	%esi
3640Sstevel@tonic-gate	pushl	%edi
3650Sstevel@tonic-gate
3660Sstevel@tonic-gateEOF
3670Sstevel@tonic-gate	push(@out,$tmp);
3680Sstevel@tonic-gate	$stack=20;
3690Sstevel@tonic-gate	}
3700Sstevel@tonic-gate
3710Sstevel@tonic-gatesub main'function_begin_B
3720Sstevel@tonic-gate	{
3730Sstevel@tonic-gate	local($func,$extra)=@_;
3740Sstevel@tonic-gate
3750Sstevel@tonic-gate	&main'external_label($func);
3760Sstevel@tonic-gate	$func=$under.$func;
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate	local($tmp)=<<"EOF";
3790Sstevel@tonic-gate.text
380*2139Sjp161948.globl	$func
3810Sstevel@tonic-gateEOF
3820Sstevel@tonic-gate	push(@out,$tmp);
3830Sstevel@tonic-gate	if ($main'cpp)
384*2139Sjp161948		{ push(@out,"TYPE($func,\@function)\n"); }
385*2139Sjp161948	elsif ($main'coff)
386*2139Sjp161948		{ $tmp=push(@out,".def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
387*2139Sjp161948	elsif ($main'aout and !$main'pic)
388*2139Sjp161948		{ }
389*2139Sjp161948	else	{ push(@out,".type	$func,\@function\n"); }
390*2139Sjp161948	push(@out,".align\t$align\n");
3910Sstevel@tonic-gate	push(@out,"$func:\n");
3920Sstevel@tonic-gate	$stack=4;
3930Sstevel@tonic-gate	}
3940Sstevel@tonic-gate
3950Sstevel@tonic-gatesub main'function_end
3960Sstevel@tonic-gate	{
3970Sstevel@tonic-gate	local($func)=@_;
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate	$func=$under.$func;
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate	local($tmp)=<<"EOF";
4020Sstevel@tonic-gate	popl	%edi
4030Sstevel@tonic-gate	popl	%esi
4040Sstevel@tonic-gate	popl	%ebx
4050Sstevel@tonic-gate	popl	%ebp
4060Sstevel@tonic-gate	ret
407*2139Sjp161948${dot}L_${func}_end:
4080Sstevel@tonic-gateEOF
4090Sstevel@tonic-gate	push(@out,$tmp);
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate	if ($main'cpp)
412*2139Sjp161948		{ push(@out,"SIZE($func,${dot}L_${func}_end-$func)\n"); }
413*2139Sjp161948	elsif ($main'coff or $main'aout)
414*2139Sjp161948                { }
415*2139Sjp161948	else	{ push(@out,".size\t$func,${dot}L_${func}_end-$func\n"); }
4160Sstevel@tonic-gate	push(@out,".ident	\"$func\"\n");
4170Sstevel@tonic-gate	$stack=0;
4180Sstevel@tonic-gate	%label=();
4190Sstevel@tonic-gate	}
4200Sstevel@tonic-gate
4210Sstevel@tonic-gatesub main'function_end_A
4220Sstevel@tonic-gate	{
4230Sstevel@tonic-gate	local($func)=@_;
4240Sstevel@tonic-gate
4250Sstevel@tonic-gate	local($tmp)=<<"EOF";
4260Sstevel@tonic-gate	popl	%edi
4270Sstevel@tonic-gate	popl	%esi
4280Sstevel@tonic-gate	popl	%ebx
4290Sstevel@tonic-gate	popl	%ebp
4300Sstevel@tonic-gate	ret
4310Sstevel@tonic-gateEOF
4320Sstevel@tonic-gate	push(@out,$tmp);
4330Sstevel@tonic-gate	}
4340Sstevel@tonic-gate
4350Sstevel@tonic-gatesub main'function_end_B
4360Sstevel@tonic-gate	{
4370Sstevel@tonic-gate	local($func)=@_;
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate	$func=$under.$func;
4400Sstevel@tonic-gate
441*2139Sjp161948	push(@out,"${dot}L_${func}_end:\n");
4420Sstevel@tonic-gate	if ($main'cpp)
443*2139Sjp161948		{ push(@out,"SIZE($func,${dot}L_${func}_end-$func)\n"); }
444*2139Sjp161948        elsif ($main'coff or $main'aout)
445*2139Sjp161948                { }
446*2139Sjp161948	else	{ push(@out,".size\t$func,${dot}L_${func}_end-$func\n"); }
447*2139Sjp161948	push(@out,".ident	\"$func\"\n");
4480Sstevel@tonic-gate	$stack=0;
4490Sstevel@tonic-gate	%label=();
4500Sstevel@tonic-gate	}
4510Sstevel@tonic-gate
4520Sstevel@tonic-gatesub main'wparam
4530Sstevel@tonic-gate	{
4540Sstevel@tonic-gate	local($num)=@_;
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate	return(&main'DWP($stack+$num*4,"esp","",0));
4570Sstevel@tonic-gate	}
4580Sstevel@tonic-gate
4590Sstevel@tonic-gatesub main'stack_push
4600Sstevel@tonic-gate	{
4610Sstevel@tonic-gate	local($num)=@_;
4620Sstevel@tonic-gate	$stack+=$num*4;
4630Sstevel@tonic-gate	&main'sub("esp",$num*4);
4640Sstevel@tonic-gate	}
4650Sstevel@tonic-gate
4660Sstevel@tonic-gatesub main'stack_pop
4670Sstevel@tonic-gate	{
4680Sstevel@tonic-gate	local($num)=@_;
4690Sstevel@tonic-gate	$stack-=$num*4;
4700Sstevel@tonic-gate	&main'add("esp",$num*4);
4710Sstevel@tonic-gate	}
4720Sstevel@tonic-gate
4730Sstevel@tonic-gatesub main'swtmp
4740Sstevel@tonic-gate	{
4750Sstevel@tonic-gate	return(&main'DWP($_[0]*4,"esp","",0));
4760Sstevel@tonic-gate	}
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate# Should use swtmp, which is above esp.  Linix can trash the stack above esp
4790Sstevel@tonic-gate#sub main'wtmp
4800Sstevel@tonic-gate#	{
4810Sstevel@tonic-gate#	local($num)=@_;
4820Sstevel@tonic-gate#
4830Sstevel@tonic-gate#	return(&main'DWP(-($num+1)*4,"esp","",0));
4840Sstevel@tonic-gate#	}
4850Sstevel@tonic-gate
4860Sstevel@tonic-gatesub main'comment
4870Sstevel@tonic-gate	{
488*2139Sjp161948	if (!defined($com_start) or $main'elf)
489*2139Sjp161948		{	# Regarding $main'elf above...
490*2139Sjp161948			# GNU and SVR4 as'es use different comment delimiters,
491*2139Sjp161948		push(@out,"\n");	# so we just skip ELF comments...
4920Sstevel@tonic-gate		return;
4930Sstevel@tonic-gate		}
4940Sstevel@tonic-gate	foreach (@_)
4950Sstevel@tonic-gate		{
4960Sstevel@tonic-gate		if (/^\s*$/)
4970Sstevel@tonic-gate			{ push(@out,"\n"); }
4980Sstevel@tonic-gate		else
4990Sstevel@tonic-gate			{ push(@out,"\t$com_start $_ $com_end\n"); }
5000Sstevel@tonic-gate		}
5010Sstevel@tonic-gate	}
5020Sstevel@tonic-gate
503*2139Sjp161948sub main'public_label
504*2139Sjp161948	{
505*2139Sjp161948	$label{$_[0]}="${under}${_[0]}"	if (!defined($label{$_[0]}));
506*2139Sjp161948	push(@out,".globl\t$label{$_[0]}\n");
507*2139Sjp161948	}
508*2139Sjp161948
5090Sstevel@tonic-gatesub main'label
5100Sstevel@tonic-gate	{
5110Sstevel@tonic-gate	if (!defined($label{$_[0]}))
5120Sstevel@tonic-gate		{
513*2139Sjp161948		$label{$_[0]}="${dot}${label}${_[0]}";
5140Sstevel@tonic-gate		$label++;
5150Sstevel@tonic-gate		}
5160Sstevel@tonic-gate	return($label{$_[0]});
5170Sstevel@tonic-gate	}
5180Sstevel@tonic-gate
5190Sstevel@tonic-gatesub main'set_label
5200Sstevel@tonic-gate	{
5210Sstevel@tonic-gate	if (!defined($label{$_[0]}))
5220Sstevel@tonic-gate		{
523*2139Sjp161948		$label{$_[0]}="${dot}${label}${_[0]}";
5240Sstevel@tonic-gate		$label++;
5250Sstevel@tonic-gate		}
526*2139Sjp161948	if ($_[1]!=0)
527*2139Sjp161948		{
528*2139Sjp161948		if ($_[1]>1)	{ main'align($_[1]);		}
529*2139Sjp161948		else		{ push(@out,".align $align\n");	}
530*2139Sjp161948		}
5310Sstevel@tonic-gate	push(@out,"$label{$_[0]}:\n");
5320Sstevel@tonic-gate	}
5330Sstevel@tonic-gate
5340Sstevel@tonic-gatesub main'file_end
5350Sstevel@tonic-gate	{
536*2139Sjp161948	# try to detect if SSE2 or MMX extensions were used on ELF platform...
537*2139Sjp161948	if ($main'elf && grep {/%[x]*mm[0-7]/i} @out) {
538*2139Sjp161948		local($tmp);
539*2139Sjp161948
540*2139Sjp161948		push (@out,"\n.section\t.bss\n");
541*2139Sjp161948		push (@out,".comm\t${under}OPENSSL_ia32cap_P,4,4\n");
542*2139Sjp161948
543*2139Sjp161948		push (@out,".section\t.init\n");
544*2139Sjp161948		# One can argue that it's wasteful to craft every
545*2139Sjp161948		# SSE/MMX module with this snippet... Well, it's 72
546*2139Sjp161948		# bytes long and for the moment we have two modules.
547*2139Sjp161948		# Let's argue when we have 7 modules or so...
548*2139Sjp161948		#
549*2139Sjp161948		# $1<<10 sets a reserved bit to signal that variable
550*2139Sjp161948		# was initialized already...
551*2139Sjp161948		&main'picmeup("edx","OPENSSL_ia32cap_P");
552*2139Sjp161948		$tmp=<<___;
553*2139Sjp161948		cmpl	\$0,(%edx)
554*2139Sjp161948		jne	1f
555*2139Sjp161948		movl	\$1<<10,(%edx)
556*2139Sjp161948		pushf
557*2139Sjp161948		popl	%eax
558*2139Sjp161948		movl	%eax,%ecx
559*2139Sjp161948		xorl	\$1<<21,%eax
560*2139Sjp161948		pushl	%eax
561*2139Sjp161948		popf
562*2139Sjp161948		pushf
563*2139Sjp161948		popl	%eax
564*2139Sjp161948		xorl	%ecx,%eax
565*2139Sjp161948		btl	\$21,%eax
566*2139Sjp161948		jnc	1f
567*2139Sjp161948		pushl	%edi
568*2139Sjp161948		pushl	%ebx
569*2139Sjp161948		movl	%edx,%edi
570*2139Sjp161948		movl	\$1,%eax
571*2139Sjp161948		.byte	0x0f,0xa2
572*2139Sjp161948		orl	\$1<<10,%edx
573*2139Sjp161948		movl	%edx,0(%edi)
574*2139Sjp161948		popl	%ebx
575*2139Sjp161948		popl	%edi
576*2139Sjp161948		jmp	1f
577*2139Sjp161948	.align	$align
578*2139Sjp161948	1:
579*2139Sjp161948___
580*2139Sjp161948		push (@out,$tmp);
581*2139Sjp161948	}
582*2139Sjp161948
5830Sstevel@tonic-gate	if ($const ne "")
5840Sstevel@tonic-gate		{
5850Sstevel@tonic-gate		push(@out,".section .rodata\n");
5860Sstevel@tonic-gate		push(@out,$const);
5870Sstevel@tonic-gate		$const="";
5880Sstevel@tonic-gate		}
5890Sstevel@tonic-gate	}
5900Sstevel@tonic-gate
5910Sstevel@tonic-gatesub main'data_word
5920Sstevel@tonic-gate	{
593*2139Sjp161948	push(@out,"\t.long\t".join(',',@_)."\n");
594*2139Sjp161948	}
595*2139Sjp161948
596*2139Sjp161948sub main'align
597*2139Sjp161948	{
598*2139Sjp161948	my $val=$_[0],$p2,$i;
599*2139Sjp161948	if ($main'aout) {
600*2139Sjp161948		for ($p2=0;$val!=0;$val>>=1) { $p2++; }
601*2139Sjp161948		$val=$p2-1;
602*2139Sjp161948		$val.=",0x90";
603*2139Sjp161948	}
604*2139Sjp161948	push(@out,".align\t$val\n");
6050Sstevel@tonic-gate	}
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate# debug output functions: puts, putx, printf
6080Sstevel@tonic-gate
6090Sstevel@tonic-gatesub main'puts
6100Sstevel@tonic-gate	{
6110Sstevel@tonic-gate	&pushvars();
6120Sstevel@tonic-gate	&main'push('$Lstring' . ++$constl);
6130Sstevel@tonic-gate	&main'call('puts');
6140Sstevel@tonic-gate	$stack-=4;
6150Sstevel@tonic-gate	&main'add("esp",4);
6160Sstevel@tonic-gate	&popvars();
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate	$const .= "Lstring$constl:\n\t.string \"@_[0]\"\n";
6190Sstevel@tonic-gate	}
6200Sstevel@tonic-gate
6210Sstevel@tonic-gatesub main'putx
6220Sstevel@tonic-gate	{
6230Sstevel@tonic-gate	&pushvars();
6240Sstevel@tonic-gate	&main'push($_[0]);
6250Sstevel@tonic-gate	&main'push('$Lstring' . ++$constl);
6260Sstevel@tonic-gate	&main'call('printf');
6270Sstevel@tonic-gate	&main'add("esp",8);
6280Sstevel@tonic-gate	$stack-=8;
6290Sstevel@tonic-gate	&popvars();
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate	$const .= "Lstring$constl:\n\t.string \"\%X\"\n";
6320Sstevel@tonic-gate	}
6330Sstevel@tonic-gate
6340Sstevel@tonic-gatesub main'printf
6350Sstevel@tonic-gate	{
6360Sstevel@tonic-gate	$ostack = $stack;
6370Sstevel@tonic-gate	&pushvars();
6380Sstevel@tonic-gate	for ($i = @_ - 1; $i >= 0; $i--)
6390Sstevel@tonic-gate		{
6400Sstevel@tonic-gate		if ($i == 0) # change this to support %s format strings
6410Sstevel@tonic-gate			{
6420Sstevel@tonic-gate			&main'push('$Lstring' . ++$constl);
6430Sstevel@tonic-gate			$const .= "Lstring$constl:\n\t.string \"@_[$i]\"\n";
6440Sstevel@tonic-gate			}
6450Sstevel@tonic-gate		else
6460Sstevel@tonic-gate			{
6470Sstevel@tonic-gate			if ($_[$i] =~ /([0-9]*)\(%esp\)/)
6480Sstevel@tonic-gate				{
6490Sstevel@tonic-gate				&main'push(($1 + $stack - $ostack) . '(%esp)');
6500Sstevel@tonic-gate				}
6510Sstevel@tonic-gate			else
6520Sstevel@tonic-gate				{
6530Sstevel@tonic-gate				&main'push($_[$i]);
6540Sstevel@tonic-gate				}
6550Sstevel@tonic-gate			}
6560Sstevel@tonic-gate		}
6570Sstevel@tonic-gate	&main'call('printf');
6580Sstevel@tonic-gate	$stack-=4*@_;
6590Sstevel@tonic-gate	&main'add("esp",4*@_);
6600Sstevel@tonic-gate	&popvars();
6610Sstevel@tonic-gate	}
6620Sstevel@tonic-gate
6630Sstevel@tonic-gatesub pushvars
6640Sstevel@tonic-gate	{
6650Sstevel@tonic-gate	&main'pushf();
6660Sstevel@tonic-gate	&main'push("edx");
6670Sstevel@tonic-gate	&main'push("ecx");
6680Sstevel@tonic-gate	&main'push("eax");
6690Sstevel@tonic-gate	}
6700Sstevel@tonic-gate
6710Sstevel@tonic-gatesub popvars
6720Sstevel@tonic-gate	{
6730Sstevel@tonic-gate	&main'pop("eax");
6740Sstevel@tonic-gate	&main'pop("ecx");
6750Sstevel@tonic-gate	&main'pop("edx");
6760Sstevel@tonic-gate	&main'popf();
6770Sstevel@tonic-gate	}
6780Sstevel@tonic-gate
6790Sstevel@tonic-gatesub main'picmeup
6800Sstevel@tonic-gate	{
6810Sstevel@tonic-gate	local($dst,$sym)=@_;
6820Sstevel@tonic-gate	if ($main'cpp)
6830Sstevel@tonic-gate		{
6840Sstevel@tonic-gate		local($tmp)=<<___;
6850Sstevel@tonic-gate#if (defined(ELF) || defined(SOL)) && defined(PIC)
6860Sstevel@tonic-gate	call	1f
6870Sstevel@tonic-gate1:	popl	$regs{$dst}
6880Sstevel@tonic-gate	addl	\$_GLOBAL_OFFSET_TABLE_+[.-1b],$regs{$dst}
6890Sstevel@tonic-gate	movl	$sym\@GOT($regs{$dst}),$regs{$dst}
6900Sstevel@tonic-gate#else
6910Sstevel@tonic-gate	leal	$sym,$regs{$dst}
6920Sstevel@tonic-gate#endif
6930Sstevel@tonic-gate___
6940Sstevel@tonic-gate		push(@out,$tmp);
6950Sstevel@tonic-gate		}
6960Sstevel@tonic-gate	elsif ($main'pic && ($main'elf || $main'aout))
6970Sstevel@tonic-gate		{
6980Sstevel@tonic-gate		&main'call(&main'label("PIC_me_up"));
6990Sstevel@tonic-gate		&main'set_label("PIC_me_up");
7000Sstevel@tonic-gate		&main'blindpop($dst);
701*2139Sjp161948		&main'add($dst,"\$${under}_GLOBAL_OFFSET_TABLE_+[.-".
7020Sstevel@tonic-gate				&main'label("PIC_me_up") . "]");
703*2139Sjp161948		&main'mov($dst,&main'DWP($under.$sym."\@GOT",$dst));
7040Sstevel@tonic-gate		}
7050Sstevel@tonic-gate	else
7060Sstevel@tonic-gate		{
7070Sstevel@tonic-gate		&main'lea($dst,&main'DWP($sym));
7080Sstevel@tonic-gate		}
7090Sstevel@tonic-gate	}
7100Sstevel@tonic-gate
7110Sstevel@tonic-gatesub main'blindpop { &out1("popl",@_); }
712*2139Sjp161948
713*2139Sjp161948sub main'initseg
714*2139Sjp161948	{
715*2139Sjp161948	local($f)=@_;
716*2139Sjp161948	local($tmp);
717*2139Sjp161948	if ($main'elf)
718*2139Sjp161948		{
719*2139Sjp161948		$tmp=<<___;
720*2139Sjp161948.section	.init
721*2139Sjp161948	call	$under$f
722*2139Sjp161948	jmp	.Linitalign
723*2139Sjp161948.align	$align
724*2139Sjp161948.Linitalign:
725*2139Sjp161948___
726*2139Sjp161948		}
727*2139Sjp161948	elsif ($main'coff)
728*2139Sjp161948		{
729*2139Sjp161948		$tmp=<<___;	# applies to both Cygwin and Mingw
730*2139Sjp161948.section	.ctors
731*2139Sjp161948.long	$under$f
732*2139Sjp161948___
733*2139Sjp161948		}
734*2139Sjp161948	elsif ($main'aout)
735*2139Sjp161948		{
736*2139Sjp161948		local($ctor)="${under}_GLOBAL_\$I\$$f";
737*2139Sjp161948		$tmp=".text\n";
738*2139Sjp161948		$tmp.=".type	$ctor,\@function\n" if ($main'pic);
739*2139Sjp161948		$tmp.=<<___;	# OpenBSD way...
740*2139Sjp161948.globl	$ctor
741*2139Sjp161948.align	2
742*2139Sjp161948$ctor:
743*2139Sjp161948	jmp	$under$f
744*2139Sjp161948___
745*2139Sjp161948		}
746*2139Sjp161948	push(@out,$tmp) if ($tmp);
747*2139Sjp161948	}
748*2139Sjp161948
749*2139Sjp1619481;
750