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