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)
+ break;
+
+ case burm_float_ATTR:
hop_add_insel(hop, "stfsu %H, -4(sp)", src);
- else
+ break;
+
+ case burm_double_ATTR:
+ hop_add_insel(hop, "stfdu %H, -8(sp)", src);
+ break;
+
+ default:
assert(false);
+ }
- if (dest->type & burm_int_ATTR)
+ switch (dest->type & type_attrs)
+ {
+ case burm_int_ATTR:
hop_add_insel(hop, "lwz %H, 0(sp)", dest);
- else if (dest->type & burm_float_ATTR)
+ break;
+
+ case burm_float_ATTR:
hop_add_insel(hop, "lfs %H, 0(sp)", dest);
- else
+ break;
+
+ case burm_double_ATTR:
+ hop_add_insel(hop, "lfd %H, 0(sp)", dest);
+ 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:
+ 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;
}
* 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;
-
- 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!;
-
- 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;
-
- 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!;
-
- cr0 "cr0" cr!;
+ 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 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!;
+
+ 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;
+
+ 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!;
+
+ 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!;
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"
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"
/* 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;
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;
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;
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;
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);
}
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;
}
}
case INSEL_HREG:
{
struct hreg* hreg = insel->u.hreg;
- appendf("%s", hreg->realname);
+ appendf("%s", hreg->brd->names[insel->index]);
break;
}
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;
struct insel
{
enum insel_type type;
+ int index;
union
{
const char* string;
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);
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)
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);
}
}
* this. */
const struct burm_register_data* brd = burm_register_data;
- while (brd->name)
+ while (brd->id)
{
if (brd->attrs & attr)
return brd->type;
{
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;
}
}
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)
}
}
+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)
{
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;
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. */
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);
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);
}
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
/* 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);
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);
}
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;
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);
}
}
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);
}
}
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++)
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");
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;
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);
}
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;
}
{
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;
}
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
);
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)
);
break;
+ case op_lde:
+ push(
+ new_ir1(
+ IR_LOAD, EM_wordsize*2,
+ address_of_external(label, offset)
+ )
+ );
+ break;
+
case op_ste:
appendir(
new_ir2(
);
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(
%term EMIT
%term EQUALS
%term FRAGMENT
+%term NAMED
%term NOTEQUALS
%term PATTERNS
%term PREFERS
%token <string> ID
%token <string> QFRAGMENT
-%type <stringlist> aliases;
%type <constraint> constraint
%type <constraint> constraints
%type <expr> predicate
%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
;
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); }
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);
static int number = 0;
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(®isters, id, 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* p = smap_get(®isterattrs, id);
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");
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;
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;
}
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 */
};
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);
S LOAD # must be followed by float form
S LOADF
S STORE
+S STOREF
# Arithemetic operations
S ADD
{
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);
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;
};
<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;
}
"cost" return COST;
"emit" return EMIT;
"fragment" return FRAGMENT;
+"named" return NAMED;
"prefers" return PREFERS;
"when" return WHEN;
"with" return WITH;