1# Manipulate the CPU, FPU and architecture descriptions for ARM.
2# Copyright (C) 2017-2020 Free Software Foundation, Inc.
3#
4# This file is part of GCC.
5#
6# GCC is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 3, or (at your option)
9# any later version.
10#
11# GCC is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with GCC; see the file COPYING3.  If not see
18# <http://www.gnu.org/licenses/>.
19
20# Invoke this with '-v cmd=<cmd>"
21# where <cmd> is one of:
22#	data: Print the standard 'C' data tables for the CPUs
23#	common-data: Print the 'C' data for shared driver/compiler files
24#	native: Print the data structures used by the native driver
25#	headers: Print the standard 'C' headers for the CPUs
26#	isa: Generate the arm-isa.h header
27#	md: Print the machine description fragment
28#	opt: Print the option tables fragment
29#	chkcpu <name>: Checks that <name> is a valid CPU
30#	chktune <name>: Checks that <name> is a valid CPU
31#	chkfpu <name>: Checks that <name> is a valid FPU
32#	chkarch <name>: Checks that <arch> is a valid architecture
33
34function fatal (m) {
35    print "error ("lineno"): " m > "/dev/stderr"
36    fatal_err = 1
37    if (parse_done) exit 1
38}
39
40function toplevel () {
41    if (cpu_name != "") fatal("missing \"end cpu\"")
42    if (arch_name != "") fatal("missing \"end arch\"")
43    if (fpu_name != "") fatal("missing \"end fpu\"")
44}
45
46function boilerplate (style) {
47    ce = ""
48    if (style == "C" ) {
49	cs = "/* "
50	cc = "   "
51	ce = "  */"
52    } else if (style == "md") {
53	cc = "; "
54	cs = cc
55    } else if (style == "sh") {
56	cc = "# "
57	cs = cc
58    } else fatal("Unknown comment style: "style)
59
60    print cs "-*- buffer-read-only: t -*-"
61
62    print cc "Generated automatically by parsecpu.awk from arm-cpus.in."
63    print cc "Do not edit."
64    print ""
65    print cc "Copyright (C) 2011-2020 Free Software Foundation, Inc."
66    print ""
67    print cc "This file is part of GCC."
68    print ""
69    print cc "GCC is free software; you can redistribute it and/or modify"
70    print cc "it under the terms of the GNU General Public License as"
71    print cc "published by the Free Software Foundation; either version 3,"
72    print cc "or (at your option) any later version."
73    print ""
74    print cc "GCC is distributed in the hope that it will be useful,"
75    print cc "but WITHOUT ANY WARRANTY; without even the implied warranty of"
76    print cc "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the"
77    print cc "GNU General Public License for more details."
78    print ""
79    print cc "You should have received a copy of the GNU General Public"
80    print cc "License along with GCC; see the file COPYING3.  If not see"
81    print cc "<http://www.gnu.org/licenses/>." ce
82    print ""
83}
84
85function tune_flag_pfx (f) {
86    return "TF_" f
87}
88
89# Print out the bits for the features in FLIST, which may be a
90# mixture of fgroup and individual bits.  Print each feature needed
91# exactly once.  Terminate the list with isa_nobit.  Prefix each line by
92# INDENT.  Does not print a new line at the end.
93function print_isa_bits_for (flist, indent) {
94    nbits = split (flist, bits)
95
96    for (bit = 1; bit <= nbits; bit++) {
97	if (bits[bit] in features) {
98	    pbit[bits[bit]] = 1
99	} else if (bits[bit] in fgroup) {
100	    for (gbits in fgrp_bits) {
101		split (gbits, bitsep, SUBSEP)
102		if (bitsep[1] == bits[bit]) {
103		    pbit[bitsep[2]] = 1
104		}
105	    }
106	} else fatal("feature " bits[bit] " not declared")
107    }
108    zbit = ORS
109    ORS = ""
110    print indent "{\n" indent "  "
111    ORS = ", "
112    count = 0
113    for (bname in pbit) {
114	print "isa_bit_" bname
115	count++
116	if (count == 4) {
117	    count = 0
118	    ORS = ""
119	    print "\n" indent "  "
120	    ORS = ", "
121	}
122    }
123    ORS = ""
124    print "isa_nobit\n" indent "}"
125    ORS = zbit
126    delete pbit
127}
128
129function gen_headers () {
130    boilerplate("C")
131
132    print "enum processor_type"
133    print "{"
134
135    ncpus = split (cpu_list, cpus)
136
137    for (n = 1; n <= ncpus; n++) {
138	print "  TARGET_CPU_"cpu_cnames[cpus[n]]","
139    }
140    print "  TARGET_CPU_arm_none"
141    print "};\n"
142
143    print "enum arch_type"
144    print "{"
145
146    narchs = split (arch_list, archs)
147
148    for (n = 1; n <= narchs; n++) {
149	print "  TARGET_ARCH_"arch_cnames[archs[n]]","
150    }
151    print "  TARGET_ARCH_arm_none"
152    print "};\n"
153
154    print "enum fpu_type"
155    print "{"
156
157    nfpus = split (fpu_list, fpus)
158
159    for (n = 1; n <= nfpus; n++) {
160	print "  TARGET_FPU_"fpu_cnames[fpus[n]]","
161    }
162    print "  TARGET_FPU_auto"
163    print "};"
164}
165
166function gen_isa () {
167    boilerplate("C")
168    print "enum isa_feature {"
169    print "  isa_nobit = 0,"
170    for (fbit in features) {
171	print "  isa_bit_" fbit ","
172    }
173    print "  isa_num_bits"
174    print "};\n"
175
176    for (fgrp in fgroup) {
177	print "#define ISA_"fgrp " \\"
178	z = ORS
179	ORS = ""
180	first = 1
181	for (bitcomb in fgrp_bits) {
182	    split (bitcomb, bitsep, SUBSEP)
183	    if (bitsep[1] == fgrp) {
184		if (first) {
185		    first = 0
186		} else print ", \\\n"
187		print "  isa_bit_" bitsep[2]
188	    }
189	}
190	ORS = z
191	print "\n"
192    }
193
194    print "struct fbit_implication {"
195    print "  /* Represents a feature implication, where:"
196    print "     ante IMPLIES cons"
197    print "     meaning that if ante is enabled then we should"
198    print "     also implicitly enable cons.  */"
199    print "  enum isa_feature ante;"
200    print "  enum isa_feature cons;"
201    print "};\n"
202    print "static const struct fbit_implication all_implied_fbits[] ="
203    print "{"
204    for (impl in implied_bits) {
205      split (impl, impl_parts, SUBSEP)
206      print "  { isa_bit_" impl_parts[2] ", isa_bit_" impl_parts[1] " },"
207    }
208    print "  { isa_nobit, isa_nobit }"
209    print "};\n"
210}
211
212function gen_data () {
213    boilerplate("C")
214
215    print "static const cpu_tune all_tunes[] ="
216    print "{"
217
218    ncpus = split (cpu_list, cpus)
219
220    for (n = 1; n <= ncpus; n++) {
221	print "  { /* " cpus[n] ".  */"
222	# scheduler
223	if (cpus[n] in cpu_tune_for) {
224	    if (! (cpu_tune_for[cpus[n]] in cpu_cnames)) {
225		fatal("unknown \"tune for\" target " cpu_tune_for[cpus[n]] \
226		      " for CPU " cpus[n])
227	    }
228	    print "    TARGET_CPU_" cpu_cnames[cpu_tune_for[cpus[n]]] ","
229	} else {
230	    print "    TARGET_CPU_" cpu_cnames[cpus[n]] ","
231	}
232	# tune_flags
233	if (cpus[n] in cpu_tune_flags) {
234	    print "    (" cpu_tune_flags[cpus[n]] "),"
235	} else print "    0,"
236	# tune
237	print "    &arm_" cpu_cost[cpus[n]] "_tune"
238	print "  },"
239    }
240    print "  {TARGET_CPU_arm_none, 0, NULL}"
241    print "};"
242}
243
244function gen_comm_data () {
245    boilerplate("C")
246
247    ncpus = split (cpu_list, cpus)
248
249    for (n = 1; n <= ncpus; n++) {
250	if (cpus[n] in cpu_opts) {
251	    print "static const cpu_arch_extension cpu_opttab_" \
252		cpu_cnames[cpus[n]] "[] = {"
253	    nopts = split (cpu_opts[cpus[n]], opts)
254	    for (opt = 1; opt <= nopts; opt++) {
255		print "  {"
256		print "    \"" opts[opt] "\", " \
257		    cpu_opt_remove[cpus[n],opts[opt]] ", false,"
258		print_isa_bits_for(cpu_opt_isa[cpus[n],opts[opt]], "    ")
259		print "\n  },"
260	    }
261	    if (cpus[n] in cpu_optaliases) {
262		naliases = split (cpu_optaliases[cpus[n]], aliases)
263		for (alias = 1; alias <= naliases; alias++) {
264		    if (! ((cpus[n], \
265			    cpu_opt_alias[cpus[n],aliases[alias]]) in \
266			   cpu_opt_isa)) {
267			fatal("Alias " aliases[alias] " target not defined " \
268			      "for CPU " cpus[n])
269		    }
270		    equiv=cpu_opt_alias[cpus[n],aliases[alias]]
271		    print "  {"
272		    print "    \"" aliases[alias] "\", " \
273			cpu_opt_remove[cpus[n],equiv] ", true, "
274		    print_isa_bits_for(cpu_opt_isa[cpus[n],equiv], "    ")
275		    print "\n  },"
276		}
277	    }
278	    print "  { NULL, false, false, {isa_nobit}}"
279	    print "};\n"
280	}
281
282	if (cpus[n] in cpu_aliases) {
283	    print "static const cpu_alias cpu_aliastab_" \
284		cpu_cnames[cpus[n]] "[] = {"
285	    naliases = split (cpu_aliases[cpus[n]], aliases)
286	    for (alias = 1; alias <= naliases; alias++) {
287		print "  { \"" aliases[alias] "\", " \
288		    cpu_alias_visible[cpus[n],aliases[alias]] "},"
289	    }
290	    print "  { NULL, false}"
291	    print "};\n"
292	}
293    }
294
295    print "const cpu_option all_cores[] ="
296    print "{"
297
298    for (n = 1; n <= ncpus; n++) {
299	print "  {"
300	print "    {"
301	# common.name
302	print "      \"" cpus[n] "\","
303	# common.extensions
304	if (cpus[n] in cpu_opts) {
305	    print "      cpu_opttab_" cpu_cnames[cpus[n]] ","
306	} else print "      NULL,"
307	# common.isa_bits
308	nfeats = split (cpu_arch[cpus[n]], feats, "+")
309	if (! (feats[1] in arch_isa)) {
310	    fatal("unknown arch " feats[1] " for cpu " cpus[n])
311	}
312	all_isa_bits = arch_isa[feats[1]]
313	for (m = 2; m <= nfeats; m++) {
314	    if (! ((feats[1], feats[m]) in arch_opt_isa)) {
315		fatal("unknown feature " feats[m] " for architecture " feats[1])
316	    }
317	    if (arch_opt_remove[feats[1],feats[m]] == "true") {
318		fatal("cannot remove features from architecture specs")
319	    }
320	    all_isa_bits = all_isa_bits " " arch_opt_isa[feats[1],feats[m]]
321	}
322	if (cpus[n] in cpu_isa) {
323	    all_isa_bits = all_isa_bits " " cpu_isa[cpus[n]]
324	}
325	print_isa_bits_for(all_isa_bits, "      ")
326	print "\n    },"
327	# aliases
328	if (cpus[n] in cpu_aliases) {
329	    print "    cpu_aliastab_" cpu_cnames[cpus[n]] ","
330	} else print "    NULL,"
331	# arch
332	print "    TARGET_ARCH_" arch_cnames[feats[1]]
333	print "  },"
334    }
335
336    print "  {{NULL, NULL, {isa_nobit}}, NULL, TARGET_ARCH_arm_none}"
337    print "};"
338
339    narchs = split (arch_list, archs)
340
341    for (n = 1; n <= narchs; n++) {
342	if (archs[n] in arch_opts) {
343	    print "static const struct cpu_arch_extension arch_opttab_" \
344		arch_cnames[archs[n]] "[] = {"
345	    nopts = split (arch_opts[archs[n]], opts)
346	    for (opt = 1; opt <= nopts; opt++) {
347		print "  {"
348		print "    \"" opts[opt] "\", " \
349		    arch_opt_remove[archs[n],opts[opt]] ", false,"
350		print_isa_bits_for(arch_opt_isa[archs[n],opts[opt]], "    ")
351		print "\n  },"
352	    }
353	    if (archs[n] in arch_optaliases) {
354		naliases = split (arch_optaliases[archs[n]], aliases)
355		for (alias = 1; alias <= naliases; alias++) {
356		    if (! ((archs[n], \
357			    arch_opt_alias[archs[n],aliases[alias]]) in \
358			   arch_opt_isa)) {
359			fatal("Alias " aliases[alias] " target not defined " \
360			      "for architecture " archs[n])
361		    }
362		    equiv=arch_opt_alias[archs[n],aliases[alias]]
363		    print "  {"
364		    print "    \"" aliases[alias] "\", " \
365			arch_opt_remove[archs[n],equiv] ", true, "
366		    print_isa_bits_for(arch_opt_isa[archs[n],equiv], "    ")
367		    print "\n  },"
368		}
369	    }
370	    print "  { NULL, false, false, {isa_nobit}}"
371	    print "};\n"
372	} else if (archs[n] in arch_optaliases) {
373	    fatal("Architecture " archs[n] " has option aliases but no options")
374	}
375    }
376
377    print "const arch_option all_architectures[] ="
378    print "{"
379
380    for (n = 1; n <= narchs; n++) {
381	print "  {"
382	if (! (arch_tune_for[archs[n]] in cpu_cnames)) {
383	    fatal("unknown \"tune for\" target " arch_tune_for[archs[n]] \
384		  " for architecture " archs[n])
385	}
386	# common.name
387	print "    \"" archs[n] "\","
388	# common.extensions
389	if (archs[n] in arch_opts) {
390	    print "    arch_opttab_" arch_cnames[archs[n]] ","
391	} else print "    NULL,"
392	# common.isa_bits
393	print_isa_bits_for(arch_isa[archs[n]], "    ")
394	print ","
395	# arch, base_arch
396	print "    \"" arch_base[archs[n]] "\", BASE_ARCH_" \
397	    arch_base[archs[n]] ","
398	# profile letter code, or zero if none.
399	if (archs[n] in arch_prof) {
400	    print "    '" arch_prof[archs[n]] "',"
401	} else {
402	    print "    0,"
403	}
404	# tune_id
405	print "    TARGET_CPU_" cpu_cnames[arch_tune_for[archs[n]]] ","
406	print "  },"
407    }
408
409    print "  {{NULL, NULL, {isa_nobit}},"
410    print "   NULL, BASE_ARCH_0, 0, TARGET_CPU_arm_none}"
411    print "};\n"
412
413    print "const arm_fpu_desc all_fpus[] ="
414    print "{"
415
416    nfpus = split (fpu_list, fpus)
417
418    for (n = 1; n <= nfpus; n++) {
419	print "  {"
420	print "    \"" fpus[n] "\","
421	print_isa_bits_for(fpu_isa[fpus[n]], "    ")
422	print "\n  },"
423    }
424
425    print "};"
426}
427
428function gen_native () {
429    boilerplate("C")
430
431    for (vendor in vendor_ids) {
432	print "static struct vendor_cpu vendor"vendor"_cpu_table[] = {"
433	ncpus = split (cpu_list, cpus)
434
435	for (n = 1; n <= ncpus; n++) {
436	    if ((cpus[n] in cpu_vendor) && (cpus[n] in cpu_part)	\
437		&& cpu_vendor[cpus[n]] == vendor) {
438		print "  {\"0x"cpu_part[cpus[n]]"\", \""cpu_arch[cpus[n]]"\", \""cpus[n]"\"},"
439	    }
440	}
441	print "  {NULL, NULL, NULL}"
442	print "};"
443    }
444
445    print "\nstatic struct vendor vendors_table[] = {"
446    for (vendor in vendor_ids) {
447	print "  {\"0x"vendor"\", vendor"vendor"_cpu_table},"
448    }
449    print "  {NULL, NULL}"
450    print "};"
451}
452
453function gen_md () {
454    boilerplate("md")
455
456    z = ORS
457    ORS = ""
458    print "(define_attr \"tune\"\n\t\""
459
460    ncpus = split (cpu_list, cpus)
461
462    for (n = 1; n < ncpus; n++) {
463	if ((n % 3) != 0) {
464	    ORS = ","
465	} else ORS = ",\n\t"
466	print cpu_cnames[cpus[n]]
467    }
468    ORS = z
469    print cpu_cnames[cpus[ncpus]]"\""
470    print "\t(const (symbol_ref \"((enum attr_tune) arm_tune)\")))"
471}
472
473function gen_opt () {
474    boilerplate("md")
475
476    print "Enum"
477    print "Name(processor_type) Type(enum processor_type)"
478    print "Known ARM CPUs (for use with the -mcpu= and -mtune= options):\n"
479
480    ncpus = split (cpu_list, cpus)
481
482    for (n = 1; n <= ncpus; n++) {
483	print "EnumValue"
484	print "Enum(processor_type) String(" cpus[n] \
485	    ") Value( TARGET_CPU_"cpu_cnames[cpus[n]]")"
486	print ""
487    }
488
489    print "Enum"
490    print "Name(arm_arch) Type(int)"
491    print "Known ARM architectures (for use with the -march= option):\n"
492
493    narchs = split (arch_list, archs)
494
495    for (n = 1; n <= narchs; n++) {
496	print "EnumValue"
497	print "Enum(arm_arch) String(" archs[n] \
498	    ") Value("n - 1")"
499	print ""
500    }
501
502    print "Enum"
503    print "Name(arm_fpu) Type(enum fpu_type)"
504    print "Known ARM FPUs (for use with the -mfpu= option):\n"
505
506    nfpus = split (fpu_list, fpus)
507
508    for (n = 1; n <= nfpus; n++) {
509	print "EnumValue"
510	print "Enum(arm_fpu) String(" fpus[n] \
511	    ") Value(TARGET_FPU_"fpu_cnames[fpus[n]]")"
512	print ""
513    }
514
515    print "EnumValue"
516    print "Enum(arm_fpu) String(auto) Value(TARGET_FPU_auto)"
517}
518
519function check_cpu (name) {
520    exts = split (name, extensions, "+")
521
522    cpu_name = extensions[1]
523    if (! (cpu_name in cpu_cnames)) {
524	if (! (cpu_name in cpu_all_aliases)) {
525	    return "error"
526	}
527	cpu_name = cpu_all_aliases[cpu_name]
528    }
529
530    for (n = 2; n <= exts; n++) {
531	if (!((cpu_name, extensions[n]) in cpu_opt_remove)	\
532	    && !((cpu_name, extensions[n]) in cpu_optaliases)) {
533	    return "error"
534	}
535    }
536    return name
537}
538
539function check_fpu (name) {
540    if (! (name in fpu_cnames)) {
541	return "error"
542    }
543    return fpu_cnames[name]
544}
545
546function check_arch (name) {
547    exts = split (name, extensions, "+")
548
549    if (! (extensions[1] in arch_isa)) {
550	return "error"
551    }
552
553    for (n = 2; n <= exts; n++) {
554	if (!((extensions[1], extensions[n]) in arch_opt_remove)	\
555	    && !((extensions[1], extensions[n]) in arch_optaliases)) {
556	    return "error"
557	}
558    }
559    return name
560}
561
562BEGIN {
563    cpu_name = ""
564    arch_name = ""
565    fpu_name = ""
566    lineno = 0
567    fatal_err = 0
568    parse_done = 0
569    if (cmd == "") fatal("Usage parsecpu.awk -v cmd=<xyz>")
570}
571
572# New line.  Reset parse status and increment line count for error messages
573// {
574    lineno++
575    parse_ok = 0
576}
577
578# Comments must be on a line on their own.
579/^#/ {
580    parse_ok = 1
581}
582
583/^define feature / {
584    if (NF != 3) fatal("syntax: define feature <name>")
585    toplevel()
586    fbit = $3
587    if (fbit in features) fatal("feature " fbit " already defined")
588    features[fbit] = 1
589    parse_ok = 1
590}
591
592/^define fgroup / {
593    if (NF < 4) fatal("syntax: define fgroup <name> <feature> [<feature>]*")
594    toplevel()
595    fgrp = $3
596    if (fgrp in fgroup) fatal("feature group " fgrp " already defined")
597    if (fgrp in features) fatal("feature group " fgrp " aliases a feature")
598    fcount = NF
599    for (n = 4; n <= fcount; n++) {
600	feat = $n
601	if (feat in features) {
602	    fgrp_bits[fgrp,feat] = 1
603	} else if (feat in fgroup) {
604	    # fgroups may reference other fgroups, copy their bits
605	    # to our bits.  To avoid recursion we don't set fgroup[fgrp]
606	    # until after we have done this, so such attempts will result
607	    # in an invalid group definition.
608	    for (bitcomb in fgrp_bits) {
609		split (bitcomb, bitsep, SUBSEP)
610		if (bitsep[1] == feat) {
611		    fgrp_bits[fgrp,bitsep[2]] = 1
612		}
613	    }
614	} else fatal("feature group member " feat " unrecognized")
615    }
616    fgroup[fgrp] = 1
617    parse_ok = 1
618}
619
620/^define implied / {
621  if (NF < 4) fatal("syntax: define implied <name> [<feature-or-fgroup>]+\n" \
622		    "Implied bits must be defined with at least one antecedent.")
623  toplevel()
624  fbit = $3
625  if (fbit in features) fatal("implied feature " fbit " aliases a real feature")
626  if (fbit in fgroup) fatal("implied feature " fbit " aliases a feature group")
627  fcount = NF
628  features[fbit] = 1
629  for (n = 4; n <= fcount; n++) {
630    ante = $n
631    if (fbit == ante) fatal("feature cannot imply itself")
632    else if (ante in features) {
633      for (impl in implied_bits) {
634	split(impl, impl_sep, SUBSEP)
635	if (ante == impl_sep[1])
636	  fatal(ante " implies implied bit " fbit		\
637		". Chained implications not currently supported")
638      }
639      implied_bits[fbit, ante] = 1
640    } else if (ante in fgroup) {
641      for (bitcomb in fgrp_bits) {
642	split(bitcomb, bitsep, SUBSEP)
643	if (bitsep[1] == ante) {
644	  implied_bits[fbit, bitsep[2]] = 1
645	}
646      }
647    } else {
648      fatal("implied bit antecedent " ante " unrecognized")
649    }
650  }
651  parse_ok = 1
652}
653
654/^begin fpu / {
655    if (NF != 3) fatal("syntax: begin fpu <name>")
656    toplevel()
657    fpu_name = $3
658    parse_ok = 1
659}
660
661/^end fpu / {
662    if (NF != 3) fatal("syntax: end fpu <name>")
663    if (fpu_name != $3) fatal("mimatched end fpu")
664    if (! (fpu_name in fpu_isa)) {
665	fatal("fpu definition \"" fpu_name "\" lacks an \"isa\" statement")
666    }
667    fpu_cnames[fpu_name] = fpu_name
668    gsub(/[-+.]/, "_", fpu_cnames[fpu_name])
669    fpu_list = fpu_list " " fpu_name
670    fpu_name = ""
671    parse_ok = 1
672}
673
674/^begin arch / {
675    if (NF != 3) fatal("syntax: begin arch <name>")
676    toplevel()
677    arch_name = $3
678    parse_ok = 1
679}
680
681/^[ 	]*base / {
682    if (NF != 2) fatal("syntax: base <architecture-base-name>")
683    if (arch_name == "") fatal("\"base\" statement outside of arch block")
684    arch_base[arch_name] = $2
685    parse_ok = 1
686}
687
688/^[ 	]*profile / {
689    if (NF != 2) fatal("syntax: profile <profile-name>")
690    if (arch_name == "") fatal("\"profile\" statement outside of arch block")
691    arch_prof[arch_name] = $2
692    parse_ok = 1
693}
694
695/^end arch / {
696    if (NF != 3) fatal("syntax: end arch <name>")
697    if (arch_name != $3) fatal("mimatched end arch")
698    if (! (arch_name in arch_tune_for)) {
699	fatal("arch definition lacks a \"tune for\" statement")
700    }
701    if (! (arch_name in arch_isa)) {
702	fatal("arch definition lacks an \"isa\" statement")
703    }
704    arch_list = arch_list " " arch_name
705    arch_cnames[arch_name] = arch_name
706    gsub(/[-+.]/, "_", arch_cnames[arch_name])
707    arch_name = ""
708    parse_ok = 1
709}
710
711/^begin cpu / {
712    if (NF != 3) fatal("syntax: begin cpu <name>")
713    toplevel()
714    cpu_name = $3
715    parse_ok = 1
716    if (cpu_name in cpu_cnames) {
717	fatal(cpu_name " is already defined")
718    }
719    if (cpu_name in cpu_all_aliases) {
720	fatal(cpu_name " has already been defined as an alias")
721    }
722}
723
724/^[ 	]*cname / {
725    if (NF != 2) fatal("syntax: cname <identifier>")
726    if (cpu_name == "") fatal("\"cname\" outside of cpu block")
727    cpu_cnames[cpu_name] = $2
728    parse_ok = 1
729}
730
731/^[ 	]*alias / {
732    if (NF < 2) fatal("syntax: alias <name>+")
733    if (cpu_name == "") fatal("\"alias\" outside of cpu block")
734    alias_count = NF
735    for (n = 2; n <= alias_count; n++) {
736	visible = "true"
737	alias = $n
738	if (alias ~ /^!.*/) {
739	    visible = "false"
740	    gsub(/^!/, "", alias)
741	}
742	if (alias in cpu_cnames) {
743	    fatal(alias " is already defined as a cpu name")
744	}
745	if (n == 2) {
746	    cpu_aliases[cpu_name] = alias
747	} else cpu_aliases[cpu_name] = cpu_aliases[cpu_name] " " alias
748	cpu_alias_visible[cpu_name,alias] = visible
749	if (alias in cpu_all_aliases) {
750	    fatal(alias " is already an alias for " cpu_all_aliases[alias])
751	}
752	cpu_all_aliases[alias] = cpu_name
753    }
754    parse_ok = 1
755}
756
757/^[ 	]*tune for / {
758    if (NF != 3) fatal("syntax: tune for <cpu-name>")
759    if (cpu_name != "") {
760	cpu_tune_for[cpu_name] = $3
761    } else if (arch_name != "") {
762	arch_tune_for[arch_name] = $3
763    } else fatal("\"tune for\" outside of cpu or arch block")
764    parse_ok = 1
765}
766
767/^[ 	]*tune flags / {
768    if (NF < 3) fatal("syntax: tune flags <flag> [<flag>]*")
769    flags=""
770    flag_count = NF
771    for (n = 3; n <= flag_count; n++) {
772	if (n == 3) {
773	    flags = tune_flag_pfx($n)
774	} else flags = flags " | " tune_flag_pfx($n)
775    }
776    if (cpu_name != "") {
777	cpu_tune_flags[cpu_name] = flags
778    } else if (arch_name != "") {
779	arch_tune_flags[arch_name] = flags
780    } else fatal("\"tune flags\" outside of cpu or arch block")
781    parse_ok = 1
782}
783
784/^[ 	]*architecture / {
785    if (NF != 2) fatal("syntax: architecture <arch-name>")
786    if (cpu_name == "") fatal("\"architecture\" outside of cpu block")
787    cpu_arch[cpu_name] = $2
788    parse_ok = 1
789}
790
791/^[ 	]*isa / {
792    if (NF < 2) fatal("syntax: isa <feature-or-fgroup> [<feature-or-fgroup>]*")
793    flags=""
794    flag_count = NF
795    for (n = 2; n <= flag_count; n++) {
796	if (n == 2) {
797	    flags = $n
798	} else flags = flags " " $n
799    }
800    if (cpu_name != "") {
801	cpu_isa[cpu_name] = flags
802    } else if (arch_name != "") {
803	arch_isa[arch_name] = flags
804    } else  if (fpu_name != "") {
805	fpu_isa[fpu_name] = flags
806    } else fatal("\"isa\" outside of cpu, fpu or arch block")
807    parse_ok = 1
808}
809
810/^[ 	]*option / {
811    if (NF < 4) fatal("syntax: option <name> add|remove <feature-or-fgroup>+")
812    name=$2
813    if ($3 == "add") {
814	remove = "false"
815    } else if ($3 == "remove") {
816	remove = "true"
817    } else fatal("syntax: option <name> add|remove isa-list")
818    flags=""
819    flag_count = NF
820    for (n = 4; n <= flag_count; n++) {
821	if (n == 4) {
822	    flags = $n
823	} else flags = flags " " $n
824    }
825    if (cpu_name != "") {
826	cpu_opts[cpu_name] = cpu_opts[cpu_name] " " name
827	cpu_opt_remove[cpu_name,name] = remove
828	cpu_opt_isa[cpu_name,name] = flags
829    } else if (arch_name != "") {
830	arch_opts[arch_name] = arch_opts[arch_name] " " name
831	arch_opt_remove[arch_name,name] = remove
832	arch_opt_isa[arch_name,name] = flags
833    } else fatal("\"option\" outside of cpu or arch block")
834    parse_ok = 1
835}
836
837/^[ 	]*optalias / {
838    if (NF != 3) fatal("syntax: optalias <name> <option-name>")
839    name=$2
840    alias=$3
841    if (cpu_name != "") {
842	cpu_optaliases[cpu_name] = cpu_optaliases[cpu_name] " " name
843	cpu_opt_alias[cpu_name,name] = alias
844    } else if (arch_name != "") {
845	arch_optaliases[arch_name] = arch_optaliases[arch_name] " " name
846	arch_opt_alias[arch_name,name] = alias
847    } else fatal("\"optalias\" outside of cpu or arch block")
848    parse_ok = 1
849}
850
851/^[ 	]*costs / {
852    if (NF != 2) fatal("syntax: costs <identifier>")
853    if (cpu_name == "") fatal("\"costs\" outside of cpu block")
854    cpu_cost[cpu_name] = $2
855    parse_ok = 1
856}
857
858/^[ 	]*vendor / {
859    if (NF != 2) fatal("syntax: vendor <vendor-id>")
860    if (cpu_name == "") fatal("\"vendor\" outside of cpu block")
861    cpu_vendor[cpu_name] = $2
862    vendor_ids[$2] = 1
863    parse_ok = 1
864}
865
866/^[ 	]*part / {
867    if (NF < 2 || NF > 4) fatal("syntax: part <part-id> [minrev [maxrev]]")
868    if (cpu_name == "") fatal("\"part\" outside of cpu block")
869    cpu_part[cpu_name] = $2
870    if (NF > 2) cpu_minrev[cpu_name] = $3
871    if (NF == 4) cpu_maxrev[cpu_name] = $4
872    parse_ok = 1
873}
874
875/^end cpu / {
876    if (NF != 3) fatal("syntax: end cpu <name>")
877    if (cpu_name != $3) fatal("mimatched end cpu")
878    if (! (cpu_name in cpu_cnames)) {
879	cpu_cnames[cpu_name] = cpu_name
880	gsub(/[-+.]/, "_", cpu_cnames[cpu_name])
881    }
882    if (! (cpu_name in cpu_arch)) fatal("cpu definition lacks an architecture")
883    if ((cpu_name in cpu_part) && !(cpu_name in cpu_vendor)) {
884	fatal("part number specified for " cpu_name " but no vendor")
885    }
886    cpu_list = cpu_list " " cpu_name
887    cpu_name = ""
888    parse_ok = 1
889}
890
891/[^\s]/ {
892    if (! parse_ok) fatal("Unrecognized statement: " $0)
893}
894
895END {
896    parse_done = 1
897    if (fatal_err) exit 1
898    toplevel()
899    if (cmd == "data") {
900	gen_data()
901    } else if (cmd == "common-data") {
902	gen_comm_data()
903    } else if (cmd == "native") {
904	gen_native()
905    } else if (cmd == "headers") {
906	gen_headers()
907    } else if (cmd == "isa") {
908	gen_isa()
909    } else if (cmd == "md") {
910	gen_md()
911    } else if (cmd == "opt") {
912	gen_opt()
913    } else if (cmd ~ /^chk(cpu|tune) /) {
914	split (cmd, target)
915	print check_cpu(target[2])
916    } else if (cmd ~ /^chkarch /) {
917	split (cmd, target)
918	print check_arch(target[2])
919    } else if (cmd ~ /^chkfpu /) {
920	split (cmd, target)
921	print check_fpu(target[2])
922    } else fatal("unrecognized command: "cmd)
923}
924