This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / sim / mips / sim-main.c
1 /* Copyright (C) 1998, Cygnus Solutions
2
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.
7
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.
12
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.
16
17 */
18
19
20 #ifndef SIM_MAIN_C
21 #define SIM_MAIN_C
22
23 #include "sim-main.h"
24 #include "sim-assert.h"
25
26
27 /*---------------------------------------------------------------------------*/
28 /*-- simulator engine -------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*/
30
31
32 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
33 (revision 3.1) */
34 /* Translate a virtual address to a physical address and cache
35 coherence algorithm describing the mechanism used to resolve the
36 memory reference. Given the virtual address vAddr, and whether the
37 reference is to Instructions ot Data (IorD), find the corresponding
38 physical address (pAddr) and the cache coherence algorithm (CCA)
39 used to resolve the reference. If the virtual address is in one of
40 the unmapped address spaces the physical address and the CCA are
41 determined directly by the virtual address. If the virtual address
42 is in one of the mapped address spaces then the TLB is used to
43 determine the physical address and access type; if the required
44 translation is not present in the TLB or the desired access is not
45 permitted the function fails and an exception is taken.
46
47 NOTE: Normally (RAW == 0), when address translation fails, this
48 function raises an exception and does not return. */
49
50 INLINE_SIM_MAIN
51 (int)
52 address_translation (SIM_DESC sd,
53 sim_cpu * cpu,
54 address_word cia,
55 address_word vAddr,
56 int IorD,
57 int LorS,
58 address_word * pAddr,
59 int *CCA,
60 int raw)
61 {
62 int res = -1; /* TRUE : Assume good return */
63
64 #ifdef DEBUG
65 sim_io_printf (sd, "AddressTranslation(0x%s,%s,%s,...);\n", pr_addr (vAddr), (IorD ? "isDATA" : "isINSTRUCTION"), (LorS ? "iSTORE" : "isLOAD"));
66 #endif
67
68 /* Check that the address is valid for this memory model */
69
70 /* For a simple (flat) memory model, we simply pass virtual
71 addressess through (mostly) unchanged. */
72 vAddr &= 0xFFFFFFFF;
73
74 *pAddr = vAddr; /* default for isTARGET */
75 *CCA = Uncached; /* not used for isHOST */
76
77 return (res);
78 }
79
80
81
82 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
83 (revision 3.1) */
84 /* Prefetch data from memory. Prefetch is an advisory instruction for
85 which an implementation specific action is taken. The action taken
86 may increase performance, but must not change the meaning of the
87 program, or alter architecturally-visible state. */
88
89 INLINE_SIM_MAIN (void)
90 prefetch (SIM_DESC sd,
91 sim_cpu *cpu,
92 address_word cia,
93 int CCA,
94 address_word pAddr,
95 address_word vAddr,
96 int DATA,
97 int hint)
98 {
99 #ifdef DEBUG
100 sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint);
101 #endif /* DEBUG */
102
103 /* For our simple memory model we do nothing */
104 return;
105 }
106
107 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
108 (revision 3.1) */
109 /* Load a value from memory. Use the cache and main memory as
110 specified in the Cache Coherence Algorithm (CCA) and the sort of
111 access (IorD) to find the contents of AccessLength memory bytes
112 starting at physical location pAddr. The data is returned in the
113 fixed width naturally-aligned memory element (MemElem). The
114 low-order two (or three) bits of the address and the AccessLength
115 indicate which of the bytes within MemElem needs to be given to the
116 processor. If the memory access type of the reference is uncached
117 then only the referenced bytes are read from memory and valid
118 within the memory element. If the access type is cached, and the
119 data is not present in cache, an implementation specific size and
120 alignment block of memory is read and loaded into the cache to
121 satisfy a load reference. At a minimum, the block is the entire
122 memory element. */
123 INLINE_SIM_MAIN (void)
124 load_memory (SIM_DESC SD,
125 sim_cpu *CPU,
126 address_word cia,
127 uword64* memvalp,
128 uword64* memval1p,
129 int CCA,
130 unsigned int AccessLength,
131 address_word pAddr,
132 address_word vAddr,
133 int IorD)
134 {
135 uword64 value = 0;
136 uword64 value1 = 0;
137
138 #ifdef DEBUG
139 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"));
140 #endif /* DEBUG */
141
142 #if defined(WARN_MEM)
143 if (CCA != uncached)
144 sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
145 #endif /* WARN_MEM */
146
147 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
148 {
149 /* In reality this should be a Bus Error */
150 sim_io_error (SD, "LOAD AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
151 AccessLength,
152 (LOADDRMASK + 1) << 3,
153 pr_addr (pAddr));
154 }
155
156 #if defined(TRACE)
157 dotrace (SD, CPU, tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
158 #endif /* TRACE */
159
160 /* Read the specified number of bytes from memory. Adjust for
161 host/target byte ordering/ Align the least significant byte
162 read. */
163
164 switch (AccessLength)
165 {
166 case AccessLength_QUADWORD:
167 {
168 unsigned_16 val = sim_core_read_aligned_16 (CPU, cia, read_map, pAddr);
169 value1 = VH8_16 (val);
170 value = VL8_16 (val);
171 break;
172 }
173 case AccessLength_DOUBLEWORD:
174 value = sim_core_read_aligned_8 (CPU, cia, read_map, pAddr);
175 break;
176 case AccessLength_SEPTIBYTE:
177 value = sim_core_read_misaligned_7 (CPU, cia, read_map, pAddr);
178 break;
179 case AccessLength_SEXTIBYTE:
180 value = sim_core_read_misaligned_6 (CPU, cia, read_map, pAddr);
181 break;
182 case AccessLength_QUINTIBYTE:
183 value = sim_core_read_misaligned_5 (CPU, cia, read_map, pAddr);
184 break;
185 case AccessLength_WORD:
186 value = sim_core_read_aligned_4 (CPU, cia, read_map, pAddr);
187 break;
188 case AccessLength_TRIPLEBYTE:
189 value = sim_core_read_misaligned_3 (CPU, cia, read_map, pAddr);
190 break;
191 case AccessLength_HALFWORD:
192 value = sim_core_read_aligned_2 (CPU, cia, read_map, pAddr);
193 break;
194 case AccessLength_BYTE:
195 value = sim_core_read_aligned_1 (CPU, cia, read_map, pAddr);
196 break;
197 default:
198 abort ();
199 }
200
201 #ifdef DEBUG
202 printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
203 (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
204 #endif /* DEBUG */
205
206 /* See also store_memory. Position data in correct byte lanes. */
207 if (AccessLength <= LOADDRMASK)
208 {
209 if (BigEndianMem)
210 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
211 shifted to the most significant byte position. */
212 value <<= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
213 else
214 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
215 is already in the correct postition. */
216 value <<= ((pAddr & LOADDRMASK) * 8);
217 }
218
219 #ifdef DEBUG
220 printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
221 pr_uword64(value1),pr_uword64(value));
222 #endif /* DEBUG */
223
224 *memvalp = value;
225 if (memval1p) *memval1p = value1;
226 }
227
228
229 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
230 (revision 3.1) */
231 /* Store a value to memory. The specified data is stored into the
232 physical location pAddr using the memory hierarchy (data caches and
233 main memory) as specified by the Cache Coherence Algorithm
234 (CCA). The MemElem contains the data for an aligned, fixed-width
235 memory element (word for 32-bit processors, doubleword for 64-bit
236 processors), though only the bytes that will actually be stored to
237 memory need to be valid. The low-order two (or three) bits of pAddr
238 and the AccessLength field indicates which of the bytes within the
239 MemElem data should actually be stored; only these bytes in memory
240 will be changed. */
241
242 INLINE_SIM_MAIN (void)
243 store_memory (SIM_DESC SD,
244 sim_cpu *CPU,
245 address_word cia,
246 int CCA,
247 unsigned int AccessLength,
248 uword64 MemElem,
249 uword64 MemElem1, /* High order 64 bits */
250 address_word pAddr,
251 address_word vAddr)
252 {
253 #ifdef DEBUG
254 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));
255 #endif /* DEBUG */
256
257 #if defined(WARN_MEM)
258 if (CCA != uncached)
259 sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
260 #endif /* WARN_MEM */
261
262 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
263 sim_io_error (SD, "STORE AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
264 AccessLength,
265 (LOADDRMASK + 1) << 3,
266 pr_addr(pAddr));
267
268 #if defined(TRACE)
269 dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
270 #endif /* TRACE */
271
272 #ifdef DEBUG
273 printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
274 #endif /* DEBUG */
275
276 /* See also load_memory. Position data in correct byte lanes. */
277 if (AccessLength <= LOADDRMASK)
278 {
279 if (BigEndianMem)
280 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
281 shifted to the most significant byte position. */
282 MemElem >>= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
283 else
284 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
285 is already in the correct postition. */
286 MemElem >>= ((pAddr & LOADDRMASK) * 8);
287 }
288
289 #ifdef DEBUG
290 printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
291 #endif /* DEBUG */
292
293 switch (AccessLength)
294 {
295 case AccessLength_QUADWORD:
296 {
297 unsigned_16 val = U16_8 (MemElem1, MemElem);
298 sim_core_write_aligned_16 (CPU, cia, write_map, pAddr, val);
299 break;
300 }
301 case AccessLength_DOUBLEWORD:
302 sim_core_write_aligned_8 (CPU, cia, write_map, pAddr, MemElem);
303 break;
304 case AccessLength_SEPTIBYTE:
305 sim_core_write_misaligned_7 (CPU, cia, write_map, pAddr, MemElem);
306 break;
307 case AccessLength_SEXTIBYTE:
308 sim_core_write_misaligned_6 (CPU, cia, write_map, pAddr, MemElem);
309 break;
310 case AccessLength_QUINTIBYTE:
311 sim_core_write_misaligned_5 (CPU, cia, write_map, pAddr, MemElem);
312 break;
313 case AccessLength_WORD:
314 sim_core_write_aligned_4 (CPU, cia, write_map, pAddr, MemElem);
315 break;
316 case AccessLength_TRIPLEBYTE:
317 sim_core_write_misaligned_3 (CPU, cia, write_map, pAddr, MemElem);
318 break;
319 case AccessLength_HALFWORD:
320 sim_core_write_aligned_2 (CPU, cia, write_map, pAddr, MemElem);
321 break;
322 case AccessLength_BYTE:
323 sim_core_write_aligned_1 (CPU, cia, write_map, pAddr, MemElem);
324 break;
325 default:
326 abort ();
327 }
328
329 return;
330 }
331
332
333 INLINE_SIM_MAIN (unsigned32)
334 ifetch32 (SIM_DESC SD,
335 sim_cpu *CPU,
336 address_word cia,
337 address_word vaddr)
338 {
339 /* Copy the action of the LW instruction */
340 address_word mask = LOADDRMASK;
341 address_word access = AccessLength_WORD;
342 address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
343 address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
344 unsigned int byte;
345 address_word paddr;
346 int uncached;
347 unsigned64 memval;
348
349 if ((vaddr & access) != 0)
350 SignalExceptionInstructionFetch ();
351 AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
352 paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
353 LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
354 byte = ((vaddr & mask) ^ bigendiancpu);
355 return (memval >> (8 * byte));
356 }
357
358
359 INLINE_SIM_MAIN (unsigned16)
360 ifetch16 (SIM_DESC SD,
361 sim_cpu *CPU,
362 address_word cia,
363 address_word vaddr)
364 {
365 /* Copy the action of the LH instruction */
366 address_word mask = LOADDRMASK;
367 address_word access = AccessLength_HALFWORD;
368 address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
369 address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
370 unsigned int byte;
371 address_word paddr;
372 int uncached;
373 unsigned64 memval;
374
375 if ((vaddr & access) != 0)
376 SignalExceptionInstructionFetch ();
377 AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
378 paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
379 LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
380 byte = ((vaddr & mask) ^ bigendiancpu);
381 return (memval >> (8 * byte));
382 }
383
384
385
386 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
387 /* Order loads and stores to synchronise shared memory. Perform the
388 action necessary to make the effects of groups of synchronizable
389 loads and stores indicated by stype occur in the same order for all
390 processors. */
391 INLINE_SIM_MAIN (void)
392 sync_operation (SIM_DESC sd,
393 sim_cpu *cpu,
394 address_word cia,
395 int stype)
396 {
397 #ifdef DEBUG
398 sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
399 #endif /* DEBUG */
400 return;
401 }
402
403 INLINE_SIM_MAIN (void)
404 cache_op (SIM_DESC SD,
405 sim_cpu *CPU,
406 address_word cia,
407 int op,
408 address_word pAddr,
409 address_word vAddr,
410 unsigned int instruction)
411 {
412 #if 1 /* stop warning message being displayed (we should really just remove the code) */
413 static int icache_warning = 1;
414 static int dcache_warning = 1;
415 #else
416 static int icache_warning = 0;
417 static int dcache_warning = 0;
418 #endif
419
420 /* If CP0 is not useable (User or Supervisor mode) and the CP0
421 enable bit in the Status Register is clear - a coprocessor
422 unusable exception is taken. */
423 #if 0
424 sim_io_printf(SD,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia));
425 #endif
426
427 switch (op & 0x3) {
428 case 0: /* instruction cache */
429 switch (op >> 2) {
430 case 0: /* Index Invalidate */
431 case 1: /* Index Load Tag */
432 case 2: /* Index Store Tag */
433 case 4: /* Hit Invalidate */
434 case 5: /* Fill */
435 case 6: /* Hit Writeback */
436 if (!icache_warning)
437 {
438 sim_io_eprintf(SD,"Instruction CACHE operation %d to be coded\n",(op >> 2));
439 icache_warning = 1;
440 }
441 break;
442
443 default:
444 SignalException(ReservedInstruction,instruction);
445 break;
446 }
447 break;
448
449 case 1: /* data cache */
450 case 3: /* secondary data cache */
451 switch (op >> 2) {
452 case 0: /* Index Writeback Invalidate */
453 case 1: /* Index Load Tag */
454 case 2: /* Index Store Tag */
455 case 3: /* Create Dirty */
456 case 4: /* Hit Invalidate */
457 case 5: /* Hit Writeback Invalidate */
458 case 6: /* Hit Writeback */
459 if (!dcache_warning)
460 {
461 sim_io_eprintf(SD,"Data CACHE operation %d to be coded\n",(op >> 2));
462 dcache_warning = 1;
463 }
464 break;
465
466 default:
467 SignalException(ReservedInstruction,instruction);
468 break;
469 }
470 break;
471
472 default: /* unrecognised cache ID */
473 SignalException(ReservedInstruction,instruction);
474 break;
475 }
476
477 return;
478 }
479
480
481 INLINE_SIM_MAIN (void)
482 pending_tick (SIM_DESC SD,
483 sim_cpu *CPU,
484 address_word cia)
485 {
486 if (PENDING_TRACE)
487 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);
488 if (PENDING_OUT != PENDING_IN)
489 {
490 int loop;
491 int index = PENDING_OUT;
492 int total = PENDING_TOTAL;
493 if (PENDING_TOTAL == 0)
494 sim_engine_abort (SD, CPU, cia, "PENDING_DRAIN - Mis-match on pending update pointers\n");
495 for (loop = 0, index = PENDING_OUT;
496 (loop < total);
497 loop++, index = (index + 1) % PSLOTS)
498 {
499 if (PENDING_SLOT_DEST[index] != NULL)
500 {
501 PENDING_SLOT_DELAY[index] -= 1;
502 if (PENDING_SLOT_DELAY[index] == 0)
503 {
504 if (PENDING_TRACE)
505 sim_io_eprintf (SD, "PENDING_DRAIN - drained - index %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
506 index,
507 (unsigned long) PENDING_SLOT_DEST[index],
508 PENDING_SLOT_BIT[index],
509 (unsigned long) PENDING_SLOT_VALUE[index],
510 PENDING_SLOT_SIZE[index]);
511 if (PENDING_SLOT_BIT[index] >= 0)
512 switch (PENDING_SLOT_SIZE[index])
513 {
514 case 4:
515 if (PENDING_SLOT_VALUE[index])
516 *(unsigned32*)PENDING_SLOT_DEST[index] |=
517 BIT32 (PENDING_SLOT_BIT[index]);
518 else
519 *(unsigned32*)PENDING_SLOT_DEST[index] &=
520 BIT32 (PENDING_SLOT_BIT[index]);
521 break;
522 case 8:
523 if (PENDING_SLOT_VALUE[index])
524 *(unsigned64*)PENDING_SLOT_DEST[index] |=
525 BIT64 (PENDING_SLOT_BIT[index]);
526 else
527 *(unsigned64*)PENDING_SLOT_DEST[index] &=
528 BIT64 (PENDING_SLOT_BIT[index]);
529 break;
530 }
531 else
532 switch (PENDING_SLOT_SIZE[index])
533 {
534 case 4:
535 *(unsigned32*)PENDING_SLOT_DEST[index] =
536 PENDING_SLOT_VALUE[index];
537 break;
538 case 8:
539 *(unsigned64*)PENDING_SLOT_DEST[index] =
540 PENDING_SLOT_VALUE[index];
541 break;
542 }
543 if (PENDING_OUT == index)
544 {
545 PENDING_SLOT_DEST[index] = NULL;
546 PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;
547 PENDING_TOTAL--;
548 }
549 }
550 else if (PENDING_TRACE && PENDING_SLOT_DELAY[index] > 0)
551 sim_io_eprintf (SD, "PENDING_DRAIN - queued - index %d, delay %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
552 index, PENDING_SLOT_DELAY[index],
553 (unsigned long) PENDING_SLOT_DEST[index],
554 PENDING_SLOT_BIT[index],
555 (unsigned long) PENDING_SLOT_VALUE[index],
556 PENDING_SLOT_SIZE[index]);
557
558 }
559 }
560 }
561 }
562
563
564 #endif
This page took 0.042008 seconds and 5 git commands to generate.