* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
#pragma ident "@(#)aslex.l 1.2 07/02/12 SMI"
#include <sys/param.h> /* for MAXPATHLEN */
#include <string.h> /* for strchr & strdup */
#include <ctype.h> /* for islower / toupper */
bool_t flag_debug = false;
#define UOP(_t, _size) { yylval.ldst.wordsize=(_size); yylval.ldst.signext=false; return (_t); }
#define SOP(_t, _size) { yylval.ldst.wordsize=(_size); yylval.ldst.signext=true; return (_t); }
void validate_op(token_t tok, ldst_t *ldstinfop, char *namep);
DBG(printf("comment: %s\n", yytext););
DBG(printf("directive: %s\n", yytext););
DBG(printf("comment begin\n"););
DBG(printf("comment end\n"););
DBG(printf("string begin\n"););
DBG(printf("string end\n"););
yylval.namep = NULL; /* dont care for now */
<string>"\\\"" { /* escaped quote is part of string */ }
<string>[^\"]* { /* swallow for now */ }
yyloc.last_line = ++yy_line_num;
"ldsb" { SOP(T_load, 1); }
"ldub" { UOP(T_load, 1); }
"ldsh" { SOP(T_load, 2); }
"lduh" { UOP(T_load, 2); }
"ldsw" { SOP(T_load, 4); }
"lduw" { UOP(T_load, 4); }
"ldn" { UOP(T_load, 8); }
"ldx" { UOP(T_load, 8); }
"ldd" { UOP(T_load, 16); }
"stb" { UOP(T_store, 1); }
"sth" { UOP(T_store, 2); }
"stw" { UOP(T_store, 4); }
"stx" { UOP(T_store, 8); }
"stn" { UOP(T_store, 8); }
"std" { UOP(T_store, 16); }
yylval.namep = strdup(yytext);
yylval.namep = strdup(yytext);
([A-Za-z])([A-Za-z0-9_])* {
yylval.namep = strdup(yytext);
"0x"([1-9A-Fa-f])([0-9A-Fa-f])* {
val = strtoull(yytext, NULL, 16);
val = strtoull(yytext, NULL, 10);
([ \t])+ { /* swallow */ }
fprintf(stderr,"error @ line %d: %s\n",
static char *tok_to_str(int tok)
#define T(_t) case _t : s = #_t; break;
DBG( printf("Line %d : token %d : %s",
yyloc.first_line, tok, tok_to_str(tok));
case T_eof: printf("END OF FILE"); break;
case T_name: printf(" : %s", yylval.namep); break;
case T_labeldef: printf(" : %s", yylval.namep); break;
case T_register: printf(" : %s", yylval.namep); break;
case T_number: printf(" : 0x%llx", yylval.val); break;
case T_load: printf(" : %s : bytes=%d",
yylval.ldst.signext ? "s" : "u", yylval.ldst.wordsize);
void free_yyval(token_t tok)
* Ultra simple parser to pull out only load or store instructions
* that fit a very basic template.
token_t tok, ldsttok, tok_left, tok_right;
char *tok_left_ptr, *tok_right_ptr;
while ((tok = get_token())!=T_eof) {
DBG( printf("Start line with token %d\n", tok); );
* Look for a load or store at the beginning of a line.
* if not found - swallow the line and move to the next.
* A line may also be allowed to have an initial label def.
if (tok == T_nl) continue;
DBG( printf("look for memop %d\n", tok); );
if (tok != T_load && tok != T_store) goto swallow;
if (tok == T_store) goto handle_store;
DBG( printf("Handle load\n"); );
if (tok != '[') goto swallow;
if (tok != T_register && tok != T_name && tok != T_number) goto swallow;
tok_left_ptr = yylval.namep;
/* only want a + b forms */
if (tok != '+') goto cleanup;
if (tok != T_register && tok != T_name && tok != T_number) goto cleanup;
tok_right_ptr = yylval.namep;
if (tok != ']') goto cleanup;
DBG( printf("Load accepted\n"); );
DBG( printf("Handle store\n"););
if (tok != T_register) goto swallow;
if (tok != ',') goto swallow;
if (tok != '[') goto swallow;
if (tok != T_register && tok != T_name && tok != T_number) goto swallow;
tok_left_ptr = yylval.namep;
/* only want a + b forms */
if (tok != '+') goto cleanup;
if (tok != T_register && tok != T_name && tok != T_number) goto cleanup;
tok_right_ptr = yylval.namep;
if (tok != ']') goto cleanup;
DBG( printf("Store accepted\n"); );
* Finally the check we care about ...
* The load/store operands can be given in any order -
* register + offset or offset + register ... so to make things easier
* if we find one form we swap the paramaters to give us the other.
/* one side must have a name for us to check */
if (tok_left != T_name && tok_right != T_name) goto cleanup;
* if both sides are a name - we bail since there is likely more than one type
* for us to have to sanity check .. i.e. %g3 + BASE_OFSET + FOOBAR
if (tok_left == T_name && tok_right == T_name) goto cleanup;
/* now for the switch over */
if (tok_left == T_name) {
tok_left_ptr = tok_right_ptr;
/* finally something we can validate ... */
DBG( printf("Validation of name %s\n", tok_right_ptr); );
validate_op(ldsttok, &ldstinfo, tok_right_ptr);
if (tok_left == T_name || tok_left == T_register) {
if (tok_left == T_name || tok_left == T_register) {
if (tok!=T_nl) goto swallow_loop;
void validate_op(token_t ldsttok, ldst_t *ldstinfop, char *namep)
if (!flag_suppress_unknowns) {
fprintf(stderr,"%s:%d : Warning: unknown symbol \'%s\' for memop\n",
yyloc.fnamep, yyloc.first_line, namep);
if (symp->size != ldstinfop->wordsize) {
fprintf(stderr,"%s:%d : Warning: access size mismatch using symbol \'%s\'\n",
yyloc.fnamep, yyloc.first_line, namep);
fprintf(stderr,"\tAccess uses %d byte memop, but should be a %d byte memop\n",
ldstinfop->wordsize, symp->size);
/* if its a load compare sign extension */
if (ldstinfop->signext && ((symp->flags & Sym_unsigned)!=0)) {
fprintf(stderr,"%s:%d : Warning: sign extension mismatch for symbol \'%s\'\n",
yyloc.fnamep, yyloc.first_line, namep);
fprintf(stderr,"\tAccess uses signed memop, but should be unsigned\n");
if (!ldstinfop->signext && ((symp->flags & Sym_signed)!=0)) {
fprintf(stderr,"%s:%d : Warning: sign extension mismatch for symbol \'%s\'\n",
yyloc.fnamep, yyloc.first_line, namep);
fprintf(stderr,"\tAccess uses unsigned memop, but should be signed\n");