📄 iceif.c
字号:
/************************************************************** void write_target(int type,Ulong addr,Ulong v,int sz) DEF*/void write_target(int type,Ulong addr,Ulong v,int sz){int reg;printDiag(1,"write_target(%s,%08x,%08x,%d)\n", xtcodes[type],addr,v,sz);reg = addr;switch (type) { case XT_PC : switch (reg) { case 0 : getSAP(); if (savearea.vers > 1) write_target(XT_MEM,(Ulong)(ICE_EPC+savearea.sap),v,4); else write_target(XT_MEM,(Ulong)(ICE_OLD_EPC+savearea.sap),v,4); break; case 1 : writeGpr(8,v); send_instr(OP_MTHI|(8<<21)); break; case 2 : writeGpr(8,v); send_instr(OP_MTLO|(8<<21)); break; } break; /* 990319 */ case XT_MEM : if (!savearea.sap) getSAP(); /* 980818 */ /* Be sure that sap info is known before starting to * fill the buffer. Otherwise download can fail. */#if 0 /* 981222 This screws up 4011 downloads. The 3 bytes at the beginning of each block gets corrupted. I can't see why I thought I needed it. */ if (is_cacheable(addr) && has_wb_dcache && dcache_dirty) flush_target(DCACHE);#endif switch (sz) { case 1 : write_target_byte(addr,v); break; case 2 : /* 980704 This is a hack */ send_buffer(); send_bhw(addr,v,2); break; case 4 : if (is_bptReq(addr,v)) break; if (lendian_target) swap32n((Uchar *)&v,1); write_target_byte(addr,v>>24); write_target_byte(addr+1,v>>16); write_target_byte(addr+2,v>>8); write_target_byte(addr+3,v); break; } break; case XT_GPR : writeUgpr(reg,v); break; case XT_CP0 : writeGpr(8,v); send_instr(MTC0(8,reg)); v = readA0(); break; case XT_CP1 : writeGpr(8,v); send_instr(OP_MTC1|(8<<16)|(reg<<11)); v = readA0(); break; case XT_CP1C : writeGpr(8,v); send_instr(OP_CTC1|(8<<16)|(reg<<11)); v = readA0(); break; case XT_DBX : writeGpr(8,v); send_instr(MTD(8,reg)); v = readA0(); break; case XT_CP2 : case XT_CP2C : case XT_CP3 : case XT_CP3C : default : printDiag(0,"%08x: write_target: bad type\n",type); }}/************************************************************** int writeGpr(int reg,Ulong v) DEF*/int writeGpr(reg,v)int reg;Ulong v;{long n;int t,cnt;printDiag(2,"writeGpr(%d,%08x)\n",reg,v);if (reg == 8) current_r8 = v;else if (reg == 9) current_r9 = v;t = cnt = 0;n = (long)v;send_buffer();if (n >= -32768 && n <= 32767) { send_instr(OP_ADDIU|(reg<<16)|(0<<21)|v&0xffff); cnt++; }else { if (v&0xffff0000) { send_instr(OP_LUI|(reg<<16)|(v>>16)); t = reg; cnt++; } if (v&0xffff) { send_instr(OP_ORI|(reg<<16)|(t<<21)|(v&0xffff)); cnt++; } }return(cnt);}/************************************************************** Ulong read_target(int type,Ulong addr,int sz) DEF*/Ulong read_target(int type,Ulong addr,int sz){int reg,offs,diff;Ulong v;OcmRec *p;printDiag(1,"read_target(%s,%08x,%d) ",xtcodes[type],addr,sz);send_buffer();reg = addr;switch (type) { case XT_PC : switch (reg) { case 0 : /* PC */ getSAP(); if (savearea.vers > 1) return read_target(XT_MEM,(Ulong)(ICE_EPC+savearea.sap),4); else return read_target(XT_MEM,(Ulong)(ICE_OLD_EPC+savearea.sap),4); case 1 : /* HI */ send_instr(OP_MFHI|(4<<11)); return readA0(); case 2 : /* LO */ send_instr(OP_MFLO|(4<<11)); return readA0(); } case XT_MEM : if ((p=is_ocm(addr)) && p->func) { return run_ocm(p,0,addr,sz,v); } if (sz == 4 && addr&3) { /* 970401 half-word aligned */ addr &= ~1; /* clear LS bit */ v = read_target(XT_MEM,addr,2)<<16; v |= read_target(XT_MEM,addr+2,2); return(v); } offs=0; diff = addr-current_r9; if (diff < -32768 || diff > 32767) writeGpr(9,addr); else offs = (addr-current_r9)&0xffff; switch (sz) { case 1 : send_instr(OP_LBU|(4<<16)|(9<<21)|offs); break; case 2 : send_instr(OP_LHU|(4<<16)|(9<<21)|offs); break; case 4 : send_instr(LW(4,offs,9)); break; } return readA0(); case XT_GPR : return readUgpr(reg); case XT_CP0 : send_instr(MFC0(4,reg)); return readA0(); case XT_CP1 : send_instr(OP_MFC1|(4<<16)|(reg<<11)); return readA0(); case XT_CP1C : send_instr(OP_CFC1|(4<<16)|(reg<<11)); return readA0(); case XT_DBX : send_instr(MFD(4,reg)); return readA0(); break; case XT_CP2 : case XT_CP2C : case XT_CP3 : case XT_CP3C : default : printDiag(0,"%08x: read_target: bad type\n",type); }return(0);}/************************************************************** Ulong readUgpr(int reg);* Read user's GP register*/Ulong readUgpr(int reg){Ulong msk,v;int i,n;printDiag(1,"readUgpr(%d)\n",reg);getSAP();send_buffer();if (savearea.vers == 1) { switch (reg) { case 2 : /* v0 */ v = read_target(XT_MEM,(Ulong)(ICE_V0+savearea.sap),4); break; case 4 : /* a0 */ v = read_target(XT_MEM,(Ulong)(ICE_A0+savearea.sap),4); break; case 5 : /* a1 */ v = read_target(XT_MEM,(Ulong)(ICE_A1+savearea.sap),4); break; case 8 : /* t0 */ v = read_target(XT_MEM,(Ulong)(ICE_T0+savearea.sap),4); break; case 9 : /* t1 */ v = read_target(XT_MEM,(Ulong)(ICE_T1+savearea.sap),4); break; case 10 : /* t2 */ v = read_target(XT_MEM,(Ulong)(ICE_T2+savearea.sap),4); break; case 16: /* s0 */ v = read_target(XT_MEM,(Ulong)(ICE_S0+savearea.sap),4); break; case 31: /* ra */ v = read_target(XT_MEM,(Ulong)(ICE_RA+savearea.sap),4); break; case 32 : send_instr(OP_MFHI|(4<<11)); v = readA0(); break; case 33 : send_instr(OP_MFLO|(4<<11)); v = readA0(); break; default : if (reg == 30 && no_gpr30) return(0); send_instr(OP_OR|(4<<11)|(0<<16)|(reg<<21)); v = readA0(); } return(v); }if (reg == 30 && no_gpr30) return(0);else if (reg == 32) { send_instr(OP_MFHI|(4<<11)); v = readA0(); }else if (reg == 33) { send_instr(OP_MFLO|(4<<11)); v = readA0(); }else if (savearea.map&(1<<reg)) { /* reg is in save area */ msk = 1; for (i=n=0;i<reg;i++) { if (savearea.map&msk) n++; msk <<= 1; } printDiag(1,"readUgpr hsize=%d n=%d\n",savearea.hsize,n); v = read_target(XT_MEM,(Ulong)(savearea.hsize+n+savearea.sap),4); }else { /* reg not in save area */ send_instr(OP_OR|(4<<11)|(0<<16)|(reg<<21)); v = readA0(); }return(v);}/************************************************************** void writeUgpr(int reg,Ulong v);* Write user's GP register*/void writeUgpr(int reg,Ulong v){Ulong msk;int i,n;printDiag(1,"writeUgpr(%d,%08x)\n",reg,v);getSAP();send_buffer();if (savearea.vers == 1) { switch (reg) { case 2 : /* v0 */ write_target(XT_MEM,(Ulong)(ICE_V0+savearea.sap),v,4); break; case 4 : /* a0 */ write_target(XT_MEM,(Ulong)(ICE_A0+savearea.sap),v,4); break; case 5 : /* a1 */ write_target(XT_MEM,(Ulong)(ICE_A1+savearea.sap),v,4); break; case 8 : /* t0 */ write_target(XT_MEM,(Ulong)(ICE_T0+savearea.sap),v,4); break; case 9 : /* t1 */ write_target(XT_MEM,(Ulong)(ICE_T1+savearea.sap),v,4); break; case 10 : /* t2 */ write_target(XT_MEM,(Ulong)(ICE_T2+savearea.sap),v,4); break; case 16: /* s0 */ write_target(XT_MEM,(Ulong)(ICE_S0+savearea.sap),v,4); break; case 31: /* ra */ write_target(XT_MEM,(Ulong)(ICE_RA+savearea.sap),v,4); break; case 32 : writeGpr(8,v); send_instr(OP_MTHI|(8<<21)); break; case 33 : writeGpr(8,v); send_instr(OP_MTLO|(8<<21)); break; default : if (reg == 30 && no_gpr30) break; writeGpr(reg,v); } readA0(); return; }if (reg == 30 && no_gpr30) return;else if (reg == 32) { writeGpr(8,v); send_instr(OP_MTHI|(8<<21)); readA0(); }else if (reg == 33) { writeGpr(8,v); send_instr(OP_MTLO|(8<<21)); readA0(); }else if (savearea.map&(1<<reg)) { /* reg is in save area */ msk = 1; for (i=n=0;i<reg;i++) { if (savearea.map&msk) n++; msk <<= 1; } write_target(XT_MEM,(Ulong)(savearea.hsize+n+savearea.sap),v,4); }else { /* reg not in save area */ writeGpr(reg,v); readA0(); }}/************************************************************** void freeOcmRec(OcmRec *p)* add the OcmRec to freeOcmChain* I do this because the IMON interface in crt3.s doesn't* support free();*/void freeOcmRec(OcmRec *p){p->next = freeOcmChain;freeOcmChain = p;}/************************************************************** OcmRec *mallocOcmRec(void)* Try to get an OcmRec from freeOcmChain. else use malloc.*/OcmRec *mallocOcmRec(void){OcmRec *p;if (freeOcmChain) { p = freeOcmChain; freeOcmChain = p->next; return(p); }return (OcmRec *)malloc(sizeof(OcmRec));}/************************************************************** OcmRec *addOcmRec(Ulong addr,Ulong size,Ulong *func,int funclen);* arg0 = start address of Ocm region* arg1 = size (in bytes) of Ocm region* arg2 = optional address of access function. else 0.* arg3 = optional length (in words) of access function. else 0.*/OcmRec *addOcmRec(Ulong addr,Ulong size,Ulong *func,int funclen){OcmRec *p;printDiag(1,"addOcmRec(%08x,%08x,%08x,%d)\n",addr,size,func,funclen);p = mallocOcmRec();if (!p) { printDiag(0,"addOcmRec: malloc failure. Out of memory.\n"); return(0); }p->addr = addr;p->size = size;p->func = func;p->funclen = funclen;p->regmap_ok = 0;p->readonly = 0;p->map = 0;p->next = ocmChain;ocmChain = p;return(p);}/************************************************************** int deleteOcmRec(Ulong addr)*/int deleteOcmRec(Ulong addr){OcmRec *p;printDiag(2,"deleteOcmRec(%08x)\n",addr);p = ocmChain;if (!p) return(0);if (p->addr == addr) { /* 1st item in chain */ ocmChain = p->next; freeOcmRec(p); return(1); }for (p=ocmChain;p->next;p=p->next) { if (p->next->addr == addr) { p->next = p->next->next; freeOcmRec(p->next); return(1); } }return(0);}/************************************************************** OcmRec *is_ocm(Ulong addr) DEF* return addr of OcmRec if addr falls within an ocm region.*/OcmRec *is_ocm(addr)Ulong addr;{OcmRec *p;for (p=ocmChain;p;p=p->next) { if (addr >= p->addr && addr < p->addr+p->size) { printDiag(2,"%08x=ocm\n",addr); return(p); } }return(0);}/************************************************************** Ulong run_ocm(OcmRec *ocm,int mode,Ulong addr,int sz,Ulong value);* Run the designated ocm routine.* mode: 0=read 1=write*/Ulong run_ocm(OcmRec *ocm,int mode,Ulong addr,int sz,Ulong value){int i;Ulong need,r;Ulong saved[32];printDiag(1,"run_ocm(x,%s,%08x,%d,%08x)\n",(mode)?"write":"read",addr,sz,value);/* Can't do this if there's no function */if (ocm->func == 0 || ocm->funclen == 0) { printDiag(1,"run_ocm: ERROR: func=%08x funclen=%d\n", ocm->func,ocm->funclen); return(0); }#if 0if (savearea.vers == 1) { printDiag(1,"ocm %08x needs new format savearea.\n",addr); return(0); }#endif/* return if this is a write and ocm region is readonly */if (mode == 1 && ocm->readonly) { printDiag(1,"run_ocm: ERROR: write to ro ocm\n"); return(0); }/* must know regmap and ibs of kernel */if (savearea.map == 0) savearea.map = kernel_map;if (savearea.ibs == 0) savearea.ibs = kernel_ibs;if (savearea.map == 0 || savearea.ibs == 0) { printDiag(1,"run_ocm: ERROR: map=%08x ibs=%d\n", savearea.map,savearea.ibs); return(0); }if (ocm->funclen > ((int)savearea.ibs)) { printDiag(1,"ocm %08x func too large for ibuf.\n",addr); return(0); }if (!ocm->regmap_ok) { send_buffer(); if (ocm->map == 0) { writeGpr(4,2); /* regmap function */ for (i=0;i<ocm->funclen;i++) send_instr(ocm->func[i]); ocm->map = readA0(); } printDiag(1,"ocm %08x samap %08x ocmmap %08x.\n", addr,savearea.map,ocm->map); /* savearea.map is what the kernel saves */ /* ocm.map is what the ocm routine needs */ need = (~(savearea.map&ocm->map)) & ocm->map; /* need are those extra registers that must be saved */ if (need) {#if 0 if ((savearea.map®map) != regmap) { /* incompatible regmaps */ printDiag(1,"ocm %08x bad regmap %08x %08x.\n", addr,savearea.map,regmap); return(0);#endif printDiag(1,"ocm %08x need %08x\n",addr,need); send_buffer(); for (i=0;i<32;i++) { if (need&(1<<i)) { send_instr(OP_OR|(4<<11)|(0<<16)|(i<<21)); saved[i] = readA0(); printDiag(1,"ocm %08x save $%d %08x\n", addr,i,saved[i]); } } } if (!need) ocm->regmap_ok = 1; /* regmap_ok indicates that no extra saves are necessary */ }send_buffer();writeGpr(4,mode);writeGpr(5,addr);writeGpr(6,sz);writeGpr(7,value);for (i=0;i<ocm->funclen;i++) send_instr(ocm->func[i]);r = readA0();/* restore extra regs */if (need) { for (i=0;i<32;i++) if (need&(1<<i)) { printDiag(1,"ocm %08x restore $%d %08x\n", addr,i,saved[i]); writeGpr(i,saved[i]); } readA0(); }return(r);}/************************************************************** Ulong domt1(Ulong sadr,Ulong eadr)* Do Memory test part1*/Ulong domt1(Ulong sadr,Ulong eadr){/* domt1: The gpr[10]s in this func were 26 (k0) *//* domt1: The gpr[11]s in this func were 27 (k1) */send_buffer();/* part1: walking ones */writeGpr(4,sadr);writeGpr(9,eadr);/* 1: */writeGpr(10,1);/* 2: */send_instr(SW(10,0,4));send_instr(LW(11,0,4));send_instr(0);send_instr(BNE(10,11,6)); /* 1f */send_instr(0);send_instr(SLLV(10,1));send_instr(BNE(10,0,-7)); /* 2b */send_instr(0);send_instr(ADDIU(4,4,4));send_instr(BNE(4,9,-11)); /* 1b *//* 1: */return readA0();}/************************************************************** int domt2(Ulong sadr,Ulong eadr)* Do Memory test part2* part2: write address to each word*/void domt2(Ulong sadr,Ulong eadr){send_buffer();writeGpr(4,sadr);writeGpr(9,eadr);/* 1: */send_instr(SW(4,0,4));send_instr(ADDIU(4,4,4));send_instr(BNE(4,9,-3)); /* 1b */readA0();}/************************************************************** Ulong domt3(Ulong sadr,Ulong eadr)* Do Memory test part3* part3: check each word contains address*/Ulong domt3(Ulong sadr,Ulong eadr){/* domt3: The gpr[10]s in this func were 26 (k0) */send_buffer();writeGpr(4,sadr);writeGpr(9,eadr);/* 1: */send_instr(LW(10,0,4));send_instr(0);send_instr(BNE(10,4,3)); /* 1f */send_instr(0);send_instr(ADDIU(4,4,4));send_instr(BNE(4,9,-6)); /* 1b *//* 1: */return readA0();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -