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