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