// $Id: CPUCore.cc 6127 2007-03-01 09:30:39Z m9710797 $ #include "MSXCPUInterface.hh" #include "Scheduler.hh" #include "MSXMotherBoard.hh" #include "MSXCliComm.hh" #include "Event.hh" #include "EventDistributor.hh" #include "BooleanSetting.hh" #include "IntegerSetting.hh" #include "Dasm.hh" #include "CPUCore.hh" #include "Z80.hh" #include "R800.hh" #include "Thread.hh" #include "likely.hh" #include #include #include using std::string; namespace openmsx { template CPUCore::CPUCore( MSXMotherBoard& motherboard_, const string& name, const BooleanSetting& traceSetting_, const EmuTime& time) : T(time) , nmiEdge(false) , NMIStatus(0) , IRQStatus(0) , exitLoop(false) , interface(NULL) , motherboard(motherboard_) , scheduler(motherboard.getScheduler()) , freqLocked(new BooleanSetting(motherboard.getCommandController(), name + "_freq_locked", "real (locked) or custom (unlocked) " + name + " frequency", true)) , freqValue(new IntegerSetting(motherboard.getCommandController(), name + "_freq", "custom " + name + " frequency (only valid when unlocked)", T::CLOCK_FREQ, 1000000, 100000000)) , freq(T::CLOCK_FREQ) , traceSetting(traceSetting_) { if (freqLocked->getValue()) { // locked T::setFreq(T::CLOCK_FREQ); } else { // unlocked T::setFreq(freqValue->getValue()); } freqLocked->attach(*this); freqValue->attach(*this); doReset(time); } template CPUCore::~CPUCore() { freqValue->detach(*this); freqLocked->detach(*this); } template void CPUCore::setInterface(MSXCPUInterface* interf) { interface = interf; } template void CPUCore::warp(const EmuTime& time) { assert(T::getTime() <= time); T::setTime(time); } template const EmuTime& CPUCore::getCurrentTime() const { return T::getTime(); } template void CPUCore::invalidateMemCache(word start, unsigned size) { unsigned first = start / CacheLine::SIZE; unsigned num = (size + CacheLine::SIZE - 1) / CacheLine::SIZE; memset(&readCacheLine [first], 0, num * sizeof(byte*)); // NULL memset(&writeCacheLine [first], 0, num * sizeof(byte*)); // memset(&readCacheTried [first], 0, num * sizeof(bool)); // FALSE memset(&writeCacheTried[first], 0, num * sizeof(bool)); // } template CPU::CPURegs& CPUCore::getRegisters() { return R; } template void CPUCore::doReset(const EmuTime& time) { // AF and SP are 0xFFFF // PC, R, IFF1, IFF2, HALT and IM are 0x0 // all others are random R.AF = 0xFFFF; R.BC = 0xFFFF; R.DE = 0xFFFF; R.HL = 0xFFFF; R.IX = 0xFFFF; R.IY = 0xFFFF; R.PC = 0x0000; R.SP = 0xFFFF; R.AF2 = 0xFFFF; R.BC2 = 0xFFFF; R.DE2 = 0xFFFF; R.HL2 = 0xFFFF; R.nextIFF1 = false; R.IFF1 = false; R.IFF2 = false; R.HALT = false; R.IM = 0; R.I = 0x00; R.R = 0x00; R.R2 = 0; memptr = 0xFFFF; invalidateMemCache(0x0000, 0x10000); assert(T::getTime() <= time); T::setTime(time); assert(NMIStatus == 0); // other devices must reset their NMI source assert(IRQStatus == 0); // other devices must reset their IRQ source } // I believe the following two methods are thread safe even without any // locking. The worst that can happen is that we occasionally needlessly // exit the CPU loop, but that's harmless // TODO thread issues are always tricky, can someone confirm this really // is thread safe template void CPUCore::exitCPULoopAsync() { // can get called from non-main threads exitLoop = true; } template void CPUCore::exitCPULoopSync() { assert(Thread::isMainThread()); exitLoop = true; T::enableLimit(false); } template inline bool CPUCore::needExitCPULoop() { // always executed in main thread if (unlikely(exitLoop)) { exitLoop = false; return true; } return false; } template void CPUCore::setSlowInstructions() { slowInstructions = 2; T::enableLimit(false); } template void CPUCore::raiseIRQ() { assert(IRQStatus >= 0); if (IRQStatus == 0) { setSlowInstructions(); } IRQStatus++; } template void CPUCore::lowerIRQ() { IRQStatus--; assert(IRQStatus >= 0); } template void CPUCore::raiseNMI() { assert(NMIStatus >= 0); if (NMIStatus == 0) { nmiEdge = true; setSlowInstructions(); } NMIStatus++; } template void CPUCore::lowerNMI() { NMIStatus--; assert(NMIStatus >= 0); } template void CPUCore::wait(const EmuTime& time) { assert(time >= getCurrentTime()); scheduler.schedule(time); T::advanceTime(time); T::setLimit(scheduler.getNext()); } template void CPUCore::doBreak() { if (!breaked) { breaked = true; motherboard.block(); motherboard.getMSXCliComm().update(CliComm::STATUS, "cpu", "suspended"); motherboard.getEventDistributor().distributeEvent( new SimpleEvent()); } } template void CPUCore::doStep() { if (breaked) { step = true; doContinue2(); } } template void CPUCore::doContinue() { if (breaked) { continued = true; doContinue2(); } } template void CPUCore::doContinue2() { breaked = false; motherboard.getMSXCliComm().update(CliComm::STATUS, "cpu", "running"); motherboard.unblock(); } static inline char toHex(byte x) { return (x < 10) ? (x + '0') : (x - 10 + 'A'); } static void toHex(byte x, char* buf) { buf[0] = toHex(x / 16); buf[1] = toHex(x & 15); } template void CPUCore::disasmCommand( const std::vector& tokens, TclObject& result) const { word address = (tokens.size() < 3) ? R.PC : tokens[2]->getInt(); byte outBuf[4]; std::string dasmOutput; int len = dasm(*interface, address, outBuf, dasmOutput, T::getTime()); result.addListElement(dasmOutput); char tmp[3]; tmp[2] = 0; for (int i = 0; i < len; ++i) { toHex(outBuf[i], tmp); result.addListElement(tmp); } } template void CPUCore::update(const Setting& setting) { if (&setting == freqLocked.get()) { if (freqLocked->getValue()) { // locked T::setFreq(freq); } else { // unlocked T::setFreq(freqValue->getValue()); } } else if (&setting == freqValue.get()) { if (!freqLocked->getValue()) { T::setFreq(freqValue->getValue()); } } else { assert(false); } } template void CPUCore::setFreq(unsigned freq_) { freq = freq_; if (freqLocked->getValue()) { // locked T::setFreq(freq); } } template inline byte CPUCore::READ_PORT(word port) { memptr = port + 1; T::PRE_IO(port); scheduler.schedule(T::getTime()); byte result = interface->readIO(port, T::getTime()); T::setLimit(scheduler.getNext()); T::POST_IO(port); return result; } template inline void CPUCore::WRITE_PORT(word port, byte value) { memptr = port + 1; T::PRE_IO(port); scheduler.schedule(T::getTime()); interface->writeIO(port, value, T::getTime()); T::setLimit(scheduler.getNext()); T::POST_IO(port); } template inline byte CPUCore::RDMEM_common(word address) { int line = address >> CacheLine::BITS; if (likely(readCacheLine[line] != NULL)) { // cached, fast path T::POST_MEM(address); return readCacheLine[line][address & CacheLine::LOW]; } else { return RDMEMslow(address); // not inlined } } template byte CPUCore::RDMEMslow(word address) { // not cached int line = address >> CacheLine::BITS; if (!readCacheTried[line]) { // try to cache now readCacheTried[line] = true; readCacheLine[line] = interface->getReadCacheLine(address & CacheLine::HIGH); if (readCacheLine[line] != NULL) { // cached ok T::POST_MEM(address); return readCacheLine[line][address & CacheLine::LOW]; } } // uncacheable scheduler.schedule(T::getTime()); byte result = interface->readMem(address, T::getTime()); T::setLimit(scheduler.getNext()); T::POST_MEM(address); return result; } template inline void CPUCore::WRMEM_common(word address, byte value) { int line = address >> CacheLine::BITS; if (likely(writeCacheLine[line] != NULL)) { // cached, fast path T::POST_MEM(address); writeCacheLine[line][address & CacheLine::LOW] = value; } else { WRMEMslow(address, value); // not inlined } } template void CPUCore::WRMEMslow(word address, byte value) { // not cached int line = address >> CacheLine::BITS; if (!writeCacheTried[line]) { // try to cache now writeCacheTried[line] = true; writeCacheLine[line] = interface->getWriteCacheLine(address & CacheLine::HIGH); if (writeCacheLine[line] != NULL) { // cached ok T::POST_MEM(address); writeCacheLine[line][address & CacheLine::LOW] = value; return; } } // uncacheable scheduler.schedule(T::getTime()); interface->writeMem(address, value, T::getTime()); T::setLimit(scheduler.getNext()); T::POST_MEM(address); } template inline byte CPUCore::RDMEM_OPCODE(word address) { T::PRE_RDMEM_OPCODE(address); return RDMEM_common(address); } template inline word CPUCore::RD_WORD_PC() { word res = RDMEM_OPCODE(R.PC + 0); res += RDMEM_OPCODE(R.PC + 1) << 8; R.PC += 2; return res; } template inline byte CPUCore::RDMEM(word address) { T::PRE_RDMEM(address); return RDMEM_common(address); } template inline void CPUCore::WRMEM(word address, byte value) { T::PRE_WRMEM(address); WRMEM_common(address, value); } template inline void CPUCore::M1Cycle() { T::M1_DELAY(); ++R.R; } // NMI interrupt template inline void CPUCore::nmi() { PUSH(R.PC); R.HALT = false; R.IFF1 = false; R.nextIFF1 = false; R.PC = 0x0066; T::NMI_DELAY(); M1Cycle(); } // IM0 interrupt template inline void CPUCore::irq0() { // TODO current implementation only works for 1-byte instructions // ok for MSX R.HALT = false; R.di(); T::IM0_DELAY(); executeInstruction1(interface->dataBus()); } // IM1 interrupt template inline void CPUCore::irq1() { R.HALT = false; R.di(); T::IM1_DELAY(); executeInstruction1(0xFF); // RST 0x38 } // IM2 interrupt template inline void CPUCore::irq2() { R.HALT = false; R.di(); PUSH(R.PC); word x = interface->dataBus() | (R.I << 8); R.PC = RDMEM(x + 0); R.PC += RDMEM(x + 1) << 8; T::IM2_DELAY(); M1Cycle(); } template inline void CPUCore::executeInstruction1(byte opcode) { M1Cycle(); (this->*opcode_main[opcode])(); } template inline void CPUCore::executeInstruction() { byte opcode = RDMEM_OPCODE(R.PC++); executeInstruction1(opcode); } template inline void CPUCore::cpuTracePre() { start_pc = R.PC; } template inline void CPUCore::cpuTracePost() { if (traceSetting.getValue()) { byte opbuf[4]; string dasmOutput; dasm(*interface, start_pc, opbuf, dasmOutput, T::getTime()); std::cout << std::setfill('0') << std::hex << std::setw(4) << start_pc << " : " << dasmOutput << " AF=" << std::setw(4) << R.AF << " BC=" << std::setw(4) << R.BC << " DE=" << std::setw(4) << R.DE << " HL=" << std::setw(4) << R.HL << " IX=" << std::setw(4) << R.IX << " IY=" << std::setw(4) << R.IY << " SP=" << std::setw(4) << R.SP << std::endl << std::dec; } } template inline void CPUCore::executeFast() { T::R800Refresh(); executeInstruction(); } template void CPUCore::executeSlow() { if (unlikely(nmiEdge)) { nmiEdge = false; nmi(); // NMI occured } else if (unlikely(R.IFF1 && IRQStatus)) { // normal interrupt switch (R.IM) { case 0: irq0(); break; case 1: irq1(); break; case 2: irq2(); break; default: assert(false); } } else if (unlikely(R.HALT || paused)) { // in halt mode R.R += T::advanceHalt(T::haltStates(), scheduler.getNext()); setSlowInstructions(); } else { R.IFF1 = R.nextIFF1; cpuTracePre(); executeFast(); cpuTracePost(); } } template void CPUCore::execute() { executeInternal(); } template void CPUCore::executeInternal() { assert(!breaked); scheduler.schedule(T::getTime()); setSlowInstructions(); if (continued || step) { // at least one instruction continued = false; executeSlow(); scheduler.schedule(T::getTime()); --slowInstructions; if (step) { step = false; doBreak(); return; } } // Note: we call scheduler _after_ executing the instruction and before // deciding between executeFast() and executeSlow() (because a // SyncPoint could set an IRQ and then we must choose executeSlow()) if (!anyBreakPoints() && !traceSetting.getValue()) { // fast path, no breakpoints, no tracing while (!needExitCPULoop()) { if (slowInstructions) { --slowInstructions; executeSlow(); scheduler.schedule(T::getTime()); } else { while (slowInstructions == 0) { T::enableLimit(true); T::setLimit(scheduler.getNext()); while (likely(!T::limitReached())) { // too much overhead for non-debug build #ifdef DEBUG assert(T::getTime() < scheduler.getNext()); assert(slowInstructions == 0); #endif executeFast(); } scheduler.schedule(T::getTime()); if (needExitCPULoop()) return; } } } } else { while (!needExitCPULoop()) { if (checkBreakPoints(R)) { continued = true; // skip bp check on next instr break; } if (slowInstructions == 0) { cpuTracePre(); executeFast(); cpuTracePost(); scheduler.schedule(T::getTime()); } else { --slowInstructions; executeSlow(); scheduler.schedule(T::getTime()); } } } } // conditions template inline bool CPUCore::C() { return R.getF() & C_FLAG; } template inline bool CPUCore::NC() { return !C(); } template inline bool CPUCore::Z() { return R.getF() & Z_FLAG; } template inline bool CPUCore::NZ() { return !Z(); } template inline bool CPUCore::M() { return R.getF() & S_FLAG; } template inline bool CPUCore::P() { return !M(); } template inline bool CPUCore::PE() { return R.getF() & V_FLAG; } template inline bool CPUCore::PO() { return !PE(); } // LD r,r template void CPUCore::ld_a_a() { } template void CPUCore::ld_a_b() { R.setA( R.getB()); } template void CPUCore::ld_a_c() { R.setA( R.getC()); } template void CPUCore::ld_a_d() { R.setA( R.getD()); } template void CPUCore::ld_a_e() { R.setA( R.getE()); } template void CPUCore::ld_a_h() { R.setA( R.getH()); } template void CPUCore::ld_a_l() { R.setA( R.getL()); } template void CPUCore::ld_a_ixh() { R.setA( R.getIXh()); } template void CPUCore::ld_a_ixl() { R.setA( R.getIXl()); } template void CPUCore::ld_a_iyh() { R.setA( R.getIYh()); } template void CPUCore::ld_a_iyl() { R.setA( R.getIYl()); } template void CPUCore::ld_b_b() { } template void CPUCore::ld_b_a() { R.setB(R.getA()); } template void CPUCore::ld_b_c() { R.setB(R.getC()); } template void CPUCore::ld_b_d() { R.setB(R.getD()); } template void CPUCore::ld_b_e() { R.setB(R.getE()); } template void CPUCore::ld_b_h() { R.setB(R.getH()); } template void CPUCore::ld_b_l() { R.setB(R.getL()); } template void CPUCore::ld_b_ixh() { R.setB(R.getIXh()); } template void CPUCore::ld_b_ixl() { R.setB(R.getIXl()); } template void CPUCore::ld_b_iyh() { R.setB(R.getIYh()); } template void CPUCore::ld_b_iyl() { R.setB(R.getIYl()); } template void CPUCore::ld_c_c() { } template void CPUCore::ld_c_a() { R.setC(R.getA()); } template void CPUCore::ld_c_b() { R.setC(R.getB()); } template void CPUCore::ld_c_d() { R.setC(R.getD()); } template void CPUCore::ld_c_e() { R.setC(R.getE()); } template void CPUCore::ld_c_h() { R.setC(R.getH()); } template void CPUCore::ld_c_l() { R.setC(R.getL()); } template void CPUCore::ld_c_ixh() { R.setC(R.getIXh()); } template void CPUCore::ld_c_ixl() { R.setC(R.getIXl()); } template void CPUCore::ld_c_iyh() { R.setC(R.getIYh()); } template void CPUCore::ld_c_iyl() { R.setC(R.getIYl()); } template void CPUCore::ld_d_d() { } template void CPUCore::ld_d_a() { R.setD(R.getA()); } template void CPUCore::ld_d_c() { R.setD(R.getC()); } template void CPUCore::ld_d_b() { R.setD(R.getB()); } template void CPUCore::ld_d_e() { R.setD(R.getE()); } template void CPUCore::ld_d_h() { R.setD(R.getH()); } template void CPUCore::ld_d_l() { R.setD(R.getL()); } template void CPUCore::ld_d_ixh() { R.setD(R.getIXh()); } template void CPUCore::ld_d_ixl() { R.setD(R.getIXl()); } template void CPUCore::ld_d_iyh() { R.setD(R.getIYh()); } template void CPUCore::ld_d_iyl() { R.setD(R.getIYl()); } template void CPUCore::ld_e_e() { } template void CPUCore::ld_e_a() { R.setE(R.getA()); } template void CPUCore::ld_e_c() { R.setE(R.getC()); } template void CPUCore::ld_e_b() { R.setE(R.getB()); } template void CPUCore::ld_e_d() { R.setE(R.getD()); } template void CPUCore::ld_e_h() { R.setE(R.getH()); } template void CPUCore::ld_e_l() { R.setE(R.getL()); } template void CPUCore::ld_e_ixh() { R.setE(R.getIXh()); } template void CPUCore::ld_e_ixl() { R.setE(R.getIXl()); } template void CPUCore::ld_e_iyh() { R.setE(R.getIYh()); } template void CPUCore::ld_e_iyl() { R.setE(R.getIYl()); } template void CPUCore::ld_h_h() { } template void CPUCore::ld_h_a() { R.setH(R.getA()); } template void CPUCore::ld_h_c() { R.setH(R.getC()); } template void CPUCore::ld_h_b() { R.setH(R.getB()); } template void CPUCore::ld_h_e() { R.setH(R.getE()); } template void CPUCore::ld_h_d() { R.setH(R.getD()); } template void CPUCore::ld_h_l() { R.setH(R.getL()); } template void CPUCore::ld_l_l() { } template void CPUCore::ld_l_a() { R.setL(R.getA()); } template void CPUCore::ld_l_c() { R.setL(R.getC()); } template void CPUCore::ld_l_b() { R.setL(R.getB()); } template void CPUCore::ld_l_e() { R.setL(R.getE()); } template void CPUCore::ld_l_d() { R.setL(R.getD()); } template void CPUCore::ld_l_h() { R.setL(R.getH()); } template void CPUCore::ld_ixh_a() { R.setIXh(R.getA()); } template void CPUCore::ld_ixh_b() { R.setIXh(R.getB()); } template void CPUCore::ld_ixh_c() { R.setIXh(R.getC()); } template void CPUCore::ld_ixh_d() { R.setIXh(R.getD()); } template void CPUCore::ld_ixh_e() { R.setIXh(R.getE()); } template void CPUCore::ld_ixh_ixh() { } template void CPUCore::ld_ixh_ixl() { R.setIXh(R.getIXl()); } template void CPUCore::ld_ixl_a() { R.setIXl(R.getA()); } template void CPUCore::ld_ixl_b() { R.setIXl(R.getB()); } template void CPUCore::ld_ixl_c() { R.setIXl(R.getC()); } template void CPUCore::ld_ixl_d() { R.setIXl(R.getD()); } template void CPUCore::ld_ixl_e() { R.setIXl(R.getE()); } template void CPUCore::ld_ixl_ixh() { R.setIXl(R.getIXh()); } template void CPUCore::ld_ixl_ixl() { } template void CPUCore::ld_iyh_a() { R.setIYh(R.getA()); } template void CPUCore::ld_iyh_b() { R.setIYh(R.getB()); } template void CPUCore::ld_iyh_c() { R.setIYh(R.getC()); } template void CPUCore::ld_iyh_d() { R.setIYh(R.getD()); } template void CPUCore::ld_iyh_e() { R.setIYh(R.getE()); } template void CPUCore::ld_iyh_iyh() { } template void CPUCore::ld_iyh_iyl() { R.setIYh(R.getIYl()); } template void CPUCore::ld_iyl_a() { R.setIYl(R.getA()); } template void CPUCore::ld_iyl_b() { R.setIYl(R.getB()); } template void CPUCore::ld_iyl_c() { R.setIYl(R.getC()); } template void CPUCore::ld_iyl_d() { R.setIYl(R.getD()); } template void CPUCore::ld_iyl_e() { R.setIYl(R.getE()); } template void CPUCore::ld_iyl_iyh() { R.setIYl(R.getIYh()); } template void CPUCore::ld_iyl_iyl() { } // LD SP,ss template void CPUCore::ld_sp_hl() { T::LD_SP_HL_DELAY(); R.SP = R.HL; } template void CPUCore::ld_sp_ix() { T::LD_SP_HL_DELAY(); R.SP = R.IX; } template void CPUCore::ld_sp_iy() { T::LD_SP_HL_DELAY(); R.SP = R.IY; } // LD (ss),a template inline void CPUCore::WR_X_A(word x) { WRMEM(x, R.getA()); } template void CPUCore::ld_xbc_a() { WR_X_A(R.BC); } template void CPUCore::ld_xde_a() { WR_X_A(R.DE); } template void CPUCore::ld_xhl_a() { WR_X_A(R.HL); } // LD (HL),r template inline void CPUCore::WR_HL_X(byte val) { WRMEM(R.HL, val); } template void CPUCore::ld_xhl_b() { WR_HL_X(R.getB()); } template void CPUCore::ld_xhl_c() { WR_HL_X(R.getC()); } template void CPUCore::ld_xhl_d() { WR_HL_X(R.getD()); } template void CPUCore::ld_xhl_e() { WR_HL_X(R.getE()); } template void CPUCore::ld_xhl_h() { WR_HL_X(R.getH()); } template void CPUCore::ld_xhl_l() { WR_HL_X(R.getL()); } // LD (HL),n template void CPUCore::ld_xhl_byte() { byte val = RDMEM_OPCODE(R.PC++); WR_HL_X(val); } // LD (IX+e),r template inline void CPUCore::WR_X_X(byte val) { WRMEM(memptr, val); } template inline void CPUCore::WR_XIX(byte val) { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); WR_X_X(val); } template void CPUCore::ld_xix_a() { WR_XIX(R.getA()); } template void CPUCore::ld_xix_b() { WR_XIX(R.getB()); } template void CPUCore::ld_xix_c() { WR_XIX(R.getC()); } template void CPUCore::ld_xix_d() { WR_XIX(R.getD()); } template void CPUCore::ld_xix_e() { WR_XIX(R.getE()); } template void CPUCore::ld_xix_h() { WR_XIX(R.getH()); } template void CPUCore::ld_xix_l() { WR_XIX(R.getL()); } // LD (IY+e),r template inline void CPUCore::WR_XIY(byte val) { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); WR_X_X(val); } template void CPUCore::ld_xiy_a() { WR_XIY(R.getA()); } template void CPUCore::ld_xiy_b() { WR_XIY(R.getB()); } template void CPUCore::ld_xiy_c() { WR_XIY(R.getC()); } template void CPUCore::ld_xiy_d() { WR_XIY(R.getD()); } template void CPUCore::ld_xiy_e() { WR_XIY(R.getE()); } template void CPUCore::ld_xiy_h() { WR_XIY(R.getH()); } template void CPUCore::ld_xiy_l() { WR_XIY(R.getL()); } // LD (IX+e),n template void CPUCore::ld_xix_byte() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; byte val = RDMEM_OPCODE(R.PC++); T::PARALLEL_DELAY(); WR_X_X(val); } // LD (IY+e),n template void CPUCore::ld_xiy_byte() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; byte val = RDMEM_OPCODE(R.PC++); T::PARALLEL_DELAY(); WR_X_X(val); } // LD (nn),A template void CPUCore::ld_xbyte_a() { word x = RD_WORD_PC(); memptr = R.getA() << 8; WRMEM(x, R.getA()); } // LD (nn),ss template inline void CPUCore::WR_NN_Y(word reg) { memptr = RD_WORD_PC(); WRMEM(memptr + 0, reg & 255); WRMEM(memptr + 1, reg >> 8); } template void CPUCore::ld_xword_bc() { WR_NN_Y(R.BC); } template void CPUCore::ld_xword_de() { WR_NN_Y(R.DE); } template void CPUCore::ld_xword_hl() { WR_NN_Y(R.HL); } template void CPUCore::ld_xword_ix() { WR_NN_Y(R.IX); } template void CPUCore::ld_xword_iy() { WR_NN_Y(R.IY); } template void CPUCore::ld_xword_sp() { WR_NN_Y(R.SP); } // LD A,(ss) template inline void CPUCore::RD_A_X(word x) { R.setA(RDMEM(x)); } template void CPUCore::ld_a_xbc() { RD_A_X(R.BC); } template void CPUCore::ld_a_xde() { RD_A_X(R.DE); } template void CPUCore::ld_a_xhl() { RD_A_X(R.HL); } // LD A,(IX+e) template void CPUCore::ld_a_xix() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); RD_A_X(memptr); } // LD A,(IY+e) template void CPUCore::ld_a_xiy() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); RD_A_X(memptr); } // LD A,(nn) template void CPUCore::ld_a_xbyte() { memptr = RD_WORD_PC(); RD_A_X(memptr); ++memptr; } // LD r,n template void CPUCore::ld_a_byte() { R.setA(RDMEM_OPCODE(R.PC++)); } template void CPUCore::ld_b_byte() { R.setB(RDMEM_OPCODE(R.PC++)); } template void CPUCore::ld_c_byte() { R.setC(RDMEM_OPCODE(R.PC++)); } template void CPUCore::ld_d_byte() { R.setD(RDMEM_OPCODE(R.PC++)); } template void CPUCore::ld_e_byte() { R.setE(RDMEM_OPCODE(R.PC++)); } template void CPUCore::ld_h_byte() { R.setH(RDMEM_OPCODE(R.PC++)); } template void CPUCore::ld_l_byte() { R.setL(RDMEM_OPCODE(R.PC++)); } template void CPUCore::ld_ixh_byte() { R.setIXh(RDMEM_OPCODE(R.PC++)); } template void CPUCore::ld_ixl_byte() { R.setIXl(RDMEM_OPCODE(R.PC++)); } template void CPUCore::ld_iyh_byte() { R.setIYh(RDMEM_OPCODE(R.PC++)); } template void CPUCore::ld_iyl_byte() { R.setIYl(RDMEM_OPCODE(R.PC++)); } // LD r,(hl) template void CPUCore::ld_b_xhl() { R.setB(RDMEM(R.HL)); } template void CPUCore::ld_c_xhl() { R.setC(RDMEM(R.HL)); } template void CPUCore::ld_d_xhl() { R.setD(RDMEM(R.HL)); } template void CPUCore::ld_e_xhl() { R.setE(RDMEM(R.HL)); } template void CPUCore::ld_h_xhl() { R.setH(RDMEM(R.HL)); } template void CPUCore::ld_l_xhl() { R.setL(RDMEM(R.HL)); } // LD r,(IX+e) template inline byte CPUCore::RD_R_XIX() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); return RDMEM(memptr); } template void CPUCore::ld_b_xix() { R.setB(RD_R_XIX()); } template void CPUCore::ld_c_xix() { R.setC(RD_R_XIX()); } template void CPUCore::ld_d_xix() { R.setD(RD_R_XIX()); } template void CPUCore::ld_e_xix() { R.setE(RD_R_XIX()); } template void CPUCore::ld_h_xix() { R.setH(RD_R_XIX()); } template void CPUCore::ld_l_xix() { R.setL(RD_R_XIX()); } // LD r,(IY+e) template inline byte CPUCore::RD_R_XIY() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); return RDMEM(memptr); } template void CPUCore::ld_b_xiy() { R.setB(RD_R_XIY()); } template void CPUCore::ld_c_xiy() { R.setC(RD_R_XIY()); } template void CPUCore::ld_d_xiy() { R.setD(RD_R_XIY()); } template void CPUCore::ld_e_xiy() { R.setE(RD_R_XIY()); } template void CPUCore::ld_h_xiy() { R.setH(RD_R_XIY()); } template void CPUCore::ld_l_xiy() { R.setL(RD_R_XIY()); } // LD ss,(nn) template inline word CPUCore::RD_P_XX() { memptr = RD_WORD_PC(); word res = RDMEM(memptr + 0); res += RDMEM(memptr + 1) << 8; ++memptr; return res; } template void CPUCore::ld_bc_xword() { R.BC = RD_P_XX(); } template void CPUCore::ld_de_xword() { R.DE = RD_P_XX(); } template void CPUCore::ld_hl_xword() { R.HL = RD_P_XX(); } template void CPUCore::ld_ix_xword() { R.IX = RD_P_XX(); } template void CPUCore::ld_iy_xword() { R.IY = RD_P_XX(); } template void CPUCore::ld_sp_xword() { R.SP = RD_P_XX(); } // LD ss,nn template void CPUCore::ld_bc_word() { R.BC = RD_WORD_PC(); } template void CPUCore::ld_de_word() { R.DE = RD_WORD_PC(); } template void CPUCore::ld_hl_word() { R.HL = RD_WORD_PC(); } template void CPUCore::ld_ix_word() { R.IX = RD_WORD_PC(); } template void CPUCore::ld_iy_word() { R.IY = RD_WORD_PC(); } template void CPUCore::ld_sp_word() { R.SP = RD_WORD_PC(); } // ADC A,r template inline void CPUCore::ADC(byte reg) { int res = R.getA() + reg + ((R.getF() & C_FLAG) ? 1 : 0); R.setF(ZSXYTable[res & 0xFF] | ((res & 0x100) ? C_FLAG : 0) | ((R.getA() ^ res ^ reg) & H_FLAG) | (((reg ^ R.getA() ^ 0x80) & (reg ^ res) & 0x80) ? V_FLAG : 0)); R.setA(res); } template void CPUCore::adc_a_a() { ADC(R.getA()); } template void CPUCore::adc_a_b() { ADC(R.getB()); } template void CPUCore::adc_a_c() { ADC(R.getC()); } template void CPUCore::adc_a_d() { ADC(R.getD()); } template void CPUCore::adc_a_e() { ADC(R.getE()); } template void CPUCore::adc_a_h() { ADC(R.getH()); } template void CPUCore::adc_a_l() { ADC(R.getL()); } template void CPUCore::adc_a_ixl() { ADC(R.getIXl()); } template void CPUCore::adc_a_ixh() { ADC(R.getIXh()); } template void CPUCore::adc_a_iyl() { ADC(R.getIYl()); } template void CPUCore::adc_a_iyh() { ADC(R.getIYh()); } template void CPUCore::adc_a_byte(){ ADC(RDMEM_OPCODE(R.PC++)); } template inline void CPUCore::adc_a_x(word x) { ADC(RDMEM(x)); } template void CPUCore::adc_a_xhl() { adc_a_x(R.HL); } template void CPUCore::adc_a_xix() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); adc_a_x(memptr); } template void CPUCore::adc_a_xiy() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); adc_a_x(memptr); } // ADD A,r template inline void CPUCore::ADD(byte reg) { int res = R.getA() + reg; R.setF(ZSXYTable[res & 0xFF] | ((res & 0x100) ? C_FLAG : 0) | ((R.getA() ^ res ^ reg) & H_FLAG) | (((reg ^ R.getA() ^ 0x80) & (reg ^ res) & 0x80) ? V_FLAG : 0)); R.setA(res); } template void CPUCore::add_a_a() { ADD(R.getA()); } template void CPUCore::add_a_b() { ADD(R.getB()); } template void CPUCore::add_a_c() { ADD(R.getC()); } template void CPUCore::add_a_d() { ADD(R.getD()); } template void CPUCore::add_a_e() { ADD(R.getE()); } template void CPUCore::add_a_h() { ADD(R.getH()); } template void CPUCore::add_a_l() { ADD(R.getL()); } template void CPUCore::add_a_ixl() { ADD(R.getIXl()); } template void CPUCore::add_a_ixh() { ADD(R.getIXh()); } template void CPUCore::add_a_iyl() { ADD(R.getIYl()); } template void CPUCore::add_a_iyh() { ADD(R.getIYh()); } template void CPUCore::add_a_byte(){ ADD(RDMEM_OPCODE(R.PC++)); } template inline void CPUCore::add_a_x(word x) { ADD(RDMEM(x)); } template void CPUCore::add_a_xhl() { add_a_x(R.HL); } template void CPUCore::add_a_xix() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); add_a_x(memptr); } template void CPUCore::add_a_xiy() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); add_a_x(memptr); } // AND r template inline void CPUCore::AND(byte reg) { R.setA(R.getA() & reg); R.setF(ZSPXYTable[R.getA()] | H_FLAG); } template void CPUCore::and_a() { AND(R.getA()); } template void CPUCore::and_b() { AND(R.getB()); } template void CPUCore::and_c() { AND(R.getC()); } template void CPUCore::and_d() { AND(R.getD()); } template void CPUCore::and_e() { AND(R.getE()); } template void CPUCore::and_h() { AND(R.getH()); } template void CPUCore::and_l() { AND(R.getL()); } template void CPUCore::and_ixh() { AND(R.getIXh()); } template void CPUCore::and_ixl() { AND(R.getIXl()); } template void CPUCore::and_iyh() { AND(R.getIYh()); } template void CPUCore::and_iyl() { AND(R.getIYl()); } template void CPUCore::and_byte(){ AND(RDMEM_OPCODE(R.PC++)); } template inline void CPUCore::and_x(word x) { AND(RDMEM(x)); } template void CPUCore::and_xhl() { and_x(R.HL); } template void CPUCore::and_xix() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); and_x(memptr); } template void CPUCore::and_xiy() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); and_x(memptr); } // CP r template inline void CPUCore::CP(byte reg) { int q = R.getA() - reg; R.setF(ZSTable[q & 0xFF] | (reg & (X_FLAG | Y_FLAG)) | // XY from operand, not from result ((q & 0x100) ? C_FLAG : 0) | N_FLAG | ((R.getA() ^ q ^ reg) & H_FLAG) | (((reg ^ R.getA()) & (R.getA() ^ q) & 0x80) ? V_FLAG : 0)); } template void CPUCore::cp_a() { CP(R.getA()); } template void CPUCore::cp_b() { CP(R.getB()); } template void CPUCore::cp_c() { CP(R.getC()); } template void CPUCore::cp_d() { CP(R.getD()); } template void CPUCore::cp_e() { CP(R.getE()); } template void CPUCore::cp_h() { CP(R.getH()); } template void CPUCore::cp_l() { CP(R.getL()); } template void CPUCore::cp_ixh() { CP(R.getIXh()); } template void CPUCore::cp_ixl() { CP(R.getIXl()); } template void CPUCore::cp_iyh() { CP(R.getIYh()); } template void CPUCore::cp_iyl() { CP(R.getIYl()); } template void CPUCore::cp_byte(){ CP(RDMEM_OPCODE(R.PC++)); } template inline void CPUCore::cp_x(word x) { CP(RDMEM(x)); } template void CPUCore::cp_xhl() { cp_x(R.HL); } template void CPUCore::cp_xix() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); cp_x(memptr); } template void CPUCore::cp_xiy() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); cp_x(memptr); } // OR r template inline void CPUCore::OR(byte reg) { R.setA(R.getA() | reg); R.setF(ZSPXYTable[R.getA()]); } template void CPUCore::or_a() { OR(R.getA()); } template void CPUCore::or_b() { OR(R.getB()); } template void CPUCore::or_c() { OR(R.getC()); } template void CPUCore::or_d() { OR(R.getD()); } template void CPUCore::or_e() { OR(R.getE()); } template void CPUCore::or_h() { OR(R.getH()); } template void CPUCore::or_l() { OR(R.getL()); } template void CPUCore::or_ixh() { OR(R.getIXh()); } template void CPUCore::or_ixl() { OR(R.getIXl()); } template void CPUCore::or_iyh() { OR(R.getIYh()); } template void CPUCore::or_iyl() { OR(R.getIYl()); } template void CPUCore::or_byte(){ OR(RDMEM_OPCODE(R.PC++)); } template inline void CPUCore::or_x(word x) { OR(RDMEM(x)); } template void CPUCore::or_xhl() { or_x(R.HL); } template void CPUCore::or_xix() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); or_x(memptr); } template void CPUCore::or_xiy() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); or_x(memptr); } // SBC A,r template inline void CPUCore::SBC(byte reg) { int res = R.getA() - reg - ((R.getF() & C_FLAG) ? 1 : 0); R.setF(ZSXYTable[res & 0xFF] | ((res & 0x100) ? C_FLAG : 0) | N_FLAG | ((R.getA() ^ res ^ reg) & H_FLAG) | (((reg ^ R.getA()) & (R.getA() ^ res) & 0x80) ? V_FLAG : 0)); R.setA(res); } template void CPUCore::sbc_a_a() { SBC(R.getA()); } template void CPUCore::sbc_a_b() { SBC(R.getB()); } template void CPUCore::sbc_a_c() { SBC(R.getC()); } template void CPUCore::sbc_a_d() { SBC(R.getD()); } template void CPUCore::sbc_a_e() { SBC(R.getE()); } template void CPUCore::sbc_a_h() { SBC(R.getH()); } template void CPUCore::sbc_a_l() { SBC(R.getL()); } template void CPUCore::sbc_a_ixh() { SBC(R.getIXh()); } template void CPUCore::sbc_a_ixl() { SBC(R.getIXl()); } template void CPUCore::sbc_a_iyh() { SBC(R.getIYh()); } template void CPUCore::sbc_a_iyl() { SBC(R.getIYl()); } template void CPUCore::sbc_a_byte(){ SBC(RDMEM_OPCODE(R.PC++)); } template inline void CPUCore::sbc_a_x(word x) { SBC(RDMEM(x)); } template void CPUCore::sbc_a_xhl() { sbc_a_x(R.HL); } template void CPUCore::sbc_a_xix() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); sbc_a_x(memptr); } template void CPUCore::sbc_a_xiy() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); sbc_a_x(memptr); } // SUB r template inline void CPUCore::SUB(byte reg) { int res = R.getA() - reg; R.setF(ZSXYTable[res & 0xFF] | ((res & 0x100) ? C_FLAG : 0) | N_FLAG | ((R.getA() ^ res ^ reg) & H_FLAG) | (((reg ^ R.getA()) & (R.getA() ^ res) & 0x80) ? V_FLAG : 0)); R.setA(res); } template void CPUCore::sub_a() { SUB(R.getA()); } template void CPUCore::sub_b() { SUB(R.getB()); } template void CPUCore::sub_c() { SUB(R.getC()); } template void CPUCore::sub_d() { SUB(R.getD()); } template void CPUCore::sub_e() { SUB(R.getE()); } template void CPUCore::sub_h() { SUB(R.getH()); } template void CPUCore::sub_l() { SUB(R.getL()); } template void CPUCore::sub_ixh() { SUB(R.getIXh()); } template void CPUCore::sub_ixl() { SUB(R.getIXl()); } template void CPUCore::sub_iyh() { SUB(R.getIYh()); } template void CPUCore::sub_iyl() { SUB(R.getIYl()); } template void CPUCore::sub_byte(){ SUB(RDMEM_OPCODE(R.PC++)); } template inline void CPUCore::sub_x(word x) { SUB(RDMEM(x)); } template void CPUCore::sub_xhl() { sub_x(R.HL); } template void CPUCore::sub_xix() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); sub_x(memptr); } template void CPUCore::sub_xiy() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); sub_x(memptr); } // XOR r template inline void CPUCore::XOR(byte reg) { R.setA(R.getA() ^ reg); R.setF(ZSPXYTable[R.getA()]); } template void CPUCore::xor_a() { XOR(R.getA()); } template void CPUCore::xor_b() { XOR(R.getB()); } template void CPUCore::xor_c() { XOR(R.getC()); } template void CPUCore::xor_d() { XOR(R.getD()); } template void CPUCore::xor_e() { XOR(R.getE()); } template void CPUCore::xor_h() { XOR(R.getH()); } template void CPUCore::xor_l() { XOR(R.getL()); } template void CPUCore::xor_ixh() { XOR(R.getIXh()); } template void CPUCore::xor_ixl() { XOR(R.getIXl()); } template void CPUCore::xor_iyh() { XOR(R.getIYh()); } template void CPUCore::xor_iyl() { XOR(R.getIYl()); } template void CPUCore::xor_byte(){ XOR(RDMEM_OPCODE(R.PC++)); } template inline void CPUCore::xor_x(word x) { XOR(RDMEM(x)); } template void CPUCore::xor_xhl() { xor_x(R.HL); } template void CPUCore::xor_xix() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); xor_x(memptr); } template void CPUCore::xor_xiy() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); xor_x(memptr); } // DEC r template inline byte CPUCore::DEC(byte reg) { reg--; R.setF((R.getF() & C_FLAG) | ((reg == 0x7f) ? V_FLAG : 0) | (((reg & 0x0f) == 0x0f) ? H_FLAG : 0) | ZSXYTable[reg] | N_FLAG); return reg; } template void CPUCore::dec_a() { R.setA(DEC(R.getA())); } template void CPUCore::dec_b() { R.setB(DEC(R.getB())); } template void CPUCore::dec_c() { R.setC(DEC(R.getC())); } template void CPUCore::dec_d() { R.setD(DEC(R.getD())); } template void CPUCore::dec_e() { R.setE(DEC(R.getE())); } template void CPUCore::dec_h() { R.setH(DEC(R.getH())); } template void CPUCore::dec_l() { R.setL(DEC(R.getL())); } template void CPUCore::dec_ixh() { R.setIXh(DEC(R.getIXh())); } template void CPUCore::dec_ixl() { R.setIXl(DEC(R.getIXl())); } template void CPUCore::dec_iyh() { R.setIYh(DEC(R.getIYh())); } template void CPUCore::dec_iyl() { R.setIYl(DEC(R.getIYl())); } template inline void CPUCore::DEC_X(word x) { byte val = DEC(RDMEM(x)); T::INC_DELAY(); WRMEM(x, val); } template void CPUCore::dec_xhl() { DEC_X(R.HL); } template void CPUCore::dec_xix() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); DEC_X(memptr); } template void CPUCore::dec_xiy() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); DEC_X(memptr); } // INC r template inline byte CPUCore::INC(byte reg) { reg++; R.setF((R.getF() & C_FLAG) | ((reg == 0x80) ? V_FLAG : 0) | (((reg & 0x0f) == 0x00) ? H_FLAG : 0) | ZSXYTable[reg]); return reg; } template void CPUCore::inc_a() { R.setA(INC(R.getA())); } template void CPUCore::inc_b() { R.setB(INC(R.getB())); } template void CPUCore::inc_c() { R.setC(INC(R.getC())); } template void CPUCore::inc_d() { R.setD(INC(R.getD())); } template void CPUCore::inc_e() { R.setE(INC(R.getE())); } template void CPUCore::inc_h() { R.setH(INC(R.getH())); } template void CPUCore::inc_l() { R.setL(INC(R.getL())); } template void CPUCore::inc_ixh() { R.setIXh(INC(R.getIXh())); } template void CPUCore::inc_ixl() { R.setIXl(INC(R.getIXl())); } template void CPUCore::inc_iyh() { R.setIYh(INC(R.getIYh())); } template void CPUCore::inc_iyl() { R.setIYl(INC(R.getIYl())); } template inline void CPUCore::INC_X(word x) { byte val = INC(RDMEM(x)); T::INC_DELAY(); WRMEM(x, val); } template void CPUCore::inc_xhl() { INC_X(R.HL); } template void CPUCore::inc_xix() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IX + ofst; T::ADD_16_8_DELAY(); INC_X(memptr); } template void CPUCore::inc_xiy() { offset ofst = RDMEM_OPCODE(R.PC++); memptr = R.IY + ofst; T::ADD_16_8_DELAY(); INC_X(memptr); } // ADC HL,ss template inline void CPUCore::ADCW(word reg) { memptr = R.HL + 1; int res = R.HL + reg + ((R.getF() & C_FLAG) ? 1 : 0); R.setF((((R.HL ^ res ^ reg) >> 8) & H_FLAG) | ((res & 0x10000) ? C_FLAG : 0) | ((res & 0xffff) ? 0 : Z_FLAG) | (((reg ^ R.HL ^ 0x8000) & (reg ^ res) & 0x8000) ? V_FLAG : 0) | ((res >> 8) & (S_FLAG | X_FLAG | Y_FLAG))); R.HL = res; T::OP_16_16_DELAY(); } template void CPUCore::adc_hl_bc() { ADCW(R.BC); } template void CPUCore::adc_hl_de() { ADCW(R.DE); } template void CPUCore::adc_hl_hl() { ADCW(R.HL); } template void CPUCore::adc_hl_sp() { ADCW(R.SP); } // ADD HL/IX/IY,ss template inline void CPUCore::ADDW(word ®1, word reg2) { memptr = reg1 + 1; int res = reg1 + reg2; R.setF((R.getF() & (S_FLAG | Z_FLAG | V_FLAG)) | (((reg1 ^ res ^ reg2) >> 8) & H_FLAG) | ((res & 0x10000) ? C_FLAG : 0) | ((res >> 8) & (X_FLAG | Y_FLAG))); reg1 = res; T::OP_16_16_DELAY(); } template void CPUCore::add_hl_bc() { ADDW(R.HL, R.BC); } template void CPUCore::add_hl_de() { ADDW(R.HL, R.DE); } template void CPUCore::add_hl_hl() { ADDW(R.HL, R.HL); } template void CPUCore::add_hl_sp() { ADDW(R.HL, R.SP); } template void CPUCore::add_ix_bc() { ADDW(R.IX, R.BC); } template void CPUCore::add_ix_de() { ADDW(R.IX, R.DE); } template void CPUCore::add_ix_ix() { ADDW(R.IX, R.IX); } template void CPUCore::add_ix_sp() { ADDW(R.IX, R.SP); } template void CPUCore::add_iy_bc() { ADDW(R.IY, R.BC); } template void CPUCore::add_iy_de() { ADDW(R.IY, R.DE); } template void CPUCore::add_iy_iy() { ADDW(R.IY, R.IY); } template void CPUCore::add_iy_sp() { ADDW(R.IY, R.SP); } // SBC HL,ss template inline void CPUCore::SBCW(word reg) { memptr = R.HL + 1; int res = R.HL - reg - ((R.getF() & C_FLAG) ? 1 : 0); R.setF((((R.HL ^ res ^ reg) >> 8) & H_FLAG) | ((res & 0x10000) ? C_FLAG : 0) | ((res & 0xffff) ? 0 : Z_FLAG) | (((reg ^ R.HL) & (R.HL ^ res) & 0x8000) ? V_FLAG : 0) | ((res >> 8) & (S_FLAG | X_FLAG | Y_FLAG)) | N_FLAG); R.HL = res; T::OP_16_16_DELAY(); } template void CPUCore::sbc_hl_bc() { SBCW(R.BC); } template void CPUCore::sbc_hl_de() { SBCW(R.DE); } template void CPUCore::sbc_hl_hl() { SBCW(R.HL); } template void CPUCore::sbc_hl_sp() { SBCW(R.SP); } // DEC ss template void CPUCore::dec_bc() { --R.BC; T::INC_16_DELAY(); } template void CPUCore::dec_de() { --R.DE; T::INC_16_DELAY(); } template void CPUCore::dec_hl() { --R.HL; T::INC_16_DELAY(); } template void CPUCore::dec_ix() { --R.IX; T::INC_16_DELAY(); } template void CPUCore::dec_iy() { --R.IY; T::INC_16_DELAY(); } template void CPUCore::dec_sp() { --R.SP; T::INC_16_DELAY(); } // INC ss template void CPUCore::inc_bc() { ++R.BC; T::INC_16_DELAY(); } template void CPUCore::inc_de() { ++R.DE; T::INC_16_DELAY(); } template void CPUCore::inc_hl() { ++R.HL; T::INC_16_DELAY(); } template void CPUCore::inc_ix() { ++R.IX; T::INC_16_DELAY(); } template void CPUCore::inc_iy() { ++R.IY; T::INC_16_DELAY(); } template void CPUCore::inc_sp() { ++R.SP; T::INC_16_DELAY(); } // BIT n,r template inline void CPUCore::BIT(byte b, byte reg) { R.setF((R.getF() & C_FLAG) | ZSPTable[reg & (1 << b)] | (reg & (X_FLAG | Y_FLAG)) | H_FLAG); } template void CPUCore::bit_0_a() { BIT(0, R.getA()); } template void CPUCore::bit_0_b() { BIT(0, R.getB()); } template void CPUCore::bit_0_c() { BIT(0, R.getC()); } template void CPUCore::bit_0_d() { BIT(0, R.getD()); } template void CPUCore::bit_0_e() { BIT(0, R.getE()); } template void CPUCore::bit_0_h() { BIT(0, R.getH()); } template void CPUCore::bit_0_l() { BIT(0, R.getL()); } template void CPUCore::bit_1_a() { BIT(1, R.getA()); } template void CPUCore::bit_1_b() { BIT(1, R.getB()); } template void CPUCore::bit_1_c() { BIT(1, R.getC()); } template void CPUCore::bit_1_d() { BIT(1, R.getD()); } template void CPUCore::bit_1_e() { BIT(1, R.getE()); } template void CPUCore::bit_1_h() { BIT(1, R.getH()); } template void CPUCore::bit_1_l() { BIT(1, R.getL()); } template void CPUCore::bit_2_a() { BIT(2, R.getA()); } template void CPUCore::bit_2_b() { BIT(2, R.getB()); } template void CPUCore::bit_2_c() { BIT(2, R.getC()); } template void CPUCore::bit_2_d() { BIT(2, R.getD()); } template void CPUCore::bit_2_e() { BIT(2, R.getE()); } template void CPUCore::bit_2_h() { BIT(2, R.getH()); } template void CPUCore::bit_2_l() { BIT(2, R.getL()); } template void CPUCore::bit_3_a() { BIT(3, R.getA()); } template void CPUCore::bit_3_b() { BIT(3, R.getB()); } template void CPUCore::bit_3_c() { BIT(3, R.getC()); } template void CPUCore::bit_3_d() { BIT(3, R.getD()); } template void CPUCore::bit_3_e() { BIT(3, R.getE()); } template void CPUCore::bit_3_h() { BIT(3, R.getH()); } template void CPUCore::bit_3_l() { BIT(3, R.getL()); } template void CPUCore::bit_4_a() { BIT(4, R.getA()); } template void CPUCore::bit_4_b() { BIT(4, R.getB()); } template void CPUCore::bit_4_c() { BIT(4, R.getC()); } template void CPUCore::bit_4_d() { BIT(4, R.getD()); } template void CPUCore::bit_4_e() { BIT(4, R.getE()); } template void CPUCore::bit_4_h() { BIT(4, R.getH()); } template void CPUCore::bit_4_l() { BIT(4, R.getL()); } template void CPUCore::bit_5_a() { BIT(5, R.getA()); } template void CPUCore::bit_5_b() { BIT(5, R.getB()); } template void CPUCore::bit_5_c() { BIT(5, R.getC()); } template void CPUCore::bit_5_d() { BIT(5, R.getD()); } template void CPUCore::bit_5_e() { BIT(5, R.getE()); } template void CPUCore::bit_5_h() { BIT(5, R.getH()); } template void CPUCore::bit_5_l() { BIT(5, R.getL()); } template void CPUCore::bit_6_a() { BIT(6, R.getA()); } template void CPUCore::bit_6_b() { BIT(6, R.getB()); } template void CPUCore::bit_6_c() { BIT(6, R.getC()); } template void CPUCore::bit_6_d() { BIT(6, R.getD()); } template void CPUCore::bit_6_e() { BIT(6, R.getE()); } template void CPUCore::bit_6_h() { BIT(6, R.getH()); } template void CPUCore::bit_6_l() { BIT(6, R.getL()); } template void CPUCore::bit_7_a() { BIT(7, R.getA()); } template void CPUCore::bit_7_b() { BIT(7, R.getB()); } template void CPUCore::bit_7_c() { BIT(7, R.getC()); } template void CPUCore::bit_7_d() { BIT(7, R.getD()); } template void CPUCore::bit_7_e() { BIT(7, R.getE()); } template void CPUCore::bit_7_h() { BIT(7, R.getH()); } template void CPUCore::bit_7_l() { BIT(7, R.getL()); } template inline void CPUCore::BIT_HL(byte bit) { R.setF((R.getF() & C_FLAG) | ZSPTable[RDMEM(R.HL) & (1 << bit)] | H_FLAG | ((memptr >> 8) & (X_FLAG | Y_FLAG))); T::SMALL_DELAY(); } template void CPUCore::bit_0_xhl() { BIT_HL(0); } template void CPUCore::bit_1_xhl() { BIT_HL(1); } template void CPUCore::bit_2_xhl() { BIT_HL(2); } template void CPUCore::bit_3_xhl() { BIT_HL(3); } template void CPUCore::bit_4_xhl() { BIT_HL(4); } template void CPUCore::bit_5_xhl() { BIT_HL(5); } template void CPUCore::bit_6_xhl() { BIT_HL(6); } template void CPUCore::bit_7_xhl() { BIT_HL(7); } template inline void CPUCore::BIT_IX(byte bit) { memptr = R.IX + ofst; R.setF((R.getF() & C_FLAG) | ZSPTable[RDMEM(memptr) & (1 << bit)] | H_FLAG | ((memptr >> 8) & (X_FLAG | Y_FLAG))); T::SMALL_DELAY(); } template void CPUCore::bit_0_xix() { BIT_IX(0); } template void CPUCore::bit_1_xix() { BIT_IX(1); } template void CPUCore::bit_2_xix() { BIT_IX(2); } template void CPUCore::bit_3_xix() { BIT_IX(3); } template void CPUCore::bit_4_xix() { BIT_IX(4); } template void CPUCore::bit_5_xix() { BIT_IX(5); } template void CPUCore::bit_6_xix() { BIT_IX(6); } template void CPUCore::bit_7_xix() { BIT_IX(7); } template inline void CPUCore::BIT_IY(byte bit) { memptr = R.IY + ofst; R.setF((R.getF() & C_FLAG) | ZSPTable[RDMEM(memptr) & (1 << bit)] | H_FLAG | ((memptr >> 8) & (X_FLAG | Y_FLAG))); T::SMALL_DELAY(); } template void CPUCore::bit_0_xiy() { BIT_IY(0); } template void CPUCore::bit_1_xiy() { BIT_IY(1); } template void CPUCore::bit_2_xiy() { BIT_IY(2); } template void CPUCore::bit_3_xiy() { BIT_IY(3); } template void CPUCore::bit_4_xiy() { BIT_IY(4); } template void CPUCore::bit_5_xiy() { BIT_IY(5); } template void CPUCore::bit_6_xiy() { BIT_IY(6); } template void CPUCore::bit_7_xiy() { BIT_IY(7); } // RES n,r template inline byte CPUCore::RES(byte b, byte reg) { return reg & ~(1 << b); } template void CPUCore::res_0_a() { R.setA(RES(0, R.getA())); } template void CPUCore::res_0_b() { R.setB(RES(0, R.getB())); } template void CPUCore::res_0_c() { R.setC(RES(0, R.getC())); } template void CPUCore::res_0_d() { R.setD(RES(0, R.getD())); } template void CPUCore::res_0_e() { R.setE(RES(0, R.getE())); } template void CPUCore::res_0_h() { R.setH(RES(0, R.getH())); } template void CPUCore::res_0_l() { R.setL(RES(0, R.getL())); } template void CPUCore::res_1_a() { R.setA(RES(1, R.getA())); } template void CPUCore::res_1_b() { R.setB(RES(1, R.getB())); } template void CPUCore::res_1_c() { R.setC(RES(1, R.getC())); } template void CPUCore::res_1_d() { R.setD(RES(1, R.getD())); } template void CPUCore::res_1_e() { R.setE(RES(1, R.getE())); } template void CPUCore::res_1_h() { R.setH(RES(1, R.getH())); } template void CPUCore::res_1_l() { R.setL(RES(1, R.getL())); } template void CPUCore::res_2_a() { R.setA(RES(2, R.getA())); } template void CPUCore::res_2_b() { R.setB(RES(2, R.getB())); } template void CPUCore::res_2_c() { R.setC(RES(2, R.getC())); } template void CPUCore::res_2_d() { R.setD(RES(2, R.getD())); } template void CPUCore::res_2_e() { R.setE(RES(2, R.getE())); } template void CPUCore::res_2_h() { R.setH(RES(2, R.getH())); } template void CPUCore::res_2_l() { R.setL(RES(2, R.getL())); } template void CPUCore::res_3_a() { R.setA(RES(3, R.getA())); } template void CPUCore::res_3_b() { R.setB(RES(3, R.getB())); } template void CPUCore::res_3_c() { R.setC(RES(3, R.getC())); } template void CPUCore::res_3_d() { R.setD(RES(3, R.getD())); } template void CPUCore::res_3_e() { R.setE(RES(3, R.getE())); } template void CPUCore::res_3_h() { R.setH(RES(3, R.getH())); } template void CPUCore::res_3_l() { R.setL(RES(3, R.getL())); } template void CPUCore::res_4_a() { R.setA(RES(4, R.getA())); } template void CPUCore::res_4_b() { R.setB(RES(4, R.getB())); } template void CPUCore::res_4_c() { R.setC(RES(4, R.getC())); } template void CPUCore::res_4_d() { R.setD(RES(4, R.getD())); } template void CPUCore::res_4_e() { R.setE(RES(4, R.getE())); } template void CPUCore::res_4_h() { R.setH(RES(4, R.getH())); } template void CPUCore::res_4_l() { R.setL(RES(4, R.getL())); } template void CPUCore::res_5_a() { R.setA(RES(5, R.getA())); } template void CPUCore::res_5_b() { R.setB(RES(5, R.getB())); } template void CPUCore::res_5_c() { R.setC(RES(5, R.getC())); } template void CPUCore::res_5_d() { R.setD(RES(5, R.getD())); } template void CPUCore::res_5_e() { R.setE(RES(5, R.getE())); } template void CPUCore::res_5_h() { R.setH(RES(5, R.getH())); } template void CPUCore::res_5_l() { R.setL(RES(5, R.getL())); } template void CPUCore::res_6_a() { R.setA(RES(6, R.getA())); } template void CPUCore::res_6_b() { R.setB(RES(6, R.getB())); } template void CPUCore::res_6_c() { R.setC(RES(6, R.getC())); } template void CPUCore::res_6_d() { R.setD(RES(6, R.getD())); } template void CPUCore::res_6_e() { R.setE(RES(6, R.getE())); } template void CPUCore::res_6_h() { R.setH(RES(6, R.getH())); } template void CPUCore::res_6_l() { R.setL(RES(6, R.getL())); } template void CPUCore::res_7_a() { R.setA(RES(7, R.getA())); } template void CPUCore::res_7_b() { R.setB(RES(7, R.getB())); } template void CPUCore::res_7_c() { R.setC(RES(7, R.getC())); } template void CPUCore::res_7_d() { R.setD(RES(7, R.getD())); } template void CPUCore::res_7_e() { R.setE(RES(7, R.getE())); } template void CPUCore::res_7_h() { R.setH(RES(7, R.getH())); } template void CPUCore::res_7_l() { R.setL(RES(7, R.getL())); } template inline byte CPUCore::RES_X(byte bit, word x) { byte res = RES(bit, RDMEM(x)); T::INC_DELAY(); WRMEM(x, res); return res; } template inline byte CPUCore::RES_X_(byte bit, word x) { memptr = x; return RES_X(bit, x); } template inline byte CPUCore::RES_X_X(byte bit) { return RES_X_(bit, R.IX + ofst); } template inline byte CPUCore::RES_X_Y(byte bit) { return RES_X_(bit, R.IY + ofst); } template void CPUCore::res_0_xhl() { RES_X(0, R.HL); } template void CPUCore::res_1_xhl() { RES_X(1, R.HL); } template void CPUCore::res_2_xhl() { RES_X(2, R.HL); } template void CPUCore::res_3_xhl() { RES_X(3, R.HL); } template void CPUCore::res_4_xhl() { RES_X(4, R.HL); } template void CPUCore::res_5_xhl() { RES_X(5, R.HL); } template void CPUCore::res_6_xhl() { RES_X(6, R.HL); } template void CPUCore::res_7_xhl() { RES_X(7, R.HL); } template void CPUCore::res_0_xix() { RES_X_X(0); } template void CPUCore::res_1_xix() { RES_X_X(1); } template void CPUCore::res_2_xix() { RES_X_X(2); } template void CPUCore::res_3_xix() { RES_X_X(3); } template void CPUCore::res_4_xix() { RES_X_X(4); } template void CPUCore::res_5_xix() { RES_X_X(5); } template void CPUCore::res_6_xix() { RES_X_X(6); } template void CPUCore::res_7_xix() { RES_X_X(7); } template void CPUCore::res_0_xiy() { RES_X_Y(0); } template void CPUCore::res_1_xiy() { RES_X_Y(1); } template void CPUCore::res_2_xiy() { RES_X_Y(2); } template void CPUCore::res_3_xiy() { RES_X_Y(3); } template void CPUCore::res_4_xiy() { RES_X_Y(4); } template void CPUCore::res_5_xiy() { RES_X_Y(5); } template void CPUCore::res_6_xiy() { RES_X_Y(6); } template void CPUCore::res_7_xiy() { RES_X_Y(7); } template void CPUCore::res_0_xix_a() { R.setA(RES_X_X(0)); } template void CPUCore::res_0_xix_b() { R.setB(RES_X_X(0)); } template void CPUCore::res_0_xix_c() { R.setC(RES_X_X(0)); } template void CPUCore::res_0_xix_d() { R.setD(RES_X_X(0)); } template void CPUCore::res_0_xix_e() { R.setE(RES_X_X(0)); } template void CPUCore::res_0_xix_h() { R.setH(RES_X_X(0)); } template void CPUCore::res_0_xix_l() { R.setL(RES_X_X(0)); } template void CPUCore::res_1_xix_a() { R.setA(RES_X_X(1)); } template void CPUCore::res_1_xix_b() { R.setB(RES_X_X(1)); } template void CPUCore::res_1_xix_c() { R.setC(RES_X_X(1)); } template void CPUCore::res_1_xix_d() { R.setD(RES_X_X(1)); } template void CPUCore::res_1_xix_e() { R.setE(RES_X_X(1)); } template void CPUCore::res_1_xix_h() { R.setH(RES_X_X(1)); } template void CPUCore::res_1_xix_l() { R.setL(RES_X_X(1)); } template void CPUCore::res_2_xix_a() { R.setA(RES_X_X(2)); } template void CPUCore::res_2_xix_b() { R.setB(RES_X_X(2)); } template void CPUCore::res_2_xix_c() { R.setC(RES_X_X(2)); } template void CPUCore::res_2_xix_d() { R.setD(RES_X_X(2)); } template void CPUCore::res_2_xix_e() { R.setE(RES_X_X(2)); } template void CPUCore::res_2_xix_h() { R.setH(RES_X_X(2)); } template void CPUCore::res_2_xix_l() { R.setL(RES_X_X(2)); } template void CPUCore::res_3_xix_a() { R.setA(RES_X_X(3)); } template void CPUCore::res_3_xix_b() { R.setB(RES_X_X(3)); } template void CPUCore::res_3_xix_c() { R.setC(RES_X_X(3)); } template void CPUCore::res_3_xix_d() { R.setD(RES_X_X(3)); } template void CPUCore::res_3_xix_e() { R.setE(RES_X_X(3)); } template void CPUCore::res_3_xix_h() { R.setH(RES_X_X(3)); } template void CPUCore::res_3_xix_l() { R.setL(RES_X_X(3)); } template void CPUCore::res_4_xix_a() { R.setA(RES_X_X(4)); } template void CPUCore::res_4_xix_b() { R.setB(RES_X_X(4)); } template void CPUCore::res_4_xix_c() { R.setC(RES_X_X(4)); } template void CPUCore::res_4_xix_d() { R.setD(RES_X_X(4)); } template void CPUCore::res_4_xix_e() { R.setE(RES_X_X(4)); } template void CPUCore::res_4_xix_h() { R.setH(RES_X_X(4)); } template void CPUCore::res_4_xix_l() { R.setL(RES_X_X(4)); } template void CPUCore::res_5_xix_a() { R.setA(RES_X_X(5)); } template void CPUCore::res_5_xix_b() { R.setB(RES_X_X(5)); } template void CPUCore::res_5_xix_c() { R.setC(RES_X_X(5)); } template void CPUCore::res_5_xix_d() { R.setD(RES_X_X(5)); } template void CPUCore::res_5_xix_e() { R.setE(RES_X_X(5)); } template void CPUCore::res_5_xix_h() { R.setH(RES_X_X(5)); } template void CPUCore::res_5_xix_l() { R.setL(RES_X_X(5)); } template void CPUCore::res_6_xix_a() { R.setA(RES_X_X(6)); } template void CPUCore::res_6_xix_b() { R.setB(RES_X_X(6)); } template void CPUCore::res_6_xix_c() { R.setC(RES_X_X(6)); } template void CPUCore::res_6_xix_d() { R.setD(RES_X_X(6)); } template void CPUCore::res_6_xix_e() { R.setE(RES_X_X(6)); } template void CPUCore::res_6_xix_h() { R.setH(RES_X_X(6)); } template void CPUCore::res_6_xix_l() { R.setL(RES_X_X(6)); } template void CPUCore::res_7_xix_a() { R.setA(RES_X_X(7)); } template void CPUCore::res_7_xix_b() { R.setB(RES_X_X(7)); } template void CPUCore::res_7_xix_c() { R.setC(RES_X_X(7)); } template void CPUCore::res_7_xix_d() { R.setD(RES_X_X(7)); } template void CPUCore::res_7_xix_e() { R.setE(RES_X_X(7)); } template void CPUCore::res_7_xix_h() { R.setH(RES_X_X(7)); } template void CPUCore::res_7_xix_l() { R.setL(RES_X_X(7)); } template void CPUCore::res_0_xiy_a() { R.setA(RES_X_Y(0)); } template void CPUCore::res_0_xiy_b() { R.setB(RES_X_Y(0)); } template void CPUCore::res_0_xiy_c() { R.setC(RES_X_Y(0)); } template void CPUCore::res_0_xiy_d() { R.setD(RES_X_Y(0)); } template void CPUCore::res_0_xiy_e() { R.setE(RES_X_Y(0)); } template void CPUCore::res_0_xiy_h() { R.setH(RES_X_Y(0)); } template void CPUCore::res_0_xiy_l() { R.setL(RES_X_Y(0)); } template void CPUCore::res_1_xiy_a() { R.setA(RES_X_Y(1)); } template void CPUCore::res_1_xiy_b() { R.setB(RES_X_Y(1)); } template void CPUCore::res_1_xiy_c() { R.setC(RES_X_Y(1)); } template void CPUCore::res_1_xiy_d() { R.setD(RES_X_Y(1)); } template void CPUCore::res_1_xiy_e() { R.setE(RES_X_Y(1)); } template void CPUCore::res_1_xiy_h() { R.setH(RES_X_Y(1)); } template void CPUCore::res_1_xiy_l() { R.setL(RES_X_Y(1)); } template void CPUCore::res_2_xiy_a() { R.setA(RES_X_Y(2)); } template void CPUCore::res_2_xiy_b() { R.setB(RES_X_Y(2)); } template void CPUCore::res_2_xiy_c() { R.setC(RES_X_Y(2)); } template void CPUCore::res_2_xiy_d() { R.setD(RES_X_Y(2)); } template void CPUCore::res_2_xiy_e() { R.setE(RES_X_Y(2)); } template void CPUCore::res_2_xiy_h() { R.setH(RES_X_Y(2)); } template void CPUCore::res_2_xiy_l() { R.setL(RES_X_Y(2)); } template void CPUCore::res_3_xiy_a() { R.setA(RES_X_Y(3)); } template void CPUCore::res_3_xiy_b() { R.setB(RES_X_Y(3)); } template void CPUCore::res_3_xiy_c() { R.setC(RES_X_Y(3)); } template void CPUCore::res_3_xiy_d() { R.setD(RES_X_Y(3)); } template void CPUCore::res_3_xiy_e() { R.setE(RES_X_Y(3)); } template void CPUCore::res_3_xiy_h() { R.setH(RES_X_Y(3)); } template void CPUCore::res_3_xiy_l() { R.setL(RES_X_Y(3)); } template void CPUCore::res_4_xiy_a() { R.setA(RES_X_Y(4)); } template void CPUCore::res_4_xiy_b() { R.setB(RES_X_Y(4)); } template void CPUCore::res_4_xiy_c() { R.setC(RES_X_Y(4)); } template void CPUCore::res_4_xiy_d() { R.setD(RES_X_Y(4)); } template void CPUCore::res_4_xiy_e() { R.setE(RES_X_Y(4)); } template void CPUCore::res_4_xiy_h() { R.setH(RES_X_Y(4)); } template void CPUCore::res_4_xiy_l() { R.setL(RES_X_Y(4)); } template void CPUCore::res_5_xiy_a() { R.setA(RES_X_Y(5)); } template void CPUCore::res_5_xiy_b() { R.setB(RES_X_Y(5)); } template void CPUCore::res_5_xiy_c() { R.setC(RES_X_Y(5)); } template void CPUCore::res_5_xiy_d() { R.setD(RES_X_Y(5)); } template void CPUCore::res_5_xiy_e() { R.setE(RES_X_Y(5)); } template void CPUCore::res_5_xiy_h() { R.setH(RES_X_Y(5)); } template void CPUCore::res_5_xiy_l() { R.setL(RES_X_Y(5)); } template void CPUCore::res_6_xiy_a() { R.setA(RES_X_Y(6)); } template void CPUCore::res_6_xiy_b() { R.setB(RES_X_Y(6)); } template void CPUCore::res_6_xiy_c() { R.setC(RES_X_Y(6)); } template void CPUCore::res_6_xiy_d() { R.setD(RES_X_Y(6)); } template void CPUCore::res_6_xiy_e() { R.setE(RES_X_Y(6)); } template void CPUCore::res_6_xiy_h() { R.setH(RES_X_Y(6)); } template void CPUCore::res_6_xiy_l() { R.setL(RES_X_Y(6)); } template void CPUCore::res_7_xiy_a() { R.setA(RES_X_Y(7)); } template void CPUCore::res_7_xiy_b() { R.setB(RES_X_Y(7)); } template void CPUCore::res_7_xiy_c() { R.setC(RES_X_Y(7)); } template void CPUCore::res_7_xiy_d() { R.setD(RES_X_Y(7)); } template void CPUCore::res_7_xiy_e() { R.setE(RES_X_Y(7)); } template void CPUCore::res_7_xiy_h() { R.setH(RES_X_Y(7)); } template void CPUCore::res_7_xiy_l() { R.setL(RES_X_Y(7)); } // SET n,r template inline byte CPUCore::SET(byte b, byte reg) { return reg | (1 << b); } template void CPUCore::set_0_a() { R.setA(SET(0, R.getA())); } template void CPUCore::set_0_b() { R.setB(SET(0, R.getB())); } template void CPUCore::set_0_c() { R.setC(SET(0, R.getC())); } template void CPUCore::set_0_d() { R.setD(SET(0, R.getD())); } template void CPUCore::set_0_e() { R.setE(SET(0, R.getE())); } template void CPUCore::set_0_h() { R.setH(SET(0, R.getH())); } template void CPUCore::set_0_l() { R.setL(SET(0, R.getL())); } template void CPUCore::set_1_a() { R.setA(SET(1, R.getA())); } template void CPUCore::set_1_b() { R.setB(SET(1, R.getB())); } template void CPUCore::set_1_c() { R.setC(SET(1, R.getC())); } template void CPUCore::set_1_d() { R.setD(SET(1, R.getD())); } template void CPUCore::set_1_e() { R.setE(SET(1, R.getE())); } template void CPUCore::set_1_h() { R.setH(SET(1, R.getH())); } template void CPUCore::set_1_l() { R.setL(SET(1, R.getL())); } template void CPUCore::set_2_a() { R.setA(SET(2, R.getA())); } template void CPUCore::set_2_b() { R.setB(SET(2, R.getB())); } template void CPUCore::set_2_c() { R.setC(SET(2, R.getC())); } template void CPUCore::set_2_d() { R.setD(SET(2, R.getD())); } template void CPUCore::set_2_e() { R.setE(SET(2, R.getE())); } template void CPUCore::set_2_h() { R.setH(SET(2, R.getH())); } template void CPUCore::set_2_l() { R.setL(SET(2, R.getL())); } template void CPUCore::set_3_a() { R.setA(SET(3, R.getA())); } template void CPUCore::set_3_b() { R.setB(SET(3, R.getB())); } template void CPUCore::set_3_c() { R.setC(SET(3, R.getC())); } template void CPUCore::set_3_d() { R.setD(SET(3, R.getD())); } template void CPUCore::set_3_e() { R.setE(SET(3, R.getE())); } template void CPUCore::set_3_h() { R.setH(SET(3, R.getH())); } template void CPUCore::set_3_l() { R.setL(SET(3, R.getL())); } template void CPUCore::set_4_a() { R.setA(SET(4, R.getA())); } template void CPUCore::set_4_b() { R.setB(SET(4, R.getB())); } template void CPUCore::set_4_c() { R.setC(SET(4, R.getC())); } template void CPUCore::set_4_d() { R.setD(SET(4, R.getD())); } template void CPUCore::set_4_e() { R.setE(SET(4, R.getE())); } template void CPUCore::set_4_h() { R.setH(SET(4, R.getH())); } template void CPUCore::set_4_l() { R.setL(SET(4, R.getL())); } template void CPUCore::set_5_a() { R.setA(SET(5, R.getA())); } template void CPUCore::set_5_b() { R.setB(SET(5, R.getB())); } template void CPUCore::set_5_c() { R.setC(SET(5, R.getC())); } template void CPUCore::set_5_d() { R.setD(SET(5, R.getD())); } template void CPUCore::set_5_e() { R.setE(SET(5, R.getE())); } template void CPUCore::set_5_h() { R.setH(SET(5, R.getH())); } template void CPUCore::set_5_l() { R.setL(SET(5, R.getL())); } template void CPUCore::set_6_a() { R.setA(SET(6, R.getA())); } template void CPUCore::set_6_b() { R.setB(SET(6, R.getB())); } template void CPUCore::set_6_c() { R.setC(SET(6, R.getC())); } template void CPUCore::set_6_d() { R.setD(SET(6, R.getD())); } template void CPUCore::set_6_e() { R.setE(SET(6, R.getE())); } template void CPUCore::set_6_h() { R.setH(SET(6, R.getH())); } template void CPUCore::set_6_l() { R.setL(SET(6, R.getL())); } template void CPUCore::set_7_a() { R.setA(SET(7, R.getA())); } template void CPUCore::set_7_b() { R.setB(SET(7, R.getB())); } template void CPUCore::set_7_c() { R.setC(SET(7, R.getC())); } template void CPUCore::set_7_d() { R.setD(SET(7, R.getD())); } template void CPUCore::set_7_e() { R.setE(SET(7, R.getE())); } template void CPUCore::set_7_h() { R.setH(SET(7, R.getH())); } template void CPUCore::set_7_l() { R.setL(SET(7, R.getL())); } template inline byte CPUCore::SET_X(byte bit, word x) { byte res = SET(bit, RDMEM(x)); T::INC_DELAY(); WRMEM(x, res); return res; } template inline byte CPUCore::SET_X_(byte bit, word x) { memptr = x; return SET_X(bit, x); } template inline byte CPUCore::SET_X_X(byte bit) { return SET_X_(bit, R.IX + ofst); } template inline byte CPUCore::SET_X_Y(byte bit) { return SET_X_(bit, R.IY + ofst); } template void CPUCore::set_0_xhl() { SET_X(0, R.HL); } template void CPUCore::set_1_xhl() { SET_X(1, R.HL); } template void CPUCore::set_2_xhl() { SET_X(2, R.HL); } template void CPUCore::set_3_xhl() { SET_X(3, R.HL); } template void CPUCore::set_4_xhl() { SET_X(4, R.HL); } template void CPUCore::set_5_xhl() { SET_X(5, R.HL); } template void CPUCore::set_6_xhl() { SET_X(6, R.HL); } template void CPUCore::set_7_xhl() { SET_X(7, R.HL); } template void CPUCore::set_0_xix() { SET_X_X(0); } template void CPUCore::set_1_xix() { SET_X_X(1); } template void CPUCore::set_2_xix() { SET_X_X(2); } template void CPUCore::set_3_xix() { SET_X_X(3); } template void CPUCore::set_4_xix() { SET_X_X(4); } template void CPUCore::set_5_xix() { SET_X_X(5); } template void CPUCore::set_6_xix() { SET_X_X(6); } template void CPUCore::set_7_xix() { SET_X_X(7); } template void CPUCore::set_0_xiy() { SET_X_Y(0); } template void CPUCore::set_1_xiy() { SET_X_Y(1); } template void CPUCore::set_2_xiy() { SET_X_Y(2); } template void CPUCore::set_3_xiy() { SET_X_Y(3); } template void CPUCore::set_4_xiy() { SET_X_Y(4); } template void CPUCore::set_5_xiy() { SET_X_Y(5); } template void CPUCore::set_6_xiy() { SET_X_Y(6); } template void CPUCore::set_7_xiy() { SET_X_Y(7); } template void CPUCore::set_0_xix_a() { R.setA(SET_X_X(0)); } template void CPUCore::set_0_xix_b() { R.setB(SET_X_X(0)); } template void CPUCore::set_0_xix_c() { R.setC(SET_X_X(0)); } template void CPUCore::set_0_xix_d() { R.setD(SET_X_X(0)); } template void CPUCore::set_0_xix_e() { R.setE(SET_X_X(0)); } template void CPUCore::set_0_xix_h() { R.setH(SET_X_X(0)); } template void CPUCore::set_0_xix_l() { R.setL(SET_X_X(0)); } template void CPUCore::set_1_xix_a() { R.setA(SET_X_X(1)); } template void CPUCore::set_1_xix_b() { R.setB(SET_X_X(1)); } template void CPUCore::set_1_xix_c() { R.setC(SET_X_X(1)); } template void CPUCore::set_1_xix_d() { R.setD(SET_X_X(1)); } template void CPUCore::set_1_xix_e() { R.setE(SET_X_X(1)); } template void CPUCore::set_1_xix_h() { R.setH(SET_X_X(1)); } template void CPUCore::set_1_xix_l() { R.setL(SET_X_X(1)); } template void CPUCore::set_2_xix_a() { R.setA(SET_X_X(2)); } template void CPUCore::set_2_xix_b() { R.setB(SET_X_X(2)); } template void CPUCore::set_2_xix_c() { R.setC(SET_X_X(2)); } template void CPUCore::set_2_xix_d() { R.setD(SET_X_X(2)); } template void CPUCore::set_2_xix_e() { R.setE(SET_X_X(2)); } template void CPUCore::set_2_xix_h() { R.setH(SET_X_X(2)); } template void CPUCore::set_2_xix_l() { R.setL(SET_X_X(2)); } template void CPUCore::set_3_xix_a() { R.setA(SET_X_X(3)); } template void CPUCore::set_3_xix_b() { R.setB(SET_X_X(3)); } template void CPUCore::set_3_xix_c() { R.setC(SET_X_X(3)); } template void CPUCore::set_3_xix_d() { R.setD(SET_X_X(3)); } template void CPUCore::set_3_xix_e() { R.setE(SET_X_X(3)); } template void CPUCore::set_3_xix_h() { R.setH(SET_X_X(3)); } template void CPUCore::set_3_xix_l() { R.setL(SET_X_X(3)); } template void CPUCore::set_4_xix_a() { R.setA(SET_X_X(4)); } template void CPUCore::set_4_xix_b() { R.setB(SET_X_X(4)); } template void CPUCore::set_4_xix_c() { R.setC(SET_X_X(4)); } template void CPUCore::set_4_xix_d() { R.setD(SET_X_X(4)); } template void CPUCore::set_4_xix_e() { R.setE(SET_X_X(4)); } template void CPUCore::set_4_xix_h() { R.setH(SET_X_X(4)); } template void CPUCore::set_4_xix_l() { R.setL(SET_X_X(4)); } template void CPUCore::set_5_xix_a() { R.setA(SET_X_X(5)); } template void CPUCore::set_5_xix_b() { R.setB(SET_X_X(5)); } template void CPUCore::set_5_xix_c() { R.setC(SET_X_X(5)); } template void CPUCore::set_5_xix_d() { R.setD(SET_X_X(5)); } template void CPUCore::set_5_xix_e() { R.setE(SET_X_X(5)); } template void CPUCore::set_5_xix_h() { R.setH(SET_X_X(5)); } template void CPUCore::set_5_xix_l() { R.setL(SET_X_X(5)); } template void CPUCore::set_6_xix_a() { R.setA(SET_X_X(6)); } template void CPUCore::set_6_xix_b() { R.setB(SET_X_X(6)); } template void CPUCore::set_6_xix_c() { R.setC(SET_X_X(6)); } template void CPUCore::set_6_xix_d() { R.setD(SET_X_X(6)); } template void CPUCore::set_6_xix_e() { R.setE(SET_X_X(6)); } template void CPUCore::set_6_xix_h() { R.setH(SET_X_X(6)); } template void CPUCore::set_6_xix_l() { R.setL(SET_X_X(6)); } template void CPUCore::set_7_xix_a() { R.setA(SET_X_X(7)); } template void CPUCore::set_7_xix_b() { R.setB(SET_X_X(7)); } template void CPUCore::set_7_xix_c() { R.setC(SET_X_X(7)); } template void CPUCore::set_7_xix_d() { R.setD(SET_X_X(7)); } template void CPUCore::set_7_xix_e() { R.setE(SET_X_X(7)); } template void CPUCore::set_7_xix_h() { R.setH(SET_X_X(7)); } template void CPUCore::set_7_xix_l() { R.setL(SET_X_X(7)); } template void CPUCore::set_0_xiy_a() { R.setA(SET_X_Y(0)); } template void CPUCore::set_0_xiy_b() { R.setB(SET_X_Y(0)); } template void CPUCore::set_0_xiy_c() { R.setC(SET_X_Y(0)); } template void CPUCore::set_0_xiy_d() { R.setD(SET_X_Y(0)); } template void CPUCore::set_0_xiy_e() { R.setE(SET_X_Y(0)); } template void CPUCore::set_0_xiy_h() { R.setH(SET_X_Y(0)); } template void CPUCore::set_0_xiy_l() { R.setL(SET_X_Y(0)); } template void CPUCore::set_1_xiy_a() { R.setA(SET_X_Y(1)); } template void CPUCore::set_1_xiy_b() { R.setB(SET_X_Y(1)); } template void CPUCore::set_1_xiy_c() { R.setC(SET_X_Y(1)); } template void CPUCore::set_1_xiy_d() { R.setD(SET_X_Y(1)); } template void CPUCore::set_1_xiy_e() { R.setE(SET_X_Y(1)); } template void CPUCore::set_1_xiy_h() { R.setH(SET_X_Y(1)); } template void CPUCore::set_1_xiy_l() { R.setL(SET_X_Y(1)); } template void CPUCore::set_2_xiy_a() { R.setA(SET_X_Y(2)); } template void CPUCore::set_2_xiy_b() { R.setB(SET_X_Y(2)); } template void CPUCore::set_2_xiy_c() { R.setC(SET_X_Y(2)); } template void CPUCore::set_2_xiy_d() { R.setD(SET_X_Y(2)); } template void CPUCore::set_2_xiy_e() { R.setE(SET_X_Y(2)); } template void CPUCore::set_2_xiy_h() { R.setH(SET_X_Y(2)); } template void CPUCore::set_2_xiy_l() { R.setL(SET_X_Y(2)); } template void CPUCore::set_3_xiy_a() { R.setA(SET_X_Y(3)); } template void CPUCore::set_3_xiy_b() { R.setB(SET_X_Y(3)); } template void CPUCore::set_3_xiy_c() { R.setC(SET_X_Y(3)); } template void CPUCore::set_3_xiy_d() { R.setD(SET_X_Y(3)); } template void CPUCore::set_3_xiy_e() { R.setE(SET_X_Y(3)); } template void CPUCore::set_3_xiy_h() { R.setH(SET_X_Y(3)); } template void CPUCore::set_3_xiy_l() { R.setL(SET_X_Y(3)); } template void CPUCore::set_4_xiy_a() { R.setA(SET_X_Y(4)); } template void CPUCore::set_4_xiy_b() { R.setB(SET_X_Y(4)); } template void CPUCore::set_4_xiy_c() { R.setC(SET_X_Y(4)); } template void CPUCore::set_4_xiy_d() { R.setD(SET_X_Y(4)); } template void CPUCore::set_4_xiy_e() { R.setE(SET_X_Y(4)); } template void CPUCore::set_4_xiy_h() { R.setH(SET_X_Y(4)); } template void CPUCore::set_4_xiy_l() { R.setL(SET_X_Y(4)); } template void CPUCore::set_5_xiy_a() { R.setA(SET_X_Y(5)); } template void CPUCore::set_5_xiy_b() { R.setB(SET_X_Y(5)); } template void CPUCore::set_5_xiy_c() { R.setC(SET_X_Y(5)); } template void CPUCore::set_5_xiy_d() { R.setD(SET_X_Y(5)); } template void CPUCore::set_5_xiy_e() { R.setE(SET_X_Y(5)); } template void CPUCore::set_5_xiy_h() { R.setH(SET_X_Y(5)); } template void CPUCore::set_5_xiy_l() { R.setL(SET_X_Y(5)); } template void CPUCore::set_6_xiy_a() { R.setA(SET_X_Y(6)); } template void CPUCore::set_6_xiy_b() { R.setB(SET_X_Y(6)); } template void CPUCore::set_6_xiy_c() { R.setC(SET_X_Y(6)); } template void CPUCore::set_6_xiy_d() { R.setD(SET_X_Y(6)); } template void CPUCore::set_6_xiy_e() { R.setE(SET_X_Y(6)); } template void CPUCore::set_6_xiy_h() { R.setH(SET_X_Y(6)); } template void CPUCore::set_6_xiy_l() { R.setL(SET_X_Y(6)); } template void CPUCore::set_7_xiy_a() { R.setA(SET_X_Y(7)); } template void CPUCore::set_7_xiy_b() { R.setB(SET_X_Y(7)); } template void CPUCore::set_7_xiy_c() { R.setC(SET_X_Y(7)); } template void CPUCore::set_7_xiy_d() { R.setD(SET_X_Y(7)); } template void CPUCore::set_7_xiy_e() { R.setE(SET_X_Y(7)); } template void CPUCore::set_7_xiy_h() { R.setH(SET_X_Y(7)); } template void CPUCore::set_7_xiy_l() { R.setL(SET_X_Y(7)); } // RL r template inline byte CPUCore::RL(byte reg) { byte c = reg >> 7; reg = (reg << 1) | ((R.getF() & C_FLAG) ? 0x01 : 0); R.setF(ZSPXYTable[reg] | (c ? C_FLAG : 0)); return reg; } template inline byte CPUCore::RL_X(word x) { byte res = RL(RDMEM(x)); T::INC_DELAY(); WRMEM(x, res); return res; } template inline byte CPUCore::RL_X_(word x) { memptr = x; return RL_X(x); } template inline byte CPUCore::RL_X_X() { return RL_X_(R.IX + ofst); } template inline byte CPUCore::RL_X_Y() { return RL_X_(R.IY + ofst); } template void CPUCore::rl_a() { R.setA(RL(R.getA())); } template void CPUCore::rl_b() { R.setB(RL(R.getB())); } template void CPUCore::rl_c() { R.setC(RL(R.getC())); } template void CPUCore::rl_d() { R.setD(RL(R.getD())); } template void CPUCore::rl_e() { R.setE(RL(R.getE())); } template void CPUCore::rl_h() { R.setH(RL(R.getH())); } template void CPUCore::rl_l() { R.setL(RL(R.getL())); } template void CPUCore::rl_xhl() { RL_X(R.HL); } template void CPUCore::rl_xix () { RL_X_X(); } template void CPUCore::rl_xiy () { RL_X_Y(); } template void CPUCore::rl_xix_a() { R.setA(RL_X_X()); } template void CPUCore::rl_xix_b() { R.setB(RL_X_X()); } template void CPUCore::rl_xix_c() { R.setC(RL_X_X()); } template void CPUCore::rl_xix_d() { R.setD(RL_X_X()); } template void CPUCore::rl_xix_e() { R.setE(RL_X_X()); } template void CPUCore::rl_xix_h() { R.setH(RL_X_X()); } template void CPUCore::rl_xix_l() { R.setL(RL_X_X()); } template void CPUCore::rl_xiy_a() { R.setA(RL_X_Y()); } template void CPUCore::rl_xiy_b() { R.setB(RL_X_Y()); } template void CPUCore::rl_xiy_c() { R.setC(RL_X_Y()); } template void CPUCore::rl_xiy_d() { R.setD(RL_X_Y()); } template void CPUCore::rl_xiy_e() { R.setE(RL_X_Y()); } template void CPUCore::rl_xiy_h() { R.setH(RL_X_Y()); } template void CPUCore::rl_xiy_l() { R.setL(RL_X_Y()); } // RLC r template inline byte CPUCore::RLC(byte reg) { byte c = reg >> 7; reg = (reg << 1) | c; R.setF(ZSPXYTable[reg] | (c ? C_FLAG : 0)); return reg; } template inline byte CPUCore::RLC_X(word x) { byte res = RLC(RDMEM(x)); T::INC_DELAY(); WRMEM(x, res); return res; } template inline byte CPUCore::RLC_X_(word x) { memptr = x; return RLC_X(x); } template inline byte CPUCore::RLC_X_X() { return RLC_X_(R.IX + ofst); } template inline byte CPUCore::RLC_X_Y() { return RLC_X_(R.IY + ofst); } template void CPUCore::rlc_a() { R.setA(RLC(R.getA())); } template void CPUCore::rlc_b() { R.setB(RLC(R.getB())); } template void CPUCore::rlc_c() { R.setC(RLC(R.getC())); } template void CPUCore::rlc_d() { R.setD(RLC(R.getD())); } template void CPUCore::rlc_e() { R.setE(RLC(R.getE())); } template void CPUCore::rlc_h() { R.setH(RLC(R.getH())); } template void CPUCore::rlc_l() { R.setL(RLC(R.getL())); } template void CPUCore::rlc_xhl() { RLC_X(R.HL); } template void CPUCore::rlc_xix () { RLC_X_X(); } template void CPUCore::rlc_xiy () { RLC_X_Y(); } template void CPUCore::rlc_xix_a() { R.setA(RLC_X_X()); } template void CPUCore::rlc_xix_b() { R.setB(RLC_X_X()); } template void CPUCore::rlc_xix_c() { R.setC(RLC_X_X()); } template void CPUCore::rlc_xix_d() { R.setD(RLC_X_X()); } template void CPUCore::rlc_xix_e() { R.setE(RLC_X_X()); } template void CPUCore::rlc_xix_h() { R.setH(RLC_X_X()); } template void CPUCore::rlc_xix_l() { R.setL(RLC_X_X()); } template void CPUCore::rlc_xiy_a() { R.setA(RLC_X_Y()); } template void CPUCore::rlc_xiy_b() { R.setB(RLC_X_Y()); } template void CPUCore::rlc_xiy_c() { R.setC(RLC_X_Y()); } template void CPUCore::rlc_xiy_d() { R.setD(RLC_X_Y()); } template void CPUCore::rlc_xiy_e() { R.setE(RLC_X_Y()); } template void CPUCore::rlc_xiy_h() { R.setH(RLC_X_Y()); } template void CPUCore::rlc_xiy_l() { R.setL(RLC_X_Y()); } // RR r template inline byte CPUCore::RR(byte reg) { byte c = reg & 1; reg = (reg >> 1) | ((R.getF() & C_FLAG) ? 0x80 : 0); R.setF(ZSPXYTable[reg] | (c ? C_FLAG : 0)); return reg; } template inline byte CPUCore::RR_X(word x) { byte res = RR(RDMEM(x)); T::INC_DELAY(); WRMEM(x, res); return res; } template inline byte CPUCore::RR_X_(word x) { memptr = x; return RR_X(x); } template inline byte CPUCore::RR_X_X() { return RR_X_(R.IX + ofst); } template inline byte CPUCore::RR_X_Y() { return RR_X_(R.IY + ofst); } template void CPUCore::rr_a() { R.setA(RR(R.getA())); } template void CPUCore::rr_b() { R.setB(RR(R.getB())); } template void CPUCore::rr_c() { R.setC(RR(R.getC())); } template void CPUCore::rr_d() { R.setD(RR(R.getD())); } template void CPUCore::rr_e() { R.setE(RR(R.getE())); } template void CPUCore::rr_h() { R.setH(RR(R.getH())); } template void CPUCore::rr_l() { R.setL(RR(R.getL())); } template void CPUCore::rr_xhl() { RR_X(R.HL); } template void CPUCore::rr_xix () { RR_X_X(); } template void CPUCore::rr_xiy () { RR_X_Y(); } template void CPUCore::rr_xix_a() { R.setA(RR_X_X()); } template void CPUCore::rr_xix_b() { R.setB(RR_X_X()); } template void CPUCore::rr_xix_c() { R.setC(RR_X_X()); } template void CPUCore::rr_xix_d() { R.setD(RR_X_X()); } template void CPUCore::rr_xix_e() { R.setE(RR_X_X()); } template void CPUCore::rr_xix_h() { R.setH(RR_X_X()); } template void CPUCore::rr_xix_l() { R.setL(RR_X_X()); } template void CPUCore::rr_xiy_a() { R.setA(RR_X_Y()); } template void CPUCore::rr_xiy_b() { R.setB(RR_X_Y()); } template void CPUCore::rr_xiy_c() { R.setC(RR_X_Y()); } template void CPUCore::rr_xiy_d() { R.setD(RR_X_Y()); } template void CPUCore::rr_xiy_e() { R.setE(RR_X_Y()); } template void CPUCore::rr_xiy_h() { R.setH(RR_X_Y()); } template void CPUCore::rr_xiy_l() { R.setL(RR_X_Y()); } // RRC r template inline byte CPUCore::RRC(byte reg) { byte c = reg & 1; reg = (reg >> 1) | (c << 7); R.setF(ZSPXYTable[reg] | (c ? C_FLAG : 0)); return reg; } template inline byte CPUCore::RRC_X(word x) { byte res = RRC(RDMEM(x)); T::INC_DELAY(); WRMEM(x, res); return res; } template inline byte CPUCore::RRC_X_(word x) { memptr = x; return RRC_X(x); } template inline byte CPUCore::RRC_X_X() { return RRC_X_(R.IX + ofst); } template inline byte CPUCore::RRC_X_Y() { return RRC_X_(R.IY + ofst); } template void CPUCore::rrc_a() { R.setA(RRC(R.getA())); } template void CPUCore::rrc_b() { R.setB(RRC(R.getB())); } template void CPUCore::rrc_c() { R.setC(RRC(R.getC())); } template void CPUCore::rrc_d() { R.setD(RRC(R.getD())); } template void CPUCore::rrc_e() { R.setE(RRC(R.getE())); } template void CPUCore::rrc_h() { R.setH(RRC(R.getH())); } template void CPUCore::rrc_l() { R.setL(RRC(R.getL())); } template void CPUCore::rrc_xhl() { RRC_X(R.HL); } template void CPUCore::rrc_xix () { RRC_X_X(); } template void CPUCore::rrc_xiy () { RRC_X_Y(); } template void CPUCore::rrc_xix_a() { R.setA(RRC_X_X()); } template void CPUCore::rrc_xix_b() { R.setB(RRC_X_X()); } template void CPUCore::rrc_xix_c() { R.setC(RRC_X_X()); } template void CPUCore::rrc_xix_d() { R.setD(RRC_X_X()); } template void CPUCore::rrc_xix_e() { R.setE(RRC_X_X()); } template void CPUCore::rrc_xix_h() { R.setH(RRC_X_X()); } template void CPUCore::rrc_xix_l() { R.setL(RRC_X_X()); } template void CPUCore::rrc_xiy_a() { R.setA(RRC_X_Y()); } template void CPUCore::rrc_xiy_b() { R.setB(RRC_X_Y()); } template void CPUCore::rrc_xiy_c() { R.setC(RRC_X_Y()); } template void CPUCore::rrc_xiy_d() { R.setD(RRC_X_Y()); } template void CPUCore::rrc_xiy_e() { R.setE(RRC_X_Y()); } template void CPUCore::rrc_xiy_h() { R.setH(RRC_X_Y()); } template void CPUCore::rrc_xiy_l() { R.setL(RRC_X_Y()); } // SLA r template inline byte CPUCore::SLA(byte reg) { byte c = reg >> 7; reg <<= 1; R.setF(ZSPXYTable[reg] | (c ? C_FLAG : 0)); return reg; } template inline byte CPUCore::SLA_X(word x) { byte res = SLA(RDMEM(x)); T::INC_DELAY(); WRMEM(x, res); return res; } template inline byte CPUCore::SLA_X_(word x) { memptr = x; return SLA_X(x); } template inline byte CPUCore::SLA_X_X() { return SLA_X_(R.IX + ofst); } template inline byte CPUCore::SLA_X_Y() { return SLA_X_(R.IY + ofst); } template void CPUCore::sla_a() { R.setA(SLA(R.getA())); } template void CPUCore::sla_b() { R.setB(SLA(R.getB())); } template void CPUCore::sla_c() { R.setC(SLA(R.getC())); } template void CPUCore::sla_d() { R.setD(SLA(R.getD())); } template void CPUCore::sla_e() { R.setE(SLA(R.getE())); } template void CPUCore::sla_h() { R.setH(SLA(R.getH())); } template void CPUCore::sla_l() { R.setL(SLA(R.getL())); } template void CPUCore::sla_xhl() { SLA_X(R.HL); } template void CPUCore::sla_xix () { SLA_X_X(); } template void CPUCore::sla_xiy () { SLA_X_Y(); } template void CPUCore::sla_xix_a() { R.setA(SLA_X_X()); } template void CPUCore::sla_xix_b() { R.setB(SLA_X_X()); } template void CPUCore::sla_xix_c() { R.setC(SLA_X_X()); } template void CPUCore::sla_xix_d() { R.setD(SLA_X_X()); } template void CPUCore::sla_xix_e() { R.setE(SLA_X_X()); } template void CPUCore::sla_xix_h() { R.setH(SLA_X_X()); } template void CPUCore::sla_xix_l() { R.setL(SLA_X_X()); } template void CPUCore::sla_xiy_a() { R.setA(SLA_X_Y()); } template void CPUCore::sla_xiy_b() { R.setB(SLA_X_Y()); } template void CPUCore::sla_xiy_c() { R.setC(SLA_X_Y()); } template void CPUCore::sla_xiy_d() { R.setD(SLA_X_Y()); } template void CPUCore::sla_xiy_e() { R.setE(SLA_X_Y()); } template void CPUCore::sla_xiy_h() { R.setH(SLA_X_Y()); } template void CPUCore::sla_xiy_l() { R.setL(SLA_X_Y()); } // SLL r template inline byte CPUCore::SLL(byte reg) { byte c = reg >> 7; reg = (reg << 1) | 1; R.setF(ZSPXYTable[reg] | (c ? C_FLAG : 0)); return reg; } template inline byte CPUCore::SLL_X(word x) { byte res = SLL(RDMEM(x)); T::INC_DELAY(); WRMEM(x, res); return res; } template inline byte CPUCore::SLL_X_(word x) { memptr = x; return SLL_X(x); } template inline byte CPUCore::SLL_X_X() { return SLL_X_(R.IX + ofst); } template inline byte CPUCore::SLL_X_Y() { return SLL_X_(R.IY + ofst); } template void CPUCore::sll_a() { R.setA(SLL(R.getA())); } template void CPUCore::sll_b() { R.setB(SLL(R.getB())); } template void CPUCore::sll_c() { R.setC(SLL(R.getC())); } template void CPUCore::sll_d() { R.setD(SLL(R.getD())); } template void CPUCore::sll_e() { R.setE(SLL(R.getE())); } template void CPUCore::sll_h() { R.setH(SLL(R.getH())); } template void CPUCore::sll_l() { R.setL(SLL(R.getL())); } template void CPUCore::sll_xhl() { SLL_X(R.HL); } template void CPUCore::sll_xix () { SLL_X_X(); } template void CPUCore::sll_xiy () { SLL_X_Y(); } template void CPUCore::sll_xix_a() { R.setA(SLL_X_X()); } template void CPUCore::sll_xix_b() { R.setB(SLL_X_X()); } template void CPUCore::sll_xix_c() { R.setC(SLL_X_X()); } template void CPUCore::sll_xix_d() { R.setD(SLL_X_X()); } template void CPUCore::sll_xix_e() { R.setE(SLL_X_X()); } template void CPUCore::sll_xix_h() { R.setH(SLL_X_X()); } template void CPUCore::sll_xix_l() { R.setL(SLL_X_X()); } template void CPUCore::sll_xiy_a() { R.setA(SLL_X_Y()); } template void CPUCore::sll_xiy_b() { R.setB(SLL_X_Y()); } template void CPUCore::sll_xiy_c() { R.setC(SLL_X_Y()); } template void CPUCore::sll_xiy_d() { R.setD(SLL_X_Y()); } template void CPUCore::sll_xiy_e() { R.setE(SLL_X_Y()); } template void CPUCore::sll_xiy_h() { R.setH(SLL_X_Y()); } template void CPUCore::sll_xiy_l() { R.setL(SLL_X_Y()); } // SRA r template inline byte CPUCore::SRA(byte reg) { byte c = reg & 1; reg = (reg >> 1) | (reg & 0x80); R.setF(ZSPXYTable[reg] | (c ? C_FLAG : 0)); return reg; } template inline byte CPUCore::SRA_X(word x) { byte res = SRA(RDMEM(x)); T::INC_DELAY(); WRMEM(x, res); return res; } template inline byte CPUCore::SRA_X_(word x) { memptr = x; return SRA_X(x); } template inline byte CPUCore::SRA_X_X() { return SRA_X_(R.IX + ofst); } template inline byte CPUCore::SRA_X_Y() { return SRA_X_(R.IY + ofst); } template void CPUCore::sra_a() { R.setA(SRA(R.getA())); } template void CPUCore::sra_b() { R.setB(SRA(R.getB())); } template void CPUCore::sra_c() { R.setC(SRA(R.getC())); } template void CPUCore::sra_d() { R.setD(SRA(R.getD())); } template void CPUCore::sra_e() { R.setE(SRA(R.getE())); } template void CPUCore::sra_h() { R.setH(SRA(R.getH())); } template void CPUCore::sra_l() { R.setL(SRA(R.getL())); } template void CPUCore::sra_xhl() { SRA_X(R.HL); } template void CPUCore::sra_xix () { SRA_X_X(); } template void CPUCore::sra_xiy () { SRA_X_Y(); } template void CPUCore::sra_xix_a() { R.setA(SRA_X_X()); } template void CPUCore::sra_xix_b() { R.setB(SRA_X_X()); } template void CPUCore::sra_xix_c() { R.setC(SRA_X_X()); } template void CPUCore::sra_xix_d() { R.setD(SRA_X_X()); } template void CPUCore::sra_xix_e() { R.setE(SRA_X_X()); } template void CPUCore::sra_xix_h() { R.setH(SRA_X_X()); } template void CPUCore::sra_xix_l() { R.setL(SRA_X_X()); } template void CPUCore::sra_xiy_a() { R.setA(SRA_X_Y()); } template void CPUCore::sra_xiy_b() { R.setB(SRA_X_Y()); } template void CPUCore::sra_xiy_c() { R.setC(SRA_X_Y()); } template void CPUCore::sra_xiy_d() { R.setD(SRA_X_Y()); } template void CPUCore::sra_xiy_e() { R.setE(SRA_X_Y()); } template void CPUCore::sra_xiy_h() { R.setH(SRA_X_Y()); } template void CPUCore::sra_xiy_l() { R.setL(SRA_X_Y()); } // SRL R template inline byte CPUCore::SRL(byte reg) { byte c = reg & 1; reg >>= 1; R.setF(ZSPXYTable[reg] | (c ? C_FLAG : 0)); return reg; } template inline byte CPUCore::SRL_X(word x) { byte res = SRL(RDMEM(x)); T::INC_DELAY(); WRMEM(x, res); return res; } template inline byte CPUCore::SRL_X_(word x) { memptr = x; return SRL_X(x); } template inline byte CPUCore::SRL_X_X() { return SRL_X_(R.IX + ofst); } template inline byte CPUCore::SRL_X_Y() { return SRL_X_(R.IY + ofst); } template void CPUCore::srl_a() { R.setA(SRL(R.getA())); } template void CPUCore::srl_b() { R.setB(SRL(R.getB())); } template void CPUCore::srl_c() { R.setC(SRL(R.getC())); } template void CPUCore::srl_d() { R.setD(SRL(R.getD())); } template void CPUCore::srl_e() { R.setE(SRL(R.getE())); } template void CPUCore::srl_h() { R.setH(SRL(R.getH())); } template void CPUCore::srl_l() { R.setL(SRL(R.getL())); } template void CPUCore::srl_xhl() { SRL_X(R.HL); } template void CPUCore::srl_xix () { SRL_X_X(); } template void CPUCore::srl_xiy () { SRL_X_Y(); } template void CPUCore::srl_xix_a() { R.setA(SRL_X_X()); } template void CPUCore::srl_xix_b() { R.setB(SRL_X_X()); } template void CPUCore::srl_xix_c() { R.setC(SRL_X_X()); } template void CPUCore::srl_xix_d() { R.setD(SRL_X_X()); } template void CPUCore::srl_xix_e() { R.setE(SRL_X_X()); } template void CPUCore::srl_xix_h() { R.setH(SRL_X_X()); } template void CPUCore::srl_xix_l() { R.setL(SRL_X_X()); } template void CPUCore::srl_xiy_a() { R.setA(SRL_X_Y()); } template void CPUCore::srl_xiy_b() { R.setB(SRL_X_Y()); } template void CPUCore::srl_xiy_c() { R.setC(SRL_X_Y()); } template void CPUCore::srl_xiy_d() { R.setD(SRL_X_Y()); } template void CPUCore::srl_xiy_e() { R.setE(SRL_X_Y()); } template void CPUCore::srl_xiy_h() { R.setH(SRL_X_Y()); } template void CPUCore::srl_xiy_l() { R.setL(SRL_X_Y()); } // RLA RLCA RRA RRCA template void CPUCore::rla() { byte c = R.getF() & C_FLAG; R.setF((R.getF() & (S_FLAG | Z_FLAG | P_FLAG)) | ((R.getA() & 0x80) ? C_FLAG : 0)); R.setA((R.getA() << 1) | (c ? 1 : 0)); R.setF(R.getF() | (R.getA() & (X_FLAG | Y_FLAG))); } template void CPUCore::rlca() { R.setA((R.getA() << 1) | (R.getA() >> 7)); R.setF((R.getF() & (S_FLAG | Z_FLAG | P_FLAG)) | (R.getA() & (Y_FLAG | X_FLAG | C_FLAG))); } template void CPUCore::rra() { byte c = R.getF() & C_FLAG; R.setF((R.getF() & (S_FLAG | Z_FLAG | P_FLAG)) | ((R.getA() & 0x01) ? C_FLAG : 0)); R.setA((R.getA() >> 1) | (c ? 0x80 : 0)); R.setF(R.getF() | (R.getA() & (X_FLAG | Y_FLAG))); } template void CPUCore::rrca() { R.setF((R.getF() & (S_FLAG | Z_FLAG | P_FLAG)) | (R.getA() & C_FLAG)); R.setA((R.getA() >> 1) | (R.getA() << 7)); R.setF(R.getF() | (R.getA() & (X_FLAG | Y_FLAG))); } // RLD template void CPUCore::rld() { byte val = RDMEM(R.HL); memptr = R.HL + 1; T::RLD_DELAY(); WRMEM(R.HL, (val << 4) | (R.getA() & 0x0F)); R.setA((R.getA() & 0xF0) | (val >> 4)); R.setF((R.getF() & C_FLAG) | ZSPXYTable[R.getA()]); } // RRD template void CPUCore::rrd() { byte val = RDMEM(R.HL); memptr = R.HL + 1; T::RLD_DELAY(); WRMEM(R.HL, (val >> 4) | (R.getA() << 4)); R.setA((R.getA() & 0xF0) | (val & 0x0F)); R.setF((R.getF() & C_FLAG) | ZSPXYTable[R.getA()]); } // PUSH ss template inline void CPUCore::PUSH(word reg) { T::PUSH_DELAY(); WRMEM(R.SP - 1, reg >> 8); WRMEM(R.SP - 2, reg & 255); R.SP -= 2; } template void CPUCore::push_af() { PUSH(R.AF); } template void CPUCore::push_bc() { PUSH(R.BC); } template void CPUCore::push_de() { PUSH(R.DE); } template void CPUCore::push_hl() { PUSH(R.HL); } template void CPUCore::push_ix() { PUSH(R.IX); } template void CPUCore::push_iy() { PUSH(R.IY); } // POP ss template inline word CPUCore::POP() { word res = RDMEM(R.SP + 0); res += RDMEM(R.SP + 1) << 8; R.SP += 2; return res; } template void CPUCore::pop_af() { R.AF = POP(); } template void CPUCore::pop_bc() { R.BC = POP(); } template void CPUCore::pop_de() { R.DE = POP(); } template void CPUCore::pop_hl() { R.HL = POP(); } template void CPUCore::pop_ix() { R.IX = POP(); } template void CPUCore::pop_iy() { R.IY = POP(); } // CALL nn / CALL cc,nn template inline void CPUCore::CALL() { memptr = RD_WORD_PC(); PUSH(R.PC); R.PC = memptr; } template inline void CPUCore::SKIP_JP() { memptr = RD_WORD_PC(); } template void CPUCore::call() { CALL(); } template void CPUCore::call_c() { if (C()) CALL(); else SKIP_JP(); } template void CPUCore::call_m() { if (M()) CALL(); else SKIP_JP(); } template void CPUCore::call_nc() { if (NC()) CALL(); else SKIP_JP(); } template void CPUCore::call_nz() { if (NZ()) CALL(); else SKIP_JP(); } template void CPUCore::call_p() { if (P()) CALL(); else SKIP_JP(); } template void CPUCore::call_pe() { if (PE()) CALL(); else SKIP_JP(); } template void CPUCore::call_po() { if (PO()) CALL(); else SKIP_JP(); } template void CPUCore::call_z() { if (Z()) CALL(); else SKIP_JP(); } // RST n template inline void CPUCore::RST(word x) { PUSH(R.PC); memptr = x; R.PC = x; } template void CPUCore::rst_00() { RST(0x00); } template void CPUCore::rst_08() { RST(0x08); } template void CPUCore::rst_10() { RST(0x10); } template void CPUCore::rst_18() { RST(0x18); } template void CPUCore::rst_20() { RST(0x20); } template void CPUCore::rst_28() { RST(0x28); } template void CPUCore::rst_30() { RST(0x30); } template void CPUCore::rst_38() { RST(0x38); } // RET template inline void CPUCore::RET() { memptr = POP(); R.PC = memptr; } template void CPUCore::ret() { RET(); } template void CPUCore::ret_c() { T::SMALL_DELAY(); if (C()) RET(); } template void CPUCore::ret_m() { T::SMALL_DELAY(); if (M()) RET(); } template void CPUCore::ret_nc() { T::SMALL_DELAY(); if (NC()) RET(); } template void CPUCore::ret_nz() { T::SMALL_DELAY(); if (NZ()) RET(); } template void CPUCore::ret_p() { T::SMALL_DELAY(); if (P()) RET(); } template void CPUCore::ret_pe() { T::SMALL_DELAY(); if (PE()) RET(); } template void CPUCore::ret_po() { T::SMALL_DELAY(); if (PO()) RET(); } template void CPUCore::ret_z() { T::SMALL_DELAY(); if (Z()) RET(); } template void CPUCore::reti() { // same as retn T::RETN_DELAY(); R.IFF1 = R.IFF2; R.nextIFF1 = R.IFF2; setSlowInstructions(); RET(); } template void CPUCore::retn() { T::RETN_DELAY(); R.IFF1 = R.IFF2; R.nextIFF1 = R.IFF2; setSlowInstructions(); RET(); } // JP ss template void CPUCore::jp_hl() { R.PC = R.HL; } template void CPUCore::jp_ix() { R.PC = R.IX; } template void CPUCore::jp_iy() { R.PC = R.IY; } // JP nn / JP cc,nn template inline void CPUCore::JP() { memptr = RD_WORD_PC(); R.PC = memptr; } template void CPUCore::jp() { JP(); } template void CPUCore::jp_c() { if (C()) JP(); else SKIP_JP(); } template void CPUCore::jp_m() { if (M()) JP(); else SKIP_JP(); } template void CPUCore::jp_nc() { if (NC()) JP(); else SKIP_JP(); } template void CPUCore::jp_nz() { if (NZ()) JP(); else SKIP_JP(); } template void CPUCore::jp_p() { if (P()) JP(); else SKIP_JP(); } template void CPUCore::jp_pe() { if (PE()) JP(); else SKIP_JP(); } template void CPUCore::jp_po() { if (PO()) JP(); else SKIP_JP(); } template void CPUCore::jp_z() { if (Z()) JP(); else SKIP_JP(); } // JR e template inline void CPUCore::JR() { offset ofst = RDMEM_OPCODE(R.PC); R.PC += ofst + 1; memptr = R.PC; T::ADD_16_8_DELAY(); } template inline void CPUCore::SKIP_JR() { RDMEM_OPCODE(R.PC++); // ignore return value } template void CPUCore::jr() { JR(); } template void CPUCore::jr_c() { if (C()) JR(); else SKIP_JR(); } template void CPUCore::jr_nc() { if (NC()) JR(); else SKIP_JR(); } template void CPUCore::jr_nz() { if (NZ()) JR(); else SKIP_JR(); } template void CPUCore::jr_z() { if (Z()) JR(); else SKIP_JR(); } // DJNZ e template void CPUCore::djnz() { T::SMALL_DELAY(); byte b = R.getB(); R.setB(--b); if (b) JR(); else SKIP_JR(); } // EX (SP),ss template inline void CPUCore::EX_SP(word& reg) { memptr = RDMEM(R.SP + 0); memptr += RDMEM(R.SP + 1) << 8; T::SMALL_DELAY(); WRMEM(R.SP + 1, reg >> 8); WRMEM(R.SP + 0, reg & 255); reg = memptr; T::EX_SP_HL_DELAY(); } template void CPUCore::ex_xsp_hl() { EX_SP(R.HL); } template void CPUCore::ex_xsp_ix() { EX_SP(R.IX); } template void CPUCore::ex_xsp_iy() { EX_SP(R.IY); } // IN r,(c) template inline byte CPUCore::IN() { byte res = READ_PORT(R.BC); R.setF((R.getF() & C_FLAG) | ZSPXYTable[res]); return res; } template void CPUCore::in_a_c() { R.setA(IN()); } template void CPUCore::in_b_c() { R.setB(IN()); } template void CPUCore::in_c_c() { R.setC(IN()); } template void CPUCore::in_d_c() { R.setD(IN()); } template void CPUCore::in_e_c() { R.setE(IN()); } template void CPUCore::in_h_c() { R.setH(IN()); } template void CPUCore::in_l_c() { R.setL(IN()); } template void CPUCore::in_0_c() { IN(); } // discard result // IN a,(n) template void CPUCore::in_a_byte() { word y = RDMEM_OPCODE(R.PC++) + 256 * R.getA(); R.setA(READ_PORT(y)); } // OUT (c),r template inline void CPUCore::OUT(byte val) { WRITE_PORT(R.BC, val); } template void CPUCore::out_c_a() { OUT(R.getA()); } template void CPUCore::out_c_b() { OUT(R.getB()); } template void CPUCore::out_c_c() { OUT(R.getC()); } template void CPUCore::out_c_d() { OUT(R.getD()); } template void CPUCore::out_c_e() { OUT(R.getE()); } template void CPUCore::out_c_h() { OUT(R.getH()); } template void CPUCore::out_c_l() { OUT(R.getL()); } template void CPUCore::out_c_0() { OUT(0); } // OUT (n),a template void CPUCore::out_byte_a() { word y = RDMEM_OPCODE(R.PC++) + 256 * R.getA(); WRITE_PORT(y, R.getA()); } // block CP template inline void CPUCore::BLOCK_CP(bool increase, bool repeat) { byte val = RDMEM(R.HL); T::BLOCK_DELAY(); byte res = R.getA() - val; if (increase) R.HL++; else R.HL--; R.BC--; byte f = (R.getF() & C_FLAG) | ((R.getA() ^ val ^ res) & H_FLAG) | ZSTable[res] | N_FLAG; if (f & H_FLAG) res -= 1; if (res & 0x02) f |= Y_FLAG; // bit 1 -> flag 5 if (res & 0x08) f |= X_FLAG; // bit 3 -> flag 3 if (R.BC) f |= V_FLAG; R.setF(f); if (repeat && R.BC && !(f & Z_FLAG)) { T::BLOCK_DELAY(); R.PC -= 2; } } template void CPUCore::cpd() { BLOCK_CP(false, false); } template void CPUCore::cpi() { BLOCK_CP(true, false); } template void CPUCore::cpdr() { BLOCK_CP(false, true ); } template void CPUCore::cpir() { BLOCK_CP(true, true ); } // block LD template inline void CPUCore::BLOCK_LD(bool increase, bool repeat) { byte val = RDMEM(R.HL); WRMEM(R.DE, val); T::LDI_DELAY(); if (increase) { R.HL++; R.DE++; } else { R.HL--; R.DE--; } R.BC--; byte f = R.getF() & (S_FLAG | Z_FLAG | C_FLAG); if ((R.getA() + val) & 0x02) f |= Y_FLAG; // bit 1 -> flag 5 if ((R.getA() + val) & 0x08) f |= X_FLAG; // bit 3 -> flag 3 if (R.BC) f |= V_FLAG; R.setF(f); if (repeat && R.BC) { T::BLOCK_DELAY(); R.PC -= 2; } } template void CPUCore::ldd() { BLOCK_LD(false, false); } template void CPUCore::ldi() { BLOCK_LD(true, false); } template void CPUCore::lddr() { BLOCK_LD(false, true ); } template void CPUCore::ldir() { BLOCK_LD(true, true ); } // block IN template inline void CPUCore::BLOCK_IN(bool increase, bool repeat) { T::SMALL_DELAY(); byte b = R.getB() - 1; R.setB(b); // decr before use byte val = READ_PORT(R.BC); WRMEM(R.HL, val); if (increase) R.HL++; else R.HL--; byte f = ZSTable[b]; if (val & S_FLAG) f |= N_FLAG; int k = val + ((R.getC() + (increase ? 1 : -1)) & 0xFF); if (k & 0x100) f |= H_FLAG | C_FLAG; R.setF(f | (ZSPXYTable[(k & 0x07) ^ b] & P_FLAG)); if (repeat && b) { T::BLOCK_DELAY(); R.PC -= 2; } } template void CPUCore::ind() { BLOCK_IN(false, false); } template void CPUCore::ini() { BLOCK_IN(true, false); } template void CPUCore::indr() { BLOCK_IN(false, true ); } template void CPUCore::inir() { BLOCK_IN(true, true ); } // block OUT template inline void CPUCore::BLOCK_OUT(bool increase, bool repeat) { T::SMALL_DELAY(); byte val = RDMEM(R.HL); WRITE_PORT(R.BC, val); byte b = R.getB() - 1; R.setB(b); // decr after use if (increase) R.HL++; else R.HL--; byte f = ZSXYTable[b]; if (val & S_FLAG) f |= N_FLAG; int k = val + R.getL(); if (k & 0x100) f |= H_FLAG | C_FLAG; R.setF(f | (ZSPXYTable[(k & 0x07) ^ b] & P_FLAG)); if (repeat && b) { T::BLOCK_DELAY(); R.PC -= 2; } } template void CPUCore::outd() { BLOCK_OUT(false, false); } template void CPUCore::outi() { BLOCK_OUT(true, false); } template void CPUCore::otdr() { BLOCK_OUT(false, true ); } template void CPUCore::otir() { BLOCK_OUT(true, true ); } // various template void CPUCore::nop() { } template void CPUCore::ccf() { R.setF(((R.getF() & (S_FLAG | Z_FLAG | P_FLAG | C_FLAG)) | ((R.getF() & C_FLAG) ? H_FLAG : 0) | (R.getA() & (X_FLAG | Y_FLAG)) ) ^ C_FLAG); } template void CPUCore::cpl() { R.setA(R.getA() ^ 0xFF); R.setF((R.getF() & (S_FLAG | Z_FLAG | P_FLAG | C_FLAG)) | H_FLAG | N_FLAG | (R.getA() & (X_FLAG | Y_FLAG))); } template void CPUCore::daa() { int i = R.getA(); if (R.getF() & C_FLAG) i |= 0x100; if (R.getF() & H_FLAG) i |= 0x200; if (R.getF() & N_FLAG) i |= 0x400; R.AF = DAATable[i]; } template void CPUCore::neg() { byte i = R.getA(); R.setA(0); SUB(i); } template void CPUCore::scf() { R.setF((R.getF() & (S_FLAG | Z_FLAG | P_FLAG)) | C_FLAG | (R.getA() & (X_FLAG | Y_FLAG))); } template void CPUCore::ex_af_af() { std::swap(R.AF, R.AF2); } template void CPUCore::ex_de_hl() { std::swap(R.DE, R.HL); } template void CPUCore::exx() { std::swap(R.BC, R.BC2); std::swap(R.DE, R.DE2); std::swap(R.HL, R.HL2); } template void CPUCore::di() { T::DI_DELAY(); R.di(); } template void CPUCore::ei() { R.IFF1 = false; // no ints after this instruction R.nextIFF1 = true; // but allow them after next instruction R.IFF2 = true; setSlowInstructions(); } template void CPUCore::halt() { R.HALT = true; setSlowInstructions(); if (!(R.IFF1 || R.nextIFF1 || R.IFF2)) { motherboard.getMSXCliComm().printWarning( "DI; HALT detected, which means a hang. " "You can just as well reset the MSX now...\n"); } } template void CPUCore::im_0() { T::SET_IM_DELAY(); R.IM = 0; } template void CPUCore::im_1() { T::SET_IM_DELAY(); R.IM = 1; } template void CPUCore::im_2() { T::SET_IM_DELAY(); R.IM = 2; } // LD A,I/R template void CPUCore::ld_a_i() { T::SMALL_DELAY(); R.setA(R.I); R.setF((R.getF() & C_FLAG) | ZSXYTable[R.getA()] | (R.IFF2 ? V_FLAG : 0)); } template void CPUCore::ld_a_r() { T::SMALL_DELAY(); R.setA((R.R & 0x7f) | (R.R2 & 0x80)); R.setF((R.getF() & C_FLAG) | ZSXYTable[R.getA()] | (R.IFF2 ? V_FLAG : 0)); } // LD I/R,A template void CPUCore::ld_i_a() { T::SMALL_DELAY(); R.I = R.getA(); } template void CPUCore::ld_r_a() { T::SMALL_DELAY(); R.R = R.R2 = R.getA(); } // MULUB A,r template inline void CPUCore::MULUB(byte reg) { // TODO check flags T::MULUB_DELAY(); R.HL = (word)R.getA() * reg; R.setF((R.getF() & (N_FLAG | H_FLAG)) | (R.HL ? 0 : Z_FLAG) | ((R.HL & 0x8000) ? C_FLAG : 0)); } template void CPUCore::mulub_a_xhl() { } // TODO template void CPUCore::mulub_a_a() { } // TODO template void CPUCore::mulub_a_b() { MULUB(R.getB()); } template void CPUCore::mulub_a_c() { MULUB(R.getC()); } template void CPUCore::mulub_a_d() { MULUB(R.getD()); } template void CPUCore::mulub_a_e() { MULUB(R.getE()); } template void CPUCore::mulub_a_h() { } // TODO template void CPUCore::mulub_a_l() { } // TODO // MULUW HL,ss template inline void CPUCore::MULUW(word reg) { // TODO check flags T::MULUW_DELAY(); unsigned long res = (unsigned long)R.HL * reg; R.DE = res >> 16; R.HL = res & 0xffff; R.setF((R.getF() & (N_FLAG | H_FLAG)) | (res ? 0 : Z_FLAG) | ((res & 0x80000000) ? C_FLAG : 0)); } template void CPUCore::muluw_hl_bc() { MULUW(R.BC); } template void CPUCore::muluw_hl_de() { } // TODO template void CPUCore::muluw_hl_hl() { } // TODO template void CPUCore::muluw_hl_sp() { MULUW(R.SP); } // prefixes template void CPUCore::dd_cb() { ofst = RDMEM_OPCODE(R.PC++); byte opcode = RDMEM_OPCODE(R.PC++); T::DD_CB_DELAY(); (this->*opcode_dd_cb[opcode])(); } template void CPUCore::fd_cb() { ofst = RDMEM_OPCODE(R.PC++); byte opcode = RDMEM_OPCODE(R.PC++); T::DD_CB_DELAY(); (this->*opcode_fd_cb[opcode])(); } template void CPUCore::cb() { byte opcode = RDMEM_OPCODE(R.PC++); M1Cycle(); (this->*opcode_cb[opcode])(); } template void CPUCore::ed() { byte opcode = RDMEM_OPCODE(R.PC++); M1Cycle(); (this->*opcode_ed[opcode])(); } template void CPUCore::dd() { byte opcode = RDMEM_OPCODE(R.PC++); M1Cycle(); (this->*opcode_dd[opcode])(); } template void CPUCore::fd() { byte opcode = RDMEM_OPCODE(R.PC++); M1Cycle(); (this->*opcode_fd[opcode])(); } // Force template instantiation template class CPUCore; template class CPUCore; } // namespace openmsx