Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / support / aschk / aslex.l
CommitLineData
920dae64
AT
1/*
2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6%{
7
8#pragma ident "@(#)aslex.l 1.2 07/02/12 SMI"
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <unistd.h>
13#include <stdarg.h>
14#include <errno.h>
15#include <sys/param.h> /* for MAXPATHLEN */
16#include <string.h> /* for strchr & strdup */
17#include <ctype.h> /* for islower / toupper */
18
19#include <assert.h>
20
21#include "basics.h"
22#include "internal.h"
23#include "parser.h"
24
25
26int yywrap();
27
28bool_t flag_debug = false;
29
30YYLTYPE yyloc;
31yylval_t yylval;
32
33int yy_line_num;
34
35#define UOP(_t, _size) { yylval.ldst.wordsize=(_size); yylval.ldst.signext=false; return (_t); }
36#define SOP(_t, _size) { yylval.ldst.wordsize=(_size); yylval.ldst.signext=true; return (_t); }
37
38void validate_op(token_t tok, ldst_t *ldstinfop, char *namep);
39
40%}
41
42%x comment
43%x string
44
45%%
46
47<<EOF>> {
48 return T_eof;
49 }
50
51"!"([^\n])*$ {
52 DBG(printf("comment: %s\n", yytext););
53 }
54
55^"#"([^\n])*$ {
56 DBG(printf("directive: %s\n", yytext););
57 }
58
59"/*" {
60 BEGIN(comment);
61 DBG(printf("comment begin\n"););
62 }
63
64<comment>\n {
65 yy_line_num++;
66 }
67
68<comment>. /* swallow */
69
70<comment>"*/" {
71 BEGIN(INITIAL);
72 DBG(printf("comment end\n"););
73 }
74
75"\"" {
76 BEGIN(string);
77 DBG(printf("string begin\n"););
78 }
79
80<string>"\"" {
81 BEGIN(INITIAL);
82 DBG(printf("string end\n"););
83 yylval.namep = NULL; /* dont care for now */
84 return T_string;
85 }
86
87<string>\n {
88 yy_line_num++;
89 }
90
91<string>"\\\"" { /* escaped quote is part of string */ }
92
93<string>[^\"]* { /* swallow for now */ }
94
95
96"\n" {
97 yyloc.first_line =
98 yyloc.last_line = ++yy_line_num;
99 return T_nl;
100 }
101
102"ldsb" { SOP(T_load, 1); }
103
104"ldub" { UOP(T_load, 1); }
105
106"ldsh" { SOP(T_load, 2); }
107
108"lduh" { UOP(T_load, 2); }
109
110"ldsw" { SOP(T_load, 4); }
111
112"lduw" { UOP(T_load, 4); }
113
114"ldn" { UOP(T_load, 8); }
115
116"ldx" { UOP(T_load, 8); }
117
118"ldd" { UOP(T_load, 16); }
119
120"stb" { UOP(T_store, 1); }
121
122"sth" { UOP(T_store, 2); }
123
124"stw" { UOP(T_store, 4); }
125
126"stx" { UOP(T_store, 8); }
127
128"stn" { UOP(T_store, 8); }
129
130"std" { UOP(T_store, 16); }
131
132^"."?[A-Za-z0-9_]+":" {
133 yylval.namep = strdup(yytext);
134 return T_labeldef;
135 }
136
137"%"([a-z]+)([0-9]*) {
138 yylval.namep = strdup(yytext);
139 return T_register;
140 }
141
142([A-Za-z])([A-Za-z0-9_])* {
143 yylval.namep = strdup(yytext);
144 return T_name;
145 }
146
147"0x"([1-9A-Fa-f])([0-9A-Fa-f])* {
148 uint64_t val;
149 val = strtoull(yytext, NULL, 16);
150 yylval.val = val;
151 return T_number;
152 }
153
154"0x0" {
155 yylval.val = 0;
156 return T_number;
157 }
158
159([1-9])([0-9])* {
160 uint64_t val;
161 val = strtoull(yytext, NULL, 10);
162 yylval.val = val;
163 return T_number;
164 }
165
166
167([ \t])+ { /* swallow */ }
168
169. return yytext[0] ;
170
171%%
172
173
174
175
176
177
178int yywrap()
179{
180 return 1;
181}
182
183
184void yyerror(char *strp)
185{
186 fprintf(stderr,"error @ line %d: %s\n",
187 yyloc.first_line,
188 strp);
189 exit(1);
190}
191
192
193static char *tok_to_str(int tok)
194{
195 static char buf[2];
196 char * s;
197
198 if (tok<256) {
199 buf[0]=tok;
200 buf[1]='\0';
201 return (char*)buf;
202 }
203#define T(_t) case _t : s = #_t; break;
204 switch(tok) {
205 T(T_nl);
206 T(T_name);
207 T(T_labeldef);
208 T(T_register);
209 T(T_number);
210 T(T_string);
211 T(T_load);
212 T(T_store);
213 T(T_cas);
214 default: s = "unknown";
215 }
216#undef T
217 return s;
218}
219
220token_t get_token()
221{
222 token_t tok;
223
224 tok = yylex();
225
226DBG( printf("Line %d : token %d : %s",
227 yyloc.first_line, tok, tok_to_str(tok));
228 switch(tok) {
229 case T_eof: printf("END OF FILE"); break;
230 case T_name: printf(" : %s", yylval.namep); break;
231 case T_labeldef: printf(" : %s", yylval.namep); break;
232 case T_register: printf(" : %s", yylval.namep); break;
233 case T_number: printf(" : 0x%llx", yylval.val); break;
234 case T_cas:
235 case T_store:
236 case T_load: printf(" : %s : bytes=%d",
237 yylval.ldst.signext ? "s" : "u", yylval.ldst.wordsize);
238 break;
239 default:
240 break;
241 }
242 printf("\n");
243 );
244
245 return tok;
246}
247
248
249void free_yyval(token_t tok)
250{
251 switch (tok) {
252 case T_name:
253 case T_labeldef:
254 case T_register:
255 free(yylval.namep);
256 yylval.namep = NULL;
257 break;
258 default:
259 break;
260 }
261}
262
263
264 /*
265 * Ultra simple parser to pull out only load or store instructions
266 * that fit a very basic template.
267 */
268
269void lex_only()
270{
271 token_t tok, ldsttok, tok_left, tok_right;
272 char *tok_left_ptr, *tok_right_ptr;
273 ldst_t ldstinfo;
274
275 while ((tok = get_token())!=T_eof) {
276DBG( printf("Start line with token %d\n", tok); );
277 if (tok == T_nl) {
278 continue;
279 }
280
281 /*
282 * Look for a load or store at the beginning of a line.
283 * if not found - swallow the line and move to the next.
284 * A line may also be allowed to have an initial label def.
285 */
286 if (tok == T_labeldef) {
287 free_yyval(tok);
288 tok = get_token();
289 if (tok==T_eof) break;
290 if (tok == T_nl) continue;
291 }
292
293DBG( printf("look for memop %d\n", tok); );
294
295 tok_left = -1;
296 tok_right = -1;
297 tok_left_ptr = NULL;
298 tok_right_ptr = NULL;
299
300 if (tok != T_load && tok != T_store) goto swallow;
301
302 ldsttok = tok;
303 ldstinfo = yylval.ldst;
304
305 if (tok == T_store) goto handle_store;
306DBG( printf("Handle load\n"); );
307
308 tok = get_token();
309 if (tok != '[') goto swallow;
310
311 tok = get_token();
312 if (tok != T_register && tok != T_name && tok != T_number) goto swallow;
313 tok_left = tok;
314 tok_left_ptr = yylval.namep;
315
316 /* only want a + b forms */
317 tok = get_token();
318 if (tok != '+') goto cleanup;
319
320 tok = get_token();
321 if (tok != T_register && tok != T_name && tok != T_number) goto cleanup;
322 tok_right = tok;
323 tok_right_ptr = yylval.namep;
324
325 tok = get_token();
326 if (tok != ']') goto cleanup;
327
328DBG( printf("Load accepted\n"); );
329
330 goto sanity_check;
331
332
333
334
335handle_store:;
336DBG( printf("Handle store\n"););
337
338 tok = get_token();
339 if (tok != T_register) goto swallow;
340
341 tok = get_token();
342 if (tok != ',') goto swallow;
343
344 tok = get_token();
345 if (tok != '[') goto swallow;
346
347 tok = get_token();
348 if (tok != T_register && tok != T_name && tok != T_number) goto swallow;
349 tok_left = tok;
350 tok_left_ptr = yylval.namep;
351
352 /* only want a + b forms */
353 tok = get_token();
354 if (tok != '+') goto cleanup;
355
356 tok = get_token();
357 if (tok != T_register && tok != T_name && tok != T_number) goto cleanup;
358 tok_right = tok;
359 tok_right_ptr = yylval.namep;
360
361 tok = get_token();
362 if (tok != ']') goto cleanup;
363
364DBG( printf("Store accepted\n"); );
365
366 goto sanity_check;
367
368
369
370 /*
371 * Finally the check we care about ...
372 */
373
374sanity_check:;
375 /*
376 * The load/store operands can be given in any order -
377 * register + offset or offset + register ... so to make things easier
378 * if we find one form we swap the paramaters to give us the other.
379 */
380
381 /* one side must have a name for us to check */
382
383 if (tok_left != T_name && tok_right != T_name) goto cleanup;
384
385 /*
386 * if both sides are a name - we bail since there is likely more than one type
387 * for us to have to sanity check .. i.e. %g3 + BASE_OFSET + FOOBAR
388 */
389 if (tok_left == T_name && tok_right == T_name) goto cleanup;
390
391 /* now for the switch over */
392
393 if (tok_left == T_name) {
394 token_t temptok;
395 char *tempptr;
396
397 temptok = tok_left;
398 tempptr = tok_left_ptr;
399 tok_left = tok_right;
400 tok_left_ptr = tok_right_ptr;
401 tok_right = temptok;
402 tok_right_ptr = tempptr;
403 }
404
405 /* finally something we can validate ... */
406
407DBG( printf("Validation of name %s\n", tok_right_ptr); );
408
409 validate_op(ldsttok, &ldstinfo, tok_right_ptr);
410
411 goto cleanup;
412
413
414cleanup:;
415 if (tok_left == T_name || tok_left == T_register) {
416 free(tok_left_ptr);
417 }
418 if (tok_left == T_name || tok_left == T_register) {
419 free(tok_left_ptr);
420 }
421 goto swallow;
422
423swallow_loop:;
424 tok = get_token();
425 if (tok==T_eof) break;
426swallow:;
427 free_yyval(tok);
428 if (tok!=T_nl) goto swallow_loop;
429 }
430}
431
432
433
434
435void validate_op(token_t ldsttok, ldst_t *ldstinfop, char *namep)
436{
437 symbol_t *symp;
438
439 symp = hash_find(namep);
440 if (symp == NULL) {
441 if (!flag_suppress_unknowns) {
442 fprintf(stderr,"%s:%d : Warning: unknown symbol \'%s\' for memop\n",
443 yyloc.fnamep, yyloc.first_line, namep);
444 warning_count++;
445 }
446 return;
447 }
448
449 /* Compare sizes */
450 if (symp->size != ldstinfop->wordsize) {
451 fprintf(stderr,"%s:%d : Warning: access size mismatch using symbol \'%s\'\n",
452 yyloc.fnamep, yyloc.first_line, namep);
453 fprintf(stderr,"\tAccess uses %d byte memop, but should be a %d byte memop\n",
454 ldstinfop->wordsize, symp->size);
455 warning_count++;
456 }
457
458 /* if its a load compare sign extension */
459
460 if (ldsttok == T_load) {
461 if (ldstinfop->signext && ((symp->flags & Sym_unsigned)!=0)) {
462 fprintf(stderr,"%s:%d : Warning: sign extension mismatch for symbol \'%s\'\n",
463 yyloc.fnamep, yyloc.first_line, namep);
464 fprintf(stderr,"\tAccess uses signed memop, but should be unsigned\n");
465 warning_count++;
466 } else
467 if (!ldstinfop->signext && ((symp->flags & Sym_signed)!=0)) {
468 fprintf(stderr,"%s:%d : Warning: sign extension mismatch for symbol \'%s\'\n",
469 yyloc.fnamep, yyloc.first_line, namep);
470 fprintf(stderr,"\tAccess uses unsigned memop, but should be signed\n");
471 warning_count++;
472 }
473 }
474}