1130803Smarcel/* Caching code for GDB, the GNU debugger. 219370Spst 3130803Smarcel Copyright 1992, 1993, 1995, 1996, 1998, 1999, 2000, 2001, 2003 Free 4130803Smarcel Software Foundation, Inc. 5130803Smarcel 619370Spst This file is part of GDB. 719370Spst 819370Spst This program is free software; you can redistribute it and/or modify 919370Spst it under the terms of the GNU General Public License as published by 1019370Spst the Free Software Foundation; either version 2 of the License, or 1119370Spst (at your option) any later version. 1219370Spst 1319370Spst This program is distributed in the hope that it will be useful, 1419370Spst but WITHOUT ANY WARRANTY; without even the implied warranty of 1519370Spst MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1619370Spst GNU General Public License for more details. 1719370Spst 1819370Spst You should have received a copy of the GNU General Public License 1919370Spst along with this program; if not, write to the Free Software 2098944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2198944Sobrien Boston, MA 02111-1307, USA. */ 2219370Spst 2319370Spst#include "defs.h" 2419370Spst#include "dcache.h" 2519370Spst#include "gdbcmd.h" 2619370Spst#include "gdb_string.h" 2746283Sdfr#include "gdbcore.h" 2898944Sobrien#include "target.h" 2919370Spst 3098944Sobrien/* The data cache could lead to incorrect results because it doesn't 3198944Sobrien know about volatile variables, thus making it impossible to debug 3298944Sobrien functions which use memory mapped I/O devices. Set the nocache 3398944Sobrien memory region attribute in those cases. 3419370Spst 3519370Spst In general the dcache speeds up performance, some speed improvement 3619370Spst comes from the actual caching mechanism, but the major gain is in 3719370Spst the reduction of the remote protocol overhead; instead of reading 3819370Spst or writing a large area of memory in 4 byte requests, the cache 3919370Spst bundles up the requests into 32 byte (actually LINE_SIZE) chunks. 4019370Spst Reducing the overhead to an eighth of what it was. This is very 4119370Spst obvious when displaying a large amount of data, 4219370Spst 4319370Spst eg, x/200x 0 4419370Spst 4519370Spst caching | no yes 4619370Spst ---------------------------- 4719370Spst first time | 4 sec 2 sec improvement due to chunking 4819370Spst second time | 4 sec 0 sec improvement due to caching 4919370Spst 5019370Spst The cache structure is unusual, we keep a number of cache blocks 5119370Spst (DCACHE_SIZE) and each one caches a LINE_SIZEed area of memory. 5219370Spst Within each line we remember the address of the line (always a 5319370Spst multiple of the LINE_SIZE) and a vector of bytes over the range. 5419370Spst There's another vector which contains the state of the bytes. 5519370Spst 5619370Spst ENTRY_BAD means that the byte is just plain wrong, and has no 5719370Spst correspondence with anything else (as it would when the cache is 5819370Spst turned on, but nothing has been done to it. 5919370Spst 6019370Spst ENTRY_DIRTY means that the byte has some data in it which should be 6119370Spst written out to the remote target one day, but contains correct 6298944Sobrien data. 6319370Spst 6498944Sobrien ENTRY_OK means that the data is the same in the cache as it is in 6598944Sobrien remote memory. 6619370Spst 6798944Sobrien 6819370Spst The ENTRY_DIRTY state is necessary because GDB likes to write large 6919370Spst lumps of memory in small bits. If the caching mechanism didn't 7019370Spst maintain the DIRTY information, then something like a two byte 7119370Spst write would mean that the entire cache line would have to be read, 7219370Spst the two bytes modified and then written out again. The alternative 7319370Spst would be to not read in the cache line in the first place, and just 7419370Spst write the two bytes directly into target memory. The trouble with 7519370Spst that is that it really nails performance, because of the remote 7619370Spst protocol overhead. This way, all those little writes are bundled 7719370Spst up into an entire cache line write in one go, without having to 7819370Spst read the cache line in the first place. 7998944Sobrien */ 8019370Spst 8198944Sobrien/* NOTE: Interaction of dcache and memory region attributes 8219370Spst 8398944Sobrien As there is no requirement that memory region attributes be aligned 8498944Sobrien to or be a multiple of the dcache page size, dcache_read_line() and 8598944Sobrien dcache_write_line() must break up the page by memory region. If a 8698944Sobrien chunk does not have the cache attribute set, an invalid memory type 8798944Sobrien is set, etc., then the chunk is skipped. Those chunks are handled 8898944Sobrien in target_xfer_memory() (or target_xfer_memory_partial()). 8919370Spst 9098944Sobrien This doesn't occur very often. The most common occurance is when 9198944Sobrien the last bit of the .text segment and the first bit of the .data 9298944Sobrien segment fall within the same dcache page with a ro/cacheable memory 9398944Sobrien region defined for the .text segment and a rw/non-cacheable memory 9498944Sobrien region defined for the .data segment. */ 9519370Spst 9619370Spst/* This value regulates the number of cache blocks stored. 9719370Spst Smaller values reduce the time spent searching for a cache 9819370Spst line, and reduce memory requirements, but increase the risk 9919370Spst of a line not being in memory */ 10019370Spst 10198944Sobrien#define DCACHE_SIZE 64 10219370Spst 10319370Spst/* This value regulates the size of a cache line. Smaller values 10419370Spst reduce the time taken to read a single byte, but reduce overall 10519370Spst throughput. */ 10619370Spst 10798944Sobrien#define LINE_SIZE_POWER (5) 10819370Spst#define LINE_SIZE (1 << LINE_SIZE_POWER) 10919370Spst 11019370Spst/* Each cache block holds LINE_SIZE bytes of data 11119370Spst starting at a multiple-of-LINE_SIZE address. */ 11219370Spst 11398944Sobrien#define LINE_SIZE_MASK ((LINE_SIZE - 1)) 11419370Spst#define XFORM(x) ((x) & LINE_SIZE_MASK) 11519370Spst#define MASK(x) ((x) & ~LINE_SIZE_MASK) 11619370Spst 11719370Spst 11898944Sobrien#define ENTRY_BAD 0 /* data at this byte is wrong */ 11998944Sobrien#define ENTRY_DIRTY 1 /* data at this byte needs to be written back */ 12098944Sobrien#define ENTRY_OK 2 /* data at this byte is same as in memory */ 12119370Spst 12219370Spst 12319370Spststruct dcache_block 12498944Sobrien { 12598944Sobrien struct dcache_block *p; /* next in list */ 12698944Sobrien CORE_ADDR addr; /* Address for which data is recorded. */ 12798944Sobrien char data[LINE_SIZE]; /* bytes at given address */ 12898944Sobrien unsigned char state[LINE_SIZE]; /* what state the data is in */ 12919370Spst 13098944Sobrien /* whether anything in state is dirty - used to speed up the 13198944Sobrien dirty scan. */ 13298944Sobrien int anydirty; 13319370Spst 13498944Sobrien int refs; 13598944Sobrien }; 13619370Spst 13719370Spst 13898944Sobrien/* FIXME: dcache_struct used to have a cache_has_stuff field that was 13998944Sobrien used to record whether the cache had been accessed. This was used 14098944Sobrien to invalidate the cache whenever caching was (re-)enabled (if the 14198944Sobrien cache was disabled and later re-enabled, it could contain stale 14298944Sobrien data). This was not needed because the cache is write through and 14398944Sobrien the code that enables, disables, and deletes memory region all 14498944Sobrien invalidate the cache. 14519370Spst 14698944Sobrien This is overkill, since it also invalidates cache lines from 14798944Sobrien unrelated regions. One way this could be addressed by adding a 14898944Sobrien new function that takes an address and a length and invalidates 14998944Sobrien only those cache lines that match. */ 15019370Spst 15198944Sobrienstruct dcache_struct 15298944Sobrien { 15398944Sobrien /* free list */ 15498944Sobrien struct dcache_block *free_head; 15598944Sobrien struct dcache_block *free_tail; 15619370Spst 15798944Sobrien /* in use list */ 15898944Sobrien struct dcache_block *valid_head; 15998944Sobrien struct dcache_block *valid_tail; 16019370Spst 16198944Sobrien /* The cache itself. */ 16298944Sobrien struct dcache_block *the_cache; 16398944Sobrien }; 16419370Spst 16598944Sobrienstatic int dcache_poke_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr); 16619370Spst 16798944Sobrienstatic int dcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr); 16846283Sdfr 16998944Sobrienstatic struct dcache_block *dcache_hit (DCACHE *dcache, CORE_ADDR addr); 17046283Sdfr 17198944Sobrienstatic int dcache_write_line (DCACHE *dcache, struct dcache_block *db); 17246283Sdfr 17398944Sobrienstatic int dcache_read_line (DCACHE *dcache, struct dcache_block *db); 17446283Sdfr 17598944Sobrienstatic struct dcache_block *dcache_alloc (DCACHE *dcache, CORE_ADDR addr); 17646283Sdfr 17798944Sobrienstatic int dcache_writeback (DCACHE *dcache); 17846283Sdfr 17998944Sobrienstatic void dcache_info (char *exp, int tty); 18046283Sdfr 18198944Sobrienvoid _initialize_dcache (void); 18246283Sdfr 18398944Sobrienstatic int dcache_enabled_p = 0; 18419370Spst 18598944SobrienDCACHE *last_cache; /* Used by info dcache */ 18619370Spst 18719370Spst 18819370Spst/* Free all the data cache blocks, thus discarding all cached data. */ 18919370Spst 19019370Spstvoid 19198944Sobriendcache_invalidate (DCACHE *dcache) 19219370Spst{ 19319370Spst int i; 19419370Spst dcache->valid_head = 0; 19519370Spst dcache->valid_tail = 0; 19619370Spst 19719370Spst dcache->free_head = 0; 19819370Spst dcache->free_tail = 0; 19919370Spst 20019370Spst for (i = 0; i < DCACHE_SIZE; i++) 20119370Spst { 20219370Spst struct dcache_block *db = dcache->the_cache + i; 20319370Spst 20419370Spst if (!dcache->free_head) 20519370Spst dcache->free_head = db; 20619370Spst else 20719370Spst dcache->free_tail->p = db; 20819370Spst dcache->free_tail = db; 20919370Spst db->p = 0; 21019370Spst } 21119370Spst 21219370Spst return; 21319370Spst} 21419370Spst 21519370Spst/* If addr is present in the dcache, return the address of the block 21619370Spst containing it. */ 21746283Sdfr 21846283Sdfrstatic struct dcache_block * 21998944Sobriendcache_hit (DCACHE *dcache, CORE_ADDR addr) 22019370Spst{ 221130803Smarcel struct dcache_block *db; 22219370Spst 22319370Spst /* Search all cache blocks for one that is at this address. */ 22419370Spst db = dcache->valid_head; 22519370Spst 22619370Spst while (db) 22719370Spst { 22898944Sobrien if (MASK (addr) == db->addr) 22919370Spst { 23019370Spst db->refs++; 23119370Spst return db; 23219370Spst } 23319370Spst db = db->p; 23419370Spst } 23519370Spst 23619370Spst return NULL; 23719370Spst} 23819370Spst 23919370Spst/* Make sure that anything in this line which needs to 24019370Spst be written is. */ 24119370Spst 24219370Spststatic int 243130803Smarceldcache_write_line (DCACHE *dcache, struct dcache_block *db) 24419370Spst{ 24598944Sobrien CORE_ADDR memaddr; 24698944Sobrien char *myaddr; 24798944Sobrien int len; 24898944Sobrien int res; 24998944Sobrien int reg_len; 25098944Sobrien struct mem_region *region; 25198944Sobrien 25298944Sobrien if (!db->anydirty) 25398944Sobrien return 1; 25498944Sobrien 25598944Sobrien len = LINE_SIZE; 25698944Sobrien memaddr = db->addr; 25798944Sobrien myaddr = db->data; 25898944Sobrien 25998944Sobrien while (len > 0) 26019370Spst { 26198944Sobrien int s; 26298944Sobrien int e; 26398944Sobrien int dirty_len; 26498944Sobrien 26598944Sobrien region = lookup_mem_region(memaddr); 26698944Sobrien if (memaddr + len < region->hi) 26798944Sobrien reg_len = len; 26898944Sobrien else 26998944Sobrien reg_len = region->hi - memaddr; 27098944Sobrien 27198944Sobrien if (!region->attrib.cache || region->attrib.mode == MEM_RO) 27219370Spst { 27398944Sobrien memaddr += reg_len; 27498944Sobrien myaddr += reg_len; 27598944Sobrien len -= reg_len; 27698944Sobrien continue; 27798944Sobrien } 27898944Sobrien 27998944Sobrien while (reg_len > 0) 28098944Sobrien { 28198944Sobrien s = XFORM(memaddr); 28298944Sobrien while (reg_len > 0) { 28398944Sobrien if (db->state[s] == ENTRY_DIRTY) 28498944Sobrien break; 28598944Sobrien s++; 28698944Sobrien reg_len--; 28798944Sobrien 28898944Sobrien memaddr++; 28998944Sobrien myaddr++; 29098944Sobrien len--; 29198944Sobrien } 29298944Sobrien 29398944Sobrien e = s; 29498944Sobrien while (reg_len > 0) { 29598944Sobrien if (db->state[e] != ENTRY_DIRTY) 29698944Sobrien break; 29798944Sobrien e++; 29898944Sobrien reg_len--; 29998944Sobrien } 30098944Sobrien 30198944Sobrien dirty_len = e - s; 30298944Sobrien while (dirty_len > 0) 30319370Spst { 30498944Sobrien res = do_xfer_memory(memaddr, myaddr, dirty_len, 1, 30598944Sobrien ®ion->attrib); 30698944Sobrien if (res <= 0) 30798944Sobrien return 0; 30898944Sobrien 30998944Sobrien memset (&db->state[XFORM(memaddr)], ENTRY_OK, res); 31098944Sobrien memaddr += res; 31198944Sobrien myaddr += res; 31298944Sobrien len -= res; 31398944Sobrien dirty_len -= res; 31419370Spst } 31519370Spst } 31619370Spst } 31798944Sobrien 31898944Sobrien db->anydirty = 0; 31919370Spst return 1; 32019370Spst} 32119370Spst 32298944Sobrien/* Read cache line */ 32398944Sobrienstatic int 32498944Sobriendcache_read_line (DCACHE *dcache, struct dcache_block *db) 32598944Sobrien{ 32698944Sobrien CORE_ADDR memaddr; 32798944Sobrien char *myaddr; 32898944Sobrien int len; 32998944Sobrien int res; 33098944Sobrien int reg_len; 33198944Sobrien struct mem_region *region; 33219370Spst 33398944Sobrien /* If there are any dirty bytes in the line, it must be written 33498944Sobrien before a new line can be read */ 33598944Sobrien if (db->anydirty) 33698944Sobrien { 33798944Sobrien if (!dcache_write_line (dcache, db)) 33898944Sobrien return 0; 33998944Sobrien } 34098944Sobrien 34198944Sobrien len = LINE_SIZE; 34298944Sobrien memaddr = db->addr; 34398944Sobrien myaddr = db->data; 34498944Sobrien 34598944Sobrien while (len > 0) 34698944Sobrien { 34798944Sobrien region = lookup_mem_region(memaddr); 34898944Sobrien if (memaddr + len < region->hi) 34998944Sobrien reg_len = len; 35098944Sobrien else 35198944Sobrien reg_len = region->hi - memaddr; 35298944Sobrien 35398944Sobrien if (!region->attrib.cache || region->attrib.mode == MEM_WO) 35498944Sobrien { 35598944Sobrien memaddr += reg_len; 35698944Sobrien myaddr += reg_len; 35798944Sobrien len -= reg_len; 35898944Sobrien continue; 35998944Sobrien } 36098944Sobrien 36198944Sobrien while (reg_len > 0) 36298944Sobrien { 36398944Sobrien res = do_xfer_memory (memaddr, myaddr, reg_len, 0, 36498944Sobrien ®ion->attrib); 36598944Sobrien if (res <= 0) 36698944Sobrien return 0; 36798944Sobrien 36898944Sobrien memaddr += res; 36998944Sobrien myaddr += res; 37098944Sobrien len -= res; 37198944Sobrien reg_len -= res; 37298944Sobrien } 37398944Sobrien } 37498944Sobrien 37598944Sobrien memset (db->state, ENTRY_OK, sizeof (db->data)); 37698944Sobrien db->anydirty = 0; 37798944Sobrien 37898944Sobrien return 1; 37998944Sobrien} 38098944Sobrien 38119370Spst/* Get a free cache block, put or keep it on the valid list, 38298944Sobrien and return its address. */ 38346283Sdfr 38446283Sdfrstatic struct dcache_block * 38598944Sobriendcache_alloc (DCACHE *dcache, CORE_ADDR addr) 38619370Spst{ 387130803Smarcel struct dcache_block *db; 38819370Spst 38919370Spst /* Take something from the free list */ 39019370Spst db = dcache->free_head; 39119370Spst if (db) 39219370Spst { 39319370Spst dcache->free_head = db->p; 39419370Spst } 39519370Spst else 39619370Spst { 39719370Spst /* Nothing left on free list, so grab one from the valid list */ 39819370Spst db = dcache->valid_head; 39998944Sobrien 40098944Sobrien if (!dcache_write_line (dcache, db)) 40198944Sobrien return NULL; 40298944Sobrien 40319370Spst dcache->valid_head = db->p; 40419370Spst } 40519370Spst 40698944Sobrien db->addr = MASK(addr); 40798944Sobrien db->refs = 0; 40898944Sobrien db->anydirty = 0; 40998944Sobrien memset (db->state, ENTRY_BAD, sizeof (db->data)); 41098944Sobrien 41119370Spst /* append this line to end of valid list */ 41219370Spst if (!dcache->valid_head) 41319370Spst dcache->valid_head = db; 41419370Spst else 41519370Spst dcache->valid_tail->p = db; 41619370Spst dcache->valid_tail = db; 41719370Spst db->p = 0; 41819370Spst 41919370Spst return db; 42019370Spst} 42119370Spst 42298944Sobrien/* Writeback any dirty lines. */ 42346283Sdfrstatic int 42498944Sobriendcache_writeback (DCACHE *dcache) 42519370Spst{ 42619370Spst struct dcache_block *db; 42719370Spst 42819370Spst db = dcache->valid_head; 42919370Spst 43019370Spst while (db) 43119370Spst { 43219370Spst if (!dcache_write_line (dcache, db)) 43319370Spst return 0; 43419370Spst db = db->p; 43519370Spst } 43619370Spst return 1; 43719370Spst} 43819370Spst 43919370Spst 44098944Sobrien/* Using the data cache DCACHE return the contents of the byte at 44198944Sobrien address ADDR in the remote machine. 44298944Sobrien 44398944Sobrien Returns 0 on error. */ 44498944Sobrien 44598944Sobrienstatic int 44698944Sobriendcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr) 44719370Spst{ 448130803Smarcel struct dcache_block *db = dcache_hit (dcache, addr); 44946283Sdfr 45098944Sobrien if (!db) 45198944Sobrien { 45298944Sobrien db = dcache_alloc (dcache, addr); 45398944Sobrien if (!db) 45498944Sobrien return 0; 45598944Sobrien } 45698944Sobrien 45798944Sobrien if (db->state[XFORM (addr)] == ENTRY_BAD) 45898944Sobrien { 45998944Sobrien if (!dcache_read_line(dcache, db)) 46098944Sobrien return 0; 46198944Sobrien } 46246283Sdfr 46398944Sobrien *ptr = db->data[XFORM (addr)]; 46498944Sobrien return 1; 46519370Spst} 46619370Spst 46719370Spst 46819370Spst/* Write the byte at PTR into ADDR in the data cache. 46919370Spst Return zero on write error. 47019370Spst */ 47119370Spst 47246283Sdfrstatic int 47398944Sobriendcache_poke_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr) 47419370Spst{ 475130803Smarcel struct dcache_block *db = dcache_hit (dcache, addr); 47619370Spst 47719370Spst if (!db) 47819370Spst { 47998944Sobrien db = dcache_alloc (dcache, addr); 48098944Sobrien if (!db) 48198944Sobrien return 0; 48219370Spst } 48319370Spst 48419370Spst db->data[XFORM (addr)] = *ptr; 48519370Spst db->state[XFORM (addr)] = ENTRY_DIRTY; 48619370Spst db->anydirty = 1; 48719370Spst return 1; 48819370Spst} 48919370Spst 49019370Spst/* Initialize the data cache. */ 49119370SpstDCACHE * 49298944Sobriendcache_init (void) 49319370Spst{ 49419370Spst int csize = sizeof (struct dcache_block) * DCACHE_SIZE; 49519370Spst DCACHE *dcache; 49619370Spst 49719370Spst dcache = (DCACHE *) xmalloc (sizeof (*dcache)); 49819370Spst 49919370Spst dcache->the_cache = (struct dcache_block *) xmalloc (csize); 50019370Spst memset (dcache->the_cache, 0, csize); 50119370Spst 50298944Sobrien dcache_invalidate (dcache); 50319370Spst 50419370Spst last_cache = dcache; 50519370Spst return dcache; 50619370Spst} 50719370Spst 50898944Sobrien/* Free a data cache */ 50998944Sobrienvoid 51098944Sobriendcache_free (DCACHE *dcache) 51198944Sobrien{ 51298944Sobrien if (last_cache == dcache) 51398944Sobrien last_cache = NULL; 51498944Sobrien 51598944Sobrien xfree (dcache->the_cache); 51698944Sobrien xfree (dcache); 51798944Sobrien} 51898944Sobrien 51919370Spst/* Read or write LEN bytes from inferior memory at MEMADDR, transferring 52019370Spst to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is 52119370Spst nonzero. 52219370Spst 52319370Spst Returns length of data written or read; 0 for error. 52419370Spst 52519370Spst This routine is indended to be called by remote_xfer_ functions. */ 52619370Spst 52719370Spstint 52898944Sobriendcache_xfer_memory (DCACHE *dcache, CORE_ADDR memaddr, char *myaddr, int len, 52998944Sobrien int should_write) 53019370Spst{ 53119370Spst int i; 53298944Sobrien int (*xfunc) (DCACHE *dcache, CORE_ADDR addr, char *ptr); 53398944Sobrien xfunc = should_write ? dcache_poke_byte : dcache_peek_byte; 53419370Spst 53598944Sobrien for (i = 0; i < len; i++) 53619370Spst { 53798944Sobrien if (!xfunc (dcache, memaddr + i, myaddr + i)) 53898944Sobrien return 0; 53919370Spst } 54019370Spst 54198944Sobrien /* FIXME: There may be some benefit from moving the cache writeback 54298944Sobrien to a higher layer, as it could occur after a sequence of smaller 54398944Sobrien writes have been completed (as when a stack frame is constructed 54498944Sobrien for an inferior function call). Note that only moving it up one 54598944Sobrien level to target_xfer_memory() (also target_xfer_memory_partial()) 54698944Sobrien is not sufficent, since we want to coalesce memory transfers that 54798944Sobrien are "logically" connected but not actually a single call to one 54898944Sobrien of the memory transfer functions. */ 54919370Spst 55098944Sobrien if (should_write) 55198944Sobrien dcache_writeback (dcache); 55298944Sobrien 55319370Spst return len; 55419370Spst} 55519370Spst 55698944Sobrienstatic void 55798944Sobriendcache_info (char *exp, int tty) 55819370Spst{ 55919370Spst struct dcache_block *p; 56019370Spst 56198944Sobrien printf_filtered ("Dcache line width %d, depth %d\n", 56219370Spst LINE_SIZE, DCACHE_SIZE); 56319370Spst 56498944Sobrien if (last_cache) 56519370Spst { 56698944Sobrien printf_filtered ("Cache state:\n"); 56719370Spst 56898944Sobrien for (p = last_cache->valid_head; p; p = p->p) 56998944Sobrien { 57098944Sobrien int j; 57198944Sobrien printf_filtered ("Line at %s, referenced %d times\n", 57298944Sobrien paddr (p->addr), p->refs); 57319370Spst 57498944Sobrien for (j = 0; j < LINE_SIZE; j++) 57598944Sobrien printf_filtered ("%02x", p->data[j] & 0xFF); 57698944Sobrien printf_filtered ("\n"); 57798944Sobrien 57898944Sobrien for (j = 0; j < LINE_SIZE; j++) 57998944Sobrien printf_filtered ("%2x", p->state[j]); 58098944Sobrien printf_filtered ("\n"); 58198944Sobrien } 58219370Spst } 58319370Spst} 58419370Spst 58519370Spstvoid 58698944Sobrien_initialize_dcache (void) 58719370Spst{ 58819370Spst add_show_from_set 58919370Spst (add_set_cmd ("remotecache", class_support, var_boolean, 59098944Sobrien (char *) &dcache_enabled_p, 59119370Spst "\ 59219370SpstSet cache use for remote targets.\n\ 59319370SpstWhen on, use data caching for remote targets. For many remote targets\n\ 59419370Spstthis option can offer better throughput for reading target memory.\n\ 59519370SpstUnfortunately, gdb does not currently know anything about volatile\n\ 59619370Spstregisters and thus data caching will produce incorrect results with\n\ 59798944Sobrienvolatile registers are in use. By default, this option is off.", 59819370Spst &setlist), 59919370Spst &showlist); 60019370Spst 60119370Spst add_info ("dcache", dcache_info, 60219370Spst "Print information on the dcache performance."); 60319370Spst 60419370Spst} 605