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* 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)
hop_add_insel(hop, "stw %H, %S(fp) ! %H", src, dest, dest);
else if (src->type & burm_float_ATTR)
hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest);
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
assert(!src->is_stacked);
assert(!dest->is_stacked);
switch (src->type & type_attrs)
{
if (src->type & burm_int_ATTR)
case burm_int_ATTR:
hop_add_insel(hop, "stwu %H, -4(sp)", src);
else if (src->type & burm_float_ATTR)
hop_add_insel(hop, "stfsu %H, -4(sp)", src);
else
assert(false);
break;
if (dest->type & burm_int_ATTR)
hop_add_insel(hop, "lwz %H, 0(sp)", dest);
else if (dest->type & burm_float_ATTR)
hop_add_insel(hop, "lfs %H, 0(sp)", dest);
else
case burm_float_ATTR:
hop_add_insel(hop, "stfsu %H, -4(sp)", src);
break;
case burm_double_ATTR:
hop_add_insel(hop, "stfdu %H, -8(sp)", src);
break;
default:
assert(false);
hop_add_insel(hop, "addi sp, sp, 4");
}
}
else
fatal("cannot generate move from %s to %s", src->name, dest->name);
switch (dest->type & type_attrs)
{
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;
}

View file

@ -7,71 +7,122 @@ REGISTERS
* a register into another register (e.g. for eviction).
*/
r12 "r12" bytes4! int! volatile;
r11 "r11" bytes4! int! volatile;
r10 "r10" bytes4! int! volatile;
r9 "r9" bytes4! int! volatile;
r8 "r8" bytes4! int! volatile;
r7 "r7" bytes4! int! volatile;
r6 "r6" bytes4! int! volatile;
r5 "r5" bytes4! int! volatile;
r4 "r4" bytes4! int! volatile;
r3 "r3" bytes4! int! volatile ret;
r12 bytes4! int! volatile;
r11 bytes4! int! volatile;
r10 bytes4! int! volatile;
r9 bytes4! int! volatile;
r8 bytes4! int! volatile;
r7 bytes4! int! volatile;
r6 bytes4! int! volatile;
r5 bytes4! int! volatile;
r4 bytes4! int! volatile;
r3 bytes4! int! volatile ret;
r31 "r31" bytes4! int!;
r30 "r30" bytes4! int!;
r29 "r29" bytes4! int!;
r28 "r28" bytes4! int!;
r27 "r27" bytes4! int!;
r26 "r26" bytes4! int!;
r25 "r25" bytes4! int!;
r24 "r24" bytes4! int!;
r23 "r23" bytes4! int!;
r22 "r22" bytes4! int!;
r21 "r21" bytes4! int!;
r20 "r20" bytes4! int!;
r19 "r19" bytes4! int!;
r18 "r18" bytes4! int!;
r17 "r17" bytes4! int!;
r16 "r16" bytes4! int!;
r15 "r15" bytes4! int!;
r14 "r14" bytes4! int!;
r31 bytes4! int!;
r30 bytes4! int!;
r29 bytes4! int!;
r28 bytes4! int!;
r27 bytes4! int!;
r26 bytes4! int!;
r25 bytes4! int!;
r24 bytes4! int!;
r23 bytes4! int!;
r22 bytes4! int!;
r21 bytes4! int!;
r20 bytes4! int!;
r19 bytes4! int!;
r18 bytes4! int!;
r17 bytes4! int!;
r16 bytes4! int!;
r15 bytes4! int!;
r14 bytes4! int!;
r13 bytes4! int!;
f14 "f14" bytes4! float! volatile;
f13 "f13" bytes4! float! volatile;
f12 "f12" bytes4! float! volatile;
f11 "f11" bytes4! float! volatile;
f10 "f10" bytes4! float! volatile;
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;
r11r12 named("r11", "r12") aliases(r11, r12) bytes8! pair! volatile;
r9r10 named("r9", "r10") aliases(r9, r10) bytes8! pair! volatile;
r7r8 named("r7", "r8") aliases(r7, r8) bytes8! pair! volatile;
r5r6 named("r5", "r6") aliases(r6, r6) bytes8! pair! volatile;
r3r4 named("r3", "r4") aliases(r3, r4) bytes8! pair! volatile pret;
f31 "f31" bytes4! float!;
f30 "f30" bytes4! float!;
f29 "f29" bytes4! float!;
f28 "f28" bytes4! float!;
f27 "f27" bytes4! float!;
f26 "f26" bytes4! float!;
f25 "f25" bytes4! float!;
f24 "f24" bytes4! float!;
f23 "f23" bytes4! float!;
f22 "f22" bytes4! float!;
f21 "f21" bytes4! float!;
f20 "f20" bytes4! float!;
f19 "f19" bytes4! float!;
f18 "f18" bytes4! float!;
f17 "f17" bytes4! float!;
f16 "f16" bytes4! float!;
f15 "f15" bytes4! float!;
r29r30 named("r29", "r30") aliases(r29, r30) bytes8! pair!;
r27r28 named("r27", "r28") aliases(r27, r28) bytes8! pair!;
r25r26 named("r25", "r26") aliases(r25, r26) bytes8! pair!;
r23r24 named("r23", "r24") aliases(r23, r24) bytes8! pair!;
r21r22 named("r21", "r22") aliases(r21, r22) bytes8! pair!;
r19r20 named("r19", "r20") aliases(r19, r20) bytes8! pair!;
r17r18 named("r17", "r18") aliases(r17, r18) bytes8! pair!;
r15r16 named("r15", "r16") aliases(r15, r16) bytes8! pair!;
r13r14 named("r13", "r14") aliases(r13, r14) bytes8! pair!;
cr0 "cr0" cr!;
f14 bytes4! float! volatile;
f13 bytes4! float! volatile;
f12 bytes4! float! volatile;
f11 bytes4! float! volatile;
f10 bytes4! float! volatile;
f9 bytes4! float! volatile;
f8 bytes4! float! volatile;
f7 bytes4! float! volatile;
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)"
cost 4;
PUSH8(in:(pair)reg)
emit "stwu %in.0, -4(sp)"
emit "stwu %in.1, -4(sp)"
cost 8;
out:(int)reg = POP4
emit "lwz %out, 0(sp)"
emit "addi sp, sp, 4"
@ -113,12 +169,20 @@ PATTERNS
SETRET4(in:(ret)reg)
emit "! setret4"
cost 4;
cost 1;
SETRET8(in:(pret)reg)
emit "! setret8"
cost 1;
(ret)reg = GETRET4
emit "! getret4"
cost 1;
(pret)reg = GETRET8
emit "! getret8"
cost 1;
STACKADJUST4(delta:CONST4)
when signed_constant(%delta, 16)
emit "addi sp, sp, $delta"
@ -142,6 +206,11 @@ PATTERNS
/* 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)
emit "stw %value, %addr"
cost 4;
@ -168,6 +237,11 @@ PATTERNS
emit "lwz %out, %addr"
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)
emit "lhz %out, %addr"
cost 4;
@ -480,6 +554,10 @@ PATTERNS
emit "lfs %out, %addr"
cost 4;
out:(double)reg = LOADF8(addr:address)
emit "lfd %out, %addr"
cost 4;
out:(float)reg = value:CONSTF4
emit "lfs %out, address-containing-$value"
cost 8;
@ -488,6 +566,10 @@ PATTERNS
emit "fadds %out, %left, %right"
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)
emit "fsubs %out, %left, %right"
cost 4;

View file

@ -31,17 +31,19 @@ void hop_add_string_insel(struct hop* hop, const char* string)
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);
insel->u.hreg = hreg;
insel->index = index;
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);
insel->u.vreg = vreg;
insel->index = index;
array_append(&hop->insels, insel);
}
@ -108,11 +110,11 @@ void hop_add_insel(struct hop* hop, const char* fmt, ...)
break;
case 'H':
hop_add_hreg_insel(hop, va_arg(ap, struct hreg*));
hop_add_hreg_insel(hop, va_arg(ap, struct hreg*), 0);
break;
case 'V':
hop_add_vreg_insel(hop, va_arg(ap, struct vreg*));
hop_add_vreg_insel(hop, va_arg(ap, struct vreg*), 0);
break;
}
}
@ -205,7 +207,7 @@ char* hop_render(struct hop* hop)
case INSEL_HREG:
{
struct hreg* hreg = insel->u.hreg;
appendf("%s", hreg->realname);
appendf("%s", hreg->brd->names[insel->index]);
break;
}
@ -216,7 +218,7 @@ char* hop_render(struct hop* hop)
if (!hreg)
hreg = pmap_findright(&hop->regsout, vreg);
if (hreg)
appendf("%s", hreg->realname);
appendf("%s", hreg->brd->names[insel->index]);
else
appendf("%%%d", vreg->id);
break;

View file

@ -16,6 +16,7 @@ enum insel_type
struct insel
{
enum insel_type type;
int index;
union
{
const char* string;
@ -54,8 +55,8 @@ struct hop
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_hreg_insel(struct hop* hop, struct hreg* hreg);
extern void hop_add_vreg_insel(struct hop* hop, struct vreg* vreg);
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, int index);
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_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);
}
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)
@ -47,13 +47,13 @@ static struct vreg* find_vreg_of_child(int child)
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);
if (vreg)
{
hop_add_vreg_insel(current_hop, vreg);
hop_add_vreg_insel(current_hop, vreg, index);
array_appendu(&vreg->used, current_hop);
}
}
@ -109,7 +109,7 @@ static uint32_t find_type_from_constraint(uint32_t attr)
* this. */
const struct burm_register_data* brd = burm_register_data;
while (brd->name)
while (brd->id)
{
if (brd->attrs & attr)
return brd->type;

View file

@ -48,7 +48,7 @@ static void promote(struct ir* ir)
{
int 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;
}
}

