1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <unistd.h>
30#include <math.h>
31#include "stabs.h"
32
33void genassym_do_sou(struct tdesc *tdp, struct node *np);
34void genassym_do_enum(struct tdesc *tdp, struct node *np);
35void genassym_do_intrinsic(struct tdesc *tdp, struct node *np);
36
37static void switch_on_type(struct mlist *mlp, struct tdesc *tdp,
38    char *format, int level);
39
40static void print_intrinsic(struct mlist *mlp, struct tdesc *tdp,
41    char *format, int level);
42static void print_forward(struct mlist *mlp, struct tdesc *tdp,
43    char *format, int level);
44static void print_pointer(struct mlist *mlp, struct tdesc *tdp,
45    char *format, int level);
46static void print_array(struct mlist *mlp, struct tdesc *tdp,
47    char *format, int level);
48static void print_function(struct mlist *mlp, struct tdesc *tdp,
49    char *format, int level);
50static void print_union(struct mlist *mlp, struct tdesc *tdp,
51    char *format, int level);
52static void print_enum(struct mlist *mlp, struct tdesc *tdp,
53    char *format, int level);
54static void print_forward(struct mlist *mlp, struct tdesc *tdp,
55    char *format, int level);
56static void print_typeof(struct mlist *mlp, struct tdesc *tdp,
57    char *format, int level);
58static void print_struct(struct mlist *mlp, struct tdesc *tdp,
59    char *format, int level);
60static void print_volatile(struct mlist *mlp, struct tdesc *tdp,
61    char *format, int level);
62static int stabs_log2(unsigned int value);
63
64void
65genassym_do_intrinsic(struct tdesc *tdp, struct node *np)
66{
67	if (np->format != NULL) {
68		char *upper = uc(np->format);
69
70		printf("#define\t%s 0x%x\n", upper, tdp->size);
71
72		free(upper);
73	}
74}
75
76
77void
78genassym_do_sou(struct tdesc *tdp, struct node *np)
79{
80	struct mlist *mlp;
81	struct child *chp;
82	char *format;
83
84	if (np->format != NULL) {
85		char *upper = uc(np->format);
86		int l;
87
88		printf("#define\t%s 0x%x\n", upper, tdp->size);
89
90		if ((np->format2 != NULL) &&
91		    (l = stabs_log2(tdp->size)) != -1) {
92			printf("#define\t%s 0x%x\n", np->format2, l);
93		}
94
95		free(upper);
96	}
97
98	/*
99	 * Run thru all the fields of a struct and print them out
100	 */
101	for (mlp = tdp->data.members.forw; mlp != NULL; mlp = mlp->next) {
102		/*
103		 * If there's a child list, only print those members.
104		 */
105		if (np->child != NULL) {
106			if (mlp->name == NULL)
107				continue;
108			chp = find_child(np, mlp->name);
109			if (chp == NULL)
110				continue;
111			format = uc(chp->format);
112		} else {
113			format = NULL;
114		}
115		if (mlp->fdesc == NULL)
116			continue;
117		switch_on_type(mlp, mlp->fdesc, format, 0);
118		if (format != NULL)
119			free(format);
120	}
121}
122
123void
124genassym_do_enum(struct tdesc *tdp, struct node *np)
125{
126	int nelem = 0;
127	struct elist *elp;
128
129	printf("\n");
130	for (elp = tdp->data.emem; elp != NULL; elp = elp->next) {
131		printf("#define\tENUM_%s 0x%x\n", elp->name, elp->number);
132		nelem++;
133	}
134	printf("%x c-enum .%s\n", nelem, np->name);
135}
136
137static void
138switch_on_type(struct mlist *mlp, struct tdesc *tdp, char *format, int level)
139{
140	boolean_t allocated = B_FALSE;
141
142	if (format == NULL) {
143		allocated = B_TRUE;
144		format = uc(mlp->name);
145	}
146
147	switch (tdp->type) {
148	case INTRINSIC:
149		print_intrinsic(mlp, tdp, format, level);
150		break;
151	case POINTER:
152		print_pointer(mlp, tdp, format, level);
153		break;
154	case ARRAY:
155		print_array(mlp, tdp, format, level);
156		break;
157	case FUNCTION:
158		print_function(mlp, tdp, format, level);
159		break;
160	case UNION:
161		print_union(mlp, tdp, format, level);
162		break;
163	case ENUM:
164		print_enum(mlp, tdp, format, level);
165		break;
166	case FORWARD:
167		print_forward(mlp, tdp, format, level);
168		break;
169	case TYPEOF:
170		print_typeof(mlp, tdp, format, level);
171		break;
172	case STRUCT:
173		print_struct(mlp, tdp, format, level);
174		break;
175	case VOLATILE:
176		print_volatile(mlp, tdp, format, level);
177		break;
178	default:
179		fprintf(stderr, "Switch to Unknown type\n");
180		error = B_TRUE;
181		break;
182	}
183	if (allocated)
184		free(format);
185}
186
187
188static void
189print_forward(struct mlist *mlp, struct tdesc *tdp, char *format, int level)
190{
191	fprintf(stderr, "%s never defined\n", mlp->name);
192	error = B_TRUE;
193}
194
195static void
196print_typeof(struct mlist *mlp, struct tdesc *tdp, char *format, int level)
197{
198	switch_on_type(mlp, tdp->data.tdesc, format, level);
199}
200
201static void
202print_volatile(struct mlist *mlp, struct tdesc *tdp, char *format, int level)
203{
204	switch_on_type(mlp, tdp->data.tdesc, format, level);
205}
206
207static void
208print_intrinsic(struct mlist *mlp, struct tdesc *tdp,
209    char *format, int level)
210{
211	if (level != 0) {
212		switch (tdp->size) {
213		case 1:
214			printf("/* ' c@ ' %s */", format);
215			break;
216		case 2:
217			printf("/* ' w@ ' %s */", format);
218			break;
219		case 4:
220			printf("/* ' l@ ' %s */", format);
221			break;
222		case 8:
223			printf("/* ' x@ ' %s */", format);
224			break;
225		}
226	/*
227	 * Check for bit field.
228	 */
229	} else if (mlp->size != 0 &&
230	    ((mlp->size % 8) != 0 || (mlp->offset % mlp->size) != 0)) {
231		int offset, shift, mask;
232
233		offset = (mlp->offset / 32) * 4;
234		shift = 32 - ((mlp->offset % 32) + mlp->size);
235		mask = ((int)pow(2, mlp->size) - 1) << shift;
236
237		printf("#define\t%s_SHIFT 0x%x\n", format, shift);
238		printf("#define\t%s_MASK 0x%x\n", format, mask);
239		printf("#define\t%s_OFFSET 0x%x\n", format, offset);
240	} else if (mlp->name != NULL) {
241		printf("#define\t%s 0x%x\n", format, mlp->offset / 8);
242	}
243}
244
245static void
246print_pointer(struct mlist *mlp, struct tdesc *tdp, char *format, int level)
247{
248	if (level != 0) {
249		switch (tdp->size) {
250		case 1:
251			printf("/* ' c@ ' %s */", format);
252			break;
253		case 2:
254			printf("/* ' w@ ' %s */", format);
255			break;
256		case 4:
257			printf("/* ' l@ ' %s */", format);
258			break;
259		case 8:
260			printf("/* ' x@ ' %s */", format);
261			break;
262		}
263	} else {
264		printf("#define\t%s 0x%x\n", format, mlp->offset / 8);
265	}
266}
267
268static void
269print_array(struct mlist *mlp, struct tdesc *tdp, char *format, int level)
270{
271	struct ardef *ap = tdp->data.ardef;
272	int items, inc;
273
274	if (level == 0) {
275		items = ap->indices->range_end - ap->indices->range_start + 1;
276		inc = (mlp->size / items) / 8;
277		printf("#define\t%s 0x%x\n", format, mlp->offset / 8);
278		printf("#define\t%s_INCR 0x%x\n", format, inc);
279	}
280}
281
282static void
283print_function(struct mlist *mlp, struct tdesc *tdp, char *format, int level)
284{
285	fprintf(stderr, "function in struct %s\n", tdp->name);
286	error = B_TRUE;
287}
288
289static void
290print_struct(struct mlist *mlp, struct tdesc *tdp, char *format, int level)
291{
292	if (level != 0)
293		printf("/* ' noop ' %s */", format);
294	else
295		printf("#define\t%s 0x%x\n", format, mlp->offset / 8);
296}
297
298static void
299print_union(struct mlist *mlp, struct tdesc *tdp, char *format, int level)
300{
301	if (level != 0)
302		printf("/* ' noop ' %s */", format);
303	else
304		printf("#define\t%s 0x%x\n", format, mlp->offset / 8);
305}
306
307static void
308print_enum(struct mlist *mlp, struct tdesc *tdp, char *format, int level)
309{
310	if (level != 0)
311		printf("/* ' l@ ' %s */", format);
312	else
313		printf("#define\t%s 0x%x\n", format, mlp->offset / 8);
314}
315
316static int
317stabs_log2(unsigned int value)
318{
319	int log = 1;
320	int i;
321
322	for (i = 0; i < sizeof (value) * 8; i++) {
323		if ((log << i) == value)
324			return (i);
325	}
326	return (-1);
327}
328