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