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