1*8fb009dcSAndroid Build Coastguard Worker#! /usr/bin/env perl 2*8fb009dcSAndroid Build Coastguard Worker# Copyright 2007-2016 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 x86masm; 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 17*8fb009dcSAndroid Build Coastguard Worker$initseg=""; 18*8fb009dcSAndroid Build Coastguard Worker$segment=""; 19*8fb009dcSAndroid Build Coastguard Worker 20*8fb009dcSAndroid Build Coastguard Workersub ::generic 21*8fb009dcSAndroid Build Coastguard Worker{ my ($opcode,@arg)=@_; 22*8fb009dcSAndroid Build Coastguard Worker 23*8fb009dcSAndroid Build Coastguard Worker # fix hexadecimal constants 24*8fb009dcSAndroid Build Coastguard Worker for (@arg) { s/(?<![\w\$\.])0x([0-9a-f]+)/0$1h/oi; } 25*8fb009dcSAndroid Build Coastguard Worker 26*8fb009dcSAndroid Build Coastguard Worker if ($opcode =~ /lea/ && @arg[1] =~ s/.*PTR\s+(\(.*\))$/OFFSET $1/) # no [] 27*8fb009dcSAndroid Build Coastguard Worker { $opcode="mov"; } 28*8fb009dcSAndroid Build Coastguard Worker elsif ($opcode !~ /mov[dq]$/) 29*8fb009dcSAndroid Build Coastguard Worker { # fix xmm references 30*8fb009dcSAndroid Build Coastguard Worker $arg[0] =~ s/\b[A-Z]+WORD\s+PTR/XMMWORD PTR/i if ($arg[-1]=~/\bxmm[0-7]\b/i); 31*8fb009dcSAndroid Build Coastguard Worker $arg[-1] =~ s/\b[A-Z]+WORD\s+PTR/XMMWORD PTR/i if ($arg[0]=~/\bxmm[0-7]\b/i); 32*8fb009dcSAndroid Build Coastguard Worker } 33*8fb009dcSAndroid Build Coastguard Worker 34*8fb009dcSAndroid Build Coastguard Worker &::emit($opcode,@arg); 35*8fb009dcSAndroid Build Coastguard Worker 1; 36*8fb009dcSAndroid Build Coastguard Worker} 37*8fb009dcSAndroid Build Coastguard Worker# 38*8fb009dcSAndroid Build Coastguard Worker# opcodes not covered by ::generic above, mostly inconsistent namings... 39*8fb009dcSAndroid Build Coastguard Worker# 40*8fb009dcSAndroid Build Coastguard Workersub ::call { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); } 41*8fb009dcSAndroid Build Coastguard Workersub ::call_ptr { &::emit("call",@_); } 42*8fb009dcSAndroid Build Coastguard Workersub ::jmp_ptr { &::emit("jmp",@_); } 43*8fb009dcSAndroid Build Coastguard Workersub ::lock { &::data_byte(0xf0); } 44*8fb009dcSAndroid Build Coastguard Worker 45*8fb009dcSAndroid Build Coastguard Workersub get_mem 46*8fb009dcSAndroid Build Coastguard Worker{ my($size,$addr,$reg1,$reg2,$idx)=@_; 47*8fb009dcSAndroid Build Coastguard Worker my($post,$ret); 48*8fb009dcSAndroid Build Coastguard Worker 49*8fb009dcSAndroid Build Coastguard Worker if (!defined($idx) && 1*$reg2) { $idx=$reg2; $reg2=$reg1; undef $reg1; } 50*8fb009dcSAndroid Build Coastguard Worker 51*8fb009dcSAndroid Build Coastguard Worker $ret .= "$size PTR " if ($size ne ""); 52*8fb009dcSAndroid Build Coastguard Worker 53*8fb009dcSAndroid Build Coastguard Worker $addr =~ s/^\s+//; 54*8fb009dcSAndroid Build Coastguard Worker # prepend global references with optional underscore 55*8fb009dcSAndroid Build Coastguard Worker $addr =~ s/^([^\+\-0-9][^\+\-]*)/&::islabel($1) or "$nmdecor$1"/ige; 56*8fb009dcSAndroid Build Coastguard Worker # put address arithmetic expression in parenthesis 57*8fb009dcSAndroid Build Coastguard Worker $addr="($addr)" if ($addr =~ /^.+[\-\+].+$/); 58*8fb009dcSAndroid Build Coastguard Worker 59*8fb009dcSAndroid Build Coastguard Worker if (($addr ne "") && ($addr ne 0)) 60*8fb009dcSAndroid Build Coastguard Worker { if ($addr !~ /^-/) { $ret .= "$addr"; } 61*8fb009dcSAndroid Build Coastguard Worker else { $post=$addr; } 62*8fb009dcSAndroid Build Coastguard Worker } 63*8fb009dcSAndroid Build Coastguard Worker $ret .= "["; 64*8fb009dcSAndroid Build Coastguard Worker 65*8fb009dcSAndroid Build Coastguard Worker if ($reg2 ne "") 66*8fb009dcSAndroid Build Coastguard Worker { $idx!=0 or $idx=1; 67*8fb009dcSAndroid Build Coastguard Worker $ret .= "$reg2*$idx"; 68*8fb009dcSAndroid Build Coastguard Worker $ret .= "+$reg1" if ($reg1 ne ""); 69*8fb009dcSAndroid Build Coastguard Worker } 70*8fb009dcSAndroid Build Coastguard Worker else 71*8fb009dcSAndroid Build Coastguard Worker { $ret .= "$reg1"; } 72*8fb009dcSAndroid Build Coastguard Worker 73*8fb009dcSAndroid Build Coastguard Worker $ret .= "$post]"; 74*8fb009dcSAndroid Build Coastguard Worker $ret =~ s/\+\]/]/; # in case $addr was the only argument 75*8fb009dcSAndroid Build Coastguard Worker $ret =~ s/\[\s*\]//; 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 ::WP { &get_mem("WORD",@_); } 81*8fb009dcSAndroid Build Coastguard Workersub ::DWP { &get_mem("DWORD",@_); } 82*8fb009dcSAndroid Build Coastguard Workersub ::QWP { &get_mem("QWORD",@_); } 83*8fb009dcSAndroid Build Coastguard Workersub ::BC { "@_"; } 84*8fb009dcSAndroid Build Coastguard Workersub ::DWC { "@_"; } 85*8fb009dcSAndroid Build Coastguard Worker 86*8fb009dcSAndroid Build Coastguard Workersub ::file 87*8fb009dcSAndroid Build Coastguard Worker{ my $tmp=<<___; 88*8fb009dcSAndroid Build Coastguard WorkerIF \@Version LT 800 89*8fb009dcSAndroid Build Coastguard WorkerECHO MASM version 8.00 or later is strongly recommended. 90*8fb009dcSAndroid Build Coastguard WorkerENDIF 91*8fb009dcSAndroid Build Coastguard Worker.686 92*8fb009dcSAndroid Build Coastguard Worker.MODEL FLAT 93*8fb009dcSAndroid Build Coastguard WorkerOPTION DOTNAME 94*8fb009dcSAndroid Build Coastguard WorkerIF \@Version LT 800 95*8fb009dcSAndroid Build Coastguard Worker.text\$ SEGMENT PAGE 'CODE' 96*8fb009dcSAndroid Build Coastguard WorkerELSE 97*8fb009dcSAndroid Build Coastguard Worker.text\$ SEGMENT ALIGN(64) 'CODE' 98*8fb009dcSAndroid Build Coastguard WorkerENDIF 99*8fb009dcSAndroid Build Coastguard Worker___ 100*8fb009dcSAndroid Build Coastguard Worker push(@out,$tmp); 101*8fb009dcSAndroid Build Coastguard Worker $segment = ".text\$"; 102*8fb009dcSAndroid Build Coastguard Worker} 103*8fb009dcSAndroid Build Coastguard Worker 104*8fb009dcSAndroid Build Coastguard Workersub ::function_begin_B 105*8fb009dcSAndroid Build Coastguard Worker{ my $func=shift; 106*8fb009dcSAndroid Build Coastguard Worker my $global=($func !~ /^_/); 107*8fb009dcSAndroid Build Coastguard Worker my $begin="${::lbdecor}_${func}_begin"; 108*8fb009dcSAndroid Build Coastguard Worker 109*8fb009dcSAndroid Build Coastguard Worker &::LABEL($func,$global?"$begin":"$nmdecor$func"); 110*8fb009dcSAndroid Build Coastguard Worker $func="ALIGN\t16\n".$nmdecor.$func."\tPROC"; 111*8fb009dcSAndroid Build Coastguard Worker 112*8fb009dcSAndroid Build Coastguard Worker if ($global) { $func.=" PUBLIC\n${begin}::\n"; } 113*8fb009dcSAndroid Build Coastguard Worker else { $func.=" PRIVATE\n"; } 114*8fb009dcSAndroid Build Coastguard Worker push(@out,$func); 115*8fb009dcSAndroid Build Coastguard Worker $::stack=4; 116*8fb009dcSAndroid Build Coastguard Worker} 117*8fb009dcSAndroid Build Coastguard Workersub ::function_end_B 118*8fb009dcSAndroid Build Coastguard Worker{ my $func=shift; 119*8fb009dcSAndroid Build Coastguard Worker 120*8fb009dcSAndroid Build Coastguard Worker push(@out,"$nmdecor$func ENDP\n"); 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{ my $xmmheader=<<___; 127*8fb009dcSAndroid Build Coastguard Worker.686 128*8fb009dcSAndroid Build Coastguard Worker.XMM 129*8fb009dcSAndroid Build Coastguard WorkerIF \@Version LT 800 130*8fb009dcSAndroid Build Coastguard WorkerXMMWORD STRUCT 16 131*8fb009dcSAndroid Build Coastguard WorkerDQ 2 dup (?) 132*8fb009dcSAndroid Build Coastguard WorkerXMMWORD ENDS 133*8fb009dcSAndroid Build Coastguard WorkerENDIF 134*8fb009dcSAndroid Build Coastguard Worker___ 135*8fb009dcSAndroid Build Coastguard Worker if (grep {/\b[x]?mm[0-7]\b/i} @out) { 136*8fb009dcSAndroid Build Coastguard Worker grep {s/\.[3-7]86/$xmmheader/} @out; 137*8fb009dcSAndroid Build Coastguard Worker } 138*8fb009dcSAndroid Build Coastguard Worker 139*8fb009dcSAndroid Build Coastguard Worker push(@out,"$segment ENDS\n"); 140*8fb009dcSAndroid Build Coastguard Worker 141*8fb009dcSAndroid Build Coastguard Worker if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out) 142*8fb009dcSAndroid Build Coastguard Worker { my $comm=<<___; 143*8fb009dcSAndroid Build Coastguard Worker.bss SEGMENT 'BSS' 144*8fb009dcSAndroid Build Coastguard WorkerCOMM ${nmdecor}OPENSSL_ia32cap_P:DWORD:4 145*8fb009dcSAndroid Build Coastguard Worker.bss ENDS 146*8fb009dcSAndroid Build Coastguard Worker___ 147*8fb009dcSAndroid Build Coastguard Worker # comment out OPENSSL_ia32cap_P declarations 148*8fb009dcSAndroid Build Coastguard Worker grep {s/(^EXTERN\s+${nmdecor}OPENSSL_ia32cap_P)/\;$1/} @out; 149*8fb009dcSAndroid Build Coastguard Worker push (@out,$comm); 150*8fb009dcSAndroid Build Coastguard Worker } 151*8fb009dcSAndroid Build Coastguard Worker push (@out,$initseg) if ($initseg); 152*8fb009dcSAndroid Build Coastguard Worker push (@out,"END\n"); 153*8fb009dcSAndroid Build Coastguard Worker} 154*8fb009dcSAndroid Build Coastguard Worker 155*8fb009dcSAndroid Build Coastguard Workersub ::comment { foreach (@_) { push(@out,"\t; $_\n"); } } 156*8fb009dcSAndroid Build Coastguard Worker 157*8fb009dcSAndroid Build Coastguard Worker*::set_label_B = sub 158*8fb009dcSAndroid Build Coastguard Worker{ my $l=shift; push(@out,$l.($l=~/^\Q${::lbdecor}\E[0-9]{3}/?":\n":"::\n")); }; 159*8fb009dcSAndroid Build Coastguard Worker 160*8fb009dcSAndroid Build Coastguard Workersub ::external_label 161*8fb009dcSAndroid Build Coastguard Worker{ foreach(@_) 162*8fb009dcSAndroid Build Coastguard Worker { push(@out, "EXTERN\t".&::LABEL($_,$nmdecor.$_).":NEAR\n"); } 163*8fb009dcSAndroid Build Coastguard Worker} 164*8fb009dcSAndroid Build Coastguard Worker 165*8fb009dcSAndroid Build Coastguard Workersub ::public_label 166*8fb009dcSAndroid Build Coastguard Worker{ push(@out,"PUBLIC\t".&::LABEL($_[0],$nmdecor.$_[0])."\n"); } 167*8fb009dcSAndroid Build Coastguard Worker 168*8fb009dcSAndroid Build Coastguard Workersub ::data_byte 169*8fb009dcSAndroid Build Coastguard Worker{ push(@out,("DB\t").join(',',splice(@_,0,16))."\n") while(@_); } 170*8fb009dcSAndroid Build Coastguard Worker 171*8fb009dcSAndroid Build Coastguard Workersub ::data_short 172*8fb009dcSAndroid Build Coastguard Worker{ push(@out,("DW\t").join(',',splice(@_,0,8))."\n") while(@_); } 173*8fb009dcSAndroid Build Coastguard Worker 174*8fb009dcSAndroid Build Coastguard Workersub ::data_word 175*8fb009dcSAndroid Build Coastguard Worker{ push(@out,("DD\t").join(',',splice(@_,0,4))."\n") while(@_); } 176*8fb009dcSAndroid Build Coastguard Worker 177*8fb009dcSAndroid Build Coastguard Workersub ::align 178*8fb009dcSAndroid Build Coastguard Worker{ push(@out,"ALIGN\t$_[0]\n"); } 179*8fb009dcSAndroid Build Coastguard Worker 180*8fb009dcSAndroid Build Coastguard Workersub ::picmeup 181*8fb009dcSAndroid Build Coastguard Worker{ my($dst,$sym)=@_; 182*8fb009dcSAndroid Build Coastguard Worker &::lea($dst,&::DWP($sym)); 183*8fb009dcSAndroid Build Coastguard Worker} 184*8fb009dcSAndroid Build Coastguard Worker 185*8fb009dcSAndroid Build Coastguard Workersub ::initseg 186*8fb009dcSAndroid Build Coastguard Worker{ my $f=$nmdecor.shift; 187*8fb009dcSAndroid Build Coastguard Worker 188*8fb009dcSAndroid Build Coastguard Worker $initseg.=<<___; 189*8fb009dcSAndroid Build Coastguard Worker.CRT\$XCU SEGMENT DWORD PUBLIC 'DATA' 190*8fb009dcSAndroid Build Coastguard WorkerEXTERN $f:NEAR 191*8fb009dcSAndroid Build Coastguard WorkerDD $f 192*8fb009dcSAndroid Build Coastguard Worker.CRT\$XCU ENDS 193*8fb009dcSAndroid Build Coastguard Worker___ 194*8fb009dcSAndroid Build Coastguard Worker} 195*8fb009dcSAndroid Build Coastguard Worker 196*8fb009dcSAndroid Build Coastguard Workersub ::dataseg 197*8fb009dcSAndroid Build Coastguard Worker{ push(@out,"$segment\tENDS\n_DATA\tSEGMENT\n"); $segment="_DATA"; } 198*8fb009dcSAndroid Build Coastguard Worker 199*8fb009dcSAndroid Build Coastguard Workersub ::safeseh 200*8fb009dcSAndroid Build Coastguard Worker{ my $nm=shift; 201*8fb009dcSAndroid Build Coastguard Worker push(@out,"IF \@Version GE 710\n"); 202*8fb009dcSAndroid Build Coastguard Worker push(@out,".SAFESEH ".&::LABEL($nm,$nmdecor.$nm)."\n"); 203*8fb009dcSAndroid Build Coastguard Worker push(@out,"ENDIF\n"); 204*8fb009dcSAndroid Build Coastguard Worker} 205*8fb009dcSAndroid Build Coastguard Worker 206*8fb009dcSAndroid Build Coastguard Workersub ::preprocessor_ifdef 207*8fb009dcSAndroid Build Coastguard Worker{ my($define)=@_; 208*8fb009dcSAndroid Build Coastguard Worker push(@out,"%ifdef ${define}\n"); 209*8fb009dcSAndroid Build Coastguard Worker} 210*8fb009dcSAndroid Build Coastguard Worker 211*8fb009dcSAndroid Build Coastguard Workersub ::preprocessor_endif 212*8fb009dcSAndroid Build Coastguard Worker{ push(@out,"%endif\n"); } 213*8fb009dcSAndroid Build Coastguard Worker 214*8fb009dcSAndroid Build Coastguard Worker1; 215