1*8fb009dcSAndroid Build Coastguard Worker#! /usr/bin/env perl 2*8fb009dcSAndroid Build Coastguard Worker# Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. 3*8fb009dcSAndroid Build Coastguard Worker# 4*8fb009dcSAndroid Build Coastguard Worker# Licensed under the OpenSSL license (the "License"). You may not use 5*8fb009dcSAndroid Build Coastguard Worker# this file except in compliance with the License. You can obtain a copy 6*8fb009dcSAndroid Build Coastguard Worker# in the file LICENSE in the source distribution or at 7*8fb009dcSAndroid Build Coastguard Worker# https://www.openssl.org/source/license.html 8*8fb009dcSAndroid Build Coastguard Worker 9*8fb009dcSAndroid Build Coastguard Worker 10*8fb009dcSAndroid Build Coastguard Workerpackage x86nasm; 11*8fb009dcSAndroid Build Coastguard Worker 12*8fb009dcSAndroid Build Coastguard Worker*out=\@::out; 13*8fb009dcSAndroid Build Coastguard Worker 14*8fb009dcSAndroid Build Coastguard Worker$::lbdecor="L\$"; # local label decoration 15*8fb009dcSAndroid Build Coastguard Worker$nmdecor="_"; # external name decoration 16*8fb009dcSAndroid Build Coastguard Worker$drdecor=$::mwerks?".":""; # directive decoration 17*8fb009dcSAndroid Build Coastguard Worker 18*8fb009dcSAndroid Build Coastguard Worker$initseg=""; 19*8fb009dcSAndroid Build Coastguard Worker 20*8fb009dcSAndroid Build Coastguard Workersub ::generic 21*8fb009dcSAndroid Build Coastguard Worker{ my $opcode=shift; 22*8fb009dcSAndroid Build Coastguard Worker my $tmp; 23*8fb009dcSAndroid Build Coastguard Worker 24*8fb009dcSAndroid Build Coastguard Worker if (!$::mwerks) 25*8fb009dcSAndroid Build Coastguard Worker { if ($opcode =~ m/^j/o && $#_==0) # optimize jumps 26*8fb009dcSAndroid Build Coastguard Worker { $_[0] = "NEAR $_[0]"; } 27*8fb009dcSAndroid Build Coastguard Worker elsif ($opcode eq "lea" && $#_==1) # wipe storage qualifier from lea 28*8fb009dcSAndroid Build Coastguard Worker { $_[1] =~ s/^[^\[]*\[/\[/o; } 29*8fb009dcSAndroid Build Coastguard Worker elsif ($opcode eq "clflush" && $#_==0) 30*8fb009dcSAndroid Build Coastguard Worker { $_[0] =~ s/^[^\[]*\[/\[/o; } 31*8fb009dcSAndroid Build Coastguard Worker } 32*8fb009dcSAndroid Build Coastguard Worker &::emit($opcode,@_); 33*8fb009dcSAndroid Build Coastguard Worker 1; 34*8fb009dcSAndroid Build Coastguard Worker} 35*8fb009dcSAndroid Build Coastguard Worker# 36*8fb009dcSAndroid Build Coastguard Worker# opcodes not covered by ::generic above, mostly inconsistent namings... 37*8fb009dcSAndroid Build Coastguard Worker# 38*8fb009dcSAndroid Build Coastguard Workersub ::call { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); } 39*8fb009dcSAndroid Build Coastguard Workersub ::call_ptr { &::emit("call",@_); } 40*8fb009dcSAndroid Build Coastguard Workersub ::jmp_ptr { &::emit("jmp",@_); } 41*8fb009dcSAndroid Build Coastguard Worker 42*8fb009dcSAndroid Build Coastguard Workersub get_mem 43*8fb009dcSAndroid Build Coastguard Worker{ my($size,$addr,$reg1,$reg2,$idx)=@_; 44*8fb009dcSAndroid Build Coastguard Worker my($post,$ret); 45*8fb009dcSAndroid Build Coastguard Worker 46*8fb009dcSAndroid Build Coastguard Worker if (!defined($idx) && 1*$reg2) { $idx=$reg2; $reg2=$reg1; undef $reg1; } 47*8fb009dcSAndroid Build Coastguard Worker 48*8fb009dcSAndroid Build Coastguard Worker if ($size ne "") 49*8fb009dcSAndroid Build Coastguard Worker { $ret .= "$size"; 50*8fb009dcSAndroid Build Coastguard Worker $ret .= " PTR" if ($::mwerks); 51*8fb009dcSAndroid Build Coastguard Worker $ret .= " "; 52*8fb009dcSAndroid Build Coastguard Worker } 53*8fb009dcSAndroid Build Coastguard Worker $ret .= "["; 54*8fb009dcSAndroid Build Coastguard Worker 55*8fb009dcSAndroid Build Coastguard Worker $addr =~ s/^\s+//; 56*8fb009dcSAndroid Build Coastguard Worker # prepend global references with optional underscore 57*8fb009dcSAndroid Build Coastguard Worker $addr =~ s/^([^\+\-0-9][^\+\-]*)/::islabel($1) or "$nmdecor$1"/ige; 58*8fb009dcSAndroid Build Coastguard Worker # put address arithmetic expression in parenthesis 59*8fb009dcSAndroid Build Coastguard Worker $addr="($addr)" if ($addr =~ /^.+[\-\+].+$/); 60*8fb009dcSAndroid Build Coastguard Worker 61*8fb009dcSAndroid Build Coastguard Worker if (($addr ne "") && ($addr ne 0)) 62*8fb009dcSAndroid Build Coastguard Worker { if ($addr !~ /^-/) { $ret .= "$addr+"; } 63*8fb009dcSAndroid Build Coastguard Worker else { $post=$addr; } 64*8fb009dcSAndroid Build Coastguard Worker } 65*8fb009dcSAndroid Build Coastguard Worker 66*8fb009dcSAndroid Build Coastguard Worker if ($reg2 ne "") 67*8fb009dcSAndroid Build Coastguard Worker { $idx!=0 or $idx=1; 68*8fb009dcSAndroid Build Coastguard Worker $ret .= "$reg2*$idx"; 69*8fb009dcSAndroid Build Coastguard Worker $ret .= "+$reg1" if ($reg1 ne ""); 70*8fb009dcSAndroid Build Coastguard Worker } 71*8fb009dcSAndroid Build Coastguard Worker else 72*8fb009dcSAndroid Build Coastguard Worker { $ret .= "$reg1"; } 73*8fb009dcSAndroid Build Coastguard Worker 74*8fb009dcSAndroid Build Coastguard Worker $ret .= "$post]"; 75*8fb009dcSAndroid Build Coastguard Worker $ret =~ s/\+\]/]/; # in case $addr was the only argument 76*8fb009dcSAndroid Build Coastguard Worker 77*8fb009dcSAndroid Build Coastguard Worker $ret; 78*8fb009dcSAndroid Build Coastguard Worker} 79*8fb009dcSAndroid Build Coastguard Workersub ::BP { &get_mem("BYTE",@_); } 80*8fb009dcSAndroid Build Coastguard Workersub ::DWP { &get_mem("DWORD",@_); } 81*8fb009dcSAndroid Build Coastguard Workersub ::WP { &get_mem("WORD",@_); } 82*8fb009dcSAndroid Build Coastguard Workersub ::QWP { &get_mem("",@_); } 83*8fb009dcSAndroid Build Coastguard Workersub ::BC { (($::mwerks)?"":"BYTE ")."@_"; } 84*8fb009dcSAndroid Build Coastguard Workersub ::DWC { (($::mwerks)?"":"DWORD ")."@_"; } 85*8fb009dcSAndroid Build Coastguard Worker 86*8fb009dcSAndroid Build Coastguard Workersub ::file 87*8fb009dcSAndroid Build Coastguard Worker{ if ($::mwerks) { push(@out,".section\t.text,64\n"); } 88*8fb009dcSAndroid Build Coastguard Worker else 89*8fb009dcSAndroid Build Coastguard Worker { my $tmp=<<___; 90*8fb009dcSAndroid Build Coastguard Worker%ifidn __OUTPUT_FORMAT__,obj 91*8fb009dcSAndroid Build Coastguard Workersection code use32 class=code align=64 92*8fb009dcSAndroid Build Coastguard Worker%elifidn __OUTPUT_FORMAT__,win32 93*8fb009dcSAndroid Build Coastguard Worker\$\@feat.00 equ 1 94*8fb009dcSAndroid Build Coastguard Workersection .text code align=64 95*8fb009dcSAndroid Build Coastguard Worker%else 96*8fb009dcSAndroid Build Coastguard Workersection .text code 97*8fb009dcSAndroid Build Coastguard Worker%endif 98*8fb009dcSAndroid Build Coastguard Worker___ 99*8fb009dcSAndroid Build Coastguard Worker push(@out,$tmp); 100*8fb009dcSAndroid Build Coastguard Worker } 101*8fb009dcSAndroid Build Coastguard Worker} 102*8fb009dcSAndroid Build Coastguard Worker 103*8fb009dcSAndroid Build Coastguard Workersub ::function_begin_B 104*8fb009dcSAndroid Build Coastguard Worker{ my $func=shift; 105*8fb009dcSAndroid Build Coastguard Worker my $global=($func !~ /^_/); 106*8fb009dcSAndroid Build Coastguard Worker my $begin="${::lbdecor}_${func}_begin"; 107*8fb009dcSAndroid Build Coastguard Worker 108*8fb009dcSAndroid Build Coastguard Worker $begin =~ s/^\@/./ if ($::mwerks); # the torture never stops 109*8fb009dcSAndroid Build Coastguard Worker 110*8fb009dcSAndroid Build Coastguard Worker &::LABEL($func,$global?"$begin":"$nmdecor$func"); 111*8fb009dcSAndroid Build Coastguard Worker $func=$nmdecor.$func; 112*8fb009dcSAndroid Build Coastguard Worker 113*8fb009dcSAndroid Build Coastguard Worker push(@out,"${drdecor}global $func\n") if ($global); 114*8fb009dcSAndroid Build Coastguard Worker push(@out,"${drdecor}align 16\n"); 115*8fb009dcSAndroid Build Coastguard Worker push(@out,"$func:\n"); 116*8fb009dcSAndroid Build Coastguard Worker push(@out,"$begin:\n") if ($global); 117*8fb009dcSAndroid Build Coastguard Worker $::stack=4; 118*8fb009dcSAndroid Build Coastguard Worker} 119*8fb009dcSAndroid Build Coastguard Worker 120*8fb009dcSAndroid Build Coastguard Workersub ::function_end_B 121*8fb009dcSAndroid Build Coastguard Worker{ $::stack=0; 122*8fb009dcSAndroid Build Coastguard Worker &::wipe_labels(); 123*8fb009dcSAndroid Build Coastguard Worker} 124*8fb009dcSAndroid Build Coastguard Worker 125*8fb009dcSAndroid Build Coastguard Workersub ::file_end 126*8fb009dcSAndroid Build Coastguard Worker{ if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out) 127*8fb009dcSAndroid Build Coastguard Worker { my $comm=<<___; 128*8fb009dcSAndroid Build Coastguard Worker${drdecor}segment .bss 129*8fb009dcSAndroid Build Coastguard Worker${drdecor}common ${nmdecor}OPENSSL_ia32cap_P 16 130*8fb009dcSAndroid Build Coastguard Worker___ 131*8fb009dcSAndroid Build Coastguard Worker # comment out OPENSSL_ia32cap_P declarations 132*8fb009dcSAndroid Build Coastguard Worker grep {s/(^extern\s+${nmdecor}OPENSSL_ia32cap_P)/\;$1/} @out; 133*8fb009dcSAndroid Build Coastguard Worker push (@out,$comm) 134*8fb009dcSAndroid Build Coastguard Worker } 135*8fb009dcSAndroid Build Coastguard Worker push (@out,$initseg) if ($initseg); 136*8fb009dcSAndroid Build Coastguard Worker} 137*8fb009dcSAndroid Build Coastguard Worker 138*8fb009dcSAndroid Build Coastguard Workersub ::comment { foreach (@_) { push(@out,"\t; $_\n"); } } 139*8fb009dcSAndroid Build Coastguard Worker 140*8fb009dcSAndroid Build Coastguard Workersub ::external_label 141*8fb009dcSAndroid Build Coastguard Worker{ foreach(@_) 142*8fb009dcSAndroid Build Coastguard Worker { push(@out,"${drdecor}extern\t".&::LABEL($_,$nmdecor.$_)."\n"); } 143*8fb009dcSAndroid Build Coastguard Worker} 144*8fb009dcSAndroid Build Coastguard Worker 145*8fb009dcSAndroid Build Coastguard Workersub ::public_label 146*8fb009dcSAndroid Build Coastguard Worker{ push(@out,"${drdecor}global\t".&::LABEL($_[0],$nmdecor.$_[0])."\n"); } 147*8fb009dcSAndroid Build Coastguard Worker 148*8fb009dcSAndroid Build Coastguard Workersub ::data_byte 149*8fb009dcSAndroid Build Coastguard Worker{ push(@out,(($::mwerks)?".byte\t":"db\t").join(',',@_)."\n"); } 150*8fb009dcSAndroid Build Coastguard Workersub ::data_short 151*8fb009dcSAndroid Build Coastguard Worker{ push(@out,(($::mwerks)?".word\t":"dw\t").join(',',@_)."\n"); } 152*8fb009dcSAndroid Build Coastguard Workersub ::data_word 153*8fb009dcSAndroid Build Coastguard Worker{ push(@out,(($::mwerks)?".long\t":"dd\t").join(',',@_)."\n"); } 154*8fb009dcSAndroid Build Coastguard Worker 155*8fb009dcSAndroid Build Coastguard Workersub ::align 156*8fb009dcSAndroid Build Coastguard Worker{ push(@out,"${drdecor}align\t$_[0]\n"); } 157*8fb009dcSAndroid Build Coastguard Worker 158*8fb009dcSAndroid Build Coastguard Workersub ::picmeup 159*8fb009dcSAndroid Build Coastguard Worker{ my($dst,$sym)=@_; 160*8fb009dcSAndroid Build Coastguard Worker &::lea($dst,&::DWP($sym)); 161*8fb009dcSAndroid Build Coastguard Worker} 162*8fb009dcSAndroid Build Coastguard Worker 163*8fb009dcSAndroid Build Coastguard Workersub ::initseg 164*8fb009dcSAndroid Build Coastguard Worker{ my $f=$nmdecor.shift; 165*8fb009dcSAndroid Build Coastguard Worker if ($::win32) 166*8fb009dcSAndroid Build Coastguard Worker { $initseg=<<___; 167*8fb009dcSAndroid Build Coastguard Workersegment .CRT\$XCU data align=4 168*8fb009dcSAndroid Build Coastguard Workerextern $f 169*8fb009dcSAndroid Build Coastguard Workerdd $f 170*8fb009dcSAndroid Build Coastguard Worker___ 171*8fb009dcSAndroid Build Coastguard Worker } 172*8fb009dcSAndroid Build Coastguard Worker} 173*8fb009dcSAndroid Build Coastguard Worker 174*8fb009dcSAndroid Build Coastguard Workersub ::dataseg 175*8fb009dcSAndroid Build Coastguard Worker{ if ($mwerks) { push(@out,".section\t.data,4\n"); } 176*8fb009dcSAndroid Build Coastguard Worker else { push(@out,"section\t.data align=4\n"); } 177*8fb009dcSAndroid Build Coastguard Worker} 178*8fb009dcSAndroid Build Coastguard Worker 179*8fb009dcSAndroid Build Coastguard Workersub ::safeseh 180*8fb009dcSAndroid Build Coastguard Worker{ my $nm=shift; 181*8fb009dcSAndroid Build Coastguard Worker push(@out,"%if __NASM_VERSION_ID__ >= 0x02030000\n"); 182*8fb009dcSAndroid Build Coastguard Worker push(@out,"safeseh ".&::LABEL($nm,$nmdecor.$nm)."\n"); 183*8fb009dcSAndroid Build Coastguard Worker push(@out,"%endif\n"); 184*8fb009dcSAndroid Build Coastguard Worker} 185*8fb009dcSAndroid Build Coastguard Worker 186*8fb009dcSAndroid Build Coastguard Workersub ::preprocessor_ifdef 187*8fb009dcSAndroid Build Coastguard Worker{ my($define)=@_; 188*8fb009dcSAndroid Build Coastguard Worker push(@out,"%ifdef ${define}\n"); 189*8fb009dcSAndroid Build Coastguard Worker} 190*8fb009dcSAndroid Build Coastguard Worker 191*8fb009dcSAndroid Build Coastguard Workersub ::preprocessor_endif 192*8fb009dcSAndroid Build Coastguard Worker{ push(@out,"%endif\n"); } 193*8fb009dcSAndroid Build Coastguard Worker 194*8fb009dcSAndroid Build Coastguard Worker1; 195