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, ARMword value) ;
27 ARMword ARMul_GetPC(ARMul_State *state) ;
28 ARMword ARMul_GetNextPC(ARMul_State *state) ;
29 void ARMul_SetPC(ARMul_State *state, ARMword value) ;
30 ARMword ARMul_GetR15(ARMul_State *state) ;
31 void ARMul_SetR15(ARMul_State *state, ARMword value) ;
33 ARMword ARMul_GetCPSR(ARMul_State *state) ;
34 void ARMul_SetCPSR(ARMul_State *state, ARMword value) ;
35 void ARMul_FixCPSR(ARMul_State *state, ARMword instr, ARMword rhs) ;
36 ARMword ARMul_GetSPSR(ARMul_State *state, ARMword mode) ;
37 void ARMul_SetSPSR(ARMul_State *state, ARMword mode, ARMword value) ;
38 void ARMul_FixSPSR(ARMul_State *state, ARMword instr, ARMword rhs) ;
40 void ARMul_CPSRAltered(ARMul_State *state) ;
41 void ARMul_R15Altered(ARMul_State *state) ;
43 ARMword ARMul_SwitchMode(ARMul_State *state,ARMword oldmode, ARMword newmode) ;
44 static ARMword ModeToBank(ARMul_State *state,ARMword mode) ;
46 unsigned ARMul_NthReg(ARMword instr, unsigned number) ;
48 void ARMul_NegZero(ARMul_State *state, ARMword result) ;
49 void ARMul_AddCarry(ARMul_State *state, ARMword a, ARMword b, ARMword result) ;
50 void ARMul_AddOverflow(ARMul_State *state, ARMword a, ARMword b, ARMword result) ;
51 void ARMul_SubCarry(ARMul_State *state, ARMword a, ARMword b, ARMword result) ;
52 void ARMul_SubOverflow(ARMul_State *state, ARMword a, ARMword b, ARMword result) ;
54 void ARMul_LDC(ARMul_State *state,ARMword instr,ARMword address) ;
55 void ARMul_STC(ARMul_State *state,ARMword instr,ARMword address) ;
56 void ARMul_MCR(ARMul_State *state,ARMword instr, ARMword source) ;
57 ARMword ARMul_MRC(ARMul_State *state,ARMword instr) ;
58 void ARMul_CDP(ARMul_State *state,ARMword instr) ;
59 void ARMul_UndefInstr(ARMul_State *state,ARMword instr) ;
60 unsigned IntPending(ARMul_State *state) ;
62 ARMword ARMul_Align(ARMul_State *state, ARMword address, ARMword data) ;
64 void ARMul_ScheduleEvent(ARMul_State *state, unsigned long delay,
66 void ARMul_EnvokeEvent(ARMul_State *state) ;
67 unsigned long ARMul_Time(ARMul_State *state) ;
68 static void EnvokeList(ARMul_State *state, unsigned long from, unsigned long to) ;
70 struct EventNode { /* An event list node */
71 unsigned (*func)() ; /* The function to call */
72 struct EventNode *next ;
75 /***************************************************************************\
76 * This routine returns the value of a register from a mode. *
77 \***************************************************************************/
79 ARMword ARMul_GetReg(ARMul_State *state, unsigned mode, unsigned reg)
81 if (mode != state->Mode)
82 return(state->RegBank[ModeToBank(state,(ARMword)mode)][reg]) ;
84 return(state->Reg[reg]) ;
87 /***************************************************************************\
88 * This routine sets the value of a register for a mode. *
89 \***************************************************************************/
91 void ARMul_SetReg(ARMul_State *state, unsigned mode, unsigned reg, ARMword value)
93 if (mode != state->Mode)
94 state->RegBank[ModeToBank(state,(ARMword)mode)][reg] = value ;
96 state->Reg[reg] = value ;
99 /***************************************************************************\
100 * This routine returns the value of the PC, mode independently. *
101 \***************************************************************************/
103 ARMword ARMul_GetPC(ARMul_State *state)
104 {if (state->Mode > SVC26MODE)
105 return(state->Reg[15]) ;
110 /***************************************************************************\
111 * This routine returns the value of the PC, mode independently. *
112 \***************************************************************************/
114 ARMword ARMul_GetNextPC(ARMul_State *state)
115 {if (state->Mode > SVC26MODE)
116 return(state->Reg[15] + isize) ;
118 return((state->Reg[15] + isize) & R15PCBITS) ;
121 /***************************************************************************\
122 * This routine sets the value of the PC. *
123 \***************************************************************************/
125 void ARMul_SetPC(ARMul_State *state, ARMword value)
126 {if (ARMul_MODE32BIT)
127 state->Reg[15] = value & PCBITS ;
129 state->Reg[15] = R15CCINTMODE | (value & R15PCBITS) ;
133 /***************************************************************************\
134 * This routine returns the value of register 15, mode independently. *
135 \***************************************************************************/
137 ARMword ARMul_GetR15(ARMul_State *state)
138 {if (state->Mode > SVC26MODE)
139 return(state->Reg[15]) ;
141 return(R15PC | ECC | ER15INT | EMODE) ;
144 /***************************************************************************\
145 * This routine sets the value of Register 15. *
146 \***************************************************************************/
148 void ARMul_SetR15(ARMul_State *state, ARMword value)
151 state->Reg[15] = value & PCBITS ;
153 state->Reg[15] = value ;
154 ARMul_R15Altered(state) ;
159 /***************************************************************************\
160 * This routine returns the value of the CPSR *
161 \***************************************************************************/
163 ARMword ARMul_GetCPSR(ARMul_State *state)
168 /***************************************************************************\
169 * This routine sets the value of the CPSR *
170 \***************************************************************************/
172 void ARMul_SetCPSR(ARMul_State *state, ARMword value)
173 {state->Cpsr = CPSR ;
174 SETPSR(state->Cpsr,value) ;
175 ARMul_CPSRAltered(state) ;
178 /***************************************************************************\
179 * This routine does all the nasty bits involved in a write to the CPSR, *
180 * including updating the register bank, given a MSR instruction. *
181 \***************************************************************************/
183 void ARMul_FixCPSR(ARMul_State *state, ARMword instr, ARMword rhs)
184 {state->Cpsr = CPSR ;
185 if (state->Bank==USERBANK) { /* Only write flags in user mode */
187 SETCC(state->Cpsr,rhs) ;
190 else { /* Not a user mode */
191 if (BITS(16,19)==9) SETPSR(state->Cpsr,rhs) ;
192 else if (BIT(16)) SETINTMODE(state->Cpsr,rhs) ;
193 else if (BIT(19)) SETCC(state->Cpsr,rhs) ;
195 ARMul_CPSRAltered(state) ;
198 /***************************************************************************\
199 * Get an SPSR from the specified mode *
200 \***************************************************************************/
202 ARMword ARMul_GetSPSR(ARMul_State *state, ARMword mode)
203 {ARMword bank = ModeToBank(state,mode & MODEBITS) ;
204 if (bank == USERBANK || bank == DUMMYBANK)
207 return(state->Spsr[bank]) ;
210 /***************************************************************************\
211 * This routine does a write to an SPSR *
212 \***************************************************************************/
214 void ARMul_SetSPSR(ARMul_State *state, ARMword mode, ARMword value)
215 {ARMword bank = ModeToBank(state,mode & MODEBITS) ;
216 if (bank != USERBANK && bank !=DUMMYBANK)
217 state->Spsr[bank] = value ;
220 /***************************************************************************\
221 * This routine does a write to the current SPSR, given an MSR instruction *
222 \***************************************************************************/
224 void ARMul_FixSPSR(ARMul_State *state, ARMword instr, ARMword rhs)
225 {if (state->Bank != USERBANK && state->Bank !=DUMMYBANK) {
226 if (BITS(16,19)==9) SETPSR(state->Spsr[state->Bank],rhs) ;
227 else if (BIT(16)) SETINTMODE(state->Spsr[state->Bank],rhs) ;
228 else if (BIT(19)) SETCC(state->Spsr[state->Bank],rhs) ;
232 /***************************************************************************\
233 * This routine updates the state of the emulator after the Cpsr has been *
234 * changed. Both the processor flags and register bank are updated. *
235 \***************************************************************************/
237 void ARMul_CPSRAltered(ARMul_State *state)
240 if (state->prog32Sig == LOW)
241 state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS) ;
242 oldmode = state->Mode ;
243 if (state->Mode != (state->Cpsr & MODEBITS)) {
244 state->Mode = ARMul_SwitchMode(state,state->Mode,state->Cpsr & MODEBITS) ;
245 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
248 ASSIGNINT(state->Cpsr & INTBITS) ;
249 ASSIGNN((state->Cpsr & NBIT) != 0) ;
250 ASSIGNZ((state->Cpsr & ZBIT) != 0) ;
251 ASSIGNC((state->Cpsr & CBIT) != 0) ;
252 ASSIGNV((state->Cpsr & VBIT) != 0) ;
254 ASSIGNT((state->Cpsr & TBIT) != 0);
257 if (oldmode > SVC26MODE) {
258 if (state->Mode <= SVC26MODE) {
259 state->Emulate = CHANGEMODE ;
260 state->Reg[15] = ECC | ER15INT | EMODE | R15PC ;
264 if (state->Mode > SVC26MODE) {
265 state->Emulate = CHANGEMODE ;
266 state->Reg[15] = R15PC ;
269 state->Reg[15] = ECC | ER15INT | EMODE | R15PC ;
274 /***************************************************************************\
275 * This routine updates the state of the emulator after register 15 has *
276 * been changed. Both the processor flags and register bank are updated. *
277 * This routine should only be called from a 26 bit mode. *
278 \***************************************************************************/
280 void ARMul_R15Altered(ARMul_State *state)
282 if (state->Mode != R15MODE) {
283 state->Mode = ARMul_SwitchMode(state,state->Mode,R15MODE) ;
284 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
286 if (state->Mode > SVC26MODE)
287 state->Emulate = CHANGEMODE ;
288 ASSIGNR15INT(R15INT) ;
289 ASSIGNN((state->Reg[15] & NBIT) != 0) ;
290 ASSIGNZ((state->Reg[15] & ZBIT) != 0) ;
291 ASSIGNC((state->Reg[15] & CBIT) != 0) ;
292 ASSIGNV((state->Reg[15] & VBIT) != 0) ;
295 /***************************************************************************\
296 * This routine controls the saving and restoring of registers across mode *
297 * changes. The regbank matrix is largely unused, only rows 13 and 14 are *
298 * used across all modes, 8 to 14 are used for FIQ, all others use the USER *
299 * column. It's easier this way. old and new parameter are modes numbers. *
300 * Notice the side effect of changing the Bank variable. *
301 \***************************************************************************/
303 ARMword ARMul_SwitchMode(ARMul_State *state,ARMword oldmode, ARMword newmode)
306 oldmode = ModeToBank(state,oldmode) ;
307 state->Bank = ModeToBank(state,newmode) ;
308 if (oldmode != state->Bank) { /* really need to do it */
309 switch (oldmode) { /* save away the old registers */
314 case UNDEFBANK : if (state->Bank == FIQBANK)
315 for (i = 8 ; i < 13 ; i++)
316 state->RegBank[USERBANK][i] = state->Reg[i] ;
317 state->RegBank[oldmode][13] = state->Reg[13] ;
318 state->RegBank[oldmode][14] = state->Reg[14] ;
320 case FIQBANK : for (i = 8 ; i < 15 ; i++)
321 state->RegBank[FIQBANK][i] = state->Reg[i] ;
323 case DUMMYBANK : for (i = 8 ; i < 15 ; i++)
324 state->RegBank[DUMMYBANK][i] = 0 ;
328 switch (state->Bank) { /* restore the new registers */
333 case UNDEFBANK : if (oldmode == FIQBANK)
334 for (i = 8 ; i < 13 ; i++)
335 state->Reg[i] = state->RegBank[USERBANK][i] ;
336 state->Reg[13] = state->RegBank[state->Bank][13] ;
337 state->Reg[14] = state->RegBank[state->Bank][14] ;
339 case FIQBANK : for (i = 8 ; i < 15 ; i++)
340 state->Reg[i] = state->RegBank[FIQBANK][i] ;
342 case DUMMYBANK : for (i = 8 ; i < 15 ; i++)
350 /***************************************************************************\
351 * Given a processor mode, this routine returns the register bank that *
352 * will be accessed in that mode. *
353 \***************************************************************************/
355 static ARMword ModeToBank(ARMul_State *state, ARMword mode)
356 {static ARMword bankofmode[] = {USERBANK, FIQBANK, IRQBANK, SVCBANK,
357 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
358 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
359 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
360 USERBANK, FIQBANK, IRQBANK, SVCBANK,
361 DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
362 DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK
365 if (mode > UNDEF32MODE)
368 return(bankofmode[mode]) ;
371 /***************************************************************************\
372 * Returns the register number of the nth register in a reg list. *
373 \***************************************************************************/
375 unsigned ARMul_NthReg(ARMword instr, unsigned number)
376 {unsigned bit, upto ;
378 for (bit = 0, upto = 0 ; upto <= number ; bit++)
379 if (BIT(bit)) upto++ ;
383 /***************************************************************************\
384 * Assigns the N and Z flags depending on the value of result *
385 \***************************************************************************/
387 void ARMul_NegZero(ARMul_State *state, ARMword result)
389 if (NEG(result)) { SETN ; CLEARZ ; }
390 else if (result == 0) { CLEARN ; SETZ ; }
391 else { CLEARN ; CLEARZ ; } ;
394 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
395 int AddOverflow (ARMword a, ARMword b, ARMword result)
397 return ((NEG (a) && NEG (b) && POS (result))
398 || (POS (a) && POS (b) && NEG (result)));
401 /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
402 int SubOverflow (ARMword a, ARMword b, ARMword result)
404 return ((NEG (a) && POS (b) && POS (result))
405 || (POS (a) && NEG (b) && NEG (result)));
408 /***************************************************************************\
409 * Assigns the C flag after an addition of a and b to give result *
410 \***************************************************************************/
412 void ARMul_AddCarry(ARMul_State *state, ARMword a,ARMword b,ARMword result)
414 ASSIGNC( (NEG(a) && NEG(b)) ||
415 (NEG(a) && POS(result)) ||
416 (NEG(b) && POS(result)) ) ;
419 /***************************************************************************\
420 * Assigns the V flag after an addition of a and b to give result *
421 \***************************************************************************/
423 void ARMul_AddOverflow(ARMul_State *state, ARMword a,ARMword b,ARMword result)
425 ASSIGNV (AddOverflow (a, b, result));
428 /***************************************************************************\
429 * Assigns the C flag after an subtraction of a and b to give result *
430 \***************************************************************************/
432 void ARMul_SubCarry(ARMul_State *state, ARMword a,ARMword b,ARMword result)
434 ASSIGNC( (NEG(a) && POS(b)) ||
435 (NEG(a) && POS(result)) ||
436 (POS(b) && POS(result)) ) ;
439 /***************************************************************************\
440 * Assigns the V flag after an subtraction of a and b to give result *
441 \***************************************************************************/
443 void ARMul_SubOverflow(ARMul_State *state,ARMword a,ARMword b,ARMword result)
445 ASSIGNV (SubOverflow (a, b, result));
448 /***************************************************************************\
449 * This function does the work of generating the addresses used in an *
450 * LDC instruction. The code here is always post-indexed, it's up to the *
451 * caller to get the input address correct and to handle base register *
452 * modification. It also handles the Busy-Waiting. *
453 \***************************************************************************/
455 void ARMul_LDC(ARMul_State *state,ARMword instr,ARMword address)
460 if (ADDREXCEPT(address)) {
461 INTERNALABORT(address) ;
463 cpab = (state->LDC[CPNum])(state,ARMul_FIRST,instr,0) ;
464 while (cpab == ARMul_BUSY) {
465 ARMul_Icycles(state,1,0) ;
466 if (IntPending(state)) {
467 cpab = (state->LDC[CPNum])(state,ARMul_INTERRUPT,instr,0) ;
471 cpab = (state->LDC[CPNum])(state,ARMul_BUSY,instr,0) ;
473 if (cpab == ARMul_CANT) {
477 cpab = (state->LDC[CPNum])(state,ARMul_TRANSFER,instr,0) ;
478 data = ARMul_LoadWordN(state,address) ;
481 LSBase = state->Base ;
482 cpab = (state->LDC[CPNum])(state,ARMul_DATA,instr,data) ;
483 while (cpab == ARMul_INC) {
485 data = ARMul_LoadWordN(state,address) ;
486 cpab = (state->LDC[CPNum])(state,ARMul_DATA,instr,data) ;
488 if (state->abortSig || state->Aborted) {
493 /***************************************************************************\
494 * This function does the work of generating the addresses used in an *
495 * STC instruction. The code here is always post-indexed, it's up to the *
496 * caller to get the input address correct and to handle base register *
497 * modification. It also handles the Busy-Waiting. *
498 \***************************************************************************/
500 void ARMul_STC(ARMul_State *state,ARMword instr,ARMword address)
505 if (ADDREXCEPT(address) || VECTORACCESS(address)) {
506 INTERNALABORT(address) ;
508 cpab = (state->STC[CPNum])(state,ARMul_FIRST,instr,&data) ;
509 while (cpab == ARMul_BUSY) {
510 ARMul_Icycles(state,1,0) ;
511 if (IntPending(state)) {
512 cpab = (state->STC[CPNum])(state,ARMul_INTERRUPT,instr,0) ;
516 cpab = (state->STC[CPNum])(state,ARMul_BUSY,instr,&data) ;
518 if (cpab == ARMul_CANT) {
523 if (ADDREXCEPT(address) || VECTORACCESS(address)) {
524 INTERNALABORT(address) ;
529 LSBase = state->Base ;
530 cpab = (state->STC[CPNum])(state,ARMul_DATA,instr,&data) ;
531 ARMul_StoreWordN(state,address,data) ;
532 while (cpab == ARMul_INC) {
534 cpab = (state->STC[CPNum])(state,ARMul_DATA,instr,&data) ;
535 ARMul_StoreWordN(state,address,data) ;
537 if (state->abortSig || state->Aborted) {
542 /***************************************************************************\
543 * This function does the Busy-Waiting for an MCR instruction. *
544 \***************************************************************************/
546 void ARMul_MCR(ARMul_State *state,ARMword instr, ARMword source)
549 cpab = (state->MCR[CPNum])(state,ARMul_FIRST,instr,source) ;
550 while (cpab == ARMul_BUSY) {
551 ARMul_Icycles(state,1,0) ;
552 if (IntPending(state)) {
553 cpab = (state->MCR[CPNum])(state,ARMul_INTERRUPT,instr,0) ;
557 cpab = (state->MCR[CPNum])(state,ARMul_BUSY,instr,source) ;
559 if (cpab == ARMul_CANT)
560 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
563 ARMul_Ccycles(state,1,0) ;
567 /***************************************************************************\
568 * This function does the Busy-Waiting for an MRC instruction. *
569 \***************************************************************************/
571 ARMword ARMul_MRC(ARMul_State *state,ARMword instr)
575 cpab = (state->MRC[CPNum])(state,ARMul_FIRST,instr,&result) ;
576 while (cpab == ARMul_BUSY) {
577 ARMul_Icycles(state,1,0) ;
578 if (IntPending(state)) {
579 cpab = (state->MRC[CPNum])(state,ARMul_INTERRUPT,instr,0) ;
583 cpab = (state->MRC[CPNum])(state,ARMul_BUSY,instr,&result) ;
585 if (cpab == ARMul_CANT) {
586 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
587 result = ECC ; /* Parent will destroy the flags otherwise */
591 ARMul_Ccycles(state,1,0) ;
592 ARMul_Icycles(state,1,0) ;
597 /***************************************************************************\
598 * This function does the Busy-Waiting for an CDP instruction. *
599 \***************************************************************************/
601 void ARMul_CDP(ARMul_State *state,ARMword instr)
604 cpab = (state->CDP[CPNum])(state,ARMul_FIRST,instr) ;
605 while (cpab == ARMul_BUSY) {
606 ARMul_Icycles(state,1,0) ;
607 if (IntPending(state)) {
608 cpab = (state->CDP[CPNum])(state,ARMul_INTERRUPT,instr) ;
612 cpab = (state->CDP[CPNum])(state,ARMul_BUSY,instr) ;
614 if (cpab == ARMul_CANT)
615 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
620 /***************************************************************************\
621 * This function handles Undefined instructions, as CP isntruction *
622 \***************************************************************************/
624 void ARMul_UndefInstr(ARMul_State *state,ARMword instr)
626 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
629 /***************************************************************************\
630 * Return TRUE if an interrupt is pending, FALSE otherwise. *
631 \***************************************************************************/
633 unsigned IntPending(ARMul_State *state)
635 if (state->Exception) { /* Any exceptions */
636 if (state->NresetSig == LOW) {
637 ARMul_Abort(state,ARMul_ResetV) ;
640 else if (!state->NfiqSig && !FFLAG) {
641 ARMul_Abort(state,ARMul_FIQV) ;
644 else if (!state->NirqSig && !IFLAG) {
645 ARMul_Abort(state,ARMul_IRQV) ;
652 /***************************************************************************\
653 * Align a word access to a non word boundary *
654 \***************************************************************************/
656 ARMword ARMul_Align(ARMul_State *state, ARMword address, ARMword data)
657 {/* this code assumes the address is really unaligned,
658 as a shift by 32 is undefined in C */
660 address = (address & 3) << 3 ; /* get the word address */
661 return( ( data >> address) | (data << (32 - address)) ) ; /* rot right */
664 /***************************************************************************\
665 * This routine is used to call another routine after a certain number of *
666 * cycles have been executed. The first parameter is the number of cycles *
667 * delay before the function is called, the second argument is a pointer *
668 * to the function. A delay of zero doesn't work, just call the function. *
669 \***************************************************************************/
671 void ARMul_ScheduleEvent(ARMul_State *state, unsigned long delay, unsigned (*what)())
672 {unsigned long when ;
673 struct EventNode *event ;
675 if (state->EventSet++ == 0)
676 state->Now = ARMul_Time(state) ;
677 when = (state->Now + delay) % EVENTLISTSIZE ;
678 event = (struct EventNode *)malloc(sizeof(struct EventNode)) ;
680 event->next = *(state->EventPtr + when) ;
681 *(state->EventPtr + when) = event ;
684 /***************************************************************************\
685 * This routine is called at the beginning of every cycle, to envoke *
686 * scheduled events. *
687 \***************************************************************************/
689 void ARMul_EnvokeEvent(ARMul_State *state)
690 {static unsigned long then ;
693 state->Now = ARMul_Time(state) % EVENTLISTSIZE ;
694 if (then < state->Now) /* schedule events */
695 EnvokeList(state,then,state->Now) ;
696 else if (then > state->Now) { /* need to wrap around the list */
697 EnvokeList(state,then,EVENTLISTSIZE-1L) ;
698 EnvokeList(state,0L,state->Now) ;
702 static void EnvokeList(ARMul_State *state, unsigned long from, unsigned long to)
703 /* envokes all the entries in a range */
704 {struct EventNode *anevent ;
706 for (; from <= to ; from++) {
707 anevent = *(state->EventPtr + from) ;
709 (anevent->func)(state) ;
711 anevent = anevent->next ;
713 *(state->EventPtr + from) = NULL ;
717 /***************************************************************************\
718 * This routine is returns the number of clock ticks since the last reset. *
719 \***************************************************************************/
721 unsigned long ARMul_Time(ARMul_State *state)
722 {return(state->NumScycles + state->NumNcycles +
723 state->NumIcycles + state->NumCcycles + state->NumFcycles) ;