cell: checkpoint: more work in emit_function_call()
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 26 Sep 2008 23:59:19 +0000 (17:59 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 26 Sep 2008 23:59:19 +0000 (17:59 -0600)
Simple function call works now, but we don't save/restore the caller's registers yet.

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

index fd12af19cef60dc8619421ab642b5d8bb8ebf9e5..8d2d4f2a0f2c2ed8e303776652512ad3324a1bf8 100644 (file)
@@ -1105,7 +1105,10 @@ emit_function_call(struct codegen *gen,
    uint addr;
    int ch;
 
-   assert(num_args <= 2);
+   /* XXX temporary value */
+   const int frameSize = 64; /* stack frame (activation record) size */
+
+   assert(num_args <= 3);
 
    /* lookup function address */
    {
@@ -1119,7 +1122,9 @@ emit_function_call(struct codegen *gen,
       assert(addr && "spu function not found");
    }
 
-   sprintf(comment, "CALL %s:", funcname);
+   addr /= 4; /* discard 2 least significant bits */
+
+   snprintf(comment, sizeof(comment), "CALL %s:", funcname);
    spe_comment(gen->f, -4, comment);
 
    for (ch = 0; ch < 4; ch++) {
@@ -1131,12 +1136,40 @@ emit_function_call(struct codegen *gen,
             s_regs[a] = get_src_reg(gen, ch, &inst->FullSrcRegisters[a]);
          }
 
-         /* XXX not done */
-         (void) s_regs;
-         (void) d_reg;
+         /* Basically:
+          * save registers on stack
+          * move parameters to registers 3, 4, 5...
+          * call function
+          * save return value (reg 3)
+          * restore registers from stack
+          */
+
+         /* XXX hack: load first function param */
+         spe_move(gen->f, 3, s_regs[0]);
+
+         /* 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, -frameSize);
+
+         /* XXX save registers to stack here */
+
+         /* adjust stack pointer  # ai $sp,$sp,-frameSize */
+         spe_ai(gen->f, SPE_REG_SP, SPE_REG_SP, -frameSize);
+
+         /* branch to function, save return addr */
+         spe_brasl(gen->f, SPE_REG_RA, addr);
+
+         /* restore stack pointer # ai $sp,$sp,frameSize */
+         spe_ai(gen->f, SPE_REG_SP, SPE_REG_SP, frameSize);
+
+         /* XXX restore registers from stack here */
 
-         spe_bisl(gen->f, SPE_REG_RA, addr, 0, 0); /* XXX untested! */
+         /* restore $lr           # lqd $lr,16($sp) */
+         spe_lqd(gen->f, SPE_REG_RA, SPE_REG_SP, 16);
 
+         /* XXX hack: save function's return value */
+         spe_move(gen->f, d_reg, 3);
 
          store_dest_reg(gen, d_reg, ch, &inst->FullDstRegisters[0]);
          free_itemps(gen);