1#!/usr/bin/perl 2 3# Copyright 2015, VIXL authors 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are met: 8# 9# * Redistributions of source code must retain the above copyright notice, 10# this list of conditions and the following disclaimer. 11# * Redistributions in binary form must reproduce the above copyright notice, 12# this list of conditions and the following disclaimer in the documentation 13# and/or other materials provided with the distribution. 14# * Neither the name of ARM Limited nor the names of its contributors may be 15# used to endorse or promote products derived from this software without 16# specific prior written permission. 17# 18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 19# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29use v5.10.1; 30no warnings 'experimental::smartmatch'; 31 32# Assembler header file. 33my $hfile = "src/aarch64/assembler-aarch64.h"; 34 35# Extra pseudo instructions added to AArch64. 36my @extras = qw/bind debug dci dc32 dc64 place/; 37 38# SVE instructions that can't be inferred from their argument types. 39my @sves = qw/addvl addpl rdvl cntb cnth cntw cntd ctermeq ctermne setffr/; 40 41my %inst = (); # Global hash of instructions. 42 43# Set record separator to one or more consecutive new lines. This causes $_ to 44# be assigned a 'paragraph' of text for each iteration of the while loop. 45$/ = ''; 46 47open(IN, "<$hfile") or die("Can't open header file $hfile.\n"); 48while(<IN>) 49{ 50 # Find a function formatted like an instruction. 51 if(my($t) = /^ ((?:void|inline void) [a-z][a-z0-9]{0,9}_?)\(/mgp) 52 { 53 # Everything before the function match, ie. the comments. 54 my $before = ${^PREMATCH}; 55 56 # Everything after the function match, ie. arguments to the function, if 57 # any, and the closing parenthesis and semi-colon. 58 my $after = ${^POSTMATCH}; 59 60 # Extract the instruction. 61 my($i) = $t =~ /(?:void|inline void) ([a-z][a-z0-9]{0,9})/; 62 63 # Extract the comment from before the function. Drop comment characters 64 # and format the architecture version suffix, if present. 65 my $d = $before; 66 $d =~ s|^ // ||; # Delete comment chars from first line. 67 $d =~ s|\n //||g; # Delete comment chars from subsequent lines. 68 $d =~ s|\n$||; # Delete trailing new line. 69 $d =~ s|\[Armv(.+)\]|_\(Armv$1\)_|gi; 70 71 # Drop any templating that may have prefixed the prototype, and has now 72 # found its way into the description. 73 $d =~ s|\n template <.*>$||g; 74 75 # Extract and tidy up the function prototype. 76 my($p) = $after =~ /(.*?\))/ms; 77 $p =~ s/\n/\n /g; 78 $p = "$t(".$p; 79 80 # Establish the type of the instruction. 81 my $type = 'integer'; 82 if ($p =~ /([PZ]Register|SVEMemOperand)/) { 83 $type = 'sve'; 84 } elsif ($i =~ /[su]?q?(inc|dec)[bhwd]/ || $i ~~ @sves) { 85 $type = 'sve'; 86 } elsif ($p =~ /VRegister/) { 87 $type = 'float'; 88 } 89 ($i ~~ @extras) and $type = 'pseudo'; 90 91 # Special case to distinguish dc() the data constant placing function from 92 # dc() the data cache maintenance instruction. 93 if (($i eq 'dc') and ($p =~ /\(T data\)/)) { 94 $type = 'pseudo'; 95 } 96 97 # Push the results into a hash keyed by prototype string. 98 $inst{$p}->{'type'} = $type; 99 $inst{$p}->{'mnemonic'} = $i; 100 $inst{$p}->{'description'} = $d; 101 $inst{$p}->{'initial'} = substr($i, 0, 1); 102 } 103} 104close(IN); 105 106my $links = get_links_list(\%inst); 107 108print <<HEADER; 109VIXL Supported Instruction List 110=============================== 111 112This is a list of the AArch64 instructions supported by the VIXL assembler, 113disassembler and simulator. The simulator may not support all floating point 114operations to the precision required by AArch64 - please check the simulator 115source code for details. 116 117#### AAch64 integer instructions #### 118$links->{'integer'} 119 120#### AArch64 floating point and NEON instructions #### 121$links->{'float'} 122 123#### AArch64 Scalable Vector Extension (SVE) instructions #### 124$links->{'sve'} 125 126#### Additional or pseudo instructions #### 127$links->{'pseudo'} 128 129___ 130 131HEADER 132 133print describe_insts('AArch64 integer instructions', 'integer'); 134print describe_insts('AArch64 floating point and NEON instructions', 'float'); 135print describe_insts('AArch64 Scalable Vector Extension (SVE) instructions', 'sve'); 136print describe_insts('Additional or pseudo instructions', 'pseudo'); 137 138# Get a hash of links to each initialed section of the document, keyed by type. 139sub get_links_list { 140 my $insts = shift; 141 my %initials; 142 foreach my $i (sort(keys(%$insts))) { 143 my $inst = $insts->{$i}; 144 $initials{$inst->{type}}->{$inst->{initial}}++; 145 } 146 my %result; 147 foreach my $t (keys(%initials)) { 148 foreach my $i (sort(keys(%{$initials{$t}}))) { 149 push(@{$result{$t}}, "[$i](#$t-$i)"); 150 } 151 $result{$t} = join(' ', @{$result{$t}}); 152 } 153 return \%result; 154} 155 156# Sort instructions by mnemonic and then description. 157sub inst_sort 158{ 159 $inst{$a}->{'mnemonic'} cmp $inst{$b}->{'mnemonic'} || 160 $inst{$a}->{'description'} cmp $inst{$b}->{'description'} || 161 $a cmp $b; 162} 163 164# Return a Markdown formatted list of instructions of a particular type. 165sub describe_insts 166{ 167 my($title, $type) = @_; 168 my $result = ''; 169 $result .= "$title\n"; 170 $result .= '-' x length($title); 171 $result .= "\n\n"; 172 173 my $last_initial = ''; 174 foreach my $i (sort inst_sort keys(%inst)) 175 { 176 next if($inst{$i}->{'type'} ne $type); 177 unless ($last_initial eq $inst{$i}->{'initial'}) { 178 $last_initial = $inst{$i}->{'initial'}; 179 $result .= sprintf("<a id=\"%s-%s\">\n\n", lc($type), $last_initial); 180 } 181 $result .= sprintf("### %s ###\n\n%s\n\n", 182 uc($inst{$i}->{'mnemonic'}), 183 $inst{$i}->{'description'}); 184 $result .= " $i\n\n\n"; 185 } 186 $result .= "\n"; 187 return $result 188} 189 190 191