Add (pretty crummy) support for register aliases and static pairs of registers.
We should have enough functionality now for rather buggy 8-bit ints and doubles. Rework the table and the platform.c to match.
This commit is contained in:
parent
d6984d60ac
commit
4db402f229
|
@ -98,51 +98,122 @@ struct hop* platform_epilogue(void)
|
||||||
struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest)
|
struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest)
|
||||||
{
|
{
|
||||||
struct hop* hop = new_hop(bb, NULL);
|
struct hop* hop = new_hop(bb, NULL);
|
||||||
|
const uint32_t type_attrs =
|
||||||
|
burm_int_ATTR | burm_pair_ATTR | burm_float_ATTR | burm_double_ATTR;
|
||||||
|
|
||||||
if (!src->is_stacked && dest->is_stacked)
|
if ((src->type & type_attrs) != (dest->type & type_attrs))
|
||||||
{
|
{
|
||||||
if (src->type & burm_int_ATTR)
|
assert(!src->is_stacked);
|
||||||
hop_add_insel(hop, "stw %H, %S(fp) ! %H", src, dest, dest);
|
assert(!dest->is_stacked);
|
||||||
else if (src->type & burm_float_ATTR)
|
|
||||||
hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest);
|
switch (src->type & type_attrs)
|
||||||
else
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
else if (src->is_stacked && !dest->is_stacked)
|
|
||||||
{
|
|
||||||
if (src->type & burm_int_ATTR)
|
|
||||||
hop_add_insel(hop, "lwz %H, %S(fp) ! %H", dest, src, src);
|
|
||||||
else if (src->type & burm_float_ATTR)
|
|
||||||
hop_add_insel(hop, "lfs %H, %S(fp) ! %H", dest, src, src);
|
|
||||||
else
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
else if (!src->is_stacked && !dest->is_stacked)
|
|
||||||
{
|
|
||||||
if ((src->type & burm_int_ATTR) && (dest->type & burm_int_ATTR))
|
|
||||||
hop_add_insel(hop, "mr %H, %H", dest, src);
|
|
||||||
else if ((src->type & burm_float_ATTR) && (dest->type & burm_float_ATTR))
|
|
||||||
hop_add_insel(hop, "fmr %H, %H", dest, src);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (src->type & burm_int_ATTR)
|
case burm_int_ATTR:
|
||||||
hop_add_insel(hop, "stwu %H, -4(sp)", src);
|
hop_add_insel(hop, "stwu %H, -4(sp)", src);
|
||||||
else if (src->type & burm_float_ATTR)
|
break;
|
||||||
hop_add_insel(hop, "stfsu %H, -4(sp)", src);
|
|
||||||
else
|
|
||||||
assert(false);
|
|
||||||
|
|
||||||
if (dest->type & burm_int_ATTR)
|
case burm_float_ATTR:
|
||||||
hop_add_insel(hop, "lwz %H, 0(sp)", dest);
|
hop_add_insel(hop, "stfsu %H, -4(sp)", src);
|
||||||
else if (dest->type & burm_float_ATTR)
|
break;
|
||||||
hop_add_insel(hop, "lfs %H, 0(sp)", dest);
|
|
||||||
else
|
case burm_double_ATTR:
|
||||||
|
hop_add_insel(hop, "stfdu %H, -8(sp)", src);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
hop_add_insel(hop, "addi sp, sp, 4");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
switch (dest->type & type_attrs)
|
||||||
fatal("cannot generate move from %s to %s", src->name, dest->name);
|
{
|
||||||
|
case burm_int_ATTR:
|
||||||
|
hop_add_insel(hop, "lwz %H, 0(sp)", dest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case burm_float_ATTR:
|
||||||
|
hop_add_insel(hop, "lfs %H, 0(sp)", dest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case burm_double_ATTR:
|
||||||
|
hop_add_insel(hop, "lfd %H, 0(sp)", dest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dest->type & type_attrs)
|
||||||
|
{
|
||||||
|
case burm_int_ATTR:
|
||||||
|
case burm_float_ATTR:
|
||||||
|
hop_add_insel(hop, "addi sp, sp, 4");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case burm_double_ATTR:
|
||||||
|
case burm_pair_ATTR:
|
||||||
|
hop_add_insel(hop, "addi sp, sp, 8");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t type = src->type & type_attrs;
|
||||||
|
|
||||||
|
if (!src->is_stacked && dest->is_stacked)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case burm_int_ATTR:
|
||||||
|
hop_add_insel(hop, "stw %H, %S(fp) ! %H", src, dest, dest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case burm_float_ATTR:
|
||||||
|
hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (src->is_stacked && !dest->is_stacked)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case burm_int_ATTR:
|
||||||
|
hop_add_insel(hop, "lwz %H, %S(fp) ! %H", dest, src, src);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case burm_float_ATTR:
|
||||||
|
hop_add_insel(hop, "lfs %H, %S(fp) ! %H", dest, src, src);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!src->is_stacked && !dest->is_stacked)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case burm_int_ATTR:
|
||||||
|
hop_add_insel(hop, "mr %H, %H", dest, src);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case burm_float_ATTR:
|
||||||
|
case burm_double_ATTR:
|
||||||
|
hop_add_insel(hop, "fmr %H, %H", dest, src);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
return hop;
|
return hop;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,71 +7,122 @@ REGISTERS
|
||||||
* a register into another register (e.g. for eviction).
|
* a register into another register (e.g. for eviction).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
r12 "r12" bytes4! int! volatile;
|
r12 bytes4! int! volatile;
|
||||||
r11 "r11" bytes4! int! volatile;
|
r11 bytes4! int! volatile;
|
||||||
r10 "r10" bytes4! int! volatile;
|
r10 bytes4! int! volatile;
|
||||||
r9 "r9" bytes4! int! volatile;
|
r9 bytes4! int! volatile;
|
||||||
r8 "r8" bytes4! int! volatile;
|
r8 bytes4! int! volatile;
|
||||||
r7 "r7" bytes4! int! volatile;
|
r7 bytes4! int! volatile;
|
||||||
r6 "r6" bytes4! int! volatile;
|
r6 bytes4! int! volatile;
|
||||||
r5 "r5" bytes4! int! volatile;
|
r5 bytes4! int! volatile;
|
||||||
r4 "r4" bytes4! int! volatile;
|
r4 bytes4! int! volatile;
|
||||||
r3 "r3" bytes4! int! volatile ret;
|
r3 bytes4! int! volatile ret;
|
||||||
|
|
||||||
r31 "r31" bytes4! int!;
|
r31 bytes4! int!;
|
||||||
r30 "r30" bytes4! int!;
|
r30 bytes4! int!;
|
||||||
r29 "r29" bytes4! int!;
|
r29 bytes4! int!;
|
||||||
r28 "r28" bytes4! int!;
|
r28 bytes4! int!;
|
||||||
r27 "r27" bytes4! int!;
|
r27 bytes4! int!;
|
||||||
r26 "r26" bytes4! int!;
|
r26 bytes4! int!;
|
||||||
r25 "r25" bytes4! int!;
|
r25 bytes4! int!;
|
||||||
r24 "r24" bytes4! int!;
|
r24 bytes4! int!;
|
||||||
r23 "r23" bytes4! int!;
|
r23 bytes4! int!;
|
||||||
r22 "r22" bytes4! int!;
|
r22 bytes4! int!;
|
||||||
r21 "r21" bytes4! int!;
|
r21 bytes4! int!;
|
||||||
r20 "r20" bytes4! int!;
|
r20 bytes4! int!;
|
||||||
r19 "r19" bytes4! int!;
|
r19 bytes4! int!;
|
||||||
r18 "r18" bytes4! int!;
|
r18 bytes4! int!;
|
||||||
r17 "r17" bytes4! int!;
|
r17 bytes4! int!;
|
||||||
r16 "r16" bytes4! int!;
|
r16 bytes4! int!;
|
||||||
r15 "r15" bytes4! int!;
|
r15 bytes4! int!;
|
||||||
r14 "r14" bytes4! int!;
|
r14 bytes4! int!;
|
||||||
|
r13 bytes4! int!;
|
||||||
|
|
||||||
f14 "f14" bytes4! float! volatile;
|
r11r12 named("r11", "r12") aliases(r11, r12) bytes8! pair! volatile;
|
||||||
f13 "f13" bytes4! float! volatile;
|
r9r10 named("r9", "r10") aliases(r9, r10) bytes8! pair! volatile;
|
||||||
f12 "f12" bytes4! float! volatile;
|
r7r8 named("r7", "r8") aliases(r7, r8) bytes8! pair! volatile;
|
||||||
f11 "f11" bytes4! float! volatile;
|
r5r6 named("r5", "r6") aliases(r6, r6) bytes8! pair! volatile;
|
||||||
f10 "f10" bytes4! float! volatile;
|
r3r4 named("r3", "r4") aliases(r3, r4) bytes8! pair! volatile pret;
|
||||||
f9 "f9" bytes4! float! volatile;
|
|
||||||
f8 "f8" bytes4! float! volatile;
|
|
||||||
f7 "f7" bytes4! float! volatile;
|
|
||||||
f6 "f6" bytes4! float! volatile;
|
|
||||||
f5 "f5" bytes4! float! volatile;
|
|
||||||
f4 "f4" bytes4! float! volatile;
|
|
||||||
f3 "f3" bytes4! float! volatile fret;
|
|
||||||
f2 "f2" bytes4! float! volatile;
|
|
||||||
f1 "f1" bytes4! float! volatile;
|
|
||||||
f0 "f0" bytes4! float! volatile;
|
|
||||||
|
|
||||||
f31 "f31" bytes4! float!;
|
r29r30 named("r29", "r30") aliases(r29, r30) bytes8! pair!;
|
||||||
f30 "f30" bytes4! float!;
|
r27r28 named("r27", "r28") aliases(r27, r28) bytes8! pair!;
|
||||||
f29 "f29" bytes4! float!;
|
r25r26 named("r25", "r26") aliases(r25, r26) bytes8! pair!;
|
||||||
f28 "f28" bytes4! float!;
|
r23r24 named("r23", "r24") aliases(r23, r24) bytes8! pair!;
|
||||||
f27 "f27" bytes4! float!;
|
r21r22 named("r21", "r22") aliases(r21, r22) bytes8! pair!;
|
||||||
f26 "f26" bytes4! float!;
|
r19r20 named("r19", "r20") aliases(r19, r20) bytes8! pair!;
|
||||||
f25 "f25" bytes4! float!;
|
r17r18 named("r17", "r18") aliases(r17, r18) bytes8! pair!;
|
||||||
f24 "f24" bytes4! float!;
|
r15r16 named("r15", "r16") aliases(r15, r16) bytes8! pair!;
|
||||||
f23 "f23" bytes4! float!;
|
r13r14 named("r13", "r14") aliases(r13, r14) bytes8! pair!;
|
||||||
f22 "f22" bytes4! float!;
|
|
||||||
f21 "f21" bytes4! float!;
|
f14 bytes4! float! volatile;
|
||||||
f20 "f20" bytes4! float!;
|
f13 bytes4! float! volatile;
|
||||||
f19 "f19" bytes4! float!;
|
f12 bytes4! float! volatile;
|
||||||
f18 "f18" bytes4! float!;
|
f11 bytes4! float! volatile;
|
||||||
f17 "f17" bytes4! float!;
|
f10 bytes4! float! volatile;
|
||||||
f16 "f16" bytes4! float!;
|
f9 bytes4! float! volatile;
|
||||||
f15 "f15" bytes4! float!;
|
f8 bytes4! float! volatile;
|
||||||
|
f7 bytes4! float! volatile;
|
||||||
cr0 "cr0" cr!;
|
f6 bytes4! float! volatile;
|
||||||
|
f5 bytes4! float! volatile;
|
||||||
|
f4 bytes4! float! volatile;
|
||||||
|
f3 bytes4! float! volatile fret;
|
||||||
|
f2 bytes4! float! volatile;
|
||||||
|
f1 bytes4! float! volatile;
|
||||||
|
f0 bytes4! float! volatile;
|
||||||
|
|
||||||
|
f31 bytes4! float!;
|
||||||
|
f30 bytes4! float!;
|
||||||
|
f29 bytes4! float!;
|
||||||
|
f28 bytes4! float!;
|
||||||
|
f27 bytes4! float!;
|
||||||
|
f26 bytes4! float!;
|
||||||
|
f25 bytes4! float!;
|
||||||
|
f24 bytes4! float!;
|
||||||
|
f23 bytes4! float!;
|
||||||
|
f22 bytes4! float!;
|
||||||
|
f21 bytes4! float!;
|
||||||
|
f20 bytes4! float!;
|
||||||
|
f19 bytes4! float!;
|
||||||
|
f18 bytes4! float!;
|
||||||
|
f17 bytes4! float!;
|
||||||
|
f16 bytes4! float!;
|
||||||
|
f15 bytes4! float!;
|
||||||
|
|
||||||
|
d14 named("f14") aliases(f14) bytes8! double! volatile;
|
||||||
|
d13 named("f13") aliases(f13) bytes8! double! volatile;
|
||||||
|
d12 named("f12") aliases(f12) bytes8! double! volatile;
|
||||||
|
d11 named("f11") aliases(f11) bytes8! double! volatile;
|
||||||
|
d10 named("f10") aliases(f10) bytes8! double! volatile;
|
||||||
|
d9 named("f9") aliases(f9) bytes8! double! volatile;
|
||||||
|
d8 named("f8") aliases(f8) bytes8! double! volatile;
|
||||||
|
d7 named("f7") aliases(f7) bytes8! double! volatile;
|
||||||
|
d6 named("f6") aliases(f6) bytes8! double! volatile;
|
||||||
|
d5 named("f5") aliases(f5) bytes8! double! volatile;
|
||||||
|
d4 named("f4") aliases(f4) bytes8! double! volatile;
|
||||||
|
d3 named("f3") aliases(f3) bytes8! double! volatile dret;
|
||||||
|
d2 named("f2") aliases(f2) bytes8! double! volatile;
|
||||||
|
d1 named("f1") aliases(f1) bytes8! double! volatile;
|
||||||
|
d0 named("f0") aliases(f0) bytes8! double! volatile;
|
||||||
|
|
||||||
|
d31 named("f31") aliases(f31) bytes8! double!;
|
||||||
|
d30 named("f30") aliases(f30) bytes8! double!;
|
||||||
|
d29 named("f29") aliases(f29) bytes8! double!;
|
||||||
|
d28 named("f28") aliases(f28) bytes8! double!;
|
||||||
|
d27 named("f27") aliases(f27) bytes8! double!;
|
||||||
|
d26 named("f26") aliases(f26) bytes8! double!;
|
||||||
|
d25 named("f25") aliases(f25) bytes8! double!;
|
||||||
|
d24 named("f24") aliases(f24) bytes8! double!;
|
||||||
|
d23 named("f23") aliases(f23) bytes8! double!;
|
||||||
|
d22 named("f22") aliases(f22) bytes8! double!;
|
||||||
|
d21 named("f21") aliases(f21) bytes8! double!;
|
||||||
|
d20 named("f20") aliases(f20) bytes8! double!;
|
||||||
|
d19 named("f19") aliases(f19) bytes8! double!;
|
||||||
|
d18 named("f18") aliases(f18) bytes8! double!;
|
||||||
|
d17 named("f17") aliases(f17) bytes8! double!;
|
||||||
|
d16 named("f16") aliases(f16) bytes8! double!;
|
||||||
|
d15 named("f15") aliases(f15) bytes8! double!;
|
||||||
|
|
||||||
|
cr0 cr!;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,6 +152,11 @@ PATTERNS
|
||||||
emit "stwu %in, -4(sp)"
|
emit "stwu %in, -4(sp)"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
PUSH8(in:(pair)reg)
|
||||||
|
emit "stwu %in.0, -4(sp)"
|
||||||
|
emit "stwu %in.1, -4(sp)"
|
||||||
|
cost 8;
|
||||||
|
|
||||||
out:(int)reg = POP4
|
out:(int)reg = POP4
|
||||||
emit "lwz %out, 0(sp)"
|
emit "lwz %out, 0(sp)"
|
||||||
emit "addi sp, sp, 4"
|
emit "addi sp, sp, 4"
|
||||||
|
@ -113,12 +169,20 @@ PATTERNS
|
||||||
|
|
||||||
SETRET4(in:(ret)reg)
|
SETRET4(in:(ret)reg)
|
||||||
emit "! setret4"
|
emit "! setret4"
|
||||||
cost 4;
|
cost 1;
|
||||||
|
|
||||||
|
SETRET8(in:(pret)reg)
|
||||||
|
emit "! setret8"
|
||||||
|
cost 1;
|
||||||
|
|
||||||
(ret)reg = GETRET4
|
(ret)reg = GETRET4
|
||||||
emit "! getret4"
|
emit "! getret4"
|
||||||
cost 1;
|
cost 1;
|
||||||
|
|
||||||
|
(pret)reg = GETRET8
|
||||||
|
emit "! getret8"
|
||||||
|
cost 1;
|
||||||
|
|
||||||
STACKADJUST4(delta:CONST4)
|
STACKADJUST4(delta:CONST4)
|
||||||
when signed_constant(%delta, 16)
|
when signed_constant(%delta, 16)
|
||||||
emit "addi sp, sp, $delta"
|
emit "addi sp, sp, $delta"
|
||||||
|
@ -142,6 +206,11 @@ PATTERNS
|
||||||
|
|
||||||
/* Stores */
|
/* Stores */
|
||||||
|
|
||||||
|
STORE8(addr:address, value:(pair)reg)
|
||||||
|
emit "stw %value.0, 4+%addr"
|
||||||
|
emit "stw %value.1, 0+%addr"
|
||||||
|
cost 4;
|
||||||
|
|
||||||
STORE4(addr:address, value:(int)reg)
|
STORE4(addr:address, value:(int)reg)
|
||||||
emit "stw %value, %addr"
|
emit "stw %value, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
@ -168,6 +237,11 @@ PATTERNS
|
||||||
emit "lwz %out, %addr"
|
emit "lwz %out, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
out:(pair)reg = LOAD8(addr:address)
|
||||||
|
emit "lwz %out.0, 4+%addr"
|
||||||
|
emit "lwz %out.1, 0+%addr"
|
||||||
|
cost 8;
|
||||||
|
|
||||||
out:(int)ushort0 = LOAD2(addr:address)
|
out:(int)ushort0 = LOAD2(addr:address)
|
||||||
emit "lhz %out, %addr"
|
emit "lhz %out, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
@ -480,6 +554,10 @@ PATTERNS
|
||||||
emit "lfs %out, %addr"
|
emit "lfs %out, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
out:(double)reg = LOADF8(addr:address)
|
||||||
|
emit "lfd %out, %addr"
|
||||||
|
cost 4;
|
||||||
|
|
||||||
out:(float)reg = value:CONSTF4
|
out:(float)reg = value:CONSTF4
|
||||||
emit "lfs %out, address-containing-$value"
|
emit "lfs %out, address-containing-$value"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
@ -488,6 +566,10 @@ PATTERNS
|
||||||
emit "fadds %out, %left, %right"
|
emit "fadds %out, %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
out:(double)reg = ADDF8(left:(double)reg, right:(double)reg)
|
||||||
|
emit "fadd %out, %left, %right"
|
||||||
|
cost 4;
|
||||||
|
|
||||||
out:(float)reg = SUBF4(left:(float)reg, right:(float)reg)
|
out:(float)reg = SUBF4(left:(float)reg, right:(float)reg)
|
||||||
emit "fsubs %out, %left, %right"
|
emit "fsubs %out, %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
|
@ -31,17 +31,19 @@ void hop_add_string_insel(struct hop* hop, const char* string)
|
||||||
array_append(&hop->insels, insel);
|
array_append(&hop->insels, insel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hop_add_hreg_insel(struct hop* hop, struct hreg* hreg)
|
void hop_add_hreg_insel(struct hop* hop, struct hreg* hreg, int index)
|
||||||
{
|
{
|
||||||
struct insel* insel = new_insel(INSEL_HREG);
|
struct insel* insel = new_insel(INSEL_HREG);
|
||||||
insel->u.hreg = hreg;
|
insel->u.hreg = hreg;
|
||||||
|
insel->index = index;
|
||||||
array_append(&hop->insels, insel);
|
array_append(&hop->insels, insel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hop_add_vreg_insel(struct hop* hop, struct vreg* vreg)
|
void hop_add_vreg_insel(struct hop* hop, struct vreg* vreg, int index)
|
||||||
{
|
{
|
||||||
struct insel* insel = new_insel(INSEL_VREG);
|
struct insel* insel = new_insel(INSEL_VREG);
|
||||||
insel->u.vreg = vreg;
|
insel->u.vreg = vreg;
|
||||||
|
insel->index = index;
|
||||||
array_append(&hop->insels, insel);
|
array_append(&hop->insels, insel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,11 +110,11 @@ void hop_add_insel(struct hop* hop, const char* fmt, ...)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'H':
|
case 'H':
|
||||||
hop_add_hreg_insel(hop, va_arg(ap, struct hreg*));
|
hop_add_hreg_insel(hop, va_arg(ap, struct hreg*), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
hop_add_vreg_insel(hop, va_arg(ap, struct vreg*));
|
hop_add_vreg_insel(hop, va_arg(ap, struct vreg*), 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,7 +207,7 @@ char* hop_render(struct hop* hop)
|
||||||
case INSEL_HREG:
|
case INSEL_HREG:
|
||||||
{
|
{
|
||||||
struct hreg* hreg = insel->u.hreg;
|
struct hreg* hreg = insel->u.hreg;
|
||||||
appendf("%s", hreg->realname);
|
appendf("%s", hreg->brd->names[insel->index]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +218,7 @@ char* hop_render(struct hop* hop)
|
||||||
if (!hreg)
|
if (!hreg)
|
||||||
hreg = pmap_findright(&hop->regsout, vreg);
|
hreg = pmap_findright(&hop->regsout, vreg);
|
||||||
if (hreg)
|
if (hreg)
|
||||||
appendf("%s", hreg->realname);
|
appendf("%s", hreg->brd->names[insel->index]);
|
||||||
else
|
else
|
||||||
appendf("%%%d", vreg->id);
|
appendf("%%%d", vreg->id);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -16,6 +16,7 @@ enum insel_type
|
||||||
struct insel
|
struct insel
|
||||||
{
|
{
|
||||||
enum insel_type type;
|
enum insel_type type;
|
||||||
|
int index;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
const char* string;
|
const char* string;
|
||||||
|
@ -54,8 +55,8 @@ struct hop
|
||||||
extern struct hop* new_hop(struct basicblock* bb, struct ir* ir);
|
extern struct hop* new_hop(struct basicblock* bb, struct ir* ir);
|
||||||
|
|
||||||
extern void hop_add_string_insel(struct hop* hop, const char* string);
|
extern void hop_add_string_insel(struct hop* hop, const char* string);
|
||||||
extern void hop_add_hreg_insel(struct hop* hop, struct hreg* hreg);
|
extern void hop_add_hreg_insel(struct hop* hop, struct hreg* hreg, int index);
|
||||||
extern void hop_add_vreg_insel(struct hop* hop, struct vreg* vreg);
|
extern void hop_add_vreg_insel(struct hop* hop, struct vreg* vreg, int index);
|
||||||
extern void hop_add_value_insel(struct hop* hop, struct ir* ir);
|
extern void hop_add_value_insel(struct hop* hop, struct ir* ir);
|
||||||
extern void hop_add_st_offset_insel(struct hop* hop, struct hreg* hreg);
|
extern void hop_add_st_offset_insel(struct hop* hop, struct hreg* hreg);
|
||||||
extern void hop_add_ab_offset_insel(struct hop* hop, int offset);
|
extern void hop_add_ab_offset_insel(struct hop* hop, int offset);
|
||||||
|
|
|
@ -32,9 +32,9 @@ void burm_panic_cannot_match(struct burm_node* node)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_return_reg(void)
|
static void emit_return_reg(int index)
|
||||||
{
|
{
|
||||||
hop_add_vreg_insel(current_hop, current_hop->output);
|
hop_add_vreg_insel(current_hop, current_hop->output, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vreg* find_vreg_of_child(int child)
|
static struct vreg* find_vreg_of_child(int child)
|
||||||
|
@ -47,13 +47,13 @@ static struct vreg* find_vreg_of_child(int child)
|
||||||
return insn->ir->result;
|
return insn->ir->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_reg(int child)
|
static void emit_reg(int child, int index)
|
||||||
{
|
{
|
||||||
struct vreg* vreg = find_vreg_of_child(child);
|
struct vreg* vreg = find_vreg_of_child(child);
|
||||||
|
|
||||||
if (vreg)
|
if (vreg)
|
||||||
{
|
{
|
||||||
hop_add_vreg_insel(current_hop, vreg);
|
hop_add_vreg_insel(current_hop, vreg, index);
|
||||||
array_appendu(&vreg->used, current_hop);
|
array_appendu(&vreg->used, current_hop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ static uint32_t find_type_from_constraint(uint32_t attr)
|
||||||
* this. */
|
* this. */
|
||||||
|
|
||||||
const struct burm_register_data* brd = burm_register_data;
|
const struct burm_register_data* brd = burm_register_data;
|
||||||
while (brd->name)
|
while (brd->id)
|
||||||
{
|
{
|
||||||
if (brd->attrs & attr)
|
if (brd->attrs & attr)
|
||||||
return brd->type;
|
return brd->type;
|
||||||
|
|
|
@ -48,7 +48,7 @@ static void promote(struct ir* ir)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<ir->u.phivalue.count; i++)
|
for (i=0; i<ir->u.phivalue.count; i++)
|
||||||
array_appendu(&promotable, ir->u.phivalue.item[i].right);
|
promote(ir->u.phivalue.item[i].right);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,30 @@ static bool type_match(struct hreg* hreg, struct vreg* vreg);
|
||||||
|
|
||||||
static void populate_hregs(void)
|
static void populate_hregs(void)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
const struct burm_register_data* brd = burm_register_data;
|
const struct burm_register_data* brd = burm_register_data;
|
||||||
|
|
||||||
hregs.count = 0;
|
hregs.count = 0;
|
||||||
while (brd->name)
|
while (brd->id)
|
||||||
{
|
{
|
||||||
array_append(&hregs, new_hreg(brd));
|
array_append(&hregs, new_hreg(brd));
|
||||||
brd++;
|
brd++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wire up the register aliases. */
|
||||||
|
|
||||||
|
for (i=0; i<hregs.count; i++)
|
||||||
|
{
|
||||||
|
struct hreg* hreg = hregs.item[i];
|
||||||
|
const struct burm_register_data** alias = hreg->brd->aliases;
|
||||||
|
|
||||||
|
while (*alias)
|
||||||
|
{
|
||||||
|
int index = *alias - burm_register_data;
|
||||||
|
array_append(&hreg->aliases, hregs.item[index]);
|
||||||
|
alias++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wire_up_blocks_ins_outs(void)
|
static void wire_up_blocks_ins_outs(void)
|
||||||
|
@ -43,6 +59,20 @@ static void wire_up_blocks_ins_outs(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool register_used(register_assignment_t* regs, struct hreg* hreg)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<hreg->aliases.count; i++)
|
||||||
|
{
|
||||||
|
struct hreg* alias = hreg->aliases.item[i];
|
||||||
|
if (pmap_findleft(regs, alias))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static struct hreg* allocate_phi_hreg(register_assignment_t* regs,
|
static struct hreg* allocate_phi_hreg(register_assignment_t* regs,
|
||||||
struct vreg* vreg, uint32_t type)
|
struct vreg* vreg, uint32_t type)
|
||||||
{
|
{
|
||||||
|
@ -54,7 +84,7 @@ static struct hreg* allocate_phi_hreg(register_assignment_t* regs,
|
||||||
for (i=0; i<hregs.count; i++)
|
for (i=0; i<hregs.count; i++)
|
||||||
{
|
{
|
||||||
struct hreg* hreg = hregs.item[i];
|
struct hreg* hreg = hregs.item[i];
|
||||||
if (!pmap_findleft(regs, hreg) && (hreg->type == type))
|
if (!register_used(regs, hreg) && (hreg->type == type))
|
||||||
{
|
{
|
||||||
/* This one is unused. Use it. */
|
/* This one is unused. Use it. */
|
||||||
return hreg;
|
return hreg;
|
||||||
|
@ -86,7 +116,10 @@ static struct hreg* evict(struct vreg* vreg)
|
||||||
|
|
||||||
if (evictable(hreg, vreg))
|
if (evictable(hreg, vreg))
|
||||||
{
|
{
|
||||||
if (!candidatein && !candidateout)
|
if (!candidatein &&
|
||||||
|
!candidateout &&
|
||||||
|
!register_used(current_ins, hreg) &&
|
||||||
|
!register_used(current_outs, hreg))
|
||||||
{
|
{
|
||||||
/* This hreg is unused, so we don't need to evict anything.
|
/* This hreg is unused, so we don't need to evict anything.
|
||||||
* Shouldn't really happen in real life. */
|
* Shouldn't really happen in real life. */
|
||||||
|
@ -95,7 +128,7 @@ static struct hreg* evict(struct vreg* vreg)
|
||||||
if (candidatein == candidateout)
|
if (candidatein == candidateout)
|
||||||
{
|
{
|
||||||
/* This is a through register. */
|
/* This is a through register. */
|
||||||
tracef('R', "R: evicting %%%d from %s\n", candidatein->id, hreg->name);
|
tracef('R', "R: evicting %%%d from %s\n", candidatein->id, hreg->id);
|
||||||
pmap_put(&evicted, candidatein, hreg);
|
pmap_put(&evicted, candidatein, hreg);
|
||||||
pmap_remove(current_ins, hreg, candidatein);
|
pmap_remove(current_ins, hreg, candidatein);
|
||||||
pmap_remove(current_outs, hreg, candidatein);
|
pmap_remove(current_outs, hreg, candidatein);
|
||||||
|
@ -120,13 +153,13 @@ static bool type_match(struct hreg* hreg, struct vreg* vreg)
|
||||||
|
|
||||||
static bool allocatable_stackable_input(struct hreg* hreg, struct vreg* vreg)
|
static bool allocatable_stackable_input(struct hreg* hreg, struct vreg* vreg)
|
||||||
{
|
{
|
||||||
return !pmap_findleft(current_ins, hreg) &&
|
return !register_used(current_ins, hreg) &&
|
||||||
type_match(hreg, vreg);
|
type_match(hreg, vreg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool allocatable_stackable_output(struct hreg* hreg, struct vreg* vreg)
|
static bool allocatable_stackable_output(struct hreg* hreg, struct vreg* vreg)
|
||||||
{
|
{
|
||||||
return !pmap_findleft(current_outs, hreg) &&
|
return !register_used(current_outs, hreg) &&
|
||||||
type_match(hreg, vreg) &&
|
type_match(hreg, vreg) &&
|
||||||
!(hreg->attrs & current_hop->insndata->corrupts);
|
!(hreg->attrs & current_hop->insndata->corrupts);
|
||||||
}
|
}
|
||||||
|
@ -295,7 +328,7 @@ static void add_output_register(struct vreg* vreg)
|
||||||
|
|
||||||
pmap_add(current_outs, hreg, vreg);
|
pmap_add(current_outs, hreg, vreg);
|
||||||
tracef('R', "R: output equality constraint requires extra move of %%%d => %s\n",
|
tracef('R', "R: output equality constraint requires extra move of %%%d => %s\n",
|
||||||
c->equals_to->id, hreg->name);
|
c->equals_to->id, hreg->id);
|
||||||
pmap_add(current_ins, hreg, c->equals_to);
|
pmap_add(current_ins, hreg, c->equals_to);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -332,7 +365,7 @@ static void add_through_register(struct vreg* vreg, struct hreg* hreg)
|
||||||
/* Nope, can't honour the hint. Mark the register as evicted; we'll
|
/* Nope, can't honour the hint. Mark the register as evicted; we'll
|
||||||
* put it in something later (probably a stack slot). */
|
* put it in something later (probably a stack slot). */
|
||||||
|
|
||||||
tracef('R', "R: cannot place %%%d in %s, evicting\n", vreg->id, hreg->name);
|
tracef('R', "R: cannot place %%%d in %s, evicting\n", vreg->id, hreg->id);
|
||||||
pmap_put(&evicted, vreg, hreg);
|
pmap_put(&evicted, vreg, hreg);
|
||||||
pmap_remove(current_ins, hreg, vreg);
|
pmap_remove(current_ins, hreg, vreg);
|
||||||
pmap_remove(current_outs, hreg, vreg);
|
pmap_remove(current_outs, hreg, vreg);
|
||||||
|
@ -372,7 +405,7 @@ static void find_new_home_for_evicted_register(struct vreg* vreg, struct hreg* s
|
||||||
array_append(&hregs, hreg);
|
array_append(&hregs, hreg);
|
||||||
|
|
||||||
found:
|
found:
|
||||||
tracef('R', "R: evicted %%%d moving to %s\n", vreg->id, hreg->name);
|
tracef('R', "R: evicted %%%d moving to %s\n", vreg->id, hreg->id);
|
||||||
pmap_add(current_ins, hreg, vreg);
|
pmap_add(current_ins, hreg, vreg);
|
||||||
pmap_add(current_outs, hreg, vreg);
|
pmap_add(current_outs, hreg, vreg);
|
||||||
}
|
}
|
||||||
|
@ -452,7 +485,7 @@ static void assign_hregs_to_vregs(void)
|
||||||
if (hreg)
|
if (hreg)
|
||||||
{
|
{
|
||||||
tracef('R', "R: import hreg %s for input %%%d from %s\n",
|
tracef('R', "R: import hreg %s for input %%%d from %s\n",
|
||||||
hreg->name, vreg->id, prevbb->name);
|
hreg->id, vreg->id, prevbb->name);
|
||||||
assert(!pmap_findleft(old, hreg));
|
assert(!pmap_findleft(old, hreg));
|
||||||
pmap_put(old, hreg, vreg);
|
pmap_put(old, hreg, vreg);
|
||||||
goto nextvreg;
|
goto nextvreg;
|
||||||
|
@ -482,7 +515,7 @@ static void assign_hregs_to_vregs(void)
|
||||||
if (hreg && !pmap_findleft(old, hreg))
|
if (hreg && !pmap_findleft(old, hreg))
|
||||||
{
|
{
|
||||||
tracef('R', "R: import hreg %s for phi input %%%d from %s\n",
|
tracef('R', "R: import hreg %s for phi input %%%d from %s\n",
|
||||||
hreg->name, vreg->id, phi->prev->name);
|
hreg->id, vreg->id, phi->prev->name);
|
||||||
pmap_put(old, hreg, vreg);
|
pmap_put(old, hreg, vreg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -503,7 +536,7 @@ static void assign_hregs_to_vregs(void)
|
||||||
struct hreg* hreg = allocate_phi_hreg(old, vreg, c->type);
|
struct hreg* hreg = allocate_phi_hreg(old, vreg, c->type);
|
||||||
|
|
||||||
tracef('R', "R: import fallback hreg %s for phi input %%%d from %s\n",
|
tracef('R', "R: import fallback hreg %s for phi input %%%d from %s\n",
|
||||||
hreg->name, vreg->id, phi->prev->name);
|
hreg->id, vreg->id, phi->prev->name);
|
||||||
pmap_add(old, hreg, vreg);
|
pmap_add(old, hreg, vreg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -525,7 +558,7 @@ static void assign_hregs_to_vregs(void)
|
||||||
struct vreg* vreg = hop->regsin.item[k].right;
|
struct vreg* vreg = hop->regsin.item[k].right;
|
||||||
if (k != 0)
|
if (k != 0)
|
||||||
tracef('R', " ");
|
tracef('R', " ");
|
||||||
tracef('R', "%%%d=>%s", vreg->id, hreg->name);
|
tracef('R', "%%%d=>%s", vreg->id, hreg->id);
|
||||||
}
|
}
|
||||||
tracef('R', "] [");
|
tracef('R', "] [");
|
||||||
for (k=0; k<hop->regsout.count; k++)
|
for (k=0; k<hop->regsout.count; k++)
|
||||||
|
@ -534,7 +567,7 @@ static void assign_hregs_to_vregs(void)
|
||||||
struct vreg* vreg = hop->regsout.item[k].right;
|
struct vreg* vreg = hop->regsout.item[k].right;
|
||||||
if (k != 0)
|
if (k != 0)
|
||||||
tracef('R', " ");
|
tracef('R', " ");
|
||||||
tracef('R', "%%%d=>%s", vreg->id, hreg->name);
|
tracef('R', "%%%d=>%s", vreg->id, hreg->id);
|
||||||
}
|
}
|
||||||
tracef('R', "]\n");
|
tracef('R', "]\n");
|
||||||
|
|
||||||
|
@ -551,9 +584,9 @@ static struct hop* create_swap(struct basicblock* bb, struct hreg* src, struct h
|
||||||
struct hop* hop = new_hop(bb, NULL);
|
struct hop* hop = new_hop(bb, NULL);
|
||||||
|
|
||||||
hop_add_string_insel(hop, "! swap ");
|
hop_add_string_insel(hop, "! swap ");
|
||||||
hop_add_hreg_insel(hop, src);
|
hop_add_hreg_insel(hop, src, 0);
|
||||||
hop_add_string_insel(hop, " <-> ");
|
hop_add_string_insel(hop, " <-> ");
|
||||||
hop_add_hreg_insel(hop, dest);
|
hop_add_hreg_insel(hop, dest, 0);
|
||||||
hop_add_eoi_insel(hop);
|
hop_add_eoi_insel(hop);
|
||||||
|
|
||||||
return hop;
|
return hop;
|
||||||
|
@ -661,7 +694,7 @@ static void insert_phi_copies(void)
|
||||||
|
|
||||||
tracef('R', "R: map %%%d -> %%%d (%s)\n",
|
tracef('R', "R: map %%%d -> %%%d (%s)\n",
|
||||||
phi->ir->result->id,
|
phi->ir->result->id,
|
||||||
vreg->id, dest->name);
|
vreg->id, dest->id);
|
||||||
|
|
||||||
pmap_put(&destregs, dest, phi->ir->result);
|
pmap_put(&destregs, dest, phi->ir->result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,12 @@ struct vreg* new_vreg(void)
|
||||||
struct hreg* new_hreg(const struct burm_register_data* brd)
|
struct hreg* new_hreg(const struct burm_register_data* brd)
|
||||||
{
|
{
|
||||||
struct hreg* hreg = calloc(1, sizeof *hreg);
|
struct hreg* hreg = calloc(1, sizeof *hreg);
|
||||||
hreg->name = brd->name;
|
hreg->id = brd->id;
|
||||||
hreg->realname = brd->realname;
|
hreg->brd = brd;
|
||||||
hreg->type = brd->type;
|
hreg->type = brd->type;
|
||||||
hreg->attrs = brd->attrs;
|
hreg->attrs = brd->attrs;
|
||||||
hreg->is_stacked = false;
|
hreg->is_stacked = false;
|
||||||
|
/* The aliases array needs to be initialised later. */
|
||||||
return hreg;
|
return hreg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,12 +25,12 @@ struct hreg* new_stacked_hreg(uint32_t type)
|
||||||
{
|
{
|
||||||
static int hreg_count = 1;
|
static int hreg_count = 1;
|
||||||
struct hreg* hreg = calloc(1, sizeof *hreg);
|
struct hreg* hreg = calloc(1, sizeof *hreg);
|
||||||
hreg->name = aprintf("stacked_%d_id_%d", type, hreg_count++);
|
hreg->id = aprintf("stacked_%d_id_%d", type, hreg_count++);
|
||||||
hreg->realname = hreg->name;
|
|
||||||
hreg->type = type;
|
hreg->type = type;
|
||||||
hreg->attrs = type;
|
hreg->attrs = type;
|
||||||
hreg->is_stacked = true;
|
hreg->is_stacked = true;
|
||||||
hreg->offset = -1;
|
hreg->offset = -1;
|
||||||
|
array_append(&hreg->aliases, hreg);
|
||||||
return hreg;
|
return hreg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,13 @@ struct phicongruence
|
||||||
|
|
||||||
struct hreg
|
struct hreg
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* id;
|
||||||
const char* realname;
|
const struct burm_register_data* brd;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t attrs;
|
uint32_t attrs;
|
||||||
bool is_stacked;
|
bool is_stacked;
|
||||||
int offset;
|
int offset;
|
||||||
|
ARRAYOF(struct hreg) aliases;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vreg
|
struct vreg
|
||||||
|
|
|
@ -495,6 +495,16 @@ static void insn_ivalue(int opcode, arith value)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case op_sdl:
|
||||||
|
appendir(
|
||||||
|
new_ir2(
|
||||||
|
IR_STORE, EM_wordsize*2,
|
||||||
|
new_localir(value),
|
||||||
|
pop(EM_wordsize*2)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case op_lal:
|
case op_lal:
|
||||||
push(
|
push(
|
||||||
new_localir(value)
|
new_localir(value)
|
||||||
|
@ -972,6 +982,15 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case op_lde:
|
||||||
|
push(
|
||||||
|
new_ir1(
|
||||||
|
IR_LOAD, EM_wordsize*2,
|
||||||
|
address_of_external(label, offset)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case op_ste:
|
case op_ste:
|
||||||
appendir(
|
appendir(
|
||||||
new_ir2(
|
new_ir2(
|
||||||
|
@ -982,6 +1001,16 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case op_sde:
|
||||||
|
appendir(
|
||||||
|
new_ir2(
|
||||||
|
IR_STORE, EM_wordsize*2,
|
||||||
|
address_of_external(label, offset),
|
||||||
|
pop(EM_wordsize*2)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case op_zre:
|
case op_zre:
|
||||||
appendir(
|
appendir(
|
||||||
new_ir2(
|
new_ir2(
|
||||||
|
|
|
@ -33,6 +33,7 @@ extern int yylex(void);
|
||||||
%term EMIT
|
%term EMIT
|
||||||
%term EQUALS
|
%term EQUALS
|
||||||
%term FRAGMENT
|
%term FRAGMENT
|
||||||
|
%term NAMED
|
||||||
%term NOTEQUALS
|
%term NOTEQUALS
|
||||||
%term PATTERNS
|
%term PATTERNS
|
||||||
%term PREFERS
|
%term PREFERS
|
||||||
|
@ -44,7 +45,6 @@ extern int yylex(void);
|
||||||
%token <string> ID
|
%token <string> ID
|
||||||
%token <string> QFRAGMENT
|
%token <string> QFRAGMENT
|
||||||
|
|
||||||
%type <stringlist> aliases;
|
|
||||||
%type <constraint> constraint
|
%type <constraint> constraint
|
||||||
%type <constraint> constraints
|
%type <constraint> constraints
|
||||||
%type <expr> predicate
|
%type <expr> predicate
|
||||||
|
@ -55,6 +55,8 @@ extern int yylex(void);
|
||||||
%type <rule> pattern
|
%type <rule> pattern
|
||||||
%type <rule> pattern_constraints
|
%type <rule> pattern_constraints
|
||||||
%type <rule> pattern_emit
|
%type <rule> pattern_emit
|
||||||
|
%type <stringlist> aliases;
|
||||||
|
%type <stringlist> names;
|
||||||
%type <stringlist> qfragments
|
%type <stringlist> qfragments
|
||||||
%type <terminfo> terminfo
|
%type <terminfo> terminfo
|
||||||
%type <tree> rhs
|
%type <tree> rhs
|
||||||
|
@ -73,12 +75,18 @@ registers
|
||||||
;
|
;
|
||||||
|
|
||||||
register
|
register
|
||||||
: ID QFRAGMENT { $$ = makereg($1, $2); }
|
: ID { $$ = makereg($1); }
|
||||||
|
| register NAMED '(' names ')' { $$ = $1; setregnames($$, $4); }
|
||||||
| register ALIASES '(' aliases ')' { $$ = $1; addregaliases($$, $4); }
|
| register ALIASES '(' aliases ')' { $$ = $1; addregaliases($$, $4); }
|
||||||
| register ID { $$ = $1; addregattr($1, $2, false); }
|
| register ID { $$ = $1; addregattr($1, $2, false); }
|
||||||
| register ID '!' { $$ = $1; addregattr($1, $2, true); }
|
| register ID '!' { $$ = $1; addregattr($1, $2, true); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
names
|
||||||
|
: QFRAGMENT { $$ = calloc(1, sizeof(*$$)); stringlist_add($$, $1); }
|
||||||
|
| names ',' QFRAGMENT { $$ = $1; stringlist_add($$, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
aliases
|
aliases
|
||||||
: ID { $$ = calloc(1, sizeof(*$$)); stringlist_add($$, $1); }
|
: ID { $$ = calloc(1, sizeof(*$$)); stringlist_add($$, $1); }
|
||||||
| aliases ',' ID { $$ = $1; stringlist_add($$, $3); }
|
| aliases ',' ID { $$ = $1; stringlist_add($$, $3); }
|
||||||
|
|
|
@ -268,7 +268,7 @@ static void* install(const char* name)
|
||||||
return &p->sym;
|
return &p->sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct reg* makereg(const char* id, const char* realname)
|
struct reg* makereg(const char* id)
|
||||||
{
|
{
|
||||||
struct reg* p = smap_get(®isters, id);
|
struct reg* p = smap_get(®isters, id);
|
||||||
static int number = 0;
|
static int number = 0;
|
||||||
|
@ -277,7 +277,6 @@ struct reg* makereg(const char* id, const char* realname)
|
||||||
yyerror("redefinition of '%s'", id);
|
yyerror("redefinition of '%s'", id);
|
||||||
p = calloc(1, sizeof(*p));
|
p = calloc(1, sizeof(*p));
|
||||||
p->name = id;
|
p->name = id;
|
||||||
p->realname = realname;
|
|
||||||
p->number = number++;
|
p->number = number++;
|
||||||
array_append(&p->aliases, p);
|
array_append(&p->aliases, p);
|
||||||
smap_put(®isters, id, p);
|
smap_put(®isters, id, p);
|
||||||
|
@ -285,6 +284,14 @@ struct reg* makereg(const char* id, const char* realname)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setregnames(struct reg* reg, struct stringlist* names)
|
||||||
|
{
|
||||||
|
if (reg->names)
|
||||||
|
yyerror("you can only set one set of register names");
|
||||||
|
|
||||||
|
reg->names = names;
|
||||||
|
}
|
||||||
|
|
||||||
struct regattr* makeregattr(const char* id)
|
struct regattr* makeregattr(const char* id)
|
||||||
{
|
{
|
||||||
struct regattr* p = smap_get(®isterattrs, id);
|
struct regattr* p = smap_get(®isterattrs, id);
|
||||||
|
@ -629,14 +636,33 @@ static void emitregisters(void)
|
||||||
print("NULL\n};\n");
|
print("NULL\n};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i=0; i<registers.count; i++)
|
||||||
|
{
|
||||||
|
struct reg* r = registers.item[i].right;
|
||||||
|
|
||||||
|
print("const char* %Pregister_names_%d_%s[] = {\n%1", i, r->name);
|
||||||
|
if (r->names)
|
||||||
|
{
|
||||||
|
struct stringfragment* f = r->names->first;
|
||||||
|
while (f)
|
||||||
|
{
|
||||||
|
print("\"%s\", ", f->data);
|
||||||
|
f = f->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
print("\"%s\", ", r->name);
|
||||||
|
print("NULL\n};\n");
|
||||||
|
}
|
||||||
|
|
||||||
print("const struct %Pregister_data %Pregister_data[] = {\n");
|
print("const struct %Pregister_data %Pregister_data[] = {\n");
|
||||||
for (i=0; i<registers.count; i++)
|
for (i=0; i<registers.count; i++)
|
||||||
{
|
{
|
||||||
struct reg* r = registers.item[i].right;
|
struct reg* r = registers.item[i].right;
|
||||||
assert(r->number == i);
|
assert(r->number == i);
|
||||||
|
|
||||||
print("%1{ \"%s\", \"%s\", 0x%x, 0x%x, %Pregister_aliases_%d_%s },\n",
|
print("%1{ \"%s\", 0x%x, 0x%x, %Pregister_names_%d_%s, %Pregister_aliases_%d_%s },\n",
|
||||||
r->name, r->realname, r->type, r->attrs, i, r->name);
|
r->name, r->type, r->attrs, i, r->name, i, r->name);
|
||||||
}
|
}
|
||||||
print("%1{ NULL }\n");
|
print("%1{ NULL }\n");
|
||||||
print("};\n\n");
|
print("};\n\n");
|
||||||
|
@ -1215,14 +1241,18 @@ static void emitinsndata(Rule rules)
|
||||||
|
|
||||||
while (f)
|
while (f)
|
||||||
{
|
{
|
||||||
switch (f->data[0])
|
char* data = strdup(f->data);
|
||||||
|
int type = *data++;
|
||||||
|
char* label = strtok(data, ".");
|
||||||
|
char* nameindex_s = strtok(NULL, ".");
|
||||||
|
int nameindex = nameindex_s ? atoi(nameindex_s) : 0;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
{
|
{
|
||||||
case '%':
|
case '%':
|
||||||
{
|
{
|
||||||
const char* label = f->data + 1;
|
|
||||||
|
|
||||||
if (r->label && (strcmp(label, r->label) == 0))
|
if (r->label && (strcmp(label, r->label) == 0))
|
||||||
print("%1data->emit_return_reg();\n", label);
|
print("%1data->emit_return_reg(%d);\n", nameindex);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Tree node;
|
Tree node;
|
||||||
|
@ -1234,25 +1264,25 @@ static void emitinsndata(Rule rules)
|
||||||
if (nt->kind == NONTERM)
|
if (nt->kind == NONTERM)
|
||||||
{
|
{
|
||||||
if (nt->is_fragment)
|
if (nt->is_fragment)
|
||||||
print("%1data->emit_fragment(");
|
print("%1data->emit_fragment(%d);\n", index);
|
||||||
else
|
else
|
||||||
print("%1data->emit_reg(");
|
print("%1data->emit_reg(%d, %d);\n", index, nameindex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
print("%1data->emit_reg(");
|
print("%1data->emit_reg(%d, %d);\n", index, nameindex);
|
||||||
|
|
||||||
print("%d);\n", index);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case '$':
|
case '$':
|
||||||
{
|
{
|
||||||
const char* label = f->data + 1;
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
if (!find_child_index(r->pattern, label, &index, NULL))
|
if (!find_child_index(r->pattern, label, &index, NULL))
|
||||||
label_not_found(r, label);
|
label_not_found(r, label);
|
||||||
|
|
||||||
|
if (nameindex != 0)
|
||||||
|
yyerror("indices other than 0 make no sense for $-values");
|
||||||
|
|
||||||
print("%1data->emit_value(%d);\n", index);
|
print("%1data->emit_value(%d);\n", index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,10 +59,10 @@ struct terminfo
|
||||||
struct reg
|
struct reg
|
||||||
{
|
{
|
||||||
const char* name; /* friendly register name */
|
const char* name; /* friendly register name */
|
||||||
const char* realname; /* name used in assembly output */
|
|
||||||
int number; /* identifying number */
|
int number; /* identifying number */
|
||||||
uint32_t attrs; /* bitfield of register attributes */
|
uint32_t attrs; /* bitfield of register attributes */
|
||||||
uint32_t type; /* register type */
|
uint32_t type; /* register type */
|
||||||
|
struct stringlist* names; /* register names */
|
||||||
ARRAYOF(struct reg) aliases; /* registers that this one aliases */
|
ARRAYOF(struct reg) aliases; /* registers that this one aliases */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,7 +72,8 @@ struct regattr
|
||||||
int number; /* identifying number */
|
int number; /* identifying number */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct reg* makereg(const char* name, const char* realname);
|
extern struct reg* makereg(const char* name);
|
||||||
|
extern void setregnames(struct reg* reg, struct stringlist* names);
|
||||||
extern void addregattr(struct reg* reg, const char* regattr, bool exact);
|
extern void addregattr(struct reg* reg, const char* regattr, bool exact);
|
||||||
extern void addregaliases(struct reg* reg, struct stringlist* aliases);
|
extern void addregaliases(struct reg* reg, struct stringlist* aliases);
|
||||||
extern struct regattr* getregattr(const char* name);
|
extern struct regattr* getregattr(const char* name);
|
||||||
|
|
|
@ -23,6 +23,7 @@ S POPF
|
||||||
S LOAD # must be followed by float form
|
S LOAD # must be followed by float form
|
||||||
S LOADF
|
S LOADF
|
||||||
S STORE
|
S STORE
|
||||||
|
S STOREF
|
||||||
|
|
||||||
# Arithemetic operations
|
# Arithemetic operations
|
||||||
S ADD
|
S ADD
|
||||||
|
|
|
@ -40,8 +40,8 @@ struct burm_emitter_data
|
||||||
{
|
{
|
||||||
void (*emit_string)(const char* data);
|
void (*emit_string)(const char* data);
|
||||||
void (*emit_fragment)(int child);
|
void (*emit_fragment)(int child);
|
||||||
void (*emit_return_reg)(void);
|
void (*emit_return_reg)(int index);
|
||||||
void (*emit_reg)(int child);
|
void (*emit_reg)(int child, int index);
|
||||||
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);
|
||||||
|
@ -63,10 +63,10 @@ extern const struct burm_instruction_data burm_instruction_data[];
|
||||||
|
|
||||||
struct burm_register_data
|
struct burm_register_data
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* id;
|
||||||
const char* realname;
|
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t attrs;
|
uint32_t attrs;
|
||||||
|
const char** names;
|
||||||
const struct burm_register_data** aliases;
|
const struct burm_register_data** aliases;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ static int braces = 0;
|
||||||
<INITIAL>"\"" BEGIN(QSTRING);
|
<INITIAL>"\"" BEGIN(QSTRING);
|
||||||
<QSTRING>"\"" BEGIN(INITIAL);
|
<QSTRING>"\"" BEGIN(INITIAL);
|
||||||
|
|
||||||
<QSTRING>[%$][a-zA-Z_][a-zA_Z_0-9]+ {
|
<QSTRING>[%$][a-zA-Z_][a-zA_Z_0-9]+(\.[0-9]+)? {
|
||||||
yylval.string = strdup(yytext);
|
yylval.string = strdup(yytext);
|
||||||
return QFRAGMENT;
|
return QFRAGMENT;
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ static int braces = 0;
|
||||||
"cost" return COST;
|
"cost" return COST;
|
||||||
"emit" return EMIT;
|
"emit" return EMIT;
|
||||||
"fragment" return FRAGMENT;
|
"fragment" return FRAGMENT;
|
||||||
|
"named" return NAMED;
|
||||||
"prefers" return PREFERS;
|
"prefers" return PREFERS;
|
||||||
"when" return WHEN;
|
"when" return WHEN;
|
||||||
"with" return WITH;
|
"with" return WITH;
|
||||||
|
|
Loading…
Reference in a new issue