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