1*0Sstevel@tonic-gate#!/usr/local/bin/perl 2*0Sstevel@tonic-gate 3*0Sstevel@tonic-gatepackage x86nasm; 4*0Sstevel@tonic-gate 5*0Sstevel@tonic-gate$label="L000"; 6*0Sstevel@tonic-gate 7*0Sstevel@tonic-gate%lb=( 'eax', 'al', 8*0Sstevel@tonic-gate 'ebx', 'bl', 9*0Sstevel@tonic-gate 'ecx', 'cl', 10*0Sstevel@tonic-gate 'edx', 'dl', 11*0Sstevel@tonic-gate 'ax', 'al', 12*0Sstevel@tonic-gate 'bx', 'bl', 13*0Sstevel@tonic-gate 'cx', 'cl', 14*0Sstevel@tonic-gate 'dx', 'dl', 15*0Sstevel@tonic-gate ); 16*0Sstevel@tonic-gate 17*0Sstevel@tonic-gate%hb=( 'eax', 'ah', 18*0Sstevel@tonic-gate 'ebx', 'bh', 19*0Sstevel@tonic-gate 'ecx', 'ch', 20*0Sstevel@tonic-gate 'edx', 'dh', 21*0Sstevel@tonic-gate 'ax', 'ah', 22*0Sstevel@tonic-gate 'bx', 'bh', 23*0Sstevel@tonic-gate 'cx', 'ch', 24*0Sstevel@tonic-gate 'dx', 'dh', 25*0Sstevel@tonic-gate ); 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gatesub main'asm_init_output { @out=(); } 28*0Sstevel@tonic-gatesub main'asm_get_output { return(@out); } 29*0Sstevel@tonic-gatesub main'get_labels { return(@labels); } 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gatesub main'external_label 32*0Sstevel@tonic-gate{ 33*0Sstevel@tonic-gate push(@labels,@_); 34*0Sstevel@tonic-gate foreach (@_) { 35*0Sstevel@tonic-gate push(@out, "extern\t_$_\n"); 36*0Sstevel@tonic-gate } 37*0Sstevel@tonic-gate} 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gatesub main'LB 40*0Sstevel@tonic-gate { 41*0Sstevel@tonic-gate (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n"; 42*0Sstevel@tonic-gate return($lb{$_[0]}); 43*0Sstevel@tonic-gate } 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gatesub main'HB 46*0Sstevel@tonic-gate { 47*0Sstevel@tonic-gate (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n"; 48*0Sstevel@tonic-gate return($hb{$_[0]}); 49*0Sstevel@tonic-gate } 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gatesub main'BP 52*0Sstevel@tonic-gate { 53*0Sstevel@tonic-gate &get_mem("BYTE",@_); 54*0Sstevel@tonic-gate } 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gatesub main'DWP 57*0Sstevel@tonic-gate { 58*0Sstevel@tonic-gate &get_mem("DWORD",@_); 59*0Sstevel@tonic-gate } 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gatesub main'BC 62*0Sstevel@tonic-gate { 63*0Sstevel@tonic-gate return "BYTE @_"; 64*0Sstevel@tonic-gate } 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gatesub main'DWC 67*0Sstevel@tonic-gate { 68*0Sstevel@tonic-gate return "DWORD @_"; 69*0Sstevel@tonic-gate } 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gatesub main'stack_push 72*0Sstevel@tonic-gate { 73*0Sstevel@tonic-gate my($num)=@_; 74*0Sstevel@tonic-gate $stack+=$num*4; 75*0Sstevel@tonic-gate &main'sub("esp",$num*4); 76*0Sstevel@tonic-gate } 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gatesub main'stack_pop 79*0Sstevel@tonic-gate { 80*0Sstevel@tonic-gate my($num)=@_; 81*0Sstevel@tonic-gate $stack-=$num*4; 82*0Sstevel@tonic-gate &main'add("esp",$num*4); 83*0Sstevel@tonic-gate } 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gatesub get_mem 86*0Sstevel@tonic-gate { 87*0Sstevel@tonic-gate my($size,$addr,$reg1,$reg2,$idx)=@_; 88*0Sstevel@tonic-gate my($t,$post); 89*0Sstevel@tonic-gate my($ret)="["; 90*0Sstevel@tonic-gate $addr =~ s/^\s+//; 91*0Sstevel@tonic-gate if ($addr =~ /^(.+)\+(.+)$/) 92*0Sstevel@tonic-gate { 93*0Sstevel@tonic-gate $reg2=&conv($1); 94*0Sstevel@tonic-gate $addr="_$2"; 95*0Sstevel@tonic-gate } 96*0Sstevel@tonic-gate elsif ($addr =~ /^[_a-zA-Z]/) 97*0Sstevel@tonic-gate { 98*0Sstevel@tonic-gate $addr="_$addr"; 99*0Sstevel@tonic-gate } 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate if ($addr =~ /^.+\-.+$/) { $addr="($addr)"; } 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate $reg1="$regs{$reg1}" if defined($regs{$reg1}); 104*0Sstevel@tonic-gate $reg2="$regs{$reg2}" if defined($regs{$reg2}); 105*0Sstevel@tonic-gate if (($addr ne "") && ($addr ne 0)) 106*0Sstevel@tonic-gate { 107*0Sstevel@tonic-gate if ($addr !~ /^-/) 108*0Sstevel@tonic-gate { $ret.="${addr}+"; } 109*0Sstevel@tonic-gate else { $post=$addr; } 110*0Sstevel@tonic-gate } 111*0Sstevel@tonic-gate if ($reg2 ne "") 112*0Sstevel@tonic-gate { 113*0Sstevel@tonic-gate $t=""; 114*0Sstevel@tonic-gate $t="*$idx" if ($idx != 0); 115*0Sstevel@tonic-gate $reg1="+".$reg1 if ("$reg1$post" ne ""); 116*0Sstevel@tonic-gate $ret.="$reg2$t$reg1$post]"; 117*0Sstevel@tonic-gate } 118*0Sstevel@tonic-gate else 119*0Sstevel@tonic-gate { 120*0Sstevel@tonic-gate $ret.="$reg1$post]" 121*0Sstevel@tonic-gate } 122*0Sstevel@tonic-gate $ret =~ s/\+\]/]/; # in case $addr was the only argument 123*0Sstevel@tonic-gate return($ret); 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gatesub main'mov { &out2("mov",@_); } 127*0Sstevel@tonic-gatesub main'movb { &out2("mov",@_); } 128*0Sstevel@tonic-gatesub main'and { &out2("and",@_); } 129*0Sstevel@tonic-gatesub main'or { &out2("or",@_); } 130*0Sstevel@tonic-gatesub main'shl { &out2("shl",@_); } 131*0Sstevel@tonic-gatesub main'shr { &out2("shr",@_); } 132*0Sstevel@tonic-gatesub main'xor { &out2("xor",@_); } 133*0Sstevel@tonic-gatesub main'xorb { &out2("xor",@_); } 134*0Sstevel@tonic-gatesub main'add { &out2("add",@_); } 135*0Sstevel@tonic-gatesub main'adc { &out2("adc",@_); } 136*0Sstevel@tonic-gatesub main'sub { &out2("sub",@_); } 137*0Sstevel@tonic-gatesub main'rotl { &out2("rol",@_); } 138*0Sstevel@tonic-gatesub main'rotr { &out2("ror",@_); } 139*0Sstevel@tonic-gatesub main'exch { &out2("xchg",@_); } 140*0Sstevel@tonic-gatesub main'cmp { &out2("cmp",@_); } 141*0Sstevel@tonic-gatesub main'lea { &out2("lea",@_); } 142*0Sstevel@tonic-gatesub main'mul { &out1("mul",@_); } 143*0Sstevel@tonic-gatesub main'div { &out1("div",@_); } 144*0Sstevel@tonic-gatesub main'dec { &out1("dec",@_); } 145*0Sstevel@tonic-gatesub main'inc { &out1("inc",@_); } 146*0Sstevel@tonic-gatesub main'jmp { &out1("jmp",@_); } 147*0Sstevel@tonic-gatesub main'jmp_ptr { &out1p("jmp",@_); } 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate# This is a bit of a kludge: declare all branches as NEAR. 150*0Sstevel@tonic-gatesub main'je { &out1("je NEAR",@_); } 151*0Sstevel@tonic-gatesub main'jle { &out1("jle NEAR",@_); } 152*0Sstevel@tonic-gatesub main'jz { &out1("jz NEAR",@_); } 153*0Sstevel@tonic-gatesub main'jge { &out1("jge NEAR",@_); } 154*0Sstevel@tonic-gatesub main'jl { &out1("jl NEAR",@_); } 155*0Sstevel@tonic-gatesub main'ja { &out1("ja NEAR",@_); } 156*0Sstevel@tonic-gatesub main'jae { &out1("jae NEAR",@_); } 157*0Sstevel@tonic-gatesub main'jb { &out1("jb NEAR",@_); } 158*0Sstevel@tonic-gatesub main'jbe { &out1("jbe NEAR",@_); } 159*0Sstevel@tonic-gatesub main'jc { &out1("jc NEAR",@_); } 160*0Sstevel@tonic-gatesub main'jnc { &out1("jnc NEAR",@_); } 161*0Sstevel@tonic-gatesub main'jnz { &out1("jnz NEAR",@_); } 162*0Sstevel@tonic-gatesub main'jne { &out1("jne NEAR",@_); } 163*0Sstevel@tonic-gatesub main'jno { &out1("jno NEAR",@_); } 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gatesub main'push { &out1("push",@_); $stack+=4; } 166*0Sstevel@tonic-gatesub main'pop { &out1("pop",@_); $stack-=4; } 167*0Sstevel@tonic-gatesub main'bswap { &out1("bswap",@_); &using486(); } 168*0Sstevel@tonic-gatesub main'not { &out1("not",@_); } 169*0Sstevel@tonic-gatesub main'call { &out1("call",($_[0]=~/^\$L/?'':'_').$_[0]); } 170*0Sstevel@tonic-gatesub main'ret { &out0("ret"); } 171*0Sstevel@tonic-gatesub main'nop { &out0("nop"); } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gatesub out2 174*0Sstevel@tonic-gate { 175*0Sstevel@tonic-gate my($name,$p1,$p2)=@_; 176*0Sstevel@tonic-gate my($l,$t); 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate push(@out,"\t$name\t"); 179*0Sstevel@tonic-gate $t=&conv($p1).","; 180*0Sstevel@tonic-gate $l=length($t); 181*0Sstevel@tonic-gate push(@out,$t); 182*0Sstevel@tonic-gate $l=4-($l+9)/8; 183*0Sstevel@tonic-gate push(@out,"\t" x $l); 184*0Sstevel@tonic-gate push(@out,&conv($p2)); 185*0Sstevel@tonic-gate push(@out,"\n"); 186*0Sstevel@tonic-gate } 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gatesub out0 189*0Sstevel@tonic-gate { 190*0Sstevel@tonic-gate my($name)=@_; 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate push(@out,"\t$name\n"); 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gatesub out1 196*0Sstevel@tonic-gate { 197*0Sstevel@tonic-gate my($name,$p1)=@_; 198*0Sstevel@tonic-gate my($l,$t); 199*0Sstevel@tonic-gate push(@out,"\t$name\t".&conv($p1)."\n"); 200*0Sstevel@tonic-gate } 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gatesub conv 203*0Sstevel@tonic-gate { 204*0Sstevel@tonic-gate my($p)=@_; 205*0Sstevel@tonic-gate $p =~ s/0x([0-9A-Fa-f]+)/0$1h/; 206*0Sstevel@tonic-gate return $p; 207*0Sstevel@tonic-gate } 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gatesub using486 210*0Sstevel@tonic-gate { 211*0Sstevel@tonic-gate return if $using486; 212*0Sstevel@tonic-gate $using486++; 213*0Sstevel@tonic-gate grep(s/\.386/\.486/,@out); 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gatesub main'file 217*0Sstevel@tonic-gate { 218*0Sstevel@tonic-gate push(@out, "segment .text use32\n"); 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gatesub main'function_begin 222*0Sstevel@tonic-gate { 223*0Sstevel@tonic-gate my($func,$extra)=@_; 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate push(@labels,$func); 226*0Sstevel@tonic-gate my($tmp)=<<"EOF"; 227*0Sstevel@tonic-gateglobal _$func 228*0Sstevel@tonic-gate_$func: 229*0Sstevel@tonic-gate push ebp 230*0Sstevel@tonic-gate push ebx 231*0Sstevel@tonic-gate push esi 232*0Sstevel@tonic-gate push edi 233*0Sstevel@tonic-gateEOF 234*0Sstevel@tonic-gate push(@out,$tmp); 235*0Sstevel@tonic-gate $stack=20; 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gatesub main'function_begin_B 239*0Sstevel@tonic-gate { 240*0Sstevel@tonic-gate my($func,$extra)=@_; 241*0Sstevel@tonic-gate my($tmp)=<<"EOF"; 242*0Sstevel@tonic-gateglobal _$func 243*0Sstevel@tonic-gate_$func: 244*0Sstevel@tonic-gateEOF 245*0Sstevel@tonic-gate push(@out,$tmp); 246*0Sstevel@tonic-gate $stack=4; 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gatesub main'function_end 250*0Sstevel@tonic-gate { 251*0Sstevel@tonic-gate my($func)=@_; 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate my($tmp)=<<"EOF"; 254*0Sstevel@tonic-gate pop edi 255*0Sstevel@tonic-gate pop esi 256*0Sstevel@tonic-gate pop ebx 257*0Sstevel@tonic-gate pop ebp 258*0Sstevel@tonic-gate ret 259*0Sstevel@tonic-gateEOF 260*0Sstevel@tonic-gate push(@out,$tmp); 261*0Sstevel@tonic-gate $stack=0; 262*0Sstevel@tonic-gate %label=(); 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gatesub main'function_end_B 266*0Sstevel@tonic-gate { 267*0Sstevel@tonic-gate $stack=0; 268*0Sstevel@tonic-gate %label=(); 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gatesub main'function_end_A 272*0Sstevel@tonic-gate { 273*0Sstevel@tonic-gate my($func)=@_; 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate my($tmp)=<<"EOF"; 276*0Sstevel@tonic-gate pop edi 277*0Sstevel@tonic-gate pop esi 278*0Sstevel@tonic-gate pop ebx 279*0Sstevel@tonic-gate pop ebp 280*0Sstevel@tonic-gate ret 281*0Sstevel@tonic-gateEOF 282*0Sstevel@tonic-gate push(@out,$tmp); 283*0Sstevel@tonic-gate } 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gatesub main'file_end 286*0Sstevel@tonic-gate { 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gatesub main'wparam 290*0Sstevel@tonic-gate { 291*0Sstevel@tonic-gate my($num)=@_; 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate return(&main'DWP($stack+$num*4,"esp","",0)); 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gatesub main'swtmp 297*0Sstevel@tonic-gate { 298*0Sstevel@tonic-gate return(&main'DWP($_[0]*4,"esp","",0)); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate# Should use swtmp, which is above esp. Linix can trash the stack above esp 302*0Sstevel@tonic-gate#sub main'wtmp 303*0Sstevel@tonic-gate# { 304*0Sstevel@tonic-gate# my($num)=@_; 305*0Sstevel@tonic-gate# 306*0Sstevel@tonic-gate# return(&main'DWP(-(($num+1)*4),"esp","",0)); 307*0Sstevel@tonic-gate# } 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gatesub main'comment 310*0Sstevel@tonic-gate { 311*0Sstevel@tonic-gate foreach (@_) 312*0Sstevel@tonic-gate { 313*0Sstevel@tonic-gate push(@out,"\t; $_\n"); 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate } 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gatesub main'label 318*0Sstevel@tonic-gate { 319*0Sstevel@tonic-gate if (!defined($label{$_[0]})) 320*0Sstevel@tonic-gate { 321*0Sstevel@tonic-gate $label{$_[0]}="\$${label}${_[0]}"; 322*0Sstevel@tonic-gate $label++; 323*0Sstevel@tonic-gate } 324*0Sstevel@tonic-gate return($label{$_[0]}); 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gatesub main'set_label 328*0Sstevel@tonic-gate { 329*0Sstevel@tonic-gate if (!defined($label{$_[0]})) 330*0Sstevel@tonic-gate { 331*0Sstevel@tonic-gate $label{$_[0]}="\$${label}${_[0]}"; 332*0Sstevel@tonic-gate $label++; 333*0Sstevel@tonic-gate } 334*0Sstevel@tonic-gate push(@out,"$label{$_[0]}:\n"); 335*0Sstevel@tonic-gate } 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gatesub main'data_word 338*0Sstevel@tonic-gate { 339*0Sstevel@tonic-gate push(@out,"\tDD\t$_[0]\n"); 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gatesub out1p 343*0Sstevel@tonic-gate { 344*0Sstevel@tonic-gate my($name,$p1)=@_; 345*0Sstevel@tonic-gate my($l,$t); 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate push(@out,"\t$name\t ".&conv($p1)."\n"); 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gatesub main'picmeup 351*0Sstevel@tonic-gate { 352*0Sstevel@tonic-gate local($dst,$sym)=@_; 353*0Sstevel@tonic-gate &main'lea($dst,&main'DWP($sym)); 354*0Sstevel@tonic-gate } 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gatesub main'blindpop { &out1("pop",@_); } 357