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