* armemu.h (PSR_FBITS, PSR_SBITS, PSR_XBITS, PSR_CBITS): New.
[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 (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 ((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 ((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 = value;
197 ARMul_CPSRAltered (state);
198 }
199
200 /***************************************************************************\
201 * This routine does all the nasty bits involved in a write to the CPSR, *
202 * including updating the register bank, given a MSR instruction. *
203 \***************************************************************************/
204
205 void
206 ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
207 {
208 state->Cpsr = CPSR;
209 if (state->Bank != USERBANK)
210 { /* In user mode, only write flags */
211 if (BIT (16))
212 SETPSR_C (state->Cpsr, rhs);
213 if (BIT (17))
214 SETPSR_X (state->Cpsr, rhs);
215 if (BIT (18))
216 SETPSR_S (state->Cpsr, rhs);
217 }
218 if (BIT (19))
219 SETPSR_F (state->Cpsr, rhs);
220 ARMul_CPSRAltered (state);
221 }
222
223 /***************************************************************************\
224 * Get an SPSR from the specified mode *
225 \***************************************************************************/
226
227 ARMword
228 ARMul_GetSPSR (ARMul_State * state, ARMword mode)
229 {
230 ARMword bank = ModeToBank (mode & MODEBITS);
231
232 if (! BANK_CAN_ACCESS_SPSR (bank))
233 return CPSR;
234
235 return state->Spsr[bank];
236 }
237
238 /***************************************************************************\
239 * This routine does a write to an SPSR *
240 \***************************************************************************/
241
242 void
243 ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
244 {
245 ARMword bank = ModeToBank (mode & MODEBITS);
246
247 if (BANK_CAN_ACCESS_SPSR (bank))
248 state->Spsr[bank] = value;
249 }
250
251 /***************************************************************************\
252 * This routine does a write to the current SPSR, given an MSR instruction *
253 \***************************************************************************/
254
255 void
256 ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
257 {
258 if (BANK_CAN_ACCESS_SPSR (state->Bank))
259 {
260 if (BIT (16))
261 SETPSR_C (state->Spsr[state->Bank], rhs);
262 if (BIT (17))
263 SETPSR_X (state->Spsr[state->Bank], rhs);
264 if (BIT (18))
265 SETPSR_S (state->Spsr[state->Bank], rhs);
266 if (BIT (19))
267 SETPSR_F (state->Spsr[state->Bank], rhs);
268 }
269 }
270
271 /***************************************************************************\
272 * This routine updates the state of the emulator after the Cpsr has been *
273 * changed. Both the processor flags and register bank are updated. *
274 \***************************************************************************/
275
276 void
277 ARMul_CPSRAltered (ARMul_State * state)
278 {
279 ARMword oldmode;
280
281 if (state->prog32Sig == LOW)
282 state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
283
284 oldmode = state->Mode;
285
286 if (state->Mode != (state->Cpsr & MODEBITS))
287 {
288 state->Mode =
289 ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS);
290
291 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
292 }
293
294 ASSIGNINT (state->Cpsr & INTBITS);
295 ASSIGNN ((state->Cpsr & NBIT) != 0);
296 ASSIGNZ ((state->Cpsr & ZBIT) != 0);
297 ASSIGNC ((state->Cpsr & CBIT) != 0);
298 ASSIGNV ((state->Cpsr & VBIT) != 0);
299 #ifdef MODET
300 ASSIGNT ((state->Cpsr & TBIT) != 0);
301 #endif
302
303 if (oldmode > SVC26MODE)
304 {
305 if (state->Mode <= SVC26MODE)
306 {
307 state->Emulate = CHANGEMODE;
308 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
309 }
310 }
311 else
312 {
313 if (state->Mode > SVC26MODE)
314 {
315 state->Emulate = CHANGEMODE;
316 state->Reg[15] = R15PC;
317 }
318 else
319 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
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 ARMword oldbank;
359 ARMword newbank;
360
361 oldbank = ModeToBank (oldmode);
362 newbank = state->Bank = ModeToBank (newmode);
363
364 if (oldbank != newbank)
365 { /* really need to do it */
366 switch (oldbank)
367 { /* save away the old registers */
368 case USERBANK:
369 case IRQBANK:
370 case SVCBANK:
371 case ABORTBANK:
372 case UNDEFBANK:
373 if (newbank == FIQBANK)
374 for (i = 8; i < 13; i++)
375 state->RegBank[USERBANK][i] = state->Reg[i];
376 state->RegBank[oldbank][13] = state->Reg[13];
377 state->RegBank[oldbank][14] = state->Reg[14];
378 break;
379 case FIQBANK:
380 for (i = 8; i < 15; i++)
381 state->RegBank[FIQBANK][i] = state->Reg[i];
382 break;
383 case DUMMYBANK:
384 for (i = 8; i < 15; i++)
385 state->RegBank[DUMMYBANK][i] = 0;
386 break;
387 default:
388 abort ();
389 }
390
391 switch (newbank)
392 { /* restore the new registers */
393 case USERBANK:
394 case IRQBANK:
395 case SVCBANK:
396 case ABORTBANK:
397 case UNDEFBANK:
398 if (oldbank == FIQBANK)
399 for (i = 8; i < 13; i++)
400 state->Reg[i] = state->RegBank[USERBANK][i];
401 state->Reg[13] = state->RegBank[newbank][13];
402 state->Reg[14] = state->RegBank[newbank][14];
403 break;
404 case FIQBANK:
405 for (i = 8; i < 15; i++)
406 state->Reg[i] = state->RegBank[FIQBANK][i];
407 break;
408 case DUMMYBANK:
409 for (i = 8; i < 15; i++)
410 state->Reg[i] = 0;
411 break;
412 default:
413 abort ();
414 } /* switch */
415 } /* if */
416
417 return newmode;
418 }
419
420 /***************************************************************************\
421 * Given a processor mode, this routine returns the register bank that *
422 * will be accessed in that mode. *
423 \***************************************************************************/
424
425 static ARMword
426 ModeToBank (ARMword mode)
427 {
428 static ARMword bankofmode[] =
429 {
430 USERBANK, FIQBANK, IRQBANK, SVCBANK,
431 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
432 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
433 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
434 USERBANK, FIQBANK, IRQBANK, SVCBANK,
435 DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
436 DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK,
437 DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK
438 };
439
440 if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0])))
441 return DUMMYBANK;
442
443 return bankofmode[mode];
444 }
445
446 /***************************************************************************\
447 * Returns the register number of the nth register in a reg list. *
448 \***************************************************************************/
449
450 unsigned
451 ARMul_NthReg (ARMword instr, unsigned number)
452 {
453 unsigned bit, upto;
454
455 for (bit = 0, upto = 0; upto <= number; bit++)
456 if (BIT (bit))
457 upto++;
458 return (bit - 1);
459 }
460
461 /***************************************************************************\
462 * Assigns the N and Z flags depending on the value of result *
463 \***************************************************************************/
464
465 void
466 ARMul_NegZero (ARMul_State * state, ARMword result)
467 {
468 if (NEG (result))
469 {
470 SETN;
471 CLEARZ;
472 }
473 else if (result == 0)
474 {
475 CLEARN;
476 SETZ;
477 }
478 else
479 {
480 CLEARN;
481 CLEARZ;
482 };
483 }
484
485 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
486 int
487 AddOverflow (ARMword a, ARMword b, ARMword result)
488 {
489 return ((NEG (a) && NEG (b) && POS (result))
490 || (POS (a) && POS (b) && NEG (result)));
491 }
492
493 /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
494 int
495 SubOverflow (ARMword a, ARMword b, ARMword result)
496 {
497 return ((NEG (a) && POS (b) && POS (result))
498 || (POS (a) && NEG (b) && NEG (result)));
499 }
500
501 /***************************************************************************\
502 * Assigns the C flag after an addition of a and b to give result *
503 \***************************************************************************/
504
505 void
506 ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
507 {
508 ASSIGNC ((NEG (a) && NEG (b)) ||
509 (NEG (a) && POS (result)) || (NEG (b) && POS (result)));
510 }
511
512 /***************************************************************************\
513 * Assigns the V flag after an addition of a and b to give result *
514 \***************************************************************************/
515
516 void
517 ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
518 {
519 ASSIGNV (AddOverflow (a, b, result));
520 }
521
522 /***************************************************************************\
523 * Assigns the C flag after an subtraction of a and b to give result *
524 \***************************************************************************/
525
526 void
527 ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
528 {
529 ASSIGNC ((NEG (a) && POS (b)) ||
530 (NEG (a) && POS (result)) || (POS (b) && POS (result)));
531 }
532
533 /***************************************************************************\
534 * Assigns the V flag after an subtraction of a and b to give result *
535 \***************************************************************************/
536
537 void
538 ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
539 {
540 ASSIGNV (SubOverflow (a, b, result));
541 }
542
543 /***************************************************************************\
544 * This function does the work of generating the addresses used in an *
545 * LDC instruction. The code here is always post-indexed, it's up to the *
546 * caller to get the input address correct and to handle base register *
547 * modification. It also handles the Busy-Waiting. *
548 \***************************************************************************/
549
550 void
551 ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
552 {
553 unsigned cpab;
554 ARMword data;
555
556 UNDEF_LSCPCBaseWb;
557 if (ADDREXCEPT (address))
558 {
559 INTERNALABORT (address);
560 }
561 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
562 while (cpab == ARMul_BUSY)
563 {
564 ARMul_Icycles (state, 1, 0);
565 if (IntPending (state))
566 {
567 cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
568 return;
569 }
570 else
571 cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0);
572 }
573 if (cpab == ARMul_CANT)
574 {
575 CPTAKEABORT;
576 return;
577 }
578 cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
579 data = ARMul_LoadWordN (state, address);
580 BUSUSEDINCPCN;
581 if (BIT (21))
582 LSBase = state->Base;
583 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
584 while (cpab == ARMul_INC)
585 {
586 address += 4;
587 data = ARMul_LoadWordN (state, address);
588 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
589 }
590 if (state->abortSig || state->Aborted)
591 {
592 TAKEABORT;
593 }
594 }
595
596 /***************************************************************************\
597 * This function does the work of generating the addresses used in an *
598 * STC instruction. The code here is always post-indexed, it's up to the *
599 * caller to get the input address correct and to handle base register *
600 * modification. It also handles the Busy-Waiting. *
601 \***************************************************************************/
602
603 void
604 ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
605 {
606 unsigned cpab;
607 ARMword data;
608
609 UNDEF_LSCPCBaseWb;
610 if (ADDREXCEPT (address) || VECTORACCESS (address))
611 {
612 INTERNALABORT (address);
613 }
614 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
615 while (cpab == ARMul_BUSY)
616 {
617 ARMul_Icycles (state, 1, 0);
618 if (IntPending (state))
619 {
620 cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
621 return;
622 }
623 else
624 cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data);
625 }
626 if (cpab == ARMul_CANT)
627 {
628 CPTAKEABORT;
629 return;
630 }
631 #ifndef MODE32
632 if (ADDREXCEPT (address) || VECTORACCESS (address))
633 {
634 INTERNALABORT (address);
635 }
636 #endif
637 BUSUSEDINCPCN;
638 if (BIT (21))
639 LSBase = state->Base;
640 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
641 ARMul_StoreWordN (state, address, data);
642 while (cpab == ARMul_INC)
643 {
644 address += 4;
645 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
646 ARMul_StoreWordN (state, address, data);
647 }
648 if (state->abortSig || state->Aborted)
649 {
650 TAKEABORT;
651 }
652 }
653
654 /***************************************************************************\
655 * This function does the Busy-Waiting for an MCR instruction. *
656 \***************************************************************************/
657
658 void
659 ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
660 {
661 unsigned cpab;
662
663 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
664
665 while (cpab == ARMul_BUSY)
666 {
667 ARMul_Icycles (state, 1, 0);
668
669 if (IntPending (state))
670 {
671 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
672 return;
673 }
674 else
675 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source);
676 }
677
678 if (cpab == ARMul_CANT)
679 ARMul_Abort (state, ARMul_UndefinedInstrV);
680 else
681 {
682 BUSUSEDINCPCN;
683 ARMul_Ccycles (state, 1, 0);
684 }
685 }
686
687 /***************************************************************************\
688 * This function does the Busy-Waiting for an MRC instruction. *
689 \***************************************************************************/
690
691 ARMword
692 ARMul_MRC (ARMul_State * state, ARMword instr)
693 {
694 unsigned cpab;
695 ARMword result = 0;
696
697 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
698 while (cpab == ARMul_BUSY)
699 {
700 ARMul_Icycles (state, 1, 0);
701 if (IntPending (state))
702 {
703 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
704 return (0);
705 }
706 else
707 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result);
708 }
709 if (cpab == ARMul_CANT)
710 {
711 ARMul_Abort (state, ARMul_UndefinedInstrV);
712 result = ECC; /* Parent will destroy the flags otherwise */
713 }
714 else
715 {
716 BUSUSEDINCPCN;
717 ARMul_Ccycles (state, 1, 0);
718 ARMul_Icycles (state, 1, 0);
719 }
720 return (result);
721 }
722
723 /***************************************************************************\
724 * This function does the Busy-Waiting for an CDP instruction. *
725 \***************************************************************************/
726
727 void
728 ARMul_CDP (ARMul_State * state, ARMword instr)
729 {
730 unsigned cpab;
731
732 cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
733 while (cpab == ARMul_BUSY)
734 {
735 ARMul_Icycles (state, 1, 0);
736 if (IntPending (state))
737 {
738 cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr);
739 return;
740 }
741 else
742 cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
743 }
744 if (cpab == ARMul_CANT)
745 ARMul_Abort (state, ARMul_UndefinedInstrV);
746 else
747 BUSUSEDN;
748 }
749
750 /***************************************************************************\
751 * This function handles Undefined instructions, as CP isntruction *
752 \***************************************************************************/
753
754 void
755 ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED)
756 {
757 ARMul_Abort (state, ARMul_UndefinedInstrV);
758 }
759
760 /***************************************************************************\
761 * Return TRUE if an interrupt is pending, FALSE otherwise. *
762 \***************************************************************************/
763
764 unsigned
765 IntPending (ARMul_State * state)
766 {
767 if (state->Exception)
768 { /* Any exceptions */
769 if (state->NresetSig == LOW)
770 {
771 ARMul_Abort (state, ARMul_ResetV);
772 return (TRUE);
773 }
774 else if (!state->NfiqSig && !FFLAG)
775 {
776 ARMul_Abort (state, ARMul_FIQV);
777 return (TRUE);
778 }
779 else if (!state->NirqSig && !IFLAG)
780 {
781 ARMul_Abort (state, ARMul_IRQV);
782 return (TRUE);
783 }
784 }
785 return (FALSE);
786 }
787
788 /***************************************************************************\
789 * Align a word access to a non word boundary *
790 \***************************************************************************/
791
792 ARMword
793 ARMul_Align (state, address, data)
794 ARMul_State * state ATTRIBUTE_UNUSED;
795 ARMword address;
796 ARMword data;
797 {
798 /* This code assumes the address is really unaligned,
799 as a shift by 32 is undefined in C. */
800
801 address = (address & 3) << 3; /* get the word address */
802 return ((data >> address) | (data << (32 - address))); /* rot right */
803 }
804
805 /***************************************************************************\
806 * This routine is used to call another routine after a certain number of *
807 * cycles have been executed. The first parameter is the number of cycles *
808 * delay before the function is called, the second argument is a pointer *
809 * to the function. A delay of zero doesn't work, just call the function. *
810 \***************************************************************************/
811
812 void
813 ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
814 unsigned (*what) ())
815 {
816 unsigned long when;
817 struct EventNode *event;
818
819 if (state->EventSet++ == 0)
820 state->Now = ARMul_Time (state);
821 when = (state->Now + delay) % EVENTLISTSIZE;
822 event = (struct EventNode *) malloc (sizeof (struct EventNode));
823 event->func = what;
824 event->next = *(state->EventPtr + when);
825 *(state->EventPtr + when) = event;
826 }
827
828 /***************************************************************************\
829 * This routine is called at the beginning of every cycle, to envoke *
830 * scheduled events. *
831 \***************************************************************************/
832
833 void
834 ARMul_EnvokeEvent (ARMul_State * state)
835 {
836 static unsigned long then;
837
838 then = state->Now;
839 state->Now = ARMul_Time (state) % EVENTLISTSIZE;
840 if (then < state->Now) /* schedule events */
841 EnvokeList (state, then, state->Now);
842 else if (then > state->Now)
843 { /* need to wrap around the list */
844 EnvokeList (state, then, EVENTLISTSIZE - 1L);
845 EnvokeList (state, 0L, state->Now);
846 }
847 }
848
849 static void
850 EnvokeList (ARMul_State * state, unsigned long from, unsigned long to)
851 /* envokes all the entries in a range */
852 {
853 struct EventNode *anevent;
854
855 for (; from <= to; from++)
856 {
857 anevent = *(state->EventPtr + from);
858 while (anevent)
859 {
860 (anevent->func) (state);
861 state->EventSet--;
862 anevent = anevent->next;
863 }
864 *(state->EventPtr + from) = NULL;
865 }
866 }
867
868 /***************************************************************************\
869 * This routine is returns the number of clock ticks since the last reset. *
870 \***************************************************************************/
871
872 unsigned long
873 ARMul_Time (ARMul_State * state)
874 {
875 return (state->NumScycles + state->NumNcycles +
876 state->NumIcycles + state->NumCcycles + state->NumFcycles);
877 }