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/>.
22 /* This must come before any other includes. */
26 #include "sim-assert.h"
30 /*---------------------------------------------------------------------------*/
31 /*-- simulator engine -------------------------------------------------------*/
32 /*---------------------------------------------------------------------------*/
35 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
37 /* Load a value from memory. Use the cache and main memory as
38 specified in the Cache Coherence Algorithm (CCA) and the sort of
39 access (IorD) to find the contents of AccessLength memory bytes
40 starting at physical location pAddr. The data is returned in the
41 fixed width naturally-aligned memory element (MemElem). The
42 low-order two (or three) bits of the address and the AccessLength
43 indicate which of the bytes within MemElem needs to be given to the
44 processor. If the memory access type of the reference is uncached
45 then only the referenced bytes are read from memory and valid
46 within the memory element. If the access type is cached, and the
47 data is not present in cache, an implementation specific size and
48 alignment block of memory is read and loaded into the cache to
49 satisfy a load reference. At a minimum, the block is the entire
51 INLINE_SIM_MAIN (void)
52 load_memory (SIM_DESC SD
,
58 unsigned int AccessLength
,
67 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"));
72 sim_io_eprintf(sd
,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA
);
75 if (((pAddr
& LOADDRMASK
) + AccessLength
) > LOADDRMASK
)
77 /* In reality this should be a Bus Error */
78 sim_io_error (SD
, "LOAD AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
80 (LOADDRMASK
+ 1) << 3,
84 dotrace (SD
, CPU
, tracefh
,((IorD
== isDATA
) ? 0 : 2),(unsigned int)(pAddr
&0xFFFFFFFF),(AccessLength
+ 1),"load%s",((IorD
== isDATA
) ? "" : " instruction"));
86 /* Read the specified number of bytes from memory. Adjust for
87 host/target byte ordering/ Align the least significant byte
92 case AccessLength_QUADWORD
:
94 unsigned_16 val
= sim_core_read_aligned_16 (CPU
, cia
, read_map
, pAddr
);
95 value1
= VH8_16 (val
);
99 case AccessLength_DOUBLEWORD
:
100 value
= sim_core_read_aligned_8 (CPU
, cia
, read_map
, pAddr
);
102 case AccessLength_SEPTIBYTE
:
103 value
= sim_core_read_misaligned_7 (CPU
, cia
, read_map
, pAddr
);
105 case AccessLength_SEXTIBYTE
:
106 value
= sim_core_read_misaligned_6 (CPU
, cia
, read_map
, pAddr
);
108 case AccessLength_QUINTIBYTE
:
109 value
= sim_core_read_misaligned_5 (CPU
, cia
, read_map
, pAddr
);
111 case AccessLength_WORD
:
112 value
= sim_core_read_aligned_4 (CPU
, cia
, read_map
, pAddr
);
114 case AccessLength_TRIPLEBYTE
:
115 value
= sim_core_read_misaligned_3 (CPU
, cia
, read_map
, pAddr
);
117 case AccessLength_HALFWORD
:
118 value
= sim_core_read_aligned_2 (CPU
, cia
, read_map
, pAddr
);
120 case AccessLength_BYTE
:
121 value
= sim_core_read_aligned_1 (CPU
, cia
, read_map
, pAddr
);
128 printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
129 (int)(pAddr
& LOADDRMASK
),pr_uword64(value1
),pr_uword64(value
));
132 /* See also store_memory. Position data in correct byte lanes. */
133 if (AccessLength
<= LOADDRMASK
)
136 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
137 shifted to the most significant byte position. */
138 value
<<= (((LOADDRMASK
- (pAddr
& LOADDRMASK
)) - AccessLength
) * 8);
140 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
141 is already in the correct postition. */
142 value
<<= ((pAddr
& LOADDRMASK
) * 8);
146 printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
147 pr_uword64(value1
),pr_uword64(value
));
151 if (memval1p
) *memval1p
= value1
;
155 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
157 /* Store a value to memory. The specified data is stored into the
158 physical location pAddr using the memory hierarchy (data caches and
159 main memory) as specified by the Cache Coherence Algorithm
160 (CCA). The MemElem contains the data for an aligned, fixed-width
161 memory element (word for 32-bit processors, doubleword for 64-bit
162 processors), though only the bytes that will actually be stored to
163 memory need to be valid. The low-order two (or three) bits of pAddr
164 and the AccessLength field indicates which of the bytes within the
165 MemElem data should actually be stored; only these bytes in memory
168 INLINE_SIM_MAIN (void)
169 store_memory (SIM_DESC SD
,
173 unsigned int AccessLength
,
175 uword64 MemElem1
, /* High order 64 bits */
180 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
));
183 #if defined(WARN_MEM)
185 sim_io_eprintf(sd
,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA
);
186 #endif /* WARN_MEM */
188 if (((pAddr
& LOADDRMASK
) + AccessLength
) > LOADDRMASK
)
189 sim_io_error (SD
, "STORE AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
191 (LOADDRMASK
+ 1) << 3,
194 dotrace (SD
, CPU
, tracefh
,1,(unsigned int)(pAddr
&0xFFFFFFFF),(AccessLength
+ 1),"store");
197 printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr
& LOADDRMASK
),pr_uword64(MemElem1
),pr_uword64(MemElem
));
200 /* See also load_memory. Position data in correct byte lanes. */
201 if (AccessLength
<= LOADDRMASK
)
204 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
205 shifted to the most significant byte position. */
206 MemElem
>>= (((LOADDRMASK
- (pAddr
& LOADDRMASK
)) - AccessLength
) * 8);
208 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
209 is already in the correct postition. */
210 MemElem
>>= ((pAddr
& LOADDRMASK
) * 8);
214 printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift
,pr_uword64(MemElem1
),pr_uword64(MemElem
));
217 switch (AccessLength
)
219 case AccessLength_QUADWORD
:
221 unsigned_16 val
= U16_8 (MemElem1
, MemElem
);
222 sim_core_write_aligned_16 (CPU
, cia
, write_map
, pAddr
, val
);
225 case AccessLength_DOUBLEWORD
:
226 sim_core_write_aligned_8 (CPU
, cia
, write_map
, pAddr
, MemElem
);
228 case AccessLength_SEPTIBYTE
:
229 sim_core_write_misaligned_7 (CPU
, cia
, write_map
, pAddr
, MemElem
);
231 case AccessLength_SEXTIBYTE
:
232 sim_core_write_misaligned_6 (CPU
, cia
, write_map
, pAddr
, MemElem
);
234 case AccessLength_QUINTIBYTE
:
235 sim_core_write_misaligned_5 (CPU
, cia
, write_map
, pAddr
, MemElem
);
237 case AccessLength_WORD
:
238 sim_core_write_aligned_4 (CPU
, cia
, write_map
, pAddr
, MemElem
);
240 case AccessLength_TRIPLEBYTE
:
241 sim_core_write_misaligned_3 (CPU
, cia
, write_map
, pAddr
, MemElem
);
243 case AccessLength_HALFWORD
:
244 sim_core_write_aligned_2 (CPU
, cia
, write_map
, pAddr
, MemElem
);
246 case AccessLength_BYTE
:
247 sim_core_write_aligned_1 (CPU
, cia
, write_map
, pAddr
, MemElem
);
257 INLINE_SIM_MAIN (uint32_t)
258 ifetch32 (SIM_DESC SD
,
263 /* Copy the action of the LW instruction */
264 address_word mask
= LOADDRMASK
;
265 address_word access
= AccessLength_WORD
;
266 address_word reverseendian
= (ReverseEndian
? (mask
^ access
) : 0);
267 address_word bigendiancpu
= (BigEndianCPU
? (mask
^ access
) : 0);
269 address_word paddr
= vaddr
;
272 if ((vaddr
& access
) != 0)
273 SignalExceptionInstructionFetch ();
274 paddr
= ((paddr
& ~mask
) | ((paddr
& mask
) ^ reverseendian
));
275 LoadMemory (&memval
, NULL
, access
, paddr
, vaddr
, isINSTRUCTION
, isREAL
);
276 byte
= ((vaddr
& mask
) ^ bigendiancpu
);
277 return (memval
>> (8 * byte
));
281 INLINE_SIM_MAIN (uint16_t)
282 ifetch16 (SIM_DESC SD
,
287 /* Copy the action of the LH instruction */
288 address_word mask
= LOADDRMASK
;
289 address_word access
= AccessLength_HALFWORD
;
290 address_word reverseendian
= (ReverseEndian
? (mask
^ access
) : 0);
291 address_word bigendiancpu
= (BigEndianCPU
? (mask
^ access
) : 0);
293 address_word paddr
= vaddr
;
296 if ((vaddr
& access
) != 0)
297 SignalExceptionInstructionFetch ();
298 paddr
= ((paddr
& ~mask
) | ((paddr
& mask
) ^ reverseendian
));
299 LoadMemory (&memval
, NULL
, access
, paddr
, vaddr
, isINSTRUCTION
, isREAL
);
300 byte
= ((vaddr
& mask
) ^ bigendiancpu
);
301 return (memval
>> (8 * byte
));
306 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
307 /* Order loads and stores to synchronise shared memory. Perform the
308 action necessary to make the effects of groups of synchronizable
309 loads and stores indicated by stype occur in the same order for all
311 INLINE_SIM_MAIN (void)
312 sync_operation (SIM_DESC sd
,
318 sim_io_printf(sd
,"SyncOperation(%d) : TODO\n",stype
);
323 INLINE_SIM_MAIN (void)
324 cache_op (SIM_DESC SD
,
330 unsigned int instruction
)
332 #if 1 /* stop warning message being displayed (we should really just remove the code) */
333 static int icache_warning
= 1;
334 static int dcache_warning
= 1;
336 static int icache_warning
= 0;
337 static int dcache_warning
= 0;
340 /* If CP0 is not useable (User or Supervisor mode) and the CP0
341 enable bit in the Status Register is clear - a coprocessor
342 unusable exception is taken. */
344 sim_io_printf(SD
,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia
));
348 case 0: /* instruction cache */
350 case 0: /* Index Invalidate */
351 case 1: /* Index Load Tag */
352 case 2: /* Index Store Tag */
353 case 4: /* Hit Invalidate */
355 case 6: /* Hit Writeback */
358 sim_io_eprintf(SD
,"Instruction CACHE operation %d to be coded\n",(op
>> 2));
364 SignalException(ReservedInstruction
,instruction
);
369 case 1: /* data cache */
370 case 3: /* secondary data cache */
372 case 0: /* Index Writeback Invalidate */
373 case 1: /* Index Load Tag */
374 case 2: /* Index Store Tag */
375 case 3: /* Create Dirty */
376 case 4: /* Hit Invalidate */
377 case 5: /* Hit Writeback Invalidate */
378 case 6: /* Hit Writeback */
381 sim_io_eprintf(SD
,"Data CACHE operation %d to be coded\n",(op
>> 2));
387 SignalException(ReservedInstruction
,instruction
);
392 default: /* unrecognised cache ID */
393 SignalException(ReservedInstruction
,instruction
);
401 INLINE_SIM_MAIN (void)
402 pending_tick (SIM_DESC SD
,
407 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
);
408 if (PENDING_OUT
!= PENDING_IN
)
411 int index
= PENDING_OUT
;
412 int total
= PENDING_TOTAL
;
413 if (PENDING_TOTAL
== 0)
414 sim_engine_abort (SD
, CPU
, cia
, "PENDING_DRAIN - Mis-match on pending update pointers\n");
415 for (loop
= 0, index
= PENDING_OUT
;
417 loop
++, index
= (index
+ 1) % PSLOTS
)
419 if (PENDING_SLOT_DEST
[index
] != NULL
)
421 PENDING_SLOT_DELAY
[index
] -= 1;
422 if (PENDING_SLOT_DELAY
[index
] == 0)
425 sim_io_eprintf (SD
, "PENDING_DRAIN - drained - index %d, dest %p, bit %d, val %" PRIx64
", size %d\n",
427 PENDING_SLOT_DEST
[index
],
428 PENDING_SLOT_BIT
[index
],
429 PENDING_SLOT_VALUE
[index
],
430 PENDING_SLOT_SIZE
[index
]);
431 if (PENDING_SLOT_BIT
[index
] >= 0)
432 switch (PENDING_SLOT_SIZE
[index
])
435 if (PENDING_SLOT_VALUE
[index
])
436 *(uint32_t*)PENDING_SLOT_DEST
[index
] |=
437 BIT32 (PENDING_SLOT_BIT
[index
]);
439 *(uint32_t*)PENDING_SLOT_DEST
[index
] &=
440 BIT32 (PENDING_SLOT_BIT
[index
]);
443 if (PENDING_SLOT_VALUE
[index
])
444 *(uint64_t*)PENDING_SLOT_DEST
[index
] |=
445 BIT64 (PENDING_SLOT_BIT
[index
]);
447 *(uint64_t*)PENDING_SLOT_DEST
[index
] &=
448 BIT64 (PENDING_SLOT_BIT
[index
]);
452 switch (PENDING_SLOT_SIZE
[index
])
455 *(uint32_t*)PENDING_SLOT_DEST
[index
] =
456 PENDING_SLOT_VALUE
[index
];
459 *(uint64_t*)PENDING_SLOT_DEST
[index
] =
460 PENDING_SLOT_VALUE
[index
];
463 if (PENDING_OUT
== index
)
465 PENDING_SLOT_DEST
[index
] = NULL
;
466 PENDING_OUT
= (PENDING_OUT
+ 1) % PSLOTS
;
470 else if (PENDING_TRACE
&& PENDING_SLOT_DELAY
[index
] > 0)
471 sim_io_eprintf (SD
, "PENDING_DRAIN - queued - index %d, delay %d, dest %p, bit %d, val %" PRIx64
", size %d\n",
472 index
, PENDING_SLOT_DELAY
[index
],
473 PENDING_SLOT_DEST
[index
],
474 PENDING_SLOT_BIT
[index
],
475 PENDING_SLOT_VALUE
[index
],
476 PENDING_SLOT_SIZE
[index
]);