#pragma once #include #include #include "Processor.h" namespace EightBit { class IntelProcessor : public Processor { public: struct opcode_decoded_t { int x; int y; int z; int p; int q; opcode_decoded_t() { x = y = z = p = q = 0; } opcode_decoded_t(uint8_t opcode) { x = (opcode & 0b11000000) >> 6; // 0 - 3 y = (opcode & 0b00111000) >> 3; // 0 - 7 z = (opcode & 0b00000111); // 0 - 7 p = (y & 0b110) >> 1; // 0 - 3 q = (y & 1); // 0 - 1 } }; const opcode_decoded_t& getDecodedOpcode(const int i) const { return m_decodedOpcodes[i]; } register16_t& MEMPTR() { return m_memptr; } virtual void initialise(); register16_t& SP() { return sp; } virtual register16_t& AF() = 0; uint8_t& A() { return AF().high; } uint8_t& F() { return AF().low; } virtual register16_t& BC() = 0; uint8_t& B() { return BC().high; } uint8_t& C() { return BC().low; } virtual register16_t& DE() = 0; uint8_t& D() { return DE().high; } uint8_t& E() { return DE().low; } virtual register16_t& HL() = 0; uint8_t& H() { return HL().high; } uint8_t& L() { return HL().low; } protected: IntelProcessor(Memory& memory); template static void adjustSign(uint8_t& f, uint8_t value) { setFlag(f, T::SF, value & T::SF); } template static void adjustZero(uint8_t& f, uint8_t value) { clearFlag(f, T::ZF, value); } template static void adjustParity(uint8_t& f, uint8_t value) { static const int lookup[0x10] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; auto set = lookup[highNibble(value)] + lookup[lowNibble(value)]; clearFlag(f, T::PF, set % 2); } template static void adjustSZ(uint8_t& f, uint8_t value) { adjustSign(f, value); adjustZero(f, value); } template static void adjustSZP(uint8_t& f, uint8_t value) { adjustSZ(f, value); adjustParity(f, value); } template static void adjustXY(uint8_t& f, uint8_t value) { setFlag(f, T::XF, value & T::XF); setFlag(f, T::YF, value & T::YF); } template static void adjustSZPXY(uint8_t& f, uint8_t value) { adjustSZP(f, value); adjustXY(f, value); } template static void adjustSZXY(uint8_t& f, uint8_t value) { adjustSZ(f, value); adjustXY(f, value); } // static int buildHalfCarryIndex(uint8_t before, uint8_t value, int calculation) { __assume(calculation < 0x1ffff); return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3); } static bool calculateHalfCarryAdd(uint8_t before, uint8_t value, int calculation) { __assume(calculation < 0x1ffff); static std::array m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } }; auto index = buildHalfCarryIndex(before, value, calculation); return m_halfCarryTableAdd[index & Mask3]; } static bool calculateHalfCarrySub(uint8_t before, uint8_t value, int calculation) { __assume(calculation < 0x1ffff); std::array m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } }; auto index = buildHalfCarryIndex(before, value, calculation); return m_halfCarryTableSub[index & Mask3]; } virtual void push(uint8_t value) { m_memory.ADDRESS().word = --SP().word; m_memory.reference() = value; } void pushWord(const register16_t& value) { push(value.high); push(value.low); } virtual uint8_t pop() { m_memory.ADDRESS().word = SP().word++; return m_memory.reference(); } void popWord(register16_t& output) { output.low = pop(); output.high = pop(); } void fetchWord() { Processor::fetchWord(MEMPTR()); } // uint8_t& memptrReference() { m_memory.ADDRESS() = MEMPTR(); MEMPTR().word++; return m_memory.reference(); } virtual void getWordViaMemptr(register16_t& value) { value.low = memptrReference(); m_memory.ADDRESS().word++; value.high = m_memory.reference(); } virtual void setWordViaMemptr(register16_t value) { memptrReference() = value.low; m_memory.ADDRESS().word++; m_memory.reference() = value.high; } // void jump() { PC() = MEMPTR(); } void call() { pushWord(PC()); jump(); } void restart(uint8_t address) { MEMPTR().low = address; MEMPTR().high = 0; call(); } bool callConditional(int condition) { fetchWord(); if (condition) call(); return condition != 0; } bool jumpConditional(int conditional) { fetchWord(); if (conditional) jump(); return conditional != 0; } void ret() { popWord(MEMPTR()); jump(); } bool returnConditional(int condition) { if (condition) ret(); return condition != 0; } void jr(int8_t offset) { MEMPTR().word = PC().word + offset; jump(); } bool jrConditional(int conditional) { auto offset = fetchByte(); if (conditional) jr(offset); return conditional != 0; } private: std::array m_decodedOpcodes; register16_t m_memptr; register16_t sp; }; }