diff options
author | Brian Paul <brian.paul@tungstengraphics.com> | 2008-10-10 14:34:43 -0600 |
---|---|---|
committer | Brian Paul <brian.paul@tungstengraphics.com> | 2008-10-10 14:36:18 -0600 |
commit | 53ae243869a9e1ff0f2b1c559ec51adff867b970 (patch) | |
tree | 7a03a1ef59ae49b7b44b28ed46230f4f22b2a64b /src/gallium | |
parent | adeed0f90fdd46ea139d5c4b3b75d5dc79b2a0c7 (diff) |
cell: fix function prologue/epilogue code for large stack frames
The ai instruction is limited to a 10-bit signed immediate value.
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/cell/ppu/cell_gen_fp.c | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fp.c b/src/gallium/drivers/cell/ppu/cell_gen_fp.c index db54c7e57b..3d0e7976df 100644 --- a/src/gallium/drivers/cell/ppu/cell_gen_fp.c +++ b/src/gallium/drivers/cell/ppu/cell_gen_fp.c @@ -369,18 +369,36 @@ store_dest_reg(struct codegen *gen, static void emit_prologue(struct codegen *gen) { - gen->frame_size = 1024; /* XXX temporary */ + gen->frame_size = 1024; /* XXX temporary, should be dynamic */ spe_comment(gen->f, -4, "Function prologue:"); /* save $lr on stack # stqd $lr,16($sp) */ spe_stqd(gen->f, SPE_REG_RA, SPE_REG_SP, 16); - /* save stack pointer # stqd $sp,-frameSize($sp) */ - spe_stqd(gen->f, SPE_REG_SP, SPE_REG_SP, -gen->frame_size); + if (gen->frame_size >= 512) { + /* offset is too large for ai instruction */ + int offset_reg = spe_allocate_available_register(gen->f); + int sp_reg = spe_allocate_available_register(gen->f); + /* offset = -framesize */ + spe_load_int(gen->f, offset_reg, -gen->frame_size); + /* sp = $sp */ + spe_move(gen->f, sp_reg, SPE_REG_SP); + /* $sp = $sp + offset_reg */ + spe_a(gen->f, SPE_REG_SP, SPE_REG_SP, offset_reg); + /* save $sp in stack frame */ + spe_stqd(gen->f, sp_reg, SPE_REG_SP, 0); + /* clean up */ + spe_release_register(gen->f, offset_reg); + spe_release_register(gen->f, sp_reg); + } + else { + /* save stack pointer # stqd $sp,-frameSize($sp) */ + spe_stqd(gen->f, SPE_REG_SP, SPE_REG_SP, -gen->frame_size); - /* adjust stack pointer # ai $sp,$sp,-frameSize */ - spe_ai(gen->f, SPE_REG_SP, SPE_REG_SP, -gen->frame_size); + /* adjust stack pointer # ai $sp,$sp,-frameSize */ + spe_ai(gen->f, SPE_REG_SP, SPE_REG_SP, -gen->frame_size); + } } @@ -389,8 +407,20 @@ emit_epilogue(struct codegen *gen) { spe_comment(gen->f, -4, "Function epilogue:"); - /* restore stack pointer # ai $sp,$sp,frameSize */ - spe_ai(gen->f, SPE_REG_SP, SPE_REG_SP, gen->frame_size); + if (gen->frame_size >= 512) { + /* offset is too large for ai instruction */ + int offset_reg = spe_allocate_available_register(gen->f); + /* offset = framesize */ + spe_load_int(gen->f, offset_reg, gen->frame_size); + /* $sp = $sp + offset */ + spe_a(gen->f, SPE_REG_SP, SPE_REG_SP, offset_reg); + /* clean up */ + spe_release_register(gen->f, offset_reg); + } + else { + /* restore stack pointer # ai $sp,$sp,frameSize */ + spe_ai(gen->f, SPE_REG_SP, SPE_REG_SP, gen->frame_size); + } /* restore $lr # lqd $lr,16($sp) */ spe_lqd(gen->f, SPE_REG_RA, SPE_REG_SP, 16); |