0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LS_SIZE
0015 #define LS_SIZE 0x40000
0016 #endif
0017
0018 typedef unsigned int u32;
0019 typedef unsigned long long u64;
0020
0021 #include <spu_intrinsics.h>
0022 #include <asm/spu_csa.h>
0023 #include "spu_utils.h"
0024
0025 #define BR_INSTR 0x327fff80
0026 #define NOP_INSTR 0x40200000
0027 #define HEQ_INSTR 0x7b000000
0028 #define STOP_INSTR 0x00000000
0029 #define ILLEGAL_INSTR 0x00800000
0030 #define RESTORE_COMPLETE 0x00003ffc
0031
0032 static inline void fetch_regs_from_mem(addr64 lscsa_ea)
0033 {
0034 unsigned int ls = (unsigned int)®s_spill[0];
0035 unsigned int size = sizeof(regs_spill);
0036 unsigned int tag_id = 0;
0037 unsigned int cmd = 0x40;
0038
0039 spu_writech(MFC_LSA, ls);
0040 spu_writech(MFC_EAH, lscsa_ea.ui[0]);
0041 spu_writech(MFC_EAL, lscsa_ea.ui[1]);
0042 spu_writech(MFC_Size, size);
0043 spu_writech(MFC_TagID, tag_id);
0044 spu_writech(MFC_Cmd, cmd);
0045 }
0046
0047 static inline void restore_upper_240kb(addr64 lscsa_ea)
0048 {
0049 unsigned int ls = 16384;
0050 unsigned int list = (unsigned int)&dma_list[0];
0051 unsigned int size = sizeof(dma_list);
0052 unsigned int tag_id = 0;
0053 unsigned int cmd = 0x44;
0054
0055
0056
0057
0058
0059 spu_writech(MFC_LSA, ls);
0060 spu_writech(MFC_EAH, lscsa_ea.ui[0]);
0061 spu_writech(MFC_EAL, list);
0062 spu_writech(MFC_Size, size);
0063 spu_writech(MFC_TagID, tag_id);
0064 spu_writech(MFC_Cmd, cmd);
0065 }
0066
0067 static inline void restore_decr(void)
0068 {
0069 unsigned int offset;
0070 unsigned int decr_running;
0071 unsigned int decr;
0072
0073
0074
0075
0076
0077
0078 offset = LSCSA_QW_OFFSET(decr_status);
0079 decr_running = regs_spill[offset].slot[0] & SPU_DECR_STATUS_RUNNING;
0080 if (decr_running) {
0081 offset = LSCSA_QW_OFFSET(decr);
0082 decr = regs_spill[offset].slot[0];
0083 spu_writech(SPU_WrDec, decr);
0084 }
0085 }
0086
0087 static inline void write_ppu_mb(void)
0088 {
0089 unsigned int offset;
0090 unsigned int data;
0091
0092
0093
0094
0095
0096 offset = LSCSA_QW_OFFSET(ppu_mb);
0097 data = regs_spill[offset].slot[0];
0098 spu_writech(SPU_WrOutMbox, data);
0099 }
0100
0101 static inline void write_ppuint_mb(void)
0102 {
0103 unsigned int offset;
0104 unsigned int data;
0105
0106
0107
0108
0109
0110 offset = LSCSA_QW_OFFSET(ppuint_mb);
0111 data = regs_spill[offset].slot[0];
0112 spu_writech(SPU_WrOutIntrMbox, data);
0113 }
0114
0115 static inline void restore_fpcr(void)
0116 {
0117 unsigned int offset;
0118 vector unsigned int fpcr;
0119
0120
0121
0122
0123
0124 offset = LSCSA_QW_OFFSET(fpcr);
0125 fpcr = regs_spill[offset].v;
0126 spu_mtfpscr(fpcr);
0127 }
0128
0129 static inline void restore_srr0(void)
0130 {
0131 unsigned int offset;
0132 unsigned int srr0;
0133
0134
0135
0136
0137 offset = LSCSA_QW_OFFSET(srr0);
0138 srr0 = regs_spill[offset].slot[0];
0139 spu_writech(SPU_WrSRR0, srr0);
0140 }
0141
0142 static inline void restore_event_mask(void)
0143 {
0144 unsigned int offset;
0145 unsigned int event_mask;
0146
0147
0148
0149
0150 offset = LSCSA_QW_OFFSET(event_mask);
0151 event_mask = regs_spill[offset].slot[0];
0152 spu_writech(SPU_WrEventMask, event_mask);
0153 }
0154
0155 static inline void restore_tag_mask(void)
0156 {
0157 unsigned int offset;
0158 unsigned int tag_mask;
0159
0160
0161
0162
0163 offset = LSCSA_QW_OFFSET(tag_mask);
0164 tag_mask = regs_spill[offset].slot[0];
0165 spu_writech(MFC_WrTagMask, tag_mask);
0166 }
0167
0168 static inline void restore_complete(void)
0169 {
0170 extern void exit_fini(void);
0171 unsigned int *exit_instrs = (unsigned int *)exit_fini;
0172 unsigned int offset;
0173 unsigned int stopped_status;
0174 unsigned int stopped_code;
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 offset = LSCSA_QW_OFFSET(stopped_status);
0192 stopped_status = regs_spill[offset].slot[0];
0193 stopped_code = regs_spill[offset].slot[1];
0194
0195 switch (stopped_status) {
0196 case SPU_STOPPED_STATUS_P_I:
0197
0198
0199
0200
0201 exit_instrs[0] = RESTORE_COMPLETE;
0202 exit_instrs[1] = ILLEGAL_INSTR;
0203 exit_instrs[2] = STOP_INSTR | stopped_code;
0204 break;
0205 case SPU_STOPPED_STATUS_P_H:
0206
0207
0208
0209
0210 exit_instrs[0] = RESTORE_COMPLETE;
0211 exit_instrs[1] = HEQ_INSTR;
0212 exit_instrs[2] = STOP_INSTR | stopped_code;
0213 break;
0214 case SPU_STOPPED_STATUS_S_P:
0215
0216
0217
0218
0219 exit_instrs[0] = RESTORE_COMPLETE;
0220 exit_instrs[1] = STOP_INSTR | stopped_code;
0221 exit_instrs[2] = NOP_INSTR;
0222 exit_instrs[3] = BR_INSTR;
0223 break;
0224 case SPU_STOPPED_STATUS_S_I:
0225
0226
0227
0228 exit_instrs[0] = RESTORE_COMPLETE;
0229 exit_instrs[1] = ILLEGAL_INSTR;
0230 exit_instrs[2] = NOP_INSTR;
0231 exit_instrs[3] = BR_INSTR;
0232 break;
0233 case SPU_STOPPED_STATUS_I:
0234
0235
0236
0237 exit_instrs[0] = RESTORE_COMPLETE;
0238 exit_instrs[1] = ILLEGAL_INSTR;
0239 exit_instrs[2] = NOP_INSTR;
0240 exit_instrs[3] = BR_INSTR;
0241 break;
0242 case SPU_STOPPED_STATUS_S:
0243
0244 exit_instrs[0] = RESTORE_COMPLETE;
0245 exit_instrs[1] = NOP_INSTR;
0246 exit_instrs[2] = NOP_INSTR;
0247 exit_instrs[3] = BR_INSTR;
0248 break;
0249 case SPU_STOPPED_STATUS_H:
0250
0251
0252
0253 exit_instrs[0] = RESTORE_COMPLETE;
0254 exit_instrs[1] = HEQ_INSTR;
0255 exit_instrs[2] = NOP_INSTR;
0256 exit_instrs[3] = BR_INSTR;
0257 break;
0258 case SPU_STOPPED_STATUS_P:
0259
0260
0261
0262 exit_instrs[0] = RESTORE_COMPLETE;
0263 exit_instrs[1] = STOP_INSTR | stopped_code;
0264 break;
0265 case SPU_STOPPED_STATUS_R:
0266
0267 exit_instrs[0] = RESTORE_COMPLETE;
0268 exit_instrs[1] = NOP_INSTR;
0269 exit_instrs[2] = NOP_INSTR;
0270 exit_instrs[3] = BR_INSTR;
0271 break;
0272 default:
0273
0274 break;
0275 }
0276 spu_sync();
0277 }
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294 int main()
0295 {
0296 addr64 lscsa_ea;
0297
0298 lscsa_ea.ui[0] = spu_readch(SPU_RdSigNotify1);
0299 lscsa_ea.ui[1] = spu_readch(SPU_RdSigNotify2);
0300 fetch_regs_from_mem(lscsa_ea);
0301
0302 set_event_mask();
0303 set_tag_mask();
0304 build_dma_list(lscsa_ea);
0305 restore_upper_240kb(lscsa_ea);
0306
0307 enqueue_putllc(lscsa_ea);
0308 set_tag_update();
0309 read_tag_status();
0310 restore_decr();
0311 read_llar_status();
0312 write_ppu_mb();
0313 write_ppuint_mb();
0314 restore_fpcr();
0315 restore_srr0();
0316 restore_event_mask();
0317 restore_tag_mask();
0318
0319 restore_complete();
0320
0321 return 0;
0322 }