Add support for preserved registers.

This commit is contained in:
David Given 2016-10-29 20:22:44 +02:00
parent e3ebf986e9
commit a311e61360
8 changed files with 43 additions and 0 deletions

View file

@ -617,12 +617,14 @@ PATTERNS
cost 4;
out:(int)reg = MOD.I(left:(int)reg, right:(int)reg)
with preserved(%left), preserved(%right)
emit "divw %out, %left, %right"
emit "mullw %out, %out, %right"
emit "subf %out, %out, %left"
cost 12;
out:(int)reg = MODU.I(left:(int)reg, right:(int)reg)
with preserved(%left), preserved(%right)
emit "divwu %out, %left, %right"
emit "mullw %out, %out, %right"
emit "subf %out, %out, %left"

View file

@ -31,6 +31,7 @@ struct insel
struct constraint
{
uint32_t attrs;
bool preserved;
struct vreg* equals_to;
};

View file

@ -100,6 +100,16 @@ static void constrain_input_reg(int child, uint32_t attr)
get_constraint(vreg)->attrs = attr;
}
static void constrain_input_reg_preserved(int child)
{
struct vreg* vreg = find_vreg_of_child(child);
struct constraint* c;
assert(vreg);
array_appendu(&current_hop->throughs, vreg);
get_constraint(vreg)->preserved = true;
}
static uint32_t find_type_from_constraint(uint32_t attr)
{
/* Looks through the registers and finds a concrete register implementing
@ -158,6 +168,7 @@ static const struct burm_emitter_data emitter_data =
&emit_value,
&emit_eoi,
&constrain_input_reg,
&constrain_input_reg_preserved,
&constrain_output_reg,
&constrain_output_reg_equal_to,
};

View file

@ -38,6 +38,7 @@ extern int yylex(void);
%term NOTEQUALS
%term PATTERNS
%term PREFERS
%term PRESERVED
%term REGISTERS
%term WHEN
%term WITH
@ -170,6 +171,8 @@ constraint
$$->type = CONSTRAINT_EQUALS; $$->left = $2; $$->right = $5; }
| CORRUPTED '(' ID ')' { $$ = calloc(1, sizeof(*$$));
$$->type = CONSTRAINT_CORRUPTED_ATTR; $$->left = $3; }
| PRESERVED '(' '%' ID ')' { $$ = calloc(1, sizeof(*$$));
$$->type = CONSTRAINT_PRESERVED; $$->left = $4; }
;
qfragments

View file

@ -1199,6 +1199,28 @@ static void emit_output_constraints(Rule r)
}
}
static void emit_input_constraints(Rule r)
{
int i;
for (i=0; i<r->constraints.count; i++)
{
int index;
struct constraint* c = r->constraints.item[i];
if (c->type == CONSTRAINT_PRESERVED)
{
if (strcmp(c->left, r->label) == 0)
yyerror("cannot preserve an output register!");
index = 0;
if (!find_child_index(r->pattern, c->left, &index, NULL))
label_not_found(r, c->left);
print("%1data->constrain_input_reg_preserved(%d);\n", index);
}
}
}
/* emitinsndata - emit the code generation data */
static void emitinsndata(Rule rules)
{
@ -1234,6 +1256,7 @@ static void emitinsndata(Rule rules)
}
emit_output_constraints(r);
emit_input_constraints(r);
while (f)
{

View file

@ -21,6 +21,7 @@ enum
{
CONSTRAINT_EQUALS,
CONSTRAINT_CORRUPTED_ATTR,
CONSTRAINT_PRESERVED,
};
struct constraint

View file

@ -45,6 +45,7 @@ struct burm_emitter_data
void (*emit_value)(int child);
void (*emit_eoi)(void);
void (*constrain_input_reg)(int child, uint32_t attr);
void (*constrain_input_reg_preserved)(int child);
void (*constrain_output_reg)(uint32_t attr);
void (*constrain_output_reg_equal_to)(int child);
};

View file

@ -46,6 +46,7 @@ static int braces = 0;
"fragment" return FRAGMENT;
"named" return NAMED;
"prefers" return PREFERS;
"preserved" return PRESERVED;
"when" return WHEN;
"with" return WITH;
"==" return EQUALS;