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