1#!/usr/local/bin/perl 2 3package x86nasm; 4 5$label="L000"; 6$under=($main'netware)?'':'_'; 7 8%lb=( 'eax', 'al', 9 'ebx', 'bl', 10 'ecx', 'cl', 11 'edx', 'dl', 12 'ax', 'al', 13 'bx', 'bl', 14 'cx', 'cl', 15 'dx', 'dl', 16 ); 17 18%hb=( 'eax', 'ah', 19 'ebx', 'bh', 20 'ecx', 'ch', 21 'edx', 'dh', 22 'ax', 'ah', 23 'bx', 'bh', 24 'cx', 'ch', 25 'dx', 'dh', 26 ); 27 28sub main'asm_init_output { @out=(); } 29sub main'asm_get_output { return(@out); } 30sub main'get_labels { return(@labels); } 31 32sub main'external_label 33{ 34 push(@labels,@_); 35 foreach (@_) { 36 push(@out,".") if ($main'mwerks); 37 push(@out, "extern\t${under}$_\n"); 38 } 39} 40 41sub main'LB 42 { 43 (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n"; 44 return($lb{$_[0]}); 45 } 46 47sub main'HB 48 { 49 (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n"; 50 return($hb{$_[0]}); 51 } 52 53sub main'BP 54 { 55 &get_mem("BYTE",@_); 56 } 57 58sub main'DWP 59 { 60 &get_mem("DWORD",@_); 61 } 62 63sub main'QWP 64 { 65 &get_mem("",@_); 66 } 67 68sub main'BC 69 { 70 return (($main'mwerks)?"":"BYTE ")."@_"; 71 } 72 73sub main'DWC 74 { 75 return (($main'mwerks)?"":"DWORD ")."@_"; 76 } 77 78sub main'stack_push 79 { 80 my($num)=@_; 81 $stack+=$num*4; 82 &main'sub("esp",$num*4); 83 } 84 85sub main'stack_pop 86 { 87 my($num)=@_; 88 $stack-=$num*4; 89 &main'add("esp",$num*4); 90 } 91 92sub get_mem 93 { 94 my($size,$addr,$reg1,$reg2,$idx)=@_; 95 my($t,$post); 96 my($ret)=$size; 97 if ($ret ne "") 98 { 99 $ret .= " PTR" if ($main'mwerks); 100 $ret .= " "; 101 } 102 $ret .= "["; 103 $addr =~ s/^\s+//; 104 if ($addr =~ /^(.+)\+(.+)$/) 105 { 106 $reg2=&conv($1); 107 $addr="$under$2"; 108 } 109 elsif ($addr =~ /^[_a-z][_a-z0-9]*$/i) 110 { 111 $addr="$under$addr"; 112 } 113 114 if ($addr =~ /^.+\-.+$/) { $addr="($addr)"; } 115 116 $reg1="$regs{$reg1}" if defined($regs{$reg1}); 117 $reg2="$regs{$reg2}" if defined($regs{$reg2}); 118 if (($addr ne "") && ($addr ne 0)) 119 { 120 if ($addr !~ /^-/) 121 { $ret.="${addr}+"; } 122 else { $post=$addr; } 123 } 124 if ($reg2 ne "") 125 { 126 $t=""; 127 $t="*$idx" if ($idx != 0); 128 $reg1="+".$reg1 if ("$reg1$post" ne ""); 129 $ret.="$reg2$t$reg1$post]"; 130 } 131 else 132 { 133 $ret.="$reg1$post]" 134 } 135 $ret =~ s/\+\]/]/; # in case $addr was the only argument 136 return($ret); 137 } 138 139sub main'mov { &out2("mov",@_); } 140sub main'movb { &out2("mov",@_); } 141sub main'and { &out2("and",@_); } 142sub main'or { &out2("or",@_); } 143sub main'shl { &out2("shl",@_); } 144sub main'shr { &out2("shr",@_); } 145sub main'xor { &out2("xor",@_); } 146sub main'xorb { &out2("xor",@_); } 147sub main'add { &out2("add",@_); } 148sub main'adc { &out2("adc",@_); } 149sub main'sub { &out2("sub",@_); } 150sub main'sbb { &out2("sbb",@_); } 151sub main'rotl { &out2("rol",@_); } 152sub main'rotr { &out2("ror",@_); } 153sub main'exch { &out2("xchg",@_); } 154sub main'cmp { &out2("cmp",@_); } 155sub main'lea { &out2("lea",@_); } 156sub main'mul { &out1("mul",@_); } 157sub main'div { &out1("div",@_); } 158sub main'dec { &out1("dec",@_); } 159sub main'inc { &out1("inc",@_); } 160sub main'jmp { &out1("jmp",@_); } 161sub main'jmp_ptr { &out1p("jmp",@_); } 162 163# This is a bit of a kludge: declare all branches as NEAR. 164$near=($main'mwerks)?'':'NEAR'; 165sub main'je { &out1("je $near",@_); } 166sub main'jle { &out1("jle $near",@_); } 167sub main'jz { &out1("jz $near",@_); } 168sub main'jge { &out1("jge $near",@_); } 169sub main'jl { &out1("jl $near",@_); } 170sub main'ja { &out1("ja $near",@_); } 171sub main'jae { &out1("jae $near",@_); } 172sub main'jb { &out1("jb $near",@_); } 173sub main'jbe { &out1("jbe $near",@_); } 174sub main'jc { &out1("jc $near",@_); } 175sub main'jnc { &out1("jnc $near",@_); } 176sub main'jnz { &out1("jnz $near",@_); } 177sub main'jne { &out1("jne $near",@_); } 178sub main'jno { &out1("jno $near",@_); } 179 180sub main'push { &out1("push",@_); $stack+=4; } 181sub main'pop { &out1("pop",@_); $stack-=4; } 182sub main'pushf { &out0("pushfd"); $stack+=4; } 183sub main'popf { &out0("popfd"); $stack-=4; } 184sub main'bswap { &out1("bswap",@_); &using486(); } 185sub main'not { &out1("not",@_); } 186sub main'call { &out1("call",($_[0]=~/^\@L/?'':$under).$_[0]); } 187sub main'call_ptr { &out1p("call",@_); } 188sub main'ret { &out0("ret"); } 189sub main'nop { &out0("nop"); } 190sub main'test { &out2("test",@_); } 191sub main'bt { &out2("bt",@_); } 192sub main'leave { &out0("leave"); } 193sub main'cpuid { &out0("cpuid"); } 194sub main'rdtsc { &out0("rdtsc"); } 195sub main'halt { &out0("hlt"); } 196sub main'movz { &out2("movzx",@_); } 197sub main'neg { &out1("neg",@_); } 198sub main'cld { &out0("cld"); } 199 200# SSE2 201sub main'emms { &out0("emms"); } 202sub main'movd { &out2("movd",@_); } 203sub main'movq { &out2("movq",@_); } 204sub main'movdqu { &out2("movdqu",@_); } 205sub main'movdqa { &out2("movdqa",@_); } 206sub main'movdq2q{ &out2("movdq2q",@_); } 207sub main'movq2dq{ &out2("movq2dq",@_); } 208sub main'paddq { &out2("paddq",@_); } 209sub main'pmuludq{ &out2("pmuludq",@_); } 210sub main'psrlq { &out2("psrlq",@_); } 211sub main'psllq { &out2("psllq",@_); } 212sub main'pxor { &out2("pxor",@_); } 213sub main'por { &out2("por",@_); } 214sub main'pand { &out2("pand",@_); } 215 216sub out2 217 { 218 my($name,$p1,$p2)=@_; 219 my($l,$t); 220 221 push(@out,"\t$name\t"); 222 if (!$main'mwerks and $name eq "lea") 223 { 224 $p1 =~ s/^[^\[]*\[/\[/; 225 $p2 =~ s/^[^\[]*\[/\[/; 226 } 227 $t=&conv($p1).","; 228 $l=length($t); 229 push(@out,$t); 230 $l=4-($l+9)/8; 231 push(@out,"\t" x $l); 232 push(@out,&conv($p2)); 233 push(@out,"\n"); 234 } 235 236sub out0 237 { 238 my($name)=@_; 239 240 push(@out,"\t$name\n"); 241 } 242 243sub out1 244 { 245 my($name,$p1)=@_; 246 my($l,$t); 247 push(@out,"\t$name\t".&conv($p1)."\n"); 248 } 249 250sub conv 251 { 252 my($p)=@_; 253 $p =~ s/0x([0-9A-Fa-f]+)/0$1h/; 254 return $p; 255 } 256 257sub using486 258 { 259 return if $using486; 260 $using486++; 261 grep(s/\.386/\.486/,@out); 262 } 263 264sub main'file 265 { 266 if ($main'mwerks) { push(@out,".section\t.text\n"); } 267 else { 268 local $tmp=<<___; 269%ifdef __omf__ 270section code use32 class=code 271%else 272section .text 273%endif 274___ 275 push(@out,$tmp); 276 } 277 } 278 279sub main'function_begin 280 { 281 my($func,$extra)=@_; 282 283 push(@labels,$func); 284 my($tmp)=<<"EOF"; 285global $under$func 286$under$func: 287 push ebp 288 push ebx 289 push esi 290 push edi 291EOF 292 push(@out,$tmp); 293 $stack=20; 294 } 295 296sub main'function_begin_B 297 { 298 my($func,$extra)=@_; 299 my($tmp)=<<"EOF"; 300global $under$func 301$under$func: 302EOF 303 push(@out,$tmp); 304 $stack=4; 305 } 306 307sub main'function_end 308 { 309 my($func)=@_; 310 311 my($tmp)=<<"EOF"; 312 pop edi 313 pop esi 314 pop ebx 315 pop ebp 316 ret 317EOF 318 push(@out,$tmp); 319 $stack=0; 320 %label=(); 321 } 322 323sub main'function_end_B 324 { 325 $stack=0; 326 %label=(); 327 } 328 329sub main'function_end_A 330 { 331 my($func)=@_; 332 333 my($tmp)=<<"EOF"; 334 pop edi 335 pop esi 336 pop ebx 337 pop ebp 338 ret 339EOF 340 push(@out,$tmp); 341 } 342 343sub main'file_end 344 { 345 } 346 347sub main'wparam 348 { 349 my($num)=@_; 350 351 return(&main'DWP($stack+$num*4,"esp","",0)); 352 } 353 354sub main'swtmp 355 { 356 return(&main'DWP($_[0]*4,"esp","",0)); 357 } 358 359# Should use swtmp, which is above esp. Linix can trash the stack above esp 360#sub main'wtmp 361# { 362# my($num)=@_; 363# 364# return(&main'DWP(-(($num+1)*4),"esp","",0)); 365# } 366 367sub main'comment 368 { 369 foreach (@_) 370 { 371 push(@out,"\t; $_\n"); 372 } 373 } 374 375sub main'public_label 376 { 377 $label{$_[0]}="${under}${_[0]}" if (!defined($label{$_[0]})); 378 push(@out,"global\t$label{$_[0]}\n"); 379 } 380 381sub main'label 382 { 383 if (!defined($label{$_[0]})) 384 { 385 $label{$_[0]}="\@${label}${_[0]}"; 386 $label++; 387 } 388 return($label{$_[0]}); 389 } 390 391sub main'set_label 392 { 393 if (!defined($label{$_[0]})) 394 { 395 $label{$_[0]}="\@${label}${_[0]}"; 396 $label++; 397 } 398 if ($_[1]!=0 && $_[1]>1) 399 { 400 main'align($_[1]); 401 } 402 push(@out,"$label{$_[0]}:\n"); 403 } 404 405sub main'data_byte 406 { 407 push(@out,(($main'mwerks)?".byte\t":"DB\t").join(',',@_)."\n"); 408 } 409 410sub main'data_word 411 { 412 push(@out,(($main'mwerks)?".long\t":"DD\t").join(',',@_)."\n"); 413 } 414 415sub main'align 416 { 417 push(@out,".") if ($main'mwerks); 418 push(@out,"align\t$_[0]\n"); 419 } 420 421sub out1p 422 { 423 my($name,$p1)=@_; 424 my($l,$t); 425 426 push(@out,"\t$name\t".&conv($p1)."\n"); 427 } 428 429sub main'picmeup 430 { 431 local($dst,$sym)=@_; 432 &main'lea($dst,&main'DWP($sym)); 433 } 434 435sub main'blindpop { &out1("pop",@_); } 436 437sub main'initseg 438 { 439 local($f)=@_; 440 if ($main'win32) 441 { 442 local($tmp)=<<___; 443segment .CRT\$XCU data 444extern $under$f 445DD $under$f 446___ 447 push(@out,$tmp); 448 } 449 } 450 4511; 452