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 */
78 *CCA
= Uncached
; /* not used for isHOST */
83 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
85 /* Prefetch data from memory. Prefetch is an advisory instruction for
86 which an implementation specific action is taken. The action taken
87 may increase performance, but must not change the meaning of the
88 program, or alter architecturally-visible state. */
90 INLINE_SIM_MAIN (void)
91 prefetch (SIM_DESC sd
,
101 sim_io_printf(sd
,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA
,pr_addr(pAddr
),pr_addr(vAddr
),DATA
,hint
);
104 /* For our simple memory model we do nothing */
108 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
110 /* Load a value from memory. Use the cache and main memory as
111 specified in the Cache Coherence Algorithm (CCA) and the sort of
112 access (IorD) to find the contents of AccessLength memory bytes
113 starting at physical location pAddr. The data is returned in the
114 fixed width naturally-aligned memory element (MemElem). The
115 low-order two (or three) bits of the address and the AccessLength
116 indicate which of the bytes within MemElem needs to be given to the
117 processor. If the memory access type of the reference is uncached
118 then only the referenced bytes are read from memory and valid
119 within the memory element. If the access type is cached, and the
120 data is not present in cache, an implementation specific size and
121 alignment block of memory is read and loaded into the cache to
122 satisfy a load reference. At a minimum, the block is the entire
124 INLINE_SIM_MAIN (void)
125 load_memory (SIM_DESC SD
,
131 unsigned int AccessLength
,
140 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"));
143 #if defined(WARN_MEM)
145 sim_io_eprintf(sd
,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA
);
146 #endif /* WARN_MEM */
148 /* If instruction fetch then we need to check that the two lo-order
149 bits are zero, otherwise raise a InstructionFetch exception: */
150 if ((IorD
== isINSTRUCTION
)
151 && ((pAddr
& 0x3) != 0)
152 && (((pAddr
& 0x1) != 0) || ((vAddr
& 0x1) == 0)))
153 SignalExceptionInstructionFetch ();
155 if (((pAddr
& LOADDRMASK
) + AccessLength
) > LOADDRMASK
)
157 /* In reality this should be a Bus Error */
158 sim_io_error (SD
, "LOAD AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
160 (LOADDRMASK
+ 1) << 3,
165 dotrace (SD
, CPU
, tracefh
,((IorD
== isDATA
) ? 0 : 2),(unsigned int)(pAddr
&0xFFFFFFFF),(AccessLength
+ 1),"load%s",((IorD
== isDATA
) ? "" : " instruction"));
168 /* Read the specified number of bytes from memory. Adjust for
169 host/target byte ordering/ Align the least significant byte
172 switch (AccessLength
)
174 case AccessLength_QUADWORD
:
176 unsigned_16 val
= sim_core_read_aligned_16 (CPU
, NULL_CIA
, read_map
, pAddr
);
177 value1
= VH8_16 (val
);
178 value
= VL8_16 (val
);
181 case AccessLength_DOUBLEWORD
:
182 value
= sim_core_read_aligned_8 (CPU
, NULL_CIA
,
185 case AccessLength_SEPTIBYTE
:
186 value
= sim_core_read_misaligned_7 (CPU
, NULL_CIA
,
189 case AccessLength_SEXTIBYTE
:
190 value
= sim_core_read_misaligned_6 (CPU
, NULL_CIA
,
193 case AccessLength_QUINTIBYTE
:
194 value
= sim_core_read_misaligned_5 (CPU
, NULL_CIA
,
197 case AccessLength_WORD
:
198 value
= sim_core_read_aligned_4 (CPU
, NULL_CIA
,
201 case AccessLength_TRIPLEBYTE
:
202 value
= sim_core_read_misaligned_3 (CPU
, NULL_CIA
,
205 case AccessLength_HALFWORD
:
206 value
= sim_core_read_aligned_2 (CPU
, NULL_CIA
,
209 case AccessLength_BYTE
:
210 value
= sim_core_read_aligned_1 (CPU
, NULL_CIA
,
218 printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
219 (int)(pAddr
& LOADDRMASK
),pr_uword64(value1
),pr_uword64(value
));
222 /* See also store_memory. Position data in correct byte lanes. */
223 if (AccessLength
<= LOADDRMASK
)
226 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
227 shifted to the most significant byte position. */
228 value
<<= (((LOADDRMASK
- (pAddr
& LOADDRMASK
)) - AccessLength
) * 8);
230 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
231 is already in the correct postition. */
232 value
<<= ((pAddr
& LOADDRMASK
) * 8);
236 printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
237 pr_uword64(value1
),pr_uword64(value
));
241 if (memval1p
) *memval1p
= value1
;
245 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
247 /* Store a value to memory. The specified data is stored into the
248 physical location pAddr using the memory hierarchy (data caches and
249 main memory) as specified by the Cache Coherence Algorithm
250 (CCA). The MemElem contains the data for an aligned, fixed-width
251 memory element (word for 32-bit processors, doubleword for 64-bit
252 processors), though only the bytes that will actually be stored to
253 memory need to be valid. The low-order two (or three) bits of pAddr
254 and the AccessLength field indicates which of the bytes within the
255 MemElem data should actually be stored; only these bytes in memory
258 INLINE_SIM_MAIN (void)
259 store_memory (SIM_DESC SD
,
263 unsigned int AccessLength
,
265 uword64 MemElem1
, /* High order 64 bits */
270 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
));
273 #if defined(WARN_MEM)
275 sim_io_eprintf(sd
,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA
);
276 #endif /* WARN_MEM */
278 if (((pAddr
& LOADDRMASK
) + AccessLength
) > LOADDRMASK
)
279 sim_io_error (SD
, "STORE AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
281 (LOADDRMASK
+ 1) << 3,
285 dotrace (SD
, CPU
, tracefh
,1,(unsigned int)(pAddr
&0xFFFFFFFF),(AccessLength
+ 1),"store");
289 printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr
& LOADDRMASK
),pr_uword64(MemElem1
),pr_uword64(MemElem
));
292 /* See also load_memory. Position data in correct byte lanes. */
293 if (AccessLength
<= LOADDRMASK
)
296 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
297 shifted to the most significant byte position. */
298 MemElem
>>= (((LOADDRMASK
- (pAddr
& LOADDRMASK
)) - AccessLength
) * 8);
300 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
301 is already in the correct postition. */
302 MemElem
>>= ((pAddr
& LOADDRMASK
) * 8);
306 printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift
,pr_uword64(MemElem1
),pr_uword64(MemElem
));
309 switch (AccessLength
)
311 case AccessLength_QUADWORD
:
313 unsigned_16 val
= U16_8 (MemElem1
, MemElem
);
314 sim_core_write_aligned_16 (CPU
, NULL_CIA
, write_map
, pAddr
, val
);
317 case AccessLength_DOUBLEWORD
:
318 sim_core_write_aligned_8 (CPU
, NULL_CIA
,
319 write_map
, pAddr
, MemElem
);
321 case AccessLength_SEPTIBYTE
:
322 sim_core_write_misaligned_7 (CPU
, NULL_CIA
,
323 write_map
, pAddr
, MemElem
);
325 case AccessLength_SEXTIBYTE
:
326 sim_core_write_misaligned_6 (CPU
, NULL_CIA
,
327 write_map
, pAddr
, MemElem
);
329 case AccessLength_QUINTIBYTE
:
330 sim_core_write_misaligned_5 (CPU
, NULL_CIA
,
331 write_map
, pAddr
, MemElem
);
333 case AccessLength_WORD
:
334 sim_core_write_aligned_4 (CPU
, NULL_CIA
,
335 write_map
, pAddr
, MemElem
);
337 case AccessLength_TRIPLEBYTE
:
338 sim_core_write_misaligned_3 (CPU
, NULL_CIA
,
339 write_map
, pAddr
, MemElem
);
341 case AccessLength_HALFWORD
:
342 sim_core_write_aligned_2 (CPU
, NULL_CIA
,
343 write_map
, pAddr
, MemElem
);
345 case AccessLength_BYTE
:
346 sim_core_write_aligned_1 (CPU
, NULL_CIA
,
347 write_map
, pAddr
, MemElem
);
357 INLINE_SIM_MAIN (unsigned32
)
358 ifetch32 (SIM_DESC SD
,
363 /* Copy the action of the LW instruction */
364 address_word reverse
= (ReverseEndian
? (LOADDRMASK
>> 2) : 0);
365 address_word bigend
= (BigEndianCPU
? (LOADDRMASK
>> 2) : 0);
368 unsigned32 instruction
;
371 AddressTranslation (vaddr
, isINSTRUCTION
, isLOAD
, &paddr
, &cca
, isTARGET
, isREAL
);
372 paddr
= ((paddr
& ~LOADDRMASK
) | ((paddr
& LOADDRMASK
) ^ (reverse
<< 2)));
373 LoadMemory (&value
, NULL
, cca
, AccessLength_WORD
, paddr
, vaddr
, isINSTRUCTION
, isREAL
);
374 byte
= ((vaddr
& LOADDRMASK
) ^ (bigend
<< 2));
375 instruction
= ((value
>> (8 * byte
)) & 0xFFFFFFFF);
380 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
381 /* Order loads and stores to synchronise shared memory. Perform the
382 action necessary to make the effects of groups of synchronizable
383 loads and stores indicated by stype occur in the same order for all
385 INLINE_SIM_MAIN (void)
386 sync_operation (SIM_DESC sd
,
392 sim_io_printf(sd
,"SyncOperation(%d) : TODO\n",stype
);
397 INLINE_SIM_MAIN (void)
398 cache_op (SIM_DESC SD
,
404 unsigned int instruction
)
406 #if 1 /* stop warning message being displayed (we should really just remove the code) */
407 static int icache_warning
= 1;
408 static int dcache_warning
= 1;
410 static int icache_warning
= 0;
411 static int dcache_warning
= 0;
414 /* If CP0 is not useable (User or Supervisor mode) and the CP0
415 enable bit in the Status Register is clear - a coprocessor
416 unusable exception is taken. */
418 sim_io_printf(SD
,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia
));
422 case 0: /* instruction cache */
424 case 0: /* Index Invalidate */
425 case 1: /* Index Load Tag */
426 case 2: /* Index Store Tag */
427 case 4: /* Hit Invalidate */
429 case 6: /* Hit Writeback */
432 sim_io_eprintf(SD
,"Instruction CACHE operation %d to be coded\n",(op
>> 2));
438 SignalException(ReservedInstruction
,instruction
);
443 case 1: /* data cache */
445 case 0: /* Index Writeback Invalidate */
446 case 1: /* Index Load Tag */
447 case 2: /* Index Store Tag */
448 case 3: /* Create Dirty */
449 case 4: /* Hit Invalidate */
450 case 5: /* Hit Writeback Invalidate */
451 case 6: /* Hit Writeback */
454 sim_io_eprintf(SD
,"Data CACHE operation %d to be coded\n",(op
>> 2));
460 SignalException(ReservedInstruction
,instruction
);
465 default: /* unrecognised cache ID */
466 SignalException(ReservedInstruction
,instruction
);
474 INLINE_SIM_MAIN (void)
475 pending_tick (SIM_DESC SD
,
480 sim_io_printf (SD
, "PENDING_DRAIN - pending_in = %d, pending_out = %d, pending_total = %d\n", PENDING_IN
, PENDING_OUT
, PENDING_TOTAL
);
481 if (PENDING_OUT
!= PENDING_IN
)
484 int index
= PENDING_OUT
;
485 int total
= PENDING_TOTAL
;
486 if (PENDING_TOTAL
== 0)
487 sim_engine_abort (SD
, CPU
, cia
, "PENDING_DRAIN - Mis-match on pending update pointers\n");
488 for (loop
= 0; (loop
< total
); loop
++)
490 if (PENDING_SLOT_DEST
[index
] != NULL
)
492 PENDING_SLOT_DELAY
[index
] -= 1;
493 if (PENDING_SLOT_DELAY
[index
] == 0)
495 if (PENDING_SLOT_BIT
[index
] >= 0)
496 switch (PENDING_SLOT_SIZE
[index
])
499 if (PENDING_SLOT_VALUE
[index
])
500 *(unsigned32
*)PENDING_SLOT_DEST
[index
] |=
501 BIT32 (PENDING_SLOT_BIT
[index
]);
503 *(unsigned32
*)PENDING_SLOT_DEST
[index
] &=
504 BIT32 (PENDING_SLOT_BIT
[index
]);
507 if (PENDING_SLOT_VALUE
[index
])
508 *(unsigned64
*)PENDING_SLOT_DEST
[index
] |=
509 BIT64 (PENDING_SLOT_BIT
[index
]);
511 *(unsigned64
*)PENDING_SLOT_DEST
[index
] &=
512 BIT64 (PENDING_SLOT_BIT
[index
]);
517 switch (PENDING_SLOT_SIZE
[index
])
520 *(unsigned32
*)PENDING_SLOT_DEST
[index
] =
521 PENDING_SLOT_VALUE
[index
];
524 *(unsigned64
*)PENDING_SLOT_DEST
[index
] =
525 PENDING_SLOT_VALUE
[index
];
529 if (PENDING_OUT
== index
)
531 PENDING_SLOT_DEST
[index
] = NULL
;
532 PENDING_OUT
= (PENDING_OUT
+ 1) % PSLOTS
;
537 index
= (index
+ 1) % PSLOTS
;
This page took 0.053016 seconds and 5 git commands to generate.