1 /* Simulator for the MIPS architecture.
3 This file is part of the MIPS sim
5 THIS SOFTWARE IS NOT COPYRIGHTED
7 Cygnus offers the following for use in the public domain. Cygnus
8 makes no warranty with regard to the software or it's performance
9 and the user accepts the software "AS IS" with all faults.
11 CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
12 THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32 /*---------------------------------------------------------------------------*/
33 /*-- simulator engine -------------------------------------------------------*/
34 /*---------------------------------------------------------------------------*/
36 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
38 /* Translate a virtual address to a physical address and cache
39 coherence algorithm describing the mechanism used to resolve the
40 memory reference. Given the virtual address vAddr, and whether the
41 reference is to Instructions ot Data (IorD), find the corresponding
42 physical address (pAddr) and the cache coherence algorithm (CCA)
43 used to resolve the reference. If the virtual address is in one of
44 the unmapped address spaces the physical address and the CCA are
45 determined directly by the virtual address. If the virtual address
46 is in one of the mapped address spaces then the TLB is used to
47 determine the physical address and access type; if the required
48 translation is not present in the TLB or the desired access is not
49 permitted the function fails and an exception is taken.
51 NOTE: Normally (RAW == 0), when address translation fails, this
52 function raises an exception and does not return. */
55 address_translation (SIM_DESC sd,
65 int res = -1; /* TRUE : Assume good return */
68 sim_io_printf(sd,"AddressTranslation(0x%s,%s,%s,...);\n",pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "iSTORE" : "isLOAD"));
71 /* Check that the address is valid for this memory model */
73 /* For a simple (flat) memory model, we simply pass virtual
74 addressess through (mostly) unchanged. */
77 *pAddr = vAddr; /* default for isTARGET */
79 /* start-sanitize-sky */
81 if (vAddr >= 0x80000000)
83 if (vAddr < 0xa0000000)
85 *pAddr = vAddr - 0x80000000;
87 else if (vAddr < 0xc0000000)
89 *pAddr = vAddr - 0xa0000000;
93 /* end-sanitize-sky */
95 *CCA = Uncached; /* not used for isHOST */
100 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
102 /* Prefetch data from memory. Prefetch is an advisory instruction for
103 which an implementation specific action is taken. The action taken
104 may increase performance, but must not change the meaning of the
105 program, or alter architecturally-visible state. */
107 INLINE_SIM_MAIN (void)
108 prefetch (SIM_DESC sd,
118 sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint);
121 /* For our simple memory model we do nothing */
125 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
127 /* Load a value from memory. Use the cache and main memory as
128 specified in the Cache Coherence Algorithm (CCA) and the sort of
129 access (IorD) to find the contents of AccessLength memory bytes
130 starting at physical location pAddr. The data is returned in the
131 fixed width naturally-aligned memory element (MemElem). The
132 low-order two (or three) bits of the address and the AccessLength
133 indicate which of the bytes within MemElem needs to be given to the
134 processor. If the memory access type of the reference is uncached
135 then only the referenced bytes are read from memory and valid
136 within the memory element. If the access type is cached, and the
137 data is not present in cache, an implementation specific size and
138 alignment block of memory is read and loaded into the cache to
139 satisfy a load reference. At a minimum, the block is the entire
141 INLINE_SIM_MAIN (void)
142 load_memory (SIM_DESC SD,
148 unsigned int AccessLength,
157 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"));
160 #if defined(WARN_MEM)
162 sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
163 #endif /* WARN_MEM */
166 /* IGEN performs this test in ifetch16() / ifetch32() */
167 /* If instruction fetch then we need to check that the two lo-order
168 bits are zero, otherwise raise a InstructionFetch exception: */
169 if ((IorD == isINSTRUCTION)
170 && ((pAddr & 0x3) != 0)
171 && (((pAddr & 0x1) != 0) || ((vAddr & 0x1) == 0)))
172 SignalExceptionInstructionFetch ();
175 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
177 /* In reality this should be a Bus Error */
178 sim_io_error (SD, "LOAD AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
180 (LOADDRMASK + 1) << 3,
185 dotrace (SD, CPU, tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
188 /* Read the specified number of bytes from memory. Adjust for
189 host/target byte ordering/ Align the least significant byte
192 switch (AccessLength)
194 case AccessLength_QUADWORD :
196 unsigned_16 val = sim_core_read_aligned_16 (CPU, NULL_CIA, read_map, pAddr);
197 value1 = VH8_16 (val);
198 value = VL8_16 (val);
201 case AccessLength_DOUBLEWORD :
202 value = sim_core_read_aligned_8 (CPU, NULL_CIA,
205 case AccessLength_SEPTIBYTE :
206 value = sim_core_read_misaligned_7 (CPU, NULL_CIA,
209 case AccessLength_SEXTIBYTE :
210 value = sim_core_read_misaligned_6 (CPU, NULL_CIA,
213 case AccessLength_QUINTIBYTE :
214 value = sim_core_read_misaligned_5 (CPU, NULL_CIA,
217 case AccessLength_WORD :
218 value = sim_core_read_aligned_4 (CPU, NULL_CIA,
221 case AccessLength_TRIPLEBYTE :
222 value = sim_core_read_misaligned_3 (CPU, NULL_CIA,
225 case AccessLength_HALFWORD :
226 value = sim_core_read_aligned_2 (CPU, NULL_CIA,
229 case AccessLength_BYTE :
230 value = sim_core_read_aligned_1 (CPU, NULL_CIA,
238 printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
239 (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
242 /* See also store_memory. Position data in correct byte lanes. */
243 if (AccessLength <= LOADDRMASK)
246 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
247 shifted to the most significant byte position. */
248 value <<= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
250 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
251 is already in the correct postition. */
252 value <<= ((pAddr & LOADDRMASK) * 8);
256 printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
257 pr_uword64(value1),pr_uword64(value));
261 if (memval1p) *memval1p = value1;
265 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
267 /* Store a value to memory. The specified data is stored into the
268 physical location pAddr using the memory hierarchy (data caches and
269 main memory) as specified by the Cache Coherence Algorithm
270 (CCA). The MemElem contains the data for an aligned, fixed-width
271 memory element (word for 32-bit processors, doubleword for 64-bit
272 processors), though only the bytes that will actually be stored to
273 memory need to be valid. The low-order two (or three) bits of pAddr
274 and the AccessLength field indicates which of the bytes within the
275 MemElem data should actually be stored; only these bytes in memory
278 INLINE_SIM_MAIN (void)
279 store_memory (SIM_DESC SD,
283 unsigned int AccessLength,
285 uword64 MemElem1, /* High order 64 bits */
290 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));
293 #if defined(WARN_MEM)
295 sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
296 #endif /* WARN_MEM */
298 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
299 sim_io_error (SD, "STORE AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
301 (LOADDRMASK + 1) << 3,
305 dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
309 printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
312 /* See also load_memory. Position data in correct byte lanes. */
313 if (AccessLength <= LOADDRMASK)
316 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
317 shifted to the most significant byte position. */
318 MemElem >>= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
320 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
321 is already in the correct postition. */
322 MemElem >>= ((pAddr & LOADDRMASK) * 8);
326 printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
329 switch (AccessLength)
331 case AccessLength_QUADWORD :
333 unsigned_16 val = U16_8 (MemElem1, MemElem);
334 sim_core_write_aligned_16 (CPU, NULL_CIA, write_map, pAddr, val);
337 case AccessLength_DOUBLEWORD :
338 sim_core_write_aligned_8 (CPU, NULL_CIA,
339 write_map, pAddr, MemElem);
341 case AccessLength_SEPTIBYTE :
342 sim_core_write_misaligned_7 (CPU, NULL_CIA,
343 write_map, pAddr, MemElem);
345 case AccessLength_SEXTIBYTE :
346 sim_core_write_misaligned_6 (CPU, NULL_CIA,
347 write_map, pAddr, MemElem);
349 case AccessLength_QUINTIBYTE :
350 sim_core_write_misaligned_5 (CPU, NULL_CIA,
351 write_map, pAddr, MemElem);
353 case AccessLength_WORD :
354 sim_core_write_aligned_4 (CPU, NULL_CIA,
355 write_map, pAddr, MemElem);
357 case AccessLength_TRIPLEBYTE :
358 sim_core_write_misaligned_3 (CPU, NULL_CIA,
359 write_map, pAddr, MemElem);
361 case AccessLength_HALFWORD :
362 sim_core_write_aligned_2 (CPU, NULL_CIA,
363 write_map, pAddr, MemElem);
365 case AccessLength_BYTE :
366 sim_core_write_aligned_1 (CPU, NULL_CIA,
367 write_map, pAddr, MemElem);
377 INLINE_SIM_MAIN (unsigned32)
378 ifetch32 (SIM_DESC SD,
383 /* Copy the action of the LW instruction */
384 address_word mask = LOADDRMASK;
385 address_word access = AccessLength_WORD;
386 address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
387 address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
393 if ((vaddr & access) != 0)
394 SignalExceptionInstructionFetch ();
395 AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
396 paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
397 LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
398 byte = ((vaddr & mask) ^ bigendiancpu);
399 return (memval >> (8 * byte));
403 INLINE_SIM_MAIN (unsigned16)
404 ifetch16 (SIM_DESC SD,
409 /* Copy the action of the LH instruction */
410 address_word mask = LOADDRMASK;
411 address_word access = AccessLength_HALFWORD;
412 address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
413 address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
419 if ((vaddr & access) != 0)
420 SignalExceptionInstructionFetch ();
421 AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
422 paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
423 LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
424 byte = ((vaddr & mask) ^ bigendiancpu);
425 return (memval >> (8 * byte));
430 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
431 /* Order loads and stores to synchronise shared memory. Perform the
432 action necessary to make the effects of groups of synchronizable
433 loads and stores indicated by stype occur in the same order for all
435 INLINE_SIM_MAIN (void)
436 sync_operation (SIM_DESC sd,
442 sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
447 INLINE_SIM_MAIN (void)
448 cache_op (SIM_DESC SD,
454 unsigned int instruction)
456 #if 1 /* stop warning message being displayed (we should really just remove the code) */
457 static int icache_warning = 1;
458 static int dcache_warning = 1;
460 static int icache_warning = 0;
461 static int dcache_warning = 0;
464 /* If CP0 is not useable (User or Supervisor mode) and the CP0
465 enable bit in the Status Register is clear - a coprocessor
466 unusable exception is taken. */
468 sim_io_printf(SD,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia));
472 case 0: /* instruction cache */
474 case 0: /* Index Invalidate */
475 case 1: /* Index Load Tag */
476 case 2: /* Index Store Tag */
477 case 4: /* Hit Invalidate */
479 case 6: /* Hit Writeback */
482 sim_io_eprintf(SD,"Instruction CACHE operation %d to be coded\n",(op >> 2));
488 SignalException(ReservedInstruction,instruction);
493 case 1: /* data cache */
495 case 0: /* Index Writeback Invalidate */
496 case 1: /* Index Load Tag */
497 case 2: /* Index Store Tag */
498 case 3: /* Create Dirty */
499 case 4: /* Hit Invalidate */
500 case 5: /* Hit Writeback Invalidate */
501 case 6: /* Hit Writeback */
504 sim_io_eprintf(SD,"Data CACHE operation %d to be coded\n",(op >> 2));
510 SignalException(ReservedInstruction,instruction);
515 default: /* unrecognised cache ID */
516 SignalException(ReservedInstruction,instruction);
524 INLINE_SIM_MAIN (void)
525 pending_tick (SIM_DESC SD,
530 sim_io_printf (SD, "PENDING_DRAIN - pending_in = %d, pending_out = %d, pending_total = %d\n", PENDING_IN, PENDING_OUT, PENDING_TOTAL);
531 if (PENDING_OUT != PENDING_IN)
534 int index = PENDING_OUT;
535 int total = PENDING_TOTAL;
536 if (PENDING_TOTAL == 0)
537 sim_engine_abort (SD, CPU, cia, "PENDING_DRAIN - Mis-match on pending update pointers\n");
538 for (loop = 0; (loop < total); loop++)
540 if (PENDING_SLOT_DEST[index] != NULL)
542 PENDING_SLOT_DELAY[index] -= 1;
543 if (PENDING_SLOT_DELAY[index] == 0)
545 if (PENDING_SLOT_BIT[index] >= 0)
546 switch (PENDING_SLOT_SIZE[index])
549 if (PENDING_SLOT_VALUE[index])
550 *(unsigned32*)PENDING_SLOT_DEST[index] |=
551 BIT32 (PENDING_SLOT_BIT[index]);
553 *(unsigned32*)PENDING_SLOT_DEST[index] &=
554 BIT32 (PENDING_SLOT_BIT[index]);
557 if (PENDING_SLOT_VALUE[index])
558 *(unsigned64*)PENDING_SLOT_DEST[index] |=
559 BIT64 (PENDING_SLOT_BIT[index]);
561 *(unsigned64*)PENDING_SLOT_DEST[index] &=
562 BIT64 (PENDING_SLOT_BIT[index]);
567 switch (PENDING_SLOT_SIZE[index])
570 *(unsigned32*)PENDING_SLOT_DEST[index] =
571 PENDING_SLOT_VALUE[index];
574 *(unsigned64*)PENDING_SLOT_DEST[index] =
575 PENDING_SLOT_VALUE[index];
579 if (PENDING_OUT == index)
581 PENDING_SLOT_DEST[index] = NULL;
582 PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;
587 index = (index + 1) % PSLOTS;