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