perlasm/x86_64-xlate.pl: refine sign extension in ea package.
[oweals/openssl.git] / crypto / perlasm / x86_64-xlate.pl
index 60b98d74075e3ce7ff4178766623619bfd42ab04..4298b3f418c89227ded643202d694be23c8deff9 100755 (executable)
@@ -151,7 +151,7 @@ my %globals;
        if ($gas) {
            if ($self->{op} eq "movz") {        # movz is pain...
                sprintf "%s%s%s",$self->{op},$self->{sz},shift;
-           } elsif ($self->{op} =~ /^set/) { 
+           } elsif ($self->{op} =~ /^set/) {
                "$self->{op}";
            } elsif ($self->{op} eq "ret") {
                my $epilogue = "";
@@ -178,7 +178,7 @@ my %globals;
                $self->{op} .= $self->{sz};
            } elsif ($self->{op} eq "call" && $current_segment eq ".CRT\$XCU") {
                $self->{op} = "\tDQ";
-           } 
+           }
            $self->{op};
        }
     }
@@ -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)/) {
@@ -639,7 +646,7 @@ my %globals;
                                                        if ($sz eq "D" && ($current_segment=~/.[px]data/ || $dir eq ".rva"))
                                                        { $var=~s/([_a-z\$\@][_a-z0-9\$\@]*)/$nasm?"$1 wrt ..imagebase":"imagerel $1"/egi; }
                                                        $var;
-                                                   };  
+                                                   };
 
                                    $sz =~ tr/bvlrq/BWDDQ/;
                                    $self->{value} = "\tD$sz\t";
@@ -649,7 +656,7 @@ my %globals;
                                  };
                /\.byte/    && do { my @str=split(/,\s*/,$$line);
                                    map(s/(0b[0-1]+)/oct($1)/eig,@str);
-                                   map(s/0x([0-9a-f]+)/0$1h/ig,@str) if ($masm);       
+                                   map(s/0x([0-9a-f]+)/0$1h/ig,@str) if ($masm);
                                    while ($#str>15) {
                                        $self->{value}.="DB\t"
                                                .join(",",@str[0..15])."\n";
@@ -805,7 +812,7 @@ my $rdrand = sub {
       my @opcode=();
       my $dst=$1;
        if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; }
-       rex(\@opcode,0,$1,8);
+       rex(\@opcode,0,$dst,8);
        push @opcode,0x0f,0xc7,0xf0|($dst&7);
        @opcode;
     } else {
@@ -818,7 +825,7 @@ my $rdseed = sub {
       my @opcode=();
       my $dst=$1;
        if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; }
-       rex(\@opcode,0,$1,8);
+       rex(\@opcode,0,$dst,8);
        push @opcode,0x0f,0xc7,0xf8|($dst&7);
        @opcode;
     } else {
@@ -896,7 +903,7 @@ while(defined(my $line=<>)) {
        printf "%s",$directive->out();
     } elsif (my $opcode=opcode->re(\$line)) {
        my $asm = eval("\$".$opcode->mnemonic());
-       
+
        if ((ref($asm) eq 'CODE') && scalar(my @bytes=&$asm($line))) {
            print $gas?".byte\t":"DB\t",join(',',@bytes),"\n";
            next;
@@ -974,7 +981,7 @@ close STDOUT;
 # %r13         -               -
 # %r14         -               -
 # %r15         -               -
-# 
+#
 # (*)  volatile register
 # (-)  preserved by callee
 # (#)  Nth argument, volatile