sim: unify toolchain probing logic
[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 3 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, see <http://www.gnu.org/licenses/>.
15
16 */
17
18
19 #ifndef SIM_MAIN_C
20 #define SIM_MAIN_C
21
22 /* This must come before any other includes. */
23 #include "defs.h"
24
25 #include "sim-main.h"
26 #include "sim-assert.h"
27
28 #include <stdlib.h>
29
30 /*---------------------------------------------------------------------------*/
31 /*-- simulator engine -------------------------------------------------------*/
32 /*---------------------------------------------------------------------------*/
33
34
35 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
36 (revision 3.1) */
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
50 memory element. */
51 INLINE_SIM_MAIN (void)
52 load_memory (SIM_DESC SD,
53 sim_cpu *CPU,
54 address_word cia,
55 uword64* memvalp,
56 uword64* memval1p,
57 int CCA,
58 unsigned int AccessLength,
59 address_word pAddr,
60 address_word vAddr,
61 int IorD)
62 {
63 uword64 value = 0;
64 uword64 value1 = 0;
65
66 #ifdef DEBUG
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"));
68 #endif /* DEBUG */
69
70 #if defined(WARN_MEM)
71 if (CCA != uncached)
72 sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
73 #endif /* WARN_MEM */
74
75 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
76 {
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",
79 AccessLength,
80 (LOADDRMASK + 1) << 3,
81 pr_addr (pAddr));
82 }
83
84 dotrace (SD, CPU, tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
85
86 /* Read the specified number of bytes from memory. Adjust for
87 host/target byte ordering/ Align the least significant byte
88 read. */
89
90 switch (AccessLength)
91 {
92 case AccessLength_QUADWORD:
93 {
94 unsigned_16 val = sim_core_read_aligned_16 (CPU, cia, read_map, pAddr);
95 value1 = VH8_16 (val);
96 value = VL8_16 (val);
97 break;
98 }
99 case AccessLength_DOUBLEWORD:
100 value = sim_core_read_aligned_8 (CPU, cia, read_map, pAddr);
101 break;
102 case AccessLength_SEPTIBYTE:
103 value = sim_core_read_misaligned_7 (CPU, cia, read_map, pAddr);
104 break;
105 case AccessLength_SEXTIBYTE:
106 value = sim_core_read_misaligned_6 (CPU, cia, read_map, pAddr);
107 break;
108 case AccessLength_QUINTIBYTE:
109 value = sim_core_read_misaligned_5 (CPU, cia, read_map, pAddr);
110 break;
111 case AccessLength_WORD:
112 value = sim_core_read_aligned_4 (CPU, cia, read_map, pAddr);
113 break;
114 case AccessLength_TRIPLEBYTE:
115 value = sim_core_read_misaligned_3 (CPU, cia, read_map, pAddr);
116 break;
117 case AccessLength_HALFWORD:
118 value = sim_core_read_aligned_2 (CPU, cia, read_map, pAddr);
119 break;
120 case AccessLength_BYTE:
121 value = sim_core_read_aligned_1 (CPU, cia, read_map, pAddr);
122 break;
123 default:
124 abort ();
125 }
126
127 #ifdef DEBUG
128 printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
129 (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
130 #endif /* DEBUG */
131
132 /* See also store_memory. Position data in correct byte lanes. */
133 if (AccessLength <= LOADDRMASK)
134 {
135 if (BigEndianMem)
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);
139 else
140 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
141 is already in the correct postition. */
142 value <<= ((pAddr & LOADDRMASK) * 8);
143 }
144
145 #ifdef DEBUG
146 printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
147 pr_uword64(value1),pr_uword64(value));
148 #endif /* DEBUG */
149
150 *memvalp = value;
151 if (memval1p) *memval1p = value1;
152 }
153
154
155 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
156 (revision 3.1) */
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
166 will be changed. */
167
168 INLINE_SIM_MAIN (void)
169 store_memory (SIM_DESC SD,
170 sim_cpu *CPU,
171 address_word cia,
172 int CCA,
173 unsigned int AccessLength,
174 uword64 MemElem,
175 uword64 MemElem1, /* High order 64 bits */
176 address_word pAddr,
177 address_word vAddr)
178 {
179 #ifdef DEBUG
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));
181 #endif /* DEBUG */
182
183 #if defined(WARN_MEM)
184 if (CCA != uncached)
185 sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
186 #endif /* WARN_MEM */
187
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",
190 AccessLength,
191 (LOADDRMASK + 1) << 3,
192 pr_addr(pAddr));
193
194 dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
195
196 #ifdef DEBUG
197 printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
198 #endif /* DEBUG */
199
200 /* See also load_memory. Position data in correct byte lanes. */
201 if (AccessLength <= LOADDRMASK)
202 {
203 if (BigEndianMem)
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);
207 else
208 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
209 is already in the correct postition. */
210 MemElem >>= ((pAddr & LOADDRMASK) * 8);
211 }
212
213 #ifdef DEBUG
214 printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
215 #endif /* DEBUG */
216
217 switch (AccessLength)
218 {
219 case AccessLength_QUADWORD:
220 {
221 unsigned_16 val = U16_8 (MemElem1, MemElem);
222 sim_core_write_aligned_16 (CPU, cia, write_map, pAddr, val);
223 break;
224 }
225 case AccessLength_DOUBLEWORD:
226 sim_core_write_aligned_8 (CPU, cia, write_map, pAddr, MemElem);
227 break;
228 case AccessLength_SEPTIBYTE:
229 sim_core_write_misaligned_7 (CPU, cia, write_map, pAddr, MemElem);
230 break;
231 case AccessLength_SEXTIBYTE:
232 sim_core_write_misaligned_6 (CPU, cia, write_map, pAddr, MemElem);
233 break;
234 case AccessLength_QUINTIBYTE:
235 sim_core_write_misaligned_5 (CPU, cia, write_map, pAddr, MemElem);
236 break;
237 case AccessLength_WORD:
238 sim_core_write_aligned_4 (CPU, cia, write_map, pAddr, MemElem);
239 break;
240 case AccessLength_TRIPLEBYTE:
241 sim_core_write_misaligned_3 (CPU, cia, write_map, pAddr, MemElem);
242 break;
243 case AccessLength_HALFWORD:
244 sim_core_write_aligned_2 (CPU, cia, write_map, pAddr, MemElem);
245 break;
246 case AccessLength_BYTE:
247 sim_core_write_aligned_1 (CPU, cia, write_map, pAddr, MemElem);
248 break;
249 default:
250 abort ();
251 }
252
253 return;
254 }
255
256
257 INLINE_SIM_MAIN (unsigned32)
258 ifetch32 (SIM_DESC SD,
259 sim_cpu *CPU,
260 address_word cia,
261 address_word vaddr)
262 {
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);
268 unsigned int byte;
269 address_word paddr = vaddr;
270 unsigned64 memval;
271
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));
278 }
279
280
281 INLINE_SIM_MAIN (unsigned16)
282 ifetch16 (SIM_DESC SD,
283 sim_cpu *CPU,
284 address_word cia,
285 address_word vaddr)
286 {
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);
292 unsigned int byte;
293 address_word paddr = vaddr;
294 unsigned64 memval;
295
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));
302 }
303
304
305
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
310 processors. */
311 INLINE_SIM_MAIN (void)
312 sync_operation (SIM_DESC sd,
313 sim_cpu *cpu,
314 address_word cia,
315 int stype)
316 {
317 #ifdef DEBUG
318 sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
319 #endif /* DEBUG */
320 return;
321 }
322
323 INLINE_SIM_MAIN (void)
324 cache_op (SIM_DESC SD,
325 sim_cpu *CPU,
326 address_word cia,
327 int op,
328 address_word pAddr,
329 address_word vAddr,
330 unsigned int instruction)
331 {
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;
335 #else
336 static int icache_warning = 0;
337 static int dcache_warning = 0;
338 #endif
339
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. */
343 #if 0
344 sim_io_printf(SD,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia));
345 #endif
346
347 switch (op & 0x3) {
348 case 0: /* instruction cache */
349 switch (op >> 2) {
350 case 0: /* Index Invalidate */
351 case 1: /* Index Load Tag */
352 case 2: /* Index Store Tag */
353 case 4: /* Hit Invalidate */
354 case 5: /* Fill */
355 case 6: /* Hit Writeback */
356 if (!icache_warning)
357 {
358 sim_io_eprintf(SD,"Instruction CACHE operation %d to be coded\n",(op >> 2));
359 icache_warning = 1;
360 }
361 break;
362
363 default:
364 SignalException(ReservedInstruction,instruction);
365 break;
366 }
367 break;
368
369 case 1: /* data cache */
370 case 3: /* secondary data cache */
371 switch (op >> 2) {
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 */
379 if (!dcache_warning)
380 {
381 sim_io_eprintf(SD,"Data CACHE operation %d to be coded\n",(op >> 2));
382 dcache_warning = 1;
383 }
384 break;
385
386 default:
387 SignalException(ReservedInstruction,instruction);
388 break;
389 }
390 break;
391
392 default: /* unrecognised cache ID */
393 SignalException(ReservedInstruction,instruction);
394 break;
395 }
396
397 return;
398 }
399
400
401 INLINE_SIM_MAIN (void)
402 pending_tick (SIM_DESC SD,
403 sim_cpu *CPU,
404 address_word cia)
405 {
406 if (PENDING_TRACE)
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)
409 {
410 int loop;
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;
416 (loop < total);
417 loop++, index = (index + 1) % PSLOTS)
418 {
419 if (PENDING_SLOT_DEST[index] != NULL)
420 {
421 PENDING_SLOT_DELAY[index] -= 1;
422 if (PENDING_SLOT_DELAY[index] == 0)
423 {
424 if (PENDING_TRACE)
425 sim_io_eprintf (SD, "PENDING_DRAIN - drained - index %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
426 index,
427 (unsigned long) PENDING_SLOT_DEST[index],
428 PENDING_SLOT_BIT[index],
429 (unsigned long) PENDING_SLOT_VALUE[index],
430 PENDING_SLOT_SIZE[index]);
431 if (PENDING_SLOT_BIT[index] >= 0)
432 switch (PENDING_SLOT_SIZE[index])
433 {
434 case 4:
435 if (PENDING_SLOT_VALUE[index])
436 *(unsigned32*)PENDING_SLOT_DEST[index] |=
437 BIT32 (PENDING_SLOT_BIT[index]);
438 else
439 *(unsigned32*)PENDING_SLOT_DEST[index] &=
440 BIT32 (PENDING_SLOT_BIT[index]);
441 break;
442 case 8:
443 if (PENDING_SLOT_VALUE[index])
444 *(unsigned64*)PENDING_SLOT_DEST[index] |=
445 BIT64 (PENDING_SLOT_BIT[index]);
446 else
447 *(unsigned64*)PENDING_SLOT_DEST[index] &=
448 BIT64 (PENDING_SLOT_BIT[index]);
449 break;
450 }
451 else
452 switch (PENDING_SLOT_SIZE[index])
453 {
454 case 4:
455 *(unsigned32*)PENDING_SLOT_DEST[index] =
456 PENDING_SLOT_VALUE[index];
457 break;
458 case 8:
459 *(unsigned64*)PENDING_SLOT_DEST[index] =
460 PENDING_SLOT_VALUE[index];
461 break;
462 }
463 if (PENDING_OUT == index)
464 {
465 PENDING_SLOT_DEST[index] = NULL;
466 PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;
467 PENDING_TOTAL--;
468 }
469 }
470 else if (PENDING_TRACE && PENDING_SLOT_DELAY[index] > 0)
471 sim_io_eprintf (SD, "PENDING_DRAIN - queued - index %d, delay %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n",
472 index, PENDING_SLOT_DELAY[index],
473 (unsigned long) PENDING_SLOT_DEST[index],
474 PENDING_SLOT_BIT[index],
475 (unsigned long) PENDING_SLOT_VALUE[index],
476 PENDING_SLOT_SIZE[index]);
477
478 }
479 }
480 }
481 }
482
483
484 #endif
This page took 0.044178 seconds and 4 git commands to generate.