1b725ae77Skettenis /* Caching code for GDB, the GNU debugger.
2e93f7393Sniklas
3b725ae77Skettenis Copyright 1992, 1993, 1995, 1996, 1998, 1999, 2000, 2001, 2003 Free
4b725ae77Skettenis Software Foundation, Inc.
5e93f7393Sniklas
6e93f7393Sniklas This file is part of GDB.
7e93f7393Sniklas
8e93f7393Sniklas This program is free software; you can redistribute it and/or modify
9e93f7393Sniklas it under the terms of the GNU General Public License as published by
10e93f7393Sniklas the Free Software Foundation; either version 2 of the License, or
11e93f7393Sniklas (at your option) any later version.
12e93f7393Sniklas
13e93f7393Sniklas This program is distributed in the hope that it will be useful,
14e93f7393Sniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
15e93f7393Sniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16e93f7393Sniklas GNU General Public License for more details.
17e93f7393Sniklas
18e93f7393Sniklas You should have received a copy of the GNU General Public License
19e93f7393Sniklas along with this program; if not, write to the Free Software
20b725ae77Skettenis Foundation, Inc., 59 Temple Place - Suite 330,
21b725ae77Skettenis Boston, MA 02111-1307, USA. */
22e93f7393Sniklas
23e93f7393Sniklas #include "defs.h"
24e93f7393Sniklas #include "dcache.h"
25e93f7393Sniklas #include "gdbcmd.h"
26e93f7393Sniklas #include "gdb_string.h"
27e93f7393Sniklas #include "gdbcore.h"
28b725ae77Skettenis #include "target.h"
29e93f7393Sniklas
30b725ae77Skettenis /* The data cache could lead to incorrect results because it doesn't
31b725ae77Skettenis know about volatile variables, thus making it impossible to debug
32b725ae77Skettenis functions which use memory mapped I/O devices. Set the nocache
33b725ae77Skettenis memory region attribute in those cases.
34e93f7393Sniklas
35e93f7393Sniklas In general the dcache speeds up performance, some speed improvement
36e93f7393Sniklas comes from the actual caching mechanism, but the major gain is in
37e93f7393Sniklas the reduction of the remote protocol overhead; instead of reading
38e93f7393Sniklas or writing a large area of memory in 4 byte requests, the cache
39e93f7393Sniklas bundles up the requests into 32 byte (actually LINE_SIZE) chunks.
40e93f7393Sniklas Reducing the overhead to an eighth of what it was. This is very
41e93f7393Sniklas obvious when displaying a large amount of data,
42e93f7393Sniklas
43e93f7393Sniklas eg, x/200x 0
44e93f7393Sniklas
45e93f7393Sniklas caching | no yes
46e93f7393Sniklas ----------------------------
47e93f7393Sniklas first time | 4 sec 2 sec improvement due to chunking
48e93f7393Sniklas second time | 4 sec 0 sec improvement due to caching
49e93f7393Sniklas
50e93f7393Sniklas The cache structure is unusual, we keep a number of cache blocks
51e93f7393Sniklas (DCACHE_SIZE) and each one caches a LINE_SIZEed area of memory.
52e93f7393Sniklas Within each line we remember the address of the line (always a
53e93f7393Sniklas multiple of the LINE_SIZE) and a vector of bytes over the range.
54e93f7393Sniklas There's another vector which contains the state of the bytes.
55e93f7393Sniklas
56e93f7393Sniklas ENTRY_BAD means that the byte is just plain wrong, and has no
57e93f7393Sniklas correspondence with anything else (as it would when the cache is
58e93f7393Sniklas turned on, but nothing has been done to it.
59e93f7393Sniklas
60e93f7393Sniklas ENTRY_DIRTY means that the byte has some data in it which should be
61e93f7393Sniklas written out to the remote target one day, but contains correct
62b725ae77Skettenis data.
63b725ae77Skettenis
64b725ae77Skettenis ENTRY_OK means that the data is the same in the cache as it is in
65b725ae77Skettenis remote memory.
66e93f7393Sniklas
67e93f7393Sniklas
68e93f7393Sniklas The ENTRY_DIRTY state is necessary because GDB likes to write large
69e93f7393Sniklas lumps of memory in small bits. If the caching mechanism didn't
70e93f7393Sniklas maintain the DIRTY information, then something like a two byte
71e93f7393Sniklas write would mean that the entire cache line would have to be read,
72e93f7393Sniklas the two bytes modified and then written out again. The alternative
73e93f7393Sniklas would be to not read in the cache line in the first place, and just
74e93f7393Sniklas write the two bytes directly into target memory. The trouble with
75e93f7393Sniklas that is that it really nails performance, because of the remote
76e93f7393Sniklas protocol overhead. This way, all those little writes are bundled
77e93f7393Sniklas up into an entire cache line write in one go, without having to
78e93f7393Sniklas read the cache line in the first place.
79e93f7393Sniklas */
80e93f7393Sniklas
81b725ae77Skettenis /* NOTE: Interaction of dcache and memory region attributes
82b725ae77Skettenis
83b725ae77Skettenis As there is no requirement that memory region attributes be aligned
84b725ae77Skettenis to or be a multiple of the dcache page size, dcache_read_line() and
85b725ae77Skettenis dcache_write_line() must break up the page by memory region. If a
86b725ae77Skettenis chunk does not have the cache attribute set, an invalid memory type
87b725ae77Skettenis is set, etc., then the chunk is skipped. Those chunks are handled
88b725ae77Skettenis in target_xfer_memory() (or target_xfer_memory_partial()).
89b725ae77Skettenis
90b725ae77Skettenis This doesn't occur very often. The most common occurance is when
91b725ae77Skettenis the last bit of the .text segment and the first bit of the .data
92b725ae77Skettenis segment fall within the same dcache page with a ro/cacheable memory
93b725ae77Skettenis region defined for the .text segment and a rw/non-cacheable memory
94b725ae77Skettenis region defined for the .data segment. */
95e93f7393Sniklas
96e93f7393Sniklas /* This value regulates the number of cache blocks stored.
97e93f7393Sniklas Smaller values reduce the time spent searching for a cache
98e93f7393Sniklas line, and reduce memory requirements, but increase the risk
99e93f7393Sniklas of a line not being in memory */
100e93f7393Sniklas
101e93f7393Sniklas #define DCACHE_SIZE 64
102e93f7393Sniklas
103e93f7393Sniklas /* This value regulates the size of a cache line. Smaller values
104e93f7393Sniklas reduce the time taken to read a single byte, but reduce overall
105e93f7393Sniklas throughput. */
106e93f7393Sniklas
107e93f7393Sniklas #define LINE_SIZE_POWER (5)
108e93f7393Sniklas #define LINE_SIZE (1 << LINE_SIZE_POWER)
109e93f7393Sniklas
110e93f7393Sniklas /* Each cache block holds LINE_SIZE bytes of data
111e93f7393Sniklas starting at a multiple-of-LINE_SIZE address. */
112e93f7393Sniklas
113e93f7393Sniklas #define LINE_SIZE_MASK ((LINE_SIZE - 1))
114e93f7393Sniklas #define XFORM(x) ((x) & LINE_SIZE_MASK)
115e93f7393Sniklas #define MASK(x) ((x) & ~LINE_SIZE_MASK)
116e93f7393Sniklas
117e93f7393Sniklas
118e93f7393Sniklas #define ENTRY_BAD 0 /* data at this byte is wrong */
119e93f7393Sniklas #define ENTRY_DIRTY 1 /* data at this byte needs to be written back */
120e93f7393Sniklas #define ENTRY_OK 2 /* data at this byte is same as in memory */
121e93f7393Sniklas
122e93f7393Sniklas
123e93f7393Sniklas struct dcache_block
124e93f7393Sniklas {
125e93f7393Sniklas struct dcache_block *p; /* next in list */
126e93f7393Sniklas CORE_ADDR addr; /* Address for which data is recorded. */
127e93f7393Sniklas char data[LINE_SIZE]; /* bytes at given address */
128e93f7393Sniklas unsigned char state[LINE_SIZE]; /* what state the data is in */
129e93f7393Sniklas
130e93f7393Sniklas /* whether anything in state is dirty - used to speed up the
131e93f7393Sniklas dirty scan. */
132e93f7393Sniklas int anydirty;
133e93f7393Sniklas
134e93f7393Sniklas int refs;
135e93f7393Sniklas };
136e93f7393Sniklas
137e93f7393Sniklas
138b725ae77Skettenis /* FIXME: dcache_struct used to have a cache_has_stuff field that was
139b725ae77Skettenis used to record whether the cache had been accessed. This was used
140b725ae77Skettenis to invalidate the cache whenever caching was (re-)enabled (if the
141b725ae77Skettenis cache was disabled and later re-enabled, it could contain stale
142b725ae77Skettenis data). This was not needed because the cache is write through and
143b725ae77Skettenis the code that enables, disables, and deletes memory region all
144b725ae77Skettenis invalidate the cache.
145b725ae77Skettenis
146b725ae77Skettenis This is overkill, since it also invalidates cache lines from
147b725ae77Skettenis unrelated regions. One way this could be addressed by adding a
148b725ae77Skettenis new function that takes an address and a length and invalidates
149b725ae77Skettenis only those cache lines that match. */
150b725ae77Skettenis
151e93f7393Sniklas struct dcache_struct
152e93f7393Sniklas {
153e93f7393Sniklas /* free list */
154e93f7393Sniklas struct dcache_block *free_head;
155e93f7393Sniklas struct dcache_block *free_tail;
156e93f7393Sniklas
157e93f7393Sniklas /* in use list */
158e93f7393Sniklas struct dcache_block *valid_head;
159e93f7393Sniklas struct dcache_block *valid_tail;
160e93f7393Sniklas
161e93f7393Sniklas /* The cache itself. */
162e93f7393Sniklas struct dcache_block *the_cache;
163e93f7393Sniklas };
164e93f7393Sniklas
165b725ae77Skettenis static int dcache_poke_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr);
166e93f7393Sniklas
167b725ae77Skettenis static int dcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr);
168e93f7393Sniklas
169b725ae77Skettenis static struct dcache_block *dcache_hit (DCACHE *dcache, CORE_ADDR addr);
170e93f7393Sniklas
171b725ae77Skettenis static int dcache_write_line (DCACHE *dcache, struct dcache_block *db);
172e93f7393Sniklas
173b725ae77Skettenis static int dcache_read_line (DCACHE *dcache, struct dcache_block *db);
174e93f7393Sniklas
175b725ae77Skettenis static struct dcache_block *dcache_alloc (DCACHE *dcache, CORE_ADDR addr);
176e93f7393Sniklas
177b725ae77Skettenis static int dcache_writeback (DCACHE *dcache);
178e93f7393Sniklas
179b725ae77Skettenis static void dcache_info (char *exp, int tty);
180b725ae77Skettenis
181b725ae77Skettenis void _initialize_dcache (void);
182b725ae77Skettenis
183b725ae77Skettenis static int dcache_enabled_p = 0;
184e93f7393Sniklas
185e93f7393Sniklas DCACHE *last_cache; /* Used by info dcache */
186e93f7393Sniklas
187e93f7393Sniklas
188e93f7393Sniklas /* Free all the data cache blocks, thus discarding all cached data. */
189e93f7393Sniklas
190e93f7393Sniklas void
dcache_invalidate(DCACHE * dcache)191b725ae77Skettenis dcache_invalidate (DCACHE *dcache)
192e93f7393Sniklas {
193e93f7393Sniklas int i;
194e93f7393Sniklas dcache->valid_head = 0;
195e93f7393Sniklas dcache->valid_tail = 0;
196e93f7393Sniklas
197e93f7393Sniklas dcache->free_head = 0;
198e93f7393Sniklas dcache->free_tail = 0;
199e93f7393Sniklas
200e93f7393Sniklas for (i = 0; i < DCACHE_SIZE; i++)
201e93f7393Sniklas {
202e93f7393Sniklas struct dcache_block *db = dcache->the_cache + i;
203e93f7393Sniklas
204e93f7393Sniklas if (!dcache->free_head)
205e93f7393Sniklas dcache->free_head = db;
206e93f7393Sniklas else
207e93f7393Sniklas dcache->free_tail->p = db;
208e93f7393Sniklas dcache->free_tail = db;
209e93f7393Sniklas db->p = 0;
210e93f7393Sniklas }
211e93f7393Sniklas
212e93f7393Sniklas return;
213e93f7393Sniklas }
214e93f7393Sniklas
215e93f7393Sniklas /* If addr is present in the dcache, return the address of the block
216e93f7393Sniklas containing it. */
217e93f7393Sniklas
218e93f7393Sniklas static struct dcache_block *
dcache_hit(DCACHE * dcache,CORE_ADDR addr)219b725ae77Skettenis dcache_hit (DCACHE *dcache, CORE_ADDR addr)
220e93f7393Sniklas {
221b725ae77Skettenis struct dcache_block *db;
222e93f7393Sniklas
223e93f7393Sniklas /* Search all cache blocks for one that is at this address. */
224e93f7393Sniklas db = dcache->valid_head;
225e93f7393Sniklas
226e93f7393Sniklas while (db)
227e93f7393Sniklas {
228e93f7393Sniklas if (MASK (addr) == db->addr)
229e93f7393Sniklas {
230e93f7393Sniklas db->refs++;
231e93f7393Sniklas return db;
232e93f7393Sniklas }
233e93f7393Sniklas db = db->p;
234e93f7393Sniklas }
235e93f7393Sniklas
236e93f7393Sniklas return NULL;
237e93f7393Sniklas }
238e93f7393Sniklas
239e93f7393Sniklas /* Make sure that anything in this line which needs to
240e93f7393Sniklas be written is. */
241e93f7393Sniklas
242e93f7393Sniklas static int
dcache_write_line(DCACHE * dcache,struct dcache_block * db)243b725ae77Skettenis dcache_write_line (DCACHE *dcache, struct dcache_block *db)
244b725ae77Skettenis {
245b725ae77Skettenis CORE_ADDR memaddr;
246b725ae77Skettenis char *myaddr;
247b725ae77Skettenis int len;
248b725ae77Skettenis int res;
249b725ae77Skettenis int reg_len;
250b725ae77Skettenis struct mem_region *region;
251b725ae77Skettenis
252b725ae77Skettenis if (!db->anydirty)
253b725ae77Skettenis return 1;
254b725ae77Skettenis
255b725ae77Skettenis len = LINE_SIZE;
256b725ae77Skettenis memaddr = db->addr;
257b725ae77Skettenis myaddr = db->data;
258b725ae77Skettenis
259b725ae77Skettenis while (len > 0)
260e93f7393Sniklas {
261e93f7393Sniklas int s;
262e93f7393Sniklas int e;
263b725ae77Skettenis int dirty_len;
264b725ae77Skettenis
265b725ae77Skettenis region = lookup_mem_region(memaddr);
266b725ae77Skettenis if (memaddr + len < region->hi)
267b725ae77Skettenis reg_len = len;
268b725ae77Skettenis else
269b725ae77Skettenis reg_len = region->hi - memaddr;
270b725ae77Skettenis
271b725ae77Skettenis if (!region->attrib.cache || region->attrib.mode == MEM_RO)
272e93f7393Sniklas {
273b725ae77Skettenis memaddr += reg_len;
274b725ae77Skettenis myaddr += reg_len;
275b725ae77Skettenis len -= reg_len;
276b725ae77Skettenis continue;
277b725ae77Skettenis }
278b725ae77Skettenis
279b725ae77Skettenis while (reg_len > 0)
280e93f7393Sniklas {
281b725ae77Skettenis s = XFORM(memaddr);
282b725ae77Skettenis while (reg_len > 0) {
283e93f7393Sniklas if (db->state[s] == ENTRY_DIRTY)
284b725ae77Skettenis break;
285b725ae77Skettenis s++;
286b725ae77Skettenis reg_len--;
287b725ae77Skettenis
288b725ae77Skettenis memaddr++;
289b725ae77Skettenis myaddr++;
290b725ae77Skettenis len--;
291b725ae77Skettenis }
292b725ae77Skettenis
293b725ae77Skettenis e = s;
294b725ae77Skettenis while (reg_len > 0) {
295e93f7393Sniklas if (db->state[e] != ENTRY_DIRTY)
296e93f7393Sniklas break;
297b725ae77Skettenis e++;
298b725ae77Skettenis reg_len--;
299b725ae77Skettenis }
300b725ae77Skettenis
301b725ae77Skettenis dirty_len = e - s;
302b725ae77Skettenis while (dirty_len > 0)
303e93f7393Sniklas {
304b725ae77Skettenis res = do_xfer_memory(memaddr, myaddr, dirty_len, 1,
305b725ae77Skettenis ®ion->attrib);
306b725ae77Skettenis if (res <= 0)
307e93f7393Sniklas return 0;
308b725ae77Skettenis
309b725ae77Skettenis memset (&db->state[XFORM(memaddr)], ENTRY_OK, res);
310b725ae77Skettenis memaddr += res;
311b725ae77Skettenis myaddr += res;
312b725ae77Skettenis len -= res;
313b725ae77Skettenis dirty_len -= res;
314e93f7393Sniklas }
315e93f7393Sniklas }
316e93f7393Sniklas }
317b725ae77Skettenis
318e93f7393Sniklas db->anydirty = 0;
319e93f7393Sniklas return 1;
320e93f7393Sniklas }
321e93f7393Sniklas
322b725ae77Skettenis /* Read cache line */
323b725ae77Skettenis static int
dcache_read_line(DCACHE * dcache,struct dcache_block * db)324b725ae77Skettenis dcache_read_line (DCACHE *dcache, struct dcache_block *db)
325b725ae77Skettenis {
326b725ae77Skettenis CORE_ADDR memaddr;
327b725ae77Skettenis char *myaddr;
328b725ae77Skettenis int len;
329b725ae77Skettenis int res;
330b725ae77Skettenis int reg_len;
331b725ae77Skettenis struct mem_region *region;
332b725ae77Skettenis
333b725ae77Skettenis /* If there are any dirty bytes in the line, it must be written
334b725ae77Skettenis before a new line can be read */
335b725ae77Skettenis if (db->anydirty)
336b725ae77Skettenis {
337b725ae77Skettenis if (!dcache_write_line (dcache, db))
338b725ae77Skettenis return 0;
339b725ae77Skettenis }
340b725ae77Skettenis
341b725ae77Skettenis len = LINE_SIZE;
342b725ae77Skettenis memaddr = db->addr;
343b725ae77Skettenis myaddr = db->data;
344b725ae77Skettenis
345b725ae77Skettenis while (len > 0)
346b725ae77Skettenis {
347b725ae77Skettenis region = lookup_mem_region(memaddr);
348b725ae77Skettenis if (memaddr + len < region->hi)
349b725ae77Skettenis reg_len = len;
350b725ae77Skettenis else
351b725ae77Skettenis reg_len = region->hi - memaddr;
352b725ae77Skettenis
353b725ae77Skettenis if (!region->attrib.cache || region->attrib.mode == MEM_WO)
354b725ae77Skettenis {
355b725ae77Skettenis memaddr += reg_len;
356b725ae77Skettenis myaddr += reg_len;
357b725ae77Skettenis len -= reg_len;
358b725ae77Skettenis continue;
359b725ae77Skettenis }
360b725ae77Skettenis
361b725ae77Skettenis while (reg_len > 0)
362b725ae77Skettenis {
363b725ae77Skettenis res = do_xfer_memory (memaddr, myaddr, reg_len, 0,
364b725ae77Skettenis ®ion->attrib);
365b725ae77Skettenis if (res <= 0)
366b725ae77Skettenis return 0;
367b725ae77Skettenis
368b725ae77Skettenis memaddr += res;
369b725ae77Skettenis myaddr += res;
370b725ae77Skettenis len -= res;
371b725ae77Skettenis reg_len -= res;
372b725ae77Skettenis }
373b725ae77Skettenis }
374b725ae77Skettenis
375b725ae77Skettenis memset (db->state, ENTRY_OK, sizeof (db->data));
376b725ae77Skettenis db->anydirty = 0;
377b725ae77Skettenis
378b725ae77Skettenis return 1;
379b725ae77Skettenis }
380e93f7393Sniklas
381e93f7393Sniklas /* Get a free cache block, put or keep it on the valid list,
382b725ae77Skettenis and return its address. */
383e93f7393Sniklas
384e93f7393Sniklas static struct dcache_block *
dcache_alloc(DCACHE * dcache,CORE_ADDR addr)385b725ae77Skettenis dcache_alloc (DCACHE *dcache, CORE_ADDR addr)
386e93f7393Sniklas {
387b725ae77Skettenis struct dcache_block *db;
388e93f7393Sniklas
389e93f7393Sniklas /* Take something from the free list */
390e93f7393Sniklas db = dcache->free_head;
391e93f7393Sniklas if (db)
392e93f7393Sniklas {
393e93f7393Sniklas dcache->free_head = db->p;
394e93f7393Sniklas }
395e93f7393Sniklas else
396e93f7393Sniklas {
397e93f7393Sniklas /* Nothing left on free list, so grab one from the valid list */
398e93f7393Sniklas db = dcache->valid_head;
399e93f7393Sniklas
400b725ae77Skettenis if (!dcache_write_line (dcache, db))
401b725ae77Skettenis return NULL;
402b725ae77Skettenis
403b725ae77Skettenis dcache->valid_head = db->p;
404e93f7393Sniklas }
405e93f7393Sniklas
406b725ae77Skettenis db->addr = MASK(addr);
407b725ae77Skettenis db->refs = 0;
408b725ae77Skettenis db->anydirty = 0;
409b725ae77Skettenis memset (db->state, ENTRY_BAD, sizeof (db->data));
410b725ae77Skettenis
411e93f7393Sniklas /* append this line to end of valid list */
412e93f7393Sniklas if (!dcache->valid_head)
413e93f7393Sniklas dcache->valid_head = db;
414e93f7393Sniklas else
415e93f7393Sniklas dcache->valid_tail->p = db;
416e93f7393Sniklas dcache->valid_tail = db;
417e93f7393Sniklas db->p = 0;
418e93f7393Sniklas
419e93f7393Sniklas return db;
420e93f7393Sniklas }
421e93f7393Sniklas
422b725ae77Skettenis /* Writeback any dirty lines. */
423e93f7393Sniklas static int
dcache_writeback(DCACHE * dcache)424b725ae77Skettenis dcache_writeback (DCACHE *dcache)
425e93f7393Sniklas {
426e93f7393Sniklas struct dcache_block *db;
427e93f7393Sniklas
428e93f7393Sniklas db = dcache->valid_head;
429e93f7393Sniklas
430e93f7393Sniklas while (db)
431e93f7393Sniklas {
432e93f7393Sniklas if (!dcache_write_line (dcache, db))
433e93f7393Sniklas return 0;
434e93f7393Sniklas db = db->p;
435e93f7393Sniklas }
436e93f7393Sniklas return 1;
437e93f7393Sniklas }
438e93f7393Sniklas
439e93f7393Sniklas
440b725ae77Skettenis /* Using the data cache DCACHE return the contents of the byte at
441b725ae77Skettenis address ADDR in the remote machine.
442b725ae77Skettenis
443b725ae77Skettenis Returns 0 on error. */
444b725ae77Skettenis
445b725ae77Skettenis static int
dcache_peek_byte(DCACHE * dcache,CORE_ADDR addr,char * ptr)446b725ae77Skettenis dcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr)
447e93f7393Sniklas {
448b725ae77Skettenis struct dcache_block *db = dcache_hit (dcache, addr);
449e93f7393Sniklas
450b725ae77Skettenis if (!db)
451b725ae77Skettenis {
452b725ae77Skettenis db = dcache_alloc (dcache, addr);
453b725ae77Skettenis if (!db)
454b725ae77Skettenis return 0;
455b725ae77Skettenis }
456e93f7393Sniklas
457b725ae77Skettenis if (db->state[XFORM (addr)] == ENTRY_BAD)
458b725ae77Skettenis {
459b725ae77Skettenis if (!dcache_read_line(dcache, db))
460b725ae77Skettenis return 0;
461b725ae77Skettenis }
462b725ae77Skettenis
463b725ae77Skettenis *ptr = db->data[XFORM (addr)];
464b725ae77Skettenis return 1;
465e93f7393Sniklas }
466e93f7393Sniklas
467e93f7393Sniklas
468e93f7393Sniklas /* Write the byte at PTR into ADDR in the data cache.
469e93f7393Sniklas Return zero on write error.
470e93f7393Sniklas */
471e93f7393Sniklas
472e93f7393Sniklas static int
dcache_poke_byte(DCACHE * dcache,CORE_ADDR addr,char * ptr)473b725ae77Skettenis dcache_poke_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr)
474e93f7393Sniklas {
475b725ae77Skettenis struct dcache_block *db = dcache_hit (dcache, addr);
476e93f7393Sniklas
477e93f7393Sniklas if (!db)
478e93f7393Sniklas {
479b725ae77Skettenis db = dcache_alloc (dcache, addr);
480b725ae77Skettenis if (!db)
481b725ae77Skettenis return 0;
482e93f7393Sniklas }
483e93f7393Sniklas
484e93f7393Sniklas db->data[XFORM (addr)] = *ptr;
485e93f7393Sniklas db->state[XFORM (addr)] = ENTRY_DIRTY;
486e93f7393Sniklas db->anydirty = 1;
487e93f7393Sniklas return 1;
488e93f7393Sniklas }
489e93f7393Sniklas
490e93f7393Sniklas /* Initialize the data cache. */
491e93f7393Sniklas DCACHE *
dcache_init(void)492b725ae77Skettenis dcache_init (void)
493e93f7393Sniklas {
494e93f7393Sniklas int csize = sizeof (struct dcache_block) * DCACHE_SIZE;
495e93f7393Sniklas DCACHE *dcache;
496e93f7393Sniklas
497e93f7393Sniklas dcache = (DCACHE *) xmalloc (sizeof (*dcache));
498e93f7393Sniklas
499e93f7393Sniklas dcache->the_cache = (struct dcache_block *) xmalloc (csize);
500e93f7393Sniklas memset (dcache->the_cache, 0, csize);
501e93f7393Sniklas
502b725ae77Skettenis dcache_invalidate (dcache);
503e93f7393Sniklas
504e93f7393Sniklas last_cache = dcache;
505e93f7393Sniklas return dcache;
506e93f7393Sniklas }
507e93f7393Sniklas
508b725ae77Skettenis /* Free a data cache */
509b725ae77Skettenis void
dcache_free(DCACHE * dcache)510b725ae77Skettenis dcache_free (DCACHE *dcache)
511b725ae77Skettenis {
512b725ae77Skettenis if (last_cache == dcache)
513b725ae77Skettenis last_cache = NULL;
514b725ae77Skettenis
515b725ae77Skettenis xfree (dcache->the_cache);
516b725ae77Skettenis xfree (dcache);
517b725ae77Skettenis }
518b725ae77Skettenis
519e93f7393Sniklas /* Read or write LEN bytes from inferior memory at MEMADDR, transferring
520e93f7393Sniklas to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
521e93f7393Sniklas nonzero.
522e93f7393Sniklas
523e93f7393Sniklas Returns length of data written or read; 0 for error.
524e93f7393Sniklas
525e93f7393Sniklas This routine is indended to be called by remote_xfer_ functions. */
526e93f7393Sniklas
527e93f7393Sniklas int
dcache_xfer_memory(DCACHE * dcache,CORE_ADDR memaddr,char * myaddr,int len,int should_write)528b725ae77Skettenis dcache_xfer_memory (DCACHE *dcache, CORE_ADDR memaddr, char *myaddr, int len,
529b725ae77Skettenis int should_write)
530e93f7393Sniklas {
531e93f7393Sniklas int i;
532b725ae77Skettenis int (*xfunc) (DCACHE *dcache, CORE_ADDR addr, char *ptr);
533e93f7393Sniklas xfunc = should_write ? dcache_poke_byte : dcache_peek_byte;
534e93f7393Sniklas
535e93f7393Sniklas for (i = 0; i < len; i++)
536e93f7393Sniklas {
537e93f7393Sniklas if (!xfunc (dcache, memaddr + i, myaddr + i))
538e93f7393Sniklas return 0;
539e93f7393Sniklas }
540b725ae77Skettenis
541b725ae77Skettenis /* FIXME: There may be some benefit from moving the cache writeback
542b725ae77Skettenis to a higher layer, as it could occur after a sequence of smaller
543b725ae77Skettenis writes have been completed (as when a stack frame is constructed
544b725ae77Skettenis for an inferior function call). Note that only moving it up one
545b725ae77Skettenis level to target_xfer_memory() (also target_xfer_memory_partial())
546b725ae77Skettenis is not sufficent, since we want to coalesce memory transfers that
547b725ae77Skettenis are "logically" connected but not actually a single call to one
548b725ae77Skettenis of the memory transfer functions. */
549b725ae77Skettenis
550b725ae77Skettenis if (should_write)
551e93f7393Sniklas dcache_writeback (dcache);
552e93f7393Sniklas
553e93f7393Sniklas return len;
554e93f7393Sniklas }
555e93f7393Sniklas
556e93f7393Sniklas static void
dcache_info(char * exp,int tty)557b725ae77Skettenis dcache_info (char *exp, int tty)
558e93f7393Sniklas {
559e93f7393Sniklas struct dcache_block *p;
560e93f7393Sniklas
561b725ae77Skettenis printf_filtered ("Dcache line width %d, depth %d\n",
562e93f7393Sniklas LINE_SIZE, DCACHE_SIZE);
563e93f7393Sniklas
564b725ae77Skettenis if (last_cache)
565b725ae77Skettenis {
566e93f7393Sniklas printf_filtered ("Cache state:\n");
567e93f7393Sniklas
568e93f7393Sniklas for (p = last_cache->valid_head; p; p = p->p)
569e93f7393Sniklas {
570e93f7393Sniklas int j;
571b725ae77Skettenis printf_filtered ("Line at %s, referenced %d times\n",
572b725ae77Skettenis paddr (p->addr), p->refs);
573e93f7393Sniklas
574e93f7393Sniklas for (j = 0; j < LINE_SIZE; j++)
575e93f7393Sniklas printf_filtered ("%02x", p->data[j] & 0xFF);
576e93f7393Sniklas printf_filtered ("\n");
577e93f7393Sniklas
578e93f7393Sniklas for (j = 0; j < LINE_SIZE; j++)
579e93f7393Sniklas printf_filtered ("%2x", p->state[j]);
580e93f7393Sniklas printf_filtered ("\n");
581e93f7393Sniklas }
582e93f7393Sniklas }
583b725ae77Skettenis }
584e93f7393Sniklas
585e93f7393Sniklas void
_initialize_dcache(void)586b725ae77Skettenis _initialize_dcache (void)
587e93f7393Sniklas {
588*63addd46Skettenis deprecated_add_show_from_set
589e93f7393Sniklas (add_set_cmd ("remotecache", class_support, var_boolean,
590b725ae77Skettenis (char *) &dcache_enabled_p,
591e93f7393Sniklas "\
592e93f7393Sniklas Set cache use for remote targets.\n\
593e93f7393Sniklas When on, use data caching for remote targets. For many remote targets\n\
594e93f7393Sniklas this option can offer better throughput for reading target memory.\n\
595e93f7393Sniklas Unfortunately, gdb does not currently know anything about volatile\n\
596e93f7393Sniklas registers and thus data caching will produce incorrect results with\n\
597b725ae77Skettenis volatile registers are in use. By default, this option is off.",
598e93f7393Sniklas &setlist),
599e93f7393Sniklas &showlist);
600e93f7393Sniklas
601e93f7393Sniklas add_info ("dcache", dcache_info,
602e93f7393Sniklas "Print information on the dcache performance.");
603e93f7393Sniklas
604e93f7393Sniklas }
605