10Sstevel@tonic-gate#!/usr/local/bin/perl 20Sstevel@tonic-gate 30Sstevel@tonic-gatepackage x86nasm; 40Sstevel@tonic-gate 50Sstevel@tonic-gate$label="L000"; 6*2139Sjp161948$under=($main'netware)?'':'_'; 70Sstevel@tonic-gate 80Sstevel@tonic-gate%lb=( 'eax', 'al', 90Sstevel@tonic-gate 'ebx', 'bl', 100Sstevel@tonic-gate 'ecx', 'cl', 110Sstevel@tonic-gate 'edx', 'dl', 120Sstevel@tonic-gate 'ax', 'al', 130Sstevel@tonic-gate 'bx', 'bl', 140Sstevel@tonic-gate 'cx', 'cl', 150Sstevel@tonic-gate 'dx', 'dl', 160Sstevel@tonic-gate ); 170Sstevel@tonic-gate 180Sstevel@tonic-gate%hb=( 'eax', 'ah', 190Sstevel@tonic-gate 'ebx', 'bh', 200Sstevel@tonic-gate 'ecx', 'ch', 210Sstevel@tonic-gate 'edx', 'dh', 220Sstevel@tonic-gate 'ax', 'ah', 230Sstevel@tonic-gate 'bx', 'bh', 240Sstevel@tonic-gate 'cx', 'ch', 250Sstevel@tonic-gate 'dx', 'dh', 260Sstevel@tonic-gate ); 270Sstevel@tonic-gate 280Sstevel@tonic-gatesub main'asm_init_output { @out=(); } 290Sstevel@tonic-gatesub main'asm_get_output { return(@out); } 300Sstevel@tonic-gatesub main'get_labels { return(@labels); } 310Sstevel@tonic-gate 320Sstevel@tonic-gatesub main'external_label 330Sstevel@tonic-gate{ 340Sstevel@tonic-gate push(@labels,@_); 350Sstevel@tonic-gate foreach (@_) { 36*2139Sjp161948 push(@out,".") if ($main'mwerks); 37*2139Sjp161948 push(@out, "extern\t${under}$_\n"); 380Sstevel@tonic-gate } 390Sstevel@tonic-gate} 400Sstevel@tonic-gate 410Sstevel@tonic-gatesub main'LB 420Sstevel@tonic-gate { 430Sstevel@tonic-gate (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n"; 440Sstevel@tonic-gate return($lb{$_[0]}); 450Sstevel@tonic-gate } 460Sstevel@tonic-gate 470Sstevel@tonic-gatesub main'HB 480Sstevel@tonic-gate { 490Sstevel@tonic-gate (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n"; 500Sstevel@tonic-gate return($hb{$_[0]}); 510Sstevel@tonic-gate } 520Sstevel@tonic-gate 530Sstevel@tonic-gatesub main'BP 540Sstevel@tonic-gate { 550Sstevel@tonic-gate &get_mem("BYTE",@_); 560Sstevel@tonic-gate } 570Sstevel@tonic-gate 580Sstevel@tonic-gatesub main'DWP 590Sstevel@tonic-gate { 600Sstevel@tonic-gate &get_mem("DWORD",@_); 610Sstevel@tonic-gate } 620Sstevel@tonic-gate 63*2139Sjp161948sub main'QWP 64*2139Sjp161948 { 65*2139Sjp161948 &get_mem("",@_); 66*2139Sjp161948 } 67*2139Sjp161948 680Sstevel@tonic-gatesub main'BC 690Sstevel@tonic-gate { 70*2139Sjp161948 return (($main'mwerks)?"":"BYTE ")."@_"; 710Sstevel@tonic-gate } 720Sstevel@tonic-gate 730Sstevel@tonic-gatesub main'DWC 740Sstevel@tonic-gate { 75*2139Sjp161948 return (($main'mwerks)?"":"DWORD ")."@_"; 760Sstevel@tonic-gate } 770Sstevel@tonic-gate 780Sstevel@tonic-gatesub main'stack_push 790Sstevel@tonic-gate { 800Sstevel@tonic-gate my($num)=@_; 810Sstevel@tonic-gate $stack+=$num*4; 820Sstevel@tonic-gate &main'sub("esp",$num*4); 830Sstevel@tonic-gate } 840Sstevel@tonic-gate 850Sstevel@tonic-gatesub main'stack_pop 860Sstevel@tonic-gate { 870Sstevel@tonic-gate my($num)=@_; 880Sstevel@tonic-gate $stack-=$num*4; 890Sstevel@tonic-gate &main'add("esp",$num*4); 900Sstevel@tonic-gate } 910Sstevel@tonic-gate 920Sstevel@tonic-gatesub get_mem 930Sstevel@tonic-gate { 940Sstevel@tonic-gate my($size,$addr,$reg1,$reg2,$idx)=@_; 950Sstevel@tonic-gate my($t,$post); 96*2139Sjp161948 my($ret)=$size; 97*2139Sjp161948 if ($ret ne "") 98*2139Sjp161948 { 99*2139Sjp161948 $ret .= " PTR" if ($main'mwerks); 100*2139Sjp161948 $ret .= " "; 101*2139Sjp161948 } 102*2139Sjp161948 $ret .= "["; 1030Sstevel@tonic-gate $addr =~ s/^\s+//; 1040Sstevel@tonic-gate if ($addr =~ /^(.+)\+(.+)$/) 1050Sstevel@tonic-gate { 1060Sstevel@tonic-gate $reg2=&conv($1); 107*2139Sjp161948 $addr="$under$2"; 1080Sstevel@tonic-gate } 109*2139Sjp161948 elsif ($addr =~ /^[_a-z][_a-z0-9]*$/i) 1100Sstevel@tonic-gate { 111*2139Sjp161948 $addr="$under$addr"; 1120Sstevel@tonic-gate } 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate if ($addr =~ /^.+\-.+$/) { $addr="($addr)"; } 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate $reg1="$regs{$reg1}" if defined($regs{$reg1}); 1170Sstevel@tonic-gate $reg2="$regs{$reg2}" if defined($regs{$reg2}); 1180Sstevel@tonic-gate if (($addr ne "") && ($addr ne 0)) 1190Sstevel@tonic-gate { 1200Sstevel@tonic-gate if ($addr !~ /^-/) 1210Sstevel@tonic-gate { $ret.="${addr}+"; } 1220Sstevel@tonic-gate else { $post=$addr; } 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate if ($reg2 ne "") 1250Sstevel@tonic-gate { 1260Sstevel@tonic-gate $t=""; 1270Sstevel@tonic-gate $t="*$idx" if ($idx != 0); 1280Sstevel@tonic-gate $reg1="+".$reg1 if ("$reg1$post" ne ""); 1290Sstevel@tonic-gate $ret.="$reg2$t$reg1$post]"; 1300Sstevel@tonic-gate } 1310Sstevel@tonic-gate else 1320Sstevel@tonic-gate { 1330Sstevel@tonic-gate $ret.="$reg1$post]" 1340Sstevel@tonic-gate } 1350Sstevel@tonic-gate $ret =~ s/\+\]/]/; # in case $addr was the only argument 1360Sstevel@tonic-gate return($ret); 1370Sstevel@tonic-gate } 1380Sstevel@tonic-gate 1390Sstevel@tonic-gatesub main'mov { &out2("mov",@_); } 1400Sstevel@tonic-gatesub main'movb { &out2("mov",@_); } 1410Sstevel@tonic-gatesub main'and { &out2("and",@_); } 1420Sstevel@tonic-gatesub main'or { &out2("or",@_); } 1430Sstevel@tonic-gatesub main'shl { &out2("shl",@_); } 1440Sstevel@tonic-gatesub main'shr { &out2("shr",@_); } 1450Sstevel@tonic-gatesub main'xor { &out2("xor",@_); } 1460Sstevel@tonic-gatesub main'xorb { &out2("xor",@_); } 1470Sstevel@tonic-gatesub main'add { &out2("add",@_); } 1480Sstevel@tonic-gatesub main'adc { &out2("adc",@_); } 1490Sstevel@tonic-gatesub main'sub { &out2("sub",@_); } 150*2139Sjp161948sub main'sbb { &out2("sbb",@_); } 1510Sstevel@tonic-gatesub main'rotl { &out2("rol",@_); } 1520Sstevel@tonic-gatesub main'rotr { &out2("ror",@_); } 1530Sstevel@tonic-gatesub main'exch { &out2("xchg",@_); } 1540Sstevel@tonic-gatesub main'cmp { &out2("cmp",@_); } 1550Sstevel@tonic-gatesub main'lea { &out2("lea",@_); } 1560Sstevel@tonic-gatesub main'mul { &out1("mul",@_); } 1570Sstevel@tonic-gatesub main'div { &out1("div",@_); } 1580Sstevel@tonic-gatesub main'dec { &out1("dec",@_); } 1590Sstevel@tonic-gatesub main'inc { &out1("inc",@_); } 1600Sstevel@tonic-gatesub main'jmp { &out1("jmp",@_); } 1610Sstevel@tonic-gatesub main'jmp_ptr { &out1p("jmp",@_); } 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate# This is a bit of a kludge: declare all branches as NEAR. 164*2139Sjp161948$near=($main'mwerks)?'':'NEAR'; 165*2139Sjp161948sub main'je { &out1("je $near",@_); } 166*2139Sjp161948sub main'jle { &out1("jle $near",@_); } 167*2139Sjp161948sub main'jz { &out1("jz $near",@_); } 168*2139Sjp161948sub main'jge { &out1("jge $near",@_); } 169*2139Sjp161948sub main'jl { &out1("jl $near",@_); } 170*2139Sjp161948sub main'ja { &out1("ja $near",@_); } 171*2139Sjp161948sub main'jae { &out1("jae $near",@_); } 172*2139Sjp161948sub main'jb { &out1("jb $near",@_); } 173*2139Sjp161948sub main'jbe { &out1("jbe $near",@_); } 174*2139Sjp161948sub main'jc { &out1("jc $near",@_); } 175*2139Sjp161948sub main'jnc { &out1("jnc $near",@_); } 176*2139Sjp161948sub main'jnz { &out1("jnz $near",@_); } 177*2139Sjp161948sub main'jne { &out1("jne $near",@_); } 178*2139Sjp161948sub main'jno { &out1("jno $near",@_); } 1790Sstevel@tonic-gate 1800Sstevel@tonic-gatesub main'push { &out1("push",@_); $stack+=4; } 1810Sstevel@tonic-gatesub main'pop { &out1("pop",@_); $stack-=4; } 182*2139Sjp161948sub main'pushf { &out0("pushfd"); $stack+=4; } 183*2139Sjp161948sub main'popf { &out0("popfd"); $stack-=4; } 1840Sstevel@tonic-gatesub main'bswap { &out1("bswap",@_); &using486(); } 1850Sstevel@tonic-gatesub main'not { &out1("not",@_); } 186*2139Sjp161948sub main'call { &out1("call",($_[0]=~/^\@L/?'':$under).$_[0]); } 1870Sstevel@tonic-gatesub main'ret { &out0("ret"); } 1880Sstevel@tonic-gatesub main'nop { &out0("nop"); } 189*2139Sjp161948sub main'test { &out2("test",@_); } 190*2139Sjp161948sub main'bt { &out2("bt",@_); } 191*2139Sjp161948sub main'leave { &out0("leave"); } 192*2139Sjp161948sub main'cpuid { &out0("cpuid"); } 193*2139Sjp161948sub main'rdtsc { &out0("rdtsc"); } 194*2139Sjp161948sub main'halt { &out0("hlt"); } 195*2139Sjp161948sub main'movz { &out2("movzx",@_); } 196*2139Sjp161948sub main'neg { &out1("neg",@_); } 197*2139Sjp161948sub main'cld { &out0("cld"); } 198*2139Sjp161948 199*2139Sjp161948# SSE2 200*2139Sjp161948sub main'emms { &out0("emms"); } 201*2139Sjp161948sub main'movd { &out2("movd",@_); } 202*2139Sjp161948sub main'movq { &out2("movq",@_); } 203*2139Sjp161948sub main'movdqu { &out2("movdqu",@_); } 204*2139Sjp161948sub main'movdqa { &out2("movdqa",@_); } 205*2139Sjp161948sub main'movdq2q{ &out2("movdq2q",@_); } 206*2139Sjp161948sub main'movq2dq{ &out2("movq2dq",@_); } 207*2139Sjp161948sub main'paddq { &out2("paddq",@_); } 208*2139Sjp161948sub main'pmuludq{ &out2("pmuludq",@_); } 209*2139Sjp161948sub main'psrlq { &out2("psrlq",@_); } 210*2139Sjp161948sub main'psllq { &out2("psllq",@_); } 211*2139Sjp161948sub main'pxor { &out2("pxor",@_); } 212*2139Sjp161948sub main'por { &out2("por",@_); } 213*2139Sjp161948sub main'pand { &out2("pand",@_); } 2140Sstevel@tonic-gate 2150Sstevel@tonic-gatesub out2 2160Sstevel@tonic-gate { 2170Sstevel@tonic-gate my($name,$p1,$p2)=@_; 2180Sstevel@tonic-gate my($l,$t); 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate push(@out,"\t$name\t"); 221*2139Sjp161948 if (!$main'mwerks and $name eq "lea") 222*2139Sjp161948 { 223*2139Sjp161948 $p1 =~ s/^[^\[]*\[/\[/; 224*2139Sjp161948 $p2 =~ s/^[^\[]*\[/\[/; 225*2139Sjp161948 } 2260Sstevel@tonic-gate $t=&conv($p1).","; 2270Sstevel@tonic-gate $l=length($t); 2280Sstevel@tonic-gate push(@out,$t); 2290Sstevel@tonic-gate $l=4-($l+9)/8; 2300Sstevel@tonic-gate push(@out,"\t" x $l); 2310Sstevel@tonic-gate push(@out,&conv($p2)); 2320Sstevel@tonic-gate push(@out,"\n"); 2330Sstevel@tonic-gate } 2340Sstevel@tonic-gate 2350Sstevel@tonic-gatesub out0 2360Sstevel@tonic-gate { 2370Sstevel@tonic-gate my($name)=@_; 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate push(@out,"\t$name\n"); 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate 2420Sstevel@tonic-gatesub out1 2430Sstevel@tonic-gate { 2440Sstevel@tonic-gate my($name,$p1)=@_; 2450Sstevel@tonic-gate my($l,$t); 2460Sstevel@tonic-gate push(@out,"\t$name\t".&conv($p1)."\n"); 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate 2490Sstevel@tonic-gatesub conv 2500Sstevel@tonic-gate { 2510Sstevel@tonic-gate my($p)=@_; 2520Sstevel@tonic-gate $p =~ s/0x([0-9A-Fa-f]+)/0$1h/; 2530Sstevel@tonic-gate return $p; 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate 2560Sstevel@tonic-gatesub using486 2570Sstevel@tonic-gate { 2580Sstevel@tonic-gate return if $using486; 2590Sstevel@tonic-gate $using486++; 2600Sstevel@tonic-gate grep(s/\.386/\.486/,@out); 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate 2630Sstevel@tonic-gatesub main'file 2640Sstevel@tonic-gate { 265*2139Sjp161948 if ($main'mwerks) { push(@out,".section\t.text\n"); } 266*2139Sjp161948 else { 267*2139Sjp161948 local $tmp=<<___; 268*2139Sjp161948%ifdef __omf__ 269*2139Sjp161948section code use32 class=code 270*2139Sjp161948%else 271*2139Sjp161948section .text 272*2139Sjp161948%endif 273*2139Sjp161948___ 274*2139Sjp161948 push(@out,$tmp); 275*2139Sjp161948 } 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2780Sstevel@tonic-gatesub main'function_begin 2790Sstevel@tonic-gate { 2800Sstevel@tonic-gate my($func,$extra)=@_; 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate push(@labels,$func); 2830Sstevel@tonic-gate my($tmp)=<<"EOF"; 284*2139Sjp161948global $under$func 285*2139Sjp161948$under$func: 2860Sstevel@tonic-gate push ebp 2870Sstevel@tonic-gate push ebx 2880Sstevel@tonic-gate push esi 2890Sstevel@tonic-gate push edi 2900Sstevel@tonic-gateEOF 2910Sstevel@tonic-gate push(@out,$tmp); 2920Sstevel@tonic-gate $stack=20; 2930Sstevel@tonic-gate } 2940Sstevel@tonic-gate 2950Sstevel@tonic-gatesub main'function_begin_B 2960Sstevel@tonic-gate { 2970Sstevel@tonic-gate my($func,$extra)=@_; 2980Sstevel@tonic-gate my($tmp)=<<"EOF"; 299*2139Sjp161948global $under$func 300*2139Sjp161948$under$func: 3010Sstevel@tonic-gateEOF 3020Sstevel@tonic-gate push(@out,$tmp); 3030Sstevel@tonic-gate $stack=4; 3040Sstevel@tonic-gate } 3050Sstevel@tonic-gate 3060Sstevel@tonic-gatesub main'function_end 3070Sstevel@tonic-gate { 3080Sstevel@tonic-gate my($func)=@_; 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate my($tmp)=<<"EOF"; 3110Sstevel@tonic-gate pop edi 3120Sstevel@tonic-gate pop esi 3130Sstevel@tonic-gate pop ebx 3140Sstevel@tonic-gate pop ebp 3150Sstevel@tonic-gate ret 3160Sstevel@tonic-gateEOF 3170Sstevel@tonic-gate push(@out,$tmp); 3180Sstevel@tonic-gate $stack=0; 3190Sstevel@tonic-gate %label=(); 3200Sstevel@tonic-gate } 3210Sstevel@tonic-gate 3220Sstevel@tonic-gatesub main'function_end_B 3230Sstevel@tonic-gate { 3240Sstevel@tonic-gate $stack=0; 3250Sstevel@tonic-gate %label=(); 3260Sstevel@tonic-gate } 3270Sstevel@tonic-gate 3280Sstevel@tonic-gatesub main'function_end_A 3290Sstevel@tonic-gate { 3300Sstevel@tonic-gate my($func)=@_; 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate my($tmp)=<<"EOF"; 3330Sstevel@tonic-gate pop edi 3340Sstevel@tonic-gate pop esi 3350Sstevel@tonic-gate pop ebx 3360Sstevel@tonic-gate pop ebp 3370Sstevel@tonic-gate ret 3380Sstevel@tonic-gateEOF 3390Sstevel@tonic-gate push(@out,$tmp); 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate 3420Sstevel@tonic-gatesub main'file_end 3430Sstevel@tonic-gate { 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate 3460Sstevel@tonic-gatesub main'wparam 3470Sstevel@tonic-gate { 3480Sstevel@tonic-gate my($num)=@_; 3490Sstevel@tonic-gate 3500Sstevel@tonic-gate return(&main'DWP($stack+$num*4,"esp","",0)); 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate 3530Sstevel@tonic-gatesub main'swtmp 3540Sstevel@tonic-gate { 3550Sstevel@tonic-gate return(&main'DWP($_[0]*4,"esp","",0)); 3560Sstevel@tonic-gate } 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate# Should use swtmp, which is above esp. Linix can trash the stack above esp 3590Sstevel@tonic-gate#sub main'wtmp 3600Sstevel@tonic-gate# { 3610Sstevel@tonic-gate# my($num)=@_; 3620Sstevel@tonic-gate# 3630Sstevel@tonic-gate# return(&main'DWP(-(($num+1)*4),"esp","",0)); 3640Sstevel@tonic-gate# } 3650Sstevel@tonic-gate 3660Sstevel@tonic-gatesub main'comment 3670Sstevel@tonic-gate { 3680Sstevel@tonic-gate foreach (@_) 3690Sstevel@tonic-gate { 3700Sstevel@tonic-gate push(@out,"\t; $_\n"); 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate } 3730Sstevel@tonic-gate 374*2139Sjp161948sub main'public_label 375*2139Sjp161948 { 376*2139Sjp161948 $label{$_[0]}="${under}${_[0]}" if (!defined($label{$_[0]})); 377*2139Sjp161948 push(@out,"global\t$label{$_[0]}\n"); 378*2139Sjp161948 } 379*2139Sjp161948 3800Sstevel@tonic-gatesub main'label 3810Sstevel@tonic-gate { 3820Sstevel@tonic-gate if (!defined($label{$_[0]})) 3830Sstevel@tonic-gate { 384*2139Sjp161948 $label{$_[0]}="\@${label}${_[0]}"; 3850Sstevel@tonic-gate $label++; 3860Sstevel@tonic-gate } 3870Sstevel@tonic-gate return($label{$_[0]}); 3880Sstevel@tonic-gate } 3890Sstevel@tonic-gate 3900Sstevel@tonic-gatesub main'set_label 3910Sstevel@tonic-gate { 3920Sstevel@tonic-gate if (!defined($label{$_[0]})) 3930Sstevel@tonic-gate { 394*2139Sjp161948 $label{$_[0]}="\@${label}${_[0]}"; 3950Sstevel@tonic-gate $label++; 3960Sstevel@tonic-gate } 397*2139Sjp161948 if ($_[1]!=0 && $_[1]>1) 398*2139Sjp161948 { 399*2139Sjp161948 main'align($_[1]); 400*2139Sjp161948 } 4010Sstevel@tonic-gate push(@out,"$label{$_[0]}:\n"); 4020Sstevel@tonic-gate } 4030Sstevel@tonic-gate 4040Sstevel@tonic-gatesub main'data_word 4050Sstevel@tonic-gate { 406*2139Sjp161948 push(@out,(($main'mwerks)?".long\t":"DD\t").join(',',@_)."\n"); 407*2139Sjp161948 } 408*2139Sjp161948 409*2139Sjp161948sub main'align 410*2139Sjp161948 { 411*2139Sjp161948 push(@out,".") if ($main'mwerks); 412*2139Sjp161948 push(@out,"align\t$_[0]\n"); 4130Sstevel@tonic-gate } 4140Sstevel@tonic-gate 4150Sstevel@tonic-gatesub out1p 4160Sstevel@tonic-gate { 4170Sstevel@tonic-gate my($name,$p1)=@_; 4180Sstevel@tonic-gate my($l,$t); 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate push(@out,"\t$name\t ".&conv($p1)."\n"); 4210Sstevel@tonic-gate } 4220Sstevel@tonic-gate 4230Sstevel@tonic-gatesub main'picmeup 4240Sstevel@tonic-gate { 4250Sstevel@tonic-gate local($dst,$sym)=@_; 4260Sstevel@tonic-gate &main'lea($dst,&main'DWP($sym)); 4270Sstevel@tonic-gate } 4280Sstevel@tonic-gate 4290Sstevel@tonic-gatesub main'blindpop { &out1("pop",@_); } 430*2139Sjp161948 431*2139Sjp161948sub main'initseg 432*2139Sjp161948 { 433*2139Sjp161948 local($f)=@_; 434*2139Sjp161948 if ($main'win32) 435*2139Sjp161948 { 436*2139Sjp161948 local($tmp)=<<___; 437*2139Sjp161948segment .CRT\$XIU data 438*2139Sjp161948extern $under$f 439*2139Sjp161948DD $under$f 440*2139Sjp161948___ 441*2139Sjp161948 push(@out,$tmp); 442*2139Sjp161948 } 443*2139Sjp161948 } 444*2139Sjp161948 445*2139Sjp1619481; 446