diff options
author | Andy Polyakov <appro@openssl.org> | 2006-04-30 21:15:29 +0000 |
---|---|---|
committer | Andy Polyakov <appro@openssl.org> | 2006-04-30 21:15:29 +0000 |
commit | 2c5d4daac5d23416ab619bfbcb0189227ffdf71f (patch) | |
tree | a7e6dbaba67a395b68a2a738654504a2929640f3 /crypto/perlasm/ppc-xlate.pl | |
parent | b46343583c1172c6e0fcad3227cf50622aae7998 (diff) |
Yet another "teaser" Montgomery multiplication module, for PowerPC.
Diffstat (limited to 'crypto/perlasm/ppc-xlate.pl')
-rwxr-xr-x | crypto/perlasm/ppc-xlate.pl | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/crypto/perlasm/ppc-xlate.pl b/crypto/perlasm/ppc-xlate.pl new file mode 100755 index 0000000000..31876e56b2 --- /dev/null +++ b/crypto/perlasm/ppc-xlate.pl @@ -0,0 +1,113 @@ +#!/usr/bin/env perl + +# PowerPC assembler distiller by <appro>. + +my $output = shift; +open STDOUT,">$output" || die "can't open $output: $!"; + +my $flavour = $output; +my %GLOBALS; +my $dotinlocallabels=0; + +################################################################ +# directives which need special treatment on different platforms +################################################################ +my $globl = sub { + my $junk = shift; + my $name = shift; + my $global = \$GLOBALS{$name}; + my $ret; + + $name =~ s|^[\.\_]||; + + SWITCH: for ($flavour) { + /aix/ && do { $name = ".$name"; + last; + }; + /osx/ && do { $name = "_$name"; + last; + }; + /linux.*32/ && do { $ret .= ".globl $name\n"; + $ret .= ".type $name,\@function"; + $dotinlocallabels = 1; + last; + }; + /linux.*64/ && do { $ret .= ".globl .$name\n"; + $ret .= ".type .$name,\@function\n"; + $ret .= ".section \".opd\",\"aw\"\n"; + $ret .= ".globl $name\n"; + $ret .= ".align 3\n"; + $ret .= "$name:\n"; + $ret .= ".quad .$name,.TOC.\@tocbase,0\n"; + $ret .= ".size $name,24\n"; + $ret .= ".previous\n"; + + $name = ".$name"; + $dotinlocallabels = 1; + last; + }; + } + + $ret = ".globl $name" if (!$ret); + $$global = $name; + $ret; +}; +my $machine = sub { + my $junk = shift; + my $arch = shift; + $arch = "ppc970" if ($arch eq "any" and $flavour =~ /osx/); + ".machine $arch"; +}; + +################################################################ +# simplified mnemonics not handled by at least one assembler +################################################################ +my $cmplw = sub { + my $f = shift; + my $cr = 0; $cr = shift if ($#_>1); + " cmpl$f ".join(',',$cr,0,@_); +}; +my $cmpld = sub { + my $f = shift; + my $cr = 0; $cr = shift if ($#_>1); + " cmpl$f ".join(',',$cr,1,@_); +}; +my $bdnz = sub { + my $f = shift; + my $bo = $f=~/[\+\-]/ ? 17 : 16; + " bc $bo,0,".shift; +}; + +while($line=<>) { + + $line =~ s|[#!;].*$||; # get rid of asm-style comments... + $line =~ s|/\*.*\*/||; # ... and C-style comments... + $line =~ s|^\s+||; # ... and skip white spaces in beginning... + $line =~ s|\s+$||; # ... and at the end + + { + $line =~ s|\b\.L(\w+)|L$1|g; # common denominator for Locallabel + $line =~ s|\bL(\w+)|\.L$1|g if ($dotinlocallabels); + } + + { + $line =~ s|(^[\.\w]+)\:\s*||; + my $label = $1; + printf "%s:",($GLOBALS{$label} or $label) if ($label); + } + + { + $line =~ s|^\s*(\.?)(\w+)([\.\+\-]?)\s*||; + my $c = $1; $c = "\t" if ($c eq ""); + my $mnemonic = $2; + my $f = $3; + my $opcode = eval("\$$mnemonic"); + if (ref($opcode) eq 'CODE') { $line = &$opcode($f,split(',',$line)); } + elsif ($mnemonic) { $line = $c.$mnemonic.$f."\t".$line; } + } + + print $line if ($line); + print "\n"; +} + +close STDOUT; |