This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / sim / arm / armsupp.c
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
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) ;
32
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) ;
39
40 void ARMul_CPSRAltered(ARMul_State *state) ;
41 void ARMul_R15Altered(ARMul_State *state) ;
42
43 ARMword ARMul_SwitchMode(ARMul_State *state,ARMword oldmode, ARMword newmode) ;
44 static ARMword ModeToBank(ARMul_State *state,ARMword mode) ;
45
46 unsigned ARMul_NthReg(ARMword instr, unsigned number) ;
47
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) ;
53
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) ;
61
62 ARMword ARMul_Align(ARMul_State *state, ARMword address, ARMword data) ;
63
64 void ARMul_ScheduleEvent(ARMul_State *state, unsigned long delay,
65 unsigned (*what)()) ;
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) ;
69
70 struct 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
79 ARMword 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
91 void 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
103 ARMword 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
114 ARMword 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
125 void 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
137 ARMword 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
148 void 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
163 ARMword ARMul_GetCPSR(ARMul_State *state)
164 {
165 return(CPSR) ;
166 }
167
168 /***************************************************************************\
169 * This routine sets the value of the CPSR *
170 \***************************************************************************/
171
172 void 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
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 */
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
202 ARMword 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
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 ;
218 }
219
220 /***************************************************************************\
221 * This routine does a write to the current SPSR, given an MSR instruction *
222 \***************************************************************************/
223
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) ;
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
237 void 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
280 void 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
303 ARMword 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
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
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
375 unsigned 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
387 void 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
394 /***************************************************************************\
395 * Assigns the C flag after an addition of a and b to give result *
396 \***************************************************************************/
397
398 void ARMul_AddCarry(ARMul_State *state, ARMword a,ARMword b,ARMword result)
399 {
400 ASSIGNC( (NEG(a) && NEG(b)) ||
401 (NEG(a) && POS(result)) ||
402 (NEG(b) && POS(result)) ) ;
403 }
404
405 /***************************************************************************\
406 * Assigns the V flag after an addition of a and b to give result *
407 \***************************************************************************/
408
409 void ARMul_AddOverflow(ARMul_State *state, ARMword a,ARMword b,ARMword result)
410 {
411 ASSIGNV( (NEG(a) && NEG(b) && POS(result)) ||
412 (POS(a) && POS(b) && NEG(result)) ) ;
413 }
414
415 /***************************************************************************\
416 * Assigns the C flag after an subtraction of a and b to give result *
417 \***************************************************************************/
418
419 void ARMul_SubCarry(ARMul_State *state, ARMword a,ARMword b,ARMword result)
420 {
421 ASSIGNC( (NEG(a) && POS(b)) ||
422 (NEG(a) && POS(result)) ||
423 (POS(b) && POS(result)) ) ;
424 }
425
426 /***************************************************************************\
427 * Assigns the V flag after an subtraction of a and b to give result *
428 \***************************************************************************/
429
430 void ARMul_SubOverflow(ARMul_State *state,ARMword a,ARMword b,ARMword result)
431 {
432 ASSIGNV( (NEG(a) && POS(b) && POS(result)) ||
433 (POS(a) && NEG(b) && NEG(result)) ) ;
434 }
435
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 \***************************************************************************/
442
443 void ARMul_LDC(ARMul_State *state,ARMword instr,ARMword address)
444 {unsigned cpab ;
445 ARMword data ;
446
447 UNDEF_LSCPCBaseWb ;
448 if (ADDREXCEPT(address)) {
449 INTERNALABORT(address) ;
450 }
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) ;
456 return ;
457 }
458 else
459 cpab = (state->LDC[CPNum])(state,ARMul_BUSY,instr,0) ;
460 }
461 if (cpab == ARMul_CANT) {
462 CPTAKEABORT ;
463 return ;
464 }
465 cpab = (state->LDC[CPNum])(state,ARMul_TRANSFER,instr,0) ;
466 data = ARMul_LoadWordN(state,address) ;
467 BUSUSEDINCPCN ;
468 if (BIT(21))
469 LSBase = state->Base ;
470 cpab = (state->LDC[CPNum])(state,ARMul_DATA,instr,data) ;
471 while (cpab == ARMul_INC) {
472 address += 4 ;
473 data = ARMul_LoadWordN(state,address) ;
474 cpab = (state->LDC[CPNum])(state,ARMul_DATA,instr,data) ;
475 }
476 if (state->abortSig || state->Aborted) {
477 TAKEABORT ;
478 }
479 }
480
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 \***************************************************************************/
487
488 void ARMul_STC(ARMul_State *state,ARMword instr,ARMword address)
489 {unsigned cpab ;
490 ARMword data ;
491
492 UNDEF_LSCPCBaseWb ;
493 if (ADDREXCEPT(address) || VECTORACCESS(address)) {
494 INTERNALABORT(address) ;
495 }
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) ;
501 return ;
502 }
503 else
504 cpab = (state->STC[CPNum])(state,ARMul_BUSY,instr,&data) ;
505 }
506 if (cpab == ARMul_CANT) {
507 CPTAKEABORT ;
508 return ;
509 }
510 #ifndef MODE32
511 if (ADDREXCEPT(address) || VECTORACCESS(address)) {
512 INTERNALABORT(address) ;
513 }
514 #endif
515 BUSUSEDINCPCN ;
516 if (BIT(21))
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) {
521 address += 4 ;
522 cpab = (state->STC[CPNum])(state,ARMul_DATA,instr,&data) ;
523 ARMul_StoreWordN(state,address,data) ;
524 }
525 if (state->abortSig || state->Aborted) {
526 TAKEABORT ;
527 }
528 }
529
530 /***************************************************************************\
531 * This function does the Busy-Waiting for an MCR instruction. *
532 \***************************************************************************/
533
534 void ARMul_MCR(ARMul_State *state,ARMword instr, ARMword source)
535 {unsigned cpab ;
536
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) ;
542 return ;
543 }
544 else
545 cpab = (state->MCR[CPNum])(state,ARMul_BUSY,instr,source) ;
546 }
547 if (cpab == ARMul_CANT)
548 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
549 else {
550 BUSUSEDINCPCN ;
551 ARMul_Ccycles(state,1,0) ;
552 }
553 }
554
555 /***************************************************************************\
556 * This function does the Busy-Waiting for an MRC instruction. *
557 \***************************************************************************/
558
559 ARMword ARMul_MRC(ARMul_State *state,ARMword instr)
560 {unsigned cpab ;
561 ARMword result = 0 ;
562
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) ;
568 return(0) ;
569 }
570 else
571 cpab = (state->MRC[CPNum])(state,ARMul_BUSY,instr,&result) ;
572 }
573 if (cpab == ARMul_CANT) {
574 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
575 result = ECC ; /* Parent will destroy the flags otherwise */
576 }
577 else {
578 BUSUSEDINCPCN ;
579 ARMul_Ccycles(state,1,0) ;
580 ARMul_Icycles(state,1,0) ;
581 }
582 return(result) ;
583 }
584
585 /***************************************************************************\
586 * This function does the Busy-Waiting for an CDP instruction. *
587 \***************************************************************************/
588
589 void ARMul_CDP(ARMul_State *state,ARMword instr)
590 {unsigned cpab ;
591
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) ;
597 return ;
598 }
599 else
600 cpab = (state->CDP[CPNum])(state,ARMul_BUSY,instr) ;
601 }
602 if (cpab == ARMul_CANT)
603 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
604 else
605 BUSUSEDN ;
606 }
607
608 /***************************************************************************\
609 * This function handles Undefined instructions, as CP isntruction *
610 \***************************************************************************/
611
612 void ARMul_UndefInstr(ARMul_State *state,ARMword instr)
613 {
614 ARMul_Abort(state,ARMul_UndefinedInstrV) ;
615 }
616
617 /***************************************************************************\
618 * Return TRUE if an interrupt is pending, FALSE otherwise. *
619 \***************************************************************************/
620
621 unsigned IntPending(ARMul_State *state)
622 {
623 if (state->Exception) { /* Any exceptions */
624 if (state->NresetSig == LOW) {
625 ARMul_Abort(state,ARMul_ResetV) ;
626 return(TRUE) ;
627 }
628 else if (!state->NfiqSig && !FFLAG) {
629 ARMul_Abort(state,ARMul_FIQV) ;
630 return(TRUE) ;
631 }
632 else if (!state->NirqSig && !IFLAG) {
633 ARMul_Abort(state,ARMul_IRQV) ;
634 return(TRUE) ;
635 }
636 }
637 return(FALSE) ;
638 }
639
640 /***************************************************************************\
641 * Align a word access to a non word boundary *
642 \***************************************************************************/
643
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 */
647
648 address = (address & 3) << 3 ; /* get the word address */
649 return( ( data >> address) | (data << (32 - address)) ) ; /* rot right */
650 }
651
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 \***************************************************************************/
658
659 void ARMul_ScheduleEvent(ARMul_State *state, unsigned long delay, unsigned (*what)())
660 {unsigned long when ;
661 struct EventNode *event ;
662
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)) ;
667 event->func = what ;
668 event->next = *(state->EventPtr + when) ;
669 *(state->EventPtr + when) = event ;
670 }
671
672 /***************************************************************************\
673 * This routine is called at the beginning of every cycle, to envoke *
674 * scheduled events. *
675 \***************************************************************************/
676
677 void ARMul_EnvokeEvent(ARMul_State *state)
678 {static unsigned long then ;
679
680 then = state->Now ;
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) ;
687 }
688 }
689
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 ;
693
694 for (; from <= to ; from++) {
695 anevent = *(state->EventPtr + from) ;
696 while (anevent) {
697 (anevent->func)(state) ;
698 state->EventSet-- ;
699 anevent = anevent->next ;
700 }
701 *(state->EventPtr + from) = NULL ;
702 }
703 }
704
705 /***************************************************************************\
706 * This routine is returns the number of clock ticks since the last reset. *
707 \***************************************************************************/
708
709 unsigned long ARMul_Time(ARMul_State *state)
710 {return(state->NumScycles + state->NumNcycles +
711 state->NumIcycles + state->NumCcycles + state->NumFcycles) ;
712 }
This page took 0.0599690000000001 seconds and 5 git commands to generate.