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