This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / sim / mips / sim-main.c
CommitLineData
fd6e6422 1/* Copyright (C) 1998, Cygnus Solutions
64ed8b6a 2
fd6e6422
FCE
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 2 of the License, or
6 (at your option) any later version.
64ed8b6a 7
fd6e6422
FCE
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.
64ed8b6a 12
fd6e6422
FCE
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
64ed8b6a 16
fd6e6422 17 */
64ed8b6a 18
64ed8b6a
AC
19
20#ifndef SIM_MAIN_C
21#define SIM_MAIN_C
22
23#include "sim-main.h"
fd6e6422 24#include "sim-assert.h"
64ed8b6a
AC
25
26#if !(WITH_IGEN)
27#define SIM_MANIFESTS
28#include "oengine.c"
29#undef SIM_MANIFESTS
30#endif
31
32
33/*---------------------------------------------------------------------------*/
34/*-- simulator engine -------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
fd6e6422
FCE
37/* start-sanitize-sky */
38#ifdef TARGET_SKY
39
64ed8b6a
AC
40/* Description from page A-22 of the "MIPS IV Instruction Set" manual
41 (revision 3.1) */
fd6e6422 42
64ed8b6a
AC
43/* Translate a virtual address to a physical address and cache
44 coherence algorithm describing the mechanism used to resolve the
45 memory reference. Given the virtual address vAddr, and whether the
46 reference is to Instructions ot Data (IorD), find the corresponding
47 physical address (pAddr) and the cache coherence algorithm (CCA)
48 used to resolve the reference. If the virtual address is in one of
49 the unmapped address spaces the physical address and the CCA are
50 determined directly by the virtual address. If the virtual address
51 is in one of the mapped address spaces then the TLB is used to
52 determine the physical address and access type; if the required
53 translation is not present in the TLB or the desired access is not
54 permitted the function fails and an exception is taken.
55
56 NOTE: Normally (RAW == 0), when address translation fails, this
57 function raises an exception and does not return. */
58
fd6e6422
FCE
59/* This implementation is for the MIPS R4000 family. See MIPS RISC
60 Architecture, Kane & Heinrich, Chapter 4. It is no good for any
61 of the 2000, 3000, or 6000 family.
62
63 One possible error in the K&H book of note. K&H has the PFN entry
64 in the TLB as being 24 bits. The high-order 4 bits would seem to be
65 unused, as the PFN is only 20-bits long. The 5900 manual shows
66 this as a 20-bit field. At any rate, the high order 4 bits are
67 unused.
68*/
69
70
71
72/* A place to remember the last cache hit. */
73static r4000_tlb_entry_t *last_hit = 0;
74
75/* Try to match a single TLB entry. Three possibilities.
76 1. No match, returns 0
77 2. Match w/o exception, pAddr and CCA set, returns 1
78 3. Match w/ exception, in which case tlb_try_match does not return.
79*/
64ed8b6a 80INLINE_SIM_MAIN (int)
fd6e6422
FCE
81tlb_try_match (SIM_DESC SD, sim_cpu *CPU, address_word cia, r4000_tlb_entry_t * entry, unsigned32 asid, unsigned32 vAddr, address_word * pAddr, int *CCA, int LorS)
82{
83 unsigned32 page_mask, vpn2_mask;
84 page_mask = (entry->mask & 0x01ffe000);
85 vpn2_mask = ~(page_mask | 0x00001fff);
86
87 if ((vAddr & vpn2_mask) == (entry->hi & vpn2_mask)
88 && ((entry->hi & TLB_HI_ASID_MASK) == asid
89 || (entry->hi & TLB_HI_G_MASK) != 0))
90 {
91 /* OK. Now, do we match lo0, or lo1? */
92 unsigned32 offset_mask, vpn_lo_mask, vpn_mask, lo;
93
94 offset_mask = (page_mask >> 1) | 0xfff;
95 vpn_lo_mask = offset_mask + 1;
96 vpn_mask = ~(offset_mask);
97
98 ASSERT(vpn_lo_mask == (-vpn2_mask) >> 1);
99 ASSERT(vpn_mask ^ vpn_lo_mask == vpn2_mask);
100
101 if ((vAddr & vpn_lo_mask) == 0)
102 {
103 lo = entry->lo0;
104 }
105 else
106 {
107 lo = entry->lo1;
108 }
109
110 /* Warn upon attempted use of scratchpad RAM */
111 if(entry->lo0 & TLB_LO_S_MASK)
112 {
113 sim_io_printf(SD,
114 "Warning: no scratchpad RAM: virtual 0x%08x maps to physical 0x%08x.\n",
115 vAddr, (vAddr & offset_mask));
116
117 /* act as if this is a valid, read/write page. */
118 lo = TLB_LO_V_MASK | TLB_LO_D_MASK;
119
120 /* alternately, act as if this TLB entry is not a match */
121 /* return 0; */
122 }
123
124 if ((lo & TLB_LO_V_MASK) == 0)
125 {
126 COP0_BADVADDR = vAddr;
127 COP0_CONTEXT_set_BADVPN2((vAddr & 0xffffe) >> 19); /* Top 19 bits */
128 COP0_ENTRYHI = (vAddr & 0xffffe) | asid;
129 COP0_RANDOM = rand()%(TLB_SIZE - COP0_WIRED) + COP0_WIRED;
130 if (LorS == isLOAD)
131 SignalExceptionTLBInvalidLoad ();
132 else
133 SignalExceptionTLBInvalidStore ();
134 ASSERT(0); /* Signal should never return. */
135 }
136
137 if ((lo & TLB_LO_D_MASK) == 0 && (LorS == isSTORE))
138 {
139 COP0_BADVADDR = vAddr;
140 COP0_CONTEXT_set_BADVPN2((vAddr & 0xffffe) >> 19); /* Top 19 bits */
141 COP0_ENTRYHI = (vAddr & 0xffffe) | asid;
142 COP0_RANDOM = rand()%(TLB_SIZE - COP0_WIRED) + COP0_WIRED;
143 SignalExceptionTLBModification ();
144 ASSERT(0); /* Signal should never return. */
145 }
146
147 /* Ignore lo.C rule for Cache access */
148
149 *pAddr = (((lo & 0x03ffffc0) << 6) & (~offset_mask)) + (vAddr & offset_mask);
150 *CCA = Uncached; /* FOR NOW, no CCA support. */
151
152 last_hit = entry; /* Remember last hit. */
153
154 return 1; /* Match */
155 }
156
157 return 0; /* No Match */
158}
159
160static void
161dump_tlb(SIM_DESC SD, sim_cpu *CPU, address_word cia) {
162
163 int i;
164 /* Now linear search for a match. */
165
166 for (i = 0; i < TLB_SIZE; i++)
167 {
168 sim_io_eprintf(SD, "%2d: %08x %08x %08x %08x\n", i, TLB[i].mask, TLB[i].hi,
169 TLB[i].lo0, TLB[i].lo1);
170 }
171}
172
173
174INLINE_SIM_MAIN (void)
175tlb_lookup (SIM_DESC SD, sim_cpu * CPU, address_word cia, unsigned32 vAddr, address_word * pAddr, int *CCA, int LorS)
176{
177 r4000_tlb_entry_t *p;
178 unsigned32 asid;
179 int rc;
180
181 asid = COP0_ENTRYHI & 0x000000ff;
182
183 /* Test last hit first. More code, but probably faster on average. */
184 if (last_hit)
185 {
186 if (tlb_try_match (SD, CPU, cia, last_hit, asid, vAddr, pAddr, CCA, LorS))
187 return;
188 }
189
190 /* Now linear search for a match. */
191 for (p = &TLB[0]; p < &TLB[TLB_SIZE]; p++)
192 {
193 if (tlb_try_match (SD, CPU, cia, p, asid, vAddr, pAddr, CCA, LorS))
194 return;
195 }
196
197 /* No match, raise a TLB refill exception. */
198 COP0_BADVADDR = vAddr;
199 COP0_CONTEXT_set_BADVPN2((vAddr & 0xffffe) >> 19); /* Top 19 bits */
200 COP0_ENTRYHI = (vAddr & 0xffffe) | asid;
201 COP0_RANDOM = rand()%(TLB_SIZE - COP0_WIRED) + COP0_WIRED;
202
203#if 0
204sim_io_eprintf(SD, "TLB Refill exception at address 0x%0x\n", vAddr);
205dump_tlb(SD, CPU, cia);
206#endif
207
208 if (LorS == isLOAD)
209 SignalExceptionTLBRefillLoad ();
210 else
211 SignalExceptionTLBRefillStore ();
212 ASSERT(0); /* Signal should never return. */
213}
214
215
216INLINE_SIM_MAIN (int)
217address_translation (SIM_DESC SD,
218 sim_cpu * CPU,
219 address_word cia,
220 address_word vAddr,
221 int IorD,
222 int LorS,
223 address_word * pAddr,
224 int *CCA,
225 int raw)
226{
227 unsigned32 operating_mode;
228 unsigned32 asid, vpn, offset, offset_bits;
229
230#ifdef DEBUG
231 sim_io_printf (sd, "AddressTranslation(0x%s,%s,%s,...);\n", pr_addr (vAddr), (IorD ? "isDATA" : "isINSTRUCTION"), (LorS ? "iSTORE" : "isLOAD"));
232#endif
233
234 vAddr &= 0xFFFFFFFF;
235
236 /* Determine operating mode. */
237 operating_mode = SR_KSU;
238 if (SR & status_ERL || SR & status_EXL)
239 operating_mode = ksu_kernel;
240
241 switch (operating_mode)
242 {
243 case ksu_unknown:
244 sim_io_eprintf (SD, "Invalid operating mode SR.KSU == 0x3. Treated as 0x0.\n");
245 operating_mode = ksu_kernel;
246 /* Fall-through */
247 case ksu_kernel:
248 /* Map and return for kseg0 and kseg1. */
249 if ((vAddr & 0xc0000000) == 0x80000000)
250 {
251 ASSERT (0x80000000 <= vAddr && vAddr < 0xc0000000);
252 if (vAddr < 0xa0000000)
253 {
254 /* kseg0: Unmapped, Cached */
255 *pAddr = vAddr - 0x80000000;
256 *CCA = Uncached; /* For now, until cache model is supported. */
257 return -1;
258 }
259 else
260 {
261 /* kseg1: Unmapped, Uncached */
262 *pAddr = vAddr - 0xa0000000;
263 *CCA = Uncached;
264 return -1;
265 }
266 }
267 break;
268
269 case ksu_supervisor:
270 {
271 /* Address error for 0x80000000->0xbfffffff and 0xe00000000->0xffffffff. */
272 unsigned32 top_three = vAddr & 0xe0000000;
273 if (top_three != 0x00000000 && top_three != 0xc0000000)
274 {
275 if (LorS == isLOAD)
276 SignalExceptionAddressLoad ();
277 else
278 SignalExceptionAddressStore ();
279 ASSERT(0); /* Signal should never return. */
280 }
281 }
282 break;
283
284 case ksu_user:
285 {
286 if (vAddr & 0x80000000)
287 {
288 if (LorS == isLOAD)
289 SignalExceptionAddressLoad ();
290 else
291 SignalExceptionAddressStore ();
292 ASSERT(0); /* Signal should never return. */
293 }
294 }
295 break;
296
297 default:
298 ASSERT(0);
299 }
300
301 /* OK. If we got this far, we're ready to use the normal virtual->physical memory mapping. */
302 tlb_lookup (SD, CPU, cia, vAddr, pAddr, CCA, LorS);
303
304 /* If the preceding call returns, a match was found, and CCA and pAddr have been set. */
305 return -1;
306}
307
308#else /* TARGET_SKY */
309/* end-sanitize-sky */
310
311/* Description from page A-22 of the "MIPS IV Instruction Set" manual
312 (revision 3.1) */
313/* Translate a virtual address to a physical address and cache
314 coherence algorithm describing the mechanism used to resolve the
315 memory reference. Given the virtual address vAddr, and whether the
316 reference is to Instructions ot Data (IorD), find the corresponding
317 physical address (pAddr) and the cache coherence algorithm (CCA)
318 used to resolve the reference. If the virtual address is in one of
319 the unmapped address spaces the physical address and the CCA are
320 determined directly by the virtual address. If the virtual address
321 is in one of the mapped address spaces then the TLB is used to
322 determine the physical address and access type; if the required
323 translation is not present in the TLB or the desired access is not
324 permitted the function fails and an exception is taken.
325
326 NOTE: Normally (RAW == 0), when address translation fails, this
327 function raises an exception and does not return. */
328
329INLINE_SIM_MAIN
330(int)
64ed8b6a 331address_translation (SIM_DESC sd,
fd6e6422 332 sim_cpu * cpu,
64ed8b6a
AC
333 address_word cia,
334 address_word vAddr,
335 int IorD,
336 int LorS,
fd6e6422 337 address_word * pAddr,
64ed8b6a
AC
338 int *CCA,
339 int raw)
340{
fd6e6422 341 int res = -1; /* TRUE : Assume good return */
64ed8b6a
AC
342
343#ifdef DEBUG
fd6e6422 344 sim_io_printf (sd, "AddressTranslation(0x%s,%s,%s,...);\n", pr_addr (vAddr), (IorD ? "isDATA" : "isINSTRUCTION"), (LorS ? "iSTORE" : "isLOAD"));
64ed8b6a
AC
345#endif
346
347 /* Check that the address is valid for this memory model */
348
349 /* For a simple (flat) memory model, we simply pass virtual
350 addressess through (mostly) unchanged. */
351 vAddr &= 0xFFFFFFFF;
352
fd6e6422
FCE
353 *pAddr = vAddr; /* default for isTARGET */
354 *CCA = Uncached; /* not used for isHOST */
355
356 return (res);
357}
8e3a0b59
IC
358
359/* start-sanitize-sky */
fd6e6422 360#endif /* !TARGET_SKY */
8e3a0b59
IC
361/* end-sanitize-sky */
362
64ed8b6a
AC
363
364/* Description from page A-23 of the "MIPS IV Instruction Set" manual
365 (revision 3.1) */
366/* Prefetch data from memory. Prefetch is an advisory instruction for
367 which an implementation specific action is taken. The action taken
368 may increase performance, but must not change the meaning of the
369 program, or alter architecturally-visible state. */
370
371INLINE_SIM_MAIN (void)
372prefetch (SIM_DESC sd,
373 sim_cpu *cpu,
374 address_word cia,
375 int CCA,
376 address_word pAddr,
377 address_word vAddr,
378 int DATA,
379 int hint)
380{
381#ifdef DEBUG
382 sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint);
383#endif /* DEBUG */
384
385 /* For our simple memory model we do nothing */
386 return;
387}
388
389/* Description from page A-22 of the "MIPS IV Instruction Set" manual
390 (revision 3.1) */
391/* Load a value from memory. Use the cache and main memory as
392 specified in the Cache Coherence Algorithm (CCA) and the sort of
393 access (IorD) to find the contents of AccessLength memory bytes
394 starting at physical location pAddr. The data is returned in the
395 fixed width naturally-aligned memory element (MemElem). The
396 low-order two (or three) bits of the address and the AccessLength
397 indicate which of the bytes within MemElem needs to be given to the
398 processor. If the memory access type of the reference is uncached
399 then only the referenced bytes are read from memory and valid
400 within the memory element. If the access type is cached, and the
401 data is not present in cache, an implementation specific size and
402 alignment block of memory is read and loaded into the cache to
403 satisfy a load reference. At a minimum, the block is the entire
404 memory element. */
405INLINE_SIM_MAIN (void)
406load_memory (SIM_DESC SD,
407 sim_cpu *CPU,
408 address_word cia,
409 uword64* memvalp,
410 uword64* memval1p,
411 int CCA,
412 unsigned int AccessLength,
413 address_word pAddr,
414 address_word vAddr,
415 int IorD)
416{
417 uword64 value = 0;
418 uword64 value1 = 0;
419
420#ifdef DEBUG
421 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"));
422#endif /* DEBUG */
423
424#if defined(WARN_MEM)
425 if (CCA != uncached)
426 sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
427#endif /* WARN_MEM */
428
8e3a0b59
IC
429#if !(WITH_IGEN)
430 /* IGEN performs this test in ifetch16() / ifetch32() */
64ed8b6a
AC
431 /* If instruction fetch then we need to check that the two lo-order
432 bits are zero, otherwise raise a InstructionFetch exception: */
433 if ((IorD == isINSTRUCTION)
434 && ((pAddr & 0x3) != 0)
435 && (((pAddr & 0x1) != 0) || ((vAddr & 0x1) == 0)))
436 SignalExceptionInstructionFetch ();
8e3a0b59 437#endif
64ed8b6a
AC
438
439 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
440 {
441 /* In reality this should be a Bus Error */
442 sim_io_error (SD, "LOAD AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
443 AccessLength,
444 (LOADDRMASK + 1) << 3,
445 pr_addr (pAddr));
446 }
447
448#if defined(TRACE)
449 dotrace (SD, CPU, tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
450#endif /* TRACE */
451
452 /* Read the specified number of bytes from memory. Adjust for
453 host/target byte ordering/ Align the least significant byte
454 read. */
455
456 switch (AccessLength)
457 {
458 case AccessLength_QUADWORD :
459 {
460 unsigned_16 val = sim_core_read_aligned_16 (CPU, NULL_CIA, read_map, pAddr);
461 value1 = VH8_16 (val);
462 value = VL8_16 (val);
463 break;
464 }
465 case AccessLength_DOUBLEWORD :
466 value = sim_core_read_aligned_8 (CPU, NULL_CIA,
467 read_map, pAddr);
468 break;
469 case AccessLength_SEPTIBYTE :
470 value = sim_core_read_misaligned_7 (CPU, NULL_CIA,
471 read_map, pAddr);
472 break;
473 case AccessLength_SEXTIBYTE :
474 value = sim_core_read_misaligned_6 (CPU, NULL_CIA,
475 read_map, pAddr);
476 break;
477 case AccessLength_QUINTIBYTE :
478 value = sim_core_read_misaligned_5 (CPU, NULL_CIA,
479 read_map, pAddr);
480 break;
481 case AccessLength_WORD :
482 value = sim_core_read_aligned_4 (CPU, NULL_CIA,
483 read_map, pAddr);
484 break;
485 case AccessLength_TRIPLEBYTE :
486 value = sim_core_read_misaligned_3 (CPU, NULL_CIA,
487 read_map, pAddr);
488 break;
489 case AccessLength_HALFWORD :
490 value = sim_core_read_aligned_2 (CPU, NULL_CIA,
491 read_map, pAddr);
492 break;
493 case AccessLength_BYTE :
494 value = sim_core_read_aligned_1 (CPU, NULL_CIA,
495 read_map, pAddr);
496 break;
497 default:
498 abort ();
499 }
500
501#ifdef DEBUG
502 printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
503 (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
504#endif /* DEBUG */
505
506 /* See also store_memory. Position data in correct byte lanes. */
507 if (AccessLength <= LOADDRMASK)
508 {
509 if (BigEndianMem)
510 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
511 shifted to the most significant byte position. */
512 value <<= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
513 else
514 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
515 is already in the correct postition. */
516 value <<= ((pAddr & LOADDRMASK) * 8);
517 }
518
519#ifdef DEBUG
520 printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
521 pr_uword64(value1),pr_uword64(value));
522#endif /* DEBUG */
523
524 *memvalp = value;
525 if (memval1p) *memval1p = value1;
526}
527
528
529/* Description from page A-23 of the "MIPS IV Instruction Set" manual
530 (revision 3.1) */
531/* Store a value to memory. The specified data is stored into the
532 physical location pAddr using the memory hierarchy (data caches and
533 main memory) as specified by the Cache Coherence Algorithm
534 (CCA). The MemElem contains the data for an aligned, fixed-width
535 memory element (word for 32-bit processors, doubleword for 64-bit
536 processors), though only the bytes that will actually be stored to
537 memory need to be valid. The low-order two (or three) bits of pAddr
538 and the AccessLength field indicates which of the bytes within the
539 MemElem data should actually be stored; only these bytes in memory
540 will be changed. */
541
542INLINE_SIM_MAIN (void)
543store_memory (SIM_DESC SD,
544 sim_cpu *CPU,
545 address_word cia,
546 int CCA,
547 unsigned int AccessLength,
548 uword64 MemElem,
549 uword64 MemElem1, /* High order 64 bits */
550 address_word pAddr,
551 address_word vAddr)
552{
553#ifdef DEBUG
554 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));
555#endif /* DEBUG */
556
557#if defined(WARN_MEM)
558 if (CCA != uncached)
559 sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
560#endif /* WARN_MEM */
561
562 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
563 sim_io_error (SD, "STORE AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
564 AccessLength,
565 (LOADDRMASK + 1) << 3,
566 pr_addr(pAddr));
567
568#if defined(TRACE)
569 dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
570#endif /* TRACE */
571
572#ifdef DEBUG
573 printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
574#endif /* DEBUG */
575
576 /* See also load_memory. Position data in correct byte lanes. */
577 if (AccessLength <= LOADDRMASK)
578 {
579 if (BigEndianMem)
580 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
581 shifted to the most significant byte position. */
582 MemElem >>= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
583 else
584 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
585 is already in the correct postition. */
586 MemElem >>= ((pAddr & LOADDRMASK) * 8);
587 }
588
589#ifdef DEBUG
590 printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
591#endif /* DEBUG */
592
593 switch (AccessLength)
594 {
595 case AccessLength_QUADWORD :
596 {
597 unsigned_16 val = U16_8 (MemElem1, MemElem);
598 sim_core_write_aligned_16 (CPU, NULL_CIA, write_map, pAddr, val);
599 break;
600 }
601 case AccessLength_DOUBLEWORD :
602 sim_core_write_aligned_8 (CPU, NULL_CIA,
603 write_map, pAddr, MemElem);
604 break;
605 case AccessLength_SEPTIBYTE :
606 sim_core_write_misaligned_7 (CPU, NULL_CIA,
607 write_map, pAddr, MemElem);
608 break;
609 case AccessLength_SEXTIBYTE :
610 sim_core_write_misaligned_6 (CPU, NULL_CIA,
611 write_map, pAddr, MemElem);
612 break;
613 case AccessLength_QUINTIBYTE :
614 sim_core_write_misaligned_5 (CPU, NULL_CIA,
615 write_map, pAddr, MemElem);
616 break;
617 case AccessLength_WORD :
618 sim_core_write_aligned_4 (CPU, NULL_CIA,
619 write_map, pAddr, MemElem);
620 break;
621 case AccessLength_TRIPLEBYTE :
622 sim_core_write_misaligned_3 (CPU, NULL_CIA,
623 write_map, pAddr, MemElem);
624 break;
625 case AccessLength_HALFWORD :
626 sim_core_write_aligned_2 (CPU, NULL_CIA,
627 write_map, pAddr, MemElem);
628 break;
629 case AccessLength_BYTE :
630 sim_core_write_aligned_1 (CPU, NULL_CIA,
631 write_map, pAddr, MemElem);
632 break;
633 default:
634 abort ();
635 }
636
637 return;
638}
639
640
641INLINE_SIM_MAIN (unsigned32)
642ifetch32 (SIM_DESC SD,
643 sim_cpu *CPU,
644 address_word cia,
645 address_word vaddr)
646{
647 /* Copy the action of the LW instruction */
8e3a0b59
IC
648 address_word mask = LOADDRMASK;
649 address_word access = AccessLength_WORD;
650 address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
651 address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
652 unsigned int byte;
653 address_word paddr;
654 int uncached;
655 unsigned64 memval;
656
657 if ((vaddr & access) != 0)
658 SignalExceptionInstructionFetch ();
659 AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
660 paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
661 LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
662 byte = ((vaddr & mask) ^ bigendiancpu);
663 return (memval >> (8 * byte));
664}
665
666
667INLINE_SIM_MAIN (unsigned16)
668ifetch16 (SIM_DESC SD,
669 sim_cpu *CPU,
670 address_word cia,
671 address_word vaddr)
672{
673 /* Copy the action of the LH instruction */
674 address_word mask = LOADDRMASK;
675 address_word access = AccessLength_HALFWORD;
676 address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
677 address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
678 unsigned int byte;
64ed8b6a 679 address_word paddr;
8e3a0b59
IC
680 int uncached;
681 unsigned64 memval;
682
683 if ((vaddr & access) != 0)
684 SignalExceptionInstructionFetch ();
685 AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
686 paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
687 LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
688 byte = ((vaddr & mask) ^ bigendiancpu);
689 return (memval >> (8 * byte));
64ed8b6a
AC
690}
691
692
8e3a0b59 693
64ed8b6a
AC
694/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
695/* Order loads and stores to synchronise shared memory. Perform the
696 action necessary to make the effects of groups of synchronizable
697 loads and stores indicated by stype occur in the same order for all
698 processors. */
699INLINE_SIM_MAIN (void)
700sync_operation (SIM_DESC sd,
701 sim_cpu *cpu,
702 address_word cia,
703 int stype)
704{
705#ifdef DEBUG
706 sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
707#endif /* DEBUG */
708 return;
709}
710
711INLINE_SIM_MAIN (void)
712cache_op (SIM_DESC SD,
713 sim_cpu *CPU,
714 address_word cia,
715 int op,
716 address_word pAddr,
717 address_word vAddr,
718 unsigned int instruction)
719{
720#if 1 /* stop warning message being displayed (we should really just remove the code) */
721 static int icache_warning = 1;
722 static int dcache_warning = 1;
723#else
724 static int icache_warning = 0;
725 static int dcache_warning = 0;
726#endif
727
728 /* If CP0 is not useable (User or Supervisor mode) and the CP0
729 enable bit in the Status Register is clear - a coprocessor
730 unusable exception is taken. */
731#if 0
732 sim_io_printf(SD,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia));
733#endif
734
735 switch (op & 0x3) {
736 case 0: /* instruction cache */
737 switch (op >> 2) {
738 case 0: /* Index Invalidate */
739 case 1: /* Index Load Tag */
740 case 2: /* Index Store Tag */
741 case 4: /* Hit Invalidate */
742 case 5: /* Fill */
743 case 6: /* Hit Writeback */
744 if (!icache_warning)
745 {
746 sim_io_eprintf(SD,"Instruction CACHE operation %d to be coded\n",(op >> 2));
747 icache_warning = 1;
748 }
749 break;
750
751 default:
752 SignalException(ReservedInstruction,instruction);
753 break;
754 }
755 break;
756
757 case 1: /* data cache */
758 switch (op >> 2) {
759 case 0: /* Index Writeback Invalidate */
760 case 1: /* Index Load Tag */
761 case 2: /* Index Store Tag */
762 case 3: /* Create Dirty */
763 case 4: /* Hit Invalidate */
764 case 5: /* Hit Writeback Invalidate */
765 case 6: /* Hit Writeback */
766 if (!dcache_warning)
767 {
768 sim_io_eprintf(SD,"Data CACHE operation %d to be coded\n",(op >> 2));
769 dcache_warning = 1;
770 }
771 break;
772
773 default:
774 SignalException(ReservedInstruction,instruction);
775 break;
776 }
777 break;
778
779 default: /* unrecognised cache ID */
780 SignalException(ReservedInstruction,instruction);
781 break;
782 }
783
784 return;
785}
786
787
788INLINE_SIM_MAIN (void)
789pending_tick (SIM_DESC SD,
790 sim_cpu *CPU,
791 address_word cia)
792{
793 if (PENDING_TRACE)
d1cbd70a 794 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);
64ed8b6a
AC
795 if (PENDING_OUT != PENDING_IN)
796 {
797 int loop;
798 int index = PENDING_OUT;
799 int total = PENDING_TOTAL;
800 if (PENDING_TOTAL == 0)
801 sim_engine_abort (SD, CPU, cia, "PENDING_DRAIN - Mis-match on pending update pointers\n");
d1cbd70a
AC
802 for (loop = 0, index = PENDING_OUT;
803 (loop < total);
804 loop++, index = (index + 1) % PSLOTS)
64ed8b6a
AC
805 {
806 if (PENDING_SLOT_DEST[index] != NULL)
807 {
808 PENDING_SLOT_DELAY[index] -= 1;
809 if (PENDING_SLOT_DELAY[index] == 0)
810 {
d1cbd70a
AC
811 if (PENDING_TRACE)
812 sim_io_eprintf (SD, "PENDING_DRAIN - drained - index %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
813 index,
814 (unsigned long) PENDING_SLOT_DEST[index],
815 PENDING_SLOT_BIT[index],
816 (unsigned long) PENDING_SLOT_VALUE[index],
817 PENDING_SLOT_SIZE[index]);
64ed8b6a
AC
818 if (PENDING_SLOT_BIT[index] >= 0)
819 switch (PENDING_SLOT_SIZE[index])
820 {
d1cbd70a 821 case 4:
64ed8b6a
AC
822 if (PENDING_SLOT_VALUE[index])
823 *(unsigned32*)PENDING_SLOT_DEST[index] |=
824 BIT32 (PENDING_SLOT_BIT[index]);
825 else
826 *(unsigned32*)PENDING_SLOT_DEST[index] &=
827 BIT32 (PENDING_SLOT_BIT[index]);
828 break;
d1cbd70a 829 case 8:
64ed8b6a
AC
830 if (PENDING_SLOT_VALUE[index])
831 *(unsigned64*)PENDING_SLOT_DEST[index] |=
832 BIT64 (PENDING_SLOT_BIT[index]);
833 else
834 *(unsigned64*)PENDING_SLOT_DEST[index] &=
835 BIT64 (PENDING_SLOT_BIT[index]);
836 break;
64ed8b6a
AC
837 }
838 else
839 switch (PENDING_SLOT_SIZE[index])
840 {
d1cbd70a 841 case 4:
64ed8b6a
AC
842 *(unsigned32*)PENDING_SLOT_DEST[index] =
843 PENDING_SLOT_VALUE[index];
844 break;
d1cbd70a 845 case 8:
64ed8b6a
AC
846 *(unsigned64*)PENDING_SLOT_DEST[index] =
847 PENDING_SLOT_VALUE[index];
848 break;
849 }
d1cbd70a
AC
850 if (PENDING_OUT == index)
851 {
852 PENDING_SLOT_DEST[index] = NULL;
853 PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;
854 PENDING_TOTAL--;
855 }
64ed8b6a 856 }
d1cbd70a
AC
857 else if (PENDING_TRACE && PENDING_SLOT_DELAY[index] > 0)
858 sim_io_eprintf (SD, "PENDING_DRAIN - queued - index %d, delay %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
859 index, PENDING_SLOT_DELAY[index],
860 (unsigned long) PENDING_SLOT_DEST[index],
861 PENDING_SLOT_BIT[index],
862 (unsigned long) PENDING_SLOT_VALUE[index],
863 PENDING_SLOT_SIZE[index]);
864
64ed8b6a
AC
865 }
866 }
64ed8b6a
AC
867 }
868}
869
870
871#endif
This page took 0.082866 seconds and 4 git commands to generate.