Come up with a syntax for register constraints.
This commit is contained in:
parent
c079e97492
commit
3aa30e50d1
|
@ -29,6 +29,9 @@ REGISTERS
|
||||||
|
|
||||||
DECLARATIONS
|
DECLARATIONS
|
||||||
|
|
||||||
|
reg;
|
||||||
|
cc;
|
||||||
|
|
||||||
address fragment;
|
address fragment;
|
||||||
aluparam fragment;
|
aluparam fragment;
|
||||||
|
|
||||||
|
@ -37,88 +40,75 @@ PATTERNS
|
||||||
|
|
||||||
/* Special */
|
/* Special */
|
||||||
|
|
||||||
int;
|
reg;
|
||||||
float;
|
|
||||||
any;
|
|
||||||
|
|
||||||
PAIR(BLOCK4, BLOCK4);
|
PAIR(BLOCK4, BLOCK4);
|
||||||
|
|
||||||
|
|
||||||
/* Miscellaneous special things */
|
/* Miscellaneous special things */
|
||||||
|
|
||||||
PUSH4(in:int)
|
PUSH4(in:reg)
|
||||||
emit "push %in"
|
emit "push %in"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = POP4
|
reg = POP4
|
||||||
emit "pop %int"
|
emit "pop %reg"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
RET
|
RET
|
||||||
emit "ret"
|
emit "ret"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
SETRET4(in:ret)
|
SETRET4(in:reg)
|
||||||
emit "mov r0, %in"
|
with ret reg
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
STACKADJUST4(delta:aluparam)
|
STACKADJUST4(delta:aluparam)
|
||||||
emit "add sp, sp, %delta"
|
emit "add sp, sp, %delta"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = in:REG4
|
reg = in:REG4
|
||||||
prefers int(in)
|
with (reg == in)
|
||||||
cost 1;
|
cost 1;
|
||||||
|
|
||||||
int = NOP4(in:int)
|
reg = NOP4(in:reg)
|
||||||
emit "mov %int, %in"
|
with (reg == in)
|
||||||
cost 1;
|
cost 1;
|
||||||
|
|
||||||
any = PHI4
|
|
||||||
cost 0;
|
|
||||||
|
|
||||||
float = in:REG4
|
|
||||||
prefers float(in)
|
|
||||||
cost 1;
|
|
||||||
|
|
||||||
ret = in:any emit "mov %ret, %in" cost 1;
|
|
||||||
any = in:int emit "mov %any, %in" cost 1;
|
|
||||||
int = in:any emit "mov %int, %in" cost 1;
|
|
||||||
any = in:float emit "mov %any, %in" cost 1;
|
|
||||||
float = in:any emit "mov %float, %in" cost 1;
|
|
||||||
|
|
||||||
|
|
||||||
/* Memory operations */
|
/* Memory operations */
|
||||||
|
|
||||||
STORE4(addr:address, value:int)
|
STORE4(addr:address, value:reg)
|
||||||
|
with int value
|
||||||
emit "str %value, %addr"
|
emit "str %value, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
STORE1(addr:address, value:int)
|
STORE1(addr:address, value:reg)
|
||||||
|
with int value
|
||||||
emit "strb %value, %addr"
|
emit "strb %value, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = LOAD4(addr:address)
|
reg = LOAD4(addr:address)
|
||||||
emit "ldr %int, %addr"
|
emit "ldr %reg, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = LOAD1(addr:address)
|
reg = LOAD1(addr:address)
|
||||||
emit "ldrb %int, %addr"
|
emit "ldrb %reg, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = CIU14(LOAD1(addr:address))
|
reg = CIU14(LOAD1(addr:address))
|
||||||
emit "ldrb %int, %addr"
|
emit "ldrb %reg, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = CII14(CIU41(CIU14(LOAD1(addr:address))))
|
reg = CII14(CIU41(CIU14(LOAD1(addr:address))))
|
||||||
emit "ldrsb %int, %addr"
|
emit "ldrsb %reg, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
|
||||||
/* Locals */
|
/* Locals */
|
||||||
|
|
||||||
int = in:LOCAL4
|
reg = in:LOCAL4
|
||||||
emit "add %int, fp, #$in"
|
emit "add %reg, fp, #$in"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
address = in:LOCAL4
|
address = in:LOCAL4
|
||||||
|
@ -127,13 +117,16 @@ PATTERNS
|
||||||
|
|
||||||
/* Memory addressing modes */
|
/* Memory addressing modes */
|
||||||
|
|
||||||
address = ADD4(addr:int, offset:CONST4)
|
address = ADD4(addr:reg, offset:CONST4)
|
||||||
|
with int addr
|
||||||
emit "[%addr, #$offset]";
|
emit "[%addr, #$offset]";
|
||||||
|
|
||||||
address = ADD4(addr1:int, addr2:int)
|
address = ADD4(addr1:reg, addr2:reg)
|
||||||
|
with int addr1, int addr2
|
||||||
emit "[%addr1, %addr2]";
|
emit "[%addr1, %addr2]";
|
||||||
|
|
||||||
address = addr:int
|
address = addr:reg
|
||||||
|
with int addr
|
||||||
emit "[%addr]";
|
emit "[%addr]";
|
||||||
|
|
||||||
|
|
||||||
|
@ -166,80 +159,80 @@ PATTERNS
|
||||||
|
|
||||||
/* Comparisons */
|
/* Comparisons */
|
||||||
|
|
||||||
cc = COMPARES4(left:int, right:aluparam)
|
cc = COMPARES4(left:reg, right:aluparam)
|
||||||
emit "cmp %left, %right"
|
emit "cmp %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
cc = COMPARES4(COMPARES4(left:int, right:aluparam), CONST4)
|
cc = COMPARES4(COMPARES4(left:reg, right:aluparam), CONST4)
|
||||||
emit "cmp %left, %right"
|
emit "cmp %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = cc
|
reg = cc
|
||||||
emit "mov %int, #0"
|
emit "mov %reg, #0"
|
||||||
emit "movlt %int, #-1"
|
emit "movlt %reg, #-1"
|
||||||
emit "movgt %int, #1"
|
emit "movgt %reg, #1"
|
||||||
cost 12;
|
cost 12;
|
||||||
|
|
||||||
|
|
||||||
/* Conversions */
|
/* Conversions */
|
||||||
|
|
||||||
int = CII14(CIU41(value:int))
|
reg = CII14(CIU41(value:reg))
|
||||||
emit "sxtb %int, %value"
|
emit "sxtb %reg, %value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = CIU41(in:int)
|
reg = CIU41(in:reg)
|
||||||
emit "and %int, %in, #0xff"
|
emit "and %reg, %in, #0xff"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
|
||||||
/* ALU operations */
|
/* ALU operations */
|
||||||
|
|
||||||
int = ADD4(left:int, right:aluparam)
|
reg = ADD4(left:reg, right:aluparam)
|
||||||
emit "add %int, %left, %right"
|
emit "add %reg, %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = ADD4(left:aluparam, right:int)
|
reg = ADD4(left:aluparam, right:reg)
|
||||||
emit "add %int, %right, %left"
|
emit "add %reg, %right, %left"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = MOD4(left:int, right:int)
|
reg = MOD4(left:reg, right:reg)
|
||||||
emit "udiv %int, %left, %right"
|
emit "udiv %reg, %left, %right"
|
||||||
emit "mls %int, %int, %right, %left"
|
emit "mls %reg, %reg, %right, %left"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
|
||||||
int = DIV4(left:int, right:aluparam)
|
reg = DIV4(left:reg, right:aluparam)
|
||||||
emit "div %int, %left, %right"
|
emit "div %reg, %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
aluparam = value:CONST4
|
aluparam = value:CONST4
|
||||||
emit "#$value";
|
emit "#$value";
|
||||||
|
|
||||||
aluparam = value:int
|
aluparam = value:reg
|
||||||
emit "%value";
|
emit "%value";
|
||||||
|
|
||||||
int = value:aluparam
|
reg = value:aluparam
|
||||||
emit "mov %int, %value"
|
emit "mov %reg, %value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = value:LABEL4
|
reg = value:LABEL4
|
||||||
emit "adr %int, $value"
|
emit "adr %reg, $value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = value:BLOCK4
|
reg = value:BLOCK4
|
||||||
emit "adr %int, $value"
|
emit "adr %reg, $value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = value:CONST4
|
reg = value:CONST4
|
||||||
emit "ldr %int, address-containing-$value"
|
emit "ldr %reg, address-containing-$value"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
|
||||||
float = value:CONSTF4
|
reg = value:CONSTF4
|
||||||
emit "vldr %float, address-containing-$value"
|
emit "vldr %reg, address-containing-$value"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
|
||||||
/* FPU operations */
|
/* FPU operations */
|
||||||
|
|
||||||
float = ADDF4(left:float, right:float)
|
reg = ADDF4(left:reg, right:reg)
|
||||||
emit "fadds %float, %left, %right"
|
emit "fadds %reg, %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
|
|
@ -24,28 +24,34 @@ static int nextern = 1;
|
||||||
struct stringlist* stringlist;
|
struct stringlist* stringlist;
|
||||||
struct terminfo terminfo;
|
struct terminfo terminfo;
|
||||||
struct expr* expr;
|
struct expr* expr;
|
||||||
|
struct constraint* constraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
%term ALLOCATES
|
%term ALLOCATES
|
||||||
%term COST
|
%term COST
|
||||||
%term DECLARATIONS
|
%term DECLARATIONS
|
||||||
%term EMIT
|
%term EMIT
|
||||||
|
%term EQUALS
|
||||||
%term FRAGMENT
|
%term FRAGMENT
|
||||||
|
%term NOTEQUALS
|
||||||
%term PATTERNS
|
%term PATTERNS
|
||||||
%term REGISTERS
|
|
||||||
%term PREFERS
|
%term PREFERS
|
||||||
%term REQUIRES
|
%term REGISTERS
|
||||||
|
%term WHEN
|
||||||
|
%term WITH
|
||||||
|
|
||||||
%token <n> INT
|
%token <n> INT
|
||||||
%token <string> ID
|
%token <string> ID
|
||||||
%token <string> QFRAGMENT
|
%token <string> QFRAGMENT
|
||||||
|
|
||||||
%type <nonterm> allocates
|
%type <nonterm> allocates
|
||||||
|
%type <constraint> constraint
|
||||||
|
%type <constraint> constraints
|
||||||
%type <nonterm> declaration
|
%type <nonterm> declaration
|
||||||
%type <reg> register
|
%type <reg> register
|
||||||
%type <rule> emit
|
%type <rule> pattern_constraints
|
||||||
|
%type <rule> pattern_emit
|
||||||
%type <rule> pattern
|
%type <rule> pattern
|
||||||
%type <stringlist> cfragments
|
|
||||||
%type <stringlist> qfragments
|
%type <stringlist> qfragments
|
||||||
%type <terminfo> terminfo
|
%type <terminfo> terminfo
|
||||||
%type <tree> rhs
|
%type <tree> rhs
|
||||||
|
@ -102,9 +108,10 @@ pattern
|
||||||
: ID '=' rhs { nonterm($1, false); $$ = rule($1, $3, nextern++); }
|
: ID '=' rhs { nonterm($1, false); $$ = rule($1, $3, nextern++); }
|
||||||
| rhs { $$ = rule("stmt", $1, nextern++); }
|
| rhs { $$ = rule("stmt", $1, nextern++); }
|
||||||
| pattern PREFERS predicate { $$ = $1; array_append(&$$->prefers, $3); }
|
| pattern PREFERS predicate { $$ = $1; array_append(&$$->prefers, $3); }
|
||||||
| pattern REQUIRES predicate { $$ = $1; array_append(&$$->requires, $3); }
|
| pattern WHEN predicate { $$ = $1; array_append(&$$->requires, $3); }
|
||||||
| emit { $$ = $1; }
|
|
||||||
| pattern COST INT { $$ = $1; $$->cost = $3; }
|
| pattern COST INT { $$ = $1; $$->cost = $3; }
|
||||||
|
| pattern_constraints { $$ = $1; }
|
||||||
|
| pattern_emit { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
rhs
|
rhs
|
||||||
|
@ -115,12 +122,10 @@ rhs
|
||||||
|
|
||||||
terminfo
|
terminfo
|
||||||
: ID { $$.name = $1; }
|
: ID { $$.name = $1; }
|
||||||
| ID '.' ID { $$.name = $1; $$.regattr = $3; }
|
|
||||||
| ID ':' ID { $$.label = $1; $$.name = $3; }
|
| ID ':' ID { $$.label = $1; $$.name = $3; }
|
||||||
| ID ':' ID '.' ID { $$.label = $1; $$.name = $3; $$.regattr = $5; }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
emit
|
pattern_emit
|
||||||
: pattern EMIT qfragments {
|
: pattern EMIT qfragments {
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
if (!$$->lhs->is_fragment)
|
if (!$$->lhs->is_fragment)
|
||||||
|
@ -129,6 +134,33 @@ emit
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
pattern_constraints
|
||||||
|
: pattern WITH constraints {
|
||||||
|
struct constraint* c = $3;
|
||||||
|
$$ = $1;
|
||||||
|
while (c)
|
||||||
|
{
|
||||||
|
array_append(&$$->constraints, c);
|
||||||
|
c = c->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
constraints
|
||||||
|
: constraint { $$ = $1; }
|
||||||
|
| constraints ',' constraint { $$ = $3; $$->next = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
constraint
|
||||||
|
: '(' constraint ')' { $$ = $2; }
|
||||||
|
| ID ID { $$ = calloc(1, sizeof(*$$));
|
||||||
|
$$->type = CONSTRAINT_ATTR; $$->left = $1; $$->right = $2; }
|
||||||
|
| ID EQUALS ID { $$ = calloc(1, sizeof(*$$));
|
||||||
|
$$->type = CONSTRAINT_EQUALS; $$->left = $1; $$->right = $3; }
|
||||||
|
| ID NOTEQUALS ID { $$ = calloc(1, sizeof(*$$));
|
||||||
|
$$->type = CONSTRAINT_NOTEQUALS; $$->left = $1; $$->right = $3; }
|
||||||
|
;
|
||||||
|
|
||||||
qfragments
|
qfragments
|
||||||
: /* nothing */ { $$ = calloc(1, sizeof *$$); }
|
: /* nothing */ { $$ = calloc(1, sizeof *$$); }
|
||||||
| qfragments QFRAGMENT { $$ = $1; stringlist_add($$, $2); }
|
| qfragments QFRAGMENT { $$ = $1; stringlist_add($$, $2); }
|
||||||
|
@ -139,7 +171,7 @@ predicate
|
||||||
;
|
;
|
||||||
|
|
||||||
predicate_args
|
predicate_args
|
||||||
: /* nothing */
|
: /* nothing */ { $$ = NULL; }
|
||||||
| ID { $$ = calloc(1, sizeof *$$); $$->name = $1; }
|
| ID { $$ = calloc(1, sizeof *$$); $$->name = $1; }
|
||||||
| ID ',' predicate_args { $$ = calloc(1, sizeof *$$); $$->name = $1; $$->next = $3; }
|
| ID ',' predicate_args { $$ = calloc(1, sizeof *$$); $$->name = $1; $$->next = $3; }
|
||||||
;
|
;
|
||||||
|
|
|
@ -262,7 +262,6 @@ void addregclass(struct reg* reg, const char* id)
|
||||||
}
|
}
|
||||||
|
|
||||||
reg->classes |= 1<<(p->number);
|
reg->classes |= 1<<(p->number);
|
||||||
nonterm(id, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct regclass* getregclass(const char* id)
|
struct regclass* getregclass(const char* id)
|
||||||
|
|
|
@ -16,6 +16,21 @@ typedef enum
|
||||||
typedef struct rule* Rule;
|
typedef struct rule* Rule;
|
||||||
typedef struct term* Term;
|
typedef struct term* Term;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CONSTRAINT_ATTR,
|
||||||
|
CONSTRAINT_EQUALS,
|
||||||
|
CONSTRAINT_NOTEQUALS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct constraint
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
const char* left;
|
||||||
|
const char* right;
|
||||||
|
struct constraint* next;
|
||||||
|
};
|
||||||
|
|
||||||
struct expr
|
struct expr
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
|
@ -26,7 +41,6 @@ struct terminfo
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
const char* label;
|
const char* label;
|
||||||
const char* regattr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct reg
|
struct reg
|
||||||
|
@ -97,8 +111,9 @@ struct rule
|
||||||
Rule chain; /* next chain rule with same rhs */
|
Rule chain; /* next chain rule with same rhs */
|
||||||
Rule decode; /* next rule with same lhs */
|
Rule decode; /* next rule with same lhs */
|
||||||
Rule kids; /* next rule with same burm_kids pattern */
|
Rule kids; /* next rule with same burm_kids pattern */
|
||||||
ARRAYOF(struct predicate) prefers; /* C predicates */
|
ARRAYOF(struct expr) prefers; /* C predicates */
|
||||||
ARRAYOF(struct predicate) requires; /* C predicates */
|
ARRAYOF(struct expr) requires; /* C predicates */
|
||||||
|
ARRAYOF(struct constraint) constraints; /* register constraints */
|
||||||
struct stringlist code; /* compiler output code strings */
|
struct stringlist code; /* compiler output code strings */
|
||||||
};
|
};
|
||||||
extern Rule rule(char* id, Tree pattern, int ern);
|
extern Rule rule(char* id, Tree pattern, int ern);
|
||||||
|
|
|
@ -43,7 +43,10 @@ static int braces = 0;
|
||||||
"emit" return EMIT;
|
"emit" return EMIT;
|
||||||
"fragment" return FRAGMENT;
|
"fragment" return FRAGMENT;
|
||||||
"prefers" return PREFERS;
|
"prefers" return PREFERS;
|
||||||
"requires" return REQUIRES;
|
"when" return WHEN;
|
||||||
|
"with" return WITH;
|
||||||
|
"==" return EQUALS;
|
||||||
|
"!=" return NOTEQUALS;
|
||||||
|
|
||||||
"//"[^\n]*\n ;
|
"//"[^\n]*\n ;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue