xref: /netbsd/sys/arch/hpc/hpc/platid_gen/platid_gen.c (revision 6550d01e)
1 /*	$NetBSD: platid_gen.c,v 1.9 2009/03/18 10:22:28 cegger 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 
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: platid_gen.c,v 1.9 2009/03/18 10:22:28 cegger Exp $");
39 
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <strings.h>
43 #include <unistd.h>
44 
45 #include "platid_gen.h"
46 
47 /*
48  * constants
49  */
50 #define SEARCH_IGNORECASE	(1<<0)
51 
52 #define NMODES	2
53 #define MAXNEST	4
54 #define MAXLEN	1024
55 
56 enum { FORM_GENHDR, FORM_MASK_H, FORM_MASK_C, FORM_NAME_C, FORM_PARSE_ONLY };
57 
58 /*
59  * data type definitions
60  */
61 struct genctx_t {
62 	int num;
63 	const char *alt;
64 	const char *node_name[2];
65 	char sym[MAXLEN];
66 	char name[MAXLEN];
67 } genctx[NMODES][MAXNEST];
68 
69 /*
70  * function prototypes
71  */
72 void	gen_list(node_t *);
73 void	gen_output(void);
74 void	gen_header(void);
75 void	gen_mask_h(void);
76 void	gen_mask_c(void);
77 void	gen_name_c(void);
78 void	gen_comment(FILE *);
79 void	enter(void);
80 void	leave(void);
81 
82 /*
83  * global data
84  */
85 node_t*	def_tree;
86 int nest;
87 int mode;
88 FILE *fp_out;
89 int form;
90 int count;
91 
92 #define MODE_INVALID	-1
93 #define MODE_CPU	0
94 #define MODE_MACHINE	1
95 char* mode_names[] = {
96 	"CPU", "MACHINE", NULL
97 };
98 #define PREFIX	"PLATID"
99 char* prefix_names[] = {
100 	"CPU", "MACH",
101 };
102 char* shift_names[NMODES][MAXNEST] = {
103 	{
104 		"PLATID_CPU_ARCH_SHIFT",
105 		"PLATID_CPU_SERIES_SHIFT",
106 		"PLATID_CPU_MODEL_SHIFT",
107 		"PLATID_CPU_SUBMODEL_SHIFT",
108 	},
109 	{
110 		"PLATID_VENDOR_SHIFT",
111 		"PLATID_SERIES_SHIFT",
112 		"PLATID_MODEL_SHIFT",
113 		"PLATID_SUBMODEL_SHIFT",
114 	},
115 };
116 
117 /*
118  * program entry
119  */
120 int
121 main(int argc, char *argv[])
122 {
123 	int i;
124 
125 	form = FORM_GENHDR;
126 	fp_out = stdout;
127 	count = 0;
128 
129 	for (i = 1; i < argc; i++) {
130 		if (strcmp(argv[i], "-header") == 0) {
131 			form = FORM_GENHDR;
132 		} else if (strcmp(argv[i], "-mask_h") == 0) {
133 			form = FORM_MASK_H;
134 		} else if (strcmp(argv[i], "-mask_c") == 0) {
135 			form = FORM_MASK_C;
136 		} else if (strcmp(argv[i], "-name_c") == 0) {
137 			form = FORM_NAME_C;
138 		} else if (strcmp(argv[i], "-parse_only") == 0) {
139 			form = FORM_PARSE_ONLY;
140 		} else {
141 		usage:
142 			fprintf(stderr, "usage platid_gen <option>\n");
143 			fprintf(stderr, "  option: -header\n");
144 			fprintf(stderr, "          -mask_h\n");
145 			fprintf(stderr, "          -mask_c\n");
146 			fprintf(stderr, "          -name_c\n");
147 			fprintf(stderr, "          -parse_only\n");
148 			exit(1);
149 		}
150 	}
151 
152 	if (read_def()) {
153 		exit(1);
154 	}
155 
156 	if (form == FORM_PARSE_ONLY) {
157 		dump_node("", def_tree);
158 		exit (0);
159 	}
160 
161 	gen_comment(fp_out);
162 	switch (form) {
163 	case FORM_GENHDR:
164 		break;
165 	case FORM_MASK_H:
166 		break;
167 	case FORM_MASK_C:
168 		fprintf(fp_out, "#include <machine/platid.h>\n");
169 		fprintf(fp_out, "#include <machine/platid_mask.h>\n");
170 		break;
171 	case FORM_NAME_C:
172 		fprintf(fp_out, "#include <machine/platid.h>\n");
173 		fprintf(fp_out, "#include <machine/platid_mask.h>\n");
174 		fprintf(fp_out,"struct platid_name platid_name_table[] = {\n");
175 		break;
176 	}
177 
178 	nest = -1;
179 	enter(); /* XXX */
180 	mode = MODE_INVALID;
181 	genctx[MODE_CPU][nest].alt = NULL;
182 	genctx[MODE_MACHINE][nest].alt = NULL;
183 	gen_list((node_t*)def_tree->ptr1);
184 
185 	switch (form) {
186 	case FORM_GENHDR:
187 	case FORM_MASK_H:
188 	case FORM_MASK_C:
189 		break;
190 	case FORM_NAME_C:
191 		fprintf(fp_out, "};\n");
192 		fprintf(fp_out, "int platid_name_table_size = sizeof(platid_name_table)/sizeof(*platid_name_table);\n");
193 		break;
194 	}
195 	fclose(fp_out);
196 
197 	exit(0);
198 }
199 
200 int
201 table_getnum(char **table, const char *s, int def, int opt)
202 {
203 	int num;
204 
205 	num = 0;
206 	while (table[num]) {
207 		int diff;
208 		if (opt & SEARCH_IGNORECASE) {
209 			diff = strcmp(table[num], s);
210 		} else {
211 			diff = strcasecmp(table[num], s);
212 		}
213 		if (diff == 0) {
214 			return (num);
215 		}
216 		num++;
217 	}
218 	return def;
219 }
220 
221 #define GET_MODE(s) \
222 	table_getnum(mode_names, (s), MODE_INVALID, SEARCH_IGNORECASE)
223 #define GET_ALT(s) \
224 	table_getnum(mode_names, (s), MODE_INVALID, SEARCH_IGNORECASE)
225 
226 void
227 enter(void)
228 {
229 	nest++;
230 	if (MAXNEST <= nest) {
231 		fprintf(stderr, "too much nest\n");
232 		exit(1);
233 	}
234 	genctx[mode][nest].num = 0;
235 	genctx[mode][nest].alt = NULL;
236 	genctx[mode][nest].node_name[0] = NULL;
237 	genctx[mode][nest].node_name[1] = NULL;
238 	if (0 < nest) {
239 		genctx[mode][nest].alt = genctx[mode][nest - 1].alt;
240 	}
241 }
242 
243 void
244 leave(void)
245 {
246 	nest--;
247 	if (nest < 0) {
248 		fprintf(stderr, "internal error (nest=%d)\n", nest);
249 		exit(1);
250 	}
251 }
252 
253 void
254 gen_comment(FILE *fp)
255 {
256 	fprintf(fp, "/*\n");
257 	fprintf(fp, " *  Do not edit.\n");
258 	fprintf(fp, " *  This file is automatically generated by platid.awk.\n");
259 	fprintf(fp, " */\n");
260 }
261 
262 gen_name(char *buf, struct genctx_t ctx[], int nest, int name, char *punct,
263     int ignr)
264 {
265 	int i;
266 	buf[0] = '\0';
267 	for (i = 0; i <= nest; i++) {
268 		if (!(ignr <= i && nest != i)) {
269 			if (i != 0) {
270 				strcat(buf, punct);
271 			}
272 			strcat(buf, ctx[i].node_name[name]);
273 		}
274 	}
275 }
276 
277 void
278 gen_list(node_t* np)
279 {
280 	int i, t;
281 
282 	for ( ; np; np = np->link) {
283 		switch (np->type) {
284 		case N_LABEL:
285 			if ((mode = GET_MODE(np->ptr1)) == MODE_INVALID) {
286 				fprintf(stderr, "invalid mode '%s'\n",
287 				    np->ptr1);
288 				exit(1);
289 			}
290 			break;
291 		case N_MODIFIER:
292 			t = GET_ALT(np->ptr1);
293 			if (t == MODE_INVALID) {
294 				fprintf(stderr, "unknown alternater '%s'\n",
295 				    np->ptr1);
296 				exit(1);
297 			}
298 			if (t == mode) {
299 				fprintf(stderr,
300 				    "invalid alternater '%s' (ignored)\n",
301 				    np->ptr1);
302 				exit(1);
303 			}
304 			genctx[mode][nest].alt = np->ptr2;
305 			break;
306 		case N_ENTRY:
307 			if (np->ptr2 == NULL) {
308 				char buf[MAXLEN];
309 				sprintf(buf, "%s%s",
310 				    nest == 0 ? "" : " ",
311 				    np->ptr1);
312 		  		np->ptr2 = strdup(buf);
313 				if (nest == 3)
314 					np->val = 1;
315 			}
316 			touppers((char*)np->ptr1);
317 
318 			genctx[mode][nest].num++;
319 		  	genctx[mode][nest].node_name[0] = np->ptr1;
320 			genctx[mode][nest].node_name[1] = np->ptr2;
321 			gen_name(genctx[mode][nest].sym, genctx[mode],
322 			    nest, 0, "_", nest == 3 ? 2 : nest);
323 			gen_name(genctx[mode][nest].name, genctx[mode],
324 			    nest, 1, "", nest - np->val);
325 			gen_output();
326 			break;
327 		case N_LIST:
328 			enter();
329 			gen_list((node_t*)np->ptr1);
330 			leave();
331 			break;
332 		case N_DIRECTIVE:
333 			fprintf(fp_out, "%s", np->ptr1);
334 			break;
335 		default:
336 			fprintf(stderr, "internal error (type=%d)\n", np->type);
337 			exit(1);
338 			break;
339 		}
340 	}
341 }
342 
343 void
344 gen_output(void)
345 {
346 	switch (form) {
347 	case FORM_GENHDR:
348 		gen_header();
349 		break;
350 	case FORM_MASK_H:
351 		gen_mask_h();
352 		break;
353 	case FORM_MASK_C:
354 		gen_mask_c();
355 		break;
356 	case FORM_NAME_C:
357 		gen_name_c();
358 		break;
359 	}
360 }
361 
362 /*
363  * platid_generated.h
364  *
365  * #define PLATID_CPU_XXX_NUM	1
366  * #define PLATID_CPU_XXX	\
367  *   ((PLATID_CPU_XXX_NUM << PLATID_CPU_ARCH_SHIFT))
368  * #define PLATID_CPU_XXX_YYY	\
369  *   ((PLATID_CPU_XXX_YYY_NUM << PLATID_CPU_SERIES_SHIFT)| \
370  *     PLATID_CPU_XXX)
371  *
372  * #ifndef SPEC_PLATFORM
373  * #define SPEC_MACH_XXX
374  * #endif
375  * #define PLATID_MACH_XXX_NUM	1
376  * #define PLATID_MACH_XXX	\
377  *   ((PLATID_MACH_XXX_NUM << PLATID_MACH_ARCH_SHIFT))
378  * #define PLATID_MACH_XXX_YYY	\
379  *   ((PLATID_MACH_XXX_YYY_NUM << PLATID_MACH_SERIES_SHIFT)| \
380  *     PLATID_MACH_XXX)
381  */
382 void
383 gen_header(void)
384 {
385 	char *prefix = prefix_names[mode];
386 	char *name = genctx[mode][nest].sym;
387 
388 	if (mode == MODE_MACHINE) {
389 		fprintf(fp_out, "#ifndef SPEC_PLATFORM\n");
390 		fprintf(fp_out, "#define %s_%s_%s\n", "SPEC", prefix, name);
391 		fprintf(fp_out, "#endif /* !SPEC_PLATFORM */\n");
392 	}
393 	fprintf(fp_out, "#define %s_%s_%s_NUM\t%d\n", PREFIX, prefix, name,
394 	    genctx[mode][nest].num);
395 	fprintf(fp_out, "#define %s_%s_%s\t\\\n", PREFIX, prefix, name);
396 	fprintf(fp_out, "  ((%s_%s_%s_NUM << %s)", PREFIX, prefix, name,
397 	    shift_names[mode][nest]);
398 	if (0 < nest) {
399 		fprintf(fp_out, "| \\\n    %s_%s_%s",
400 		    PREFIX, prefix, genctx[mode][nest - 1].sym);
401 	}
402 	fprintf(fp_out, ")\n");
403 }
404 
405 /*
406  * platid_mask.h:
407  *
408  * extern platid_t platid_mask_CPU_MIPS;
409  * #ifdef PLATID_DEFINE_MASK_NICKNAME
410  * #  define GENERIC_MIPS ((int)&platid_mask_CPU_MIPS)
411  * #endif
412  */
413 void
414 gen_mask_h(void)
415 {
416 	char *name = genctx[mode][nest].sym;
417 
418 	fprintf(fp_out, "extern platid_t platid_mask_%s_%s;\n",
419 	    prefix_names[mode], name);
420 	fprintf(fp_out, "#ifdef PLATID_DEFINE_MASK_NICKNAME\n");
421 	fprintf(fp_out, "#  define %s%s ((int)&platid_mask_%s_%s)\n",
422 	    (mode == MODE_CPU)?"GENERIC_":"",
423 	    name, prefix_names[mode], name);
424 	fprintf(fp_out, "#endif\n");
425 }
426 
427 /*
428  * platid_mask.c:
429  *
430  * platid_t platid_mask_CPU_MIPS = {{
431  * 	PLATID_CPU_MIPS,
432  *	PLATID_WILD
433  * }};
434  */
435 void
436 gen_mask_c(void)
437 {
438 	char *name = genctx[mode][nest].sym;
439 
440 	fprintf(fp_out, "platid_t platid_mask_%s_%s = {{\n",
441 	    prefix_names[mode], name);
442 	switch (mode) {
443 	case MODE_CPU:
444 		fprintf(fp_out, "\t%s_CPU_%s,\n", PREFIX, name);
445 		if (genctx[mode][nest].alt == NULL)
446 			fprintf(fp_out, "\t%s_WILD\n", PREFIX);
447 		else
448 			fprintf(fp_out, "\t%s_MACH_%s,\n", PREFIX,
449 			    genctx[mode][nest].alt);
450 		break;
451 	case MODE_MACHINE:
452 		if (genctx[mode][nest].alt == NULL)
453 			fprintf(fp_out, "\t%s_WILD,\n", PREFIX);
454 		else
455 			fprintf(fp_out, "\t%s_CPU_%s,\n", PREFIX,
456 			    genctx[mode][nest].alt);
457 		fprintf(fp_out, "\t%s_MACH_%s\n", PREFIX, name);
458 		break;
459 	}
460 	fprintf(fp_out, "}};\n");
461 }
462 
463 /*
464  * platid_name.c:
465  */
466 void
467 gen_name_c(void)
468 {
469 	fprintf(fp_out, "\t{ &platid_mask_%s_%s,\n",
470 	    prefix_names[mode], genctx[mode][nest].sym);
471 	fprintf(fp_out, "\t TEXT(\"%s\") },\n", genctx[mode][nest].name);
472 	count++;
473 }
474