---
I haven't been able to assemble prfum instructions with armasm64 yet;
dumpbin -disasm does disassemble the instruction correctly (e.g. from
an object file assembled with llvm), but armasm64 doesn't support
assembling it, either in that form or with a few variations I've tried.
In the simplest form, it fails like this:
test.asm(8) : error A2502: operand 1: Expected constant
prfum pldl1keep, [x0, #0]
The prfm instruction seems to be handled correctly though. Since
this prefetch instruction isn't essential, it can be worked around
by simply skipping the instruction.
---
gas-preprocessor.pl | 125 +++-
1 file changed, 104 insertions(+), 21 deletions(-)
diff --git a/gas-preprocessor.pl b/gas-preprocessor.pl
index 9bcdbac..a8cf1e0 100755
--- a/gas-preprocessor.pl
+++ b/gas-preprocessor.pl
@@ -245,7 +245,7 @@ my $thumb = 0;
my %thumb_labels;
my %call_targets;
-my %mov32_targets;
+my %import_symbols;
my %neon_alias_reg;
my %neon_alias_type;
@@ -626,6 +626,14 @@ sub is_arm_register {
return 0;
}
+sub is_aarch64_register {
+my $name = $_[0];
+if ($name =~ /^[xw]\d+$/) {
+return 1;
+}
+return 0;
+}
+
sub handle_local_label {
my $line = $_[0];
my $num = $_[1];
@@ -677,9 +685,9 @@ sub handle_serialized_line {
}
# handle GNU as pc-relative relocations for adrp/add
-if ($line =~ /(.*)\s*adrp([\w\s\d]+)\s*,\s*#?:pg_hi21:([^\s]+)/) {
+if ($line =~ /(.*)\s*adrp([\w\s\d]+)\s*,\s*#?:pg_hi21:([^\s]+)/ and
$as_type =~ /^apple-/) {
$line = "$1 adrp$2, ${3}\@PAGE\n";
-} elsif ($line =~
/(.*)\s*add([\w\s\d]+)\s*,([\w\s\d]+)\s*,\s*#?:lo12:([^\s]+)/) {
+} elsif ($line =~
/(.*)\s*add([\w\s\d]+)\s*,([\w\s\d]+)\s*,\s*#?:lo12:([^\s]+)/ and $as_type =~
/^apple-/) {
$line = "$1 add$2, $3, ${4}\@PAGEOFF\n";
}
@@ -797,8 +805,8 @@ sub handle_serialized_line {
if ($line =~
/^\s*(s|u)xtl(2)?\s+(v[0-3]?\d\.[248][hsdHSD])\s*,\s*(v[0-3]?\d\.(?:2|4|8|16)[bhsBHS])\b\s*$/)
{
$line = "$1shll$2 $3, $4, #0\n";
}
-# clang 3.4 does not automatically use shifted immediates in add/sub
-if ($as_type eq "clang" and
+# clang 3.4 and armasm64 do not automatically use shifted immediates
in add/sub
+if (($as_type eq "clang" or $as_type eq "armasm") and
$line =~ /^(\s*(?:add|sub)s?) ([^#l]+)#([\d\+\-\*\/ <>]+)\s*$/) {
my $imm = eval $3;
if ($imm > 4095 and not ($imm & 4095)) {
@@ -866,7 +874,7 @@ sub handle_serialized_line {
# Check branch instructions
-if ($line =~ /(?:^|\n)\s*(\w+\s*:\s*)?(bl?x?(..)?(\.w)?)\s+(\w+)/) {
+if ($line =~ /(?:^|\n)\s*(\w+\s*:\s*)?(bl?x?\.?(..)?(\.w)?)\s+(\w+)/) {
my $instr = $2;
my $cond = $3;
my $width = $4;
@@ -877,8 +885,19 @@ sub handle_serialized_line {
} elsif ($target =~ /^(\d+)([bf])$/) {
# The target is a local label
$line = handle_local_label($line, $1, $2);
-$line =~ s/\b$instr\b/$&.w/ if $width eq "";
-} elsif (!is_arm_register($target)) {
+$line =~ s/\b$instr\b/$&.w/ if $width eq "" and $arch eq "arm";
+} elsif (($arch eq "arm" and !is_arm_register($target)) or
+ ($arch eq "aarch64" and !is_aarch64_register($target))) {
+$call_targets{$target}++;
+}
+} elsif ($line =~
/(?:^|\n)\s*(\w+\s*:\s*)?(cbn?z|adr)\s+(\w+),\s*(\w+)/) {
+my $instr = $2;
+my $reg = $3;
+my $target = $4;
+if ($target =~ /^(\d+)([bf])$/) {
+# The target is a local label
+$line = handle_local_label($line, $1, $2);
+} else {
$call_targets{$target}++;
}
} elsif ($line =~ /^\s*.h?word.*\b\d+[bf]\b/) {
@@ -918,19 +937,78 @@ sub handle_serialized_line {
$line =~ s/\(\s*(\d+)\s*([<>])\s*(\d+)\s*\)/$val/;
}
-# Change a movw... #:lower16: into a mov32 pseudoinstruction
-$line =~ s/^(\s*)movw(\s+\w+\s*,\s*)\#:lower16:(.*)$/$1mov32$2$3/;
-# and remove the following, matching movt completely
-$line =~ s/^\s*movt\s+\w+\s*,\s*\#:upper16:.*$//;
+if ($arch eq "arm") {
+# Change a movw... #:lower16: into a mov32 pseudoinstruction
+$line =~ s/^(\s*)movw(\s+\w+\s*,\s*)\#:lower16:(.*)$/$1mov32$2$3/;
+# and remove the following, matching movt completely
+$line =~ s/^\s*movt\s+\w+\s*,\s*\#:upper16:.*$//;
-if ($line =~ /^\s*mov32\s+\w+,\s*([a-zA-Z]\w*)/) {
-$mov32_targets{$1}++;
-}
+if ($line =~ /^\s*mov32\s+\w+,\s*([a-zA-Z]\w*)/) {
+$import_symbols{$1}++;
+}
-# Misc bugs/deficiencies:
-# armasm seems unable to parse e.g. "vmov s0, s1" without