Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * Hypervisor Software File: asmcheck.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 "@(#)asmcheck.c 1.2 07/06/07 SMI" | |
71 | ||
72 | #include <unistd.h> | |
73 | #include <math.h> | |
74 | #include "stabs.h" | |
75 | ||
76 | void asmcheck_do_sou(struct tdesc *tdp, struct node *np); | |
77 | void asmcheck_do_enum(struct tdesc *tdp, struct node *np); | |
78 | void asmcheck_do_intrinsic(struct tdesc *tdp, struct node *np); | |
79 | ||
80 | static void switch_on_type(struct mlist *mlp, struct tdesc *tdp, | |
81 | char *format, int level); | |
82 | ||
83 | static void print_intrinsic(struct mlist *mlp, struct tdesc *tdp, | |
84 | char *format, int level); | |
85 | static void print_forward(struct mlist *mlp, struct tdesc *tdp, | |
86 | char *format, int level); | |
87 | static void print_pointer(struct mlist *mlp, struct tdesc *tdp, | |
88 | char *format, int level); | |
89 | static void print_array(struct mlist *mlp, struct tdesc *tdp, | |
90 | char *format, int level); | |
91 | static void print_function(struct mlist *mlp, struct tdesc *tdp, | |
92 | char *format, int level); | |
93 | static void print_union(struct mlist *mlp, struct tdesc *tdp, | |
94 | char *format, int level); | |
95 | static void print_enum(struct mlist *mlp, struct tdesc *tdp, | |
96 | char *format, int level); | |
97 | static void print_forward(struct mlist *mlp, struct tdesc *tdp, | |
98 | char *format, int level); | |
99 | static void print_typeof(struct mlist *mlp, struct tdesc *tdp, | |
100 | char *format, int level); | |
101 | static void print_struct(struct mlist *mlp, struct tdesc *tdp, | |
102 | char *format, int level); | |
103 | static void print_volatile(struct mlist *mlp, struct tdesc *tdp, | |
104 | char *format, int level); | |
105 | static int stabs_log2(unsigned int value); | |
106 | ||
107 | void | |
108 | asmcheck_do_intrinsic(struct tdesc *tdp, struct node *np) | |
109 | { | |
110 | if (np->format != NULL) { | |
111 | char *upper = uc(np->format); | |
112 | ||
113 | printf("\t/* %s 0x%x */\n", upper, tdp->size); | |
114 | ||
115 | free(upper); | |
116 | } | |
117 | } | |
118 | ||
119 | ||
120 | void | |
121 | asmcheck_do_sou(struct tdesc *tdp, struct node *np) | |
122 | { | |
123 | struct mlist *mlp; | |
124 | struct child *chp; | |
125 | char *format; | |
126 | ||
127 | if (np->format != NULL) { | |
128 | char *upper = uc(np->format); | |
129 | ||
130 | printf("! struct/union %s size 0x%x\n", upper, tdp->size); | |
131 | ||
132 | #if 0 /* { FIXME: */ | |
133 | { | |
134 | int l; | |
135 | if ((np->format2 != NULL) && | |
136 | (l = stabs_log2(tdp->size)) != -1) { | |
137 | printf("#define\t%s 0x%x\n", np->format2, l); | |
138 | } | |
139 | } | |
140 | #endif /* } */ | |
141 | ||
142 | free(upper); | |
143 | } | |
144 | ||
145 | /* | |
146 | * Run thru all the fields of a struct and print them out | |
147 | */ | |
148 | for (mlp = tdp->data.members.forw; mlp != NULL; mlp = mlp->next) { | |
149 | /* | |
150 | * If there's a child list, only print those members. | |
151 | */ | |
152 | if (np->child != NULL) { | |
153 | if (mlp->name == NULL) | |
154 | continue; | |
155 | chp = find_child(np, mlp->name); | |
156 | if (chp == NULL) | |
157 | continue; | |
158 | format = uc(chp->format); | |
159 | } else { | |
160 | format = NULL; | |
161 | } | |
162 | if (mlp->fdesc == NULL) | |
163 | continue; | |
164 | switch_on_type(mlp, mlp->fdesc, format, 0); | |
165 | if (format != NULL) | |
166 | free(format); | |
167 | } | |
168 | } | |
169 | ||
170 | void | |
171 | asmcheck_do_enum(struct tdesc *tdp, struct node *np) | |
172 | { | |
173 | int nelem = 0; | |
174 | struct elist *elp; | |
175 | ||
176 | printf("\n"); | |
177 | for (elp = tdp->data.emem; elp != NULL; elp = elp->next) { | |
178 | printf("#define\tENUM_%s 0x%x\n", elp->name, elp->number); | |
179 | nelem++; | |
180 | } | |
181 | printf("%x c-enum .%s\n", nelem, np->name); | |
182 | } | |
183 | ||
184 | static void | |
185 | switch_on_type(struct mlist *mlp, struct tdesc *tdp, char *format, int level) | |
186 | { | |
187 | boolean_t allocated = B_FALSE; | |
188 | ||
189 | if (format == NULL) { | |
190 | allocated = B_TRUE; | |
191 | format = uc(mlp->name); | |
192 | } | |
193 | ||
194 | switch (tdp->type) { | |
195 | case INTRINSIC: | |
196 | print_intrinsic(mlp, tdp, format, level); | |
197 | break; | |
198 | case POINTER: | |
199 | print_pointer(mlp, tdp, format, level); | |
200 | break; | |
201 | case ARRAY: | |
202 | print_array(mlp, tdp, format, level); | |
203 | break; | |
204 | case FUNCTION: | |
205 | print_function(mlp, tdp, format, level); | |
206 | break; | |
207 | case UNION: | |
208 | print_union(mlp, tdp, format, level); | |
209 | break; | |
210 | case ENUM: | |
211 | print_enum(mlp, tdp, format, level); | |
212 | break; | |
213 | case FORWARD: | |
214 | print_forward(mlp, tdp, format, level); | |
215 | break; | |
216 | case TYPEOF: | |
217 | print_typeof(mlp, tdp, format, level); | |
218 | break; | |
219 | case STRUCT: | |
220 | print_struct(mlp, tdp, format, level); | |
221 | break; | |
222 | case VOLATILE: | |
223 | print_volatile(mlp, tdp, format, level); | |
224 | break; | |
225 | default: | |
226 | fprintf(stderr, "Switch to Unknown type\n"); | |
227 | error = B_TRUE; | |
228 | break; | |
229 | } | |
230 | if (allocated) | |
231 | free(format); | |
232 | } | |
233 | ||
234 | ||
235 | static void | |
236 | print_forward(struct mlist *mlp, struct tdesc *tdp, char *format, int level) | |
237 | { | |
238 | fprintf(stderr, "%s never defined\n", mlp->name); | |
239 | error = B_TRUE; | |
240 | } | |
241 | ||
242 | static void | |
243 | print_typeof(struct mlist *mlp, struct tdesc *tdp, char *format, int level) | |
244 | { | |
245 | switch_on_type(mlp, tdp->data.tdesc, format, level); | |
246 | } | |
247 | ||
248 | static void | |
249 | print_volatile(struct mlist *mlp, struct tdesc *tdp, char *format, int level) | |
250 | { | |
251 | switch_on_type(mlp, tdp->data.tdesc, format, level); | |
252 | } | |
253 | ||
254 | static void | |
255 | print_intrinsic(struct mlist *mlp, struct tdesc *tdp, | |
256 | char *format, int level) | |
257 | { | |
258 | if (level != 0) { | |
259 | switch (tdp->size) { | |
260 | case 1: | |
261 | printf("/* ' c@ ' %s */", format); | |
262 | break; | |
263 | case 2: | |
264 | printf("/* ' w@ ' %s */", format); | |
265 | break; | |
266 | case 4: | |
267 | printf("/* ' l@ ' %s */", format); | |
268 | break; | |
269 | case 8: | |
270 | printf("/* ' x@ ' %s */", format); | |
271 | break; | |
272 | } | |
273 | /* | |
274 | * Check for bit field. | |
275 | */ | |
276 | } else | |
277 | if (mlp->size != 0 && | |
278 | ((mlp->size % 8) != 0 || (mlp->offset % (8*tdp->size)) != 0)) { | |
279 | printf("!\tbitfield: @ 0x%x : size = 0x%x\n", | |
280 | mlp->offset, mlp->size); | |
281 | #if 0 /* { FIXME: */ | |
282 | } else if (mlp->size != 0 && | |
283 | ((mlp->size % 8) != 0 || (mlp->offset % mlp->size) != 0)) { | |
284 | int offset, shift, mask; | |
285 | ||
286 | offset = (mlp->offset / 32) * 4; | |
287 | shift = 32 - ((mlp->offset % 32) + mlp->size); | |
288 | mask = ((int)pow(2, mlp->size) - 1) << shift; | |
289 | ||
290 | printf("#define\t%s_SHIFT 0x%x\n", format, shift); | |
291 | printf("#define\t%s_MASK 0x%x\n", format, mask); | |
292 | printf("#define\t%s_OFFSET 0x%x\n", format, offset); | |
293 | #endif /* } */ | |
294 | } else if (mlp->name != NULL) { | |
295 | char *typ; | |
296 | #if 0 /* { FIXME: */ | |
297 | printf("#define\t%s 0x%x\n", format, mlp->offset / 8); | |
298 | #endif /* } */ | |
299 | ||
300 | switch (tdp->data.flags) { | |
301 | case Intr_unknown: typ = "X"; break; | |
302 | case Intr_unsigned: typ = "u"; break; | |
303 | case Intr_signed: typ = "s"; break; | |
304 | case Intr_unsigned|Intr_char: typ = "uc"; break; | |
305 | case Intr_signed|Intr_char: typ = "sc"; break; | |
306 | default: | |
307 | abort(); | |
308 | } | |
309 | /* tdesc size field is already in bytes */ | |
310 | printf("%s\t0x%x\t0x%x\t%s\n", typ, | |
311 | mlp->offset/8, tdp->size, format); | |
312 | } | |
313 | } | |
314 | ||
315 | static void | |
316 | print_pointer(struct mlist *mlp, struct tdesc *tdp, char *format, int level) | |
317 | { | |
318 | if (level != 0) { | |
319 | switch (tdp->size) { | |
320 | case 1: | |
321 | printf("/* ' c@ ' %s */", format); | |
322 | break; | |
323 | case 2: | |
324 | printf("/* ' w@ ' %s */", format); | |
325 | break; | |
326 | case 4: | |
327 | printf("/* ' l@ ' %s */", format); | |
328 | break; | |
329 | case 8: | |
330 | printf("/* ' x@ ' %s */", format); | |
331 | break; | |
332 | } | |
333 | } else { | |
334 | #if 0 /* { FIXME: */ | |
335 | printf("#define\t%s 0x%x\n", format, mlp->offset / 8); | |
336 | #endif /* } */ | |
337 | printf("p\t0x%x\t0x%x\t%s\n", mlp->offset / 8, mlp->size/8, | |
338 | format); | |
339 | } | |
340 | } | |
341 | ||
342 | static void | |
343 | print_array(struct mlist *mlp, struct tdesc *tdp, char *format, int level) | |
344 | { | |
345 | struct ardef *ap = tdp->data.ardef; | |
346 | int items, inc; | |
347 | ||
348 | if (level == 0) { | |
349 | items = ap->indices->range_end - ap->indices->range_start + 1; | |
350 | inc = (mlp->size / items) / 8; | |
351 | #if 0 /* { FIXME: */ | |
352 | printf("#define\t%s 0x%x\n", format, mlp->offset / 8); | |
353 | printf("#define\t%s_INCR 0x%x\n", format, inc); | |
354 | #endif /* } */ | |
355 | printf("!\tarray %s @ 0x%x size 0x%x : element size 0x%x\n", | |
356 | format, mlp->offset / 8, mlp->size, inc); | |
357 | switch_on_type(mlp, ap->contents, format, level); | |
358 | #if 0 /* { FIXME: */ | |
359 | switch (ap->contents->type) { | |
360 | case INTRINSIC: | |
361 | print_intrinsic(mlp, ap->contents, format, level); | |
362 | break; | |
363 | ||
364 | case POINTER: | |
365 | print_pointer(mlp, ap->contents, format, level); | |
366 | break; | |
367 | ||
368 | default: | |
369 | break; | |
370 | } | |
371 | #endif /* } */ | |
372 | } | |
373 | } | |
374 | ||
375 | static void | |
376 | print_function(struct mlist *mlp, struct tdesc *tdp, char *format, int level) | |
377 | { | |
378 | fprintf(stderr, "function in struct %s\n", tdp->name); | |
379 | error = B_TRUE; | |
380 | } | |
381 | ||
382 | static void | |
383 | print_struct(struct mlist *mlp, struct tdesc *tdp, char *format, int level) | |
384 | { | |
385 | #if 0 /* { FIXME: */ | |
386 | if (level != 0) | |
387 | printf("/* ' noop ' %s */", format); | |
388 | else | |
389 | printf("#define\t%s 0x%x\n", format, mlp->offset / 8); | |
390 | #endif /* } */ | |
391 | printf("!\tstruct %s @ 0x%x has size 0x%x\n", | |
392 | format, mlp->offset / 8, mlp->size / 8); | |
393 | } | |
394 | ||
395 | static void | |
396 | print_union(struct mlist *mlp, struct tdesc *tdp, char *format, int level) | |
397 | { | |
398 | #if 0 /* { FIXME: */ | |
399 | if (level != 0) | |
400 | printf("/* ' noop ' %s */", format); | |
401 | else | |
402 | printf("#define\t%s 0x%x\n", format, mlp->offset / 8); | |
403 | #endif /* } */ | |
404 | printf("!\tunion %s @ 0x%x has size 0x%x\n", | |
405 | format, mlp->offset / 8, mlp->size / 8); | |
406 | } | |
407 | ||
408 | static void | |
409 | print_enum(struct mlist *mlp, struct tdesc *tdp, char *format, int level) | |
410 | { | |
411 | if (level != 0) | |
412 | printf("/* ' l@ ' %s */", format); | |
413 | else | |
414 | printf("#define\t%s 0x%x\n", format, mlp->offset / 8); | |
415 | } | |
416 | ||
417 | static int | |
418 | stabs_log2(unsigned int value) | |
419 | { | |
420 | int log = 1; | |
421 | int i; | |
422 | ||
423 | for (i = 0; i < sizeof (value) * 8; i++) { | |
424 | if ((log << i) == value) | |
425 | return (i); | |
426 | } | |
427 | return (-1); | |
428 | } |