]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/mips/sim-main.c
Only support interworking and pic for ELF or COFF targets
[thirdparty/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, NULL_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, NULL_CIA,
175 read_map, pAddr);
176 break;
177 case AccessLength_SEPTIBYTE :
178 value = sim_core_read_misaligned_7 (CPU, NULL_CIA,
179 read_map, pAddr);
180 break;
181 case AccessLength_SEXTIBYTE :
182 value = sim_core_read_misaligned_6 (CPU, NULL_CIA,
183 read_map, pAddr);
184 break;
185 case AccessLength_QUINTIBYTE :
186 value = sim_core_read_misaligned_5 (CPU, NULL_CIA,
187 read_map, pAddr);
188 break;
189 case AccessLength_WORD :
190 value = sim_core_read_aligned_4 (CPU, NULL_CIA,
191 read_map, pAddr);
192 break;
193 case AccessLength_TRIPLEBYTE :
194 value = sim_core_read_misaligned_3 (CPU, NULL_CIA,
195 read_map, pAddr);
196 break;
197 case AccessLength_HALFWORD :
198 value = sim_core_read_aligned_2 (CPU, NULL_CIA,
199 read_map, pAddr);
200 break;
201 case AccessLength_BYTE :
202 value = sim_core_read_aligned_1 (CPU, NULL_CIA,
203 read_map, pAddr);
204 break;
205 default:
206 abort ();
207 }
208
209 #ifdef DEBUG
210 printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
211 (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
212 #endif /* DEBUG */
213
214 /* See also store_memory. Position data in correct byte lanes. */
215 if (AccessLength <= LOADDRMASK)
216 {
217 if (BigEndianMem)
218 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
219 shifted to the most significant byte position. */
220 value <<= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
221 else
222 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
223 is already in the correct postition. */
224 value <<= ((pAddr & LOADDRMASK) * 8);
225 }
226
227 #ifdef DEBUG
228 printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
229 pr_uword64(value1),pr_uword64(value));
230 #endif /* DEBUG */
231
232 *memvalp = value;
233 if (memval1p) *memval1p = value1;
234 }
235
236
237 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
238 (revision 3.1) */
239 /* Store a value to memory. The specified data is stored into the
240 physical location pAddr using the memory hierarchy (data caches and
241 main memory) as specified by the Cache Coherence Algorithm
242 (CCA). The MemElem contains the data for an aligned, fixed-width
243 memory element (word for 32-bit processors, doubleword for 64-bit
244 processors), though only the bytes that will actually be stored to
245 memory need to be valid. The low-order two (or three) bits of pAddr
246 and the AccessLength field indicates which of the bytes within the
247 MemElem data should actually be stored; only these bytes in memory
248 will be changed. */
249
250 INLINE_SIM_MAIN (void)
251 store_memory (SIM_DESC SD,
252 sim_cpu *CPU,
253 address_word cia,
254 int CCA,
255 unsigned int AccessLength,
256 uword64 MemElem,
257 uword64 MemElem1, /* High order 64 bits */
258 address_word pAddr,
259 address_word vAddr)
260 {
261 #ifdef DEBUG
262 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));
263 #endif /* DEBUG */
264
265 #if defined(WARN_MEM)
266 if (CCA != uncached)
267 sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
268 #endif /* WARN_MEM */
269
270 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
271 sim_io_error (SD, "STORE AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
272 AccessLength,
273 (LOADDRMASK + 1) << 3,
274 pr_addr(pAddr));
275
276 #if defined(TRACE)
277 dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
278 #endif /* TRACE */
279
280 #ifdef DEBUG
281 printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
282 #endif /* DEBUG */
283
284 /* See also load_memory. Position data in correct byte lanes. */
285 if (AccessLength <= LOADDRMASK)
286 {
287 if (BigEndianMem)
288 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
289 shifted to the most significant byte position. */
290 MemElem >>= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
291 else
292 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
293 is already in the correct postition. */
294 MemElem >>= ((pAddr & LOADDRMASK) * 8);
295 }
296
297 #ifdef DEBUG
298 printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
299 #endif /* DEBUG */
300
301 switch (AccessLength)
302 {
303 case AccessLength_QUADWORD :
304 {
305 unsigned_16 val = U16_8 (MemElem1, MemElem);
306 sim_core_write_aligned_16 (CPU, NULL_CIA, write_map, pAddr, val);
307 break;
308 }
309 case AccessLength_DOUBLEWORD :
310 sim_core_write_aligned_8 (CPU, NULL_CIA,
311 write_map, pAddr, MemElem);
312 break;
313 case AccessLength_SEPTIBYTE :
314 sim_core_write_misaligned_7 (CPU, NULL_CIA,
315 write_map, pAddr, MemElem);
316 break;
317 case AccessLength_SEXTIBYTE :
318 sim_core_write_misaligned_6 (CPU, NULL_CIA,
319 write_map, pAddr, MemElem);
320 break;
321 case AccessLength_QUINTIBYTE :
322 sim_core_write_misaligned_5 (CPU, NULL_CIA,
323 write_map, pAddr, MemElem);
324 break;
325 case AccessLength_WORD :
326 sim_core_write_aligned_4 (CPU, NULL_CIA,
327 write_map, pAddr, MemElem);
328 break;
329 case AccessLength_TRIPLEBYTE :
330 sim_core_write_misaligned_3 (CPU, NULL_CIA,
331 write_map, pAddr, MemElem);
332 break;
333 case AccessLength_HALFWORD :
334 sim_core_write_aligned_2 (CPU, NULL_CIA,
335 write_map, pAddr, MemElem);
336 break;
337 case AccessLength_BYTE :
338 sim_core_write_aligned_1 (CPU, NULL_CIA,
339 write_map, pAddr, MemElem);
340 break;
341 default:
342 abort ();
343 }
344
345 return;
346 }
347
348
349 INLINE_SIM_MAIN (unsigned32)
350 ifetch32 (SIM_DESC SD,
351 sim_cpu *CPU,
352 address_word cia,
353 address_word vaddr)
354 {
355 /* Copy the action of the LW instruction */
356 address_word mask = LOADDRMASK;
357 address_word access = AccessLength_WORD;
358 address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
359 address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
360 unsigned int byte;
361 address_word paddr;
362 int uncached;
363 unsigned64 memval;
364
365 if ((vaddr & access) != 0)
366 SignalExceptionInstructionFetch ();
367 AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
368 paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
369 LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
370 byte = ((vaddr & mask) ^ bigendiancpu);
371 return (memval >> (8 * byte));
372 }
373
374
375 INLINE_SIM_MAIN (unsigned16)
376 ifetch16 (SIM_DESC SD,
377 sim_cpu *CPU,
378 address_word cia,
379 address_word vaddr)
380 {
381 /* Copy the action of the LH instruction */
382 address_word mask = LOADDRMASK;
383 address_word access = AccessLength_HALFWORD;
384 address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0);
385 address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0);
386 unsigned int byte;
387 address_word paddr;
388 int uncached;
389 unsigned64 memval;
390
391 if ((vaddr & access) != 0)
392 SignalExceptionInstructionFetch ();
393 AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL);
394 paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
395 LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL);
396 byte = ((vaddr & mask) ^ bigendiancpu);
397 return (memval >> (8 * byte));
398 }
399
400
401
402 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
403 /* Order loads and stores to synchronise shared memory. Perform the
404 action necessary to make the effects of groups of synchronizable
405 loads and stores indicated by stype occur in the same order for all
406 processors. */
407 INLINE_SIM_MAIN (void)
408 sync_operation (SIM_DESC sd,
409 sim_cpu *cpu,
410 address_word cia,
411 int stype)
412 {
413 #ifdef DEBUG
414 sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
415 #endif /* DEBUG */
416 return;
417 }
418
419 INLINE_SIM_MAIN (void)
420 cache_op (SIM_DESC SD,
421 sim_cpu *CPU,
422 address_word cia,
423 int op,
424 address_word pAddr,
425 address_word vAddr,
426 unsigned int instruction)
427 {
428 #if 1 /* stop warning message being displayed (we should really just remove the code) */
429 static int icache_warning = 1;
430 static int dcache_warning = 1;
431 #else
432 static int icache_warning = 0;
433 static int dcache_warning = 0;
434 #endif
435
436 /* If CP0 is not useable (User or Supervisor mode) and the CP0
437 enable bit in the Status Register is clear - a coprocessor
438 unusable exception is taken. */
439 #if 0
440 sim_io_printf(SD,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia));
441 #endif
442
443 switch (op & 0x3) {
444 case 0: /* instruction cache */
445 switch (op >> 2) {
446 case 0: /* Index Invalidate */
447 case 1: /* Index Load Tag */
448 case 2: /* Index Store Tag */
449 case 4: /* Hit Invalidate */
450 case 5: /* Fill */
451 case 6: /* Hit Writeback */
452 if (!icache_warning)
453 {
454 sim_io_eprintf(SD,"Instruction CACHE operation %d to be coded\n",(op >> 2));
455 icache_warning = 1;
456 }
457 break;
458
459 default:
460 SignalException(ReservedInstruction,instruction);
461 break;
462 }
463 break;
464
465 case 1: /* data cache */
466 switch (op >> 2) {
467 case 0: /* Index Writeback Invalidate */
468 case 1: /* Index Load Tag */
469 case 2: /* Index Store Tag */
470 case 3: /* Create Dirty */
471 case 4: /* Hit Invalidate */
472 case 5: /* Hit Writeback Invalidate */
473 case 6: /* Hit Writeback */
474 if (!dcache_warning)
475 {
476 sim_io_eprintf(SD,"Data CACHE operation %d to be coded\n",(op >> 2));
477 dcache_warning = 1;
478 }
479 break;
480
481 default:
482 SignalException(ReservedInstruction,instruction);
483 break;
484 }
485 break;
486
487 default: /* unrecognised cache ID */
488 SignalException(ReservedInstruction,instruction);
489 break;
490 }
491
492 return;
493 }
494
495
496 INLINE_SIM_MAIN (void)
497 pending_tick (SIM_DESC SD,
498 sim_cpu *CPU,
499 address_word cia)
500 {
501 if (PENDING_TRACE)
502 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);
503 if (PENDING_OUT != PENDING_IN)
504 {
505 int loop;
506 int index = PENDING_OUT;
507 int total = PENDING_TOTAL;
508 if (PENDING_TOTAL == 0)
509 sim_engine_abort (SD, CPU, cia, "PENDING_DRAIN - Mis-match on pending update pointers\n");
510 for (loop = 0, index = PENDING_OUT;
511 (loop < total);
512 loop++, index = (index + 1) % PSLOTS)
513 {
514 if (PENDING_SLOT_DEST[index] != NULL)
515 {
516 PENDING_SLOT_DELAY[index] -= 1;
517 if (PENDING_SLOT_DELAY[index] == 0)
518 {
519 if (PENDING_TRACE)
520 sim_io_eprintf (SD, "PENDING_DRAIN - drained - index %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
521 index,
522 (unsigned long) PENDING_SLOT_DEST[index],
523 PENDING_SLOT_BIT[index],
524 (unsigned long) PENDING_SLOT_VALUE[index],
525 PENDING_SLOT_SIZE[index]);
526 if (PENDING_SLOT_BIT[index] >= 0)
527 switch (PENDING_SLOT_SIZE[index])
528 {
529 case 4:
530 if (PENDING_SLOT_VALUE[index])
531 *(unsigned32*)PENDING_SLOT_DEST[index] |=
532 BIT32 (PENDING_SLOT_BIT[index]);
533 else
534 *(unsigned32*)PENDING_SLOT_DEST[index] &=
535 BIT32 (PENDING_SLOT_BIT[index]);
536 break;
537 case 8:
538 if (PENDING_SLOT_VALUE[index])
539 *(unsigned64*)PENDING_SLOT_DEST[index] |=
540 BIT64 (PENDING_SLOT_BIT[index]);
541 else
542 *(unsigned64*)PENDING_SLOT_DEST[index] &=
543 BIT64 (PENDING_SLOT_BIT[index]);
544 break;
545 }
546 else
547 switch (PENDING_SLOT_SIZE[index])
548 {
549 case 4:
550 *(unsigned32*)PENDING_SLOT_DEST[index] =
551 PENDING_SLOT_VALUE[index];
552 break;
553 case 8:
554 *(unsigned64*)PENDING_SLOT_DEST[index] =
555 PENDING_SLOT_VALUE[index];
556 break;
557 }
558 if (PENDING_OUT == index)
559 {
560 PENDING_SLOT_DEST[index] = NULL;
561 PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;
562 PENDING_TOTAL--;
563 }
564 }
565 else if (PENDING_TRACE && PENDING_SLOT_DELAY[index] > 0)
566 sim_io_eprintf (SD, "PENDING_DRAIN - queued - index %d, delay %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
567 index, PENDING_SLOT_DELAY[index],
568 (unsigned long) PENDING_SLOT_DEST[index],
569 PENDING_SLOT_BIT[index],
570 (unsigned long) PENDING_SLOT_VALUE[index],
571 PENDING_SLOT_SIZE[index]);
572
573 }
574 }
575 }
576 }
577
578
579 #endif