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