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