1 /* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
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.
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.
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. */
22 /***************************************************************************\
23 * Definitions for the support routines *
24 \***************************************************************************/
26 ARMword
ARMul_GetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
);
27 void ARMul_SetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
,
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
);
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
);
40 void ARMul_CPSRAltered (ARMul_State
* state
);
41 void ARMul_R15Altered (ARMul_State
* state
);
43 ARMword
ARMul_SwitchMode (ARMul_State
* state
, ARMword oldmode
,
45 static ARMword
ModeToBank (ARMword mode
);
47 unsigned ARMul_NthReg (ARMword instr
, unsigned number
);
49 void ARMul_NegZero (ARMul_State
* state
, ARMword result
);
50 void ARMul_AddCarry (ARMul_State
* state
, ARMword a
, ARMword b
,
52 void ARMul_AddOverflow (ARMul_State
* state
, ARMword a
, ARMword b
,
54 void ARMul_SubCarry (ARMul_State
* state
, ARMword a
, ARMword b
,
56 void ARMul_SubOverflow (ARMul_State
* state
, ARMword a
, ARMword b
,
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
);
66 ARMword
ARMul_Align (ARMul_State
* state
, ARMword address
, ARMword data
);
68 void ARMul_ScheduleEvent (ARMul_State
* state
, unsigned long delay
,
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
,
76 { /* An event list node */
77 unsigned (*func
) (); /* The function to call */
78 struct EventNode
*next
;
81 /***************************************************************************\
82 * This routine returns the value of a register from a mode. *
83 \***************************************************************************/
86 ARMul_GetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
)
89 if (mode
!= state
->Mode
)
90 return (state
->RegBank
[ModeToBank ((ARMword
) mode
)][reg
]);
92 return (state
->Reg
[reg
]);
95 /***************************************************************************\
96 * This routine sets the value of a register for a mode. *
97 \***************************************************************************/
100 ARMul_SetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
, ARMword value
)
103 if (mode
!= state
->Mode
)
104 state
->RegBank
[ModeToBank ((ARMword
) mode
)][reg
] = value
;
106 state
->Reg
[reg
] = value
;
109 /***************************************************************************\
110 * This routine returns the value of the PC, mode independently. *
111 \***************************************************************************/
114 ARMul_GetPC (ARMul_State
* state
)
116 if (state
->Mode
> SVC26MODE
)
117 return (state
->Reg
[15]);
122 /***************************************************************************\
123 * This routine returns the value of the PC, mode independently. *
124 \***************************************************************************/
127 ARMul_GetNextPC (ARMul_State
* state
)
129 if (state
->Mode
> SVC26MODE
)
130 return (state
->Reg
[15] + isize
);
132 return ((state
->Reg
[15] + isize
) & R15PCBITS
);
135 /***************************************************************************\
136 * This routine sets the value of the PC. *
137 \***************************************************************************/
140 ARMul_SetPC (ARMul_State
* state
, ARMword value
)
143 state
->Reg
[15] = value
& PCBITS
;
145 state
->Reg
[15] = R15CCINTMODE
| (value
& R15PCBITS
);
149 /***************************************************************************\
150 * This routine returns the value of register 15, mode independently. *
151 \***************************************************************************/
154 ARMul_GetR15 (ARMul_State
* state
)
156 if (state
->Mode
> SVC26MODE
)
157 return (state
->Reg
[15]);
159 return (R15PC
| ECC
| ER15INT
| EMODE
);
162 /***************************************************************************\
163 * This routine sets the value of Register 15. *
164 \***************************************************************************/
167 ARMul_SetR15 (ARMul_State
* state
, ARMword value
)
170 state
->Reg
[15] = value
& PCBITS
;
173 state
->Reg
[15] = value
;
174 ARMul_R15Altered (state
);
179 /***************************************************************************\
180 * This routine returns the value of the CPSR *
181 \***************************************************************************/
184 ARMul_GetCPSR (ARMul_State
* state
)
186 return (CPSR
| state
->Cpsr
);
189 /***************************************************************************\
190 * This routine sets the value of the CPSR *
191 \***************************************************************************/
194 ARMul_SetCPSR (ARMul_State
* state
, ARMword value
)
197 ARMul_CPSRAltered (state
);
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 \***************************************************************************/
206 ARMul_FixCPSR (ARMul_State
* state
, ARMword instr
, ARMword rhs
)
208 state
->Cpsr
= ARMul_GetCPSR (state
);
209 if (state
->Mode
!= USER26MODE
210 && state
->Mode
!= USER32MODE
)
211 { /* In user mode, only write flags */
213 SETPSR_C (state
->Cpsr
, rhs
);
215 SETPSR_X (state
->Cpsr
, rhs
);
217 SETPSR_S (state
->Cpsr
, rhs
);
220 SETPSR_F (state
->Cpsr
, rhs
);
221 ARMul_CPSRAltered (state
);
224 /***************************************************************************\
225 * Get an SPSR from the specified mode *
226 \***************************************************************************/
229 ARMul_GetSPSR (ARMul_State
* state
, ARMword mode
)
231 ARMword bank
= ModeToBank (mode
& MODEBITS
);
233 if (! BANK_CAN_ACCESS_SPSR (bank
))
234 return ARMul_GetCPSR (state
);
236 return state
->Spsr
[bank
];
239 /***************************************************************************\
240 * This routine does a write to an SPSR *
241 \***************************************************************************/
244 ARMul_SetSPSR (ARMul_State
* state
, ARMword mode
, ARMword value
)
246 ARMword bank
= ModeToBank (mode
& MODEBITS
);
248 if (BANK_CAN_ACCESS_SPSR (bank
))
249 state
->Spsr
[bank
] = value
;
252 /***************************************************************************\
253 * This routine does a write to the current SPSR, given an MSR instruction *
254 \***************************************************************************/
257 ARMul_FixSPSR (ARMul_State
* state
, ARMword instr
, ARMword rhs
)
259 if (BANK_CAN_ACCESS_SPSR (state
->Bank
))
262 SETPSR_C (state
->Spsr
[state
->Bank
], rhs
);
264 SETPSR_X (state
->Spsr
[state
->Bank
], rhs
);
266 SETPSR_S (state
->Spsr
[state
->Bank
], rhs
);
268 SETPSR_F (state
->Spsr
[state
->Bank
], rhs
);
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 \***************************************************************************/
278 ARMul_CPSRAltered (ARMul_State
* state
)
282 if (state
->prog32Sig
== LOW
)
283 state
->Cpsr
&= (CCBITS
| INTBITS
| R15MODEBITS
);
285 oldmode
= state
->Mode
;
287 if (state
->Mode
!= (state
->Cpsr
& MODEBITS
))
290 ARMul_SwitchMode (state
, state
->Mode
, state
->Cpsr
& MODEBITS
);
292 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
294 state
->Cpsr
&= ~MODEBITS
;
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
;
309 ASSIGNT ((state
->Cpsr
& TBIT
) != 0);
310 state
->Cpsr
&= ~TBIT
;
313 if (oldmode
> SVC26MODE
)
315 if (state
->Mode
<= SVC26MODE
)
317 state
->Emulate
= CHANGEMODE
;
318 state
->Reg
[15] = ECC
| ER15INT
| EMODE
| R15PC
;
323 if (state
->Mode
> SVC26MODE
)
325 state
->Emulate
= CHANGEMODE
;
326 state
->Reg
[15] = R15PC
;
329 state
->Reg
[15] = ECC
| ER15INT
| EMODE
| R15PC
;
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 \***************************************************************************/
340 ARMul_R15Altered (ARMul_State
* state
)
342 if (state
->Mode
!= R15MODE
)
344 state
->Mode
= ARMul_SwitchMode (state
, state
->Mode
, R15MODE
);
345 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
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);
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 \***************************************************************************/
365 ARMul_SwitchMode (ARMul_State
* state
, ARMword oldmode
, ARMword newmode
)
371 oldbank
= ModeToBank (oldmode
);
372 newbank
= state
->Bank
= ModeToBank (newmode
);
374 if (oldbank
!= newbank
)
375 { /* really need to do it */
377 { /* save away the old registers */
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];
390 for (i
= 8; i
< 15; i
++)
391 state
->RegBank
[FIQBANK
][i
] = state
->Reg
[i
];
394 for (i
= 8; i
< 15; i
++)
395 state
->RegBank
[DUMMYBANK
][i
] = 0;
402 { /* restore the new registers */
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];
415 for (i
= 8; i
< 15; i
++)
416 state
->Reg
[i
] = state
->RegBank
[FIQBANK
][i
];
419 for (i
= 8; i
< 15; i
++)
430 /***************************************************************************\
431 * Given a processor mode, this routine returns the register bank that *
432 * will be accessed in that mode. *
433 \***************************************************************************/
436 ModeToBank (ARMword mode
)
438 static ARMword bankofmode
[] =
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
450 if (mode
>= (sizeof (bankofmode
) / sizeof (bankofmode
[0])))
453 return bankofmode
[mode
];
456 /***************************************************************************\
457 * Returns the register number of the nth register in a reg list. *
458 \***************************************************************************/
461 ARMul_NthReg (ARMword instr
, unsigned number
)
465 for (bit
= 0, upto
= 0; upto
<= number
; bit
++)
471 /***************************************************************************\
472 * Assigns the N and Z flags depending on the value of result *
473 \***************************************************************************/
476 ARMul_NegZero (ARMul_State
* state
, ARMword result
)
483 else if (result
== 0)
495 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
497 AddOverflow (ARMword a
, ARMword b
, ARMword result
)
499 return ((NEG (a
) && NEG (b
) && POS (result
))
500 || (POS (a
) && POS (b
) && NEG (result
)));
503 /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
505 SubOverflow (ARMword a
, ARMword b
, ARMword result
)
507 return ((NEG (a
) && POS (b
) && POS (result
))
508 || (POS (a
) && NEG (b
) && NEG (result
)));
511 /***************************************************************************\
512 * Assigns the C flag after an addition of a and b to give result *
513 \***************************************************************************/
516 ARMul_AddCarry (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
518 ASSIGNC ((NEG (a
) && NEG (b
)) ||
519 (NEG (a
) && POS (result
)) || (NEG (b
) && POS (result
)));
522 /***************************************************************************\
523 * Assigns the V flag after an addition of a and b to give result *
524 \***************************************************************************/
527 ARMul_AddOverflow (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
529 ASSIGNV (AddOverflow (a
, b
, result
));
532 /***************************************************************************\
533 * Assigns the C flag after an subtraction of a and b to give result *
534 \***************************************************************************/
537 ARMul_SubCarry (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
539 ASSIGNC ((NEG (a
) && POS (b
)) ||
540 (NEG (a
) && POS (result
)) || (POS (b
) && POS (result
)));
543 /***************************************************************************\
544 * Assigns the V flag after an subtraction of a and b to give result *
545 \***************************************************************************/
548 ARMul_SubOverflow (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
550 ASSIGNV (SubOverflow (a
, b
, result
));
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 \***************************************************************************/
561 ARMul_LDC (ARMul_State
* state
, ARMword instr
, ARMword address
)
567 if (ADDREXCEPT (address
))
569 INTERNALABORT (address
);
571 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_FIRST
, instr
, 0);
572 while (cpab
== ARMul_BUSY
)
574 ARMul_Icycles (state
, 1, 0);
575 if (IntPending (state
))
577 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
581 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_BUSY
, instr
, 0);
583 if (cpab
== ARMul_CANT
)
588 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_TRANSFER
, instr
, 0);
589 data
= ARMul_LoadWordN (state
, address
);
592 LSBase
= state
->Base
;
593 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_DATA
, instr
, data
);
594 while (cpab
== ARMul_INC
)
597 data
= ARMul_LoadWordN (state
, address
);
598 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_DATA
, instr
, data
);
600 if (state
->abortSig
|| state
->Aborted
)
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 \***************************************************************************/
614 ARMul_STC (ARMul_State
* state
, ARMword instr
, ARMword address
)
620 if (ADDREXCEPT (address
) || VECTORACCESS (address
))
622 INTERNALABORT (address
);
624 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_FIRST
, instr
, &data
);
625 while (cpab
== ARMul_BUSY
)
627 ARMul_Icycles (state
, 1, 0);
628 if (IntPending (state
))
630 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
634 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_BUSY
, instr
, &data
);
636 if (cpab
== ARMul_CANT
)
642 if (ADDREXCEPT (address
) || VECTORACCESS (address
))
644 INTERNALABORT (address
);
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
)
655 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_DATA
, instr
, &data
);
656 ARMul_StoreWordN (state
, address
, data
);
658 if (state
->abortSig
|| state
->Aborted
)
664 /***************************************************************************\
665 * This function does the Busy-Waiting for an MCR instruction. *
666 \***************************************************************************/
669 ARMul_MCR (ARMul_State
* state
, ARMword instr
, ARMword source
)
673 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_FIRST
, instr
, source
);
675 while (cpab
== ARMul_BUSY
)
677 ARMul_Icycles (state
, 1, 0);
679 if (IntPending (state
))
681 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
685 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_BUSY
, instr
, source
);
688 if (cpab
== ARMul_CANT
)
689 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
693 ARMul_Ccycles (state
, 1, 0);
697 /***************************************************************************\
698 * This function does the Busy-Waiting for an MRC instruction. *
699 \***************************************************************************/
702 ARMul_MRC (ARMul_State
* state
, ARMword instr
)
707 cpab
= (state
->MRC
[CPNum
]) (state
, ARMul_FIRST
, instr
, &result
);
708 while (cpab
== ARMul_BUSY
)
710 ARMul_Icycles (state
, 1, 0);
711 if (IntPending (state
))
713 cpab
= (state
->MRC
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
717 cpab
= (state
->MRC
[CPNum
]) (state
, ARMul_BUSY
, instr
, &result
);
719 if (cpab
== ARMul_CANT
)
721 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
722 result
= ECC
; /* Parent will destroy the flags otherwise */
727 ARMul_Ccycles (state
, 1, 0);
728 ARMul_Icycles (state
, 1, 0);
733 /***************************************************************************\
734 * This function does the Busy-Waiting for an CDP instruction. *
735 \***************************************************************************/
738 ARMul_CDP (ARMul_State
* state
, ARMword instr
)
742 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_FIRST
, instr
);
743 while (cpab
== ARMul_BUSY
)
745 ARMul_Icycles (state
, 1, 0);
746 if (IntPending (state
))
748 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
);
752 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_BUSY
, instr
);
754 if (cpab
== ARMul_CANT
)
755 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
760 /***************************************************************************\
761 * This function handles Undefined instructions, as CP isntruction *
762 \***************************************************************************/
765 ARMul_UndefInstr (ARMul_State
* state
, ARMword instr ATTRIBUTE_UNUSED
)
767 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
770 /***************************************************************************\
771 * Return TRUE if an interrupt is pending, FALSE otherwise. *
772 \***************************************************************************/
775 IntPending (ARMul_State
* state
)
777 if (state
->Exception
)
778 { /* Any exceptions */
779 if (state
->NresetSig
== LOW
)
781 ARMul_Abort (state
, ARMul_ResetV
);
784 else if (!state
->NfiqSig
&& !FFLAG
)
786 ARMul_Abort (state
, ARMul_FIQV
);
789 else if (!state
->NirqSig
&& !IFLAG
)
791 ARMul_Abort (state
, ARMul_IRQV
);
798 /***************************************************************************\
799 * Align a word access to a non word boundary *
800 \***************************************************************************/
803 ARMul_Align (state
, address
, data
)
804 ARMul_State
* state ATTRIBUTE_UNUSED
;
808 /* This code assumes the address is really unaligned,
809 as a shift by 32 is undefined in C. */
811 address
= (address
& 3) << 3; /* get the word address */
812 return ((data
>> address
) | (data
<< (32 - address
))); /* rot right */
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 \***************************************************************************/
823 ARMul_ScheduleEvent (ARMul_State
* state
, unsigned long delay
,
827 struct EventNode
*event
;
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
));
834 event
->next
= *(state
->EventPtr
+ when
);
835 *(state
->EventPtr
+ when
) = event
;
838 /***************************************************************************\
839 * This routine is called at the beginning of every cycle, to envoke *
840 * scheduled events. *
841 \***************************************************************************/
844 ARMul_EnvokeEvent (ARMul_State
* state
)
846 static unsigned long then
;
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
);
860 EnvokeList (ARMul_State
* state
, unsigned long from
, unsigned long to
)
861 /* envokes all the entries in a range */
863 struct EventNode
*anevent
;
865 for (; from
<= to
; from
++)
867 anevent
= *(state
->EventPtr
+ from
);
870 (anevent
->func
) (state
);
872 anevent
= anevent
->next
;
874 *(state
->EventPtr
+ from
) = NULL
;
878 /***************************************************************************\
879 * This routine is returns the number of clock ticks since the last reset. *
880 \***************************************************************************/
883 ARMul_Time (ARMul_State
* state
)
885 return (state
->NumScycles
+ state
->NumNcycles
+
886 state
->NumIcycles
+ state
->NumCcycles
+ state
->NumFcycles
);