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