diff --git a/mach/powerpc/mcg/platform.c b/mach/powerpc/mcg/platform.c index 0feaf0da7..e3ab26913 100644 --- a/mach/powerpc/mcg/platform.c +++ b/mach/powerpc/mcg/platform.c @@ -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; } diff --git a/mach/powerpc/mcg/table b/mach/powerpc/mcg/table index 3a1da6fd6..236f5c7c1 100644 --- a/mach/powerpc/mcg/table +++ b/mach/powerpc/mcg/table @@ -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!; - - cr0 "cr0" cr!; + 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!; @@ -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; diff --git a/mach/proto/mcg/hop.c b/mach/proto/mcg/hop.c index 7bdb232ff..9dbb010cc 100644 --- a/mach/proto/mcg/hop.c +++ b/mach/proto/mcg/hop.c @@ -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; diff --git a/mach/proto/mcg/hop.h b/mach/proto/mcg/hop.h index e1f2f6d92..0cc5dc0b1 100644 --- a/mach/proto/mcg/hop.h +++ b/mach/proto/mcg/hop.h @@ -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); diff --git a/mach/proto/mcg/pass_instructionselection.c b/mach/proto/mcg/pass_instructionselection.c index fcfb55182..863ed56e9 100644 --- a/mach/proto/mcg/pass_instructionselection.c +++ b/mach/proto/mcg/pass_instructionselection.c @@ -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; diff --git a/mach/proto/mcg/pass_promotefloatops.c b/mach/proto/mcg/pass_promotefloatops.c index 87db1e47d..2708c7fda 100644 --- a/mach/proto/mcg/pass_promotefloatops.c +++ b/mach/proto/mcg/pass_promotefloatops.c @@ -48,7 +48,7 @@ static void promote(struct ir* ir) { int i; for (i=0; iu.phivalue.count; i++) - array_appendu(&promotable, ir->u.phivalue.item[i].right); + promote(ir->u.phivalue.item[i].right); break; } } diff --git a/mach/proto/mcg/pass_registerallocator.c b/mach/proto/mcg/pass_registerallocator.c index 93a9b1dad..5d9e702fc 100644 --- a/mach/proto/mcg/pass_registerallocator.c +++ b/mach/proto/mcg/pass_registerallocator.c @@ -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; ibrd->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; ialiases.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; itype == 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; kregsout.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); } diff --git a/mach/proto/mcg/reg.c b/mach/proto/mcg/reg.c index 25ec0b607..8af8079e2 100644 --- a/mach/proto/mcg/reg.c +++ b/mach/proto/mcg/reg.c @@ -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; } diff --git a/mach/proto/mcg/reg.h b/mach/proto/mcg/reg.h index e71864f3a..f449b7e19 100644 --- a/mach/proto/mcg/reg.h +++ b/mach/proto/mcg/reg.h @@ -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 diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 8684f1fd5..7b9ba842c 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -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( diff --git a/util/mcgg/gram.y b/util/mcgg/gram.y index e6b1c2fd0..4844da073 100644 --- a/util/mcgg/gram.y +++ b/util/mcgg/gram.y @@ -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 ID %token QFRAGMENT -%type aliases; %type constraint %type constraints %type predicate @@ -55,6 +55,8 @@ extern int yylex(void); %type pattern %type pattern_constraints %type pattern_emit +%type aliases; +%type names; %type qfragments %type terminfo %type 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); } diff --git a/util/mcgg/iburg.c b/util/mcgg/iburg.c index cf7950b26..146f920c3 100644 --- a/util/mcgg/iburg.c +++ b/util/mcgg/iburg.c @@ -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(®isters, 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(®isters, 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(®isterattrs, id); @@ -629,14 +636,33 @@ static void emitregisters(void) print("NULL\n};\n"); } + for (i=0; iname); + 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; inumber == 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; } diff --git a/util/mcgg/iburg.h b/util/mcgg/iburg.h index f50e4c9da..e0bbeef57 100644 --- a/util/mcgg/iburg.h +++ b/util/mcgg/iburg.h @@ -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); diff --git a/util/mcgg/ir.dat b/util/mcgg/ir.dat index 6f40ae3c0..576587247 100644 --- a/util/mcgg/ir.dat +++ b/util/mcgg/ir.dat @@ -23,6 +23,7 @@ S POPF S LOAD # must be followed by float form S LOADF S STORE +S STOREF # Arithemetic operations S ADD diff --git a/util/mcgg/mcgg.h b/util/mcgg/mcgg.h index 211aaf1cc..da0c8b1a1 100644 --- a/util/mcgg/mcgg.h +++ b/util/mcgg/mcgg.h @@ -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; }; diff --git a/util/mcgg/scan.l b/util/mcgg/scan.l index 44a582456..272dd2bf1 100644 --- a/util/mcgg/scan.l +++ b/util/mcgg/scan.l @@ -21,7 +21,7 @@ static int braces = 0; "\"" BEGIN(QSTRING); "\"" BEGIN(INITIAL); -[%$][a-zA-Z_][a-zA_Z_0-9]+ { +[%$][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;