common/
[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 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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 }