sim-main.c revision 1.1 1 1.1 christos /* Copyright (C) 1998, Cygnus Solutions
2 1.1 christos
3 1.1 christos This program is free software; you can redistribute it and/or modify
4 1.1 christos it under the terms of the GNU General Public License as published by
5 1.1 christos the Free Software Foundation; either version 3 of the License, or
6 1.1 christos (at your option) any later version.
7 1.1 christos
8 1.1 christos This program is distributed in the hope that it will be useful,
9 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
10 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 1.1 christos GNU General Public License for more details.
12 1.1 christos
13 1.1 christos You should have received a copy of the GNU General Public License
14 1.1 christos along with this program; if not, see <http://www.gnu.org/licenses/>.
15 1.1 christos
16 1.1 christos */
17 1.1 christos
18 1.1 christos
19 1.1 christos #ifndef SIM_MAIN_C
20 1.1 christos #define SIM_MAIN_C
21 1.1 christos
22 1.1 christos #include "sim-main.h"
23 1.1 christos #include "sim-assert.h"
24 1.1 christos
25 1.1 christos
26 1.1 christos /*---------------------------------------------------------------------------*/
27 1.1 christos /*-- simulator engine -------------------------------------------------------*/
28 1.1 christos /*---------------------------------------------------------------------------*/
29 1.1 christos
30 1.1 christos
31 1.1 christos /* Description from page A-22 of the "MIPS IV Instruction Set" manual
32 1.1 christos (revision 3.1) */
33 1.1 christos /* Translate a virtual address to a physical address and cache
34 1.1 christos coherence algorithm describing the mechanism used to resolve the
35 1.1 christos memory reference. Given the virtual address vAddr, and whether the
36 1.1 christos reference is to Instructions ot Data (IorD), find the corresponding
37 1.1 christos physical address (pAddr) and the cache coherence algorithm (CCA)
38 1.1 christos used to resolve the reference. If the virtual address is in one of
39 1.1 christos the unmapped address spaces the physical address and the CCA are
40 1.1 christos determined directly by the virtual address. If the virtual address
41 1.1 christos is in one of the mapped address spaces then the TLB is used to
42 1.1 christos determine the physical address and access type; if the required
43 1.1 christos translation is not present in the TLB or the desired access is not
44 1.1 christos permitted the function fails and an exception is taken.
45 1.1 christos
46 1.1 christos NOTE: Normally (RAW == 0), when address translation fails, this
47 1.1 christos function raises an exception and does not return. */
48 1.1 christos
49 1.1 christos INLINE_SIM_MAIN
50 1.1 christos (int)
51 1.1 christos address_translation (SIM_DESC sd,
52 1.1 christos sim_cpu * cpu,
53 1.1 christos address_word cia,
54 1.1 christos address_word vAddr,
55 1.1 christos int IorD,
56 1.1 christos int LorS,
57 1.1 christos address_word * pAddr,
58 1.1 christos int *CCA,
59 1.1 christos int raw)
60 1.1 christos {
61 1.1 christos int res = -1; /* TRUE : Assume good return */
62 1.1 christos
63 1.1 christos #ifdef DEBUG
64 1.1 christos sim_io_printf (sd, "AddressTranslation(0x%s,%s,%s,...);\n", pr_addr (vAddr), (IorD ? "isDATA" : "isINSTRUCTION"), (LorS ? "iSTORE" : "isLOAD"));
65 1.1 christos #endif
66 1.1 christos
67 1.1 christos /* Check that the address is valid for this memory model */
68 1.1 christos
69 1.1 christos /* For a simple (flat) memory model, we simply pass virtual
70 1.1 christos addressess through (mostly) unchanged. */
71 1.1 christos vAddr &= 0xFFFFFFFF;
72 1.1 christos
73 1.1 christos *pAddr = vAddr; /* default for isTARGET */
74 1.1 christos *CCA = Uncached; /* not used for isHOST */
75 1.1 christos
76 1.1 christos return (res);
77 1.1 christos }
78 1.1 christos
79 1.1 christos
80 1.1 christos
81 1.1 christos /* Description from page A-23 of the "MIPS IV Instruction Set" manual
82 1.1 christos (revision 3.1) */
83 1.1 christos /* Prefetch data from memory. Prefetch is an advisory instruction for
84 1.1 christos which an implementation specific action is taken. The action taken
85 1.1 christos may increase performance, but must not change the meaning of the
86 1.1 christos program, or alter architecturally-visible state. */
87 1.1 christos
88 1.1 christos INLINE_SIM_MAIN (void)
89 1.1 christos prefetch (SIM_DESC sd,
90 1.1 christos sim_cpu *cpu,
91 1.1 christos address_word cia,
92 1.1 christos int CCA,
93 1.1 christos address_word pAddr,
94 1.1 christos address_word vAddr,
95 1.1 christos int DATA,
96 1.1 christos int hint)
97 1.1 christos {
98 1.1 christos #ifdef DEBUG
99 1.1 christos sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint);
100 1.1 christos #endif /* DEBUG */
101 1.1 christos
102 1.1 christos /* For our simple memory model we do nothing */
103 1.1 christos return;
104 1.1 christos }
105 1.1 christos
106 1.1 christos /* Description from page A-22 of the "MIPS IV Instruction Set" manual
107 1.1 christos (revision 3.1) */
108 1.1 christos /* Load a value from memory. Use the cache and main memory as
109 1.1 christos specified in the Cache Coherence Algorithm (CCA) and the sort of
110 1.1 christos access (IorD) to find the contents of AccessLength memory bytes
111 1.1 christos starting at physical location pAddr. The data is returned in the
112 1.1 christos fixed width naturally-aligned memory element (MemElem). The
113 1.1 christos low-order two (or three) bits of the address and the AccessLength
114 1.1 christos indicate which of the bytes within MemElem needs to be given to the
115 1.1 christos processor. If the memory access type of the reference is uncached
116 1.1 christos then only the referenced bytes are read from memory and valid
117 1.1 christos within the memory element. If the access type is cached, and the
118 1.1 christos data is not present in cache, an implementation specific size and
119 1.1 christos alignment block of memory is read and loaded into the cache to
120 1.1 christos satisfy a load reference. At a minimum, the block is the entire
121 1.1 christos memory element. */
122 1.1 christos INLINE_SIM_MAIN (void)
123 1.1 christos load_memory (SIM_DESC SD,
124 1.1 christos sim_cpu *CPU,
125 1.1 christos address_word cia,
126 1.1 christos uword64* memvalp,
127 1.1 christos uword64* memval1p,
128 1.1 christos int CCA,
129 1.1 christos unsigned int AccessLength,
130 1.1 christos address_word pAddr,
131 1.1 christos address_word vAddr,
132 1.1 christos int IorD)
133 1.1 christos {
134 1.1 christos uword64 value = 0;
135 1.1 christos uword64 value1 = 0;
136 1.1 christos
137 1.1 christos #ifdef DEBUG
138 1.1 christos sim_io_printf(sd,"DBG: LoadMemory(%p,%p,%d,%d,0x%s,0x%s,%s)\n",memvalp,memval1p,CCA,AccessLength,pr_addr(pAddr),pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"));
139 1.1 christos #endif /* DEBUG */
140 1.1 christos
141 1.1 christos #if defined(WARN_MEM)
142 1.1 christos if (CCA != uncached)
143 1.1 christos sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
144 1.1 christos #endif /* WARN_MEM */
145 1.1 christos
146 1.1 christos if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
147 1.1 christos {
148 1.1 christos /* In reality this should be a Bus Error */
149 1.1 christos sim_io_error (SD, "LOAD AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
150 1.1 christos AccessLength,
151 1.1 christos (LOADDRMASK + 1) << 3,
152 1.1 christos pr_addr (pAddr));
153 1.1 christos }
154 1.1 christos
155 1.1 christos #if defined(TRACE)
156 1.1 christos dotrace (SD, CPU, tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
157 1.1 christos #endif /* TRACE */
158 1.1 christos
159 1.1 christos /* Read the specified number of bytes from memory. Adjust for
160 1.1 christos host/target byte ordering/ Align the least significant byte
161 1.1 christos read. */
162 1.1 christos
163 1.1 christos switch (AccessLength)
164 1.1 christos {
165 1.1 christos case AccessLength_QUADWORD:
166 1.1 christos {
167 1.1 christos unsigned_16 val = sim_core_read_aligned_16 (CPU, cia, read_map, pAddr);
168 1.1 christos value1 = VH8_16 (val);
169 1.1 christos value = VL8_16 (val);
170 1.1 christos break;
171 1.1 christos }
172 1.1 christos case AccessLength_DOUBLEWORD:
173 1.1 christos value = sim_core_read_aligned_8 (CPU, cia, read_map, pAddr);
174 1.1 christos break;
175 1.1 christos case AccessLength_SEPTIBYTE:
176 1.1 christos value = sim_core_read_misaligned_7 (CPU, cia, read_map, pAddr);
177 1.1 christos break;
178 1.1 christos case AccessLength_SEXTIBYTE:
179 1.1 christos value = sim_core_read_misaligned_6 (CPU, cia, read_map, pAddr);
180 1.1 christos break;
181 1.1 christos case AccessLength_QUINTIBYTE:
182 1.1 christos value = sim_core_read_misaligned_5 (CPU, cia, read_map, pAddr);
183 1.1 christos break;
184 1.1 christos case AccessLength_WORD:
185 1.1 christos value = sim_core_read_aligned_4 (CPU, cia, read_map, pAddr);
186 1.1 christos break;
187 1.1 christos case AccessLength_TRIPLEBYTE:
188 1.1 christos value = sim_core_read_misaligned_3 (CPU, cia, read_map, pAddr);
189 1.1 christos break;
190 1.1 christos case AccessLength_HALFWORD:
191 1.1 christos value = sim_core_read_aligned_2 (CPU, cia, read_map, pAddr);
192 1.1 christos break;
193 1.1 christos case AccessLength_BYTE:
194 1.1 christos value = sim_core_read_aligned_1 (CPU, cia, read_map, pAddr);
195 1.1 christos break;
196 1.1 christos default:
197 1.1 christos abort ();
198 1.1 christos }
199 1.1 christos
200 1.1 christos #ifdef DEBUG
201 1.1 christos printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
202 1.1 christos (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
203 1.1 christos #endif /* DEBUG */
204 1.1 christos
205 1.1 christos /* See also store_memory. Position data in correct byte lanes. */
206 1.1 christos if (AccessLength <= LOADDRMASK)
207 1.1 christos {
208 1.1 christos if (BigEndianMem)
209 1.1 christos /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
210 1.1 christos shifted to the most significant byte position. */
211 1.1 christos value <<= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
212 1.1 christos else
213 1.1 christos /* For little endian target, byte (pAddr&LOADDRMASK == 0)
214 1.1 christos is already in the correct postition. */
215 1.1 christos value <<= ((pAddr & LOADDRMASK) * 8);
216 1.1 christos }
217 1.1 christos
218 1.1 christos #ifdef DEBUG
219 1.1 christos printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
220 1.1 christos pr_uword64(value1),pr_uword64(value));
221 1.1 christos #endif /* DEBUG */
222 1.1 christos
223 1.1 christos *memvalp = value;
224 1.1 christos if (memval1p) *memval1p = value1;
225 1.1 christos }
226 1.1 christos
227 1.1 christos
228 1.1 christos /* Description from page A-23 of the "MIPS IV Instruction Set" manual
229 1.1 christos (revision 3.1) */
230 1.1 christos /* Store a value to memory. The specified data is stored into the
231 1.1 christos physical location pAddr using the memory hierarchy (data caches and
232 1.1 christos main memory) as specified by the Cache Coherence Algorithm
233 1.1 christos (CCA). The MemElem contains the data for an aligned, fixed-width
234 1.1 christos memory element (word for 32-bit processors, doubleword for 64-bit
235 1.1 christos processors), though only the bytes that will actually be stored to
236 1.1 christos memory need to be valid. The low-order two (or three) bits of pAddr
237 1.1 christos and the AccessLength field indicates which of the bytes within the
238 1.1 christos MemElem data should actually be stored; only these bytes in memory
239 1.1 christos will be changed. */
240 1.1 christos
241 1.1 christos INLINE_SIM_MAIN (void)
242 1.1 christos store_memory (SIM_DESC SD,
243 1.1 christos sim_cpu *CPU,
244 1.1 christos address_word cia,
245 1.1 christos int CCA,
246 1.1 christos unsigned int AccessLength,
247 1.1 christos uword64 MemElem,
248 1.1 christos uword64 MemElem1, /* High order 64 bits */
249 1.1 christos address_word pAddr,
250 1.1 christos address_word vAddr)
251 1.1 christos {
252 1.1 christos #ifdef DEBUG
253 1.1 christos sim_io_printf(sd,"DBG: StoreMemory(%d,%d,0x%s,0x%s,0x%s,0x%s)\n",CCA,AccessLength,pr_uword64(MemElem),pr_uword64(MemElem1),pr_addr(pAddr),pr_addr(vAddr));
254 1.1 christos #endif /* DEBUG */
255 1.1 christos
256 1.1 christos #if defined(WARN_MEM)
257 1.1 christos if (CCA != uncached)
258 1.1 christos sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
259 1.1 christos #endif /* WARN_MEM */
260 1.1 christos
261 1.1 christos if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
262 1.1 christos sim_io_error (SD, "STORE AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
263 1.1 christos AccessLength,
264 1.1 christos (LOADDRMASK + 1) << 3,
265 1.1 christos pr_addr(pAddr));
266 1.1 christos
267 1.1 christos #if defined(TRACE)
268 1.1 christos dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
269 1.1 christos #endif /* TRACE */
270 1.1 christos
271 1.1 christos #ifdef DEBUG
272 1.1 christos printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
273 1.1 christos #endif /* DEBUG */
274 1.1 christos
275 1.1 christos /* See also load_memory. Position data in correct byte lanes. */
276 1.1 christos if (AccessLength <= LOADDRMASK)
277 1.1 christos {
278 1.1 christos if (BigEndianMem)
279 1.1 christos /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
280 1.1 christos shifted to the most significant byte position. */
281 1.1 christos MemElem >>= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
282 1.1 christos else
283 1.1 christos /* For little endian target, byte (pAddr&LOADDRMASK == 0)
284 1.1 christos is already in the correct postition. */
285 1.1 christos MemElem >>= ((pAddr & LOADDRMASK) * 8);
286 1.1 christos }
287 1.1 christos
288 1.1 christos #ifdef DEBUG
289 1.1 christos printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
290 1.1 christos #endif /* DEBUG */
291 1.1 christos
292 1.1 christos switch (AccessLength)
293 1.1 christos {
294 1.1 christos case AccessLength_QUADWORD:
295 1.1 christos {
296 1.1 christos unsigned_16 val = U16_8 (MemElem1, MemElem);
297 1.1 christos sim_core_write_aligned_16 (CPU, cia, write_map, pAddr, val);
298 1.1 christos break;
299 1.1 christos }
300 1.1 christos case AccessLength_DOUBLEWORD:
301 1.1 christos sim_core_write_aligned_8 (CPU, cia, write_map, pAddr, MemElem);
302 1.1 christos break;
303 1.1 christos case AccessLength_SEPTIBYTE:
304 1.1 christos sim_core_write_misaligned_7 (CPU, cia, write_map, pAddr, MemElem);
305 1.1 christos break;
306 1.1 christos case AccessLength_SEXTIBYTE:
307 1.1 christos sim_core_write_misaligned_6 (CPU, cia, write_map, pAddr, MemElem);
308 1.1 christos break;
309 1.1 christos case AccessLength_QUINTIBYTE:
310 1.1 christos sim_core_write_misaligned_5 (CPU, cia, write_map, pAddr, MemElem);
311 1.1 christos break;
312 1.1 christos case AccessLength_WORD:
313 1.1 christos sim_core_write_aligned_4 (CPU, cia, write_map, pAddr, MemElem);
314 1.1 christos break;
315 1.1 christos case AccessLength_TRIPLEBYTE:
316 1.1 christos sim_core_write_misaligned_3 (CPU, cia, write_map, pAddr, MemElem);
317 1.1 christos break;
318 1.1 christos case AccessLength_HALFWORD:
319 1.1 christos sim_core_write_aligned_2 (CPU, cia, write_map, pAddr, MemElem);
320 1.1 christos break;
321 1.1 christos case AccessLength_BYTE:
322 1.1 christos sim_core_write_aligned_1 (CPU, cia, write_map, pAddr, MemElem);
323 1.1 christos break;
324 1.1 christos default:
325 1.1 christos abort ();
326 1.1 christos }
327 1.1 christos
328 1.1 christos return;
329 1.1 christos }
330 1.1 christos
331 1.1 christos
332 1.1 christos INLINE_SIM_MAIN (unsigned32)
333 1.1 christos ifetch32 (SIM_DESC SD,
334 1.1 christos sim_cpu *CPU,
335 1.1 christos address_word cia,
336 1.1 christos address_word vaddr)
337 1.1 christos {
338 1.1 christos /* Copy the action of the LW instruction */
339 1.1 christos address_word mask = LOADDRMASK;
340 1.1 christos address_word access = AccessLength_WORD;
341 1.1 christos address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
342 1.1 christos address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
343 1.1 christos unsigned int byte;
344 1.1 christos address_word paddr;
345 1.1 christos int uncached;
346 1.1 christos unsigned64 memval;
347 1.1 christos
348 1.1 christos if ((vaddr & access) != 0)
349 1.1 christos SignalExceptionInstructionFetch ();
350 1.1 christos AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
351 1.1 christos paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
352 1.1 christos LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
353 1.1 christos byte = ((vaddr & mask) ^ bigendiancpu);
354 1.1 christos return (memval >> (8 * byte));
355 1.1 christos }
356 1.1 christos
357 1.1 christos
358 1.1 christos INLINE_SIM_MAIN (unsigned16)
359 1.1 christos ifetch16 (SIM_DESC SD,
360 1.1 christos sim_cpu *CPU,
361 1.1 christos address_word cia,
362 1.1 christos address_word vaddr)
363 1.1 christos {
364 1.1 christos /* Copy the action of the LH instruction */
365 1.1 christos address_word mask = LOADDRMASK;
366 1.1 christos address_word access = AccessLength_HALFWORD;
367 1.1 christos address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
368 1.1 christos address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
369 1.1 christos unsigned int byte;
370 1.1 christos address_word paddr;
371 1.1 christos int uncached;
372 1.1 christos unsigned64 memval;
373 1.1 christos
374 1.1 christos if ((vaddr & access) != 0)
375 1.1 christos SignalExceptionInstructionFetch ();
376 1.1 christos AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
377 1.1 christos paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
378 1.1 christos LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
379 1.1 christos byte = ((vaddr & mask) ^ bigendiancpu);
380 1.1 christos return (memval >> (8 * byte));
381 1.1 christos }
382 1.1 christos
383 1.1 christos
384 1.1 christos
385 1.1 christos /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
386 1.1 christos /* Order loads and stores to synchronise shared memory. Perform the
387 1.1 christos action necessary to make the effects of groups of synchronizable
388 1.1 christos loads and stores indicated by stype occur in the same order for all
389 1.1 christos processors. */
390 1.1 christos INLINE_SIM_MAIN (void)
391 1.1 christos sync_operation (SIM_DESC sd,
392 1.1 christos sim_cpu *cpu,
393 1.1 christos address_word cia,
394 1.1 christos int stype)
395 1.1 christos {
396 1.1 christos #ifdef DEBUG
397 1.1 christos sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
398 1.1 christos #endif /* DEBUG */
399 1.1 christos return;
400 1.1 christos }
401 1.1 christos
402 1.1 christos INLINE_SIM_MAIN (void)
403 1.1 christos cache_op (SIM_DESC SD,
404 1.1 christos sim_cpu *CPU,
405 1.1 christos address_word cia,
406 1.1 christos int op,
407 1.1 christos address_word pAddr,
408 1.1 christos address_word vAddr,
409 1.1 christos unsigned int instruction)
410 1.1 christos {
411 1.1 christos #if 1 /* stop warning message being displayed (we should really just remove the code) */
412 1.1 christos static int icache_warning = 1;
413 1.1 christos static int dcache_warning = 1;
414 1.1 christos #else
415 1.1 christos static int icache_warning = 0;
416 1.1 christos static int dcache_warning = 0;
417 1.1 christos #endif
418 1.1 christos
419 1.1 christos /* If CP0 is not useable (User or Supervisor mode) and the CP0
420 1.1 christos enable bit in the Status Register is clear - a coprocessor
421 1.1 christos unusable exception is taken. */
422 1.1 christos #if 0
423 1.1 christos sim_io_printf(SD,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia));
424 1.1 christos #endif
425 1.1 christos
426 1.1 christos switch (op & 0x3) {
427 1.1 christos case 0: /* instruction cache */
428 1.1 christos switch (op >> 2) {
429 1.1 christos case 0: /* Index Invalidate */
430 1.1 christos case 1: /* Index Load Tag */
431 1.1 christos case 2: /* Index Store Tag */
432 1.1 christos case 4: /* Hit Invalidate */
433 1.1 christos case 5: /* Fill */
434 1.1 christos case 6: /* Hit Writeback */
435 1.1 christos if (!icache_warning)
436 1.1 christos {
437 1.1 christos sim_io_eprintf(SD,"Instruction CACHE operation %d to be coded\n",(op >> 2));
438 1.1 christos icache_warning = 1;
439 1.1 christos }
440 1.1 christos break;
441 1.1 christos
442 1.1 christos default:
443 1.1 christos SignalException(ReservedInstruction,instruction);
444 1.1 christos break;
445 1.1 christos }
446 1.1 christos break;
447 1.1 christos
448 1.1 christos case 1: /* data cache */
449 1.1 christos case 3: /* secondary data cache */
450 1.1 christos switch (op >> 2) {
451 1.1 christos case 0: /* Index Writeback Invalidate */
452 1.1 christos case 1: /* Index Load Tag */
453 1.1 christos case 2: /* Index Store Tag */
454 1.1 christos case 3: /* Create Dirty */
455 1.1 christos case 4: /* Hit Invalidate */
456 1.1 christos case 5: /* Hit Writeback Invalidate */
457 1.1 christos case 6: /* Hit Writeback */
458 1.1 christos if (!dcache_warning)
459 1.1 christos {
460 1.1 christos sim_io_eprintf(SD,"Data CACHE operation %d to be coded\n",(op >> 2));
461 1.1 christos dcache_warning = 1;
462 1.1 christos }
463 1.1 christos break;
464 1.1 christos
465 1.1 christos default:
466 1.1 christos SignalException(ReservedInstruction,instruction);
467 1.1 christos break;
468 1.1 christos }
469 1.1 christos break;
470 1.1 christos
471 1.1 christos default: /* unrecognised cache ID */
472 1.1 christos SignalException(ReservedInstruction,instruction);
473 1.1 christos break;
474 1.1 christos }
475 1.1 christos
476 1.1 christos return;
477 1.1 christos }
478 1.1 christos
479 1.1 christos
480 1.1 christos INLINE_SIM_MAIN (void)
481 1.1 christos pending_tick (SIM_DESC SD,
482 1.1 christos sim_cpu *CPU,
483 1.1 christos address_word cia)
484 1.1 christos {
485 1.1 christos if (PENDING_TRACE)
486 1.1 christos sim_io_eprintf (SD, "PENDING_DRAIN - 0x%lx - pending_in = %d, pending_out = %d, pending_total = %d\n", (unsigned long) cia, PENDING_IN, PENDING_OUT, PENDING_TOTAL);
487 1.1 christos if (PENDING_OUT != PENDING_IN)
488 1.1 christos {
489 1.1 christos int loop;
490 1.1 christos int index = PENDING_OUT;
491 1.1 christos int total = PENDING_TOTAL;
492 1.1 christos if (PENDING_TOTAL == 0)
493 1.1 christos sim_engine_abort (SD, CPU, cia, "PENDING_DRAIN - Mis-match on pending update pointers\n");
494 1.1 christos for (loop = 0, index = PENDING_OUT;
495 1.1 christos (loop < total);
496 1.1 christos loop++, index = (index + 1) % PSLOTS)
497 1.1 christos {
498 1.1 christos if (PENDING_SLOT_DEST[index] != NULL)
499 1.1 christos {
500 1.1 christos PENDING_SLOT_DELAY[index] -= 1;
501 1.1 christos if (PENDING_SLOT_DELAY[index] == 0)
502 1.1 christos {
503 1.1 christos if (PENDING_TRACE)
504 1.1 christos sim_io_eprintf (SD, "PENDING_DRAIN - drained - index %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
505 1.1 christos index,
506 1.1 christos (unsigned long) PENDING_SLOT_DEST[index],
507 1.1 christos PENDING_SLOT_BIT[index],
508 1.1 christos (unsigned long) PENDING_SLOT_VALUE[index],
509 1.1 christos PENDING_SLOT_SIZE[index]);
510 1.1 christos if (PENDING_SLOT_BIT[index] >= 0)
511 1.1 christos switch (PENDING_SLOT_SIZE[index])
512 1.1 christos {
513 1.1 christos case 4:
514 1.1 christos if (PENDING_SLOT_VALUE[index])
515 1.1 christos *(unsigned32*)PENDING_SLOT_DEST[index] |=
516 1.1 christos BIT32 (PENDING_SLOT_BIT[index]);
517 1.1 christos else
518 1.1 christos *(unsigned32*)PENDING_SLOT_DEST[index] &=
519 1.1 christos BIT32 (PENDING_SLOT_BIT[index]);
520 1.1 christos break;
521 1.1 christos case 8:
522 1.1 christos if (PENDING_SLOT_VALUE[index])
523 1.1 christos *(unsigned64*)PENDING_SLOT_DEST[index] |=
524 1.1 christos BIT64 (PENDING_SLOT_BIT[index]);
525 1.1 christos else
526 1.1 christos *(unsigned64*)PENDING_SLOT_DEST[index] &=
527 1.1 christos BIT64 (PENDING_SLOT_BIT[index]);
528 1.1 christos break;
529 1.1 christos }
530 1.1 christos else
531 1.1 christos switch (PENDING_SLOT_SIZE[index])
532 1.1 christos {
533 1.1 christos case 4:
534 1.1 christos *(unsigned32*)PENDING_SLOT_DEST[index] =
535 1.1 christos PENDING_SLOT_VALUE[index];
536 1.1 christos break;
537 1.1 christos case 8:
538 1.1 christos *(unsigned64*)PENDING_SLOT_DEST[index] =
539 1.1 christos PENDING_SLOT_VALUE[index];
540 1.1 christos break;
541 1.1 christos }
542 1.1 christos if (PENDING_OUT == index)
543 1.1 christos {
544 1.1 christos PENDING_SLOT_DEST[index] = NULL;
545 1.1 christos PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;
546 1.1 christos PENDING_TOTAL--;
547 1.1 christos }
548 1.1 christos }
549 1.1 christos else if (PENDING_TRACE && PENDING_SLOT_DELAY[index] > 0)
550 1.1 christos sim_io_eprintf (SD, "PENDING_DRAIN - queued - index %d, delay %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
551 1.1 christos index, PENDING_SLOT_DELAY[index],
552 1.1 christos (unsigned long) PENDING_SLOT_DEST[index],
553 1.1 christos PENDING_SLOT_BIT[index],
554 1.1 christos (unsigned long) PENDING_SLOT_VALUE[index],
555 1.1 christos PENDING_SLOT_SIZE[index]);
556 1.1 christos
557 1.1 christos }
558 1.1 christos }
559 1.1 christos }
560 1.1 christos }
561 1.1 christos
562 1.1 christos
563 1.1 christos #endif
564