📄 400x.c
字号:
/************************************************************* * File: bsps/400x.c * Purpose: provide 400x-specific routines for SerialICE drivers * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970218 Created using code from d4003.c * 970218 Moved do_icache/dcache here from iceif.c * 970224 Disabled dcache dataram printing. * 970225 Fixed the dcache dataram printing. * 970226 Removed lockbit check. * 970226 Various changes to optimize flushes. * 970226 Fixed soft iflush. Set 1 is lockable not set0. * 970226 Added stuff to i/dcache_opts[]. * 970226 Removed set selection from dcache cmd. * 970227 Added code to force alignment in cache display funcs. * 970305 Switched i/dcache to use get_rsa(). * 970310 moved brkInstall and brkRemove here from iceif.c and * rewrote them. * 970310 Created ilockReq, hwibReq, and hwdbReq. * 970311 Removed write_target from method_ram * 970312 Added -l and -v to icache/dcache * 970312 Merged icache and dcache cmds * 970402 Changed the "don't flush locked entries" to iset0 * I don't understand how it worked before! * 980312 Switched to unified scheme for dll and imon. * 980319 Removed code from ilockReq_400x. * 980323 Ignore flush_cache requests if target is running. * 980421 Added cache_size to cache_cmd * 980720 Added nobrkRemove. Needed for force_getsap. * 980803 Added isset=0 to brkRemove. * 980812 Added return if cache_size == 0. Also setFlushneeded(). * 980823 Removed t0 to hold const. No need for value of zero. * 981026 Added lnsize to flush_cache printDiag. * 981215 Added flush_target_400x_ejtag in an attempt to speed up * the time taken to perform a flush. * 981216 400x ejtag needs dflush after dma downloads. */#ifndef LR4001#define LR4001#endif#include <imon.h>#include <mips.h>#include "iceif.h"#include "defs.h"#ifndef PMCC#include <stdlib.h>#endif#define ONLY_FLUSH_WHEN_NEEDED /* optimize the cache flushes */#define LCK_BIT (1<<4)#define USE_SINGLE_LINE_FLUSH /* use single-line flushes when possible */#define k12k0(a) (((Ulong)(a))&~(1<<29))char *dirty_icache_line;char *dirty_dcache_line;void setupcacheline_400x(Ulong addr);void markIcacheDirty(Ulong addr,int size);void markDcacheDirty(Ulong addr,int size);/************************************************************** void flush_target_400x(mode)* Flush the designated cache in the target.*/void flush_target_400x(int mode){Ulong cfg,tmpcfg;/* flush_target_400x: The gpr[10]s in this func were 26 (k0) *//* flush_target_400x: The gpr[11]s in this func were 26 (k1) *//* emit code to flush the caches *//* we are already in an isr with ints disabled *//* the instr buffer is in kseg1 */if (!target_stopped) return; /* 980323 */if (need_initial_flush) { printDiag(1,"performing initial flush 400x\n"); need_initial_flush = 0; flush_target_400x(DCACHEI); flush_target_400x(ICACHEI); }switch (mode) { case ICACHEI : printDiag(1,"\niflush 400x size=%d lnsize=%d\n", icache_size,cache_line_size); if (icache_size == 0) { iflush_needed = 0; return; } send_buffer(); cfg = read_target(XT_MEM,M_CFG4001,4); tmpcfg = cfg; tmpcfg &= ~(CFG_CMODEMASK|CFG_IS1EN|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= (CFG_ICEN|CFG_DCEN|CFG_CMODE_ITEST); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpr(8,tmpcfg); writeGpr(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* actual cache code */ writeGpr(9,K0BASE); writeGpr(8,K0BASE+icache_size); /* flush loop */ send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,cache_line_size)); send_instr(BNE(8,9,-3)); readA0(); /* flush Icache set1 */ tmpcfg = cfg; tmpcfg &= ~(CFG_CMODEMASK|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= (CFG_ICEN|CFG_IS1EN|CFG_DCEN|CFG_CMODE_ITEST); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpr(8,tmpcfg); writeGpr(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* actual cache code */ writeGpr(9,K0BASE); writeGpr(8,K0BASE+icache_size); /* flush loop */ send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,cache_line_size)); send_instr(BNE(8,9,-3)); readA0(); iflush_needed = 0; break; case ICACHE :#ifdef ONLY_FLUSH_WHEN_NEEDED if (!iflush_needed) return;#endif printDiag(1,"\nsoft iflush 400x size=%d lnsize=%d\n", icache_size,cache_line_size); if (icache_size == 0) { iflush_needed = 0; return; } send_buffer(); cfg = read_target(XT_MEM,M_CFG4001,4); tmpcfg = cfg; tmpcfg &= ~(CFG_CMODEMASK|CFG_IS1EN|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= (CFG_ICEN|CFG_DCEN|CFG_CMODE_ITEST); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpr(8,tmpcfg); writeGpr(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* actual cache code */ writeGpr(9,K0BASE); writeGpr(8,K0BASE+icache_size); /* flush loop */#if 1 /* only flush non-locked entries */ /* 970226 only set 1 is lockable */ /* 970402 Wrong! only set0 is lockable */ send_instr(LW(10,0,9)); send_instr(0); /* nop */ send_instr(SLLV(10,27)); send_instr(BLTZ(10,2)); send_instr(0); /* nop */ send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,cache_line_size)); send_instr(BNE(8,9,-8));#else send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,cache_line_size)); send_instr(BNE(8,9,-3));#endif readA0(); /* flush Icache set1 */ tmpcfg = cfg; tmpcfg &= ~(CFG_CMODEMASK|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= (CFG_ICEN|CFG_IS1EN|CFG_DCEN|CFG_CMODE_ITEST); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpr(8,tmpcfg); writeGpr(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* actual cache code */ writeGpr(9,K0BASE); writeGpr(8,K0BASE+icache_size); /* flush loop */#if 0 /* only flush non-locked entries */ /* 970226 only set 1 is lockable. */ /* 970402 Wrong! only set0 is lockable */ send_instr(LW(10,0,9)); send_instr(0); /* nop */ send_instr(SLLV(10,27)); send_instr(BLTZ(10,2)); send_instr(0); /* nop */ send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,cache_line_size)); send_instr(BNE(8,9,-8));#else send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,cache_line_size)); send_instr(BNE(8,9,-3));#endif readA0(); iflush_needed = 0; break; case DCACHE :#ifdef ONLY_FLUSH_WHEN_NEEDED if (!dflush_needed) return;#endif case DCACHEI : printDiag(1,"\ndflush 400x size=%d lnsize=%d\n", dcache_size,cache_line_size); if (dcache_size == 0) { dflush_needed = 0; return; } send_buffer(); /* flush Dcache set0 */ cfg = read_target(XT_MEM,M_CFG4001,4); tmpcfg = cfg; tmpcfg &= ~(CFG_CMODEMASK|CFG_ICEN|CFG_IS1EN|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= (CFG_DCEN|CFG_CMODE_DTEST); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpr(8,tmpcfg); writeGpr(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* actual cache code */ writeGpr(9,K0BASE); writeGpr(8,K0BASE+dcache_size); /* flush loop */ send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,cache_line_size)); send_instr(BNE(8,9,-3)); readA0(); dflush_needed = 0; break; }/* restore cfg reg *//* write_target(XT_MEM,M_CFG4001,cfg,4); */writeGpr(8,cfg);writeGpr(9,M_CFG4001);send_instr(SW(8,0,9));send_instr(0);readA0();}/**************************************************************/Ulong readCache_400x(set,what,addr)int set,what;Ulong addr;{Ulong cfg,tmpcfg,val;/* we are already in an isr with ints disabled *//* the instr buffer is in kseg1 */tmpcfg = cfg = read_target(XT_MEM,M_CFG4001,4);tmpcfg &= ~(CFG_CMODEMASK|CFG_IS1EN|CFG_ICEN|CFG_DSIZEMASK|CFG_ISIZEMASK);tmpcfg |= CFG_DCEN;tmpcfg &= ~(CFG_WBEN|CFG_PGSZMASK);if (what == ICACHETAG) tmpcfg |= (CFG_ICEN|CFG_CMODE_ITEST);else if (what == ICACHERAM) tmpcfg |= (CFG_ICEN|CFG_CMODE_IDATA);else if (what == DCACHETAG) tmpcfg |= CFG_CMODE_DTEST;else if (what == DCACHERAM) return(0); /* there is no way to read this */if ((what == ICACHERAM || what == ICACHETAG) && set) tmpcfg |= CFG_IS1EN;else if (what == DCACHERAM || what == DCACHETAG) /* only one set */ ;send_buffer();/* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */writeGpr(8,tmpcfg);writeGpr(9,M_CFG4001);send_instr(SW(8,0,9));send_instr(0);send_instr(0);send_instr(0);/* val = read_target(XT_MEM,addr,4); */writeGpr(9,addr);send_instr(LW(4,0,9));send_instr(0);send_instr(0);send_instr(0);/* restore cfg reg write_target(XT_MEM,M_CFG4001,cfg,4); */writeGpr(8,cfg);writeGpr(9,M_CFG4001);send_instr(SW(8,0,9));send_instr(0);send_instr(0);send_instr(0);val = readA0();return(val);}/**************************************************************/static void writeCache(int set,int what,Ulong addr,Ulong val,int sz){Ulong cfg,tmpcfg;/* The target is already in an isr with ints disabled *//* the instr buffer is in kseg1 */tmpcfg = cfg = read_target(XT_MEM,M_CFG4001,4);tmpcfg &= ~(CFG_CMODEMASK|CFG_IS1EN|CFG_ICEN|CFG_DSIZEMASK|CFG_ISIZEMASK);tmpcfg |= CFG_DCEN;if (what == ICACHETAG) tmpcfg |= (CFG_ICEN|CFG_CMODE_ITEST);else if (what == ICACHERAM) tmpcfg |= (CFG_ICEN|CFG_CMODE_IDATA);else if (what == DCACHETAG) tmpcfg |= CFG_CMODE_DTEST;else if (what == DCACHERAM) ;if ((what == ICACHERAM || what == ICACHETAG) && set) tmpcfg |= CFG_IS1EN;else if (what == DCACHERAM || what == DCACHETAG) /* only one set */ ;send_buffer();/* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */writeGpr(8,tmpcfg);writeGpr(9,M_CFG4001);send_instr(SW(8,0,9));send_instr(0);send_instr(0);send_instr(0);/* write value to cache */writeGpr(8,val);writeGpr(9,addr);if (sz == 4) send_instr(SW(8,0,9));else if (sz == 2) send_instr(SH(8,0,9));else send_instr(SB(8,0,9));send_instr(0);send_instr(0);send_instr(0);/* write_target(XT_MEM,M_CFG4001,cfg,4); */writeGpr(8,cfg);writeGpr(9,M_CFG4001);send_instr(SW(8,0,9));send_instr(0);send_instr(0);send_instr(0);readA0();}#ifdef PMCC/**************************************************************/Optdesc cache_opts_400x[] = { {"[-vidl][set [addr [value]]]","display cache"}, {"set","select set (default 0)"}, {"addr","specify address"}, {"-i","display icache"}, {"-d","display dcache (default)"}, {"-v","display only valid entries"}, {"-l","display only locked entries"}, {"-w","write entry"}, {"-t","write tag entry"}, {0}};void cache_cmd_400x(ac,av)int ac;char *av[];{int n,i,j,set,vflag,lflag,iflag,wflag,tflag,cachetag;static Ulong next_adr;Ulong adr,tag,msk,dadr,val;int cache_size;vflag = lflag = iflag = wflag = tflag = 0;for (n=0,i=1;i<ac;i++) { if (av[i][0] == '-') { for (j=1;av[i][j];j++) { if (av[i][j] == 'v') vflag = 1; else if (av[i][j] == 'l') lflag = 1; else if (av[i][j] == 'i') iflag = 1; else if (av[i][j] == 'd') iflag = 0; else if (av[i][j] == 'w') wflag = 1; else if (av[i][j] == 't') tflag = 1; else { printf("%s: unknown option\n",av[i][j]); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -