static inline void restore_decr(void) { unsigned int offset; unsigned int decr_running; unsigned int decr; /* 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); } }
static inline void save_tag_mask(void) { unsigned int offset; /* Save, Step 3: * Read the SPU_RdTagMsk channel and save to the LSCSA. */ offset = LSCSA_QW_OFFSET(tag_mask); regs_spill[offset].slot[0] = spu_readch(MFC_RdTagMask); }
static inline void save_event_mask(void) { unsigned int offset; /* Save, Step 2: * Read the SPU_RdEventMsk channel and save to the LSCSA. */ offset = LSCSA_QW_OFFSET(event_mask); regs_spill[offset].slot[0] = spu_readch(SPU_RdEventMask); }
static inline void save_decr(void) { unsigned int offset; /* Save, Step 10: * Read and save the SPU_RdDec channel data to * the LSCSA. */ offset = LSCSA_QW_OFFSET(decr); regs_spill[offset].slot[0] = spu_readch(SPU_RdDec); }
static inline void save_srr0(void) { unsigned int offset; /* Save, Step 11: * Read and save the SPU_WSRR0 channel data to * the LSCSA. */ offset = LSCSA_QW_OFFSET(srr0); regs_spill[offset].slot[0] = spu_readch(SPU_RdSRR0); }
static inline void restore_tag_mask(void) { unsigned int offset; unsigned int tag_mask; /* Restore, Step 16: * Restore the SPU_RdTagMsk data from the LSCSA. */ offset = LSCSA_QW_OFFSET(tag_mask); tag_mask = regs_spill[offset].slot[0]; spu_writech(MFC_WrTagMask, tag_mask); }
static inline void restore_event_mask(void) { unsigned int offset; unsigned int event_mask; /* Restore, Step 15: * Restore the SPU_RdEventMsk data from the LSCSA. */ offset = LSCSA_QW_OFFSET(event_mask); event_mask = regs_spill[offset].slot[0]; spu_writech(SPU_WrEventMask, event_mask); }
static inline void restore_srr0(void) { unsigned int offset; unsigned int srr0; /* Restore, Step 14: * Restore the SPU SRR0 data from the LSCSA. */ offset = LSCSA_QW_OFFSET(srr0); srr0 = regs_spill[offset].slot[0]; spu_writech(SPU_WrSRR0, srr0); }
static inline void save_fpcr(void) { // vector unsigned int fpcr; unsigned int offset; /* Save, Step 9: * Issue the floating-point status and control register * read instruction, and save to the LSCSA. */ offset = LSCSA_QW_OFFSET(fpcr); regs_spill[offset].v = spu_mffpscr(); }
static inline void restore_fpcr(void) { unsigned int offset; vector unsigned int fpcr; /* 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); }
static inline void write_ppuint_mb(void) { unsigned int offset; unsigned int 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); }
static inline void restore_complete(void) { extern void exit_fini(void); unsigned int *exit_instrs = (unsigned int *)exit_fini; unsigned int offset; unsigned int stopped_status; unsigned int stopped_code; /* 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. */ offset = LSCSA_QW_OFFSET(stopped_status); stopped_status = regs_spill[offset].slot[0]; stopped_code = regs_spill[offset].slot[1]; 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 additonal instructions. */ break; } spu_sync(); }