1 /* Copyright (C) 1998, Cygnus Solutions
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 3 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "sim-assert.h"
26 /*---------------------------------------------------------------------------*/
27 /*-- simulator engine -------------------------------------------------------*/
28 /*---------------------------------------------------------------------------*/
31 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
33 /* Translate a virtual address to a physical address and cache
34 coherence algorithm describing the mechanism used to resolve the
35 memory reference. Given the virtual address vAddr, and whether the
36 reference is to Instructions ot Data (IorD), find the corresponding
37 physical address (pAddr) and the cache coherence algorithm (CCA)
38 used to resolve the reference. If the virtual address is in one of
39 the unmapped address spaces the physical address and the CCA are
40 determined directly by the virtual address. If the virtual address
41 is in one of the mapped address spaces then the TLB is used to
42 determine the physical address and access type; if the required
43 translation is not present in the TLB or the desired access is not
44 permitted the function fails and an exception is taken.
46 NOTE: Normally (RAW == 0), when address translation fails, this
47 function raises an exception and does not return. */
51 address_translation (SIM_DESC sd
,
61 int res
= -1; /* TRUE : Assume good return */
64 sim_io_printf (sd
, "AddressTranslation(0x%s,%s,%s,...);\n", pr_addr (vAddr
), (IorD
? "isDATA" : "isINSTRUCTION"), (LorS
? "iSTORE" : "isLOAD"));
67 /* Check that the address is valid for this memory model */
69 /* For a simple (flat) memory model, we simply pass virtual
70 addressess through (mostly) unchanged. */
73 *pAddr
= vAddr
; /* default for isTARGET */
74 *CCA
= Uncached
; /* not used for isHOST */
81 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
83 /* Prefetch data from memory. Prefetch is an advisory instruction for
84 which an implementation specific action is taken. The action taken
85 may increase performance, but must not change the meaning of the
86 program, or alter architecturally-visible state. */
88 INLINE_SIM_MAIN (void)
89 prefetch (SIM_DESC sd
,
99 sim_io_printf(sd
,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA
,pr_addr(pAddr
),pr_addr(vAddr
),DATA
,hint
);
102 /* For our simple memory model we do nothing */
106 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
108 /* Load a value from memory. Use the cache and main memory as
109 specified in the Cache Coherence Algorithm (CCA) and the sort of
110 access (IorD) to find the contents of AccessLength memory bytes
111 starting at physical location pAddr. The data is returned in the
112 fixed width naturally-aligned memory element (MemElem). The
113 low-order two (or three) bits of the address and the AccessLength
114 indicate which of the bytes within MemElem needs to be given to the
115 processor. If the memory access type of the reference is uncached
116 then only the referenced bytes are read from memory and valid
117 within the memory element. If the access type is cached, and the
118 data is not present in cache, an implementation specific size and
119 alignment block of memory is read and loaded into the cache to
120 satisfy a load reference. At a minimum, the block is the entire
122 INLINE_SIM_MAIN (void)
123 load_memory (SIM_DESC SD
,
129 unsigned int AccessLength
,
138 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"));
141 #if defined(WARN_MEM)
143 sim_io_eprintf(sd
,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA
);
144 #endif /* WARN_MEM */
146 if (((pAddr
& LOADDRMASK
) + AccessLength
) > LOADDRMASK
)
148 /* In reality this should be a Bus Error */
149 sim_io_error (SD
, "LOAD AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
151 (LOADDRMASK
+ 1) << 3,
155 dotrace (SD
, CPU
, tracefh
,((IorD
== isDATA
) ? 0 : 2),(unsigned int)(pAddr
&0xFFFFFFFF),(AccessLength
+ 1),"load%s",((IorD
== isDATA
) ? "" : " instruction"));
157 /* Read the specified number of bytes from memory. Adjust for
158 host/target byte ordering/ Align the least significant byte
161 switch (AccessLength
)
163 case AccessLength_QUADWORD
:
165 unsigned_16 val
= sim_core_read_aligned_16 (CPU
, cia
, read_map
, pAddr
);
166 value1
= VH8_16 (val
);
167 value
= VL8_16 (val
);
170 case AccessLength_DOUBLEWORD
:
171 value
= sim_core_read_aligned_8 (CPU
, cia
, read_map
, pAddr
);
173 case AccessLength_SEPTIBYTE
:
174 value
= sim_core_read_misaligned_7 (CPU
, cia
, read_map
, pAddr
);
176 case AccessLength_SEXTIBYTE
:
177 value
= sim_core_read_misaligned_6 (CPU
, cia
, read_map
, pAddr
);
179 case AccessLength_QUINTIBYTE
:
180 value
= sim_core_read_misaligned_5 (CPU
, cia
, read_map
, pAddr
);
182 case AccessLength_WORD
:
183 value
= sim_core_read_aligned_4 (CPU
, cia
, read_map
, pAddr
);
185 case AccessLength_TRIPLEBYTE
:
186 value
= sim_core_read_misaligned_3 (CPU
, cia
, read_map
, pAddr
);
188 case AccessLength_HALFWORD
:
189 value
= sim_core_read_aligned_2 (CPU
, cia
, read_map
, pAddr
);
191 case AccessLength_BYTE
:
192 value
= sim_core_read_aligned_1 (CPU
, cia
, read_map
, pAddr
);
199 printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
200 (int)(pAddr
& LOADDRMASK
),pr_uword64(value1
),pr_uword64(value
));
203 /* See also store_memory. Position data in correct byte lanes. */
204 if (AccessLength
<= LOADDRMASK
)
207 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
208 shifted to the most significant byte position. */
209 value
<<= (((LOADDRMASK
- (pAddr
& LOADDRMASK
)) - AccessLength
) * 8);
211 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
212 is already in the correct postition. */
213 value
<<= ((pAddr
& LOADDRMASK
) * 8);
217 printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
218 pr_uword64(value1
),pr_uword64(value
));
222 if (memval1p
) *memval1p
= value1
;
226 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
228 /* Store a value to memory. The specified data is stored into the
229 physical location pAddr using the memory hierarchy (data caches and
230 main memory) as specified by the Cache Coherence Algorithm
231 (CCA). The MemElem contains the data for an aligned, fixed-width
232 memory element (word for 32-bit processors, doubleword for 64-bit
233 processors), though only the bytes that will actually be stored to
234 memory need to be valid. The low-order two (or three) bits of pAddr
235 and the AccessLength field indicates which of the bytes within the
236 MemElem data should actually be stored; only these bytes in memory
239 INLINE_SIM_MAIN (void)
240 store_memory (SIM_DESC SD
,
244 unsigned int AccessLength
,
246 uword64 MemElem1
, /* High order 64 bits */
251 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 #if defined(WARN_MEM)
256 sim_io_eprintf(sd
,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA
);
257 #endif /* WARN_MEM */
259 if (((pAddr
& LOADDRMASK
) + AccessLength
) > LOADDRMASK
)
260 sim_io_error (SD
, "STORE AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
262 (LOADDRMASK
+ 1) << 3,
265 dotrace (SD
, CPU
, tracefh
,1,(unsigned int)(pAddr
&0xFFFFFFFF),(AccessLength
+ 1),"store");
268 printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr
& LOADDRMASK
),pr_uword64(MemElem1
),pr_uword64(MemElem
));
271 /* See also load_memory. Position data in correct byte lanes. */
272 if (AccessLength
<= LOADDRMASK
)
275 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
276 shifted to the most significant byte position. */
277 MemElem
>>= (((LOADDRMASK
- (pAddr
& LOADDRMASK
)) - AccessLength
) * 8);
279 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
280 is already in the correct postition. */
281 MemElem
>>= ((pAddr
& LOADDRMASK
) * 8);
285 printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift
,pr_uword64(MemElem1
),pr_uword64(MemElem
));
288 switch (AccessLength
)
290 case AccessLength_QUADWORD
:
292 unsigned_16 val
= U16_8 (MemElem1
, MemElem
);
293 sim_core_write_aligned_16 (CPU
, cia
, write_map
, pAddr
, val
);
296 case AccessLength_DOUBLEWORD
:
297 sim_core_write_aligned_8 (CPU
, cia
, write_map
, pAddr
, MemElem
);
299 case AccessLength_SEPTIBYTE
:
300 sim_core_write_misaligned_7 (CPU
, cia
, write_map
, pAddr
, MemElem
);
302 case AccessLength_SEXTIBYTE
:
303 sim_core_write_misaligned_6 (CPU
, cia
, write_map
, pAddr
, MemElem
);
305 case AccessLength_QUINTIBYTE
:
306 sim_core_write_misaligned_5 (CPU
, cia
, write_map
, pAddr
, MemElem
);
308 case AccessLength_WORD
:
309 sim_core_write_aligned_4 (CPU
, cia
, write_map
, pAddr
, MemElem
);
311 case AccessLength_TRIPLEBYTE
:
312 sim_core_write_misaligned_3 (CPU
, cia
, write_map
, pAddr
, MemElem
);
314 case AccessLength_HALFWORD
:
315 sim_core_write_aligned_2 (CPU
, cia
, write_map
, pAddr
, MemElem
);
317 case AccessLength_BYTE
:
318 sim_core_write_aligned_1 (CPU
, cia
, write_map
, pAddr
, MemElem
);
328 INLINE_SIM_MAIN (unsigned32
)
329 ifetch32 (SIM_DESC SD
,
334 /* Copy the action of the LW instruction */
335 address_word mask
= LOADDRMASK
;
336 address_word access
= AccessLength_WORD
;
337 address_word reverseendian
= (ReverseEndian
? (mask
^ access
) : 0);
338 address_word bigendiancpu
= (BigEndianCPU
? (mask
^ access
) : 0);
344 if ((vaddr
& access
) != 0)
345 SignalExceptionInstructionFetch ();
346 AddressTranslation (vaddr
, isINSTRUCTION
, isLOAD
, &paddr
, &uncached
, isTARGET
, isREAL
);
347 paddr
= ((paddr
& ~mask
) | ((paddr
& mask
) ^ reverseendian
));
348 LoadMemory (&memval
, NULL
, uncached
, access
, paddr
, vaddr
, isINSTRUCTION
, isREAL
);
349 byte
= ((vaddr
& mask
) ^ bigendiancpu
);
350 return (memval
>> (8 * byte
));
354 INLINE_SIM_MAIN (unsigned16
)
355 ifetch16 (SIM_DESC SD
,
360 /* Copy the action of the LH instruction */
361 address_word mask
= LOADDRMASK
;
362 address_word access
= AccessLength_HALFWORD
;
363 address_word reverseendian
= (ReverseEndian
? (mask
^ access
) : 0);
364 address_word bigendiancpu
= (BigEndianCPU
? (mask
^ access
) : 0);
370 if ((vaddr
& access
) != 0)
371 SignalExceptionInstructionFetch ();
372 AddressTranslation (vaddr
, isINSTRUCTION
, isLOAD
, &paddr
, &uncached
, isTARGET
, isREAL
);
373 paddr
= ((paddr
& ~mask
) | ((paddr
& mask
) ^ reverseendian
));
374 LoadMemory (&memval
, NULL
, uncached
, access
, paddr
, vaddr
, isINSTRUCTION
, isREAL
);
375 byte
= ((vaddr
& mask
) ^ bigendiancpu
);
376 return (memval
>> (8 * byte
));
381 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
382 /* Order loads and stores to synchronise shared memory. Perform the
383 action necessary to make the effects of groups of synchronizable
384 loads and stores indicated by stype occur in the same order for all
386 INLINE_SIM_MAIN (void)
387 sync_operation (SIM_DESC sd
,
393 sim_io_printf(sd
,"SyncOperation(%d) : TODO\n",stype
);
398 INLINE_SIM_MAIN (void)
399 cache_op (SIM_DESC SD
,
405 unsigned int instruction
)
407 #if 1 /* stop warning message being displayed (we should really just remove the code) */
408 static int icache_warning
= 1;
409 static int dcache_warning
= 1;
411 static int icache_warning
= 0;
412 static int dcache_warning
= 0;
415 /* If CP0 is not useable (User or Supervisor mode) and the CP0
416 enable bit in the Status Register is clear - a coprocessor
417 unusable exception is taken. */
419 sim_io_printf(SD
,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia
));
423 case 0: /* instruction cache */
425 case 0: /* Index Invalidate */
426 case 1: /* Index Load Tag */
427 case 2: /* Index Store Tag */
428 case 4: /* Hit Invalidate */
430 case 6: /* Hit Writeback */
433 sim_io_eprintf(SD
,"Instruction CACHE operation %d to be coded\n",(op
>> 2));
439 SignalException(ReservedInstruction
,instruction
);
444 case 1: /* data cache */
445 case 3: /* secondary data cache */
447 case 0: /* Index Writeback Invalidate */
448 case 1: /* Index Load Tag */
449 case 2: /* Index Store Tag */
450 case 3: /* Create Dirty */
451 case 4: /* Hit Invalidate */
452 case 5: /* Hit Writeback Invalidate */
453 case 6: /* Hit Writeback */
456 sim_io_eprintf(SD
,"Data CACHE operation %d to be coded\n",(op
>> 2));
462 SignalException(ReservedInstruction
,instruction
);
467 default: /* unrecognised cache ID */
468 SignalException(ReservedInstruction
,instruction
);
476 INLINE_SIM_MAIN (void)
477 pending_tick (SIM_DESC SD
,
482 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
);
483 if (PENDING_OUT
!= PENDING_IN
)
486 int index
= PENDING_OUT
;
487 int total
= PENDING_TOTAL
;
488 if (PENDING_TOTAL
== 0)
489 sim_engine_abort (SD
, CPU
, cia
, "PENDING_DRAIN - Mis-match on pending update pointers\n");
490 for (loop
= 0, index
= PENDING_OUT
;
492 loop
++, index
= (index
+ 1) % PSLOTS
)
494 if (PENDING_SLOT_DEST
[index
] != NULL
)
496 PENDING_SLOT_DELAY
[index
] -= 1;
497 if (PENDING_SLOT_DELAY
[index
] == 0)
500 sim_io_eprintf (SD
, "PENDING_DRAIN - drained - index %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
502 (unsigned long) PENDING_SLOT_DEST
[index
],
503 PENDING_SLOT_BIT
[index
],
504 (unsigned long) PENDING_SLOT_VALUE
[index
],
505 PENDING_SLOT_SIZE
[index
]);
506 if (PENDING_SLOT_BIT
[index
] >= 0)
507 switch (PENDING_SLOT_SIZE
[index
])
510 if (PENDING_SLOT_VALUE
[index
])
511 *(unsigned32
*)PENDING_SLOT_DEST
[index
] |=
512 BIT32 (PENDING_SLOT_BIT
[index
]);
514 *(unsigned32
*)PENDING_SLOT_DEST
[index
] &=
515 BIT32 (PENDING_SLOT_BIT
[index
]);
518 if (PENDING_SLOT_VALUE
[index
])
519 *(unsigned64
*)PENDING_SLOT_DEST
[index
] |=
520 BIT64 (PENDING_SLOT_BIT
[index
]);
522 *(unsigned64
*)PENDING_SLOT_DEST
[index
] &=
523 BIT64 (PENDING_SLOT_BIT
[index
]);
527 switch (PENDING_SLOT_SIZE
[index
])
530 *(unsigned32
*)PENDING_SLOT_DEST
[index
] =
531 PENDING_SLOT_VALUE
[index
];
534 *(unsigned64
*)PENDING_SLOT_DEST
[index
] =
535 PENDING_SLOT_VALUE
[index
];
538 if (PENDING_OUT
== index
)
540 PENDING_SLOT_DEST
[index
] = NULL
;
541 PENDING_OUT
= (PENDING_OUT
+ 1) % PSLOTS
;
545 else if (PENDING_TRACE
&& PENDING_SLOT_DELAY
[index
] > 0)
546 sim_io_eprintf (SD
, "PENDING_DRAIN - queued - index %d, delay %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
547 index
, PENDING_SLOT_DELAY
[index
],
548 (unsigned long) PENDING_SLOT_DEST
[index
],
549 PENDING_SLOT_BIT
[index
],
550 (unsigned long) PENDING_SLOT_VALUE
[index
],
551 PENDING_SLOT_SIZE
[index
]);