Blame crypto/perlasm/arm-xlate.pl

Packit c4476c
#! /usr/bin/env perl
Packit c4476c
# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
Packit c4476c
#
Packit c4476c
# Licensed under the OpenSSL license (the "License").  You may not use
Packit c4476c
# this file except in compliance with the License.  You can obtain a copy
Packit c4476c
# in the file LICENSE in the source distribution or at
Packit c4476c
# https://www.openssl.org/source/license.html
Packit c4476c
Packit c4476c
use strict;
Packit c4476c
Packit c4476c
my $flavour = shift;
Packit c4476c
my $output = shift;
Packit c4476c
open STDOUT,">$output" || die "can't open $output: $!";
Packit c4476c
Packit c4476c
$flavour = "linux32" if (!$flavour or $flavour eq "void");
Packit c4476c
Packit c4476c
my %GLOBALS;
Packit c4476c
my $dotinlocallabels=($flavour=~/linux/)?1:0;
Packit c4476c
Packit c4476c
################################################################
Packit c4476c
# directives which need special treatment on different platforms
Packit c4476c
################################################################
Packit c4476c
my $arch = sub {
Packit c4476c
    if ($flavour =~ /linux/)	{ ".arch\t".join(',',@_); }
Packit c4476c
    else			{ ""; }
Packit c4476c
};
Packit c4476c
my $fpu = sub {
Packit c4476c
    if ($flavour =~ /linux/)	{ ".fpu\t".join(',',@_); }
Packit c4476c
    else			{ ""; }
Packit c4476c
};
Packit c4476c
my $hidden = sub {
Packit c4476c
    if ($flavour =~ /ios/)	{ ".private_extern\t".join(',',@_); }
Packit c4476c
    else			{ ".hidden\t".join(',',@_); }
Packit c4476c
};
Packit c4476c
my $comm = sub {
Packit c4476c
    my @args = split(/,\s*/,shift);
Packit c4476c
    my $name = @args[0];
Packit c4476c
    my $global = \$GLOBALS{$name};
Packit c4476c
    my $ret;
Packit c4476c
Packit c4476c
    if ($flavour =~ /ios32/)	{
Packit c4476c
	$ret = ".comm\t_$name,@args[1]\n";
Packit c4476c
	$ret .= ".non_lazy_symbol_pointer\n";
Packit c4476c
	$ret .= "$name:\n";
Packit c4476c
	$ret .= ".indirect_symbol\t_$name\n";
Packit c4476c
	$ret .= ".long\t0";
Packit c4476c
	$name = "_$name";
Packit c4476c
    } else			{ $ret = ".comm\t".join(',',@args); }
Packit c4476c
Packit c4476c
    $$global = $name;
Packit c4476c
    $ret;
Packit c4476c
};
Packit c4476c
my $globl = sub {
Packit c4476c
    my $name = shift;
Packit c4476c
    my $global = \$GLOBALS{$name};
Packit c4476c
    my $ret;
Packit c4476c
Packit c4476c
    SWITCH: for ($flavour) {
Packit c4476c
	/ios/		&& do { $name = "_$name";
Packit c4476c
				last;
Packit c4476c
			      };
Packit c4476c
    }
Packit c4476c
Packit c4476c
    $ret = ".globl	$name" if (!$ret);
Packit c4476c
    $$global = $name;
Packit c4476c
    $ret;
Packit c4476c
};
Packit c4476c
my $global = $globl;
Packit c4476c
my $extern = sub {
Packit c4476c
    &$globl(@_);
Packit c4476c
    return;	# return nothing
Packit c4476c
};
Packit c4476c
my $type = sub {
Packit c4476c
    if ($flavour =~ /linux/)	{ ".type\t".join(',',@_); }
Packit c4476c
    elsif ($flavour =~ /ios32/)	{ if (join(',',@_) =~ /(\w+),%function/) {
Packit c4476c
					"#ifdef __thumb2__\n".
Packit c4476c
					".thumb_func	$1\n".
Packit c4476c
					"#endif";
Packit c4476c
				  }
Packit c4476c
			        }
Packit c4476c
    else			{ ""; }
Packit c4476c
};
Packit c4476c
my $size = sub {
Packit c4476c
    if ($flavour =~ /linux/)	{ ".size\t".join(',',@_); }
Packit c4476c
    else			{ ""; }
Packit c4476c
};
Packit c4476c
my $inst = sub {
Packit c4476c
    if ($flavour =~ /linux/)    { ".inst\t".join(',',@_); }
Packit c4476c
    else                        { ".long\t".join(',',@_); }
Packit c4476c
};
Packit c4476c
my $asciz = sub {
Packit c4476c
    my $line = join(",",@_);
Packit c4476c
    if ($line =~ /^"(.*)"$/)
Packit c4476c
    {	".byte	" . join(",",unpack("C*",$1),0) . "\n.align	2";	}
Packit c4476c
    else
Packit c4476c
    {	"";	}
Packit c4476c
};
Packit c4476c
Packit c4476c
sub range {
Packit c4476c
  my ($r,$sfx,$start,$end) = @_;
Packit c4476c
Packit c4476c
    join(",",map("$r$_$sfx",($start..$end)));
Packit c4476c
}
Packit c4476c
Packit c4476c
sub expand_line {
Packit c4476c
  my $line = shift;
Packit c4476c
  my @ret = ();
Packit c4476c
Packit c4476c
    pos($line)=0;
Packit c4476c
Packit c4476c
    while ($line =~ m/\G[^@\/\{\"]*/g) {
Packit c4476c
	if ($line =~ m/\G(@|\/\/|$)/gc) {
Packit c4476c
	    last;
Packit c4476c
	}
Packit c4476c
	elsif ($line =~ m/\G\{/gc) {
Packit c4476c
	    my $saved_pos = pos($line);
Packit c4476c
	    $line =~ s/\G([rdqv])([0-9]+)([^\-]*)\-\1([0-9]+)\3/range($1,$3,$2,$4)/e;
Packit c4476c
	    pos($line) = $saved_pos;
Packit c4476c
	    $line =~ m/\G[^\}]*\}/g;
Packit c4476c
	}
Packit c4476c
	elsif ($line =~ m/\G\"/gc) {
Packit c4476c
	    $line =~ m/\G[^\"]*\"/g;
Packit c4476c
	}
Packit c4476c
    }
Packit c4476c
Packit c4476c
    $line =~ s/\b(\w+)/$GLOBALS{$1} or $1/ge;
Packit c4476c
Packit c4476c
    return $line;
Packit c4476c
}
Packit c4476c
Packit c4476c
while(my $line=<>) {
Packit c4476c
Packit c4476c
    if ($line =~ m/^\s*(#|@|\/\/)/)	{ print $line; next; }
Packit c4476c
Packit c4476c
    $line =~ s|/\*.*\*/||;	# get rid of C-style comments...
Packit c4476c
    $line =~ s|^\s+||;		# ... and skip white spaces in beginning...
Packit c4476c
    $line =~ s|\s+$||;		# ... and at the end
Packit c4476c
Packit c4476c
    {
Packit c4476c
	$line =~ s|[\b\.]L(\w{2,})|L$1|g;	# common denominator for Locallabel
Packit c4476c
	$line =~ s|\bL(\w{2,})|\.L$1|g	if ($dotinlocallabels);
Packit c4476c
    }
Packit c4476c
Packit c4476c
    {
Packit c4476c
	$line =~ s|(^[\.\w]+)\:\s*||;
Packit c4476c
	my $label = $1;
Packit c4476c
	if ($label) {
Packit c4476c
	    printf "%s:",($GLOBALS{$label} or $label);
Packit c4476c
	}
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if ($line !~ m/^[#@]/) {
Packit c4476c
	$line =~ s|^\s*(\.?)(\S+)\s*||;
Packit c4476c
	my $c = $1; $c = "\t" if ($c eq "");
Packit c4476c
	my $mnemonic = $2;
Packit c4476c
	my $opcode;
Packit c4476c
	if ($mnemonic =~ m/([^\.]+)\.([^\.]+)/) {
Packit c4476c
	    $opcode = eval("\$$1_$2");
Packit c4476c
	} else {
Packit c4476c
	    $opcode = eval("\$$mnemonic");
Packit c4476c
	}
Packit c4476c
Packit c4476c
	my $arg=expand_line($line);
Packit c4476c
Packit c4476c
	if (ref($opcode) eq 'CODE') {
Packit c4476c
		$line = &$opcode($arg);
Packit c4476c
	} elsif ($mnemonic)         {
Packit c4476c
		$line = $c.$mnemonic;
Packit c4476c
		$line.= "\t$arg" if ($arg ne "");
Packit c4476c
	}
Packit c4476c
    }
Packit c4476c
Packit c4476c
    print $line if ($line);
Packit c4476c
    print "\n";
Packit c4476c
}
Packit c4476c
Packit c4476c
close STDOUT or die "error closing STDOUT: $!";