1238384Sjkim#!/usr/bin/env perl 2238384Sjkim 3238384Sjkimpackage x86gas; 4238384Sjkim 5238384Sjkim*out=\@::out; 6238384Sjkim 7238384Sjkim$::lbdecor=$::aout?"L":".L"; # local label decoration 8238384Sjkim$nmdecor=($::aout or $::coff)?"_":""; # external name decoration 9238384Sjkim 10238384Sjkim$initseg=""; 11238384Sjkim 12238384Sjkim$align=16; 13238384Sjkim$align=log($align)/log(2) if ($::aout); 14238384Sjkim$com_start="#" if ($::aout or $::coff); 15238384Sjkim 16238384Sjkimsub opsize() 17238384Sjkim{ my $reg=shift; 18238384Sjkim if ($reg =~ m/^%e/o) { "l"; } 19238384Sjkim elsif ($reg =~ m/^%[a-d][hl]$/o) { "b"; } 20238384Sjkim elsif ($reg =~ m/^%[xm]/o) { undef; } 21238384Sjkim else { "w"; } 22238384Sjkim} 23238384Sjkim 24238384Sjkim# swap arguments; 25238384Sjkim# expand opcode with size suffix; 26238384Sjkim# prefix numeric constants with $; 27238384Sjkimsub ::generic 28238384Sjkim{ my($opcode,@arg)=@_; 29238384Sjkim my($suffix,$dst,$src); 30238384Sjkim 31238384Sjkim @arg=reverse(@arg); 32238384Sjkim 33238384Sjkim for (@arg) 34238384Sjkim { s/^(\*?)(e?[a-dsixphl]{2})$/$1%$2/o; # gp registers 35238384Sjkim s/^([xy]?mm[0-7])$/%$1/o; # xmm/mmx registers 36238384Sjkim s/^(\-?[0-9]+)$/\$$1/o; # constants 37238384Sjkim s/^(\-?0x[0-9a-f]+)$/\$$1/o; # constants 38238384Sjkim } 39238384Sjkim 40238384Sjkim $dst = $arg[$#arg] if ($#arg>=0); 41238384Sjkim $src = $arg[$#arg-1] if ($#arg>=1); 42238384Sjkim if ($dst =~ m/^%/o) { $suffix=&opsize($dst); } 43238384Sjkim elsif ($src =~ m/^%/o) { $suffix=&opsize($src); } 44238384Sjkim else { $suffix="l"; } 45238384Sjkim undef $suffix if ($dst =~ m/^%[xm]/o || $src =~ m/^%[xm]/o); 46238384Sjkim 47238384Sjkim if ($#_==0) { &::emit($opcode); } 48238384Sjkim elsif ($#_==1 && $opcode =~ m/^(call|clflush|j|loop|set)/o) 49238384Sjkim { &::emit($opcode,@arg); } 50238384Sjkim else { &::emit($opcode.$suffix,@arg);} 51238384Sjkim 52238384Sjkim 1; 53238384Sjkim} 54238384Sjkim# 55238384Sjkim# opcodes not covered by ::generic above, mostly inconsistent namings... 56238384Sjkim# 57238384Sjkimsub ::movzx { &::movzb(@_); } 58238384Sjkimsub ::pushfd { &::pushfl; } 59238384Sjkimsub ::popfd { &::popfl; } 60238384Sjkimsub ::cpuid { &::emit(".byte\t0x0f,0xa2"); } 61238384Sjkimsub ::rdtsc { &::emit(".byte\t0x0f,0x31"); } 62238384Sjkim 63238384Sjkimsub ::call { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); } 64238384Sjkimsub ::call_ptr { &::generic("call","*$_[0]"); } 65238384Sjkimsub ::jmp_ptr { &::generic("jmp","*$_[0]"); } 66238384Sjkim 67238384Sjkim*::bswap = sub { &::emit("bswap","%$_[0]"); } if (!$::i386); 68238384Sjkim 69238384Sjkimsub ::DWP 70238384Sjkim{ my($addr,$reg1,$reg2,$idx)=@_; 71238384Sjkim my $ret=""; 72238384Sjkim 73238384Sjkim $addr =~ s/^\s+//; 74238384Sjkim # prepend global references with optional underscore 75238384Sjkim $addr =~ s/^([^\+\-0-9][^\+\-]*)/&::islabel($1) or "$nmdecor$1"/ige; 76238384Sjkim 77238384Sjkim $reg1 = "%$reg1" if ($reg1); 78238384Sjkim $reg2 = "%$reg2" if ($reg2); 79238384Sjkim 80238384Sjkim $ret .= $addr if (($addr ne "") && ($addr ne 0)); 81238384Sjkim 82238384Sjkim if ($reg2) 83238384Sjkim { $idx!= 0 or $idx=1; 84238384Sjkim $ret .= "($reg1,$reg2,$idx)"; 85238384Sjkim } 86238384Sjkim elsif ($reg1) 87238384Sjkim { $ret .= "($reg1)"; } 88238384Sjkim 89238384Sjkim $ret; 90238384Sjkim} 91238384Sjkimsub ::QWP { &::DWP(@_); } 92238384Sjkimsub ::BP { &::DWP(@_); } 93238384Sjkimsub ::WP { &::DWP(@_); } 94238384Sjkimsub ::BC { @_; } 95238384Sjkimsub ::DWC { @_; } 96238384Sjkim 97238384Sjkimsub ::file 98238384Sjkim{ push(@out,".file\t\"$_[0].s\"\n.text\n"); } 99238384Sjkim 100238384Sjkimsub ::function_begin_B 101238384Sjkim{ my $func=shift; 102238384Sjkim my $global=($func !~ /^_/); 103238384Sjkim my $begin="${::lbdecor}_${func}_begin"; 104238384Sjkim 105238384Sjkim &::LABEL($func,$global?"$begin":"$nmdecor$func"); 106238384Sjkim $func=$nmdecor.$func; 107238384Sjkim 108238384Sjkim push(@out,".globl\t$func\n") if ($global); 109238384Sjkim if ($::coff) 110238384Sjkim { push(@out,".def\t$func;\t.scl\t".(3-$global).";\t.type\t32;\t.endef\n"); } 111238384Sjkim elsif (($::aout and !$::pic) or $::macosx) 112238384Sjkim { } 113238384Sjkim else 114238384Sjkim { push(@out,".type $func,\@function\n"); } 115238384Sjkim push(@out,".align\t$align\n"); 116238384Sjkim push(@out,"$func:\n"); 117238384Sjkim push(@out,"$begin:\n") if ($global); 118238384Sjkim $::stack=4; 119238384Sjkim} 120238384Sjkim 121238384Sjkimsub ::function_end_B 122238384Sjkim{ my $func=shift; 123238384Sjkim push(@out,".size\t$nmdecor$func,.-".&::LABEL($func)."\n") if ($::elf); 124238384Sjkim $::stack=0; 125238384Sjkim &::wipe_labels(); 126238384Sjkim} 127238384Sjkim 128238384Sjkimsub ::comment 129238384Sjkim { 130238384Sjkim if (!defined($com_start) or $::elf) 131238384Sjkim { # Regarding $::elf above... 132238384Sjkim # GNU and SVR4 as'es use different comment delimiters, 133238384Sjkim push(@out,"\n"); # so we just skip ELF comments... 134238384Sjkim return; 135238384Sjkim } 136238384Sjkim foreach (@_) 137238384Sjkim { 138238384Sjkim if (/^\s*$/) 139238384Sjkim { push(@out,"\n"); } 140238384Sjkim else 141238384Sjkim { push(@out,"\t$com_start $_ $com_end\n"); } 142238384Sjkim } 143238384Sjkim } 144238384Sjkim 145238384Sjkimsub ::external_label 146238384Sjkim{ foreach(@_) { &::LABEL($_,$nmdecor.$_); } } 147238384Sjkim 148238384Sjkimsub ::public_label 149238384Sjkim{ push(@out,".globl\t".&::LABEL($_[0],$nmdecor.$_[0])."\n"); } 150238384Sjkim 151238384Sjkimsub ::file_end 152238384Sjkim{ if ($::macosx) 153238384Sjkim { if (%non_lazy_ptr) 154238384Sjkim { push(@out,".section __IMPORT,__pointers,non_lazy_symbol_pointers\n"); 155238384Sjkim foreach $i (keys %non_lazy_ptr) 156238384Sjkim { push(@out,"$non_lazy_ptr{$i}:\n.indirect_symbol\t$i\n.long\t0\n"); } 157238384Sjkim } 158238384Sjkim } 159238384Sjkim if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out) { 160238384Sjkim my $tmp=".comm\t${nmdecor}OPENSSL_ia32cap_P,8"; 161238384Sjkim if ($::macosx) { push (@out,"$tmp,2\n"); } 162238384Sjkim elsif ($::elf) { push (@out,"$tmp,4\n"); } 163238384Sjkim else { push (@out,"$tmp\n"); } 164238384Sjkim } 165238384Sjkim push(@out,$initseg) if ($initseg); 166238384Sjkim} 167238384Sjkim 168238384Sjkimsub ::data_byte { push(@out,".byte\t".join(',',@_)."\n"); } 169238384Sjkimsub ::data_short{ push(@out,".value\t".join(',',@_)."\n"); } 170238384Sjkimsub ::data_word { push(@out,".long\t".join(',',@_)."\n"); } 171238384Sjkim 172238384Sjkimsub ::align 173238384Sjkim{ my $val=$_[0],$p2,$i; 174238384Sjkim if ($::aout) 175238384Sjkim { for ($p2=0;$val!=0;$val>>=1) { $p2++; } 176238384Sjkim $val=$p2-1; 177238384Sjkim $val.=",0x90"; 178238384Sjkim } 179238384Sjkim push(@out,".align\t$val\n"); 180238384Sjkim} 181238384Sjkim 182238384Sjkimsub ::picmeup 183238384Sjkim{ my($dst,$sym,$base,$reflabel)=@_; 184238384Sjkim 185238384Sjkim if (($::pic && ($::elf || $::aout)) || $::macosx) 186238384Sjkim { if (!defined($base)) 187238384Sjkim { &::call(&::label("PIC_me_up")); 188238384Sjkim &::set_label("PIC_me_up"); 189238384Sjkim &::blindpop($dst); 190238384Sjkim $base=$dst; 191238384Sjkim $reflabel=&::label("PIC_me_up"); 192238384Sjkim } 193238384Sjkim if ($::macosx) 194238384Sjkim { my $indirect=&::static_label("$nmdecor$sym\$non_lazy_ptr"); 195238384Sjkim &::mov($dst,&::DWP("$indirect-$reflabel",$base)); 196238384Sjkim $non_lazy_ptr{"$nmdecor$sym"}=$indirect; 197238384Sjkim } 198238384Sjkim else 199238384Sjkim { &::lea($dst,&::DWP("_GLOBAL_OFFSET_TABLE_+[.-$reflabel]", 200238384Sjkim $base)); 201238384Sjkim &::mov($dst,&::DWP("$sym\@GOT",$dst)); 202238384Sjkim } 203238384Sjkim } 204238384Sjkim else 205238384Sjkim { &::lea($dst,&::DWP($sym)); } 206238384Sjkim} 207238384Sjkim 208238384Sjkimsub ::initseg 209238384Sjkim{ my $f=$nmdecor.shift; 210238384Sjkim 211238384Sjkim if ($::android) 212238384Sjkim { $initseg.=<<___; 213238384Sjkim.section .init_array 214238384Sjkim.align 4 215238384Sjkim.long $f 216238384Sjkim___ 217238384Sjkim } 218238384Sjkim elsif ($::elf) 219238384Sjkim { $initseg.=<<___; 220238384Sjkim.section .init 221238384Sjkim call $f 222238384Sjkim___ 223238384Sjkim } 224238384Sjkim elsif ($::coff) 225238384Sjkim { $initseg.=<<___; # applies to both Cygwin and Mingw 226238384Sjkim.section .ctors 227238384Sjkim.long $f 228238384Sjkim___ 229238384Sjkim } 230238384Sjkim elsif ($::macosx) 231238384Sjkim { $initseg.=<<___; 232238384Sjkim.mod_init_func 233238384Sjkim.align 2 234238384Sjkim.long $f 235238384Sjkim___ 236238384Sjkim } 237238384Sjkim elsif ($::aout) 238238384Sjkim { my $ctor="${nmdecor}_GLOBAL_\$I\$$f"; 239238384Sjkim $initseg.=".text\n"; 240238384Sjkim $initseg.=".type $ctor,\@function\n" if ($::pic); 241238384Sjkim $initseg.=<<___; # OpenBSD way... 242238384Sjkim.globl $ctor 243238384Sjkim.align 2 244238384Sjkim$ctor: 245238384Sjkim jmp $f 246238384Sjkim___ 247238384Sjkim } 248238384Sjkim} 249238384Sjkim 250238384Sjkimsub ::dataseg 251238384Sjkim{ push(@out,".data\n"); } 252238384Sjkim 253299983Sjkim*::hidden = sub { push(@out,".hidden\t$nmdecor$_[0]\n"); } if ($::elf); 254299983Sjkim 255238384Sjkim1; 256