5c6897e40b9cd507b9921401ba16cf180d78caed
[mesa.git] / src / freedreno / rnn / rnn.c
1 /*
2 * Copyright (C) 2010-2011 Marcin Koƛcielnicki <koriakin@0x04.net>
3 * Copyright (C) 2010 Luca Barbieri <luca@luca-barbieri.com>
4 * Copyright (C) 2010 Francisco Jerez <currojerez@riseup.net>
5 * Copyright (C) 2010 Martin Peres <martin.peres@ensi-bourges.fr>
6 * Copyright (C) 2010 Marcin Slusarz <marcin.slusarz@gmail.com>
7 * All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29 /* workaround libxml2 silliness: */
30 #pragma GCC diagnostic ignored "-Wpointer-sign"
31
32 #include <libxml/xmlversion.h>
33 #include <libxml/parser.h>
34 #include <libxml/xpath.h>
35 #include <libxml/xmlreader.h>
36 #include <stdint.h>
37 #include <string.h>
38 #include <limits.h>
39 #include <ctype.h>
40 #include <stdio.h>
41 #include "rnn.h"
42 #include "rnn_path.h"
43 #include "util.h"
44
45 #include "util/u_debug.h"
46
47 static char *catstr (char *a, char *b) {
48 if (!a)
49 return b;
50 return aprintf("%s_%s", a, b);
51 }
52
53 static int strdiff (const char *a, const char *b) {
54 if (!a && !b)
55 return 0;
56 if (!a || !b)
57 return 1;
58 return strcmp (a, b);
59 }
60
61 static void rnn_err(struct rnndb *db, const char *format, ...) _util_printf_format(2, 3);
62
63 static void rnn_err(struct rnndb *db, const char *format, ...)
64 {
65 va_list ap;
66 va_start(ap, format);
67 vfprintf(stderr, format, ap);
68 va_end(ap);
69 db->estatus = 1;
70 }
71
72 void rnn_init(void) {
73 LIBXML_TEST_VERSION
74 xmlInitParser();
75 }
76
77 struct rnndb *rnn_newdb(void) {
78 struct rnndb *db = calloc(sizeof *db, 1);
79 return db;
80 }
81
82 static char *getcontent (xmlNode *attr) {
83 xmlNode *chain = attr->children;
84 size_t size = 0;
85 char *content, *p;
86 while (chain) {
87 if (chain->type == XML_TEXT_NODE)
88 size += strlen(chain->content);
89 chain = chain->next;
90 }
91 p = content = malloc(size + 1);
92 chain = attr->children;
93 while (chain) {
94 if (chain->type == XML_TEXT_NODE) {
95 char* sp = chain->content;
96 if(p == content) {
97 while(isspace(*sp))
98 ++sp;
99 }
100 size_t len = strlen(sp);
101 memcpy(p, sp, len);
102 p += len;
103 }
104 chain = chain->next;
105 }
106 while(p != content && isspace(p[-1]))
107 --p;
108 *p = 0;
109 return content;
110 }
111
112 static char *getattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
113 xmlNode *chain = attr->children;
114 while (chain) {
115 if (chain->type != XML_TEXT_NODE) {
116 rnn_err(db, "%s:%d: unknown attribute child \"%s\" in attribute \"%s\"\n", file, line, chain->name, attr->name);
117 } else {
118 return chain->content;
119 }
120 chain = chain->next;
121 }
122 return "";
123 }
124
125 static int getboolattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
126 char *c = getattrib(db, file, line, attr);
127 if (!strcmp(c, "yes") || !strcmp(c, "1") || !strcmp(c, "true"))
128 return 1;
129 if (!strcmp(c, "no") || !strcmp(c, "0") || !strcmp(c, "false"))
130 return 0;
131 rnn_err(db, "%s:%d: invalid boolean value \"%s\" in attribute \"%s\"\n", file, line, c, attr->name);
132 return 0;
133 }
134
135 static uint64_t getnum(struct rnndb *db, char *file, int line, xmlAttr *attr, char *c)
136 {
137 char *cc;
138 uint64_t res;
139 if (strchr(c, 'x') || strchr(c, 'X'))
140 res = strtoull(c, &cc, 16);
141 else
142 res = strtoull(c, &cc, 10);
143 if (*cc) {
144 rnn_err(db, "%s:%d: invalid numeric value \"%s\" in attribute \"%s\"\n", file, line, c, attr->name);
145 }
146 return res;
147 }
148
149 static uint64_t getnumattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
150 char *c = getattrib(db, file, line, attr);
151 return getnum(db, file, line, attr, c);
152 }
153
154 static int trytop (struct rnndb *db, char *file, xmlNode *node);
155
156 static int trydoc (struct rnndb *db, char *file, xmlNode *node) {
157 if (!strcmp(node->name, "brief")) {
158 return 1;
159 } else if (!strcmp(node->name, "doc")) {
160 return 1;
161 }
162 return 0;
163 }
164
165 static struct rnnvalue *parsevalue(struct rnndb *db, char *file, xmlNode *node);
166 static struct rnnbitfield *parsebitfield(struct rnndb *db, char *file, xmlNode *node);
167
168 static int trytypetag (struct rnndb *db, char *file, xmlNode *node, struct rnntypeinfo *ti) {
169 if (!strcmp(node->name, "value")) {
170 struct rnnvalue *val = parsevalue(db, file, node);
171 if (val)
172 ADDARRAY(ti->vals, val);
173 return 1;
174 } else if (!strcmp(node->name, "bitfield")) {
175 struct rnnbitfield *bf = parsebitfield(db, file, node);
176 if (bf)
177 ADDARRAY(ti->bitfields, bf);
178 return 1;
179 }
180 return 0;
181 }
182 static int trytypeattr (struct rnndb *db, char *file, xmlNode *node, xmlAttr *attr, struct rnntypeinfo *ti) {
183 if (!strcmp(attr->name, "shr")) {
184 ti->shr = getnumattrib(db, file, node->line, attr);
185 return 1;
186 } else if (!strcmp(attr->name, "min")) {
187 ti->min = getnumattrib(db, file, node->line, attr);
188 ti->minvalid = 1;
189 return 1;
190 } else if (!strcmp(attr->name, "max")) {
191 ti->max = getnumattrib(db, file, node->line, attr);
192 ti->maxvalid = 1;
193 return 1;
194 } else if (!strcmp(attr->name, "align")) {
195 ti->align = getnumattrib(db, file, node->line, attr);
196 ti->alignvalid = 1;
197 return 1;
198 } else if (!strcmp(attr->name, "type")) {
199 ti->name = strdup(getattrib(db, file, node->line, attr));;
200 return 1;
201 } else if (!strcmp(attr->name, "radix")) {
202 ti->radix = getnumattrib(db, file, node->line, attr);
203 ti->radixvalid = 1;
204 return 1;
205 } else if (!strcmp(attr->name, "pos")) {
206 ti->high = ti->low = getnumattrib(db, file, node->line, attr);
207 return 1;
208 } else if (!strcmp(attr->name, "low")) {
209 ti->low = getnumattrib(db, file, node->line, attr);
210 return 1;
211 } else if (!strcmp(attr->name, "high")) {
212 ti->high = getnumattrib(db, file, node->line, attr);
213 return 1;
214 } else if (!strcmp(attr->name, "addvariant")) {
215 ti->addvariant = getboolattrib(db, file, node->line, attr);
216 return 1;
217 }
218 return 0;
219 }
220
221 static struct rnnvalue *parsevalue(struct rnndb *db, char *file, xmlNode *node) {
222 struct rnnvalue *val = calloc(sizeof *val, 1);
223 val->file = file;
224 xmlAttr *attr = node->properties;
225 while (attr) {
226 if (!strcmp(attr->name, "name")) {
227 val->name = strdup(getattrib(db, file, node->line, attr));
228 } else if (!strcmp(attr->name, "value")) {
229 val->value = getnumattrib(db, file, node->line, attr);
230 val->valvalid = 1;
231 } else if (!strcmp(attr->name, "varset")) {
232 val->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
233 } else if (!strcmp(attr->name, "variants")) {
234 val->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
235 } else {
236 rnn_err(db, "%s:%d: wrong attribute \"%s\" for value\n", file, node->line, attr->name);
237 }
238 attr = attr->next;
239 }
240 xmlNode *chain = node->children;
241 while (chain) {
242 if (chain->type != XML_ELEMENT_NODE) {
243 } else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
244 rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
245 }
246 chain = chain->next;
247 }
248 if (!val->name) {
249 rnn_err(db, "%s:%d: nameless value\n", file, node->line);
250 return 0;
251 } else {
252 return val;
253 }
254 }
255
256 static void parsespectype(struct rnndb *db, char *file, xmlNode *node) {
257 struct rnnspectype *res = calloc (sizeof *res, 1);
258 res->file = file;
259 xmlAttr *attr = node->properties;
260 int i;
261 while (attr) {
262 if (!strcmp(attr->name, "name")) {
263 res->name = strdup(getattrib(db, file, node->line, attr));
264 } else if (!trytypeattr(db, file, node, attr, &res->typeinfo)) {
265 rnn_err(db, "%s:%d: wrong attribute \"%s\" for spectype\n", file, node->line, attr->name);
266 }
267 attr = attr->next;
268 }
269 if (!res->name) {
270 rnn_err(db, "%s:%d: nameless spectype\n", file, node->line);
271 return;
272 }
273 for (i = 0; i < db->spectypesnum; i++)
274 if (!strcmp(db->spectypes[i]->name, res->name)) {
275 rnn_err(db, "%s:%d: duplicated spectype name %s\n", file, node->line, res->name);
276 return;
277 }
278 ADDARRAY(db->spectypes, res);
279 xmlNode *chain = node->children;
280 while (chain) {
281 if (chain->type != XML_ELEMENT_NODE) {
282 } else if (!trytypetag(db, file, chain, &res->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) {
283 rnn_err(db, "%s:%d: wrong tag in spectype: <%s>\n", file, chain->line, chain->name);
284 }
285 chain = chain->next;
286 }
287 }
288
289 static void parseenum(struct rnndb *db, char *file, xmlNode *node) {
290 xmlAttr *attr = node->properties;
291 char *name = 0;
292 int isinline = 0;
293 int bare = 0;
294 char *prefixstr = 0;
295 char *varsetstr = 0;
296 char *variantsstr = 0;
297 int i;
298 while (attr) {
299 if (!strcmp(attr->name, "name")) {
300 name = getattrib(db, file, node->line, attr);
301 } else if (!strcmp(attr->name, "bare")) {
302 bare = getboolattrib(db, file, node->line, attr);
303 } else if (!strcmp(attr->name, "inline")) {
304 isinline = getboolattrib(db, file, node->line, attr);
305 } else if (!strcmp(attr->name, "prefix")) {
306 prefixstr = strdup(getattrib(db, file, node->line, attr));
307 } else if (!strcmp(attr->name, "varset")) {
308 varsetstr = strdup(getattrib(db, file, node->line, attr));
309 } else if (!strcmp(attr->name, "variants")) {
310 variantsstr = strdup(getattrib(db, file, node->line, attr));
311 } else {
312 rnn_err(db, "%s:%d: wrong attribute \"%s\" for enum\n", file, node->line, attr->name);
313 }
314 attr = attr->next;
315 }
316 if (!name) {
317 rnn_err(db, "%s:%d: nameless enum\n", file, node->line);
318 return;
319 }
320 struct rnnenum *cur = 0;
321 for (i = 0; i < db->enumsnum; i++)
322 if (!strcmp(db->enums[i]->name, name)) {
323 cur = db->enums[i];
324 break;
325 }
326 if (cur) {
327 if (strdiff(cur->varinfo.prefixstr, prefixstr) ||
328 strdiff(cur->varinfo.varsetstr, varsetstr) ||
329 strdiff(cur->varinfo.variantsstr, variantsstr) ||
330 cur->isinline != isinline || cur->bare != bare) {
331 rnn_err(db, "%s:%d: merge fail for enum %s\n", file, node->line, node->name);
332 }
333 } else {
334 cur = calloc(sizeof *cur, 1);
335 cur->name = strdup(name);
336 cur->isinline = isinline;
337 cur->bare = bare;
338 cur->varinfo.prefixstr = prefixstr;
339 cur->varinfo.varsetstr = varsetstr;
340 cur->varinfo.variantsstr = variantsstr;
341 cur->file = file;
342 ADDARRAY(db->enums, cur);
343 }
344 xmlNode *chain = node->children;
345 while (chain) {
346 if (chain->type != XML_ELEMENT_NODE) {
347 } else if (!strcmp(chain->name, "value")) {
348 struct rnnvalue *val = parsevalue(db, file, chain);
349 if (val)
350 ADDARRAY(cur->vals, val);
351 } else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
352 rnn_err(db, "%s:%d: wrong tag in enum: <%s>\n", file, chain->line, chain->name);
353 }
354 chain = chain->next;
355 }
356 }
357
358 static struct rnnbitfield *parsebitfield(struct rnndb *db, char *file, xmlNode *node) {
359 struct rnnbitfield *bf = calloc(sizeof *bf, 1);
360 bf->file = file;
361 xmlAttr *attr = node->properties;
362 bf->typeinfo.low = bf->typeinfo.high = -1;
363 while (attr) {
364 if (!strcmp(attr->name, "name")) {
365 bf->name = strdup(getattrib(db, file, node->line, attr));
366 } else if (!strcmp(attr->name, "varset")) {
367 bf->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
368 } else if (!strcmp(attr->name, "variants")) {
369 bf->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
370 } else if (!trytypeattr(db, file, node, attr, &bf->typeinfo)) {
371 rnn_err(db, "%s:%d: wrong attribute \"%s\" for bitfield\n", file, node->line, attr->name);
372 }
373 attr = attr->next;
374 }
375 xmlNode *chain = node->children;
376 while (chain) {
377 if (chain->type != XML_ELEMENT_NODE) {
378 } else if (!trytypetag(db, file, chain, &bf->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) {
379 rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
380 }
381 chain = chain->next;
382 }
383 if (!bf->name) {
384 rnn_err(db, "%s:%d: nameless bitfield\n", file, node->line);
385 return 0;
386 } else if (bf->typeinfo.low < 0|| bf->typeinfo.high < 0 || bf->typeinfo.high < bf->typeinfo.low) {
387 rnn_err(db, "%s:%d: bitfield has wrong placement\n", file, node->line);
388 return 0;
389 } else {
390 return bf;
391 }
392 }
393
394 static void parsebitset(struct rnndb *db, char *file, xmlNode *node) {
395 xmlAttr *attr = node->properties;
396 char *name = 0;
397 int isinline = 0;
398 int bare = 0;
399 char *prefixstr = 0;
400 char *varsetstr = 0;
401 char *variantsstr = 0;
402 int i;
403 while (attr) {
404 if (!strcmp(attr->name, "name")) {
405 name = getattrib(db, file, node->line, attr);
406 } else if (!strcmp(attr->name, "bare")) {
407 bare = getboolattrib(db, file, node->line, attr);
408 } else if (!strcmp(attr->name, "inline")) {
409 isinline = getboolattrib(db, file, node->line, attr);
410 } else if (!strcmp(attr->name, "prefix")) {
411 prefixstr = strdup(getattrib(db, file, node->line, attr));
412 } else if (!strcmp(attr->name, "varset")) {
413 varsetstr = strdup(getattrib(db, file, node->line, attr));
414 } else if (!strcmp(attr->name, "variants")) {
415 variantsstr = strdup(getattrib(db, file, node->line, attr));
416 } else {
417 rnn_err(db, "%s:%d: wrong attribute \"%s\" for bitset\n", file, node->line, attr->name);
418 }
419 attr = attr->next;
420 }
421 if (!name) {
422 rnn_err(db, "%s:%d: nameless bitset\n", file, node->line);
423 return;
424 }
425 struct rnnbitset *cur = 0;
426 for (i = 0; i < db->bitsetsnum; i++)
427 if (!strcmp(db->bitsets[i]->name, name)) {
428 cur = db->bitsets[i];
429 break;
430 }
431 if (cur) {
432 if (strdiff(cur->varinfo.prefixstr, prefixstr) ||
433 strdiff(cur->varinfo.varsetstr, varsetstr) ||
434 strdiff(cur->varinfo.variantsstr, variantsstr) ||
435 cur->isinline != isinline || cur->bare != bare) {
436 rnn_err(db, "%s:%d: merge fail for bitset %s\n", file, node->line, node->name);
437 }
438 } else {
439 cur = calloc(sizeof *cur, 1);
440 cur->name = strdup(name);
441 cur->isinline = isinline;
442 cur->bare = bare;
443 cur->varinfo.prefixstr = prefixstr;
444 cur->varinfo.varsetstr = varsetstr;
445 cur->varinfo.variantsstr = variantsstr;
446 cur->file = file;
447 ADDARRAY(db->bitsets, cur);
448 }
449 xmlNode *chain = node->children;
450 while (chain) {
451 if (chain->type != XML_ELEMENT_NODE) {
452 } else if (!strcmp(chain->name, "bitfield")) {
453 struct rnnbitfield *bf = parsebitfield(db, file, chain);
454 if (bf)
455 ADDARRAY(cur->bitfields, bf);
456 } else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
457 rnn_err(db, "%s:%d: wrong tag in bitset: <%s>\n", file, chain->line, chain->name);
458 }
459 chain = chain->next;
460 }
461 }
462
463 static struct rnndelem *trydelem(struct rnndb *db, char *file, xmlNode *node) {
464 if (!strcmp(node->name, "use-group")) {
465 struct rnndelem *res = calloc(sizeof *res, 1);
466 res->file = file;
467 res->type = RNN_ETYPE_USE_GROUP;
468 xmlAttr *attr = node->properties;
469 while (attr) {
470 if (!strcmp(attr->name, "ref")) {
471 res->name = strdup(getattrib(db, file, node->line, attr));
472 } else {
473 rnn_err(db, "%s:%d: wrong attribute \"%s\" for %s\n", file, node->line, attr->name, node->name);
474 }
475 attr = attr->next;
476 }
477 if (!res->name) {
478 rnn_err(db, "%s:%d: nameless use-group\n", file, node->line);
479 return 0;
480 }
481 return res;
482 } else if (!strcmp(node->name, "stripe") || !strcmp(node->name, "array")) {
483 struct rnndelem *res = calloc(sizeof *res, 1);
484 if (!strcmp(node->name, "array"))
485 res->name = "";
486 res->type = (strcmp(node->name, "stripe")?RNN_ETYPE_ARRAY:RNN_ETYPE_STRIPE);
487 res->length = 1;
488 res->file = file;
489 xmlAttr *attr = node->properties;
490 while (attr) {
491 if (!strcmp(attr->name, "name")) {
492 res->name = strdup(getattrib(db, file, node->line, attr));
493 } else if (!strcmp(attr->name, "offset")) {
494 res->offset = getnumattrib(db, file, node->line, attr);
495 } else if (!strcmp(attr->name, "offsets")) {
496 char *str = strdup(getattrib(db, file, node->line, attr));
497 char *tok, *save, *tmp = str;
498 while ((tok = strtok_r(str, ",", &save))) {
499 uint64_t offset = getnum(db, file, node->line, attr, tok);
500 ADDARRAY(res->offsets, offset);
501 str = NULL;
502 }
503 if (str)
504 fprintf(stderr, "%s:%d: invalid offsets: %s\n", file, node->line, str);
505 free(tmp);
506 } else if (!strcmp(attr->name, "doffset")) {
507 /* dynamic runtime determined offset: */
508 res->doffset = strdup(getattrib(db, file, node->line, attr));
509 } else if (!strcmp(attr->name, "doffsets")) {
510 /* dynamic runtime determined offsets: */
511 char *str = strdup(getattrib(db, file, node->line, attr));
512 char *tok, *save, *tmp = str;
513 while ((tok = strtok_r(str, ",", &save))) {
514 char *doffset = strdup(tok);
515 ADDARRAY(res->doffsets, doffset);
516 str = NULL;
517 }
518 if (str)
519 fprintf(stderr, "%s:%d: invalid offsets: %s\n", file, node->line, str);
520 free(tmp);
521 } else if (!strcmp(attr->name, "length")) {
522 res->length = getnumattrib(db, file, node->line, attr);
523 } else if (!strcmp(attr->name, "stride")) {
524 res->stride = getnumattrib(db, file, node->line, attr);
525 } else if (!strcmp(attr->name, "prefix")) {
526 res->varinfo.prefixstr = strdup(getattrib(db, file, node->line, attr));
527 } else if (!strcmp(attr->name, "varset")) {
528 res->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
529 } else if (!strcmp(attr->name, "variants")) {
530 res->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
531 } else if (!strcmp(attr->name, "index")) {
532 const char *enumname = getattrib(db, file, node->line, attr);
533 res->index = rnn_findenum(db, enumname);
534 if (!res->index) {
535 rnn_err(db, "%s:%d: invalid enum name \"%s\"\n", file, node->line, enumname);
536 }
537 } else {
538 rnn_err(db, "%s:%d: wrong attribute \"%s\" for %s\n", file, node->line, attr->name, node->name);
539 }
540 attr = attr->next;
541 }
542 xmlNode *chain = node->children;
543 while (chain) {
544 struct rnndelem *delem;
545 if (chain->type != XML_ELEMENT_NODE) {
546 } else if ((delem = trydelem(db, file, chain))) {
547 ADDARRAY(res->subelems, delem);
548 } else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
549 rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
550 }
551 chain = chain->next;
552 }
553
554 /* Sanity checking */
555 if (res->type == RNN_ETYPE_ARRAY && res->stride == 0) {
556 fprintf(stderr, "%s: Array %s's stride is undefined. Aborting.\n", file, res->name);
557 exit(-1);
558 }
559 return res;
560
561 }
562 int width;
563 if (!strcmp(node->name, "reg8"))
564 width = 8;
565 else if (!strcmp(node->name, "reg16"))
566 width = 16;
567 else if (!strcmp(node->name, "reg32"))
568 width = 32;
569 else if (!strcmp(node->name, "reg64"))
570 width = 64;
571 else
572 return 0;
573 struct rnndelem *res = calloc(sizeof *res, 1);
574 res->file = file;
575 res->type = RNN_ETYPE_REG;
576 res->width = width;
577 res->length = 1;
578 res->access = RNN_ACCESS_RW;
579 xmlAttr *attr = node->properties;
580 res->typeinfo.low = 0;
581 res->typeinfo.high = width - 1;
582 while (attr) {
583 if (!strcmp(attr->name, "name")) {
584 res->name = strdup(getattrib(db, file, node->line, attr));
585 } else if (!strcmp(attr->name, "offset")) {
586 res->offset = getnumattrib(db, file, node->line, attr);
587 } else if (!strcmp(attr->name, "length")) {
588 res->length = getnumattrib(db, file, node->line, attr);
589 } else if (!strcmp(attr->name, "stride")) {
590 res->stride = getnumattrib(db, file, node->line, attr);
591 } else if (!strcmp(attr->name, "varset")) {
592 res->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
593 } else if (!strcmp(attr->name, "variants")) {
594 res->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
595 } else if (!strcmp(attr->name, "access")) {
596 char *str = getattrib(db, file, node->line, attr);
597 if (!strcmp(str, "r"))
598 res->access = RNN_ACCESS_R;
599 else if (!strcmp(str, "w"))
600 res->access = RNN_ACCESS_W;
601 else if (!strcmp(str, "rw"))
602 res->access = RNN_ACCESS_RW;
603 else
604 fprintf (stderr, "%s:%d: wrong access type \"%s\" for register\n", file, node->line, str);
605 } else if (!trytypeattr(db, file, node, attr, &res->typeinfo)) {
606 rnn_err(db, "%s:%d: wrong attribute \"%s\" for register\n", file, node->line, attr->name);
607 }
608 attr = attr->next;
609 }
610 xmlNode *chain = node->children;
611 while (chain) {
612 if (chain->type != XML_ELEMENT_NODE) {
613 } else if (!trytypetag(db, file, chain, &res->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) {
614 rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
615 }
616 chain = chain->next;
617 }
618 if (!res->name) {
619 rnn_err(db, "%s:%d: nameless register\n", file, node->line);
620 return 0;
621 } else {
622 }
623 return res;
624 }
625
626 static void parsegroup(struct rnndb *db, char *file, xmlNode *node) {
627 xmlAttr *attr = node->properties;
628 char *name = 0;
629 int i;
630 while (attr) {
631 if (!strcmp(attr->name, "name")) {
632 name = getattrib(db, file, node->line, attr);
633 } else {
634 rnn_err(db, "%s:%d: wrong attribute \"%s\" for group\n", file, node->line, attr->name);
635 }
636 attr = attr->next;
637 }
638 if (!name) {
639 rnn_err(db, "%s:%d: nameless group\n", file, node->line);
640 return;
641 }
642 struct rnngroup *cur = 0;
643 for (i = 0; i < db->groupsnum; i++)
644 if (!strcmp(db->groups[i]->name, name)) {
645 cur = db->groups[i];
646 break;
647 }
648 if (!cur) {
649 cur = calloc(sizeof *cur, 1);
650 cur->name = strdup(name);
651 ADDARRAY(db->groups, cur);
652 }
653 xmlNode *chain = node->children;
654 while (chain) {
655 struct rnndelem *delem;
656 if (chain->type != XML_ELEMENT_NODE) {
657 } else if ((delem = trydelem(db, file, chain))) {
658 ADDARRAY(cur->subelems, delem);
659 } else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
660 rnn_err(db, "%s:%d: wrong tag in group: <%s>\n", file, chain->line, chain->name);
661 }
662 chain = chain->next;
663 }
664 }
665
666 static void parsedomain(struct rnndb *db, char *file, xmlNode *node) {
667 xmlAttr *attr = node->properties;
668 char *name = 0;
669 uint64_t size = 0; int width = 8;
670 int bare = 0;
671 char *prefixstr = 0;
672 char *varsetstr = 0;
673 char *variantsstr = 0;
674 int i;
675 while (attr) {
676 if (!strcmp(attr->name, "name")) {
677 name = getattrib(db, file, node->line, attr);
678 } else if (!strcmp(attr->name, "bare")) {
679 bare = getboolattrib(db, file, node->line, attr);
680 } else if (!strcmp(attr->name, "size")) {
681 size = getnumattrib(db, file, node->line, attr);
682 } else if (!strcmp(attr->name, "width")) {
683 width = getnumattrib(db, file, node->line, attr);
684 } else if (!strcmp(attr->name, "prefix")) {
685 prefixstr = strdup(getattrib(db, file, node->line, attr));
686 } else if (!strcmp(attr->name, "varset")) {
687 varsetstr = strdup(getattrib(db, file, node->line, attr));
688 } else if (!strcmp(attr->name, "variants")) {
689 variantsstr = strdup(getattrib(db, file, node->line, attr));
690 } else {
691 rnn_err(db, "%s:%d: wrong attribute \"%s\" for domain\n", file, node->line, attr->name);
692 }
693 attr = attr->next;
694 }
695 if (!name) {
696 rnn_err(db, "%s:%d: nameless domain\n", file, node->line);
697 return;
698 }
699 struct rnndomain *cur = 0;
700 for (i = 0; i < db->domainsnum; i++)
701 if (!strcmp(db->domains[i]->name, name)) {
702 cur = db->domains[i];
703 break;
704 }
705 if (cur) {
706 if (strdiff(cur->varinfo.prefixstr, prefixstr) ||
707 strdiff(cur->varinfo.varsetstr, varsetstr) ||
708 strdiff(cur->varinfo.variantsstr, variantsstr) ||
709 cur->width != width ||
710 cur->bare != bare ||
711 (size && cur->size && size != cur->size)) {
712 rnn_err(db, "%s:%d: merge fail for domain %s\n", file, node->line, node->name);
713 } else {
714 if (size)
715 cur->size = size;
716 }
717 } else {
718 cur = calloc(sizeof *cur, 1);
719 cur->name = strdup(name);
720 cur->bare = bare;
721 cur->width = width;
722 cur->size = size;
723 cur->varinfo.prefixstr = prefixstr;
724 cur->varinfo.varsetstr = varsetstr;
725 cur->varinfo.variantsstr = variantsstr;
726 cur->file = file;
727 ADDARRAY(db->domains, cur);
728 }
729 xmlNode *chain = node->children;
730 while (chain) {
731 struct rnndelem *delem;
732 if (chain->type != XML_ELEMENT_NODE) {
733 } else if ((delem = trydelem(db, file, chain))) {
734 ADDARRAY(cur->subelems, delem);
735 } else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
736 rnn_err(db, "%s:%d: wrong tag in domain: <%s>\n", file, chain->line, chain->name);
737 }
738 chain = chain->next;
739 }
740 }
741
742 static void parsecopyright(struct rnndb *db, char *file, xmlNode *node) {
743 struct rnncopyright* copyright = &db->copyright;
744 xmlAttr *attr = node->properties;
745 while (attr) {
746 if (!strcmp(attr->name, "year")) {
747 unsigned firstyear = getnumattrib(db, file, node->line, attr);
748 if(!copyright->firstyear || firstyear < copyright->firstyear)
749 copyright->firstyear = firstyear;
750 } else {
751 rnn_err(db, "%s:%d: wrong attribute \"%s\" for copyright\n", file, node->line, attr->name);
752 }
753 attr = attr->next;
754 }
755 xmlNode *chain = node->children;
756 while (chain) {
757 if (chain->type != XML_ELEMENT_NODE) {
758 } else if (!strcmp(chain->name, "license"))
759 if(copyright->license) {
760 if(strcmp(copyright->license, node->content)) {
761 fprintf(stderr, "fatal error: multiple different licenses specified!\n");
762 abort(); /* TODO: do something better here, but headergen, xml2html, etc. should not produce anything in this case */
763 }
764 } else
765 copyright->license = getcontent(chain);
766 else if (!strcmp(chain->name, "author")) {
767 struct rnnauthor* author = calloc(sizeof *author, 1);
768 xmlAttr* authorattr = chain->properties;
769 xmlNode *authorchild = chain->children;
770 author->contributions = getcontent(chain);
771 while (authorattr) {
772 if (!strcmp(authorattr->name, "name"))
773 author->name = strdup(getattrib(db, file, chain->line, authorattr));
774 else if (!strcmp(authorattr->name, "email"))
775 author->email = strdup(getattrib(db, file, chain->line, authorattr));
776 else {
777 rnn_err(db, "%s:%d: wrong attribute \"%s\" for author\n", file, chain->line, authorattr->name);
778 }
779 authorattr = authorattr->next;
780 }
781 while(authorchild) {
782 if (authorchild->type != XML_ELEMENT_NODE) {
783 } else if (!strcmp(authorchild->name, "nick")) {
784 xmlAttr* nickattr = authorchild->properties;
785 char* nickname = 0;
786 while(nickattr) {
787 if (!strcmp(nickattr->name, "name"))
788 nickname = strdup(getattrib(db, file, authorchild->line, nickattr));
789 else {
790 rnn_err(db, "%s:%d: wrong attribute \"%s\" for nick\n", file, authorchild->line, nickattr->name);
791 }
792 nickattr = nickattr->next;
793 }
794 if(!nickname) {
795 rnn_err(db, "%s:%d: missing \"name\" attribute for nick\n", file, authorchild->line);
796 } else
797 ADDARRAY(author->nicknames, nickname);
798 } else {
799 rnn_err(db, "%s:%d: wrong tag in author: <%s>\n", file, authorchild->line, authorchild->name);
800 }
801 authorchild = authorchild->next;
802 }
803 ADDARRAY(copyright->authors, author);
804 } else {
805 rnn_err(db, "%s:%d: wrong tag in copyright: <%s>\n", file, chain->line, chain->name);
806 }
807 chain = chain->next;
808 }
809 }
810
811 static int trytop (struct rnndb *db, char *file, xmlNode *node) {
812 if (!strcmp(node->name, "enum")) {
813 parseenum(db, file, node);
814 return 1;
815 } else if (!strcmp(node->name, "bitset")) {
816 parsebitset(db, file, node);
817 return 1;
818 } else if (!strcmp(node->name, "group")) {
819 parsegroup(db, file, node);
820 return 1;
821 } else if (!strcmp(node->name, "domain")) {
822 parsedomain(db, file, node);
823 return 1;
824 } else if (!strcmp(node->name, "spectype")) {
825 parsespectype(db, file, node);
826 return 1;
827 } else if (!strcmp(node->name, "import")) {
828 xmlAttr *attr = node->properties;
829 char *subfile = 0;
830 while (attr) {
831 if (!strcmp(attr->name, "file")) {
832 subfile = getattrib(db, file, node->line, attr);
833 } else {
834 rnn_err(db, "%s:%d: wrong attribute \"%s\" for import\n", file, node->line, attr->name);
835 }
836 attr = attr->next;
837 }
838 if (!subfile) {
839 rnn_err(db, "%s:%d: missing \"file\" attribute for import\n", file, node->line);
840 } else {
841 rnn_parsefile(db, subfile);
842 }
843 return 1;
844 } else if (!strcmp(node->name, "copyright")) {
845 parsecopyright(db, file, node);
846 return 1;
847 }
848 return 0;
849 }
850
851 static char * find_file(const char *file_orig)
852 {
853 const char *rnn_path = getenv("RNN_PATH");
854 char *fname;
855
856 if (!rnn_path)
857 rnn_path = RNN_DEF_PATH;
858
859 FILE *file = find_in_path(file_orig, rnn_path, &fname);
860 if (!file) {
861 fprintf (stderr, "%s: couldn't find database file. Please set the env var RNN_PATH.\n", file_orig);
862 return NULL;
863 }
864 fclose(file);
865
866 return fname;
867 }
868
869 static int validate_doc(struct rnndb *db, xmlDocPtr doc, xmlNodePtr database)
870 {
871 /* find the schemaLocation property: */
872 xmlAttrPtr attr = database->properties;
873 const char *schema_name = NULL;
874 char *schema_path;
875
876 while (attr) {
877 if (!strcmp(attr->name, "schemaLocation")) {
878 xmlNodePtr data = attr->children;
879 schema_name = data->content;
880 /* we expect this to look like <namespace url> schema.xsd.. I think
881 * technically it is supposed to be just a URL, but that doesn't
882 * quite match up to what we do.. Just skip over everything up to
883 * and including the first whitespace character:
884 */
885 while (schema_name && (schema_name[0] != ' '))
886 schema_name++;
887 schema_name++;
888 break;
889 }
890 }
891
892 if (!schema_name) {
893 rnn_err(db, "could not find schema. Missing schemaLocation?");
894 return 0;
895 }
896
897 schema_path = find_file(schema_name);
898 if (!schema_path) {
899 rnn_err(db, "%s: couldn't find database file. Please set the env var RNN_PATH.\n", schema_name);
900 return 0;
901 }
902
903 xmlSchemaParserCtxtPtr parser = xmlSchemaNewParserCtxt(schema_path);
904 xmlSchemaPtr schema = xmlSchemaParse(parser);
905 xmlSchemaValidCtxtPtr validCtxt = xmlSchemaNewValidCtxt(schema);
906 int ret = xmlSchemaValidateDoc(validCtxt, doc);
907
908 xmlSchemaFreeValidCtxt(validCtxt);
909 xmlSchemaFree(schema);
910 xmlSchemaFreeParserCtxt(parser);
911
912 free(schema_path);
913
914 return ret;
915 }
916
917 void rnn_parsefile (struct rnndb *db, char *file_orig) {
918 int i;
919 char *fname;
920
921 fname = find_file(file_orig);
922 if (!fname) {
923 db->estatus = 1;
924 return;
925 }
926
927 for (i = 0; i < db->filesnum; i++)
928 if (!strcmp(db->files[i], fname))
929 return;
930
931 ADDARRAY(db->files, fname);
932 xmlDocPtr doc = xmlParseFile(fname);
933 if (!doc) {
934 rnn_err(db, "%s: couldn't open database file. Please set the env var RNN_PATH.\n", fname);
935 return;
936 }
937 xmlNode *root = doc->children;
938 while (root) {
939 if (root->type != XML_ELEMENT_NODE) {
940 } else if (strcmp(root->name, "database")) {
941 rnn_err(db, "%s:%d: wrong top-level tag <%s>\n", fname, root->line, root->name);
942 } else {
943 xmlNode *chain = root->children;
944 if (validate_doc(db, doc, root)) {
945 rnn_err(db, "%s: database file has errors\n", fname);
946 return;
947 }
948 while (chain) {
949 if (chain->type != XML_ELEMENT_NODE) {
950 } else if (!trytop(db, fname, chain) && !trydoc(db, fname, chain)) {
951 rnn_err(db, "%s:%d: wrong tag in database: <%s>\n", fname, chain->line, chain->name);
952 }
953 chain = chain->next;
954 }
955 }
956 root = root->next;
957 }
958 xmlFreeDoc(doc);
959 }
960
961 static struct rnnvalue *copyvalue (struct rnnvalue *val, char *file) {
962 struct rnnvalue *res = calloc (sizeof *res, 1);
963 res->name = val->name;
964 res->valvalid = val->valvalid;
965 res->value = val->value;
966 res->varinfo = val->varinfo;
967 res->file = file;
968 return res;
969 }
970
971 static struct rnnbitfield *copybitfield (struct rnnbitfield *bf, char *file);
972
973
974 static void copytypeinfo (struct rnntypeinfo *dst, struct rnntypeinfo *src, char *file) {
975 int i;
976 dst->name = src->name;
977 dst->shr = src->shr;
978 dst->low = src->low;
979 dst->high = src->high;
980 dst->min = src->min;
981 dst->max = src->max;
982 dst->align = src->align;
983 dst->addvariant = src->addvariant;
984 for (i = 0; i < src->valsnum; i++)
985 ADDARRAY(dst->vals, copyvalue(src->vals[i], file));
986 for (i = 0; i < src->bitfieldsnum; i++)
987 ADDARRAY(dst->bitfields, copybitfield(src->bitfields[i], file));
988 }
989
990 static struct rnnbitfield *copybitfield (struct rnnbitfield *bf, char *file) {
991 struct rnnbitfield *res = calloc (sizeof *res, 1);
992 res->name = bf->name;
993 res->varinfo = bf->varinfo;
994 res->file = file;
995 copytypeinfo(&res->typeinfo, &bf->typeinfo, file);
996 return res;
997 }
998
999 static struct rnndelem *copydelem (struct rnndelem *elem, char *file) {
1000 struct rnndelem *res = calloc (sizeof *res, 1);
1001 res->type = elem->type;
1002 res->name = elem->name;
1003 res->width = elem->width;
1004 res->access = elem->access;
1005 res->offset = elem->offset;
1006 res->length = elem->length;
1007 res->stride = elem->stride;
1008 res->varinfo = elem->varinfo;
1009 res->file = file;
1010 copytypeinfo(&res->typeinfo, &elem->typeinfo, file);
1011 int i;
1012 for (i = 0; i < elem->subelemsnum; i++)
1013 ADDARRAY(res->subelems, copydelem(elem->subelems[i], file));
1014 for (i = 0; i < elem->offsetsnum; i++)
1015 ADDARRAY(res->offsets, elem->offsets[i]);
1016 return res;
1017 }
1018
1019 static struct rnnvarset *copyvarset (struct rnnvarset *varset) {
1020 struct rnnvarset *res = calloc(sizeof *res, 1);
1021 res->venum = varset->venum;
1022 res->variants = calloc(sizeof *res->variants, res->venum->valsnum);
1023 int i;
1024 for (i = 0; i < res->venum->valsnum; i++)
1025 res->variants[i] = varset->variants[i];
1026 return res;
1027 }
1028
1029 static void prepenum(struct rnndb *db, struct rnnenum *en);
1030
1031 static int findvidx (struct rnndb *db, struct rnnenum *en, char *name) {
1032 int i;
1033 for (i = 0; i < en->valsnum; i++)
1034 if (!strcmp(en->vals[i]->name, name))
1035 return i;
1036 rnn_err(db, "Cannot find variant %s in enum %s!\n", name, en->name);
1037 return -1;
1038 }
1039
1040 static void prepvarinfo (struct rnndb *db, char *what, struct rnnvarinfo *vi, struct rnnvarinfo *parent) {
1041 if (parent)
1042 vi->prefenum = parent->prefenum;
1043 if (vi->prefixstr) {
1044 if (!strcmp(vi->prefixstr, "none"))
1045 vi->prefenum = 0;
1046 else
1047 vi->prefenum = rnn_findenum(db, vi->prefixstr); // XXX
1048 }
1049 int i;
1050 if (parent)
1051 for (i = 0; i < parent->varsetsnum; i++)
1052 ADDARRAY(vi->varsets, copyvarset(parent->varsets[i]));
1053 struct rnnenum *varset = vi->prefenum;
1054 if (!varset && !vi->varsetstr && parent)
1055 vi->varsetstr = parent->varsetstr;
1056 if (vi->varsetstr)
1057 varset = rnn_findenum(db, vi->varsetstr);
1058 if (vi->variantsstr) {
1059 char *vars = vi->variantsstr;
1060 if (!varset) {
1061 rnn_err(db, "%s: tried to use variants without active varset!\n", what);
1062 return;
1063 }
1064 struct rnnvarset *vs = 0;
1065 int nvars = varset->valsnum;
1066 for (i = 0; i < vi->varsetsnum; i++)
1067 if (vi->varsets[i]->venum == varset) {
1068 vs = vi->varsets[i];
1069 break;
1070 }
1071 if (!vs) {
1072 vs = calloc (sizeof *vs, 1);
1073 vs->venum = varset;
1074 vs->variants = calloc(sizeof *vs->variants, nvars);
1075 for (i = 0; i < nvars; i++)
1076 vs->variants[i] = 1;
1077 ADDARRAY(vi->varsets, vs);
1078 }
1079 while (1) {
1080 while (*vars == ' ') vars++;
1081 if (*vars == 0)
1082 break;
1083 char *split = vars;
1084 while (*split != ':' && *split != '-' && *split != ' ' && *split != 0)
1085 split++;
1086 char *first = 0;
1087 if (split != vars)
1088 first = strndup(vars, split-vars);
1089 if (*split == ' ' || *split == 0) {
1090 int idx = findvidx(db, varset, first);
1091 if (idx != -1)
1092 vs->variants[idx] |= 2;
1093 vars = split;
1094 } else {
1095 char *end = split+1;
1096 while (*end != ' ' && *end != 0)
1097 end++;
1098 char *second = 0;
1099 if (end != split+1)
1100 second = strndup(split+1, end-split-1);
1101 int idx1 = 0;
1102 if (first)
1103 idx1 = findvidx(db, varset, first);
1104 int idx2 = nvars;
1105 if (second) {
1106 idx2 = findvidx(db, varset, second);
1107 if (*split == '-')
1108 idx2++;
1109 }
1110 if (idx1 != -1 && idx2 != -1)
1111 for (i = idx1; i < idx2; i++)
1112 vs->variants[i] |= 2;
1113 vars = end;
1114 free(second);
1115 }
1116 free(first);
1117 }
1118 vi->dead = 1;
1119 for (i = 0; i < nvars; i++) {
1120 vs->variants[i] = (vs->variants[i] == 3);
1121 if (vs->variants[i])
1122 vi->dead = 0;
1123 }
1124 }
1125 if (vi->dead)
1126 return;
1127 if (vi->prefenum) {
1128 struct rnnvarset *vs = 0;
1129 for (i = 0; i < vi->varsetsnum; i++)
1130 if (vi->varsets[i]->venum == vi->prefenum) {
1131 vs = vi->varsets[i];
1132 break;
1133 }
1134 if (vs) {
1135 for (i = 0; i < vi->prefenum->valsnum; i++)
1136 if (vs->variants[i]) {
1137 vi->prefix = vi->prefenum->vals[i]->name;
1138 return;
1139 }
1140 } else {
1141 vi->prefix = vi->prefenum->vals[0]->name;
1142 }
1143 }
1144 }
1145
1146 static void prepvalue(struct rnndb *db, struct rnnvalue *val, char *prefix, struct rnnvarinfo *parvi) {
1147 val->fullname = catstr(prefix, val->name);
1148 prepvarinfo (db, val->fullname, &val->varinfo, parvi);
1149 if (val->varinfo.dead)
1150 return;
1151 if (val->varinfo.prefix)
1152 val->fullname = catstr(val->varinfo.prefix, val->fullname);
1153 }
1154
1155 static void prepbitfield(struct rnndb *db, struct rnnbitfield *bf, char *prefix, struct rnnvarinfo *parvi);
1156
1157 static void preptypeinfo(struct rnndb *db, struct rnntypeinfo *ti, char *prefix, struct rnnvarinfo *vi, char *file) {
1158 int i;
1159 if (ti->name) {
1160 struct rnnenum *en = rnn_findenum (db, ti->name);
1161 struct rnnbitset *bs = rnn_findbitset (db, ti->name);
1162 struct rnnspectype *st = rnn_findspectype (db, ti->name);
1163 if (en) {
1164 if (en->isinline) {
1165 ti->type = RNN_TTYPE_INLINE_ENUM;
1166 int j;
1167 for (j = 0; j < en->valsnum; j++)
1168 ADDARRAY(ti->vals, copyvalue(en->vals[j], file));
1169 } else {
1170 ti->type = RNN_TTYPE_ENUM;
1171 ti->eenum = en;
1172 }
1173 } else if (bs) {
1174 if (bs->isinline) {
1175 ti->type = RNN_TTYPE_INLINE_BITSET;
1176 int j;
1177 for (j = 0; j < bs->bitfieldsnum; j++)
1178 ADDARRAY(ti->bitfields, copybitfield(bs->bitfields[j], file));
1179 } else {
1180 ti->type = RNN_TTYPE_BITSET;
1181 ti->ebitset = bs;
1182 }
1183 } else if (st) {
1184 ti->type = RNN_TTYPE_SPECTYPE;
1185 ti->spectype = st;
1186 } else if (!strcmp(ti->name, "hex")) {
1187 ti->type = RNN_TTYPE_HEX;
1188 } else if (!strcmp(ti->name, "float")) {
1189 ti->type = RNN_TTYPE_FLOAT;
1190 } else if (!strcmp(ti->name, "uint")) {
1191 ti->type = RNN_TTYPE_UINT;
1192 } else if (!strcmp(ti->name, "int")) {
1193 ti->type = RNN_TTYPE_INT;
1194 } else if (!strcmp(ti->name, "boolean")) {
1195 ti->type = RNN_TTYPE_BOOLEAN;
1196 } else if (!strcmp(ti->name, "bitfield")) {
1197 ti->type = RNN_TTYPE_INLINE_BITSET;
1198 } else if (!strcmp(ti->name, "enum")) {
1199 ti->type = RNN_TTYPE_INLINE_ENUM;
1200 } else if (!strcmp(ti->name, "fixed")) {
1201 ti->type = RNN_TTYPE_FIXED;
1202 } else if (!strcmp(ti->name, "ufixed")) {
1203 ti->type = RNN_TTYPE_UFIXED;
1204 } else if (!strcmp(ti->name, "a3xx_regid")) {
1205 ti->type = RNN_TTYPE_A3XX_REGID;
1206 } else if (!strcmp(ti->name, "waddress") || !strcmp(ti->name, "address")) {
1207 ti->type = RNN_TTYPE_HEX;
1208 } else {
1209 ti->type = RNN_TTYPE_HEX;
1210 rnn_err(db, "%s: unknown type %s\n", prefix, ti->name);
1211 }
1212 } else if (ti->bitfieldsnum) {
1213 ti->name = "bitfield";
1214 ti->type = RNN_TTYPE_INLINE_BITSET;
1215 } else if (ti->valsnum) {
1216 ti->name = "enum";
1217 ti->type = RNN_TTYPE_INLINE_ENUM;
1218 } else if (ti->low == 0 && ti->high == 0) {
1219 ti->name = "boolean";
1220 ti->type = RNN_TTYPE_BOOLEAN;
1221 } else {
1222 ti->name = "hex";
1223 ti->type = RNN_TTYPE_HEX;
1224 }
1225 if (ti->addvariant && ti->type != RNN_TTYPE_ENUM) {
1226 rnn_err(db, "%s: addvariant specified on non-enum type %s\n", prefix, ti->name);
1227 }
1228 for (i = 0; i < ti->bitfieldsnum; i++)
1229 prepbitfield(db, ti->bitfields[i], prefix, vi);
1230 for (i = 0; i < ti->valsnum; i++)
1231 prepvalue(db, ti->vals[i], prefix, vi);
1232 }
1233
1234 static void prepbitfield(struct rnndb *db, struct rnnbitfield *bf, char *prefix, struct rnnvarinfo *parvi) {
1235 bf->fullname = catstr(prefix, bf->name);
1236 prepvarinfo (db, bf->fullname, &bf->varinfo, parvi);
1237 if (bf->varinfo.dead)
1238 return;
1239 preptypeinfo(db, &bf->typeinfo, bf->fullname, &bf->varinfo, bf->file);
1240 if (bf->varinfo.prefix)
1241 bf->fullname = catstr(bf->varinfo.prefix, bf->fullname);
1242 }
1243
1244 static void prepdelem(struct rnndb *db, struct rnndelem *elem, char *prefix, struct rnnvarinfo *parvi, int width) {
1245 if (elem->type == RNN_ETYPE_USE_GROUP) {
1246 int i;
1247 struct rnngroup *gr = 0;
1248 for (i = 0; i < db->groupsnum; i++)
1249 if (!strcmp(db->groups[i]->name, elem->name)) {
1250 gr = db->groups[i];
1251 break;
1252 }
1253 if (gr) {
1254 for (i = 0; i < gr->subelemsnum; i++)
1255 ADDARRAY(elem->subelems, copydelem(gr->subelems[i], elem->file));
1256 } else {
1257 rnn_err(db, "group %s not found!\n", elem->name);
1258 }
1259 elem->type = RNN_ETYPE_STRIPE;
1260 elem->length = 1;
1261 elem->name = 0;
1262 }
1263 if (elem->name)
1264 elem->fullname = catstr(prefix, elem->name);
1265 prepvarinfo (db, elem->fullname?elem->fullname:prefix, &elem->varinfo, parvi);
1266 if (elem->varinfo.dead)
1267 return;
1268 if (elem->length != 1 && !elem->stride) {
1269 if (elem->type != RNN_ETYPE_REG) {
1270 rnn_err(db, "%s has non-1 length, but no stride!\n", elem->fullname);
1271 } else {
1272 elem->stride = elem->width/width;
1273 }
1274 }
1275 preptypeinfo(db, &elem->typeinfo, elem->name?elem->fullname:prefix, &elem->varinfo, elem->file);
1276
1277 int i;
1278 for (i = 0; i < elem->subelemsnum; i++)
1279 prepdelem(db, elem->subelems[i], elem->name?elem->fullname:prefix, &elem->varinfo, width);
1280 if (elem->varinfo.prefix && elem->name)
1281 elem->fullname = catstr(elem->varinfo.prefix, elem->fullname);
1282 }
1283
1284 static void prepdomain(struct rnndb *db, struct rnndomain *dom) {
1285 prepvarinfo (db, dom->name, &dom->varinfo, 0);
1286 int i;
1287 for (i = 0; i < dom->subelemsnum; i++)
1288 prepdelem(db, dom->subelems[i], dom->bare?0:dom->name, &dom->varinfo, dom->width);
1289 dom->fullname = catstr(dom->varinfo.prefix, dom->name);
1290 }
1291
1292 static void prepenum(struct rnndb *db, struct rnnenum *en) {
1293 if (en->prepared)
1294 return;
1295 prepvarinfo (db, en->name, &en->varinfo, 0);
1296 int i;
1297 if (en->isinline)
1298 return;
1299 for (i = 0; i < en->valsnum; i++)
1300 prepvalue(db, en->vals[i], en->bare?0:en->name, &en->varinfo);
1301 en->fullname = catstr(en->varinfo.prefix, en->name);
1302 en->prepared = 1;
1303 }
1304
1305 static void prepbitset(struct rnndb *db, struct rnnbitset *bs) {
1306 prepvarinfo (db, bs->name, &bs->varinfo, 0);
1307 int i;
1308 if (bs->isinline)
1309 return;
1310 for (i = 0; i < bs->bitfieldsnum; i++)
1311 prepbitfield(db, bs->bitfields[i], bs->bare?0:bs->name, &bs->varinfo);
1312 bs->fullname = catstr(bs->varinfo.prefix, bs->name);
1313 }
1314
1315 static void prepspectype(struct rnndb *db, struct rnnspectype *st) {
1316 preptypeinfo(db, &st->typeinfo, st->name, 0, st->file); // XXX doesn't exactly make sense...
1317 }
1318
1319 void rnn_prepdb (struct rnndb *db) {
1320 int i;
1321 for (i = 0; i < db->enumsnum; i++)
1322 prepenum(db, db->enums[i]);
1323 for (i = 0; i < db->bitsetsnum; i++)
1324 prepbitset(db, db->bitsets[i]);
1325 for (i = 0; i < db->domainsnum; i++)
1326 prepdomain(db, db->domains[i]);
1327 for (i = 0; i < db->spectypesnum; i++)
1328 prepspectype(db, db->spectypes[i]);
1329 }
1330
1331 struct rnnenum *rnn_findenum (struct rnndb *db, const char *name) {
1332 int i;
1333 for (i = 0; i < db->enumsnum; i++)
1334 if (!strcmp(db->enums[i]->name, name))
1335 return db->enums[i];
1336 return 0;
1337 }
1338
1339 struct rnnbitset *rnn_findbitset (struct rnndb *db, const char *name) {
1340 int i;
1341 for (i = 0; i < db->bitsetsnum; i++)
1342 if (!strcmp(db->bitsets[i]->name, name))
1343 return db->bitsets[i];
1344 return 0;
1345 }
1346
1347 struct rnndomain *rnn_finddomain (struct rnndb *db, const char *name) {
1348 int i;
1349 for (i = 0; i < db->domainsnum; i++)
1350 if (!strcmp(db->domains[i]->name, name))
1351 return db->domains[i];
1352 return 0;
1353 }
1354
1355 struct rnnspectype *rnn_findspectype (struct rnndb *db, const char *name) {
1356 int i;
1357 for (i = 0; i < db->spectypesnum; i++)
1358 if (!strcmp(db->spectypes[i]->name, name))
1359 return db->spectypes[i];
1360 return 0;
1361 }