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 /***************************************************************************\
395 * Assigns the C flag after an addition of a and b to give result *
396 \***************************************************************************/
398 void ARMul_AddCarry(ARMul_State *state, ARMword a,ARMword b,ARMword result)
400 ASSIGNC( (NEG(a) && NEG(b)) ||
401 (NEG(a) && POS(result)) ||
402 (NEG(b) && POS(result)) ) ;
405 /***************************************************************************\
406 * Assigns the V flag after an addition of a and b to give result *
407 \***************************************************************************/
409 void ARMul_AddOverflow(ARMul_State *state, ARMword a,ARMword b,ARMword result)
411 ASSIGNV( (NEG(a) && NEG(b) && POS(result)) ||
412 (POS(a) && POS(b) && NEG(result)) ) ;
415 /***************************************************************************\
416 * Assigns the C flag after an subtraction of a and b to give result *
417 \***************************************************************************/
419 void ARMul_SubCarry(ARMul_State *state, ARMword a,ARMword b,ARMword result)
421 ASSIGNC( (NEG(a) && POS(b)) ||
422 (NEG(a) && POS(result)) ||
423 (POS(b) && POS(result)) ) ;
426 /***************************************************************************\
427 * Assigns the V flag after an subtraction of a and b to give result *
428 \***************************************************************************/
430 void ARMul_SubOverflow(ARMul_State *state,ARMword a,ARMword b,ARMword result)
432 ASSIGNV( (NEG(a) && POS(b) && POS(result)) ||
433 (POS(a) && NEG(b) && NEG(result)) ) ;
436 /***************************************************************************\
437 * This function does the work of generating the addresses used in an *
438 * LDC instruction. The code here is always post-indexed, it's up to the *
439 * caller to get the input address correct and to handle base register *
440 * modification. It also handles the Busy-Waiting. *
441 \***************************************************************************/
443 void ARMul_LDC(ARMul_State *state,ARMword instr,ARMword address)
448 if (ADDREXCEPT(address)) {
449 INTERNALABORT(address) ;
451 cpab = (state->LDC[CPNum])(state,ARMul_FIRST,instr,0) ;
452 while (cpab == ARMul_BUSY) {
453 ARMul_Icycles(state,1,0) ;
454 if (IntPending(state)) {
455 cpab = (state->LDC[CPNum])(state,ARMul_INTERRUPT,instr,0) ;
459 cpab = (state->LDC[CPNum])(state,ARMul_BUSY,instr,0) ;
461 if (cpab == ARMul_CANT) {
465 cpab = (state->LDC[CPNum])(state,ARMul_TRANSFER,instr,0) ;
466 data = ARMul_LoadWordN(state,address) ;
469 LSBase = state->Base ;
470 cpab = (state->LDC[CPNum])(state,ARMul_DATA,instr,data) ;
471 while (cpab == ARMul_INC) {
473 data = ARMul_LoadWordN(state,address) ;
474 cpab = (state->LDC[CPNum])(state,ARMul_DATA,instr,data) ;
476 if (state->abortSig || state->Aborted) {
481 /***************************************************************************\
482 * This function does the work of generating the addresses used in an *
483 * STC instruction. The code here is always post-indexed, it's up to the *
484 * caller to get the input address correct and to handle base register *
485 * modification. It also handles the Busy-Waiting. *
486 \***************************************************************************/
488 void ARMul_STC(ARMul_State *state,ARMword instr,ARMword address)
493 if (ADDREXCEPT(address) || VECTORACCESS(address)) {
494 INTERNALABORT(address) ;
496 cpab = (state->STC[CPNum])(state,ARMul_FIRST,instr,&data) ;
497 while (cpab == ARMul_BUSY) {
498 ARMul_Icycles(state,1,0) ;
499 if (IntPending(state)) {
500 cpab = (state->STC[CPNum])(state,ARMul_INTERRUPT,instr,0) ;
504 cpab = (state->STC[CPNum])(state,ARMul_BUSY,instr,&data) ;
506 if (cpab == ARMul_CANT) {
511 if (ADDREXCEPT(address) || VECTORACCESS(address)) {
512 INTERNALABORT(address) ;
517 LSBase = state->Base ;
518 cpab = (state->STC[CPNum])(state,ARMul_DATA,instr,&data) ;
519 ARMul_StoreWordN(state,address,data) ;
520 while (cpab == ARMul_INC) {
522 cpab = (state->STC[CPNum])(state,ARMul_DATA,instr,&data) ;
523 ARMul_StoreWordN(state,address,data) ;
525 if (state->abortSig || state->Aborted) {
530 /***************************************************************************\
531 * This function does the Busy-Waiting for an MCR instruction. *
532 \***************************************************************************/
534 void ARMul_MCR(ARMul_State *state,ARMword instr, ARMword source)
537 cpab = (state->MCR[CPNum])(state,ARMul_FIRST,instr,source) ;
538 while (cpab == ARMul_BUSY) {
539 ARMul_Icycles(state,1,0) ;
540 if (IntPending(state)) {
541 cpab = (state->MCR[CPNum])(state,ARMul_INTERRUPT,instr,0) ;
545 cpab = (state->MCR[CPNum])(state,ARMul_BUSY,instr,source) ;
547 if (cpab == ARMul_CANT)
548 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
551 ARMul_Ccycles(state,1,0) ;
555 /***************************************************************************\
556 * This function does the Busy-Waiting for an MRC instruction. *
557 \***************************************************************************/
559 ARMword ARMul_MRC(ARMul_State *state,ARMword instr)
563 cpab = (state->MRC[CPNum])(state,ARMul_FIRST,instr,&result) ;
564 while (cpab == ARMul_BUSY) {
565 ARMul_Icycles(state,1,0) ;
566 if (IntPending(state)) {
567 cpab = (state->MRC[CPNum])(state,ARMul_INTERRUPT,instr,0) ;
571 cpab = (state->MRC[CPNum])(state,ARMul_BUSY,instr,&result) ;
573 if (cpab == ARMul_CANT) {
574 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
575 result = ECC ; /* Parent will destroy the flags otherwise */
579 ARMul_Ccycles(state,1,0) ;
580 ARMul_Icycles(state,1,0) ;
585 /***************************************************************************\
586 * This function does the Busy-Waiting for an CDP instruction. *
587 \***************************************************************************/
589 void ARMul_CDP(ARMul_State *state,ARMword instr)
592 cpab = (state->CDP[CPNum])(state,ARMul_FIRST,instr) ;
593 while (cpab == ARMul_BUSY) {
594 ARMul_Icycles(state,1,0) ;
595 if (IntPending(state)) {
596 cpab = (state->CDP[CPNum])(state,ARMul_INTERRUPT,instr) ;
600 cpab = (state->CDP[CPNum])(state,ARMul_BUSY,instr) ;
602 if (cpab == ARMul_CANT)
603 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
608 /***************************************************************************\
609 * This function handles Undefined instructions, as CP isntruction *
610 \***************************************************************************/
612 void ARMul_UndefInstr(ARMul_State *state,ARMword instr)
614 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
617 /***************************************************************************\
618 * Return TRUE if an interrupt is pending, FALSE otherwise. *
619 \***************************************************************************/
621 unsigned IntPending(ARMul_State *state)
623 if (state->Exception) { /* Any exceptions */
624 if (state->NresetSig == LOW) {
625 ARMul_Abort(state,ARMul_ResetV) ;
628 else if (!state->NfiqSig && !FFLAG) {
629 ARMul_Abort(state,ARMul_FIQV) ;
632 else if (!state->NirqSig && !IFLAG) {
633 ARMul_Abort(state,ARMul_IRQV) ;
640 /***************************************************************************\
641 * Align a word access to a non word boundary *
642 \***************************************************************************/
644 ARMword ARMul_Align(ARMul_State *state, ARMword address, ARMword data)
645 {/* this code assumes the address is really unaligned,
646 as a shift by 32 is undefined in C */
648 address = (address & 3) << 3 ; /* get the word address */
649 return( ( data >> address) | (data << (32 - address)) ) ; /* rot right */
652 /***************************************************************************\
653 * This routine is used to call another routine after a certain number of *
654 * cycles have been executed. The first parameter is the number of cycles *
655 * delay before the function is called, the second argument is a pointer *
656 * to the function. A delay of zero doesn't work, just call the function. *
657 \***************************************************************************/
659 void ARMul_ScheduleEvent(ARMul_State *state, unsigned long delay, unsigned (*what)())
660 {unsigned long when ;
661 struct EventNode *event ;
663 if (state->EventSet++ == 0)
664 state->Now = ARMul_Time(state) ;
665 when = (state->Now + delay) % EVENTLISTSIZE ;
666 event = (struct EventNode *)malloc(sizeof(struct EventNode)) ;
668 event->next = *(state->EventPtr + when) ;
669 *(state->EventPtr + when) = event ;
672 /***************************************************************************\
673 * This routine is called at the beginning of every cycle, to envoke *
674 * scheduled events. *
675 \***************************************************************************/
677 void ARMul_EnvokeEvent(ARMul_State *state)
678 {static unsigned long then ;
681 state->Now = ARMul_Time(state) % EVENTLISTSIZE ;
682 if (then < state->Now) /* schedule events */
683 EnvokeList(state,then,state->Now) ;
684 else if (then > state->Now) { /* need to wrap around the list */
685 EnvokeList(state,then,EVENTLISTSIZE-1L) ;
686 EnvokeList(state,0L,state->Now) ;
690 static void EnvokeList(ARMul_State *state, unsigned long from, unsigned long to)
691 /* envokes all the entries in a range */
692 {struct EventNode *anevent ;
694 for (; from <= to ; from++) {
695 anevent = *(state->EventPtr + from) ;
697 (anevent->func)(state) ;
699 anevent = anevent->next ;
701 *(state->EventPtr + from) = NULL ;
705 /***************************************************************************\
706 * This routine is returns the number of clock ticks since the last reset. *
707 \***************************************************************************/
709 unsigned long ARMul_Time(ARMul_State *state)
710 {return(state->NumScycles + state->NumNcycles +
711 state->NumIcycles + state->NumCcycles + state->NumFcycles) ;