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 3 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, see <http://www.gnu.org/licenses/>. */ 16 17 #include "armdefs.h" 18 #include "armemu.h" 19 #include "ansidecl.h" 20 21 /* Definitions for the support routines. */ 22 23 static ARMword ModeToBank (ARMword); 24 static void EnvokeList (ARMul_State *, unsigned long, unsigned long); 25 26 struct EventNode 27 { /* An event list node. */ 28 unsigned (*func) (ARMul_State *); /* The function to call. */ 29 struct EventNode *next; 30 }; 31 32 /* This routine returns the value of a register from a mode. */ 33 34 ARMword 35 ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg) 36 { 37 mode &= MODEBITS; 38 if (mode != state->Mode) 39 return (state->RegBank[ModeToBank ((ARMword) mode)][reg]); 40 else 41 return (state->Reg[reg]); 42 } 43 44 /* This routine sets the value of a register for a mode. */ 45 46 void 47 ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value) 48 { 49 mode &= MODEBITS; 50 if (mode != state->Mode) 51 state->RegBank[ModeToBank ((ARMword) mode)][reg] = value; 52 else 53 state->Reg[reg] = value; 54 } 55 56 /* This routine returns the value of the PC, mode independently. */ 57 58 ARMword 59 ARMul_GetPC (ARMul_State * state) 60 { 61 if (state->Mode > SVC26MODE) 62 return state->Reg[15]; 63 else 64 return R15PC; 65 } 66 67 /* This routine returns the value of the PC, mode independently. */ 68 69 ARMword 70 ARMul_GetNextPC (ARMul_State * state) 71 { 72 if (state->Mode > SVC26MODE) 73 return state->Reg[15] + isize; 74 else 75 return (state->Reg[15] + isize) & R15PCBITS; 76 } 77 78 /* This routine sets the value of the PC. */ 79 80 void 81 ARMul_SetPC (ARMul_State * state, ARMword value) 82 { 83 if (ARMul_MODE32BIT) 84 state->Reg[15] = value & PCBITS; 85 else 86 state->Reg[15] = R15CCINTMODE | (value & R15PCBITS); 87 FLUSHPIPE; 88 } 89 90 /* This routine returns the value of register 15, mode independently. */ 91 92 ARMword 93 ARMul_GetR15 (ARMul_State * state) 94 { 95 if (state->Mode > SVC26MODE) 96 return (state->Reg[15]); 97 else 98 return (R15PC | ECC | ER15INT | EMODE); 99 } 100 101 /* This routine sets the value of Register 15. */ 102 103 void 104 ARMul_SetR15 (ARMul_State * state, ARMword value) 105 { 106 if (ARMul_MODE32BIT) 107 state->Reg[15] = value & PCBITS; 108 else 109 { 110 state->Reg[15] = value; 111 ARMul_R15Altered (state); 112 } 113 FLUSHPIPE; 114 } 115 116 /* This routine returns the value of the CPSR. */ 117 118 ARMword 119 ARMul_GetCPSR (ARMul_State * state) 120 { 121 return (CPSR | state->Cpsr); 122 } 123 124 /* This routine sets the value of the CPSR. */ 125 126 void 127 ARMul_SetCPSR (ARMul_State * state, ARMword value) 128 { 129 state->Cpsr = value; 130 ARMul_CPSRAltered (state); 131 } 132 133 /* This routine does all the nasty bits involved in a write to the CPSR, 134 including updating the register bank, given a MSR instruction. */ 135 136 void 137 ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs) 138 { 139 state->Cpsr = ARMul_GetCPSR (state); 140 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 #endif 573 BUSUSEDINCPCN; 574 if (BIT (21)) 575 LSBase = state->Base; 576 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); 577 ARMul_StoreWordN (state, address, data); 578 579 while (cpab == ARMul_INC) 580 { 581 address += 4; 582 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); 583 ARMul_StoreWordN (state, address, data); 584 } 585 586 if (state->abortSig || state->Aborted) 587 TAKEABORT; 588 } 589 590 /* This function does the Busy-Waiting for an MCR instruction. */ 591 592 void 593 ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) 594 { 595 unsigned cpab; 596 597 if (! CP_ACCESS_ALLOWED (state, CPNum)) 598 { 599 ARMul_UndefInstr (state, instr); 600 return; 601 } 602 603 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source); 604 605 while (cpab == ARMul_BUSY) 606 { 607 ARMul_Icycles (state, 1, 0); 608 609 if (IntPending (state)) 610 { 611 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0); 612 return; 613 } 614 else 615 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source); 616 } 617 618 if (cpab == ARMul_CANT) 619 ARMul_Abort (state, ARMul_UndefinedInstrV); 620 else 621 { 622 BUSUSEDINCPCN; 623 ARMul_Ccycles (state, 1, 0); 624 } 625 } 626 627 /* This function does the Busy-Waiting for an MRC instruction. */ 628 629 ARMword 630 ARMul_MRC (ARMul_State * state, ARMword instr) 631 { 632 unsigned cpab; 633 ARMword result = 0; 634 635 if (! CP_ACCESS_ALLOWED (state, CPNum)) 636 { 637 ARMul_UndefInstr (state, instr); 638 return result; 639 } 640 641 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result); 642 while (cpab == ARMul_BUSY) 643 { 644 ARMul_Icycles (state, 1, 0); 645 if (IntPending (state)) 646 { 647 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0); 648 return (0); 649 } 650 else 651 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result); 652 } 653 if (cpab == ARMul_CANT) 654 { 655 ARMul_Abort (state, ARMul_UndefinedInstrV); 656 /* Parent will destroy the flags otherwise. */ 657 result = ECC; 658 } 659 else 660 { 661 BUSUSEDINCPCN; 662 ARMul_Ccycles (state, 1, 0); 663 ARMul_Icycles (state, 1, 0); 664 } 665 666 return result; 667 } 668 669 /* This function does the Busy-Waiting for an CDP instruction. */ 670 671 void 672 ARMul_CDP (ARMul_State * state, ARMword instr) 673 { 674 unsigned cpab; 675 676 if (! CP_ACCESS_ALLOWED (state, CPNum)) 677 { 678 ARMul_UndefInstr (state, instr); 679 return; 680 } 681 682 cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr); 683 while (cpab == ARMul_BUSY) 684 { 685 ARMul_Icycles (state, 1, 0); 686 if (IntPending (state)) 687 { 688 cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr); 689 return; 690 } 691 else 692 cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr); 693 } 694 if (cpab == ARMul_CANT) 695 ARMul_Abort (state, ARMul_UndefinedInstrV); 696 else 697 BUSUSEDN; 698 } 699 700 /* This function handles Undefined instructions, as CP isntruction. */ 701 702 void 703 ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED) 704 { 705 ARMul_Abort (state, ARMul_UndefinedInstrV); 706 } 707 708 /* Return TRUE if an interrupt is pending, FALSE otherwise. */ 709 710 unsigned 711 IntPending (ARMul_State * state) 712 { 713 if (state->Exception) 714 { 715 /* Any exceptions. */ 716 if (state->NresetSig == LOW) 717 { 718 ARMul_Abort (state, ARMul_ResetV); 719 return TRUE; 720 } 721 else if (!state->NfiqSig && !FFLAG) 722 { 723 ARMul_Abort (state, ARMul_FIQV); 724 return TRUE; 725 } 726 else if (!state->NirqSig && !IFLAG) 727 { 728 ARMul_Abort (state, ARMul_IRQV); 729 return TRUE; 730 } 731 } 732 733 return FALSE; 734 } 735 736 /* Align a word access to a non word boundary. */ 737 738 ARMword 739 ARMul_Align (state, address, data) 740 ARMul_State * state ATTRIBUTE_UNUSED; 741 ARMword address; 742 ARMword data; 743 { 744 /* This code assumes the address is really unaligned, 745 as a shift by 32 is undefined in C. */ 746 747 address = (address & 3) << 3; /* Get the word address. */ 748 return ((data >> address) | (data << (32 - address))); /* rot right */ 749 } 750 751 /* This routine is used to call another routine after a certain number of 752 cycles have been executed. The first parameter is the number of cycles 753 delay before the function is called, the second argument is a pointer 754 to the function. A delay of zero doesn't work, just call the function. */ 755 756 void 757 ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay, 758 unsigned (*what) (ARMul_State *)) 759 { 760 unsigned long when; 761 struct EventNode *event; 762 763 if (state->EventSet++ == 0) 764 state->Now = ARMul_Time (state); 765 when = (state->Now + delay) % EVENTLISTSIZE; 766 event = (struct EventNode *) malloc (sizeof (struct EventNode)); 767 event->func = what; 768 event->next = *(state->EventPtr + when); 769 *(state->EventPtr + when) = event; 770 } 771 772 /* This routine is called at the beginning of 773 every cycle, to envoke scheduled events. */ 774 775 void 776 ARMul_EnvokeEvent (ARMul_State * state) 777 { 778 static unsigned long then; 779 780 then = state->Now; 781 state->Now = ARMul_Time (state) % EVENTLISTSIZE; 782 if (then < state->Now) 783 /* Schedule events. */ 784 EnvokeList (state, then, state->Now); 785 else if (then > state->Now) 786 { 787 /* Need to wrap around the list. */ 788 EnvokeList (state, then, EVENTLISTSIZE - 1L); 789 EnvokeList (state, 0L, state->Now); 790 } 791 } 792 793 /* Envokes all the entries in a range. */ 794 795 static void 796 EnvokeList (ARMul_State * state, unsigned long from, unsigned long to) 797 { 798 for (; from <= to; from++) 799 { 800 struct EventNode *anevent; 801 802 anevent = *(state->EventPtr + from); 803 while (anevent) 804 { 805 (anevent->func) (state); 806 state->EventSet--; 807 anevent = anevent->next; 808 } 809 *(state->EventPtr + from) = NULL; 810 } 811 } 812 813 /* This routine is returns the number of clock ticks since the last reset. */ 814 815 unsigned long 816 ARMul_Time (ARMul_State * state) 817 { 818 return (state->NumScycles + state->NumNcycles + 819 state->NumIcycles + state->NumCcycles + state->NumFcycles); 820 } 821