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. */
21 /***************************************************************************\
22 * Definitions for the support routines *
23 \***************************************************************************/
25 ARMword
ARMul_GetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
);
26 void ARMul_SetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
,
28 ARMword
ARMul_GetPC (ARMul_State
* state
);
29 ARMword
ARMul_GetNextPC (ARMul_State
* state
);
30 void ARMul_SetPC (ARMul_State
* state
, ARMword value
);
31 ARMword
ARMul_GetR15 (ARMul_State
* state
);
32 void ARMul_SetR15 (ARMul_State
* state
, ARMword value
);
34 ARMword
ARMul_GetCPSR (ARMul_State
* state
);
35 void ARMul_SetCPSR (ARMul_State
* state
, ARMword value
);
36 void ARMul_FixCPSR (ARMul_State
* state
, ARMword instr
, ARMword rhs
);
37 ARMword
ARMul_GetSPSR (ARMul_State
* state
, ARMword mode
);
38 void ARMul_SetSPSR (ARMul_State
* state
, ARMword mode
, ARMword value
);
39 void ARMul_FixSPSR (ARMul_State
* state
, ARMword instr
, ARMword rhs
);
41 void ARMul_CPSRAltered (ARMul_State
* state
);
42 void ARMul_R15Altered (ARMul_State
* state
);
44 ARMword
ARMul_SwitchMode (ARMul_State
* state
, ARMword oldmode
,
46 static ARMword
ModeToBank (ARMul_State
* state
, ARMword mode
);
48 unsigned ARMul_NthReg (ARMword instr
, unsigned number
);
50 void ARMul_NegZero (ARMul_State
* state
, ARMword result
);
51 void ARMul_AddCarry (ARMul_State
* state
, ARMword a
, ARMword b
,
53 void ARMul_AddOverflow (ARMul_State
* state
, ARMword a
, ARMword b
,
55 void ARMul_SubCarry (ARMul_State
* state
, ARMword a
, ARMword b
,
57 void ARMul_SubOverflow (ARMul_State
* state
, ARMword a
, ARMword b
,
60 void ARMul_LDC (ARMul_State
* state
, ARMword instr
, ARMword address
);
61 void ARMul_STC (ARMul_State
* state
, ARMword instr
, ARMword address
);
62 void ARMul_MCR (ARMul_State
* state
, ARMword instr
, ARMword source
);
63 ARMword
ARMul_MRC (ARMul_State
* state
, ARMword instr
);
64 void ARMul_CDP (ARMul_State
* state
, ARMword instr
);
65 void ARMul_UndefInstr (ARMul_State
* state
, ARMword instr
);
66 unsigned IntPending (ARMul_State
* state
);
68 ARMword
ARMul_Align (ARMul_State
* state
, ARMword address
, ARMword data
);
70 void ARMul_ScheduleEvent (ARMul_State
* state
, unsigned long delay
,
72 void ARMul_EnvokeEvent (ARMul_State
* state
);
73 unsigned long ARMul_Time (ARMul_State
* state
);
74 static void EnvokeList (ARMul_State
* state
, unsigned long from
,
78 { /* An event list node */
79 unsigned (*func
) (); /* The function to call */
80 struct EventNode
*next
;
83 /***************************************************************************\
84 * This routine returns the value of a register from a mode. *
85 \***************************************************************************/
88 ARMul_GetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
)
91 if (mode
!= state
->Mode
)
92 return (state
->RegBank
[ModeToBank (state
, (ARMword
) mode
)][reg
]);
94 return (state
->Reg
[reg
]);
97 /***************************************************************************\
98 * This routine sets the value of a register for a mode. *
99 \***************************************************************************/
102 ARMul_SetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
, ARMword value
)
105 if (mode
!= state
->Mode
)
106 state
->RegBank
[ModeToBank (state
, (ARMword
) mode
)][reg
] = value
;
108 state
->Reg
[reg
] = value
;
111 /***************************************************************************\
112 * This routine returns the value of the PC, mode independently. *
113 \***************************************************************************/
116 ARMul_GetPC (ARMul_State
* state
)
118 if (state
->Mode
> SVC26MODE
)
119 return (state
->Reg
[15]);
124 /***************************************************************************\
125 * This routine returns the value of the PC, mode independently. *
126 \***************************************************************************/
129 ARMul_GetNextPC (ARMul_State
* state
)
131 if (state
->Mode
> SVC26MODE
)
132 return (state
->Reg
[15] + isize
);
134 return ((state
->Reg
[15] + isize
) & R15PCBITS
);
137 /***************************************************************************\
138 * This routine sets the value of the PC. *
139 \***************************************************************************/
142 ARMul_SetPC (ARMul_State
* state
, ARMword value
)
145 state
->Reg
[15] = value
& PCBITS
;
147 state
->Reg
[15] = R15CCINTMODE
| (value
& R15PCBITS
);
151 /***************************************************************************\
152 * This routine returns the value of register 15, mode independently. *
153 \***************************************************************************/
156 ARMul_GetR15 (ARMul_State
* state
)
158 if (state
->Mode
> SVC26MODE
)
159 return (state
->Reg
[15]);
161 return (R15PC
| ECC
| ER15INT
| EMODE
);
164 /***************************************************************************\
165 * This routine sets the value of Register 15. *
166 \***************************************************************************/
169 ARMul_SetR15 (ARMul_State
* state
, ARMword value
)
172 state
->Reg
[15] = value
& PCBITS
;
175 state
->Reg
[15] = value
;
176 ARMul_R15Altered (state
);
181 /***************************************************************************\
182 * This routine returns the value of the CPSR *
183 \***************************************************************************/
186 ARMul_GetCPSR (ARMul_State
* state
)
191 /***************************************************************************\
192 * This routine sets the value of the CPSR *
193 \***************************************************************************/
196 ARMul_SetCPSR (ARMul_State
* state
, ARMword value
)
199 SETPSR (state
->Cpsr
, value
);
200 ARMul_CPSRAltered (state
);
203 /***************************************************************************\
204 * This routine does all the nasty bits involved in a write to the CPSR, *
205 * including updating the register bank, given a MSR instruction. *
206 \***************************************************************************/
209 ARMul_FixCPSR (ARMul_State
* state
, ARMword instr
, ARMword rhs
)
212 if (state
->Bank
== USERBANK
)
213 { /* Only write flags in user mode */
216 SETCC (state
->Cpsr
, rhs
);
220 { /* Not a user mode */
221 if (BITS (16, 19) == 9)
222 SETPSR (state
->Cpsr
, rhs
);
224 SETINTMODE (state
->Cpsr
, rhs
);
226 SETCC (state
->Cpsr
, rhs
);
228 ARMul_CPSRAltered (state
);
231 /***************************************************************************\
232 * Get an SPSR from the specified mode *
233 \***************************************************************************/
236 ARMul_GetSPSR (ARMul_State
* state
, ARMword mode
)
238 ARMword bank
= ModeToBank (state
, mode
& MODEBITS
);
239 if (bank
== USERBANK
|| bank
== DUMMYBANK
)
242 return (state
->Spsr
[bank
]);
245 /***************************************************************************\
246 * This routine does a write to an SPSR *
247 \***************************************************************************/
250 ARMul_SetSPSR (ARMul_State
* state
, ARMword mode
, ARMword value
)
252 ARMword bank
= ModeToBank (state
, mode
& MODEBITS
);
253 if (bank
!= USERBANK
&& bank
!= DUMMYBANK
)
254 state
->Spsr
[bank
] = value
;
257 /***************************************************************************\
258 * This routine does a write to the current SPSR, given an MSR instruction *
259 \***************************************************************************/
262 ARMul_FixSPSR (ARMul_State
* state
, ARMword instr
, ARMword rhs
)
264 if (state
->Bank
!= USERBANK
&& state
->Bank
!= DUMMYBANK
)
266 if (BITS (16, 19) == 9)
267 SETPSR (state
->Spsr
[state
->Bank
], rhs
);
269 SETINTMODE (state
->Spsr
[state
->Bank
], rhs
);
271 SETCC (state
->Spsr
[state
->Bank
], rhs
);
275 /***************************************************************************\
276 * This routine updates the state of the emulator after the Cpsr has been *
277 * changed. Both the processor flags and register bank are updated. *
278 \***************************************************************************/
281 ARMul_CPSRAltered (ARMul_State
* state
)
285 if (state
->prog32Sig
== LOW
)
286 state
->Cpsr
&= (CCBITS
| INTBITS
| R15MODEBITS
);
287 oldmode
= state
->Mode
;
288 if (state
->Mode
!= (state
->Cpsr
& MODEBITS
))
291 ARMul_SwitchMode (state
, state
->Mode
, state
->Cpsr
& MODEBITS
);
292 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
295 ASSIGNINT (state
->Cpsr
& INTBITS
);
296 ASSIGNN ((state
->Cpsr
& NBIT
) != 0);
297 ASSIGNZ ((state
->Cpsr
& ZBIT
) != 0);
298 ASSIGNC ((state
->Cpsr
& CBIT
) != 0);
299 ASSIGNV ((state
->Cpsr
& VBIT
) != 0);
301 ASSIGNT ((state
->Cpsr
& TBIT
) != 0);
304 if (oldmode
> SVC26MODE
)
306 if (state
->Mode
<= SVC26MODE
)
308 state
->Emulate
= CHANGEMODE
;
309 state
->Reg
[15] = ECC
| ER15INT
| EMODE
| R15PC
;
314 if (state
->Mode
> SVC26MODE
)
316 state
->Emulate
= CHANGEMODE
;
317 state
->Reg
[15] = R15PC
;
320 state
->Reg
[15] = ECC
| ER15INT
| EMODE
| R15PC
;
325 /***************************************************************************\
326 * This routine updates the state of the emulator after register 15 has *
327 * been changed. Both the processor flags and register bank are updated. *
328 * This routine should only be called from a 26 bit mode. *
329 \***************************************************************************/
332 ARMul_R15Altered (ARMul_State
* state
)
334 if (state
->Mode
!= R15MODE
)
336 state
->Mode
= ARMul_SwitchMode (state
, state
->Mode
, R15MODE
);
337 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
339 if (state
->Mode
> SVC26MODE
)
340 state
->Emulate
= CHANGEMODE
;
341 ASSIGNR15INT (R15INT
);
342 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
343 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
344 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
345 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
348 /***************************************************************************\
349 * This routine controls the saving and restoring of registers across mode *
350 * changes. The regbank matrix is largely unused, only rows 13 and 14 are *
351 * used across all modes, 8 to 14 are used for FIQ, all others use the USER *
352 * column. It's easier this way. old and new parameter are modes numbers. *
353 * Notice the side effect of changing the Bank variable. *
354 \***************************************************************************/
357 ARMul_SwitchMode (ARMul_State
* state
, ARMword oldmode
, ARMword newmode
)
361 oldmode
= ModeToBank (state
, oldmode
);
362 state
->Bank
= ModeToBank (state
, newmode
);
363 if (oldmode
!= state
->Bank
)
364 { /* really need to do it */
366 { /* save away the old registers */
372 if (state
->Bank
== FIQBANK
)
373 for (i
= 8; i
< 13; i
++)
374 state
->RegBank
[USERBANK
][i
] = state
->Reg
[i
];
375 state
->RegBank
[oldmode
][13] = state
->Reg
[13];
376 state
->RegBank
[oldmode
][14] = state
->Reg
[14];
379 for (i
= 8; i
< 15; i
++)
380 state
->RegBank
[FIQBANK
][i
] = state
->Reg
[i
];
383 for (i
= 8; i
< 15; i
++)
384 state
->RegBank
[DUMMYBANK
][i
] = 0;
389 { /* restore the new registers */
395 if (oldmode
== FIQBANK
)
396 for (i
= 8; i
< 13; i
++)
397 state
->Reg
[i
] = state
->RegBank
[USERBANK
][i
];
398 state
->Reg
[13] = state
->RegBank
[state
->Bank
][13];
399 state
->Reg
[14] = state
->RegBank
[state
->Bank
][14];
402 for (i
= 8; i
< 15; i
++)
403 state
->Reg
[i
] = state
->RegBank
[FIQBANK
][i
];
406 for (i
= 8; i
< 15; i
++)
414 /***************************************************************************\
415 * Given a processor mode, this routine returns the register bank that *
416 * will be accessed in that mode. *
417 \***************************************************************************/
420 ModeToBank (ARMul_State
* state
, ARMword mode
)
422 static ARMword bankofmode
[] = { USERBANK
, FIQBANK
, IRQBANK
, SVCBANK
,
423 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, DUMMYBANK
,
424 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, DUMMYBANK
,
425 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, DUMMYBANK
,
426 USERBANK
, FIQBANK
, IRQBANK
, SVCBANK
,
427 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, ABORTBANK
,
428 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, UNDEFBANK
431 if (mode
> UNDEF32MODE
)
434 return (bankofmode
[mode
]);
437 /***************************************************************************\
438 * Returns the register number of the nth register in a reg list. *
439 \***************************************************************************/
442 ARMul_NthReg (ARMword instr
, unsigned number
)
446 for (bit
= 0, upto
= 0; upto
<= number
; bit
++)
452 /***************************************************************************\
453 * Assigns the N and Z flags depending on the value of result *
454 \***************************************************************************/
457 ARMul_NegZero (ARMul_State
* state
, ARMword result
)
464 else if (result
== 0)
476 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
478 AddOverflow (ARMword a
, ARMword b
, ARMword result
)
480 return ((NEG (a
) && NEG (b
) && POS (result
))
481 || (POS (a
) && POS (b
) && NEG (result
)));
484 /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
486 SubOverflow (ARMword a
, ARMword b
, ARMword result
)
488 return ((NEG (a
) && POS (b
) && POS (result
))
489 || (POS (a
) && NEG (b
) && NEG (result
)));
492 /***************************************************************************\
493 * Assigns the C flag after an addition of a and b to give result *
494 \***************************************************************************/
497 ARMul_AddCarry (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
499 ASSIGNC ((NEG (a
) && NEG (b
)) ||
500 (NEG (a
) && POS (result
)) || (NEG (b
) && POS (result
)));
503 /***************************************************************************\
504 * Assigns the V flag after an addition of a and b to give result *
505 \***************************************************************************/
508 ARMul_AddOverflow (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
510 ASSIGNV (AddOverflow (a
, b
, result
));
513 /***************************************************************************\
514 * Assigns the C flag after an subtraction of a and b to give result *
515 \***************************************************************************/
518 ARMul_SubCarry (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
520 ASSIGNC ((NEG (a
) && POS (b
)) ||
521 (NEG (a
) && POS (result
)) || (POS (b
) && POS (result
)));
524 /***************************************************************************\
525 * Assigns the V flag after an subtraction of a and b to give result *
526 \***************************************************************************/
529 ARMul_SubOverflow (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
531 ASSIGNV (SubOverflow (a
, b
, result
));
534 /***************************************************************************\
535 * This function does the work of generating the addresses used in an *
536 * LDC instruction. The code here is always post-indexed, it's up to the *
537 * caller to get the input address correct and to handle base register *
538 * modification. It also handles the Busy-Waiting. *
539 \***************************************************************************/
542 ARMul_LDC (ARMul_State
* state
, ARMword instr
, ARMword address
)
548 if (ADDREXCEPT (address
))
550 INTERNALABORT (address
);
552 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_FIRST
, instr
, 0);
553 while (cpab
== ARMul_BUSY
)
555 ARMul_Icycles (state
, 1, 0);
556 if (IntPending (state
))
558 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
562 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_BUSY
, instr
, 0);
564 if (cpab
== ARMul_CANT
)
569 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_TRANSFER
, instr
, 0);
570 data
= ARMul_LoadWordN (state
, address
);
573 LSBase
= state
->Base
;
574 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_DATA
, instr
, data
);
575 while (cpab
== ARMul_INC
)
578 data
= ARMul_LoadWordN (state
, address
);
579 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_DATA
, instr
, data
);
581 if (state
->abortSig
|| state
->Aborted
)
587 /***************************************************************************\
588 * This function does the work of generating the addresses used in an *
589 * STC instruction. The code here is always post-indexed, it's up to the *
590 * caller to get the input address correct and to handle base register *
591 * modification. It also handles the Busy-Waiting. *
592 \***************************************************************************/
595 ARMul_STC (ARMul_State
* state
, ARMword instr
, ARMword address
)
601 if (ADDREXCEPT (address
) || VECTORACCESS (address
))
603 INTERNALABORT (address
);
605 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_FIRST
, instr
, &data
);
606 while (cpab
== ARMul_BUSY
)
608 ARMul_Icycles (state
, 1, 0);
609 if (IntPending (state
))
611 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
615 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_BUSY
, instr
, &data
);
617 if (cpab
== ARMul_CANT
)
623 if (ADDREXCEPT (address
) || VECTORACCESS (address
))
625 INTERNALABORT (address
);
630 LSBase
= state
->Base
;
631 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_DATA
, instr
, &data
);
632 ARMul_StoreWordN (state
, address
, data
);
633 while (cpab
== ARMul_INC
)
636 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_DATA
, instr
, &data
);
637 ARMul_StoreWordN (state
, address
, data
);
639 if (state
->abortSig
|| state
->Aborted
)
645 /***************************************************************************\
646 * This function does the Busy-Waiting for an MCR instruction. *
647 \***************************************************************************/
650 ARMul_MCR (ARMul_State
* state
, ARMword instr
, ARMword source
)
654 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_FIRST
, instr
, source
);
655 while (cpab
== ARMul_BUSY
)
657 ARMul_Icycles (state
, 1, 0);
658 if (IntPending (state
))
660 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
664 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_BUSY
, instr
, source
);
666 if (cpab
== ARMul_CANT
)
667 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
671 ARMul_Ccycles (state
, 1, 0);
675 /***************************************************************************\
676 * This function does the Busy-Waiting for an MRC instruction. *
677 \***************************************************************************/
680 ARMul_MRC (ARMul_State
* state
, ARMword instr
)
685 cpab
= (state
->MRC
[CPNum
]) (state
, ARMul_FIRST
, instr
, &result
);
686 while (cpab
== ARMul_BUSY
)
688 ARMul_Icycles (state
, 1, 0);
689 if (IntPending (state
))
691 cpab
= (state
->MRC
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
695 cpab
= (state
->MRC
[CPNum
]) (state
, ARMul_BUSY
, instr
, &result
);
697 if (cpab
== ARMul_CANT
)
699 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
700 result
= ECC
; /* Parent will destroy the flags otherwise */
705 ARMul_Ccycles (state
, 1, 0);
706 ARMul_Icycles (state
, 1, 0);
711 /***************************************************************************\
712 * This function does the Busy-Waiting for an CDP instruction. *
713 \***************************************************************************/
716 ARMul_CDP (ARMul_State
* state
, ARMword instr
)
720 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_FIRST
, instr
);
721 while (cpab
== ARMul_BUSY
)
723 ARMul_Icycles (state
, 1, 0);
724 if (IntPending (state
))
726 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
);
730 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_BUSY
, instr
);
732 if (cpab
== ARMul_CANT
)
733 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
738 /***************************************************************************\
739 * This function handles Undefined instructions, as CP isntruction *
740 \***************************************************************************/
743 ARMul_UndefInstr (ARMul_State
* state
, ARMword instr
)
745 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
748 /***************************************************************************\
749 * Return TRUE if an interrupt is pending, FALSE otherwise. *
750 \***************************************************************************/
753 IntPending (ARMul_State
* state
)
755 if (state
->Exception
)
756 { /* Any exceptions */
757 if (state
->NresetSig
== LOW
)
759 ARMul_Abort (state
, ARMul_ResetV
);
762 else if (!state
->NfiqSig
&& !FFLAG
)
764 ARMul_Abort (state
, ARMul_FIQV
);
767 else if (!state
->NirqSig
&& !IFLAG
)
769 ARMul_Abort (state
, ARMul_IRQV
);
776 /***************************************************************************\
777 * Align a word access to a non word boundary *
778 \***************************************************************************/
781 ARMul_Align (ARMul_State
* state
, ARMword address
, ARMword data
)
782 { /* this code assumes the address is really unaligned,
783 as a shift by 32 is undefined in C */
785 address
= (address
& 3) << 3; /* get the word address */
786 return ((data
>> address
) | (data
<< (32 - address
))); /* rot right */
789 /***************************************************************************\
790 * This routine is used to call another routine after a certain number of *
791 * cycles have been executed. The first parameter is the number of cycles *
792 * delay before the function is called, the second argument is a pointer *
793 * to the function. A delay of zero doesn't work, just call the function. *
794 \***************************************************************************/
797 ARMul_ScheduleEvent (ARMul_State
* state
, unsigned long delay
,
801 struct EventNode
*event
;
803 if (state
->EventSet
++ == 0)
804 state
->Now
= ARMul_Time (state
);
805 when
= (state
->Now
+ delay
) % EVENTLISTSIZE
;
806 event
= (struct EventNode
*) malloc (sizeof (struct EventNode
));
808 event
->next
= *(state
->EventPtr
+ when
);
809 *(state
->EventPtr
+ when
) = event
;
812 /***************************************************************************\
813 * This routine is called at the beginning of every cycle, to envoke *
814 * scheduled events. *
815 \***************************************************************************/
818 ARMul_EnvokeEvent (ARMul_State
* state
)
820 static unsigned long then
;
823 state
->Now
= ARMul_Time (state
) % EVENTLISTSIZE
;
824 if (then
< state
->Now
) /* schedule events */
825 EnvokeList (state
, then
, state
->Now
);
826 else if (then
> state
->Now
)
827 { /* need to wrap around the list */
828 EnvokeList (state
, then
, EVENTLISTSIZE
- 1L);
829 EnvokeList (state
, 0L, state
->Now
);
834 EnvokeList (ARMul_State
* state
, unsigned long from
, unsigned long to
)
835 /* envokes all the entries in a range */
837 struct EventNode
*anevent
;
839 for (; from
<= to
; from
++)
841 anevent
= *(state
->EventPtr
+ from
);
844 (anevent
->func
) (state
);
846 anevent
= anevent
->next
;
848 *(state
->EventPtr
+ from
) = NULL
;
852 /***************************************************************************\
853 * This routine is returns the number of clock ticks since the last reset. *
854 \***************************************************************************/
857 ARMul_Time (ARMul_State
* state
)
859 return (state
->NumScycles
+ state
->NumNcycles
+
860 state
->NumIcycles
+ state
->NumCcycles
+ state
->NumFcycles
);
This page took 0.051788 seconds and 4 git commands to generate.