1# Generate one sh*.s file for each architecture defined in sh-opc.h 2# This will contain all the instructions valid on that platform 3 4# Pull the architecture inheritance macros out of sh-opc.h 5# Pull all the insns out of the sh-opc.h file. 6while (<>) 7{ 8 chomp; 9 # Handle line continuation 10 if (s/\\$//) { 11 $_ .= <>; 12 redo unless eof(); 13 } 14 # Concat comment line and the next line 15 if (/^\s*\/\* 16 (?:\s*\S+){2} 17 \s+ ([^*]+?) 18 \s* \*\/ $ 19 /x) 20 { 21 $_ .= " "; 22 $_ .= <>; 23 redo unless eof(); 24 } 25 if (/#define\s+arch_([^ ]*)_up\s*\(([^)]*)\)/) 26 { 27 ($arches[$archcount] = $1) =~ tr/_/-/; 28 ($descendents[$archcount] = $2) =~ tr/_/-/; 29 $archcount += 1; 30 next; 31 } 32 # Special case: Match the repeat pseudo op 33 if (/^\s*\/\* 34 \s* repeat 35 \s+ start\s+end 36 \s+ ([^*]+?) # instruction operand 37 \s* \*\/ 38 \s* \{ 39 ((?:[^\}]+\}){2}) # 2 brace pairs (operands and nibbles) 40 \s* , 41 \s* arch_(\S+)_up # architecture name 42 \s* \} 43 /x) 44 { 45 $insns[$insncount] = "repeat 10 20 ".$1; 46 $insns_context[$insncount] = $_; 47 ($insns_arch[$insncount] = $3) =~ tr/_/-/; 48 $insncount += 1; 49 next; 50 } 51 # Match all 32 bit opcodes 52 if (/^\s*\/\* 53 (?:\s*\S+){2} 54 \s+ ([^*]+?) # instruction operand 55 \s* \*\/ 56 \s* \{ 57 ((?:[^\}]+\}){2}) # 2 brace pairs (operands and nibbles) 58 \s* , 59 \s* arch_(\S+)_up # architecture name 60 \s* \| 61 \s* arch_op32 62 \s* \} 63 /x) 64 { 65 $insns[$insncount] = $1; 66 $insns_context[$insncount] = $_; 67 ($insns_arch[$insncount] = $3) =~ tr/_/-/; 68 $insncount += 1; 69 next; 70 } 71 # Match all 16 bit opcodes 72 if (/^\s*\/\* 73 \s* \S+ 74 \s+ ([^*]+?) # instruction operand 75 \s* \*\/ 76 \s* \{ 77 ((?:[^\}]+\}){2}) # 2 brace pairs (operands and nibbles) 78 \s* , 79 \s* arch_(\S+)_up # architecture name 80 \s* \} 81 /x) 82 { 83 $insns[$insncount] = $1; 84 $insns_context[$insncount] = $_; 85 ($insns_arch[$insncount] = $3) =~ tr/_/-/; 86 $insncount += 1; 87 next; 88 } 89 # Match all remaining possible instructions (error detection) 90 if (/^\s*\/\* 91 (?:[^*]*(?:\*[^\/])?)+ # match contents of comment allowing * 92 \*\/ 93 \s* \{ 94 (?:[^\}]+\}){2} # 2 brace pairs (operands and nibbles) 95 \s* , 96 [^\}]* 97 arch 98 [^\}]* 99 \} 100 /x) 101 { 102 print ("Found something that looks like an instruction", 103 " but cannot be decoded:\n", "\t", $_); 104 next; 105 } 106} 107 108#print $insncount, "\n"; 109print $archcount, "\n"; 110 111# Munge the insns such that they will assemble 112# Each instruction in sh-opc.h has an example format 113# with placeholders for the parameters. These placeholders 114# need to be replaced with real registers and constants 115# as appropriate in order to assemble correctly. 116 117foreach $i (0 .. $insncount) { 118 $out = $insns[$i]; 119 if ($insns_context[$i] =~ /AY_.{3,4}_N/) { 120 $out =~ s/<REG_N>/r6/; 121 } else { 122 $out =~ s/<REG_N>/r4/; 123 } 124 $out =~ s/<REG_M>/r5/; 125 if ($insns_context[$i] =~ /IMM0_20BY8/) { 126 $out =~ s/<imm>/1024/; 127 } else { 128 $out =~ s/<imm>/4/; 129 } 130 $out =~ s/<bdisp\d*>/.+8/; 131 $out =~ s/<disp12>/2048/; 132 $out =~ s/<DISP12>/2048/; 133 $out =~ s/<disp\d*>/8/; 134 $out =~ s/Rn_BANK/r1_bank/; 135 $out =~ s/Rm_BANK/r2_bank/; 136 $out =~ s/<F_REG_N>/fr1/; 137 $out =~ s/<F_REG_M>/fr2/; 138 $out =~ s/<D_REG_N>/dr2/; 139 $out =~ s/<D_REG_M>/dr4/; 140 $out =~ s/<V_REG_[Nn]>/fv0/; 141 $out =~ s/<V_REG_M>/fv4/; 142 $out =~ s/<DX_REG_N>/xd2/; 143 $out =~ s/<DX_REG_M>/xd4/; 144 $out =~ s/XMTRX_M4/xmtrx/; 145 $out =~ s/<DSP_REG_X>/x1/; 146 $out =~ s/<DSP_REG_Y>/y0/; 147 $out =~ s/<DSP_REG_M>/a1/; 148 $out =~ s/<DSP_REG_N>/m0/; 149 $out =~ s/<REG_Axy>/r1/; 150 $out =~ s/<REG_Ayx>/r3/; 151 $out =~ s/<DSP_REG_XY>/y1/; 152 $out =~ s/<DSP_REG_YX>/y1/; 153 $out =~ s/<DSP_REG_AX>/a0/; 154 $out =~ s/<DSP_REG_AY>/a0/; 155 $out =~ s/Se/x0/; 156 $out =~ s/Sf/y0/; 157 $out =~ s/Dg/m0/; 158 if ($insns_context[$i] =~ /PPIC/) { 159 $out = "dct $out"; 160 } 161 if ($insns_context[$i] =~ /i8p4/) { 162 $out = ".align 2\n\t$out"; 163 } 164 # Write back the results. 165 # print ($out, "\n"); 166 $insns[$i] = $out; 167} 168 169# For each architecture, extract its immediate parents 170foreach $a (0 .. $archcount) { 171 $s = $descendents[$a]; 172 $s =~ s/[\s|]+/ /g; 173 @list = split(' ', $s); 174 while ($word = shift (@list)) { 175 if ($word =~ /^arch-(.*)-up$/) { 176 push @{$archtree{$1}}, $arches[$a]; 177 } 178 } 179} 180 181# Propagate the inhertances through the list 182# Iterate to ensure all inheritances are found (necessary?) 183$changesmade = 1; 184while ($changesmade) { 185 $changesmade = 0; 186 foreach $a (@arches) { 187 foreach $b (@arches) { 188 # If arch 'a' is a parent of arch 'b' then b inherits from a 189 if (grep {$_ eq $a} @{$archtree{$b}}) { 190 # Only add each arch if it is not already present 191 foreach $c (@{$archtree{$a}}) { 192 if ((grep {$_ eq $c} @{$archtree{$b}}) == 0) { 193 push @{$archtree{$b}}, $c; 194 $changesmade = 1; 195 } 196 } 197 } 198 } 199 } 200} 201 202# Generate the assembler file for each architecture 203# Also count up how many instructions should be valid for each architecture 204 205foreach $arch (0 .. ($archcount - 1)) { 206 print $arches[$arch], "\n"; 207 $insns_valid{$arches[$arch]} = 0; 208 unless (open ($fd, ">$arches[$arch].s")) { 209 die "Can't open $arches[$arch].s\n"; 210 } 211 print $fd "! Generated file. DO NOT EDIT.\n"; 212 print $fd "!\n"; 213 print $fd "! This file was generated by gas/testsuite/gas/sh/arch/sh-opc-gen-as.pl .\n"; 214 print $fd "! This file should contain every instruction valid on\n"; 215 print $fd "! architecture $arches[$arch] but no more.\n"; 216 print $fd "! If the tests are failing because the expected results have changed then run\n"; 217 print $fd "! 'cat ../../../../../opcodes/sh-opc.h | perl sh-opc-gen-as.pl'\n"; 218 print $fd "! in <srcdir>/gas/testsuite/gas/sh/arch to re-generate the files.\n"; 219 print $fd "! Make sure there are no unexpected or missing instructions.\n"; 220 print $fd "\n\t.section .text\n"; 221 ($lab = $arches[$arch]) =~ tr/-/_/; 222 print $fd "$lab:\n"; 223 print $fd "! Instructions introduced into $arches[$arch]\n"; 224 foreach $i (0 .. $insncount) { 225 if ($arches[$arch] eq $insns_arch[$i]) { 226 $context = $insns_context[$i]; 227 $context =~ s/,$//; 228 $context =~ s/^\s*\//\//; 229 printf $fd "\t%-25s ;!%s\n", $insns[$i], $context; 230 $insns_valid{$arches[$arch]} += 1; 231 } 232 } 233 print $fd "\n! Instructions inherited from ancestors:"; 234 foreach $anc (sort @{$archtree{$arches[$arch]}}) { 235 print $fd " $anc"; 236 } 237 print $fd "\n"; 238 foreach $i (0 .. $insncount) { 239 if (($arches[$arch] ne $insns_arch[$i]) 240 && (grep {$_ eq $insns_arch[$i]} @{$archtree{$arches[$arch]}})) { 241 $context = $insns_context[$i]; 242 $context =~ s/,$//; 243 $context =~ s/^\s*\//\//; 244 printf $fd "\t%-25s ;!%s\n", $insns[$i], $context; 245 $insns_valid{$arches[$arch]} += 1; 246 } 247 } 248 close $fd; 249} 250