View file

@ -20,14 +20,30 @@ static bool type_match(struct hreg* hreg, struct vreg* vreg);
static void populate_hregs(void)
{
int i;
const struct burm_register_data* brd = burm_register_data;
hregs.count = 0;
while (brd->name)
while (brd->id)
{
array_append(&hregs, new_hreg(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)
@ -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,
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++)
{
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. */
return hreg;
@ -86,7 +116,10 @@ static struct hreg* evict(struct vreg* 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.
* Shouldn't really happen in real life. */
@ -95,7 +128,7 @@ static struct hreg* evict(struct vreg* vreg)
if (candidatein == candidateout)
{
/* 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_remove(current_ins, 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)
{
return !pmap_findleft(current_ins, hreg) &&
return !register_used(current_ins, hreg) &&
type_match(hreg, 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) &&
!(hreg->attrs & current_hop->insndata->corrupts);
}
@ -295,7 +328,7 @@ static void add_output_register(struct vreg* vreg)
pmap_add(current_outs, hreg, vreg);
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);
}
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
* 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_remove(current_ins, 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);
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_outs, hreg, vreg);
}
@ -452,7 +485,7 @@ static void assign_hregs_to_vregs(void)
if (hreg)
{
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));
pmap_put(old, hreg, vreg);
goto nextvreg;
@ -482,7 +515,7 @@ static void assign_hregs_to_vregs(void)
if (hreg && !pmap_findleft(old, hreg))
{
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);
}
}
@ -503,7 +536,7 @@ static void assign_hregs_to_vregs(void)
struct hreg* hreg = allocate_phi_hreg(old, vreg, c->type);
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);
}
}
@ -525,7 +558,7 @@ static void assign_hregs_to_vregs(void)
struct vreg* vreg = hop->regsin.item[k].right;
if (k != 0)
tracef('R', " ");
tracef('R', "%%%d=>%s", vreg->id, hreg->name);
tracef('R', "%%%d=>%s", vreg->id, hreg->id);
}
tracef('R', "] [");
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;
if (k != 0)
tracef('R', " ");
tracef('R', "%%%d=>%s", vreg->id, hreg->name);
tracef('R', "%%%d=>%s", vreg->id, hreg->id);
}
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);
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_hreg_insel(hop, dest);
hop_add_hreg_insel(hop, dest, 0);
hop_add_eoi_insel(hop);
return hop;
@ -661,7 +694,7 @@ static void insert_phi_copies(void)
tracef('R', "R: map %%%d -> %%%d (%s)\n",
phi->ir->result->id,
vreg->id, dest->name);
vreg->id, dest->id);
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* hreg = calloc(1, sizeof *hreg);
hreg->name = brd->name;
hreg->realname = brd->realname;
hreg->id = brd->id;
hreg->brd = brd;
hreg->type = brd->type;
hreg->attrs = brd->attrs;
hreg->is_stacked = false;
/* The aliases array needs to be initialised later. */
return hreg;
}
@ -24,12 +25,12 @@ struct hreg* new_stacked_hreg(uint32_t type)
{
static int hreg_count = 1;
struct hreg* hreg = calloc(1, sizeof *hreg);
hreg->name = aprintf("stacked_%d_id_%d", type, hreg_count++);
hreg->realname = hreg->name;
hreg->id = aprintf("stacked_%d_id_%d", type, hreg_count++);
hreg->type = type;
hreg->attrs = type;
hreg->is_stacked = true;
hreg->offset = -1;
array_append(&hreg->aliases, hreg);
return hreg;
}

View file

@ -13,12 +13,13 @@ struct phicongruence
struct hreg
{
const char* name;
const char* realname;
const char* id;
const struct burm_register_data* brd;
uint32_t type;
uint32_t attrs;
bool is_stacked;
int offset;
ARRAYOF(struct hreg) aliases;
};
struct vreg

View file

@ -495,6 +495,16 @@ static void insn_ivalue(int opcode, arith value)
);
break;
case op_sdl:
appendir(
new_ir2(
IR_STORE, EM_wordsize*2,
new_localir(value),
pop(EM_wordsize*2)
)
);
break;
case op_lal:
push(
new_localir(value)
@ -972,6 +982,15 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
);
break;
case op_lde:
push(
new_ir1(
IR_LOAD, EM_wordsize*2,
address_of_external(label, offset)
)
);
break;
case op_ste:
appendir(
new_ir2(
@ -982,6 +1001,16 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
);
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:
appendir(
new_ir2(

View file

@ -33,6 +33,7 @@ extern int yylex(void);
%term EMIT
%term EQUALS
%term FRAGMENT
%term NAMED
%term NOTEQUALS
%term PATTERNS
%term PREFERS
@ -44,7 +45,6 @@ extern int yylex(void);
%token <string> ID
%token <string> QFRAGMENT
%type <stringlist> aliases;
%type <constraint> constraint
%type <constraint> constraints
%type <expr> predicate
@ -55,6 +55,8 @@ extern int yylex(void);
%type <rule> pattern
%type <rule> pattern_constraints
%type <rule> pattern_emit
%type <stringlist> aliases;
%type <stringlist> names;
%type <stringlist> qfragments
%type <terminfo> terminfo
%type <tree> rhs
@ -73,12 +75,18 @@ registers
;
register
: ID QFRAGMENT { $$ = makereg($1, $2); }
: ID { $$ = makereg($1); }
| register NAMED '(' names ')' { $$ = $1; setregnames($$, $4); }
| register ALIASES '(' aliases ')' { $$ = $1; addregaliases($$, $4); }
| register ID { $$ = $1; addregattr($1, $2, false); }
| register ID '!' { $$ = $1; addregattr($1, $2, true); }
;
names
: QFRAGMENT { $$ = calloc(1, sizeof(*$$)); stringlist_add($$, $1); }
| names ',' QFRAGMENT { $$ = $1; stringlist_add($$, $3); }
;
aliases
: ID { $$ = calloc(1, sizeof(*$$)); stringlist_add($$, $1); }
| aliases ',' ID { $$ = $1; stringlist_add($$, $3); }

View file

@ -268,7 +268,7 @@ static void* install(const char* name)
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);
static int number = 0;
@ -277,7 +277,6 @@ struct reg* makereg(const char* id, const char* realname)
yyerror("redefinition of '%s'", id);
p = calloc(1, sizeof(*p));
p->name = id;
p->realname = realname;
p->number = number++;
array_append(&p->aliases, p);
smap_put(&registers, id, p);
@ -285,6 +284,14 @@ struct reg* makereg(const char* id, const char* realname)
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* p = smap_get(&registerattrs, id);
@ -629,14 +636,33 @@ static void emitregisters(void)
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");
for (i=0; i<registers.count; i++)
{
struct reg* r = registers.item[i].right;
assert(r->number == i);
print("%1{ \"%s\", \"%s\", 0x%x, 0x%x, %Pregister_aliases_%d_%s },\n",
r->name, r->realname, r->type, r->attrs, i, r->name);
print("%1{ \"%s\", 0x%x, 0x%x, %Pregister_names_%d_%s, %Pregister_aliases_%d_%s },\n",
r->name, r->type, r->attrs, i, r->name, i, r->name);
}
print("%1{ NULL }\n");
print("};\n\n");
@ -1215,14 +1241,18 @@ static void emitinsndata(Rule rules)
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 '%':
{
const char* label = f->data + 1;
if (r->label && (strcmp(label, r->label) == 0))
print("%1data->emit_return_reg();\n", label);
print("%1data->emit_return_reg(%d);\n", nameindex);
else
{
Tree node;
@ -1234,25 +1264,25 @@ static void emitinsndata(Rule rules)
if (nt->kind == NONTERM)
{
if (nt->is_fragment)
print("%1data->emit_fragment(");
print("%1data->emit_fragment(%d);\n", index);
else
print("%1data->emit_reg(");
print("%1data->emit_reg(%d, %d);\n", index, nameindex);
}
else
print("%1data->emit_reg(");
print("%d);\n", index);
print("%1data->emit_reg(%d, %d);\n", index, nameindex);
}
break;
}
case '$':
{
const char* label = f->data + 1;
int index = 0;
if (!find_child_index(r->pattern, label, &index, NULL))
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);
break;
}

View file

@ -59,10 +59,10 @@ struct terminfo
struct reg
{
const char* name; /* friendly register name */
const char* realname; /* name used in assembly output */
int number; /* identifying number */
uint32_t attrs; /* bitfield of register attributes */
uint32_t type; /* register type */
struct stringlist* names; /* register names */
ARRAYOF(struct reg) aliases; /* registers that this one aliases */
};
@ -72,7 +72,8 @@ struct regattr
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 addregaliases(struct reg* reg, struct stringlist* aliases);
extern struct regattr* getregattr(const char* name);

View file

@ -23,6 +23,7 @@ S POPF
S LOAD # must be followed by float form
S LOADF
S STORE
S STOREF
# Arithemetic operations
S ADD

View file

@ -40,8 +40,8 @@ struct burm_emitter_data
{
void (*emit_string)(const char* data);
void (*emit_fragment)(int child);
void (*emit_return_reg)(void);
void (*emit_reg)(int child);
void (*emit_return_reg)(int index);
void (*emit_reg)(int child, int index);
void (*emit_value)(int child);
void (*emit_eoi)(void);
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
{
const char* name;
const char* realname;
const char* id;
uint32_t type;
uint32_t attrs;
const char** names;
const struct burm_register_data** aliases;
};

View file

@ -21,7 +21,7 @@ static int braces = 0;
<INITIAL>"\"" BEGIN(QSTRING);
<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);
return QFRAGMENT;
}
@ -44,6 +44,7 @@ static int braces = 0;
"cost" return COST;
"emit" return EMIT;
"fragment" return FRAGMENT;
"named" return NAMED;
"prefers" return PREFERS;
"when" return WHEN;
"with" return WITH;