perlasm/x86_64-xlate.pl: refine sign extension in ea package.
authorAndy Polyakov <appro@openssl.org>
Fri, 9 Dec 2016 14:26:19 +0000 (15:26 +0100)
committerAndy Polyakov <appro@openssl.org>
Mon, 12 Dec 2016 10:02:43 +0000 (11:02 +0100)
$1<<32>>32 worked fine with either 32- or 64-bit perl for a good while,
relying on quirk that [pure] 32-bit perl performed it as $1<<0>>0. But
this apparently changed in some version past minimally required 5.10,
and operation result became 0. Yet, it went unnoticed for another while,
because most perl package providers configure their packages with
-Duse64bitint option.

Reviewed-by: Rich Salz <rsalz@openssl.org>
(cherry picked from commit 82e089308bd9a7794a45f0fa3973d7659420fbd8)

crypto/perlasm/x86_64-xlate.pl

index 617adf9a3850bbd5bf1a211b9afff71fbd5ab9ef..2d9e1a1cc4966fcfc684a10bf47d535403041907 100755 (executable)
@@ -262,11 +262,18 @@ my %globals;
        $self->{base}  =~ s/^[er](.?[0-9xpi])[d]?$/r\1/;
 
        # Solaris /usr/ccs/bin/as can't handle multiplications
-       # in $self->{label}, new gas requires sign extension...
+       # in $self->{label}...
        use integer;
        $self->{label} =~ s/(?<![\w\$\.])(0x?[0-9a-f]+)/oct($1)/egi;
        $self->{label} =~ s/\b([0-9]+\s*[\*\/\%]\s*[0-9]+)\b/eval($1)/eg;
-       $self->{label} =~ s/\b([0-9]+)\b/$1<<32>>32/eg;
+
+       # Some assemblers insist on signed presentation of 32-bit
+       # offsets, but sign extension is a tricky business in perl...
+       if ((1<<31)<<1) {
+           $self->{label} =~ s/\b([0-9]+)\b/$1<<32>>32/eg;
+       } else {
+           $self->{label} =~ s/\b([0-9]+)\b/$1>>0/eg;
+       }
 
        if (!$self->{label} && $self->{index} && $self->{scale}==1 &&
            $self->{base} =~ /(rbp|r13)/) {