xref: /netbsd-src/sys/arch/hpc/hpc/platid_gen/platid_gen.c (revision 1c9d295ac50e01b09df0d79bf02aee4de7cc31dd)
1 /*	$NetBSD: platid_gen.c,v 1.11 2014/03/26 17:54:46 christos 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.11 2014/03/26 17:54:46 christos 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
main(int argc,char * argv[])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
table_getnum(char ** table,const char * s,int def,int opt)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
enter(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
leave(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
gen_comment(FILE * fp)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 int
gen_name(char * buf,struct genctx_t ctx[],int nest,int name,char * punct,int ignr)263 gen_name(char *buf, struct genctx_t ctx[], int nest, int name, char *punct,
264     int ignr)
265 {
266 	int i;
267 	buf[0] = '\0';
268 	for (i = 0; i <= nest; i++) {
269 		if (!(ignr <= i && nest != i)) {
270 			if (i != 0) {
271 				strcat(buf, punct);
272 			}
273 			strcat(buf, ctx[i].node_name[name]);
274 		}
275 	}
276 }
277 
278 void
gen_list(node_t * np)279 gen_list(node_t* np)
280 {
281 	int i, t;
282 
283 	for ( ; np; np = np->link) {
284 		switch (np->type) {
285 		case N_LABEL:
286 			if ((mode = GET_MODE(np->ptr1)) == MODE_INVALID) {
287 				fprintf(stderr, "invalid mode '%s'\n",
288 				    np->ptr1);
289 				exit(1);
290 			}
291 			break;
292 		case N_MODIFIER:
293 			t = GET_ALT(np->ptr1);
294 			if (t == MODE_INVALID) {
295 				fprintf(stderr, "unknown alternater '%s'\n",
296 				    np->ptr1);
297 				exit(1);
298 			}
299 			if (t == mode) {
300 				fprintf(stderr,
301 				    "invalid alternater '%s' (ignored)\n",
302 				    np->ptr1);
303 				exit(1);
304 			}
305 			genctx[mode][nest].alt = np->ptr2;
306 			break;
307 		case N_ENTRY:
308 			if (np->ptr2 == NULL) {
309 				char buf[MAXLEN];
310 				snprintf(buf, sizeof(buf), "%s%s",
311 				    nest == 0 ? "" : " ",
312 				    np->ptr1);
313 		  		np->ptr2 = strdup(buf);
314 				if (nest == 3)
315 					np->val = 1;
316 			}
317 			touppers((char*)np->ptr1);
318 
319 			genctx[mode][nest].num++;
320 		  	genctx[mode][nest].node_name[0] = np->ptr1;
321 			genctx[mode][nest].node_name[1] = np->ptr2;
322 			gen_name(genctx[mode][nest].sym, genctx[mode],
323 			    nest, 0, "_", nest == 3 ? 2 : nest);
324 			gen_name(genctx[mode][nest].name, genctx[mode],
325 			    nest, 1, "", nest - np->val);
326 			gen_output();
327 			break;
328 		case N_LIST:
329 			enter();
330 			gen_list((node_t*)np->ptr1);
331 			leave();
332 			break;
333 		case N_DIRECTIVE:
334 			fprintf(fp_out, "%s", np->ptr1);
335 			break;
336 		default:
337 			fprintf(stderr, "internal error (type=%d)\n", np->type);
338 			exit(1);
339 			break;
340 		}
341 	}
342 }
343 
344 void
gen_output(void)345 gen_output(void)
346 {
347 	switch (form) {
348 	case FORM_GENHDR:
349 		gen_header();
350 		break;
351 	case FORM_MASK_H:
352 		gen_mask_h();
353 		break;
354 	case FORM_MASK_C:
355 		gen_mask_c();
356 		break;
357 	case FORM_NAME_C:
358 		gen_name_c();
359 		break;
360 	}
361 }
362 
363 /*
364  * platid_generated.h
365  *
366  * #define PLATID_CPU_XXX_NUM	1
367  * #define PLATID_CPU_XXX	\
368  *   ((PLATID_CPU_XXX_NUM << PLATID_CPU_ARCH_SHIFT))
369  * #define PLATID_CPU_XXX_YYY	\
370  *   ((PLATID_CPU_XXX_YYY_NUM << PLATID_CPU_SERIES_SHIFT)| \
371  *     PLATID_CPU_XXX)
372  *
373  * #ifndef SPEC_PLATFORM
374  * #define SPEC_MACH_XXX
375  * #endif
376  * #define PLATID_MACH_XXX_NUM	1
377  * #define PLATID_MACH_XXX	\
378  *   ((PLATID_MACH_XXX_NUM << PLATID_MACH_ARCH_SHIFT))
379  * #define PLATID_MACH_XXX_YYY	\
380  *   ((PLATID_MACH_XXX_YYY_NUM << PLATID_MACH_SERIES_SHIFT)| \
381  *     PLATID_MACH_XXX)
382  */
383 void
gen_header(void)384 gen_header(void)
385 {
386 	char *prefix = prefix_names[mode];
387 	char *name = genctx[mode][nest].sym;
388 
389 	if (mode == MODE_MACHINE) {
390 		fprintf(fp_out, "#ifndef SPEC_PLATFORM\n");
391 		fprintf(fp_out, "#define %s_%s_%s\n", "SPEC", prefix, name);
392 		fprintf(fp_out, "#endif /* !SPEC_PLATFORM */\n");
393 	}
394 	fprintf(fp_out, "#define %s_%s_%s_NUM\t%d\n", PREFIX, prefix, name,
395 	    genctx[mode][nest].num);
396 	fprintf(fp_out, "#define %s_%s_%s\t\\\n", PREFIX, prefix, name);
397 	fprintf(fp_out, "  ((%s_%s_%s_NUM << %s)", PREFIX, prefix, name,
398 	    shift_names[mode][nest]);
399 	if (0 < nest) {
400 		fprintf(fp_out, "| \\\n    %s_%s_%s",
401 		    PREFIX, prefix, genctx[mode][nest - 1].sym);
402 	}
403 	fprintf(fp_out, ")\n");
404 }
405 
406 /*
407  * platid_mask.h:
408  *
409  * extern platid_t platid_mask_CPU_MIPS;
410  * #ifdef PLATID_DEFINE_MASK_NICKNAME
411  * #  define GENERIC_MIPS ((int)&platid_mask_CPU_MIPS)
412  * #endif
413  */
414 void
gen_mask_h(void)415 gen_mask_h(void)
416 {
417 	char *name = genctx[mode][nest].sym;
418 
419 	fprintf(fp_out, "extern platid_t platid_mask_%s_%s;\n",
420 	    prefix_names[mode], name);
421 	fprintf(fp_out, "#ifdef PLATID_DEFINE_MASK_NICKNAME\n");
422 	fprintf(fp_out, "#  define %s%s ((int)&platid_mask_%s_%s)\n",
423 	    (mode == MODE_CPU)?"GENERIC_":"",
424 	    name, prefix_names[mode], name);
425 	fprintf(fp_out, "#endif\n");
426 }
427 
428 /*
429  * platid_mask.c:
430  *
431  * platid_t platid_mask_CPU_MIPS = {{
432  * 	PLATID_CPU_MIPS,
433  *	PLATID_WILD
434  * }};
435  */
436 void
gen_mask_c(void)437 gen_mask_c(void)
438 {
439 	char *name = genctx[mode][nest].sym;
440 
441 	fprintf(fp_out, "platid_t platid_mask_%s_%s = {{\n",
442 	    prefix_names[mode], name);
443 	switch (mode) {
444 	case MODE_CPU:
445 		fprintf(fp_out, "\t%s_CPU_%s,\n", PREFIX, name);
446 		if (genctx[mode][nest].alt == NULL)
447 			fprintf(fp_out, "\t%s_WILD\n", PREFIX);
448 		else
449 			fprintf(fp_out, "\t%s_MACH_%s,\n", PREFIX,
450 			    genctx[mode][nest].alt);
451 		break;
452 	case MODE_MACHINE:
453 		if (genctx[mode][nest].alt == NULL)
454 			fprintf(fp_out, "\t%s_WILD,\n", PREFIX);
455 		else
456 			fprintf(fp_out, "\t%s_CPU_%s,\n", PREFIX,
457 			    genctx[mode][nest].alt);
458 		fprintf(fp_out, "\t%s_MACH_%s\n", PREFIX, name);
459 		break;
460 	}
461 	fprintf(fp_out, "}};\n");
462 }
463 
464 /*
465  * platid_name.c:
466  */
467 void
gen_name_c(void)468 gen_name_c(void)
469 {
470 	fprintf(fp_out, "\t{ &platid_mask_%s_%s,\n",
471 	    prefix_names[mode], genctx[mode][nest].sym);
472 	fprintf(fp_out, "\t TEXT(\"%s\") },\n", genctx[mode][nest].name);
473 	count++;
474 }
475