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