Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / support / stabs / main.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: main.c
5*
6* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
7*
8* - Do no alter or remove copyright notices
9*
10* - Redistribution and use of this software in source and binary forms, with
11* or without modification, are permitted provided that the following
12* conditions are met:
13*
14* - Redistribution of source code must retain the above copyright notice,
15* this list of conditions and the following disclaimer.
16*
17* - Redistribution in binary form must reproduce the above copyright notice,
18* this list of conditions and the following disclaimer in the
19* documentation and/or other materials provided with the distribution.
20*
21* Neither the name of Sun Microsystems, Inc. or the names of contributors
22* may be used to endorse or promote products derived from this software
23* without specific prior written permission.
24*
25* This software is provided "AS IS," without a warranty of any kind.
26* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
27* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
28* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
29* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
30* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
31* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
32* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
33* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
34* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
35* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
36* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37*
38* You acknowledge that this software is not designed, licensed or
39* intended for use in the design, construction, operation or maintenance of
40* any nuclear facility.
41*
42* ========== Copyright Header End ============================================
43*/
44/*
45 * CDDL HEADER START
46 *
47 * The contents of this file are subject to the terms of the
48 * Common Development and Distribution License (the "License").
49 * You may not use this file except in compliance with the License.
50 *
51 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
52 * or http://www.opensolaris.org/os/licensing.
53 * See the License for the specific language governing permissions
54 * and limitations under the License.
55 *
56 * When distributing Covered Code, include this CDDL HEADER in each
57 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
58 * If applicable, add the following below this CDDL HEADER, with the
59 * fields enclosed by brackets "[]" replaced with your own identifying
60 * information: Portions Copyright [yyyy] [name of copyright owner]
61 *
62 * CDDL HEADER END
63 */
64
65/*
66 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
67 * Use is subject to license terms.
68 */
69
70#pragma ident "@(#)main.c 1.2 07/06/07 SMI"
71
72#include <unistd.h>
73#include <math.h>
74#include <stdlib.h>
75#include "stabs.h"
76
77int debug_level = 0;
78int line;
79
80boolean_t error = B_FALSE;
81char *program = NULL;
82
83extern void forth_do_sou(struct tdesc *, struct node *);
84extern void forth_do_enum(struct tdesc *, struct node *);
85extern void forth_do_intrinsic(struct tdesc *, struct node *);
86extern void genassym_do_sou(struct tdesc *, struct node *);
87extern void genassym_do_enum(struct tdesc *, struct node *);
88extern void genassym_do_intrinsic(struct tdesc *, struct node *);
89extern void squander_do_sou(struct tdesc *, struct node *);
90extern void squander_do_enum(struct tdesc *, struct node *);
91extern void squander_do_intrinsic(struct tdesc *, struct node *);
92extern void asmcheck_do_sou(struct tdesc *, struct node *);
93extern void asmcheck_do_enum(struct tdesc *, struct node *);
94extern void asmcheck_do_intrinsic(struct tdesc *, struct node *);
95
96struct model_info models[] = {
97 { "ilp32", 4, 1, 2, 4, 4 },
98 { "lp64", 8, 1, 2, 4, 8 },
99 { NULL, 0, 0, 0 }
100};
101
102struct stab_ops {
103 char *type;
104 void (*do_sou)(struct tdesc *, struct node *);
105 void (*do_enum)(struct tdesc *, struct node *);
106 void (*do_intrinsic)(struct tdesc *, struct node *);
107} ops_table[] = {
108 { "forth",
109 forth_do_sou, forth_do_enum, forth_do_intrinsic },
110 { "genassym",
111 genassym_do_sou, genassym_do_enum, genassym_do_intrinsic },
112 { "squander",
113 squander_do_sou, squander_do_enum, squander_do_intrinsic },
114 { "asmcheck",
115 asmcheck_do_sou, asmcheck_do_enum, asmcheck_do_intrinsic },
116 { NULL, NULL, NULL }
117};
118
119static void get_dbgs(int argc, char **argv);
120static void parse_dbg(FILE *sp);
121static void printnode(struct node *np);
122static struct tdesc *find_member(struct tdesc *tdp, char *name);
123static char *namex(char *cp, char **w);
124static void addchild(char *cp, struct node *np);
125static struct node *getnode(char *cp);
126
127struct stab_ops *ops;
128struct model_info *model;
129
130int
131main(int argc, char **argv)
132{
133 char *output_type = NULL;
134 char *model_name = NULL;
135 int c;
136
137 program = strrchr(argv[0], '/');
138 if (program != NULL)
139 program++;
140 else
141 program = argv[0];
142
143 /* defaults */
144 output_type = "forth";
145 model_name = "ilp32";
146
147 while (!error && ((c = getopt(argc, argv, "dt:m:")) != EOF)) {
148 switch (c) {
149 case 't':
150 output_type = optarg;
151 break;
152 case 'm':
153 model_name = optarg;
154 break;
155 case 'd':
156 debug_level++;
157 break;
158 case '?':
159 default:
160 error = B_TRUE;
161 break;
162 }
163 }
164
165 if (!error) {
166 /*
167 * Find ops for the specified output type
168 */
169 for (ops = ops_table; ops->type != NULL; ops++) {
170 if (strcmp(ops->type, output_type) == 0)
171 break;
172 }
173 if (ops->type == NULL)
174 error = B_TRUE;
175 }
176
177 if (!error) {
178 /*
179 * Find model characteristics
180 */
181 for (model = models; model->name != NULL; model++) {
182 if (strcmp(model->name, model_name) == 0)
183 break;
184 }
185 if (model->name == NULL)
186 error = B_TRUE;
187 }
188
189 /* skip over previously processed arguments */
190 argc -= optind;
191 argv += optind;
192 if (argc < 1)
193 error = B_TRUE;
194
195 if (error) {
196 fprintf(stderr, "Usage: %s [-d] {-m datamodel} "
197 "{-t output_type} files\n", program);
198 fprintf(stderr, "\tSupported data models:\n");
199 for (model = models; model->name != NULL; model++)
200 fprintf(stderr, "\t\t%s\n", model->name);
201 fprintf(stderr, "\tSupported output types:\n");
202 for (ops = ops_table; ops->type != NULL; ops++)
203 fprintf(stderr, "\t\t%s\n", ops->type);
204 return (1);
205 }
206
207 parse_input();
208
209 get_dbgs(argc, argv);
210
211 return (error ? 1 : 0);
212}
213
214/*
215 * This routine will read the .dbg files and build a list of the structures
216 * and fields that user is interested in. Any struct specified will get all
217 * its fields included. If nested struct needs to be printed - then the
218 * field name and name of struct type needs to be included in the next line.
219 */
220static void
221get_dbgs(int argc, char **argv)
222{
223 FILE *fp;
224
225 for (; argc != 0; argc--, argv++) {
226 if ((fp = fopen(*argv, "r")) == NULL) {
227 fprintf(stderr, "Cannot open %s\n", *argv);
228 error = B_TRUE;
229 return;
230 }
231 /* add all types in this file to our table */
232 parse_dbg(fp);
233 }
234}
235
236static char *
237namex(char *cp, char **w)
238{
239 char *new, *orig, c;
240 int len;
241
242 if (*cp == '\0') {
243 *w = NULL;
244 return (cp);
245 }
246
247 for (c = *cp++; isspace(c); c = *cp++)
248 /* LINTED */
249 ;
250 orig = --cp;
251 c = *cp++;
252 if (isalpha(c) || ispunct(c)) {
253 for (c = *cp++; isalnum(c) || ispunct(c); c = *cp++)
254 /* LINTED */
255 ;
256 len = cp - orig;
257 new = (char *)malloc(len);
258 while (orig < cp - 1)
259 *new++ = *orig++;
260 *new = '\0';
261 *w = new - (len - 1);
262 } else if (c != '\0') {
263 fprintf(stderr, "line %d has bad character %c\n", line, c);
264 error = B_TRUE;
265 }
266
267 return (cp);
268}
269
270/*
271 * checks to see if this field in the struct was requested for by user
272 * in the .dbg file.
273 */
274struct child *
275find_child(struct node *np, char *w)
276{
277 struct child *chp;
278
279 for (chp = np->child; chp != NULL; chp = chp->next) {
280 if (strcmp(chp->name, w) == 0)
281 return (chp);
282 }
283 return (NULL);
284}
285
286static struct tdesc *
287find_member(struct tdesc *tdp, char *name)
288{
289 struct mlist *mlp;
290
291 while (tdp->type == TYPEOF)
292 tdp = tdp->data.tdesc;
293 if (tdp->type != STRUCT && tdp->type != UNION)
294 return (NULL);
295 for (mlp = tdp->data.members.forw; mlp != NULL; mlp = mlp->next)
296 if (strcmp(mlp->name, name) == 0)
297 return (mlp->fdesc);
298 return (NULL);
299}
300
301/*
302 * add this field to our table of structs/fields that the user has
303 * requested in the .dbg files
304 */
305static void
306addchild(char *cp, struct node *np)
307{
308 struct child *chp;
309 char *w;
310
311 chp = malloc(sizeof (*chp));
312 cp = namex(cp, &w);
313 chp->name = w;
314 cp = namex(cp, &w);
315 if (w == NULL) {
316 if (chp->name == NULL) {
317 fprintf(stderr, "NULL child name\n");
318 exit(1);
319 }
320 /* XXX - always convert to upper-case? */
321 chp->format = uc(chp->name);
322 } else {
323 chp->format = w;
324 }
325 chp->next = np->child;
326 np->child = chp;
327}
328
329/*
330 * add this struct to our table of structs/fields that the user has
331 * requested in the .dbg files
332 */
333static struct node *
334getnode(char *cp)
335{
336 char *w;
337 struct node *np;
338
339 cp = namex(cp, &w);
340 np = malloc(sizeof (*np));
341 np->name = w;
342
343 /*
344 * XXX - These positional parameters are a hack
345 * We have two right now for genassym. The back-ends
346 * can use format and format2 any way they'd like.
347 */
348 cp = namex(cp, &w);
349 np->format = w;
350 if (w != NULL) {
351 w = NULL;
352 cp = namex(cp, &w);
353 np->format2 = w;
354 } else {
355 np->format2 = NULL;
356 }
357 np->child = NULL;
358 return (np);
359}
360
361/*
362 * Format for .dbg files should be
363 * Ex:
364 * seg
365 * as s_as
366 * if you wanted the contents of "s_as" (a pointer) to be printed in
367 * the format of a "as"
368 */
369static void
370parse_dbg(FILE *sp)
371{
372 char *cp;
373 struct node *np;
374 static char linebuf[MAXLINE];
375 int copy_flag = 0;
376 int ignore_flag = 0;
377 size_t c;
378
379 /* grab each line and add them to our table */
380 for (line = 1; (cp = fgets(linebuf, MAXLINE, sp)) != NULL; line++) {
381 if (*cp == '\n') {
382 if (copy_flag)
383 printf("\n");
384 continue;
385 }
386 if (*cp == '\\') {
387 if (cp[1] == '#')
388 printf("%s", (cp + 1));
389 continue;
390 }
391 if (strcmp(cp, "model_end\n") == 0) {
392 if (ignore_flag)
393 ignore_flag = 0;
394 continue;
395 }
396 if (ignore_flag)
397 continue;
398 c = strlen("model_start ");
399 if (strncmp(cp, "model_start ", c) == 0) {
400 if (strncmp(cp + c, model->name, strlen(model->name))
401 == 0 && *(cp + c + strlen(model->name)) == '\n')
402 /* model matches */;
403 else
404 ignore_flag = 1;
405 continue;
406 }
407 if ((strcmp(cp, "verbatim_begin\n") == 0) ||
408 (strcmp(cp, "forth_start\n") == 0)) {
409 copy_flag = 1;
410 continue;
411 }
412 if ((strcmp(cp, "verbatim_end\n") == 0) ||
413 (strcmp(cp, "forth_end\n") == 0)) {
414 copy_flag = 0;
415 continue;
416 }
417 if (copy_flag) {
418 printf("%s", cp);
419 continue;
420 }
421 np = getnode(cp);
422 for (line++; ((cp = fgets(linebuf, MAXLINE, sp)) != NULL) &&
423 *cp != '\n'; line++) {
424 /* members of struct, union or enum */
425 addchild(cp, np);
426 }
427 printnode(np);
428 }
429}
430
431static void
432printnode(struct node *np)
433{
434 struct tdesc *tdp;
435
436 tdp = lookupname(np->name);
437 if (tdp == NULL) {
438 char *member;
439 struct tdesc *ptdp;
440
441 if ((member = strchr(np->name, '.')) != NULL) {
442 *member = '\0';
443 ptdp = lookupname(np->name);
444 if (ptdp != NULL)
445 tdp = find_member(ptdp, member + 1);
446 *member = '.';
447 }
448 if (tdp == NULL) {
449 fprintf(stderr, "Can't find %s\n", np->name);
450 error = B_TRUE;
451 return;
452 }
453 }
454again:
455 switch (tdp->type) {
456 case STRUCT:
457 case UNION:
458 ops->do_sou(tdp, np);
459 break;
460 case ENUM:
461 ops->do_enum(tdp, np);
462 break;
463 case TYPEOF:
464 tdp = tdp->data.tdesc;
465 goto again;
466 case INTRINSIC:
467 ops->do_intrinsic(tdp, np);
468 break;
469 default:
470 fprintf(stderr, "%s isn't aggregate\n", np->name);
471 error = B_TRUE;
472 break;
473 }
474}
475
476
477char *
478convert_format(char *format, char *dfault)
479{
480 static char dot[3] = ".";
481
482 if (format == NULL)
483 return (dfault);
484 else if (strlen(format) == 1) {
485 dot[1] = *format;
486 return (dot);
487 } else
488 return (format);
489}
490
491char *
492uc(const char *s)
493{
494 char *buf;
495 int i;
496
497 buf = strdup(s);
498 for (i = 0; i < strlen(buf); i++)
499 buf[i] = toupper(buf[i]);
500 buf[i] = '\0';
501 return (buf);
502}