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