11cb0ef41Sopenharmony_ci#! /usr/bin/env perl 21cb0ef41Sopenharmony_ci# Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci# 41cb0ef41Sopenharmony_ci# Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci# this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci# in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci# https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_cipackage x86nasm; 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci*out=\@::out; 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ci$::lbdecor="L\$"; # local label decoration 151cb0ef41Sopenharmony_ci$nmdecor="_"; # external name decoration 161cb0ef41Sopenharmony_ci$drdecor=$::mwerks?".":""; # directive decoration 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci$initseg=""; 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_cisub ::generic 211cb0ef41Sopenharmony_ci{ my $opcode=shift; 221cb0ef41Sopenharmony_ci my $tmp; 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci if (!$::mwerks) 251cb0ef41Sopenharmony_ci { if ($opcode =~ m/^j/o && $#_==0) # optimize jumps 261cb0ef41Sopenharmony_ci { $_[0] = "NEAR $_[0]"; } 271cb0ef41Sopenharmony_ci elsif ($opcode eq "lea" && $#_==1) # wipe storage qualifier from lea 281cb0ef41Sopenharmony_ci { $_[1] =~ s/^[^\[]*\[/\[/o; } 291cb0ef41Sopenharmony_ci elsif ($opcode eq "clflush" && $#_==0) 301cb0ef41Sopenharmony_ci { $_[0] =~ s/^[^\[]*\[/\[/o; } 311cb0ef41Sopenharmony_ci } 321cb0ef41Sopenharmony_ci &::emit($opcode,@_); 331cb0ef41Sopenharmony_ci 1; 341cb0ef41Sopenharmony_ci} 351cb0ef41Sopenharmony_ci# 361cb0ef41Sopenharmony_ci# opcodes not covered by ::generic above, mostly inconsistent namings... 371cb0ef41Sopenharmony_ci# 381cb0ef41Sopenharmony_cisub ::call { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); } 391cb0ef41Sopenharmony_cisub ::call_ptr { &::emit("call",@_); } 401cb0ef41Sopenharmony_cisub ::jmp_ptr { &::emit("jmp",@_); } 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_cisub get_mem 431cb0ef41Sopenharmony_ci{ my($size,$addr,$reg1,$reg2,$idx)=@_; 441cb0ef41Sopenharmony_ci my($post,$ret); 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci if (!defined($idx) && 1*$reg2) { $idx=$reg2; $reg2=$reg1; undef $reg1; } 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci if ($size ne "") 491cb0ef41Sopenharmony_ci { $ret .= "$size"; 501cb0ef41Sopenharmony_ci $ret .= " PTR" if ($::mwerks); 511cb0ef41Sopenharmony_ci $ret .= " "; 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci $ret .= "["; 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci $addr =~ s/^\s+//; 561cb0ef41Sopenharmony_ci # prepend global references with optional underscore 571cb0ef41Sopenharmony_ci $addr =~ s/^([^\+\-0-9][^\+\-]*)/::islabel($1) or "$nmdecor$1"/ige; 581cb0ef41Sopenharmony_ci # put address arithmetic expression in parenthesis 591cb0ef41Sopenharmony_ci $addr="($addr)" if ($addr =~ /^.+[\-\+].+$/); 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci if (($addr ne "") && ($addr ne 0)) 621cb0ef41Sopenharmony_ci { if ($addr !~ /^-/) { $ret .= "$addr+"; } 631cb0ef41Sopenharmony_ci else { $post=$addr; } 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci if ($reg2 ne "") 671cb0ef41Sopenharmony_ci { $idx!=0 or $idx=1; 681cb0ef41Sopenharmony_ci $ret .= "$reg2*$idx"; 691cb0ef41Sopenharmony_ci $ret .= "+$reg1" if ($reg1 ne ""); 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci else 721cb0ef41Sopenharmony_ci { $ret .= "$reg1"; } 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci $ret .= "$post]"; 751cb0ef41Sopenharmony_ci $ret =~ s/\+\]/]/; # in case $addr was the only argument 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci $ret; 781cb0ef41Sopenharmony_ci} 791cb0ef41Sopenharmony_cisub ::BP { &get_mem("BYTE",@_); } 801cb0ef41Sopenharmony_cisub ::DWP { &get_mem("DWORD",@_); } 811cb0ef41Sopenharmony_cisub ::WP { &get_mem("WORD",@_); } 821cb0ef41Sopenharmony_cisub ::QWP { &get_mem("",@_); } 831cb0ef41Sopenharmony_cisub ::BC { (($::mwerks)?"":"BYTE ")."@_"; } 841cb0ef41Sopenharmony_cisub ::DWC { (($::mwerks)?"":"DWORD ")."@_"; } 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_cisub ::file 871cb0ef41Sopenharmony_ci{ if ($::mwerks) { push(@out,".section\t.text,64\n"); } 881cb0ef41Sopenharmony_ci else 891cb0ef41Sopenharmony_ci { my $tmp=<<___; 901cb0ef41Sopenharmony_ci%ifidn __OUTPUT_FORMAT__,obj 911cb0ef41Sopenharmony_cisection code use32 class=code align=64 921cb0ef41Sopenharmony_ci%elifidn __OUTPUT_FORMAT__,win32 931cb0ef41Sopenharmony_ci\$\@feat.00 equ 1 941cb0ef41Sopenharmony_cisection .text code align=64 951cb0ef41Sopenharmony_ci%else 961cb0ef41Sopenharmony_cisection .text code 971cb0ef41Sopenharmony_ci%endif 981cb0ef41Sopenharmony_ci___ 991cb0ef41Sopenharmony_ci push(@out,$tmp); 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci} 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_cisub ::function_begin_B 1041cb0ef41Sopenharmony_ci{ my $func=shift; 1051cb0ef41Sopenharmony_ci my $global=($func !~ /^_/); 1061cb0ef41Sopenharmony_ci my $begin="${::lbdecor}_${func}_begin"; 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci $begin =~ s/^\@/./ if ($::mwerks); # the torture never stops 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci &::LABEL($func,$global?"$begin":"$nmdecor$func"); 1111cb0ef41Sopenharmony_ci $func=$nmdecor.$func; 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci push(@out,"${drdecor}global $func\n") if ($global); 1141cb0ef41Sopenharmony_ci push(@out,"${drdecor}align 16\n"); 1151cb0ef41Sopenharmony_ci push(@out,"$func:\n"); 1161cb0ef41Sopenharmony_ci push(@out,"$begin:\n") if ($global); 1171cb0ef41Sopenharmony_ci $::stack=4; 1181cb0ef41Sopenharmony_ci} 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_cisub ::function_end_B 1211cb0ef41Sopenharmony_ci{ $::stack=0; 1221cb0ef41Sopenharmony_ci &::wipe_labels(); 1231cb0ef41Sopenharmony_ci} 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_cisub ::file_end 1261cb0ef41Sopenharmony_ci{ if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out) 1271cb0ef41Sopenharmony_ci { my $comm=<<___; 1281cb0ef41Sopenharmony_ci${drdecor}segment .bss 1291cb0ef41Sopenharmony_ci${drdecor}common ${nmdecor}OPENSSL_ia32cap_P 16 1301cb0ef41Sopenharmony_ci___ 1311cb0ef41Sopenharmony_ci # comment out OPENSSL_ia32cap_P declarations 1321cb0ef41Sopenharmony_ci grep {s/(^extern\s+${nmdecor}OPENSSL_ia32cap_P)/\;$1/} @out; 1331cb0ef41Sopenharmony_ci push (@out,$comm) 1341cb0ef41Sopenharmony_ci } 1351cb0ef41Sopenharmony_ci push (@out,$initseg) if ($initseg); 1361cb0ef41Sopenharmony_ci} 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_cisub ::comment { foreach (@_) { push(@out,"\t; $_\n"); } } 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_cisub ::external_label 1411cb0ef41Sopenharmony_ci{ foreach(@_) 1421cb0ef41Sopenharmony_ci { push(@out,"${drdecor}extern\t".&::LABEL($_,$nmdecor.$_)."\n"); } 1431cb0ef41Sopenharmony_ci} 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_cisub ::public_label 1461cb0ef41Sopenharmony_ci{ push(@out,"${drdecor}global\t".&::LABEL($_[0],$nmdecor.$_[0])."\n"); } 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_cisub ::data_byte 1491cb0ef41Sopenharmony_ci{ push(@out,(($::mwerks)?".byte\t":"db\t").join(',',@_)."\n"); } 1501cb0ef41Sopenharmony_cisub ::data_short 1511cb0ef41Sopenharmony_ci{ push(@out,(($::mwerks)?".word\t":"dw\t").join(',',@_)."\n"); } 1521cb0ef41Sopenharmony_cisub ::data_word 1531cb0ef41Sopenharmony_ci{ push(@out,(($::mwerks)?".long\t":"dd\t").join(',',@_)."\n"); } 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_cisub ::align 1561cb0ef41Sopenharmony_ci{ push(@out,"${drdecor}align\t$_[0]\n"); } 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_cisub ::picmeup 1591cb0ef41Sopenharmony_ci{ my($dst,$sym)=@_; 1601cb0ef41Sopenharmony_ci &::lea($dst,&::DWP($sym)); 1611cb0ef41Sopenharmony_ci} 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_cisub ::initseg 1641cb0ef41Sopenharmony_ci{ my $f=$nmdecor.shift; 1651cb0ef41Sopenharmony_ci if ($::win32) 1661cb0ef41Sopenharmony_ci { $initseg=<<___; 1671cb0ef41Sopenharmony_cisegment .CRT\$XCU data align=4 1681cb0ef41Sopenharmony_ciextern $f 1691cb0ef41Sopenharmony_cidd $f 1701cb0ef41Sopenharmony_ci___ 1711cb0ef41Sopenharmony_ci } 1721cb0ef41Sopenharmony_ci} 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_cisub ::dataseg 1751cb0ef41Sopenharmony_ci{ if ($mwerks) { push(@out,".section\t.data,4\n"); } 1761cb0ef41Sopenharmony_ci else { push(@out,"section\t.data align=4\n"); } 1771cb0ef41Sopenharmony_ci} 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_cisub ::safeseh 1801cb0ef41Sopenharmony_ci{ my $nm=shift; 1811cb0ef41Sopenharmony_ci push(@out,"%if __NASM_VERSION_ID__ >= 0x02030000\n"); 1821cb0ef41Sopenharmony_ci push(@out,"safeseh ".&::LABEL($nm,$nmdecor.$nm)."\n"); 1831cb0ef41Sopenharmony_ci push(@out,"%endif\n"); 1841cb0ef41Sopenharmony_ci} 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci1; 187