summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Storsjö <[email protected]>2024-02-15 14:56:50 +0200
committerMartin Storsjö <[email protected]>2025-09-13 20:58:29 +0000
commita3ce337926d097c23464b55d69d37adc9913d3c5 (patch)
treeff165808c1917636860b2c026abaa32a0f03fe17
parent0ba0cf94dbb038daeafc608fb2216a5d1ce9a806 (diff)
tools: Add scripts for indenting and checking aarch64 assembly
The same also applies for arm assembly, but there are more known deviations within that. Add a script which checks all files, except for a few known files that deviate, for various reasons.
-rwxr-xr-xtools/check_arm_indent.sh54
-rwxr-xr-xtools/indent_arm_assembly.pl205
2 files changed, 259 insertions, 0 deletions
diff --git a/tools/check_arm_indent.sh b/tools/check_arm_indent.sh
new file mode 100755
index 0000000000..b8bc7b1eb7
--- /dev/null
+++ b/tools/check_arm_indent.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+#
+# Copyright (c) 2025 Martin Storsjo
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+cd $(dirname $0)/..
+
+if [ "$1" = "--apply" ]; then
+ apply=1
+fi
+
+ret=0
+
+for i in */aarch64/*.S */aarch64/*/*.S; do
+ case $i in
+ libavcodec/aarch64/h264idct_neon.S|libavcodec/aarch64/h26x/epel_neon.S|libavcodec/aarch64/h26x/qpel_neon.S|libavcodec/aarch64/vc1dsp_neon.S)
+ # Skip files with known (and tolerated) deviations from the tool.
+ continue
+ esac
+ cat $i | ./tools/indent_arm_assembly.pl > tmp.S
+ if [ -n "$apply" ]; then
+ mv tmp.S $i
+ continue
+ fi
+ if ! PAGER=cat git diff --no-index $i tmp.S; then
+ ret=1
+ fi
+done
+
+rm -f tmp.S
+
+exit $ret
diff --git a/tools/indent_arm_assembly.pl b/tools/indent_arm_assembly.pl
new file mode 100755
index 0000000000..7d5d1ecef2
--- /dev/null
+++ b/tools/indent_arm_assembly.pl
@@ -0,0 +1,205 @@
+#!/usr/bin/env perl
+#
+# Copyright (c) 2025 Martin Storsjo
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+# A script for reformatting ARM/AArch64 assembly according to the following
+# style:
+# - Instructions start after 8 columns, operands start after 24 columns
+# - Vector register layouts and modifiers like "uxtw" are written in lowercase
+# - Optionally align operand columns vertically according to their
+# maximum width (accommodating for e.g. x0 vs x10, or v0.8b vs v16.16b).
+#
+# The input code is passed to stdin, and the reformatted code is written
+# on stdout.
+
+use strict;
+
+my $indent_operands = 0;
+my $instr_indent = 8;
+my $operand_indent = 24;
+my $match_indent = 0;
+
+while (@ARGV) {
+ my $opt = shift;
+
+ if ($opt eq "-operands") {
+ $indent_operands = 1;
+ } elsif ($opt eq "-indent") {
+ $instr_indent = shift;
+ } elsif ($opt eq "-operand-indent") {
+ $operand_indent = shift;
+ } elsif ($opt eq "-match-indent") {
+ $match_indent = 1;
+ } else {
+ die "Unrecognized parameter $opt\n";
+ }
+}
+
+if ($operand_indent < $instr_indent) {
+ die "Can't indent operands to $operand_indent while indenting " .
+ "instructions to $instr_indent\n";
+}
+
+# Return a string consisting of n spaces
+sub spaces {
+ my $n = $_[0];
+ return " " x $n;
+}
+
+sub indentcolumns {
+ my $input = $_[0];
+ my $chars = $_[1];
+ my @operands = split(/,/, $input);
+ my $num = @operands;
+ my $ret = "";
+ for (my $i = 0; $i < $num; $i++) {
+ my $cur = $operands[$i];
+ # Trim out leading/trailing whitespace
+ $cur =~ s/^\s+|\s+$//g;
+ $ret .= $cur;
+ if ($i + 1 < $num) {
+ # If we have a following operand, add a comma and whitespace to
+ # align the next operand.
+ my $next = $operands[$i+1];
+ my $len = length($cur);
+ if ($len > $chars) {
+ # If this operand was too wide for the intended column width,
+ # don't try to realign the line at all, just return the input
+ # untouched.
+ return $input;
+ }
+ my $pad = $chars - $len;
+ if ($next =~ /[su]xt[bhw]|[la]s[lr]/) {
+ # If the next item isn't a regular operand, but a modifier,
+ # don't try to align that. E.g. "add x0, x0, w1, uxtw #1".
+ $pad = 0;
+ }
+ $ret .= "," . spaces(1 + $pad);
+ }
+ }
+ return $ret;
+}
+
+# Realign the operands part of an instruction line, making each operand
+# take up the maximum width for that kind of operand.
+sub columns {
+ my $rest = $_[0];
+ if ($rest !~ /,/) {
+ # No commas, no operands to split and align
+ return $rest;
+ }
+ if ($rest =~ /{|[^\w]\[/) {
+ # Check for instructions that use register ranges, like {v0.8b,v1.8b}
+ # or mem address operands, like "ldr x0, [sp]" - we skip trying to
+ # realign these.
+ return $rest;
+ }
+ if ($rest =~ /v[0-9]+\.[0-9]+[bhsd]/) {
+ # If we have references to aarch64 style vector registers, like
+ # v0.8b, then align all operands to the maximum width of such
+ # operands - v16.16b.
+ #
+ # TODO: Ideally, we'd handle mixed operand types individually.
+ return indentcolumns($rest, 7);
+ }
+ # Indent operands according to the maximum width of regular registers,
+ # like x10.
+ return indentcolumns($rest, 3);
+}
+
+while (<STDIN>) {
+ # Trim off trailing whitespace.
+ chomp;
+ if (/^([\.\w\d]+:)?(\s+)([\w\\][\w\\\.]*)(?:(\s+)(.*)|$)/) {
+ my $label = $1;
+ my $indent = $2;
+ my $instr = $3;
+ my $origspace = $4;
+ my $rest = $5;
+
+ my $orig_operand_indent = length($label) + length($indent) +
+ length($instr) + length($origspace);
+
+ if ($indent_operands) {
+ $rest = columns($rest);
+ }
+
+ my $size = $instr_indent;
+ if ($match_indent) {
+ # Try to check the current attempted indent size and normalize
+ # to it; match existing ident sizes of 4, 8, 10 and 12 columns.
+ my $cur_indent = length($label) + length($indent);
+ if ($cur_indent >= 3 && $cur_indent <= 5) {
+ $size = 4;
+ } elsif ($cur_indent >= 7 && $cur_indent <= 9) {
+ $size = 8;
+ } elsif ($cur_indent == 10 || $cur_indent == 12) {
+ $size = $cur_indent;
+ }
+ }
+ if (length($label) >= $size) {
+ # Not enough space for the label; just add a space between the label
+ # and the instruction.
+ $indent = " ";
+ } else {
+ $indent = spaces($size - length($label));
+ }
+
+ my $instr_end = length($label) + length($indent) + length($instr);
+ $size = $operand_indent - $instr_end;
+ if ($match_indent) {
+ # Check how the operands currently seem to be indented.
+ my $cur_indent = $orig_operand_indent;
+ if ($cur_indent >= 11 && $cur_indent <= 13) {
+ $size = 12;
+ } elsif ($cur_indent >= 14 && $cur_indent <= 17) {
+ $size = 16;
+ } elsif ($cur_indent >= 18 && $cur_indent <= 22) {
+ $size = 20;
+ } elsif ($cur_indent >= 23 && $cur_indent <= 27) {
+ $size = 24;
+ }
+ $size -= $instr_end;
+ }
+ my $operand_space = " ";
+ if ($size > 0) {
+ $operand_space = spaces($size);
+ }
+
+ # Lowercase the aarch64 vector layout description, .8B -> .8b
+ $rest =~ s/(\.[84216]*[BHSD])/lc($1)/ge;
+ # Lowercase modifiers like "uxtw" or "lsl"
+ $rest =~ s/([SU]XT[BWH]|[LA]S[LR])/lc($1)/ge;
+
+ # Reassemble the line
+ if ($rest eq "") {
+ $_ = $label . $indent . $instr;
+ } else {
+ $_ = $label . $indent . $instr . $operand_space . $rest;
+ }
+ }
+ print $_ . "\n";
+}