* config/m68k/monitor.mt (TDEPFILE): Add remote-es.o.
[deliverable/binutils-gdb.git] / gdb / dcache.c
CommitLineData
755892d6
RP
1/* Caching code. Typically used by remote back ends for
2 caching remote memory.
3
4 Copyright 1992, 1993 Free Software Foundation, Inc.
5
6This file is part of GDB.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22#include "defs.h"
23#include "dcache.h"
d538b510 24#include "gdbcmd.h"
755892d6
RP
25
26extern int insque();
27extern int remque();
28
d538b510
RP
29int remote_dcache = 0;
30
755892d6
RP
31/* The data cache records all the data read from the remote machine
32 since the last time it stopped.
33
9e58280a
RP
34 Each cache block holds LINE_SIZE bytes of data
35 starting at a multiple-of-LINE_SIZE address. */
755892d6
RP
36
37#define LINE_SIZE_MASK ((LINE_SIZE - 1)) /* eg 7*2+1= 111*/
38#define XFORM(x) (((x) & LINE_SIZE_MASK) >> 2)
39
40/* Free all the data cache blocks, thus discarding all cached data. */
41void
42dcache_flush (dcache)
43 DCACHE *dcache;
44{
45 register struct dcache_block *db;
46
d538b510
RP
47 if (remote_dcache > 0)
48 while ((db = dcache->dcache_valid.next) != &dcache->dcache_valid)
49 {
50 remque (db);
51 insque (db, &dcache->dcache_free);
52 }
53
54 return;
755892d6
RP
55}
56
57/*
58 * If addr is present in the dcache, return the address of the block
59 * containing it.
60 */
d538b510 61static
755892d6
RP
62struct dcache_block *
63dcache_hit (dcache, addr)
64 DCACHE *dcache;
65 unsigned int addr;
66{
67 register struct dcache_block *db;
68
d538b510
RP
69 if (addr & 3
70 || remote_dcache == 0)
755892d6
RP
71 abort ();
72
73 /* Search all cache blocks for one that is at this address. */
74 db = dcache->dcache_valid.next;
75 while (db != &dcache->dcache_valid)
76 {
77 if ((addr & ~LINE_SIZE_MASK) == db->addr)
78 return db;
79 db = db->next;
80 }
d538b510 81
755892d6
RP
82 return NULL;
83}
84
85/* Return the int data at address ADDR in dcache block DC. */
d538b510 86static
755892d6
RP
87int
88dcache_value (db, addr)
89 struct dcache_block *db;
90 unsigned int addr;
91{
d538b510
RP
92 if (addr & 3
93 || remote_dcache == 0)
755892d6
RP
94 abort ();
95 return (db->data[XFORM (addr)]);
96}
97
98/* Get a free cache block, put or keep it on the valid list,
99 and return its address. The caller should store into the block
100 the address and data that it describes, then remque it from the
101 free list and insert it into the valid list. This procedure
9e58280a
RP
102 prevents errors from creeping in if a memory retrieval is
103 interrupted (which used to put garbage blocks in the valid
104 list...). */
d538b510 105static
755892d6
RP
106struct dcache_block *
107dcache_alloc (dcache)
108 DCACHE *dcache;
109{
110 register struct dcache_block *db;
111
d538b510
RP
112 if (remote_dcache == 0)
113 abort();
114
755892d6
RP
115 if ((db = dcache->dcache_free.next) == &dcache->dcache_free)
116 {
117 /* If we can't get one from the free list, take last valid and put
118 it on the free list. */
119 db = dcache->dcache_valid.last;
120 remque (db);
121 insque (db, &dcache->dcache_free);
122 }
123
124 remque (db);
125 insque (db, &dcache->dcache_valid);
126 return (db);
127}
128
d538b510
RP
129/* Using the data cache DCACHE return the contents of the word at
130 address ADDR in the remote machine. */
755892d6
RP
131int
132dcache_fetch (dcache, addr)
133 DCACHE *dcache;
134 CORE_ADDR addr;
135{
136 register struct dcache_block *db;
137
d538b510
RP
138 if (remote_dcache == 0)
139 {
140 int i;
141
142 (*dcache->read_memory) (addr, (unsigned char *) &i, 4);
143 return(i);
144 }
145
755892d6
RP
146 db = dcache_hit (dcache, addr);
147 if (db == 0)
148 {
149 db = dcache_alloc (dcache);
150 immediate_quit++;
151 (*dcache->read_memory) (addr & ~LINE_SIZE_MASK, (unsigned char *) db->data, LINE_SIZE);
152 immediate_quit--;
153 db->addr = addr & ~LINE_SIZE_MASK;
154 remque (db); /* Off the free list */
155 insque (db, &dcache->dcache_valid); /* On the valid list */
156 }
157 return (dcache_value (db, addr));
158}
159
160/* Write the word at ADDR both in the data cache and in the remote machine. */
161void
162dcache_poke (dcache, addr, data)
163 DCACHE *dcache;
164 CORE_ADDR addr;
165 int data;
166{
167 register struct dcache_block *db;
168
d538b510
RP
169 if (remote_dcache == 0)
170 {
171 (*dcache->write_memory) (addr, (unsigned char *) &data, 4);
172 return;
173 }
174
755892d6
RP
175 /* First make sure the word is IN the cache. DB is its cache block. */
176 db = dcache_hit (dcache, addr);
177 if (db == 0)
178 {
179 db = dcache_alloc (dcache);
180 immediate_quit++;
181 (*dcache->write_memory) (addr & ~LINE_SIZE_MASK, (unsigned char *) db->data, LINE_SIZE);
182 immediate_quit--;
183 db->addr = addr & ~LINE_SIZE_MASK;
d538b510
RP
184 remque (db); /* Off the free list */
185 insque (db, &dcache->dcache_valid); /* On the valid list */
755892d6
RP
186 }
187
188 /* Modify the word in the cache. */
189 db->data[XFORM (addr)] = data;
190
191 /* Send the changed word. */
192 immediate_quit++;
193 (*dcache->write_memory) (addr, (unsigned char *) &data, 4);
194 immediate_quit--;
195}
196
197/* Initialize the data cache. */
198DCACHE *
199dcache_init (reading, writing)
200 memxferfunc reading;
201 memxferfunc writing;
202{
203 register i;
204 register struct dcache_block *db;
205 DCACHE *dcache;
206
ac7a377f 207 dcache = (DCACHE *) xmalloc (sizeof (*dcache));
755892d6
RP
208 dcache->read_memory = reading;
209 dcache->write_memory = writing;
ac7a377f
JK
210 dcache->the_cache = (struct dcache_block *)
211 xmalloc (sizeof (*dcache->the_cache) * DCACHE_SIZE);
755892d6
RP
212
213 dcache->dcache_free.next = dcache->dcache_free.last = &dcache->dcache_free;
214 dcache->dcache_valid.next = dcache->dcache_valid.last = &dcache->dcache_valid;
215 for (db = dcache->the_cache, i = 0; i < DCACHE_SIZE; i++, db++)
216 insque (db, &dcache->dcache_free);
217
218 return(dcache);
219}
220
d538b510
RP
221void
222_initialitize_dcache ()
223{
224 add_show_from_set
225 (add_set_cmd ("remotecache", class_support, var_boolean,
226 (char *) &remote_dcache,
227 "\
228Set cache use for remote targets.\n\
229When on, use data caching for remote targets. For many remote targets\n\
230this option can offer better throughput for reading target memory.\n\
231Unfortunately, gdb does not currently know anything about volatile\n\
232registers and thus data caching will produce incorrect results with\n\
233volatile registers are in use. By default, this option is off.",
234 &setlist),
235 &showlist);
236}
This page took 0.053092 seconds and 4 git commands to generate.