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