* ltcf-cxx.sh (osf3/osf4/osf5): Support creation of C++ shared
[deliverable/binutils-gdb.git] / sim / arm / armsupp.c
1 /* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18 #include "armdefs.h"
19 #include "armemu.h"
20 #include "ansidecl.h"
21
22 /***************************************************************************\
23 * Definitions for the support routines *
24 \***************************************************************************/
25
26 ARMword ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg);
27 void ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg,
28 ARMword value);
29 ARMword ARMul_GetPC (ARMul_State * state);
30 ARMword ARMul_GetNextPC (ARMul_State * state);
31 void ARMul_SetPC (ARMul_State * state, ARMword value);
32 ARMword ARMul_GetR15 (ARMul_State * state);
33 void ARMul_SetR15 (ARMul_State * state, ARMword value);
34
35 ARMword ARMul_GetCPSR (ARMul_State * state);
36 void ARMul_SetCPSR (ARMul_State * state, ARMword value);
37 ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode);
38 void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value);
39
40 void ARMul_CPSRAltered (ARMul_State * state);
41 void ARMul_R15Altered (ARMul_State * state);
42
43 ARMword ARMul_SwitchMode (ARMul_State * state, ARMword oldmode,
44 ARMword newmode);
45 static ARMword ModeToBank (ARMword mode);
46
47 unsigned ARMul_NthReg (ARMword instr, unsigned number);
48
49 void ARMul_NegZero (ARMul_State * state, ARMword result);
50 void ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b,
51 ARMword result);
52 void ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b,
53 ARMword result);
54 void ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b,
55 ARMword result);
56 void ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b,
57 ARMword result);
58
59 void ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address);
60 void ARMul_STC (ARMul_State * state, ARMword instr, ARMword address);
61 void ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source);
62 ARMword ARMul_MRC (ARMul_State * state, ARMword instr);
63 void ARMul_CDP (ARMul_State * state, ARMword instr);
64 unsigned IntPending (ARMul_State * state);
65
66 ARMword ARMul_Align (ARMul_State * state, ARMword address, ARMword data);
67
68 void ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
69 unsigned (*what) ());
70 void ARMul_EnvokeEvent (ARMul_State * state);
71 unsigned long ARMul_Time (ARMul_State * state);
72 static void EnvokeList (ARMul_State * state, unsigned long from,
73 unsigned long to);
74
75 struct EventNode
76 { /* An event list node */
77 unsigned (*func) (); /* The function to call */
78 struct EventNode *next;
79 };
80
81 /***************************************************************************\
82 * This routine returns the value of a register from a mode. *
83 \***************************************************************************/
84
85 ARMword
86 ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg)
87 {
88 mode &= MODEBITS;
89 if (mode != state->Mode)
90 return (state->RegBank[ModeToBank ((ARMword) mode)][reg]);
91 else
92 return (state->Reg[reg]);
93 }
94
95 /***************************************************************************\
96 * This routine sets the value of a register for a mode. *
97 \***************************************************************************/
98
99 void
100 ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value)
101 {
102 mode &= MODEBITS;
103 if (mode != state->Mode)
104 state->RegBank[ModeToBank ((ARMword) mode)][reg] = value;
105 else
106 state->Reg[reg] = value;
107 }
108
109 /***************************************************************************\
110 * This routine returns the value of the PC, mode independently. *
111 \***************************************************************************/
112
113 ARMword
114 ARMul_GetPC (ARMul_State * state)
115 {
116 if (state->Mode > SVC26MODE)
117 return (state->Reg[15]);
118 else
119 return (R15PC);
120 }
121
122 /***************************************************************************\
123 * This routine returns the value of the PC, mode independently. *
124 \***************************************************************************/
125
126 ARMword
127 ARMul_GetNextPC (ARMul_State * state)
128 {
129 if (state->Mode > SVC26MODE)
130 return (state->Reg[15] + isize);
131 else
132 return ((state->Reg[15] + isize) & R15PCBITS);
133 }
134
135 /***************************************************************************\
136 * This routine sets the value of the PC. *
137 \***************************************************************************/
138
139 void
140 ARMul_SetPC (ARMul_State * state, ARMword value)
141 {
142 if (ARMul_MODE32BIT)
143 state->Reg[15] = value & PCBITS;
144 else
145 state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);
146 FLUSHPIPE;
147 }
148
149 /***************************************************************************\
150 * This routine returns the value of register 15, mode independently. *
151 \***************************************************************************/
152
153 ARMword
154 ARMul_GetR15 (ARMul_State * state)
155 {
156 if (state->Mode > SVC26MODE)
157 return (state->Reg[15]);
158 else
159 return (R15PC | ECC | ER15INT | EMODE);
160 }
161
162 /***************************************************************************\
163 * This routine sets the value of Register 15. *
164 \***************************************************************************/
165
166 void
167 ARMul_SetR15 (ARMul_State * state, ARMword value)
168 {
169 if (ARMul_MODE32BIT)
170 state->Reg[15] = value & PCBITS;
171 else
172 {
173 state->Reg[15] = value;
174 ARMul_R15Altered (state);
175 }
176 FLUSHPIPE;
177 }
178
179 /***************************************************************************\
180 * This routine returns the value of the CPSR *
181 \***************************************************************************/
182
183 ARMword
184 ARMul_GetCPSR (ARMul_State * state)
185 {
186 return (CPSR | state->Cpsr);
187 }
188
189 /***************************************************************************\
190 * This routine sets the value of the CPSR *
191 \***************************************************************************/
192
193 void
194 ARMul_SetCPSR (ARMul_State * state, ARMword value)
195 {
196 state->Cpsr = value;
197 ARMul_CPSRAltered (state);
198 }
199
200 /***************************************************************************\
201 * This routine does all the nasty bits involved in a write to the CPSR, *
202 * including updating the register bank, given a MSR instruction. *
203 \***************************************************************************/
204
205 void
206 ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
207 {
208 state->Cpsr = ARMul_GetCPSR (state);
209 if (state->Mode != USER26MODE
210 && state->Mode != USER32MODE)
211 { /* In user mode, only write flags */
212 if (BIT (16))
213 SETPSR_C (state->Cpsr, rhs);
214 if (BIT (17))
215 SETPSR_X (state->Cpsr, rhs);
216 if (BIT (18))
217 SETPSR_S (state->Cpsr, rhs);
218 }
219 if (BIT (19))
220 SETPSR_F (state->Cpsr, rhs);
221 ARMul_CPSRAltered (state);
222 }
223
224 /***************************************************************************\
225 * Get an SPSR from the specified mode *
226 \***************************************************************************/
227
228 ARMword
229 ARMul_GetSPSR (ARMul_State * state, ARMword mode)
230 {
231 ARMword bank = ModeToBank (mode & MODEBITS);
232
233 if (! BANK_CAN_ACCESS_SPSR (bank))
234 return ARMul_GetCPSR (state);
235
236 return state->Spsr[bank];
237 }
238
239 /***************************************************************************\
240 * This routine does a write to an SPSR *
241 \***************************************************************************/
242
243 void
244 ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
245 {
246 ARMword bank = ModeToBank (mode & MODEBITS);
247
248 if (BANK_CAN_ACCESS_SPSR (bank))
249 state->Spsr[bank] = value;
250 }
251
252 /***************************************************************************\
253 * This routine does a write to the current SPSR, given an MSR instruction *
254 \***************************************************************************/
255
256 void
257 ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
258 {
259 if (BANK_CAN_ACCESS_SPSR (state->Bank))
260 {
261 if (BIT (16))
262 SETPSR_C (state->Spsr[state->Bank], rhs);
263 if (BIT (17))
264 SETPSR_X (state->Spsr[state->Bank], rhs);
265 if (BIT (18))
266 SETPSR_S (state->Spsr[state->Bank], rhs);
267 if (BIT (19))
268 SETPSR_F (state->Spsr[state->Bank], rhs);
269 }
270 }
271
272 /***************************************************************************\
273 * This routine updates the state of the emulator after the Cpsr has been *
274 * changed. Both the processor flags and register bank are updated. *
275 \***************************************************************************/
276
277 void
278 ARMul_CPSRAltered (ARMul_State * state)
279 {
280 ARMword oldmode;
281
282 if (state->prog32Sig == LOW)
283 state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
284
285 oldmode = state->Mode;
286
287 if (state->Mode != (state->Cpsr & MODEBITS))
288 {
289 state->Mode =
290 ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS);
291
292 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
293 }
294 state->Cpsr &= ~MODEBITS;
295
296 ASSIGNINT (state->Cpsr & INTBITS);
297 state->Cpsr &= ~INTBITS;
298 ASSIGNN ((state->Cpsr & NBIT) != 0);
299 state->Cpsr &= ~NBIT;
300 ASSIGNZ ((state->Cpsr & ZBIT) != 0);
301 state->Cpsr &= ~ZBIT;
302 ASSIGNC ((state->Cpsr & CBIT) != 0);
303 state->Cpsr &= ~CBIT;
304 ASSIGNV ((state->Cpsr & VBIT) != 0);
305 state->Cpsr &= ~VBIT;
306 ASSIGNS ((state->Cpsr & SBIT) != 0);
307 state->Cpsr &= ~SBIT;
308 #ifdef MODET
309 ASSIGNT ((state->Cpsr & TBIT) != 0);
310 state->Cpsr &= ~TBIT;
311 #endif
312
313 if (oldmode > SVC26MODE)
314 {
315 if (state->Mode <= SVC26MODE)
316 {
317 state->Emulate = CHANGEMODE;
318 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
319 }
320 }
321 else
322 {
323 if (state->Mode > SVC26MODE)
324 {
325 state->Emulate = CHANGEMODE;
326 state->Reg[15] = R15PC;
327 }
328 else
329 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
330 }
331 }
332
333 /***************************************************************************\
334 * This routine updates the state of the emulator after register 15 has *
335 * been changed. Both the processor flags and register bank are updated. *
336 * This routine should only be called from a 26 bit mode. *
337 \***************************************************************************/
338
339 void
340 ARMul_R15Altered (ARMul_State * state)
341 {
342 if (state->Mode != R15MODE)
343 {
344 state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);
345 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
346 }
347 if (state->Mode > SVC26MODE)
348 state->Emulate = CHANGEMODE;
349 ASSIGNR15INT (R15INT);
350 ASSIGNN ((state->Reg[15] & NBIT) != 0);
351 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
352 ASSIGNC ((state->Reg[15] & CBIT) != 0);
353 ASSIGNV ((state->Reg[15] & VBIT) != 0);
354 }
355
356 /***************************************************************************\
357 * This routine controls the saving and restoring of registers across mode *
358 * changes. The regbank matrix is largely unused, only rows 13 and 14 are *
359 * used across all modes, 8 to 14 are used for FIQ, all others use the USER *
360 * column. It's easier this way. old and new parameter are modes numbers. *
361 * Notice the side effect of changing the Bank variable. *
362 \***************************************************************************/
363
364 ARMword
365 ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
366 {
367 unsigned i;
368 ARMword oldbank;
369 ARMword newbank;
370
371 oldbank = ModeToBank (oldmode);
372 newbank = state->Bank = ModeToBank (newmode);
373
374 if (oldbank != newbank)
375 { /* really need to do it */
376 switch (oldbank)
377 { /* save away the old registers */
378 case USERBANK:
379 case IRQBANK:
380 case SVCBANK:
381 case ABORTBANK:
382 case UNDEFBANK:
383 if (newbank == FIQBANK)
384 for (i = 8; i < 13; i++)
385 state->RegBank[USERBANK][i] = state->Reg[i];
386 state->RegBank[oldbank][13] = state->Reg[13];
387 state->RegBank[oldbank][14] = state->Reg[14];
388 break;
389 case FIQBANK:
390 for (i = 8; i < 15; i++)
391 state->RegBank[FIQBANK][i] = state->Reg[i];
392 break;
393 case DUMMYBANK:
394 for (i = 8; i < 15; i++)
395 state->RegBank[DUMMYBANK][i] = 0;
396 break;
397 default:
398 abort ();
399 }
400
401 switch (newbank)
402 { /* restore the new registers */
403 case USERBANK:
404 case IRQBANK:
405 case SVCBANK:
406 case ABORTBANK:
407 case UNDEFBANK:
408 if (oldbank == FIQBANK)
409 for (i = 8; i < 13; i++)
410 state->Reg[i] = state->RegBank[USERBANK][i];
411 state->Reg[13] = state->RegBank[newbank][13];
412 state->Reg[14] = state->RegBank[newbank][14];
413 break;
414 case FIQBANK:
415 for (i = 8; i < 15; i++)
416 state->Reg[i] = state->RegBank[FIQBANK][i];
417 break;
418 case DUMMYBANK:
419 for (i = 8; i < 15; i++)
420 state->Reg[i] = 0;
421 break;
422 default:
423 abort ();
424 } /* switch */
425 } /* if */
426
427 return newmode;
428 }
429
430 /***************************************************************************\
431 * Given a processor mode, this routine returns the register bank that *
432 * will be accessed in that mode. *
433 \***************************************************************************/
434
435 static ARMword
436 ModeToBank (ARMword mode)
437 {
438 static ARMword bankofmode[] =
439 {
440 USERBANK, FIQBANK, IRQBANK, SVCBANK,
441 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
442 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
443 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
444 USERBANK, FIQBANK, IRQBANK, SVCBANK,
445 DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
446 DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK,
447 DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK
448 };
449
450 if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0])))
451 return DUMMYBANK;
452
453 return bankofmode[mode];
454 }
455
456 /***************************************************************************\
457 * Returns the register number of the nth register in a reg list. *
458 \***************************************************************************/
459
460 unsigned
461 ARMul_NthReg (ARMword instr, unsigned number)
462 {
463 unsigned bit, upto;
464
465 for (bit = 0, upto = 0; upto <= number; bit++)
466 if (BIT (bit))
467 upto++;
468 return (bit - 1);
469 }
470
471 /***************************************************************************\
472 * Assigns the N and Z flags depending on the value of result *
473 \***************************************************************************/
474
475 void
476 ARMul_NegZero (ARMul_State * state, ARMword result)
477 {
478 if (NEG (result))
479 {
480 SETN;
481 CLEARZ;
482 }
483 else if (result == 0)
484 {
485 CLEARN;
486 SETZ;
487 }
488 else
489 {
490 CLEARN;
491 CLEARZ;
492 };
493 }
494
495 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
496 int
497 AddOverflow (ARMword a, ARMword b, ARMword result)
498 {
499 return ((NEG (a) && NEG (b) && POS (result))
500 || (POS (a) && POS (b) && NEG (result)));
501 }
502
503 /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
504 int
505 SubOverflow (ARMword a, ARMword b, ARMword result)
506 {
507 return ((NEG (a) && POS (b) && POS (result))
508 || (POS (a) && NEG (b) && NEG (result)));
509 }
510
511 /***************************************************************************\
512 * Assigns the C flag after an addition of a and b to give result *
513 \***************************************************************************/
514
515 void
516 ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
517 {
518 ASSIGNC ((NEG (a) && NEG (b)) ||
519 (NEG (a) && POS (result)) || (NEG (b) && POS (result)));
520 }
521
522 /***************************************************************************\
523 * Assigns the V flag after an addition of a and b to give result *
524 \***************************************************************************/
525
526 void
527 ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
528 {
529 ASSIGNV (AddOverflow (a, b, result));
530 }
531
532 /***************************************************************************\
533 * Assigns the C flag after an subtraction of a and b to give result *
534 \***************************************************************************/
535
536 void
537 ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
538 {
539 ASSIGNC ((NEG (a) && POS (b)) ||
540 (NEG (a) && POS (result)) || (POS (b) && POS (result)));
541 }
542
543 /***************************************************************************\
544 * Assigns the V flag after an subtraction of a and b to give result *
545 \***************************************************************************/
546
547 void
548 ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
549 {
550 ASSIGNV (SubOverflow (a, b, result));
551 }
552
553 /***************************************************************************\
554 * This function does the work of generating the addresses used in an *
555 * LDC instruction. The code here is always post-indexed, it's up to the *
556 * caller to get the input address correct and to handle base register *
557 * modification. It also handles the Busy-Waiting. *
558 \***************************************************************************/
559
560 void
561 ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
562 {
563 unsigned cpab;
564 ARMword data;
565
566 UNDEF_LSCPCBaseWb;
567 if (ADDREXCEPT (address))
568 {
569 INTERNALABORT (address);
570 }
571 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
572 while (cpab == ARMul_BUSY)
573 {
574 ARMul_Icycles (state, 1, 0);
575 if (IntPending (state))
576 {
577 cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
578 return;
579 }
580 else
581 cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0);
582 }
583 if (cpab == ARMul_CANT)
584 {
585 CPTAKEABORT;
586 return;
587 }
588 cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
589 data = ARMul_LoadWordN (state, address);
590 BUSUSEDINCPCN;
591 if (BIT (21))
592 LSBase = state->Base;
593 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
594 while (cpab == ARMul_INC)
595 {
596 address += 4;
597 data = ARMul_LoadWordN (state, address);
598 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
599 }
600 if (state->abortSig || state->Aborted)
601 {
602 TAKEABORT;
603 }
604 }
605
606 /***************************************************************************\
607 * This function does the work of generating the addresses used in an *
608 * STC instruction. The code here is always post-indexed, it's up to the *
609 * caller to get the input address correct and to handle base register *
610 * modification. It also handles the Busy-Waiting. *
611 \***************************************************************************/
612
613 void
614 ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
615 {
616 unsigned cpab;
617 ARMword data;
618
619 UNDEF_LSCPCBaseWb;
620 if (ADDREXCEPT (address) || VECTORACCESS (address))
621 {
622 INTERNALABORT (address);
623 }
624 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
625 while (cpab == ARMul_BUSY)
626 {
627 ARMul_Icycles (state, 1, 0);
628 if (IntPending (state))
629 {
630 cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
631 return;
632 }
633 else
634 cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data);
635 }
636 if (cpab == ARMul_CANT)
637 {
638 CPTAKEABORT;
639 return;
640 }
641 #ifndef MODE32
642 if (ADDREXCEPT (address) || VECTORACCESS (address))
643 {
644 INTERNALABORT (address);
645 }
646 #endif
647 BUSUSEDINCPCN;
648 if (BIT (21))
649 LSBase = state->Base;
650 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
651 ARMul_StoreWordN (state, address, data);
652 while (cpab == ARMul_INC)
653 {
654 address += 4;
655 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
656 ARMul_StoreWordN (state, address, data);
657 }
658 if (state->abortSig || state->Aborted)
659 {
660 TAKEABORT;
661 }
662 }
663
664 /***************************************************************************\
665 * This function does the Busy-Waiting for an MCR instruction. *
666 \***************************************************************************/
667
668 void
669 ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
670 {
671 unsigned cpab;
672
673 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
674
675 while (cpab == ARMul_BUSY)
676 {
677 ARMul_Icycles (state, 1, 0);
678
679 if (IntPending (state))
680 {
681 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
682 return;
683 }
684 else
685 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source);
686 }
687
688 if (cpab == ARMul_CANT)
689 ARMul_Abort (state, ARMul_UndefinedInstrV);
690 else
691 {
692 BUSUSEDINCPCN;
693 ARMul_Ccycles (state, 1, 0);
694 }
695 }
696
697 /***************************************************************************\
698 * This function does the Busy-Waiting for an MRC instruction. *
699 \***************************************************************************/
700
701 ARMword
702 ARMul_MRC (ARMul_State * state, ARMword instr)
703 {
704 unsigned cpab;
705 ARMword result = 0;
706
707 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
708 while (cpab == ARMul_BUSY)
709 {
710 ARMul_Icycles (state, 1, 0);
711 if (IntPending (state))
712 {
713 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
714 return (0);
715 }
716 else
717 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result);
718 }
719 if (cpab == ARMul_CANT)
720 {
721 ARMul_Abort (state, ARMul_UndefinedInstrV);
722 result = ECC; /* Parent will destroy the flags otherwise */
723 }
724 else
725 {
726 BUSUSEDINCPCN;
727 ARMul_Ccycles (state, 1, 0);
728 ARMul_Icycles (state, 1, 0);
729 }
730 return (result);
731 }
732
733 /***************************************************************************\
734 * This function does the Busy-Waiting for an CDP instruction. *
735 \***************************************************************************/
736
737 void
738 ARMul_CDP (ARMul_State * state, ARMword instr)
739 {
740 unsigned cpab;
741
742 cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
743 while (cpab == ARMul_BUSY)
744 {
745 ARMul_Icycles (state, 1, 0);
746 if (IntPending (state))
747 {
748 cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr);
749 return;
750 }
751 else
752 cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
753 }
754 if (cpab == ARMul_CANT)
755 ARMul_Abort (state, ARMul_UndefinedInstrV);
756 else
757 BUSUSEDN;
758 }
759
760 /***************************************************************************\
761 * This function handles Undefined instructions, as CP isntruction *
762 \***************************************************************************/
763
764 void
765 ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED)
766 {
767 ARMul_Abort (state, ARMul_UndefinedInstrV);
768 }
769
770 /***************************************************************************\
771 * Return TRUE if an interrupt is pending, FALSE otherwise. *
772 \***************************************************************************/
773
774 unsigned
775 IntPending (ARMul_State * state)
776 {
777 if (state->Exception)
778 { /* Any exceptions */
779 if (state->NresetSig == LOW)
780 {
781 ARMul_Abort (state, ARMul_ResetV);
782 return (TRUE);
783 }
784 else if (!state->NfiqSig && !FFLAG)
785 {
786 ARMul_Abort (state, ARMul_FIQV);
787 return (TRUE);
788 }
789 else if (!state->NirqSig && !IFLAG)
790 {
791 ARMul_Abort (state, ARMul_IRQV);
792 return (TRUE);
793 }
794 }
795 return (FALSE);
796 }
797
798 /***************************************************************************\
799 * Align a word access to a non word boundary *
800 \***************************************************************************/
801
802 ARMword
803 ARMul_Align (state, address, data)
804 ARMul_State * state ATTRIBUTE_UNUSED;
805 ARMword address;
806 ARMword data;
807 {
808 /* This code assumes the address is really unaligned,
809 as a shift by 32 is undefined in C. */
810
811 address = (address & 3) << 3; /* get the word address */
812 return ((data >> address) | (data << (32 - address))); /* rot right */
813 }
814
815 /***************************************************************************\
816 * This routine is used to call another routine after a certain number of *
817 * cycles have been executed. The first parameter is the number of cycles *
818 * delay before the function is called, the second argument is a pointer *
819 * to the function. A delay of zero doesn't work, just call the function. *
820 \***************************************************************************/
821
822 void
823 ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
824 unsigned (*what) ())
825 {
826 unsigned long when;
827 struct EventNode *event;
828
829 if (state->EventSet++ == 0)
830 state->Now = ARMul_Time (state);
831 when = (state->Now + delay) % EVENTLISTSIZE;
832 event = (struct EventNode *) malloc (sizeof (struct EventNode));
833 event->func = what;
834 event->next = *(state->EventPtr + when);
835 *(state->EventPtr + when) = event;
836 }
837
838 /***************************************************************************\
839 * This routine is called at the beginning of every cycle, to envoke *
840 * scheduled events. *
841 \***************************************************************************/
842
843 void
844 ARMul_EnvokeEvent (ARMul_State * state)
845 {
846 static unsigned long then;
847
848 then = state->Now;
849 state->Now = ARMul_Time (state) % EVENTLISTSIZE;
850 if (then < state->Now) /* schedule events */
851 EnvokeList (state, then, state->Now);
852 else if (then > state->Now)
853 { /* need to wrap around the list */
854 EnvokeList (state, then, EVENTLISTSIZE - 1L);
855 EnvokeList (state, 0L, state->Now);
856 }
857 }
858
859 static void
860 EnvokeList (ARMul_State * state, unsigned long from, unsigned long to)
861 /* envokes all the entries in a range */
862 {
863 struct EventNode *anevent;
864
865 for (; from <= to; from++)
866 {
867 anevent = *(state->EventPtr + from);
868 while (anevent)
869 {
870 (anevent->func) (state);
871 state->EventSet--;
872 anevent = anevent->next;
873 }
874 *(state->EventPtr + from) = NULL;
875 }
876 }
877
878 /***************************************************************************\
879 * This routine is returns the number of clock ticks since the last reset. *
880 \***************************************************************************/
881
882 unsigned long
883 ARMul_Time (ARMul_State * state)
884 {
885 return (state->NumScycles + state->NumNcycles +
886 state->NumIcycles + state->NumCcycles + state->NumFcycles);
887 }
This page took 0.0522 seconds and 4 git commands to generate.