summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2008-10-10 14:34:43 -0600
committerBrian Paul <[email protected]>2008-10-10 14:36:18 -0600
commit53ae243869a9e1ff0f2b1c559ec51adff867b970 (patch)
tree7a03a1ef59ae49b7b44b28ed46230f4f22b2a64b /src
parentadeed0f90fdd46ea139d5c4b3b75d5dc79b2a0c7 (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')
-rw-r--r--src/gallium/drivers/cell/ppu/cell_gen_fp.c44
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 db54c7e57b5..3d0e7976dfb 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);