Add parsing support for register aliases.

This commit is contained in:
David Given 2016-10-20 21:47:28 +02:00
parent e4fec71f9c
commit d6984d60ac
5 changed files with 59 additions and 8 deletions

View file

@ -25,6 +25,7 @@ extern int yylex(void);
struct constraint* constraint;
}
%term ALIASES
%term COPY
%term CORRUPTED
%term COST
@ -43,6 +44,7 @@ extern int yylex(void);
%token <string> ID
%token <string> QFRAGMENT
%type <stringlist> aliases;
%type <constraint> constraint
%type <constraint> constraints
%type <expr> predicate
@ -72,10 +74,16 @@ registers
register
: ID QFRAGMENT { $$ = makereg($1, $2); }
| register ALIASES '(' aliases ')' { $$ = $1; addregaliases($$, $4); }
| register ID { $$ = $1; addregattr($1, $2, false); }
| register ID '!' { $$ = $1; addregattr($1, $2, true); }
;
aliases
: ID { $$ = calloc(1, sizeof(*$$)); stringlist_add($$, $1); }
| aliases ',' ID { $$ = $1; stringlist_add($$, $3); }
;
declarations
: /* nothing */
| declarations declaration ';'

View file

@ -279,6 +279,7 @@ struct reg* makereg(const char* id, const char* realname)
p->name = id;
p->realname = realname;
p->number = number++;
array_append(&p->aliases, p);
smap_put(&registers, id, p);
return p;
@ -311,6 +312,34 @@ void addregattr(struct reg* reg, const char* id, bool exact)
reg->type |= 1<<(p->number);
}
void addregalias(struct reg* r1, struct reg* r2)
{
if (!array_appendu(&r1->aliases, r2))
{
int i;
for (i=0; i<r1->aliases.count; i++)
addregalias(r1->aliases.item[i], r2);
}
}
void addregaliases(struct reg* reg, struct stringlist* aliases)
{
struct stringfragment* f = aliases->first;
while (f)
{
struct reg* r = smap_get(&registers, f->data);
if (!r)
yyerror("register '%s' is not defined here", f->data);
array_appendu(&reg->aliases, r);
array_appendu(&r->aliases, reg);
f = f->next;
}
}
struct regattr* getregattr(const char* id)
{
struct regattr* p = smap_get(&registerattrs, id);
@ -588,7 +617,17 @@ static void emitregisterattrs(void)
static void emitregisters(void)
{
int i;
int i, j;
for (i=0; i<registers.count; i++)
{
struct reg* r = registers.item[i].right;
print("const struct %Pregister_data* %Pregister_aliases_%d_%s[] = {\n%1", i, r->name);
for (j=0; j<r->aliases.count; j++)
print("&%Pregister_data[%d], ", r->aliases.item[j]->number);
print("NULL\n};\n");
}
print("const struct %Pregister_data %Pregister_data[] = {\n");
for (i=0; i<registers.count; i++)
@ -596,8 +635,8 @@ static void emitregisters(void)
struct reg* r = registers.item[i].right;
assert(r->number == i);
print("%1{ \"%s\", \"%s\", 0x%x, 0x%x },\n",
r->name, r->realname, r->type, r->attrs);
print("%1{ \"%s\", \"%s\", 0x%x, 0x%x, %Pregister_aliases_%d_%s },\n",
r->name, r->realname, r->type, r->attrs, i, r->name);
}
print("%1{ NULL }\n");
print("};\n\n");

View file

@ -58,11 +58,12 @@ struct terminfo
struct reg
{
const char* name; /* friendly register name */
const char* realname; /* name used in assembly output */
int number; /* identifying number */
uint32_t attrs; /* bitfield of register attributes */
uint32_t type; /* register type */
const char* name; /* friendly register name */
const char* realname; /* name used in assembly output */
int number; /* identifying number */
uint32_t attrs; /* bitfield of register attributes */
uint32_t type; /* register type */
ARRAYOF(struct reg) aliases; /* registers that this one aliases */
};
struct regattr
@ -73,6 +74,7 @@ struct regattr
extern struct reg* makereg(const char* name, const char* realname);
extern void addregattr(struct reg* reg, const char* regattr, bool exact);
extern void addregaliases(struct reg* reg, struct stringlist* aliases);
extern struct regattr* getregattr(const char* name);
struct term

View file

@ -67,6 +67,7 @@ struct burm_register_data
const char* realname;
uint32_t type;
uint32_t attrs;
const struct burm_register_data** aliases;
};
extern const struct burm_register_data burm_register_data[];

View file

@ -39,6 +39,7 @@ static int braces = 0;
"DECLARATIONS" return DECLARATIONS;
"PATTERNS" return PATTERNS;
"REGISTERS" return REGISTERS;
"aliases" return ALIASES;
"corrupted" return CORRUPTED;
"cost" return COST;
"emit" return EMIT;