This commit was generated by cvs2svn to track changes on a CVS vendor
[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 (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 }