DECLARATIONS
+ reg;
+ cc;
+
address fragment;
aluparam fragment;
/* 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
/* 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]";
/* 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;
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
: 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
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)
}
;
+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); }
;
predicate_args
- : /* nothing */
+ : /* nothing */ { $$ = NULL; }
| ID { $$ = calloc(1, sizeof *$$); $$->name = $1; }
| ID ',' predicate_args { $$ = calloc(1, sizeof *$$); $$->name = $1; $$->next = $3; }
;