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