diff --git a/mach/powerpc/mcg/table b/mach/powerpc/mcg/table index 3be30c306..7023c08b6 100644 --- a/mach/powerpc/mcg/table +++ b/mach/powerpc/mcg/table @@ -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" diff --git a/mach/proto/mcg/hop.h b/mach/proto/mcg/hop.h index 0cc5dc0b1..21c7e9293 100644 --- a/mach/proto/mcg/hop.h +++ b/mach/proto/mcg/hop.h @@ -31,6 +31,7 @@ struct insel struct constraint { uint32_t attrs; + bool preserved; struct vreg* equals_to; }; diff --git a/mach/proto/mcg/pass_instructionselection.c b/mach/proto/mcg/pass_instructionselection.c index 2bf5e5b59..860dad02f 100644 --- a/mach/proto/mcg/pass_instructionselection.c +++ b/mach/proto/mcg/pass_instructionselection.c @@ -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(¤t_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, }; diff --git a/util/mcgg/gram.y b/util/mcgg/gram.y index 99fdeda95..891030a10 100644 --- a/util/mcgg/gram.y +++ b/util/mcgg/gram.y @@ -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 diff --git a/util/mcgg/iburg.c b/util/mcgg/iburg.c index 55a24e717..23705c7d8 100644 --- a/util/mcgg/iburg.c +++ b/util/mcgg/iburg.c @@ -1199,6 +1199,28 @@ static void emit_output_constraints(Rule r) } } +static void emit_input_constraints(Rule r) +{ + int i; + for (i=0; iconstraints.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) { diff --git a/util/mcgg/iburg.h b/util/mcgg/iburg.h index 8ba4f5ab9..739641d4d 100644 --- a/util/mcgg/iburg.h +++ b/util/mcgg/iburg.h @@ -21,6 +21,7 @@ enum { CONSTRAINT_EQUALS, CONSTRAINT_CORRUPTED_ATTR, + CONSTRAINT_PRESERVED, }; struct constraint diff --git a/util/mcgg/mcgg.h b/util/mcgg/mcgg.h index a068fa660..c0c930a27 100644 --- a/util/mcgg/mcgg.h +++ b/util/mcgg/mcgg.h @@ -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); }; diff --git a/util/mcgg/scan.l b/util/mcgg/scan.l index 272dd2bf1..447a7d395 100644 --- a/util/mcgg/scan.l +++ b/util/mcgg/scan.l @@ -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;