Updated sim/sky/t-dma.c: It missed check-in earlier today.
[binutils-gdb.git] / sim / mips / sim-main.c
1 /* Simulator for the MIPS architecture.
2
3 This file is part of the MIPS sim
4
5 THIS SOFTWARE IS NOT COPYRIGHTED
6
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.
10
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.
14
15 $Revision$
16 $Date$
17
18 */
19
20 #ifndef SIM_MAIN_C
21 #define SIM_MAIN_C
22
23 #include "sim-main.h"
24
25 #if !(WITH_IGEN)
26 #define SIM_MANIFESTS
27 #include "oengine.c"
28 #undef SIM_MANIFESTS
29 #endif
30
31
32 /*---------------------------------------------------------------------------*/
33 /*-- simulator engine -------------------------------------------------------*/
34 /*---------------------------------------------------------------------------*/
35
36 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
37 (revision 3.1) */
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.
50
51 NOTE: Normally (RAW == 0), when address translation fails, this
52 function raises an exception and does not return. */
53
54 INLINE_SIM_MAIN (int)
55 address_translation (SIM_DESC sd,
56 sim_cpu *cpu,
57 address_word cia,
58 address_word vAddr,
59 int IorD,
60 int LorS,
61 address_word *pAddr,
62 int *CCA,
63 int raw)
64 {
65 int res = -1; /* TRUE : Assume good return */
66
67 #ifdef DEBUG
68 sim_io_printf(sd,"AddressTranslation(0x%s,%s,%s,...);\n",pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "iSTORE" : "isLOAD"));
69 #endif
70
71 /* Check that the address is valid for this memory model */
72
73 /* For a simple (flat) memory model, we simply pass virtual
74 addressess through (mostly) unchanged. */
75 vAddr &= 0xFFFFFFFF;
76
77 *pAddr = vAddr; /* default for isTARGET */
78
79 /* start-sanitize-sky */
80 #ifdef TARGET_SKY
81 if (vAddr >= 0x80000000)
82 {
83 if (vAddr < 0xa0000000)
84 {
85 *pAddr = vAddr - 0x80000000;
86 }
87 else if (vAddr < 0xc0000000)
88 {
89 *pAddr = vAddr - 0xa0000000;
90 }
91 }
92 #endif
93 /* end-sanitize-sky */
94
95 *CCA = Uncached; /* not used for isHOST */
96
97 return(res);
98 }
99
100 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
101 (revision 3.1) */
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. */
106
107 INLINE_SIM_MAIN (void)
108 prefetch (SIM_DESC sd,
109 sim_cpu *cpu,
110 address_word cia,
111 int CCA,
112 address_word pAddr,
113 address_word vAddr,
114 int DATA,
115 int hint)
116 {
117 #ifdef DEBUG
118 sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint);
119 #endif /* DEBUG */
120
121 /* For our simple memory model we do nothing */
122 return;
123 }
124
125 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
126 (revision 3.1) */
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
140 memory element. */
141 INLINE_SIM_MAIN (void)
142 load_memory (SIM_DESC SD,
143 sim_cpu *CPU,
144 address_word cia,
145 uword64* memvalp,
146 uword64* memval1p,
147 int CCA,
148 unsigned int AccessLength,
149 address_word pAddr,
150 address_word vAddr,
151 int IorD)
152 {
153 uword64 value = 0;
154 uword64 value1 = 0;
155
156 #ifdef DEBUG
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"));
158 #endif /* DEBUG */
159
160 #if defined(WARN_MEM)
161 if (CCA != uncached)
162 sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
163 #endif /* WARN_MEM */
164
165 #if !(WITH_IGEN)
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 ();
173 #endif
174
175 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
176 {
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",
179 AccessLength,
180 (LOADDRMASK + 1) << 3,
181 pr_addr (pAddr));
182 }
183
184 #if defined(TRACE)
185 dotrace (SD, CPU, tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
186 #endif /* TRACE */
187
188 /* Read the specified number of bytes from memory. Adjust for
189 host/target byte ordering/ Align the least significant byte
190 read. */
191
192 switch (AccessLength)
193 {
194 case AccessLength_QUADWORD :
195 {
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);
199 break;
200 }
201 case AccessLength_DOUBLEWORD :
202 value = sim_core_read_aligned_8 (CPU, NULL_CIA,
203 read_map, pAddr);
204 break;
205 case AccessLength_SEPTIBYTE :
206 value = sim_core_read_misaligned_7 (CPU, NULL_CIA,
207 read_map, pAddr);
208 break;
209 case AccessLength_SEXTIBYTE :
210 value = sim_core_read_misaligned_6 (CPU, NULL_CIA,
211 read_map, pAddr);
212 break;
213 case AccessLength_QUINTIBYTE :
214 value = sim_core_read_misaligned_5 (CPU, NULL_CIA,
215 read_map, pAddr);
216 break;
217 case AccessLength_WORD :
218 value = sim_core_read_aligned_4 (CPU, NULL_CIA,
219 read_map, pAddr);
220 break;
221 case AccessLength_TRIPLEBYTE :
222 value = sim_core_read_misaligned_3 (CPU, NULL_CIA,
223 read_map, pAddr);
224 break;
225 case AccessLength_HALFWORD :
226 value = sim_core_read_aligned_2 (CPU, NULL_CIA,
227 read_map, pAddr);
228 break;
229 case AccessLength_BYTE :
230 value = sim_core_read_aligned_1 (CPU, NULL_CIA,
231 read_map, pAddr);
232 break;
233 default:
234 abort ();
235 }
236
237 #ifdef DEBUG
238 printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
239 (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
240 #endif /* DEBUG */
241
242 /* See also store_memory. Position data in correct byte lanes. */
243 if (AccessLength <= LOADDRMASK)
244 {
245 if (BigEndianMem)
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);
249 else
250 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
251 is already in the correct postition. */
252 value <<= ((pAddr & LOADDRMASK) * 8);
253 }
254
255 #ifdef DEBUG
256 printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
257 pr_uword64(value1),pr_uword64(value));
258 #endif /* DEBUG */
259
260 *memvalp = value;
261 if (memval1p) *memval1p = value1;
262 }
263
264
265 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
266 (revision 3.1) */
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
276 will be changed. */
277
278 INLINE_SIM_MAIN (void)
279 store_memory (SIM_DESC SD,
280 sim_cpu *CPU,
281 address_word cia,
282 int CCA,
283 unsigned int AccessLength,
284 uword64 MemElem,
285 uword64 MemElem1, /* High order 64 bits */
286 address_word pAddr,
287 address_word vAddr)
288 {
289 #ifdef DEBUG
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));
291 #endif /* DEBUG */
292
293 #if defined(WARN_MEM)
294 if (CCA != uncached)
295 sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
296 #endif /* WARN_MEM */
297
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",
300 AccessLength,
301 (LOADDRMASK + 1) << 3,
302 pr_addr(pAddr));
303
304 #if defined(TRACE)
305 dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
306 #endif /* TRACE */
307
308 #ifdef DEBUG
309 printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
310 #endif /* DEBUG */
311
312 /* See also load_memory. Position data in correct byte lanes. */
313 if (AccessLength <= LOADDRMASK)
314 {
315 if (BigEndianMem)
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);
319 else
320 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
321 is already in the correct postition. */
322 MemElem >>= ((pAddr & LOADDRMASK) * 8);
323 }
324
325 #ifdef DEBUG
326 printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
327 #endif /* DEBUG */
328
329 switch (AccessLength)
330 {
331 case AccessLength_QUADWORD :
332 {
333 unsigned_16 val = U16_8 (MemElem1, MemElem);
334 sim_core_write_aligned_16 (CPU, NULL_CIA, write_map, pAddr, val);
335 break;
336 }
337 case AccessLength_DOUBLEWORD :
338 sim_core_write_aligned_8 (CPU, NULL_CIA,
339 write_map, pAddr, MemElem);
340 break;
341 case AccessLength_SEPTIBYTE :
342 sim_core_write_misaligned_7 (CPU, NULL_CIA,
343 write_map, pAddr, MemElem);
344 break;
345 case AccessLength_SEXTIBYTE :
346 sim_core_write_misaligned_6 (CPU, NULL_CIA,
347 write_map, pAddr, MemElem);
348 break;
349 case AccessLength_QUINTIBYTE :
350 sim_core_write_misaligned_5 (CPU, NULL_CIA,
351 write_map, pAddr, MemElem);
352 break;
353 case AccessLength_WORD :
354 sim_core_write_aligned_4 (CPU, NULL_CIA,
355 write_map, pAddr, MemElem);
356 break;
357 case AccessLength_TRIPLEBYTE :
358 sim_core_write_misaligned_3 (CPU, NULL_CIA,
359 write_map, pAddr, MemElem);
360 break;
361 case AccessLength_HALFWORD :
362 sim_core_write_aligned_2 (CPU, NULL_CIA,
363 write_map, pAddr, MemElem);
364 break;
365 case AccessLength_BYTE :
366 sim_core_write_aligned_1 (CPU, NULL_CIA,
367 write_map, pAddr, MemElem);
368 break;
369 default:
370 abort ();
371 }
372
373 return;
374 }
375
376
377 INLINE_SIM_MAIN (unsigned32)
378 ifetch32 (SIM_DESC SD,
379 sim_cpu *CPU,
380 address_word cia,
381 address_word vaddr)
382 {
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);
388 unsigned int byte;
389 address_word paddr;
390 int uncached;
391 unsigned64 memval;
392
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));
400 }
401
402
403 INLINE_SIM_MAIN (unsigned16)
404 ifetch16 (SIM_DESC SD,
405 sim_cpu *CPU,
406 address_word cia,
407 address_word vaddr)
408 {
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);
414 unsigned int byte;
415 address_word paddr;
416 int uncached;
417 unsigned64 memval;
418
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));
426 }
427
428
429
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
434 processors. */
435 INLINE_SIM_MAIN (void)
436 sync_operation (SIM_DESC sd,
437 sim_cpu *cpu,
438 address_word cia,
439 int stype)
440 {
441 #ifdef DEBUG
442 sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
443 #endif /* DEBUG */
444 return;
445 }
446
447 INLINE_SIM_MAIN (void)
448 cache_op (SIM_DESC SD,
449 sim_cpu *CPU,
450 address_word cia,
451 int op,
452 address_word pAddr,
453 address_word vAddr,
454 unsigned int instruction)
455 {
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;
459 #else
460 static int icache_warning = 0;
461 static int dcache_warning = 0;
462 #endif
463
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. */
467 #if 0
468 sim_io_printf(SD,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia));
469 #endif
470
471 switch (op & 0x3) {
472 case 0: /* instruction cache */
473 switch (op >> 2) {
474 case 0: /* Index Invalidate */
475 case 1: /* Index Load Tag */
476 case 2: /* Index Store Tag */
477 case 4: /* Hit Invalidate */
478 case 5: /* Fill */
479 case 6: /* Hit Writeback */
480 if (!icache_warning)
481 {
482 sim_io_eprintf(SD,"Instruction CACHE operation %d to be coded\n",(op >> 2));
483 icache_warning = 1;
484 }
485 break;
486
487 default:
488 SignalException(ReservedInstruction,instruction);
489 break;
490 }
491 break;
492
493 case 1: /* data cache */
494 switch (op >> 2) {
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 */
502 if (!dcache_warning)
503 {
504 sim_io_eprintf(SD,"Data CACHE operation %d to be coded\n",(op >> 2));
505 dcache_warning = 1;
506 }
507 break;
508
509 default:
510 SignalException(ReservedInstruction,instruction);
511 break;
512 }
513 break;
514
515 default: /* unrecognised cache ID */
516 SignalException(ReservedInstruction,instruction);
517 break;
518 }
519
520 return;
521 }
522
523
524 INLINE_SIM_MAIN (void)
525 pending_tick (SIM_DESC SD,
526 sim_cpu *CPU,
527 address_word cia)
528 {
529 if (PENDING_TRACE)
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)
532 {
533 int loop;
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++)
539 {
540 if (PENDING_SLOT_DEST[index] != NULL)
541 {
542 PENDING_SLOT_DELAY[index] -= 1;
543 if (PENDING_SLOT_DELAY[index] == 0)
544 {
545 if (PENDING_SLOT_BIT[index] >= 0)
546 switch (PENDING_SLOT_SIZE[index])
547 {
548 case 32:
549 if (PENDING_SLOT_VALUE[index])
550 *(unsigned32*)PENDING_SLOT_DEST[index] |=
551 BIT32 (PENDING_SLOT_BIT[index]);
552 else
553 *(unsigned32*)PENDING_SLOT_DEST[index] &=
554 BIT32 (PENDING_SLOT_BIT[index]);
555 break;
556 case 64:
557 if (PENDING_SLOT_VALUE[index])
558 *(unsigned64*)PENDING_SLOT_DEST[index] |=
559 BIT64 (PENDING_SLOT_BIT[index]);
560 else
561 *(unsigned64*)PENDING_SLOT_DEST[index] &=
562 BIT64 (PENDING_SLOT_BIT[index]);
563 break;
564 break;
565 }
566 else
567 switch (PENDING_SLOT_SIZE[index])
568 {
569 case 32:
570 *(unsigned32*)PENDING_SLOT_DEST[index] =
571 PENDING_SLOT_VALUE[index];
572 break;
573 case 64:
574 *(unsigned64*)PENDING_SLOT_DEST[index] =
575 PENDING_SLOT_VALUE[index];
576 break;
577 }
578 }
579 if (PENDING_OUT == index)
580 {
581 PENDING_SLOT_DEST[index] = NULL;
582 PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;
583 PENDING_TOTAL--;
584 }
585 }
586 }
587 index = (index + 1) % PSLOTS;
588 }
589 }
590
591
592 #endif