]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/dcache.c
864b068597961abfc6d0a4d858ceb810b5507bb3
1 /* Caching code. Typically used by remote back ends for
4 Copyright 1992, 1993 Free Software Foundation, Inc.
6 This file is part of GDB.
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.
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.
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. */
28 /* The data cache records all the data read from the remote machine
29 since the last time it stopped.
31 Each cache block holds LINE_SIZE bytes of data
32 starting at a multiple-of-LINE_SIZE address. */
34 #define LINE_SIZE_MASK ((LINE_SIZE - 1)) /* eg 7*2+1= 111*/
35 #define XFORM(x) (((x) & LINE_SIZE_MASK) >> 2)
37 /* Free all the data cache blocks, thus discarding all cached data. */
42 register struct dcache_block
*db
;
44 while ((db
= dcache
->dcache_valid
.next
) != &dcache
->dcache_valid
)
47 insque (db
, &dcache
->dcache_free
);
52 * If addr is present in the dcache, return the address of the block
56 dcache_hit (dcache
, addr
)
60 register struct dcache_block
*db
;
65 /* Search all cache blocks for one that is at this address. */
66 db
= dcache
->dcache_valid
.next
;
67 while (db
!= &dcache
->dcache_valid
)
69 if ((addr
& ~LINE_SIZE_MASK
) == db
->addr
)
76 /* Return the int data at address ADDR in dcache block DC. */
78 dcache_value (db
, addr
)
79 struct dcache_block
*db
;
84 return (db
->data
[XFORM (addr
)]);
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
98 register struct dcache_block
*db
;
100 if ((db
= dcache
->dcache_free
.next
) == &dcache
->dcache_free
)
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
;
106 insque (db
, &dcache
->dcache_free
);
110 insque (db
, &dcache
->dcache_valid
);
114 /* Return the contents of the word at address ADDR in the remote machine,
115 using the data cache. */
117 dcache_fetch (dcache
, addr
)
121 register struct dcache_block
*db
;
123 db
= dcache_hit (dcache
, addr
);
126 db
= dcache_alloc (dcache
);
128 (*dcache
->read_memory
) (addr
& ~LINE_SIZE_MASK
, (unsigned char *) db
->data
, LINE_SIZE
);
130 db
->addr
= addr
& ~LINE_SIZE_MASK
;
131 remque (db
); /* Off the free list */
132 insque (db
, &dcache
->dcache_valid
); /* On the valid list */
134 return (dcache_value (db
, addr
));
137 /* Write the word at ADDR both in the data cache and in the remote machine. */
139 dcache_poke (dcache
, addr
, data
)
144 register struct dcache_block
*db
;
146 /* First make sure the word is IN the cache. DB is its cache block. */
147 db
= dcache_hit (dcache
, addr
);
150 db
= dcache_alloc (dcache
);
152 (*dcache
->write_memory
) (addr
& ~LINE_SIZE_MASK
, (unsigned char *) db
->data
, LINE_SIZE
);
154 db
->addr
= addr
& ~LINE_SIZE_MASK
;
155 remque (db
); /* Off the free list */
156 insque (db
, &dcache
->dcache_valid
); /* On the valid list */
159 /* Modify the word in the cache. */
160 db
->data
[XFORM (addr
)] = data
;
162 /* Send the changed word. */
164 (*dcache
->write_memory
) (addr
, (unsigned char *) &data
, 4);
168 /* Initialize the data cache. */
170 dcache_init (reading
, writing
)
175 register struct dcache_block
*db
;
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
);
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
);