xref: /netbsd/sys/arch/hpc/hpc/platid_gen/platid_gen.c (revision bf9ec67e)
1 /*	$NetBSD: platid_gen.c,v 1.4 2001/09/27 16:31:24 uch Exp $	*/
2 
3 /*-
4  * Copyright (c) 1999
5  *         Shin Takemura and PocketBSD Project. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the PocketBSD project
18  *	and its contributors.
19  * 4. Neither the name of the project nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  */
36 #include <stdio.h>
37 #include <strings.h>
38 #include <unistd.h>
39 
40 #include "platid_gen.h"
41 
42 /*
43  * constants
44  */
45 #define SEARCH_IGNORECASE	(1<<0)
46 
47 #define NMODES	2
48 #define MAXNEST	4
49 #define MAXLEN	1024
50 
51 enum { FORM_GENHDR, FORM_MASK_H, FORM_MASK_C, FORM_NAME_C, FORM_PARSE_ONLY };
52 
53 /*
54  * data type definitions
55  */
56 struct genctx_t {
57 	int num;
58 	const char *alt;
59 	const char *node_name[2];
60 	char sym[MAXLEN];
61 	char name[MAXLEN];
62 } genctx[NMODES][MAXNEST];
63 
64 /*
65  * function prototypes
66  */
67 void	gen_list(node_t *);
68 void	gen_output(void);
69 void	gen_header(void);
70 void	gen_mask_h(void);
71 void	gen_mask_c(void);
72 void	gen_name_c(void);
73 void	gen_comment(FILE *);
74 void	enter(void);
75 void	leave(void);
76 
77 /*
78  * global data
79  */
80 node_t*	def_tree;
81 int nest;
82 int mode;
83 FILE *fp_out;
84 int form;
85 int count;
86 
87 #define MODE_INVALID	-1
88 #define MODE_CPU	0
89 #define MODE_MACHINE	1
90 char* mode_names[] = {
91 	"CPU", "MACHINE", NULL
92 };
93 #define PREFIX	"PLATID"
94 char* prefix_names[] = {
95 	"CPU", "MACH",
96 };
97 char* shift_names[NMODES][MAXNEST] = {
98 	{
99 		"PLATID_CPU_ARCH_SHIFT",
100 		"PLATID_CPU_SERIES_SHIFT",
101 		"PLATID_CPU_MODEL_SHIFT",
102 		"PLATID_CPU_SUBMODEL_SHIFT",
103 	},
104 	{
105 		"PLATID_VENDOR_SHIFT",
106 		"PLATID_SERIES_SHIFT",
107 		"PLATID_MODEL_SHIFT",
108 		"PLATID_SUBMODEL_SHIFT",
109 	},
110 };
111 
112 /*
113  * program entry
114  */
115 int
116 main(int argc, char *argv[])
117 {
118 	int i;
119 
120 	form = FORM_GENHDR;
121 	fp_out = stdout;
122 	count = 0;
123 
124 	for (i = 1; i < argc; i++) {
125 		if (strcmp(argv[i], "-header") == 0) {
126 			form = FORM_GENHDR;
127 		} else if (strcmp(argv[i], "-mask_h") == 0) {
128 			form = FORM_MASK_H;
129 		} else if (strcmp(argv[i], "-mask_c") == 0) {
130 			form = FORM_MASK_C;
131 		} else if (strcmp(argv[i], "-name_c") == 0) {
132 			form = FORM_NAME_C;
133 		} else if (strcmp(argv[i], "-parse_only") == 0) {
134 			form = FORM_PARSE_ONLY;
135 		} else {
136 		usage:
137 			fprintf(stderr, "usage platid_gen <option>\n");
138 			fprintf(stderr, "  option: -header\n");
139 			fprintf(stderr, "          -mask_h\n");
140 			fprintf(stderr, "          -mask_c\n");
141 			fprintf(stderr, "          -name_c\n");
142 			fprintf(stderr, "          -parse_only\n");
143 			exit(1);
144 		}
145 	}
146 
147 	if (read_def()) {
148 		exit(1);
149 	}
150 
151 	if (form == FORM_PARSE_ONLY) {
152 		dump_node("", def_tree);
153 		exit (0);
154 	}
155 
156 	gen_comment(fp_out);
157 	switch (form) {
158 	case FORM_GENHDR:
159 		break;
160 	case FORM_MASK_H:
161 		break;
162 	case FORM_MASK_C:
163 		fprintf(fp_out, "#include <machine/platid.h>\n");
164 		fprintf(fp_out, "#include <machine/platid_mask.h>\n");
165 		break;
166 	case FORM_NAME_C:
167 		fprintf(fp_out, "#include <machine/platid.h>\n");
168 		fprintf(fp_out, "#include <machine/platid_mask.h>\n");
169 		fprintf(fp_out,"struct platid_name platid_name_table[] = {\n");
170 		break;
171 	}
172 
173 	nest = -1;
174 	enter(); /* XXX */
175 	mode = MODE_INVALID;
176 	genctx[MODE_CPU][nest].alt = NULL;
177 	genctx[MODE_MACHINE][nest].alt = NULL;
178 	gen_list((node_t*)def_tree->ptr1);
179 
180 	switch (form) {
181 	case FORM_GENHDR:
182 	case FORM_MASK_H:
183 	case FORM_MASK_C:
184 		break;
185 	case FORM_NAME_C:
186 		fprintf(fp_out, "};\n");
187 		fprintf(fp_out, "int platid_name_table_size = sizeof(platid_name_table)/sizeof(*platid_name_table);\n");
188 		break;
189 	}
190 	fclose(fp_out);
191 
192 	exit(0);
193 }
194 
195 int
196 table_getnum(char **table, char *s, int def, int opt)
197 {
198 	int num;
199 
200 	num = 0;
201 	while (table[num]) {
202 		int diff;
203 		if (opt & SEARCH_IGNORECASE) {
204 			diff = strcmp(table[num], s);
205 		} else {
206 			diff = strcasecmp(table[num], s);
207 		}
208 		if (diff == 0) {
209 			return (num);
210 		}
211 		num++;
212 	}
213 	return def;
214 }
215 
216 #define GET_MODE(s) \
217 	table_getnum(mode_names, (s), MODE_INVALID, SEARCH_IGNORECASE)
218 #define GET_ALT(s) \
219 	table_getnum(mode_names, (s), MODE_INVALID, SEARCH_IGNORECASE)
220 
221 void
222 enter()
223 {
224 	nest++;
225 	if (MAXNEST <= nest) {
226 		fprintf(stderr, "too much nest\n");
227 		exit(1);
228 	}
229 	genctx[mode][nest].num = 0;
230 	genctx[mode][nest].alt = NULL;
231 	genctx[mode][nest].node_name[0] = NULL;
232 	genctx[mode][nest].node_name[1] = NULL;
233 	if (0 < nest) {
234 		genctx[mode][nest].alt = genctx[mode][nest - 1].alt;
235 	}
236 }
237 
238 void
239 leave()
240 {
241 	nest--;
242 	if (nest < 0) {
243 		fprintf(stderr, "internal error (nest=%d)\n", nest);
244 		exit(1);
245 	}
246 }
247 
248 void
249 gen_comment(FILE *fp)
250 {
251 	fprintf(fp, "/*\n");
252 	fprintf(fp, " *  Do not edit.\n");
253 	fprintf(fp, " *  This file is automatically generated by platid.awk.\n");
254 	fprintf(fp, " */\n");
255 }
256 
257 gen_name(char *buf, struct genctx_t ctx[], int nest, int name, char *punct,
258     int ignr)
259 {
260 	int i;
261 	buf[0] = '\0';
262 	for (i = 0; i <= nest; i++) {
263 		if (!(ignr <= i && nest != i)) {
264 			if (i != 0) {
265 				strcat(buf, punct);
266 			}
267 			strcat(buf, ctx[i].node_name[name]);
268 		}
269 	}
270 }
271 
272 void
273 gen_list(node_t* np)
274 {
275 	int i, t;
276 
277 	for ( ; np; np = np->link) {
278 		switch (np->type) {
279 		case N_LABEL:
280 			if ((mode = GET_MODE(np->ptr1)) == MODE_INVALID) {
281 				fprintf(stderr, "invalid mode '%s'\n",
282 				    np->ptr1);
283 				exit(1);
284 			}
285 			break;
286 		case N_MODIFIER:
287 			t = GET_ALT(np->ptr1);
288 			if (t == MODE_INVALID) {
289 				fprintf(stderr, "unknown alternater '%s'\n",
290 				    np->ptr1);
291 				exit(1);
292 			}
293 			if (t == mode) {
294 				fprintf(stderr,
295 				    "invalid alternater '%s' (ignored)\n",
296 				    np->ptr1);
297 				exit(1);
298 			}
299 			genctx[mode][nest].alt = np->ptr2;
300 			break;
301 		case N_ENTRY:
302 			if (np->ptr2 == NULL) {
303 				char buf[MAXLEN];
304 				sprintf(buf, "%s%s",
305 				    nest == 0 ? "" : " ",
306 				    np->ptr1);
307 		  		np->ptr2 = strdup(buf);
308 				if (nest == 3)
309 					np->val = 1;
310 			}
311 			touppers((char*)np->ptr1);
312 
313 			genctx[mode][nest].num++;
314 		  	genctx[mode][nest].node_name[0] = np->ptr1;
315 			genctx[mode][nest].node_name[1] = np->ptr2;
316 			gen_name(genctx[mode][nest].sym, genctx[mode],
317 			    nest, 0, "_", nest == 3 ? 2 : nest);
318 			gen_name(genctx[mode][nest].name, genctx[mode],
319 			    nest, 1, "", nest - np->val);
320 			gen_output();
321 			break;
322 		case N_LIST:
323 			enter();
324 			gen_list((node_t*)np->ptr1);
325 			leave();
326 			break;
327 		case N_DIRECTIVE:
328 			fprintf(fp_out, "%s", np->ptr1);
329 			break;
330 		default:
331 			fprintf(stderr, "internal error (type=%d)\n", np->type);
332 			exit(1);
333 			break;
334 		}
335 	}
336 }
337 
338 void
339 gen_output()
340 {
341 	switch (form) {
342 	case FORM_GENHDR:
343 		gen_header();
344 		break;
345 	case FORM_MASK_H:
346 		gen_mask_h();
347 		break;
348 	case FORM_MASK_C:
349 		gen_mask_c();
350 		break;
351 	case FORM_NAME_C:
352 		gen_name_c();
353 		break;
354 	}
355 }
356 
357 /*
358  * platid_generated.h
359  *
360  * #define PLATID_CPU_XXX_NUM	1
361  * #define PLATID_CPU_XXX	\
362  *   ((PLATID_CPU_XXX_NUM << PLATID_CPU_ARCH_SHIFT))
363  * #define PLATID_CPU_XXX_YYY	\
364  *   ((PLATID_CPU_XXX_YYY_NUM << PLATID_CPU_SERIES_SHIFT)| \
365  *     PLATID_CPU_XXX)
366  *
367  * #ifndef SPEC_PLATFORM
368  * #define SPEC_MACH_XXX
369  * #endif
370  * #define PLATID_MACH_XXX_NUM	1
371  * #define PLATID_MACH_XXX	\
372  *   ((PLATID_MACH_XXX_NUM << PLATID_MACH_ARCH_SHIFT))
373  * #define PLATID_MACH_XXX_YYY	\
374  *   ((PLATID_MACH_XXX_YYY_NUM << PLATID_MACH_SERIES_SHIFT)| \
375  *     PLATID_MACH_XXX)
376  */
377 void
378 gen_header()
379 {
380 	char *prefix = prefix_names[mode];
381 	char *name = genctx[mode][nest].sym;
382 
383 	if (mode == MODE_MACHINE) {
384 		fprintf(fp_out, "#ifndef SPEC_PLATFORM\n");
385 		fprintf(fp_out, "#define %s_%s_%s\n", "SPEC", prefix, name);
386 		fprintf(fp_out, "#endif /* !SPEC_PLATFORM */\n");
387 	}
388 	fprintf(fp_out, "#define %s_%s_%s_NUM\t%d\n", PREFIX, prefix, name,
389 	    genctx[mode][nest].num);
390 	fprintf(fp_out, "#define %s_%s_%s\t\\\n", PREFIX, prefix, name);
391 	fprintf(fp_out, "  ((%s_%s_%s_NUM << %s)", PREFIX, prefix, name,
392 	    shift_names[mode][nest]);
393 	if (0 < nest) {
394 		fprintf(fp_out, "| \\\n    %s_%s_%s",
395 		    PREFIX, prefix, genctx[mode][nest - 1].sym);
396 	}
397 	fprintf(fp_out, ")\n");
398 }
399 
400 /*
401  * platid_mask.h:
402  *
403  * extern platid_t platid_mask_CPU_MIPS;
404  * #ifdef PLATID_DEFINE_MASK_NICKNAME
405  * #  define GENERIC_MIPS ((int)&platid_mask_CPU_MIPS)
406  * #endif
407  */
408 void
409 gen_mask_h()
410 {
411 	char *name = genctx[mode][nest].sym;
412 
413 	fprintf(fp_out, "extern platid_t platid_mask_%s_%s;\n",
414 	    prefix_names[mode], name);
415 	fprintf(fp_out, "#ifdef PLATID_DEFINE_MASK_NICKNAME\n");
416 	fprintf(fp_out, "#  define %s%s ((int)&platid_mask_%s_%s)\n",
417 	    (mode == MODE_CPU)?"GENERIC_":"",
418 	    name, prefix_names[mode], name);
419 	fprintf(fp_out, "#endif\n");
420 }
421 
422 /*
423  * platid_mask.c:
424  *
425  * platid_t platid_mask_CPU_MIPS = {{
426  * 	PLATID_CPU_MIPS,
427  *	PLATID_WILD
428  * }};
429  */
430 void
431 gen_mask_c()
432 {
433 	char *name = genctx[mode][nest].sym;
434 
435 	fprintf(fp_out, "platid_t platid_mask_%s_%s = {{\n",
436 	    prefix_names[mode], name);
437 	switch (mode) {
438 	case MODE_CPU:
439 		fprintf(fp_out, "\t%s_CPU_%s,\n", PREFIX, name);
440 		if (genctx[mode][nest].alt == NULL)
441 			fprintf(fp_out, "\t%s_WILD\n", PREFIX);
442 		else
443 			fprintf(fp_out, "\t%s_MACH_%s,\n", PREFIX,
444 			    genctx[mode][nest].alt);
445 		break;
446 	case MODE_MACHINE:
447 		if (genctx[mode][nest].alt == NULL)
448 			fprintf(fp_out, "\t%s_WILD,\n", PREFIX);
449 		else
450 			fprintf(fp_out, "\t%s_CPU_%s,\n", PREFIX,
451 			    genctx[mode][nest].alt);
452 		fprintf(fp_out, "\t%s_MACH_%s\n", PREFIX, name);
453 		break;
454 	}
455 	fprintf(fp_out, "}};\n");
456 }
457 
458 /*
459  * platid_name.c:
460  */
461 void
462 gen_name_c()
463 {
464 	fprintf(fp_out, "\t{ &platid_mask_%s_%s,\n",
465 	    prefix_names[mode], genctx[mode][nest].sym);
466 	fprintf(fp_out, "\t TEXT(\"%s\") },\n", genctx[mode][nest].name);
467 	count++;
468 }
469