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 #include "ansidecl.h"
21
22 /***************************************************************************\
23 * Definitions for the support routines *
24 \***************************************************************************/
25
26 ARMword ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg);
27 void ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg,
28 ARMword value);
29 ARMword ARMul_GetPC (ARMul_State * state);
30 ARMword ARMul_GetNextPC (ARMul_State * state);
31 void ARMul_SetPC (ARMul_State * state, ARMword value);
32 ARMword ARMul_GetR15 (ARMul_State * state);
33 void ARMul_SetR15 (ARMul_State * state, ARMword value);
34
35 ARMword ARMul_GetCPSR (ARMul_State * state);
36 void ARMul_SetCPSR (ARMul_State * state, ARMword value);
37 ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode);
38 void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value);
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,
44 ARMword newmode);
45 static ARMword ModeToBank (ARMul_State * state, ARMword mode);
46
47 unsigned ARMul_NthReg (ARMword instr, unsigned number);
48
49 void ARMul_NegZero (ARMul_State * state, ARMword result);
50 void ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b,
51 ARMword result);
52 void ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b,
53 ARMword result);
54 void ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b,
55 ARMword result);
56 void ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b,
57 ARMword result);
58
59 void ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address);
60 void ARMul_STC (ARMul_State * state, ARMword instr, ARMword address);
61 void ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source);
62 ARMword ARMul_MRC (ARMul_State * state, ARMword instr);
63 void ARMul_CDP (ARMul_State * state, ARMword instr);
64 unsigned IntPending (ARMul_State * state);
65
66 ARMword ARMul_Align (ARMul_State * state, ARMword address, ARMword data);
67
68 void ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
69 unsigned (*what) ());
70 void ARMul_EnvokeEvent (ARMul_State * state);
71 unsigned long ARMul_Time (ARMul_State * state);
72 static void EnvokeList (ARMul_State * state, unsigned long from,
73 unsigned long to);
74
75 struct EventNode
76 { /* An event list node */
77 unsigned (*func) (); /* The function to call */
78 struct EventNode *next;
79 };
80
81 /***************************************************************************\
82 * This routine returns the value of a register from a mode. *
83 \***************************************************************************/
84
85 ARMword
86 ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg)
87 {
88 mode &= MODEBITS;
89 if (mode != state->Mode)
90 return (state->RegBank[ModeToBank (state, (ARMword) mode)][reg]);
91 else
92 return (state->Reg[reg]);
93 }
94
95 /***************************************************************************\
96 * This routine sets the value of a register for a mode. *
97 \***************************************************************************/
98
99 void
100 ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value)
101 {
102 mode &= MODEBITS;
103 if (mode != state->Mode)
104 state->RegBank[ModeToBank (state, (ARMword) mode)][reg] = value;
105 else
106 state->Reg[reg] = value;
107 }
108
109 /***************************************************************************\
110 * This routine returns the value of the PC, mode independently. *
111 \***************************************************************************/
112
113 ARMword
114 ARMul_GetPC (ARMul_State * state)
115 {
116 if (state->Mode > SVC26MODE)
117 return (state->Reg[15]);
118 else
119 return (R15PC);
120 }
121
122 /***************************************************************************\
123 * This routine returns the value of the PC, mode independently. *
124 \***************************************************************************/
125
126 ARMword
127 ARMul_GetNextPC (ARMul_State * state)
128 {
129 if (state->Mode > SVC26MODE)
130 return (state->Reg[15] + isize);
131 else
132 return ((state->Reg[15] + isize) & R15PCBITS);
133 }
134
135 /***************************************************************************\
136 * This routine sets the value of the PC. *
137 \***************************************************************************/
138
139 void
140 ARMul_SetPC (ARMul_State * state, ARMword value)
141 {
142 if (ARMul_MODE32BIT)
143 state->Reg[15] = value & PCBITS;
144 else
145 state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);
146 FLUSHPIPE;
147 }
148
149 /***************************************************************************\
150 * This routine returns the value of register 15, mode independently. *
151 \***************************************************************************/
152
153 ARMword
154 ARMul_GetR15 (ARMul_State * state)
155 {
156 if (state->Mode > SVC26MODE)
157 return (state->Reg[15]);
158 else
159 return (R15PC | ECC | ER15INT | EMODE);
160 }
161
162 /***************************************************************************\
163 * This routine sets the value of Register 15. *
164 \***************************************************************************/
165
166 void
167 ARMul_SetR15 (ARMul_State * state, ARMword value)
168 {
169 if (ARMul_MODE32BIT)
170 state->Reg[15] = value & PCBITS;
171 else
172 {
173 state->Reg[15] = value;
174 ARMul_R15Altered (state);
175 }
176 FLUSHPIPE;
177 }
178
179 /***************************************************************************\
180 * This routine returns the value of the CPSR *
181 \***************************************************************************/
182
183 ARMword
184 ARMul_GetCPSR (ARMul_State * state)
185 {
186 return (CPSR);
187 }
188
189 /***************************************************************************\
190 * This routine sets the value of the CPSR *
191 \***************************************************************************/
192
193 void
194 ARMul_SetCPSR (ARMul_State * state, ARMword value)
195 {
196 state->Cpsr = CPSR;
197 SETPSR (state->Cpsr, value);
198 ARMul_CPSRAltered (state);
199 }
200
201 /***************************************************************************\
202 * This routine does all the nasty bits involved in a write to the CPSR, *
203 * including updating the register bank, given a MSR instruction. *
204 \***************************************************************************/
205
206 void
207 ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
208 {
209 state->Cpsr = CPSR;
210 if (state->Bank == USERBANK)
211 { /* Only write flags in user mode */
212 if (BIT (19))
213 {
214 SETCC (state->Cpsr, rhs);
215 }
216 }
217 else
218 { /* Not a user mode */
219 if (BITS (16, 19) == 9)
220 SETPSR (state->Cpsr, rhs);
221 else if (BIT (16))
222 SETINTMODE (state->Cpsr, rhs);
223 else if (BIT (19))
224 SETCC (state->Cpsr, rhs);
225 }
226 ARMul_CPSRAltered (state);
227 }
228
229 /***************************************************************************\
230 * Get an SPSR from the specified mode *
231 \***************************************************************************/
232
233 ARMword
234 ARMul_GetSPSR (ARMul_State * state, ARMword mode)
235 {
236 ARMword bank = ModeToBank (state, mode & MODEBITS);
237 if (bank == USERBANK || bank == DUMMYBANK)
238 return (CPSR);
239 else
240 return (state->Spsr[bank]);
241 }
242
243 /***************************************************************************\
244 * This routine does a write to an SPSR *
245 \***************************************************************************/
246
247 void
248 ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
249 {
250 ARMword bank = ModeToBank (state, mode & MODEBITS);
251 if (bank != USERBANK && bank != DUMMYBANK)
252 state->Spsr[bank] = value;
253 }
254
255 /***************************************************************************\
256 * This routine does a write to the current SPSR, given an MSR instruction *
257 \***************************************************************************/
258
259 void
260 ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
261 {
262 if (state->Bank != USERBANK && state->Bank != DUMMYBANK)
263 {
264 if (BITS (16, 19) == 9)
265 SETPSR (state->Spsr[state->Bank], rhs);
266 else if (BIT (16))
267 SETINTMODE (state->Spsr[state->Bank], rhs);
268 else if (BIT (19))
269 SETCC (state->Spsr[state->Bank], rhs);
270 }
271 }
272
273 /***************************************************************************\
274 * This routine updates the state of the emulator after the Cpsr has been *
275 * changed. Both the processor flags and register bank are updated. *
276 \***************************************************************************/
277
278 void
279 ARMul_CPSRAltered (ARMul_State * state)
280 {
281 ARMword oldmode;
282
283 if (state->prog32Sig == LOW)
284 state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
285 oldmode = state->Mode;
286 if (state->Mode != (state->Cpsr & MODEBITS))
287 {
288 state->Mode =
289 ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS);
290 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
291 }
292
293 ASSIGNINT (state->Cpsr & INTBITS);
294 ASSIGNN ((state->Cpsr & NBIT) != 0);
295 ASSIGNZ ((state->Cpsr & ZBIT) != 0);
296 ASSIGNC ((state->Cpsr & CBIT) != 0);
297 ASSIGNV ((state->Cpsr & VBIT) != 0);
298 #ifdef MODET
299 ASSIGNT ((state->Cpsr & TBIT) != 0);
300 #endif
301
302 if (oldmode > SVC26MODE)
303 {
304 if (state->Mode <= SVC26MODE)
305 {
306 state->Emulate = CHANGEMODE;
307 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
308 }
309 }
310 else
311 {
312 if (state->Mode > SVC26MODE)
313 {
314 state->Emulate = CHANGEMODE;
315 state->Reg[15] = R15PC;
316 }
317 else
318 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
319 }
320
321 }
322
323 /***************************************************************************\
324 * This routine updates the state of the emulator after register 15 has *
325 * been changed. Both the processor flags and register bank are updated. *
326 * This routine should only be called from a 26 bit mode. *
327 \***************************************************************************/
328
329 void
330 ARMul_R15Altered (ARMul_State * state)
331 {
332 if (state->Mode != R15MODE)
333 {
334 state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);
335 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
336 }
337 if (state->Mode > SVC26MODE)
338 state->Emulate = CHANGEMODE;
339 ASSIGNR15INT (R15INT);
340 ASSIGNN ((state->Reg[15] & NBIT) != 0);
341 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
342 ASSIGNC ((state->Reg[15] & CBIT) != 0);
343 ASSIGNV ((state->Reg[15] & VBIT) != 0);
344 }
345
346 /***************************************************************************\
347 * This routine controls the saving and restoring of registers across mode *
348 * changes. The regbank matrix is largely unused, only rows 13 and 14 are *
349 * used across all modes, 8 to 14 are used for FIQ, all others use the USER *
350 * column. It's easier this way. old and new parameter are modes numbers. *
351 * Notice the side effect of changing the Bank variable. *
352 \***************************************************************************/
353
354 ARMword
355 ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
356 {
357 unsigned i;
358
359 oldmode = ModeToBank (state, oldmode);
360 state->Bank = ModeToBank (state, newmode);
361 if (oldmode != state->Bank)
362 { /* really need to do it */
363 switch (oldmode)
364 { /* save away the old registers */
365 case USERBANK:
366 case IRQBANK:
367 case SVCBANK:
368 case ABORTBANK:
369 case UNDEFBANK:
370 if (state->Bank == FIQBANK)
371 for (i = 8; i < 13; i++)
372 state->RegBank[USERBANK][i] = state->Reg[i];
373 state->RegBank[oldmode][13] = state->Reg[13];
374 state->RegBank[oldmode][14] = state->Reg[14];
375 break;
376 case FIQBANK:
377 for (i = 8; i < 15; i++)
378 state->RegBank[FIQBANK][i] = state->Reg[i];
379 break;
380 case DUMMYBANK:
381 for (i = 8; i < 15; i++)
382 state->RegBank[DUMMYBANK][i] = 0;
383 break;
384
385 }
386 switch (state->Bank)
387 { /* restore the new registers */
388 case USERBANK:
389 case IRQBANK:
390 case SVCBANK:
391 case ABORTBANK:
392 case UNDEFBANK:
393 if (oldmode == FIQBANK)
394 for (i = 8; i < 13; i++)
395 state->Reg[i] = state->RegBank[USERBANK][i];
396 state->Reg[13] = state->RegBank[state->Bank][13];
397 state->Reg[14] = state->RegBank[state->Bank][14];
398 break;
399 case FIQBANK:
400 for (i = 8; i < 15; i++)
401 state->Reg[i] = state->RegBank[FIQBANK][i];
402 break;
403 case DUMMYBANK:
404 for (i = 8; i < 15; i++)
405 state->Reg[i] = 0;
406 break;
407 } /* switch */
408 } /* if */
409 return (newmode);
410 }
411
412 /***************************************************************************\
413 * Given a processor mode, this routine returns the register bank that *
414 * will be accessed in that mode. *
415 \***************************************************************************/
416
417 static ARMword
418 ModeToBank (ARMul_State * state ATTRIBUTE_UNUSED, ARMword mode)
419 {
420 static ARMword bankofmode[] = { USERBANK, FIQBANK, IRQBANK, SVCBANK,
421 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
422 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
423 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
424 USERBANK, FIQBANK, IRQBANK, SVCBANK,
425 DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
426 DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK
427 };
428
429 if (mode > UNDEF32MODE)
430 return (DUMMYBANK);
431 else
432 return (bankofmode[mode]);
433 }
434
435 /***************************************************************************\
436 * Returns the register number of the nth register in a reg list. *
437 \***************************************************************************/
438
439 unsigned
440 ARMul_NthReg (ARMword instr, unsigned number)
441 {
442 unsigned bit, upto;
443
444 for (bit = 0, upto = 0; upto <= number; bit++)
445 if (BIT (bit))
446 upto++;
447 return (bit - 1);
448 }
449
450 /***************************************************************************\
451 * Assigns the N and Z flags depending on the value of result *
452 \***************************************************************************/
453
454 void
455 ARMul_NegZero (ARMul_State * state, ARMword result)
456 {
457 if (NEG (result))
458 {
459 SETN;
460 CLEARZ;
461 }
462 else if (result == 0)
463 {
464 CLEARN;
465 SETZ;
466 }
467 else
468 {
469 CLEARN;
470 CLEARZ;
471 };
472 }
473
474 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
475 int
476 AddOverflow (ARMword a, ARMword b, ARMword result)
477 {
478 return ((NEG (a) && NEG (b) && POS (result))
479 || (POS (a) && POS (b) && NEG (result)));
480 }
481
482 /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
483 int
484 SubOverflow (ARMword a, ARMword b, ARMword result)
485 {
486 return ((NEG (a) && POS (b) && POS (result))
487 || (POS (a) && NEG (b) && NEG (result)));
488 }
489
490 /***************************************************************************\
491 * Assigns the C flag after an addition of a and b to give result *
492 \***************************************************************************/
493
494 void
495 ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
496 {
497 ASSIGNC ((NEG (a) && NEG (b)) ||
498 (NEG (a) && POS (result)) || (NEG (b) && POS (result)));
499 }
500
501 /***************************************************************************\
502 * Assigns the V flag after an addition of a and b to give result *
503 \***************************************************************************/
504
505 void
506 ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
507 {
508 ASSIGNV (AddOverflow (a, b, result));
509 }
510
511 /***************************************************************************\
512 * Assigns the C flag after an subtraction of a and b to give result *
513 \***************************************************************************/
514
515 void
516 ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
517 {
518 ASSIGNC ((NEG (a) && POS (b)) ||
519 (NEG (a) && POS (result)) || (POS (b) && POS (result)));
520 }
521
522 /***************************************************************************\
523 * Assigns the V flag after an subtraction of a and b to give result *
524 \***************************************************************************/
525
526 void
527 ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
528 {
529 ASSIGNV (SubOverflow (a, b, result));
530 }
531
532 /***************************************************************************\
533 * This function does the work of generating the addresses used in an *
534 * LDC instruction. The code here is always post-indexed, it's up to the *
535 * caller to get the input address correct and to handle base register *
536 * modification. It also handles the Busy-Waiting. *
537 \***************************************************************************/
538
539 void
540 ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
541 {
542 unsigned cpab;
543 ARMword data;
544
545 UNDEF_LSCPCBaseWb;
546 if (ADDREXCEPT (address))
547 {
548 INTERNALABORT (address);
549 }
550 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
551 while (cpab == ARMul_BUSY)
552 {
553 ARMul_Icycles (state, 1, 0);
554 if (IntPending (state))
555 {
556 cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
557 return;
558 }
559 else
560 cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0);
561 }
562 if (cpab == ARMul_CANT)
563 {
564 CPTAKEABORT;
565 return;
566 }
567 cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
568 data = ARMul_LoadWordN (state, address);
569 BUSUSEDINCPCN;
570 if (BIT (21))
571 LSBase = state->Base;
572 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
573 while (cpab == ARMul_INC)
574 {
575 address += 4;
576 data = ARMul_LoadWordN (state, address);
577 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
578 }
579 if (state->abortSig || state->Aborted)
580 {
581 TAKEABORT;
582 }
583 }
584
585 /***************************************************************************\
586 * This function does the work of generating the addresses used in an *
587 * STC instruction. The code here is always post-indexed, it's up to the *
588 * caller to get the input address correct and to handle base register *
589 * modification. It also handles the Busy-Waiting. *
590 \***************************************************************************/
591
592 void
593 ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
594 {
595 unsigned cpab;
596 ARMword data;
597
598 UNDEF_LSCPCBaseWb;
599 if (ADDREXCEPT (address) || VECTORACCESS (address))
600 {
601 INTERNALABORT (address);
602 }
603 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
604 while (cpab == ARMul_BUSY)
605 {
606 ARMul_Icycles (state, 1, 0);
607 if (IntPending (state))
608 {
609 cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
610 return;
611 }
612 else
613 cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data);
614 }
615 if (cpab == ARMul_CANT)
616 {
617 CPTAKEABORT;
618 return;
619 }
620 #ifndef MODE32
621 if (ADDREXCEPT (address) || VECTORACCESS (address))
622 {
623 INTERNALABORT (address);
624 }
625 #endif
626 BUSUSEDINCPCN;
627 if (BIT (21))
628 LSBase = state->Base;
629 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
630 ARMul_StoreWordN (state, address, data);
631 while (cpab == ARMul_INC)
632 {
633 address += 4;
634 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
635 ARMul_StoreWordN (state, address, data);
636 }
637 if (state->abortSig || state->Aborted)
638 {
639 TAKEABORT;
640 }
641 }
642
643 /***************************************************************************\
644 * This function does the Busy-Waiting for an MCR instruction. *
645 \***************************************************************************/
646
647 void
648 ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
649 {
650 unsigned cpab;
651
652 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
653 while (cpab == ARMul_BUSY)
654 {
655 ARMul_Icycles (state, 1, 0);
656 if (IntPending (state))
657 {
658 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
659 return;
660 }
661 else
662 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source);
663 }
664 if (cpab == ARMul_CANT)
665 ARMul_Abort (state, ARMul_UndefinedInstrV);
666 else
667 {
668 BUSUSEDINCPCN;
669 ARMul_Ccycles (state, 1, 0);
670 }
671 }
672
673 /***************************************************************************\
674 * This function does the Busy-Waiting for an MRC instruction. *
675 \***************************************************************************/
676
677 ARMword
678 ARMul_MRC (ARMul_State * state, ARMword instr)
679 {
680 unsigned cpab;
681 ARMword result = 0;
682
683 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
684 while (cpab == ARMul_BUSY)
685 {
686 ARMul_Icycles (state, 1, 0);
687 if (IntPending (state))
688 {
689 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
690 return (0);
691 }
692 else
693 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result);
694 }
695 if (cpab == ARMul_CANT)
696 {
697 ARMul_Abort (state, ARMul_UndefinedInstrV);
698 result = ECC; /* Parent will destroy the flags otherwise */
699 }
700 else
701 {
702 BUSUSEDINCPCN;
703 ARMul_Ccycles (state, 1, 0);
704 ARMul_Icycles (state, 1, 0);
705 }
706 return (result);
707 }
708
709 /***************************************************************************\
710 * This function does the Busy-Waiting for an CDP instruction. *
711 \***************************************************************************/
712
713 void
714 ARMul_CDP (ARMul_State * state, ARMword instr)
715 {
716 unsigned cpab;
717
718 cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
719 while (cpab == ARMul_BUSY)
720 {
721 ARMul_Icycles (state, 1, 0);
722 if (IntPending (state))
723 {
724 cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr);
725 return;
726 }
727 else
728 cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
729 }
730 if (cpab == ARMul_CANT)
731 ARMul_Abort (state, ARMul_UndefinedInstrV);
732 else
733 BUSUSEDN;
734 }
735
736 /***************************************************************************\
737 * This function handles Undefined instructions, as CP isntruction *
738 \***************************************************************************/
739
740 void
741 ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED)
742 {
743 ARMul_Abort (state, ARMul_UndefinedInstrV);
744 }
745
746 /***************************************************************************\
747 * Return TRUE if an interrupt is pending, FALSE otherwise. *
748 \***************************************************************************/
749
750 unsigned
751 IntPending (ARMul_State * state)
752 {
753 if (state->Exception)
754 { /* Any exceptions */
755 if (state->NresetSig == LOW)
756 {
757 ARMul_Abort (state, ARMul_ResetV);
758 return (TRUE);
759 }
760 else if (!state->NfiqSig && !FFLAG)
761 {
762 ARMul_Abort (state, ARMul_FIQV);
763 return (TRUE);
764 }
765 else if (!state->NirqSig && !IFLAG)
766 {
767 ARMul_Abort (state, ARMul_IRQV);
768 return (TRUE);
769 }
770 }
771 return (FALSE);
772 }
773
774 /***************************************************************************\
775 * Align a word access to a non word boundary *
776 \***************************************************************************/
777
778 ARMword
779 ARMul_Align (state, address, data)
780 ARMul_State * state ATTRIBUTE_UNUSED;
781 ARMword address;
782 ARMword data;
783 {
784 /* This code assumes the address is really unaligned,
785 as a shift by 32 is undefined in C. */
786
787 address = (address & 3) << 3; /* get the word address */
788 return ((data >> address) | (data << (32 - address))); /* rot right */
789 }
790
791 /***************************************************************************\
792 * This routine is used to call another routine after a certain number of *
793 * cycles have been executed. The first parameter is the number of cycles *
794 * delay before the function is called, the second argument is a pointer *
795 * to the function. A delay of zero doesn't work, just call the function. *
796 \***************************************************************************/
797
798 void
799 ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
800 unsigned (*what) ())
801 {
802 unsigned long when;
803 struct EventNode *event;
804
805 if (state->EventSet++ == 0)
806 state->Now = ARMul_Time (state);
807 when = (state->Now + delay) % EVENTLISTSIZE;
808 event = (struct EventNode *) malloc (sizeof (struct EventNode));
809 event->func = what;
810 event->next = *(state->EventPtr + when);
811 *(state->EventPtr + when) = event;
812 }
813
814 /***************************************************************************\
815 * This routine is called at the beginning of every cycle, to envoke *
816 * scheduled events. *
817 \***************************************************************************/
818
819 void
820 ARMul_EnvokeEvent (ARMul_State * state)
821 {
822 static unsigned long then;
823
824 then = state->Now;
825 state->Now = ARMul_Time (state) % EVENTLISTSIZE;
826 if (then < state->Now) /* schedule events */
827 EnvokeList (state, then, state->Now);
828 else if (then > state->Now)
829 { /* need to wrap around the list */
830 EnvokeList (state, then, EVENTLISTSIZE - 1L);
831 EnvokeList (state, 0L, state->Now);
832 }
833 }
834
835 static void
836 EnvokeList (ARMul_State * state, unsigned long from, unsigned long to)
837 /* envokes all the entries in a range */
838 {
839 struct EventNode *anevent;
840
841 for (; from <= to; from++)
842 {
843 anevent = *(state->EventPtr + from);
844 while (anevent)
845 {
846 (anevent->func) (state);
847 state->EventSet--;
848 anevent = anevent->next;
849 }
850 *(state->EventPtr + from) = NULL;
851 }
852 }
853
854 /***************************************************************************\
855 * This routine is returns the number of clock ticks since the last reset. *
856 \***************************************************************************/
857
858 unsigned long
859 ARMul_Time (ARMul_State * state)
860 {
861 return (state->NumScycles + state->NumNcycles +
862 state->NumIcycles + state->NumCcycles + state->NumFcycles);
863 }
This page took 0.054512 seconds and 5 git commands to generate.