PowerPC stuff (some working).
{
struct hop* hop = new_hop(bb, NULL);
- if ((src->type & burm_int_ATTR) && (dest->type & burm_int_ATTR))
- {
- if (src->is_stacked)
- hop_add_insel(hop, "lwz %H, %S(fp) ! %H", dest, src, src);
- else if (dest->is_stacked)
+ if (!src->is_stacked && dest->is_stacked)
+ {
+ if (src->type & burm_int_ATTR)
hop_add_insel(hop, "stw %H, %S(fp) ! %H", src, dest, dest);
- else
+ 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
+ {
+ if (src->type & 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);
+
+ 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
+ assert(false);
+ hop_add_insel(hop, "addi sp, sp, 4");
+ }
}
else
fatal("cannot generate move from %s to %s", src->name, dest->name);
r6 "r6" bytes4! int! volatile;
r5 "r5" bytes4! int! volatile;
r4 "r4" bytes4! int! volatile;
- r3 "r3" bytes4! int! ret volatile;
+ r3 "r3" bytes4! int! volatile ret;
r31 "r31" bytes4! int!;
r30 "r30" bytes4! int!;
f6 "f6" bytes4! float! volatile;
f5 "f5" bytes4! float! volatile;
f4 "f4" bytes4! float! volatile;
- f3 "f3" bytes4! float! volatile;
+ f3 "f3" bytes4! float! volatile fret;
f2 "f2" bytes4! float! volatile;
f1 "f1" bytes4! float! volatile;
f0 "f0" bytes4! float! volatile;
/* FPU operations */
+ out:(float)reg = LOADF4(addr:address)
+ emit "lfs %out, %addr"
+ cost 4;
+
out:(float)reg = value:CONSTF4
emit "lfs %out, address-containing-$value"
cost 8;
emit "fsubs %out, %left, %right"
cost 4;
+ out:(float)reg = MULF4(left:(float)reg, right:(float)reg)
+ emit "fmuls %out, %left, %right"
+ cost 4;
+
+ out:(float)reg = NEGF4(left:(float)reg)
+ emit "fneg %out, %left"
+ cost 4;
+
+ cr:(cr)cr = COMPAREF4(left:(float)reg, right:(float)reg)
+ emit "fcmpu %cr, %left, %right"
+ cost 4;
+
+ cr:(cr)cr = COMPARES4(COMPAREF4(left:(float)reg, right:(float)reg), result:CONST4)
+ when specific_constant(%result, 0)
+ emit "fcmpu %cr, %left, %right"
+ cost 4;
+
+ out:(ret)reg = CFI44(val:(fret)reg)
+ with corrupted(volatile)
+ emit "bl .cfi4"
+ cost 4;
+
+ out:(fret)reg = CIF44(val:(ret)reg)
+ with corrupted(volatile)
+ emit "bl .cif4"
+ cost 4;
/* vim: set sw=4 ts=4 expandtab : */
void burm_panic_cannot_match(struct burm_node* node)
{
fprintf(stderr, "could not find any patterns to match:\n");
- ir_print(0, node->ir);
+ ir_print('!', node->ir);
fprintf(stderr, "aborting!\n");
exit(1);
}
struct hop* hop = bb->hops.item[j];
for (k=0; k<hop->regsin.count; k++)
- array_appendu(¤t_proc->usedregs, hop->regsin.item[k].left);
+ {
+ struct hreg* hreg = hop->regsin.item[k].left;
+ if (!hreg->is_stacked)
+ array_appendu(¤t_proc->usedregs, hreg);
+ }
for (k=0; k<hop->regsout.count; k++)
- array_appendu(¤t_proc->usedregs, hop->regsout.item[k].left);
+ {
+ struct hreg* hreg = hop->regsout.item[k].left;
+ if (!hreg->is_stacked)
+ array_appendu(¤t_proc->usedregs, hreg);
+ }
}
}
static int insert_moves(struct basicblock* bb, int index,
register_assignment_t* srcregs, register_assignment_t* destregs);
+static bool type_match(struct hreg* hreg, struct vreg* vreg);
+
static void populate_hregs(void)
{
const struct burm_register_data* brd = burm_register_data;
static bool evictable(struct hreg* hreg, struct vreg* vreg)
{
- struct constraint* c = pmap_findleft(¤t_hop->constraints, vreg);
- return (hreg->attrs & c->attrs) && !array_contains(¤t_hop->ins, vreg);
- /* Find an unused output register of the right class which is not also being used as an input register. */
+ return type_match(hreg, vreg) && !array_contains(¤t_hop->ins, vreg);
}
static struct hreg* evict(struct vreg* vreg)
for (i=0; i<hregs.count; i++)
{
struct hreg* hreg = hregs.item[i];
- struct vreg* candidate = pmap_findleft(current_ins, hreg);
+ struct vreg* candidatein = pmap_findleft(current_ins, hreg);
+ struct vreg* candidateout = pmap_findleft(current_outs, hreg);
- if (candidate &&
- (pmap_findleft(current_outs, hreg) == candidate) &&
- evictable(hreg, vreg))
+ if (evictable(hreg, vreg))
{
- tracef('R', "R: evicting %%%d from %s\n", candidate->id, hreg->name);
- pmap_put(&evicted, candidate, hreg);
- pmap_remove(current_ins, hreg, candidate);
- pmap_remove(current_outs, hreg, candidate);
- return hreg;
+ if (!candidatein && !candidateout)
+ {
+ /* This hreg is unused, so we don't need to evict anything.
+ * Shouldn't really happen in real life. */
+ return hreg;
+ }
+ if (candidatein == candidateout)
+ {
+ /* This is a through register. */
+ tracef('R', "R: evicting %%%d from %s\n", candidatein->id, hreg->name);
+ pmap_put(&evicted, candidatein, hreg);
+ pmap_remove(current_ins, hreg, candidatein);
+ pmap_remove(current_outs, hreg, candidatein);
+ return hreg;
+ }
}
}
case op_cii: simple_convert(IR_CII1); break;
case op_ciu: simple_convert(IR_CIU1); break;
case op_cui: simple_convert(IR_CUI1); break;
+ case op_cfi: simple_convert(IR_CFI1); break;
+ case op_cif: simple_convert(IR_CIF1); break;
case op_cmp:
push(
case op_dvf: simple_alu2(opcode, value, IR_DIVF); break;
case op_ngf: simple_alu1(opcode, value, IR_NEGF); break;
+ case op_cmu: /* fall through */
+ case op_cms: push(tristate_compare(value, IR_COMPAREU)); break;
+ case op_cmi: push(tristate_compare(value, IR_COMPARES)); break;
+ case op_cmf: push(tristate_compare(value, IR_COMPAREF)); break;
+
case op_lol:
push(
new_ir1(
);
break;
+ case op_ldl:
+ push(
+ new_ir1(
+ IR_LOAD, EM_wordsize*2,
+ new_localir(value)
+ )
+ );
+ break;
+
case op_stl:
appendir(
new_ir2(
break;
}
- case op_cmi:
- push(
- tristate_compare(value, IR_COMPARES)
- );
- break;
-
- case op_cmu:
- case op_cms:
- push(
- tristate_compare(value, IR_COMPAREU)
- );
- break;
-
case op_ads:
{
struct ir* off = pop(value);
{
switch (opcode)
{
+ case op_lpi:
case op_lae:
push(
address_of_external(label, offset)
S CUI4
S CUI8
+S CFI1
+S CFI2
+S CFI4
+S CFI8
+
+S CIF1
+S CIF2
+S CIF4
+S CIF8
+
# Tristate comparisons
S COMPARES
S COMPAREU
+S COMPAREF
# Boolean comparisons
S IFEQ