]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/arm/armsupp.c
Fix typo in ALIGN_N usage.
[thirdparty/binutils-gdb.git] / sim / arm / armsupp.c
CommitLineData
c906108c
SS
1/* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3
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.
8
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.
13
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. */
17
18#include "armdefs.h"
19#include "armemu.h"
20
21/***************************************************************************\
22* Definitions for the support routines *
23\***************************************************************************/
24
25ARMword ARMul_GetReg(ARMul_State *state, unsigned mode, unsigned reg) ;
26void ARMul_SetReg(ARMul_State *state, unsigned mode, unsigned reg, ARMword value) ;
27ARMword ARMul_GetPC(ARMul_State *state) ;
28ARMword ARMul_GetNextPC(ARMul_State *state) ;
29void ARMul_SetPC(ARMul_State *state, ARMword value) ;
30ARMword ARMul_GetR15(ARMul_State *state) ;
31void ARMul_SetR15(ARMul_State *state, ARMword value) ;
32
33ARMword ARMul_GetCPSR(ARMul_State *state) ;
34void ARMul_SetCPSR(ARMul_State *state, ARMword value) ;
35void ARMul_FixCPSR(ARMul_State *state, ARMword instr, ARMword rhs) ;
36ARMword ARMul_GetSPSR(ARMul_State *state, ARMword mode) ;
37void ARMul_SetSPSR(ARMul_State *state, ARMword mode, ARMword value) ;
38void ARMul_FixSPSR(ARMul_State *state, ARMword instr, ARMword rhs) ;
39
40void ARMul_CPSRAltered(ARMul_State *state) ;
41void ARMul_R15Altered(ARMul_State *state) ;
42
43ARMword ARMul_SwitchMode(ARMul_State *state,ARMword oldmode, ARMword newmode) ;
44static ARMword ModeToBank(ARMul_State *state,ARMword mode) ;
45
46unsigned ARMul_NthReg(ARMword instr, unsigned number) ;
47
48void ARMul_NegZero(ARMul_State *state, ARMword result) ;
49void ARMul_AddCarry(ARMul_State *state, ARMword a, ARMword b, ARMword result) ;
50void ARMul_AddOverflow(ARMul_State *state, ARMword a, ARMword b, ARMword result) ;
51void ARMul_SubCarry(ARMul_State *state, ARMword a, ARMword b, ARMword result) ;
52void ARMul_SubOverflow(ARMul_State *state, ARMword a, ARMword b, ARMword result) ;
53
54void ARMul_LDC(ARMul_State *state,ARMword instr,ARMword address) ;
55void ARMul_STC(ARMul_State *state,ARMword instr,ARMword address) ;
56void ARMul_MCR(ARMul_State *state,ARMword instr, ARMword source) ;
57ARMword ARMul_MRC(ARMul_State *state,ARMword instr) ;
58void ARMul_CDP(ARMul_State *state,ARMword instr) ;
59void ARMul_UndefInstr(ARMul_State *state,ARMword instr) ;
60unsigned IntPending(ARMul_State *state) ;
61
62ARMword ARMul_Align(ARMul_State *state, ARMword address, ARMword data) ;
63
64void ARMul_ScheduleEvent(ARMul_State *state, unsigned long delay,
65 unsigned (*what)()) ;
66void ARMul_EnvokeEvent(ARMul_State *state) ;
67unsigned long ARMul_Time(ARMul_State *state) ;
68static void EnvokeList(ARMul_State *state, unsigned long from, unsigned long to) ;
69
70struct EventNode { /* An event list node */
71 unsigned (*func)() ; /* The function to call */
72 struct EventNode *next ;
73 } ;
74
75/***************************************************************************\
76* This routine returns the value of a register from a mode. *
77\***************************************************************************/
78
79ARMword ARMul_GetReg(ARMul_State *state, unsigned mode, unsigned reg)
80{mode &= MODEBITS ;
81 if (mode != state->Mode)
82 return(state->RegBank[ModeToBank(state,(ARMword)mode)][reg]) ;
83 else
84 return(state->Reg[reg]) ;
85}
86
87/***************************************************************************\
88* This routine sets the value of a register for a mode. *
89\***************************************************************************/
90
91void ARMul_SetReg(ARMul_State *state, unsigned mode, unsigned reg, ARMword value)
92{mode &= MODEBITS ;
93 if (mode != state->Mode)
94 state->RegBank[ModeToBank(state,(ARMword)mode)][reg] = value ;
95 else
96 state->Reg[reg] = value ;
97}
98
99/***************************************************************************\
100* This routine returns the value of the PC, mode independently. *
101\***************************************************************************/
102
103ARMword ARMul_GetPC(ARMul_State *state)
104{if (state->Mode > SVC26MODE)
105 return(state->Reg[15]) ;
106 else
107 return(R15PC) ;
108}
109
110/***************************************************************************\
111* This routine returns the value of the PC, mode independently. *
112\***************************************************************************/
113
114ARMword ARMul_GetNextPC(ARMul_State *state)
115{if (state->Mode > SVC26MODE)
116 return(state->Reg[15] + isize) ;
117 else
118 return((state->Reg[15] + isize) & R15PCBITS) ;
119}
120
121/***************************************************************************\
122* This routine sets the value of the PC. *
123\***************************************************************************/
124
125void ARMul_SetPC(ARMul_State *state, ARMword value)
126{if (ARMul_MODE32BIT)
127 state->Reg[15] = value & PCBITS ;
128 else
129 state->Reg[15] = R15CCINTMODE | (value & R15PCBITS) ;
130 FLUSHPIPE ;
131}
132
133/***************************************************************************\
134* This routine returns the value of register 15, mode independently. *
135\***************************************************************************/
136
137ARMword ARMul_GetR15(ARMul_State *state)
138{if (state->Mode > SVC26MODE)
139 return(state->Reg[15]) ;
140 else
141 return(R15PC | ECC | ER15INT | EMODE) ;
142}
143
144/***************************************************************************\
145* This routine sets the value of Register 15. *
146\***************************************************************************/
147
148void ARMul_SetR15(ARMul_State *state, ARMword value)
149{
150 if (ARMul_MODE32BIT)
151 state->Reg[15] = value & PCBITS ;
152 else {
153 state->Reg[15] = value ;
154 ARMul_R15Altered(state) ;
155 }
156 FLUSHPIPE ;
157}
158
159/***************************************************************************\
160* This routine returns the value of the CPSR *
161\***************************************************************************/
162
163ARMword ARMul_GetCPSR(ARMul_State *state)
164{
165 return(CPSR) ;
166 }
167
168/***************************************************************************\
169* This routine sets the value of the CPSR *
170\***************************************************************************/
171
172void ARMul_SetCPSR(ARMul_State *state, ARMword value)
173{state->Cpsr = CPSR ;
174 SETPSR(state->Cpsr,value) ;
175 ARMul_CPSRAltered(state) ;
176 }
177
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\***************************************************************************/
182
183void ARMul_FixCPSR(ARMul_State *state, ARMword instr, ARMword rhs)
184{state->Cpsr = CPSR ;
185 if (state->Bank==USERBANK) { /* Only write flags in user mode */
186 if (BIT(19)) {
187 SETCC(state->Cpsr,rhs) ;
188 }
189 }
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) ;
194 }
195 ARMul_CPSRAltered(state) ;
196 }
197
198/***************************************************************************\
199* Get an SPSR from the specified mode *
200\***************************************************************************/
201
202ARMword ARMul_GetSPSR(ARMul_State *state, ARMword mode)
203{ARMword bank = ModeToBank(state,mode & MODEBITS) ;
204 if (bank == USERBANK || bank == DUMMYBANK)
205 return(CPSR) ;
206 else
207 return(state->Spsr[bank]) ;
208}
209
210/***************************************************************************\
211* This routine does a write to an SPSR *
212\***************************************************************************/
213
214void 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 ;
218}
219
220/***************************************************************************\
221* This routine does a write to the current SPSR, given an MSR instruction *
222\***************************************************************************/
223
224void 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) ;
229 }
230}
231
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\***************************************************************************/
236
237void ARMul_CPSRAltered(ARMul_State *state)
238{ARMword oldmode ;
239
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 ;
246 }
247
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) ;
253#ifdef MODET
254 ASSIGNT((state->Cpsr & TBIT) != 0);
255#endif
256
257 if (oldmode > SVC26MODE) {
258 if (state->Mode <= SVC26MODE) {
259 state->Emulate = CHANGEMODE ;
260 state->Reg[15] = ECC | ER15INT | EMODE | R15PC ;
261 }
262 }
263 else {
264 if (state->Mode > SVC26MODE) {
265 state->Emulate = CHANGEMODE ;
266 state->Reg[15] = R15PC ;
267 }
268 else
269 state->Reg[15] = ECC | ER15INT | EMODE | R15PC ;
270 }
271
272}
273
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\***************************************************************************/
279
280void ARMul_R15Altered(ARMul_State *state)
281{
282 if (state->Mode != R15MODE) {
283 state->Mode = ARMul_SwitchMode(state,state->Mode,R15MODE) ;
284 state->NtransSig = (state->Mode & 3)?HIGH:LOW ;
285 }
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) ;
293}
294
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\***************************************************************************/
302
303ARMword ARMul_SwitchMode(ARMul_State *state,ARMword oldmode, ARMword newmode)
304{unsigned i ;
305
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 */
310 case USERBANK :
311 case IRQBANK :
312 case SVCBANK :
313 case ABORTBANK :
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] ;
319 break ;
320 case FIQBANK : for (i = 8 ; i < 15 ; i++)
321 state->RegBank[FIQBANK][i] = state->Reg[i] ;
322 break ;
323 case DUMMYBANK : for (i = 8 ; i < 15 ; i++)
324 state->RegBank[DUMMYBANK][i] = 0 ;
325 break ;
326
327 }
328 switch (state->Bank) { /* restore the new registers */
329 case USERBANK :
330 case IRQBANK :
331 case SVCBANK :
332 case ABORTBANK :
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] ;
338 break ;
339 case FIQBANK : for (i = 8 ; i < 15 ; i++)
340 state->Reg[i] = state->RegBank[FIQBANK][i] ;
341 break ;
342 case DUMMYBANK : for (i = 8 ; i < 15 ; i++)
343 state->Reg[i] = 0 ;
344 break ;
345 } /* switch */
346 } /* if */
347 return(newmode) ;
348}
349
350/***************************************************************************\
351* Given a processor mode, this routine returns the register bank that *
352* will be accessed in that mode. *
353\***************************************************************************/
354
355static 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
363 } ;
364
365 if (mode > UNDEF32MODE)
366 return(DUMMYBANK) ;
367 else
368 return(bankofmode[mode]) ;
369 }
370
371/***************************************************************************\
372* Returns the register number of the nth register in a reg list. *
373\***************************************************************************/
374
375unsigned ARMul_NthReg(ARMword instr, unsigned number)
376{unsigned bit, upto ;
377
378 for (bit = 0, upto = 0 ; upto <= number ; bit++)
379 if (BIT(bit)) upto++ ;
380 return(bit - 1) ;
381}
382
383/***************************************************************************\
384* Assigns the N and Z flags depending on the value of result *
385\***************************************************************************/
386
387void ARMul_NegZero(ARMul_State *state, ARMword result)
388{
389 if (NEG(result)) { SETN ; CLEARZ ; }
390 else if (result == 0) { CLEARN ; SETZ ; }
391 else { CLEARN ; CLEARZ ; } ;
392 }
393
f743149e
JM
394/* Compute whether an addition of A and B, giving RESULT, overflowed. */
395int AddOverflow (ARMword a, ARMword b, ARMword result)
396{
397 return ((NEG (a) && NEG (b) && POS (result))
398 || (POS (a) && POS (b) && NEG (result)));
399}
400
401/* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
402int SubOverflow (ARMword a, ARMword b, ARMword result)
403{
404 return ((NEG (a) && POS (b) && POS (result))
405 || (POS (a) && NEG (b) && NEG (result)));
406}
407
c906108c
SS
408/***************************************************************************\
409* Assigns the C flag after an addition of a and b to give result *
410\***************************************************************************/
411
412void ARMul_AddCarry(ARMul_State *state, ARMword a,ARMword b,ARMword result)
413{
414 ASSIGNC( (NEG(a) && NEG(b)) ||
415 (NEG(a) && POS(result)) ||
416 (NEG(b) && POS(result)) ) ;
417 }
418
419/***************************************************************************\
420* Assigns the V flag after an addition of a and b to give result *
421\***************************************************************************/
422
423void ARMul_AddOverflow(ARMul_State *state, ARMword a,ARMword b,ARMword result)
424{
f743149e
JM
425 ASSIGNV (AddOverflow (a, b, result));
426}
c906108c
SS
427
428/***************************************************************************\
429* Assigns the C flag after an subtraction of a and b to give result *
430\***************************************************************************/
431
432void ARMul_SubCarry(ARMul_State *state, ARMword a,ARMword b,ARMword result)
433{
434ASSIGNC( (NEG(a) && POS(b)) ||
435 (NEG(a) && POS(result)) ||
436 (POS(b) && POS(result)) ) ;
437}
438
439/***************************************************************************\
440* Assigns the V flag after an subtraction of a and b to give result *
441\***************************************************************************/
442
443void ARMul_SubOverflow(ARMul_State *state,ARMword a,ARMword b,ARMword result)
444{
f743149e 445 ASSIGNV (SubOverflow (a, b, result));
c906108c
SS
446}
447
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\***************************************************************************/
454
455void ARMul_LDC(ARMul_State *state,ARMword instr,ARMword address)
456{unsigned cpab ;
457 ARMword data ;
458
459 UNDEF_LSCPCBaseWb ;
460 if (ADDREXCEPT(address)) {
461 INTERNALABORT(address) ;
462 }
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) ;
468 return ;
469 }
470 else
471 cpab = (state->LDC[CPNum])(state,ARMul_BUSY,instr,0) ;
472 }
473 if (cpab == ARMul_CANT) {
474 CPTAKEABORT ;
475 return ;
476 }
477 cpab = (state->LDC[CPNum])(state,ARMul_TRANSFER,instr,0) ;
478 data = ARMul_LoadWordN(state,address) ;
479 BUSUSEDINCPCN ;
480 if (BIT(21))
481 LSBase = state->Base ;
482 cpab = (state->LDC[CPNum])(state,ARMul_DATA,instr,data) ;
483 while (cpab == ARMul_INC) {
484 address += 4 ;
485 data = ARMul_LoadWordN(state,address) ;
486 cpab = (state->LDC[CPNum])(state,ARMul_DATA,instr,data) ;
487 }
488 if (state->abortSig || state->Aborted) {
489 TAKEABORT ;
490 }
491 }
492
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\***************************************************************************/
499
500void ARMul_STC(ARMul_State *state,ARMword instr,ARMword address)
501{unsigned cpab ;
502 ARMword data ;
503
504 UNDEF_LSCPCBaseWb ;
505 if (ADDREXCEPT(address) || VECTORACCESS(address)) {
506 INTERNALABORT(address) ;
507 }
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) ;
513 return ;
514 }
515 else
516 cpab = (state->STC[CPNum])(state,ARMul_BUSY,instr,&data) ;
517 }
518 if (cpab == ARMul_CANT) {
519 CPTAKEABORT ;
520 return ;
521 }
522#ifndef MODE32
523 if (ADDREXCEPT(address) || VECTORACCESS(address)) {
524 INTERNALABORT(address) ;
525 }
526#endif
527 BUSUSEDINCPCN ;
528 if (BIT(21))
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) {
533 address += 4 ;
534 cpab = (state->STC[CPNum])(state,ARMul_DATA,instr,&data) ;
535 ARMul_StoreWordN(state,address,data) ;
536 }
537 if (state->abortSig || state->Aborted) {
538 TAKEABORT ;
539 }
540 }
541
542/***************************************************************************\
543* This function does the Busy-Waiting for an MCR instruction. *
544\***************************************************************************/
545
546void ARMul_MCR(ARMul_State *state,ARMword instr, ARMword source)
547{unsigned cpab ;
548
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) ;
554 return ;
555 }
556 else
557 cpab = (state->MCR[CPNum])(state,ARMul_BUSY,instr,source) ;
558 }
559 if (cpab == ARMul_CANT)
560 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
561 else {
562 BUSUSEDINCPCN ;
563 ARMul_Ccycles(state,1,0) ;
564 }
565 }
566
567/***************************************************************************\
568* This function does the Busy-Waiting for an MRC instruction. *
569\***************************************************************************/
570
571ARMword ARMul_MRC(ARMul_State *state,ARMword instr)
572{unsigned cpab ;
573 ARMword result = 0 ;
574
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) ;
580 return(0) ;
581 }
582 else
583 cpab = (state->MRC[CPNum])(state,ARMul_BUSY,instr,&result) ;
584 }
585 if (cpab == ARMul_CANT) {
586 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
587 result = ECC ; /* Parent will destroy the flags otherwise */
588 }
589 else {
590 BUSUSEDINCPCN ;
591 ARMul_Ccycles(state,1,0) ;
592 ARMul_Icycles(state,1,0) ;
593 }
594 return(result) ;
595}
596
597/***************************************************************************\
598* This function does the Busy-Waiting for an CDP instruction. *
599\***************************************************************************/
600
601void ARMul_CDP(ARMul_State *state,ARMword instr)
602{unsigned cpab ;
603
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) ;
609 return ;
610 }
611 else
612 cpab = (state->CDP[CPNum])(state,ARMul_BUSY,instr) ;
613 }
614 if (cpab == ARMul_CANT)
615 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
616 else
617 BUSUSEDN ;
618}
619
620/***************************************************************************\
621* This function handles Undefined instructions, as CP isntruction *
622\***************************************************************************/
623
624void ARMul_UndefInstr(ARMul_State *state,ARMword instr)
625{
626 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
627}
628
629/***************************************************************************\
630* Return TRUE if an interrupt is pending, FALSE otherwise. *
631\***************************************************************************/
632
633unsigned IntPending(ARMul_State *state)
634{
635 if (state->Exception) { /* Any exceptions */
636 if (state->NresetSig == LOW) {
637 ARMul_Abort(state,ARMul_ResetV) ;
638 return(TRUE) ;
639 }
640 else if (!state->NfiqSig && !FFLAG) {
641 ARMul_Abort(state,ARMul_FIQV) ;
642 return(TRUE) ;
643 }
644 else if (!state->NirqSig && !IFLAG) {
645 ARMul_Abort(state,ARMul_IRQV) ;
646 return(TRUE) ;
647 }
648 }
649 return(FALSE) ;
650 }
651
652/***************************************************************************\
653* Align a word access to a non word boundary *
654\***************************************************************************/
655
656ARMword 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 */
659
660 address = (address & 3) << 3 ; /* get the word address */
661 return( ( data >> address) | (data << (32 - address)) ) ; /* rot right */
662}
663
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\***************************************************************************/
670
671void ARMul_ScheduleEvent(ARMul_State *state, unsigned long delay, unsigned (*what)())
672{unsigned long when ;
673 struct EventNode *event ;
674
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)) ;
679 event->func = what ;
680 event->next = *(state->EventPtr + when) ;
681 *(state->EventPtr + when) = event ;
682}
683
684/***************************************************************************\
685* This routine is called at the beginning of every cycle, to envoke *
686* scheduled events. *
687\***************************************************************************/
688
689void ARMul_EnvokeEvent(ARMul_State *state)
690{static unsigned long then ;
691
692 then = state->Now ;
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) ;
699 }
700 }
701
702static void EnvokeList(ARMul_State *state, unsigned long from, unsigned long to)
703/* envokes all the entries in a range */
704{struct EventNode *anevent ;
705
706 for (; from <= to ; from++) {
707 anevent = *(state->EventPtr + from) ;
708 while (anevent) {
709 (anevent->func)(state) ;
710 state->EventSet-- ;
711 anevent = anevent->next ;
712 }
713 *(state->EventPtr + from) = NULL ;
714 }
715 }
716
717/***************************************************************************\
718* This routine is returns the number of clock ticks since the last reset. *
719\***************************************************************************/
720
721unsigned long ARMul_Time(ARMul_State *state)
722{return(state->NumScycles + state->NumNcycles +
723 state->NumIcycles + state->NumCcycles + state->NumFcycles) ;
724}