| 446 | } |
| 447 | |
| 448 | static __forceinline bool IRQ(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn, BOOL& flagv, BOOL& flagz) |
| 449 | { |
| 450 | bool irqTaken = false; |
| 451 | |
| 452 | if (g_bmIRQ && !(regs.ps & AF_INTERRUPT)) |
| 453 | { |
| 454 | // if interrupt (eg. from 6522) occurs on opcode's last cycle, then defer IRQ by 1 opcode |
| 455 | if (g_irqOnLastOpcodeCycle && !g_irqDefer1Opcode) |
| 456 | { |
| 457 | g_irqOnLastOpcodeCycle = false; |
| 458 | g_irqDefer1Opcode = true; // if INT occurs again on next opcode, then do NOT defer |
| 459 | return false; |
| 460 | } |
| 461 | |
| 462 | g_irqDefer1Opcode = false; |
| 463 | |
| 464 | // IRQ signals are deasserted when a specific r/w operation is done on device |
| 465 | #ifdef _DEBUG |
| 466 | g_nCycleIrqStart = g_nCumulativeCycles + uExecutedCycles; |
| 467 | #endif |
| 468 | if (GetIsMemCacheValid()) |
| 469 | { |
| 470 | _PUSH(regs.pc >> 8) |
| 471 | _PUSH(regs.pc & 0xFF) |
| 472 | EF_TO_AF; |
| 473 | _PUSH(regs.ps & ~AF_BREAK) |
| 474 | regs.ps |= AF_INTERRUPT; |
| 475 | if (GetMainCpu() == CPU_65C02) // GH#1099 |
| 476 | regs.ps &= ~AF_DECIMAL; |
| 477 | regs.pc = *(WORD*)(mem + _6502_INTERRUPT_VECTOR); |
| 478 | } |
| 479 | else |
| 480 | { |
| 481 | _PUSH_ALT(regs.pc >> 8) |
| 482 | _PUSH_ALT(regs.pc & 0xFF) |
| 483 | EF_TO_AF; |
| 484 | _PUSH_ALT(regs.ps & ~AF_BREAK) |
| 485 | regs.ps |= AF_INTERRUPT; |
| 486 | if (GetMainCpu() == CPU_65C02) // GH#1099 |
| 487 | regs.ps &= ~AF_DECIMAL; |
| 488 | regs.pc = READ_WORD_ALT(_6502_INTERRUPT_VECTOR); |
| 489 | } |
| 490 | UINT uExtraCycles = 0; // Needed for CYC(a) macro |
| 491 | CYC(7); |
| 492 | #if defined(_DEBUG) && LOG_IRQ_TAKEN_AND_RTI |
| 493 | std::string irq6522; |
| 494 | GetCardMgr().GetMockingboardCardMgr().Get6522IrqDescription(irq6522); |
| 495 | const char* pSrc = (g_bmIRQ & 1) ? irq6522.c_str() : |
| 496 | (g_bmIRQ & 2) ? "SPEECH" : |
| 497 | (g_bmIRQ & 4) ? "SSC" : |
| 498 | (g_bmIRQ & 8) ? "MOUSE" : "UNKNOWN"; |
| 499 | LogOutput("IRQ (%08X) (%s)\n", (UINT)g_nCycleIrqStart, pSrc); |
| 500 | #endif |
| 501 | g_interruptInLastExecutionBatch = true; |
| 502 | irqTaken = true; |
| 503 | } |
| 504 | |
| 505 | g_irqOnLastOpcodeCycle = false; |
no test coverage detected