cell: fix function prologue/epilogue code for large stack frames
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 10 Oct 2008 20:34:43 +0000 (14:34 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 10 Oct 2008 20:36:18 +0000 (14:36 -0600)
The ai instruction is limited to a 10-bit signed immediate value.

src/gallium/drivers/cell/ppu/cell_gen_fp.c

index db54c7e57b5618232a4e4997c5af16e2852531c8..3d0e7976dfb71fa1e0271d87728113975e1b3065 100644 (file)
@@ -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);