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
) ;