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:
David Given 2016-10-21 23:31:00 +02:00
parent d6984d60ac
commit 4db402f229
16 changed files with 422 additions and 161 deletions

View file

@ -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;
} }

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;
} }
} }

View file

@ -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);
} }

View file

@ -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;
} }

View file

@ -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

View file

@ -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(

View file

@ -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); }

View file

@ -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(&registers, id); struct reg* p = smap_get(&registers, 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(&registers, id, p); smap_put(&registers, 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(&registerattrs, id); struct regattr* p = smap_get(&registerattrs, 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;
} }

View file

@ -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);

View file

@ -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

View file

@ -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;
}; };

View file

@ -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;