/************************************************************* * File: c401x.c * Purpose: provide 401x-specific routines for PMON * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970515 Created using code from bsps/401x.c */ #ifndef LR4010 #define LR4010 #endif #include #include #define ONLY_FLUSH_WHEN_NEEDED /* optimize the flushes */ #define VALID_BIT (1<<1) #define BUGFIX /* needed for 4010 */ int ilock_active; extern int iflush_needed; extern int dflush_needed; extern int verbose; extern int icache_size; extern int icache_line_size; extern int dcache_line_size; /************************************************************* * Ulong readCache401x(set,what,addr) * read one word from a cache * what: ICACHETAG DCACHETAG ICACHERAM DCACHERAM * Note that *all* LDs and STs go to the cache when ISC is set. */ Ulong readCache401x(set,what,addr) int set,what; Ulong addr; { Ulong ccc,tmpcfg,tag; /* we are already in an isr with ints disabled */ /* the instr buffer is in kseg1 */ tmpcfg = ccc = read_target(XT_CP0,C0_CCC,0).lo; tmpcfg &= ~(CCC_IE1|CCC_IE0|CCC_DE0|CCC_DE1); tmpcfg |= CCC_ISC; if (what == ICACHETAG || what == DCACHETAG) tmpcfg |= CCC_TAG; if (what == ICACHETAG || what == ICACHERAM) { if (set) tmpcfg |= CCC_IE1; else tmpcfg |= CCC_IE0; } else if (what == DCACHETAG || what == DCACHERAM) { if (set) tmpcfg |= CCC_DE1; else tmpcfg |= CCC_DE0; } return specialRead401x(addr,tmpcfg); } /************************************************************* * writeCache401x(set,what,addr,tag) * UNTESTED */ writeCache401x(set,what,addr,tag) int set,what; Ulong addr,tag; { Ulong ccc,tmpcfg; /* we are already in an isr with ints disabled */ /* the instr buffer is in kseg1 */ tmpcfg = ccc = read_target(XT_CP0,C0_CCC,0).lo; tmpcfg &= ~(CCC_IE1|CCC_IE0|CCC_DE0|CCC_DE1); tmpcfg |= CCC_ISC; if (what == ICACHETAG || what == DCACHETAG) tmpcfg |= CCC_TAG; if (what == ICACHETAG || what == ICACHERAM) { if (set) tmpcfg |= CCC_IE1; else tmpcfg |= CCC_IE0; } else if (what == DCACHETAG || what == DCACHERAM) { if (set) tmpcfg |= CCC_DE1; else tmpcfg |= CCC_DE0; } #if 0 writeGpr(8,tmpcfg); send_instr(MTC0(8,C0_CCC)); /* 3 nops before ld or st */ send_instr(0); send_instr(0); send_instr(0); /* write the cache */ writeGpr(8,tag); writeGpr(9,addr); send_instr(SW(8,0,9)); send_instr(0); /* restore CCC */ writeGpr(8,ccc); send_instr(MTC0(8,C0_CCC)); readA0(); #endif } /************************************************************* */ Optdesc cache_opts401x[] = { {"[-idv][set [addr]]","display cache"}, {"set","select set (default 0)"}, {"addr","specify address"}, {"-i","display icache"}, {"-d","display dcache (default)"}, {"-v","display only valid entries"}, {0}}; do_cache401x(ac,av) int ac; char *av[]; { int n,i,j,set,vflag,iflag; int cacheram,cachetag,cache_line_size; static Ulong next_adr; Ulong adr,tag,ccc; U64 rv; vflag = iflag = 0; for (n=0,i=1;i icache_size/cache_line_size) break; tag = readCache401x(set,cachetag,adr); if (vflag && (tag&VALID_BIT)==0) continue; printf("%08x %08x ",adr,readCache401x(set,cacheram,adr)); printf("%08x ",readCache401x(set,cacheram,adr+4)); printf("%08x ",readCache401x(set,cacheram,adr+8)); printf("%08x\n ",readCache401x(set,cacheram,adr+12)); printf("%08x ",readCache401x(set,cacheram,adr+16)); printf("%08x ",readCache401x(set,cacheram,adr+20)); printf("%08x ",readCache401x(set,cacheram,adr+24)); printf("%08x ",readCache401x(set,cacheram,adr+28)); printf(" %08x\n",tag); j++; } next_adr = adr; } /************************************************************* * ilockReq401x(addr) * verify that other ilock bpts don't conflict with this one * (ie. are a cachesize multiple apart). * Also verify that lock bit is not already set. */ ilockReq401x(addr) Ulong addr; { Ulong ccc,tmsk,omsk; int i; ccc = mfc0(C0_CCC); if (ccc&CCC_ISR1) return(0); tmsk = (icache_size)-1; /* tag mask */ omsk = tmsk&~(icache_line_size-1); /* offset mask */ for (i=0;i