diff --git a/mach/powerpc/mcg/platform.c b/mach/powerpc/mcg/platform.c index b8bd44744..36c505a9f 100644 --- a/mach/powerpc/mcg/platform.c +++ b/mach/powerpc/mcg/platform.c @@ -6,13 +6,13 @@ * | --------------- <- ab * | old FR * | old FP - * | --------------- <- st, fp (a.k.a. lb) + * | --------------- <- fp (a.k.a. lb) * | locals - * | --------------- - * | spills * | --------------- + * | spills + * | --------------- <- sb * | saved regs - * | --------------- <- sp + * | --------------- <- sp, rb * V ...user area... * * st indexes up; lb indexes down. @@ -31,17 +31,31 @@ void platform_calculate_offsets(void) { struct hreg* hreg = current_proc->usedregs.item[i]; + if (!(hreg->attrs & burm_volatile_ATTR) && + ((hreg->attrs & burm_long_ATTR) || (hreg->attrs & burm_double_ATTR))) + { + hreg->offset = current_proc->saved_size; + current_proc->saved_size += 8; + array_append(&saved_regs, hreg); + } + } + 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))) { + hreg->offset = current_proc->saved_size; current_proc->saved_size += 4; array_append(&saved_regs, hreg); } } - current_proc->fp_to_st = -current_proc->locals_size; current_proc->fp_to_ab = 8; current_proc->fp_to_lb = 0; + current_proc->fp_to_sb = -(current_proc->locals_size + current_proc->spills_size); + current_proc->fp_to_rb = current_proc->fp_to_sb - current_proc->saved_size; } struct hop* platform_prologue(void) @@ -52,9 +66,20 @@ struct hop* platform_prologue(void) current_proc->locals_size; struct hop* hop = new_hop(current_proc->entry, NULL); - hop_add_insel(hop, "! saved_size = %d bytes", current_proc->saved_size); - hop_add_insel(hop, "! spills_size = %d bytes", current_proc->spills_size); - hop_add_insel(hop, "! locals_size = %d bytes", current_proc->locals_size); + hop_add_insel(hop, "! params @ fp+%d", current_proc->fp_to_ab); + hop_add_insel(hop, "! lr @ fp+4"); + hop_add_insel(hop, "! fp @ fp+0"); + hop_add_insel(hop, "! locals @ fp-%d to fp+0", + current_proc->locals_size); + hop_add_insel(hop, "! spills @ fp-%d to fp-%d", + -current_proc->fp_to_sb, current_proc->locals_size); + for (i=0; iid, -(current_proc->fp_to_rb + hreg->offset)); + } + hop_add_insel(hop, "addi sp, sp, %d", -(spoffset + 8)); hop_add_insel(hop, "mfspr r0, lr"); hop_add_insel(hop, "stw fp, %d(sp)", spoffset + 0); @@ -67,10 +92,11 @@ struct hop* platform_prologue(void) { struct hreg* hreg = saved_regs.item[i]; if (hreg->attrs & burm_int_ATTR) - hop_add_insel(hop, "stw %H, %d(fp)", hreg, saved_offset); + hop_add_insel(hop, "stw %H, %d(fp)", + hreg, current_proc->fp_to_rb + saved_offset); else if (hreg->attrs & burm_float_ATTR) - hop_add_insel(hop, "stfs %H, %d(fp)", hreg, saved_offset); - saved_offset += 4; + hop_add_insel(hop, "stfs %H, %d(fp)", + hreg, current_proc->fp_to_rb + saved_offset); } return hop; } @@ -81,16 +107,15 @@ struct hop* platform_epilogue(void) int i; int saved_offset; - /* Saved reg offsets are negative. */ - saved_offset = -(current_proc->locals_size + current_proc->spills_size); for (i=0; iattrs & burm_int_ATTR) - hop_add_insel(hop, "lwz %H, %d(fp)", hreg, saved_offset); + hop_add_insel(hop, "lwz %H, %d(fp)", + hreg, current_proc->fp_to_rb + saved_offset); else if (hreg->attrs & burm_float_ATTR) - hop_add_insel(hop, "lfs %H, %d(fp)", hreg, saved_offset); - saved_offset += 4; + hop_add_insel(hop, "lfs %H, %d(fp)", + hreg, current_proc->fp_to_rb + saved_offset); } hop_add_insel(hop, "lwz r0, 4(fp)"); diff --git a/mach/proto/mcg/hop.c b/mach/proto/mcg/hop.c index 27ea8be03..77c6dc260 100644 --- a/mach/proto/mcg/hop.c +++ b/mach/proto/mcg/hop.c @@ -113,6 +113,10 @@ void hop_add_insel(struct hop* hop, const char* fmt, ...) hop_add_string_insel(hop, aprintf("%d", va_arg(ap, int))); break; + case 's': + hop_add_string_insel(hop, va_arg(ap, const char*)); + break; + case 'S': hop_add_st_offset_insel(hop, va_arg(ap, struct hreg*)); break; @@ -248,7 +252,7 @@ char* hop_render(struct hop* hop) break; case INSEL_ST_OFFSET: - appendf("%d", current_proc->fp_to_st + insel->u.hreg->offset); + appendf("%d", current_proc->fp_to_sb + insel->u.hreg->offset); break; case INSEL_AB_OFFSET: diff --git a/mach/proto/mcg/procedure.h b/mach/proto/mcg/procedure.h index ead7abc9b..226db804c 100644 --- a/mach/proto/mcg/procedure.h +++ b/mach/proto/mcg/procedure.h @@ -16,9 +16,10 @@ struct procedure int locals_size; int spills_size; int saved_size; - int fp_to_st; - int fp_to_ab; - int fp_to_lb; + int fp_to_ab; /* argument base (indexes up) */ + int fp_to_lb; /* locals base (indexes down) */ + int fp_to_sb; /* spill base (indexes up) */ + int fp_to_rb; /* saved registers base (indexes up) */ ARRAYOF(struct basicblock) blocks; IMAPOF(struct local) locals; ARRAYOF(struct hreg) usedregs;