diff --git a/mach/proto/mcg/pass_prologueepilogue.c b/mach/proto/mcg/pass_prologueepilogue.c index 53cc498ec..9a5762e8d 100644 --- a/mach/proto/mcg/pass_prologueepilogue.c +++ b/mach/proto/mcg/pass_prologueepilogue.c @@ -2,6 +2,25 @@ void pass_add_prologue_epilogue(void) { + int i, j, k; + + current_proc->usedregs.count = 0; + for (i=0; ihops.count; j++) + { + struct hop* hop = bb->hops.item[j]; + + for (k=0; kregsin.count; k++) + array_appendu(¤t_proc->usedregs, hop->regsin.item[k].left); + + for (k=0; kregsout.count; k++) + array_appendu(¤t_proc->usedregs, hop->regsout.item[k].left); + } + } + platform_calculate_offsets(); array_insert(¤t_proc->entry->hops, platform_prologue(), 0); diff --git a/mach/proto/mcg/powerpc.c b/mach/proto/mcg/powerpc.c index 1c900bea0..ab08209f3 100644 --- a/mach/proto/mcg/powerpc.c +++ b/mach/proto/mcg/powerpc.c @@ -15,8 +15,25 @@ * st indexes up; lb indexes down. */ +static ARRAYOF(struct hreg) saved_regs; + void platform_calculate_offsets(void) { + int i; + + saved_regs.count = 0; + for (i=0; iusedregs.count; i++) + { + struct hreg* hreg = current_proc->usedregs.item[i]; + + if (!(hreg->attrs & burm_volatile_ATTR) && + ((hreg->attrs & burm_int_ATTR) || (hreg->attrs & burm_float_ATTR))) + { + current_proc->saved_size += 4; + array_append(&saved_regs, hreg); + } + } + current_proc->fp_to_st = 0; current_proc->fp_to_ab = current_proc->spills_size + current_proc->saved_size + 8; current_proc->fp_to_lb = 0; @@ -24,6 +41,8 @@ void platform_calculate_offsets(void) struct hop* platform_prologue(void) { + int i; + int saved_offset; struct hop* hop = new_hop(current_proc->entry, NULL); hop_add_insel(hop, "! saved_size = %d+8 bytes", current_proc->saved_size); @@ -31,18 +50,47 @@ struct hop* platform_prologue(void) hop_add_insel(hop, "! locals_size = %d bytes", current_proc->locals_size); hop_add_insel(hop, "addi sp, sp, %d", -(current_proc->fp_to_ab + current_proc->locals_size)); hop_add_insel(hop, "mfspr r0, lr"); - hop_add_insel(hop, "stw fp, %d(sp)", current_proc->fp_to_st + current_proc->locals_size); - hop_add_insel(hop, "stw r0, %d(sp)", current_proc->fp_to_st + current_proc->locals_size + 4); + + hop_add_insel(hop, "stw r0, %d(sp)", current_proc->locals_size + current_proc->spills_size); + hop_add_insel(hop, "stw fp, %d(sp)", current_proc->locals_size + current_proc->spills_size + 4); hop_add_insel(hop, "addi fp, sp, %d", current_proc->locals_size); + saved_offset = current_proc->spills_size + 8; + for (i=0; itype & burm_int_ATTR) + hop_add_insel(hop, "stw %H, %d(fp)", hreg, saved_offset); + else if (hreg->type & burm_float_ATTR) + hop_add_insel(hop, "stfs %H, %d(fp)", hreg, saved_offset); + saved_offset += 4; + } return hop; } struct hop* platform_epilogue(void) { struct hop* hop = new_hop(current_proc->exit, NULL); + int i; + int saved_offset; - hop_add_insel(hop, "b .ret"); + saved_offset = current_proc->spills_size + 8; + for (i=0; itype & burm_int_ATTR) + hop_add_insel(hop, "lwz %H, %d(fp)", hreg, saved_offset); + else if (hreg->type & burm_float_ATTR) + hop_add_insel(hop, "lfs %H, %d(fp)", hreg, saved_offset); + saved_offset += 4; + } + + hop_add_insel(hop, "lwz r0, %d(fp)", current_proc->spills_size); + hop_add_insel(hop, "mtspr lr, r0"); + hop_add_insel(hop, "lwz r0, %d(fp)", current_proc->spills_size + 4); + hop_add_insel(hop, "addi sp, fp, %d", current_proc->fp_to_ab); + hop_add_insel(hop, "mr fp, r0"); + hop_add_insel(hop, "blr"); return hop; } diff --git a/mach/proto/mcg/procedure.h b/mach/proto/mcg/procedure.h index 2c0baf816..ead7abc9b 100644 --- a/mach/proto/mcg/procedure.h +++ b/mach/proto/mcg/procedure.h @@ -21,6 +21,7 @@ struct procedure int fp_to_lb; ARRAYOF(struct basicblock) blocks; IMAPOF(struct local) locals; + ARRAYOF(struct hreg) usedregs; }; extern void procedure_compile(struct procedure* proc);