Add support for preserved registers.
This commit is contained in:
parent
e3ebf986e9
commit
a311e61360
|
@ -617,12 +617,14 @@ PATTERNS
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
out:(int)reg = MOD.I(left:(int)reg, right:(int)reg)
|
out:(int)reg = MOD.I(left:(int)reg, right:(int)reg)
|
||||||
|
with preserved(%left), preserved(%right)
|
||||||
emit "divw %out, %left, %right"
|
emit "divw %out, %left, %right"
|
||||||
emit "mullw %out, %out, %right"
|
emit "mullw %out, %out, %right"
|
||||||
emit "subf %out, %out, %left"
|
emit "subf %out, %out, %left"
|
||||||
cost 12;
|
cost 12;
|
||||||
|
|
||||||
out:(int)reg = MODU.I(left:(int)reg, right:(int)reg)
|
out:(int)reg = MODU.I(left:(int)reg, right:(int)reg)
|
||||||
|
with preserved(%left), preserved(%right)
|
||||||
emit "divwu %out, %left, %right"
|
emit "divwu %out, %left, %right"
|
||||||
emit "mullw %out, %out, %right"
|
emit "mullw %out, %out, %right"
|
||||||
emit "subf %out, %out, %left"
|
emit "subf %out, %out, %left"
|
||||||
|
|
|
@ -31,6 +31,7 @@ struct insel
|
||||||
struct constraint
|
struct constraint
|
||||||
{
|
{
|
||||||
uint32_t attrs;
|
uint32_t attrs;
|
||||||
|
bool preserved;
|
||||||
struct vreg* equals_to;
|
struct vreg* equals_to;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,16 @@ static void constrain_input_reg(int child, uint32_t attr)
|
||||||
get_constraint(vreg)->attrs = 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(¤t_hop->throughs, vreg);
|
||||||
|
get_constraint(vreg)->preserved = true;
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t find_type_from_constraint(uint32_t attr)
|
static uint32_t find_type_from_constraint(uint32_t attr)
|
||||||
{
|
{
|
||||||
/* Looks through the registers and finds a concrete register implementing
|
/* 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_value,
|
||||||
&emit_eoi,
|
&emit_eoi,
|
||||||
&constrain_input_reg,
|
&constrain_input_reg,
|
||||||
|
&constrain_input_reg_preserved,
|
||||||
&constrain_output_reg,
|
&constrain_output_reg,
|
||||||
&constrain_output_reg_equal_to,
|
&constrain_output_reg_equal_to,
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,6 +38,7 @@ extern int yylex(void);
|
||||||
%term NOTEQUALS
|
%term NOTEQUALS
|
||||||
%term PATTERNS
|
%term PATTERNS
|
||||||
%term PREFERS
|
%term PREFERS
|
||||||
|
%term PRESERVED
|
||||||
%term REGISTERS
|
%term REGISTERS
|
||||||
%term WHEN
|
%term WHEN
|
||||||
%term WITH
|
%term WITH
|
||||||
|
@ -170,6 +171,8 @@ constraint
|
||||||
$$->type = CONSTRAINT_EQUALS; $$->left = $2; $$->right = $5; }
|
$$->type = CONSTRAINT_EQUALS; $$->left = $2; $$->right = $5; }
|
||||||
| CORRUPTED '(' ID ')' { $$ = calloc(1, sizeof(*$$));
|
| CORRUPTED '(' ID ')' { $$ = calloc(1, sizeof(*$$));
|
||||||
$$->type = CONSTRAINT_CORRUPTED_ATTR; $$->left = $3; }
|
$$->type = CONSTRAINT_CORRUPTED_ATTR; $$->left = $3; }
|
||||||
|
| PRESERVED '(' '%' ID ')' { $$ = calloc(1, sizeof(*$$));
|
||||||
|
$$->type = CONSTRAINT_PRESERVED; $$->left = $4; }
|
||||||
;
|
;
|
||||||
|
|
||||||
qfragments
|
qfragments
|
||||||
|
|
|
@ -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 */
|
/* emitinsndata - emit the code generation data */
|
||||||
static void emitinsndata(Rule rules)
|
static void emitinsndata(Rule rules)
|
||||||
{
|
{
|
||||||
|
@ -1234,6 +1256,7 @@ static void emitinsndata(Rule rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_output_constraints(r);
|
emit_output_constraints(r);
|
||||||
|
emit_input_constraints(r);
|
||||||
|
|
||||||
while (f)
|
while (f)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,6 +21,7 @@ enum
|
||||||
{
|
{
|
||||||
CONSTRAINT_EQUALS,
|
CONSTRAINT_EQUALS,
|
||||||
CONSTRAINT_CORRUPTED_ATTR,
|
CONSTRAINT_CORRUPTED_ATTR,
|
||||||
|
CONSTRAINT_PRESERVED,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct constraint
|
struct constraint
|
||||||
|
|
|
@ -45,6 +45,7 @@ struct burm_emitter_data
|
||||||
void (*emit_value)(int child);
|
void (*emit_value)(int child);
|
||||||
void (*emit_eoi)(void);
|
void (*emit_eoi)(void);
|
||||||
void (*constrain_input_reg)(int child, uint32_t attr);
|
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)(uint32_t attr);
|
||||||
void (*constrain_output_reg_equal_to)(int child);
|
void (*constrain_output_reg_equal_to)(int child);
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,6 +46,7 @@ static int braces = 0;
|
||||||
"fragment" return FRAGMENT;
|
"fragment" return FRAGMENT;
|
||||||
"named" return NAMED;
|
"named" return NAMED;
|
||||||
"prefers" return PREFERS;
|
"prefers" return PREFERS;
|
||||||
|
"preserved" return PRESERVED;
|
||||||
"when" return WHEN;
|
"when" return WHEN;
|
||||||
"with" return WITH;
|
"with" return WITH;
|
||||||
"==" return EQUALS;
|
"==" return EQUALS;
|
||||||
|
|
Loading…
Reference in a new issue