void Z80::nmi() { if (!m_IFF1) { return; } m_IFF1 = false; m_IFF2 = false; int cycles; switch(m_interruptMode) { case 0: // Not used by the ULA, not completely implemented runInstruction(255); // RST 38 m_cyclesSinceLastFrame += 13; break; case 1: cycles = runInstruction(255); // RST 38 m_cyclesSinceLastFrame += cycles + 2; break; case 2: // Data bus value not implemented uint16_t pos = m_registers.IR.bytes.high * 256 + 255; uint8_t low = (*m_memory)[pos]; uint8_t high = (*m_memory)[pos+1]; uint16_t address = CREATE_WORD(low, high); m_registers.SP--; (*m_memory)[m_registers.SP] = m_registers.PC >> 8; m_registers.SP--; (*m_memory)[m_registers.SP] = m_registers.PC & 0xFF; m_registers.PC = address; m_cyclesSinceLastFrame += 19; break; } }
///////////////////////////////////////////////////////////////////////////////////////// //// SLOTS ////////// void BfVM::step() { qDebug("BfVM::step()"); //Q_ASSERT_X(m_IP < m_programSize, "BfVM::step()", "IP larger than program size"); /* If we've reached the last instruction, post an EndEvent and let the state machine handle the rest */ if(m_IP >= m_programSize) { qDebug("BfVM::step() program end reached"); m_stateMachine->postEvent(new EndEvent); return; } // Inform the world of our IP emit heartBeat(m_IP); // NOTE: the IP is increased by the runInstruction() function runInstruction(m_program[m_IP]); // emit "heart beat" with current IP and then increase it }
void Z80::nextInstruction() { std::map<int, Breakpoint>* breakpoints = m_debugger->getBreakpoints(); for (auto it = breakpoints->begin(); it != breakpoints->end(); ++it) { // TODO: move to function? if ( *(it->second.getEnabled()) && *( it->second.getAddress()) == m_registers.PC ) { if ( (*(it->second.getCondition())) == BreakpointCondition::NONE) { m_debugger->breakExecution(); break; } uint16_t conditionValue = conditionToRegisterValue(*(it->second.getCondition()), &m_registers); bool conditionMet = true; switch (*(it->second.getOperator())) { case BreakpointConditionOperator::GT: conditionMet = conditionValue > *(it->second.getConditionNumber()); break; case BreakpointConditionOperator::LT: conditionMet = conditionValue < *(it->second.getConditionNumber()); break; case BreakpointConditionOperator::EQ: conditionMet = conditionValue == *(it->second.getConditionNumber()); break; case BreakpointConditionOperator::LE: conditionMet = conditionValue <= *(it->second.getConditionNumber()); break; case BreakpointConditionOperator::GE: conditionMet = conditionValue >= *(it->second.getConditionNumber()); break; case BreakpointConditionOperator::NE: conditionMet = conditionValue != *(it->second.getConditionNumber()); break; } if (conditionMet) { m_debugger->breakExecution(); break; } } } int instruction = parseNextInstruction(); int numBytes = ( instruction >= 5*256 ) ? 3 : ( instruction >= 256 ) ? 2 : 1; m_registers.PC += numBytes; int cycles = runInstruction(instruction); if (m_debugger->shouldBreak()) { // TODO: move to function? InstructionTrace trace; trace.address = m_registers.PC - numBytes; trace.registers = m_registers; trace.IFF1 = m_IFF1; trace.IFF2 = m_IFF2; trace.interruptMode = m_interruptMode; trace.frameCycleNumber = m_cyclesSinceLastFrame; Instruction inst = (*m_instructionSet)[instruction]; trace.mnemonic = inst.mnemonic; trace.bytes = getInstructionData(inst, instruction, m_registers.PC - inst.numDataBytes); std::vector<uint8_t> opcodeBytes; for (int i = 0; i < numBytes; ++i) { opcodeBytes.push_back((*m_memory)[m_registers.PC - inst.numDataBytes - numBytes + i]); } trace.opcodeBytes = opcodeBytes; m_debugger->addTrace(trace); } m_cyclesSinceLastFrame += cycles; }