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