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