📄 cache.c
字号:
/* Cache code for SPARClite * * Copyright (c) 1998 Cygnus Support * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. */#include "sparclite.h"/* Ancillary registers on the DANlite */#define DIAG 30#define ICCR 31/* Bits in the DIAG register */#define ICD 0x40000000 /* ICACHE disable */#define DCD 0x20000000 /* DCACHE disable *//* Bits in the ICCR register */#define CE 1 /* cache enable*//* Forward declarations. */void flush_i_cache ();/* Determine if this is a DANlite (MB8686x), as opposed to an earlier SPARClite (MB8683x). This is done by examining the impl and ver fields in the PSR: MB8683x: impl(bit31-28)=0x0; ver(bit27-24)=0xf; MB8686x: impl(bit31-28)=0x1; ver(bit27-24)=0xe;*/static intis_danlite (){ static int checked = 0; static int danlite = 0; if (!checked) { int psr = read_psr (); danlite = (psr & 0xff000000) == 0x1e000000; checked = 1; } return danlite;}/* This cache code is known to work on both the 930 & 932 processors. It just cheats and clears the all of the address space that could contain tags, as opposed to striding the tags at 8 or 16 word intervals, or using the cache flush registers, which don't exist on all processors. */voidcache_off (){ if (is_danlite ()) { /* Disable the ICACHE. Disabling the DCACHE crashes the machine. */ unsigned int diag = read_asr (DIAG); write_asr (DIAG, diag | ICD); } else { write_asi (1, 0, 0); }}voidcache_on (){ if (is_danlite ()) { unsigned int diag; /* Flush the caches. */ flush_i_cache (); /* Enable the ICACHE and DCACHE */ diag = read_asr (DIAG); write_asr (DIAG, diag & ~ (ICD | DCD)); } else { unsigned long addr; cache_off (); /* Make sure the cache is off */ /* Reset all of the cache line valid bits */ for (addr = 0; addr < 0x1000; addr += 8) { write_asi (0xc, addr, 0); /* Clear bank 1, icache */ write_asi (0xc, addr + 0x80000000, 0); /* Clear bank 2, icache */ write_asi (0xe, addr, 0); /* Clear bank 1, dcache */ write_asi (0xe, addr + 0x80000000, 0); /* Clear bank 2, dcache */ } /* turn on the cache */ write_asi (1, 0, 0x35); /* Write buf ena, prefetch buf ena, data & inst caches enab */ }}/* Flush the instruction cache. We need to do this for the debugger stub so that breakpoints, et. al. become visible to the instruction stream after storing them in memory. */voidflush_i_cache (){ if (is_danlite ()) { write_asi (0x31, 0, 0); /* Flush entire i/d caches */ } else { int cache_reg; unsigned long addr; cache_reg = read_asi (1, 0); /* Read cache/bus interface reg */ if (!(cache_reg & 1)) return; /* Just return if cache is already off */ for (addr = 0; addr < 0x1000; addr += 8) { write_asi (0xc, addr, 0); /* Clear bank 1, icache */ write_asi (0xc, addr + 0x80000000, 0); /* Clear bank 2, icache */ } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -