]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/dcache.c
comment change
[thirdparty/binutils-gdb.git] / gdb / dcache.c
1 /* Caching code. Typically used by remote back ends for
2 caching remote memory.
3
4 Copyright 1992, 1993 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22 #include "defs.h"
23 #include "dcache.h"
24
25 extern int insque();
26 extern int remque();
27
28 /* The data cache records all the data read from the remote machine
29 since the last time it stopped.
30
31 Each cache block holds LINE_SIZE bytes of data
32 starting at a multiple-of-LINE_SIZE address. */
33
34 #define LINE_SIZE_MASK ((LINE_SIZE - 1)) /* eg 7*2+1= 111*/
35 #define XFORM(x) (((x) & LINE_SIZE_MASK) >> 2)
36
37 /* Free all the data cache blocks, thus discarding all cached data. */
38 void
39 dcache_flush (dcache)
40 DCACHE *dcache;
41 {
42 register struct dcache_block *db;
43
44 while ((db = dcache->dcache_valid.next) != &dcache->dcache_valid)
45 {
46 remque (db);
47 insque (db, &dcache->dcache_free);
48 }
49 }
50
51 /*
52 * If addr is present in the dcache, return the address of the block
53 * containing it.
54 */
55 struct dcache_block *
56 dcache_hit (dcache, addr)
57 DCACHE *dcache;
58 unsigned int addr;
59 {
60 register struct dcache_block *db;
61
62 if (addr & 3)
63 abort ();
64
65 /* Search all cache blocks for one that is at this address. */
66 db = dcache->dcache_valid.next;
67 while (db != &dcache->dcache_valid)
68 {
69 if ((addr & ~LINE_SIZE_MASK) == db->addr)
70 return db;
71 db = db->next;
72 }
73 return NULL;
74 }
75
76 /* Return the int data at address ADDR in dcache block DC. */
77 int
78 dcache_value (db, addr)
79 struct dcache_block *db;
80 unsigned int addr;
81 {
82 if (addr & 3)
83 abort ();
84 return (db->data[XFORM (addr)]);
85 }
86
87 /* Get a free cache block, put or keep it on the valid list,
88 and return its address. The caller should store into the block
89 the address and data that it describes, then remque it from the
90 free list and insert it into the valid list. This procedure
91 prevents errors from creeping in if a memory retrieval is
92 interrupted (which used to put garbage blocks in the valid
93 list...). */
94 struct dcache_block *
95 dcache_alloc (dcache)
96 DCACHE *dcache;
97 {
98 register struct dcache_block *db;
99
100 if ((db = dcache->dcache_free.next) == &dcache->dcache_free)
101 {
102 /* If we can't get one from the free list, take last valid and put
103 it on the free list. */
104 db = dcache->dcache_valid.last;
105 remque (db);
106 insque (db, &dcache->dcache_free);
107 }
108
109 remque (db);
110 insque (db, &dcache->dcache_valid);
111 return (db);
112 }
113
114 /* Return the contents of the word at address ADDR in the remote machine,
115 using the data cache. */
116 int
117 dcache_fetch (dcache, addr)
118 DCACHE *dcache;
119 CORE_ADDR addr;
120 {
121 register struct dcache_block *db;
122
123 db = dcache_hit (dcache, addr);
124 if (db == 0)
125 {
126 db = dcache_alloc (dcache);
127 immediate_quit++;
128 (*dcache->read_memory) (addr & ~LINE_SIZE_MASK, (unsigned char *) db->data, LINE_SIZE);
129 immediate_quit--;
130 db->addr = addr & ~LINE_SIZE_MASK;
131 remque (db); /* Off the free list */
132 insque (db, &dcache->dcache_valid); /* On the valid list */
133 }
134 return (dcache_value (db, addr));
135 }
136
137 /* Write the word at ADDR both in the data cache and in the remote machine. */
138 void
139 dcache_poke (dcache, addr, data)
140 DCACHE *dcache;
141 CORE_ADDR addr;
142 int data;
143 {
144 register struct dcache_block *db;
145
146 /* First make sure the word is IN the cache. DB is its cache block. */
147 db = dcache_hit (dcache, addr);
148 if (db == 0)
149 {
150 db = dcache_alloc (dcache);
151 immediate_quit++;
152 (*dcache->write_memory) (addr & ~LINE_SIZE_MASK, (unsigned char *) db->data, LINE_SIZE);
153 immediate_quit--;
154 db->addr = addr & ~LINE_SIZE_MASK;
155 remque (db); /* Off the free list */
156 insque (db, &dcache->dcache_valid); /* On the valid list */
157 }
158
159 /* Modify the word in the cache. */
160 db->data[XFORM (addr)] = data;
161
162 /* Send the changed word. */
163 immediate_quit++;
164 (*dcache->write_memory) (addr, (unsigned char *) &data, 4);
165 immediate_quit--;
166 }
167
168 /* Initialize the data cache. */
169 DCACHE *
170 dcache_init (reading, writing)
171 memxferfunc reading;
172 memxferfunc writing;
173 {
174 register i;
175 register struct dcache_block *db;
176 DCACHE *dcache;
177
178 dcache = xmalloc(sizeof(*dcache));
179 dcache->read_memory = reading;
180 dcache->write_memory = writing;
181 dcache->the_cache = xmalloc(sizeof(*dcache->the_cache) * DCACHE_SIZE);
182
183 dcache->dcache_free.next = dcache->dcache_free.last = &dcache->dcache_free;
184 dcache->dcache_valid.next = dcache->dcache_valid.last = &dcache->dcache_valid;
185 for (db = dcache->the_cache, i = 0; i < DCACHE_SIZE; i++, db++)
186 insque (db, &dcache->dcache_free);
187
188 return(dcache);
189 }
190