/* Restore, Step 4: * Enqueue the GETL command (tag 0) to the MFC SPU command * queue to transfer the upper 240 kb of LS from CSA.
*/
spu_writech(MFC_LSA, ls);
spu_writech(MFC_EAH, lscsa_ea.ui[0]);
spu_writech(MFC_EAL, list);
spu_writech(MFC_Size, size);
spu_writech(MFC_TagID, tag_id);
spu_writech(MFC_Cmd, cmd);
}
/* Restore, Step 6(moved): * If the LSCSA "decrementer running" flag is set * then write the SPU_WrDec channel with the * decrementer value from LSCSA.
*/
offset = LSCSA_QW_OFFSET(decr_status);
decr_running = regs_spill[offset].slot[0] & SPU_DECR_STATUS_RUNNING; if (decr_running) {
offset = LSCSA_QW_OFFSET(decr);
decr = regs_spill[offset].slot[0];
spu_writech(SPU_WrDec, decr);
}
}
/* Restore, Step 11: * Write the MFC_WrOut_MB channel with the PPU_MB * data from LSCSA.
*/
offset = LSCSA_QW_OFFSET(ppu_mb);
data = regs_spill[offset].slot[0];
spu_writech(SPU_WrOutMbox, data);
}
/* Restore, Step 12: * Write the MFC_WrInt_MB channel with the PPUINT_MB * data from LSCSA.
*/
offset = LSCSA_QW_OFFSET(ppuint_mb);
data = regs_spill[offset].slot[0];
spu_writech(SPU_WrOutIntrMbox, data);
}
/* Restore, Step 13: * Restore the floating-point status and control * register from the LSCSA.
*/
offset = LSCSA_QW_OFFSET(fpcr);
fpcr = regs_spill[offset].v;
spu_mtfpscr(fpcr);
}
/* Restore, Step 18: * Issue a stop-and-signal instruction with * "good context restore" signal value. * * Restore, Step 19: * There may be additional instructions placed * here by the PPE Sequence for SPU Context * Restore in order to restore the correct * "stopped state". * * This step is handled here by analyzing the * LSCSA.stopped_status and then modifying the * exit() function to behave appropriately.
*/
switch (stopped_status) { case SPU_STOPPED_STATUS_P_I: /* SPU_Status[P,I]=1. Add illegal instruction * followed by stop-and-signal instruction after * end of restore code.
*/
exit_instrs[0] = RESTORE_COMPLETE;
exit_instrs[1] = ILLEGAL_INSTR;
exit_instrs[2] = STOP_INSTR | stopped_code; break; case SPU_STOPPED_STATUS_P_H: /* SPU_Status[P,H]=1. Add 'heq $0, $0' followed * by stop-and-signal instruction after end of * restore code.
*/
exit_instrs[0] = RESTORE_COMPLETE;
exit_instrs[1] = HEQ_INSTR;
exit_instrs[2] = STOP_INSTR | stopped_code; break; case SPU_STOPPED_STATUS_S_P: /* SPU_Status[S,P]=1. Add nop instruction * followed by 'br -4' after end of restore * code.
*/
exit_instrs[0] = RESTORE_COMPLETE;
exit_instrs[1] = STOP_INSTR | stopped_code;
exit_instrs[2] = NOP_INSTR;
exit_instrs[3] = BR_INSTR; break; case SPU_STOPPED_STATUS_S_I: /* SPU_Status[S,I]=1. Add illegal instruction * followed by 'br -4' after end of restore code.
*/
exit_instrs[0] = RESTORE_COMPLETE;
exit_instrs[1] = ILLEGAL_INSTR;
exit_instrs[2] = NOP_INSTR;
exit_instrs[3] = BR_INSTR; break; case SPU_STOPPED_STATUS_I: /* SPU_Status[I]=1. Add illegal instruction followed * by infinite loop after end of restore sequence.
*/
exit_instrs[0] = RESTORE_COMPLETE;
exit_instrs[1] = ILLEGAL_INSTR;
exit_instrs[2] = NOP_INSTR;
exit_instrs[3] = BR_INSTR; break; case SPU_STOPPED_STATUS_S: /* SPU_Status[S]=1. Add two 'nop' instructions. */
exit_instrs[0] = RESTORE_COMPLETE;
exit_instrs[1] = NOP_INSTR;
exit_instrs[2] = NOP_INSTR;
exit_instrs[3] = BR_INSTR; break; case SPU_STOPPED_STATUS_H: /* SPU_Status[H]=1. Add 'heq $0, $0' instruction * after end of restore code.
*/
exit_instrs[0] = RESTORE_COMPLETE;
exit_instrs[1] = HEQ_INSTR;
exit_instrs[2] = NOP_INSTR;
exit_instrs[3] = BR_INSTR; break; case SPU_STOPPED_STATUS_P: /* SPU_Status[P]=1. Add stop-and-signal instruction * after end of restore code.
*/
exit_instrs[0] = RESTORE_COMPLETE;
exit_instrs[1] = STOP_INSTR | stopped_code; break; case SPU_STOPPED_STATUS_R: /* SPU_Status[I,S,H,P,R]=0. Add infinite loop. */
exit_instrs[0] = RESTORE_COMPLETE;
exit_instrs[1] = NOP_INSTR;
exit_instrs[2] = NOP_INSTR;
exit_instrs[3] = BR_INSTR; break; default: /* SPU_Status[R]=1. No additional instructions. */ break;
}
spu_sync();
}
/** * main - entry point for SPU-side context restore. * * This code deviates from the documented sequence in the * following aspects: * * 1. The EA for LSCSA is passed from PPE in the * signal notification channels. * 2. The register spill area is pulled by SPU * into LS, rather than pushed by PPE. * 3. All 128 registers are restored by exit(). * 4. The exit() function is modified at run * time in order to properly restore the * SPU_Status register.
*/ int main()
{
addr64 lscsa_ea;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.