你现在是一位严格的代码检查员，而下面是实现DMG CPU （SM80）的一段C++代码，你需要严格遵循SM80CPU指令集的格式和逻辑，来对下面的代码逻辑是否一致来进行检视。若检视出有错误，你应该逐一指出其中的错误，并返回可能的修改。

// BUS.cpp

#include "Bus.hpp"

// 0x0000 - 0x3FFF : ROM Bank 0
// 0x4000 - 0x7FFF : ROM Bank 1 - Switchable
// 0x8000 - 0x97FF : CHR RAM
// 0x9800 - 0x9BFF : BG Map 1
// 0x9C00 - 0x9FFF : BG Map 2
// 0xA000 - 0xBFFF : Cartridge RAM
// 0xC000 - 0xCFFF : RAM Bank 0
// 0xD000 - 0xDFFF : RAM Bank 1-7 - switchable - Color only
// 0xE000 - 0xFDFF : Reserved - Echo RAM
// 0xFE00 - 0xFE9F : Object Attribute Memory
// 0xFEA0 - 0xFEFF : Reserved - Unusable
// 0xFF00 - 0xFF7F : I/O Registers

namespace GBCEmu {
    Bus::Bus(Cartridge& cart, RAM& ram, CPURegister& reg) : cart_(cart), ram_(ram), reg_(reg)
    {
    }

    Bus::~Bus()
    {
    }
    uint8_t Bus::read(uint16_t addr)
    {
        TRACE("Bus::read, addr: " << std::hex << addr);
        if (addr < 0x8000) {
            return cart_.read(addr);
        } else if (addr < 0xA000) {
            std::cerr << "Bus::read unspported..." << std::hex << addr << "\n";
        } else if (addr < 0xC000) {
            return cart_.read(addr);
        } else if (addr < 0xE000) {
            return ram_.readWRAM(addr);
        } else if (addr < 0xFE00) {
            std::cerr << "Bus::read unspported..." << std::hex << addr << "\n";
        } else if (addr < 0xFEA0) {
            std::cerr << "Bus::read unspported..." << std::hex << addr << "\n";
            return 0;
        } else if (addr < 0xFF00) {
            std::cerr << "Bus::read unspported..." << std::hex << addr << "\n";

        } else if (addr < 0xFF80) {
            std::cerr << "Bus::read unspported..." << std::hex << addr << "\n";
        } else if (addr == 0xFFFF) {
            return reg_.ie_;
        } else {
            ram_.readHRAM(addr);
        }
        return 0;
    }
    uint16_t Bus::read16(uint16_t addr)
    {
        TRACE("Bus::read, addr: " << std::hex << addr);
        if (addr < 0x8000) {
            return cart_.read(addr);
        }
        std::cerr << "Bus::read\n";
    }
    void Bus::write(uint16_t addr, uint8_t val)
    {
        // std::cout << "Bus::write addr: " << std::hex << addr << "\n";
        if (addr < 0x8000) {
            cart_.write(addr, val);
            return;
        } else if (addr < 0xA000) {
            std::cerr << "Bus::write unspported..." << std::hex << addr << "\n";
        } else if (addr < 0xC000) {
            cart_.write(addr, val);
        } else if (addr < 0xE000) {
            ram_.writeWRAM(addr, val);
            return;
        } else if (addr < 0xFE00) {
            std::cerr << "Bus::write unspported..." << std::hex << addr << "\n";
        } else if (addr < 0xFEA0) {
            std::cerr << "Bus::write unspported..." << std::hex << addr << "\n";
        } else if (addr < 0xFF00) {
            std::cerr << "Bus::write unspported..." << std::hex << addr << "\n";
        } else if (addr < 0xFF80) {
            std::cerr << "Bus::write unspported..." << std::hex << addr << "\n";
        } else if (addr == 0xFFFF) {
            reg_.ie_ = val; 
        } else  {
            ram_.writeHRAM(addr, val);
        }
    }
    void Bus::write16(uint16_t addr, uint16_t val)
    {
        write(addr, val & 0xFF);
        write(addr + 1, (val >> 8) & 0xFF);
    }
}

// Common.hpp
#pragma once
#include <stdint.h>
#include <string>
#include <exception>
#include <vector>
#include <iostream>
#include <unordered_map>

#define NO_IMPL std::cout << "NOT IMPLEMENTED" << std::endl; exit(-5);

namespace GBCEmu {

class logHelper {
public:
    logHelper(std::string funcName) : funcName_(funcName){
        // std::cout << funcName_ << " Entered...\n";
    }
    ~logHelper(){
        // std::cout << funcName_ << " Exited...\n";
    }
private:
    std::string funcName_;
};

#define FUNC_TRACE(funcName) logHelper log(funcName);
#define TRACE(log) while(0);


inline int getBit(uint64_t n, uint64_t digit)
{
    return n & (1 << digit) ? 1 : 0;
}

inline void setBit(uint16_t& n, uint64_t digit, bool val)
{
    if (val) {
        n |= (1 << digit);
    } else {
        n &= ~(1 << digit);
    }
}

inline void setBit(uint8_t& n, uint64_t digit, bool val)
{
    if (val) {
        n |= (1 << digit);
    } else {
        n &= ~(1 << digit);
    }
}

inline bool between(uint64_t a, uint64_t b, uint64_t c)
{
    return (a <= b) && (b <= c);
}

void delay(uint32_t ms);
}

// Instruction.cpp

#include "Instruction.hpp"
#include "unordered_map"

namespace GBCEmu {
const std::unordered_map<uint8_t, Instruction> INSTRCUTION_SET = {
    {0x00, {InstType::NOP, AddrMode::IMP}},
    {0x01, {InstType::LD, AddrMode::R_D16, RegType::BC}},
    {0x02, {InstType::LD, AddrMode::MR_R, RegType::BC, RegType::A}},
    {0x03, {InstType::INC, AddrMode::R, RegType::BC}},
    {0x04, {InstType::INC, AddrMode::R, RegType::B}},
    {0x05, {InstType::DEC, AddrMode::R, RegType::B}},
    {0x06, {InstType::LD, AddrMode::R_D8, RegType::B}},
    {0x07, {InstType::RLCA, AddrMode::IMP}},
    {0x08, {InstType::LD, AddrMode::A16_R, RegType::NONE, RegType::SP}},
    {0x09, {InstType::ADD, AddrMode::R_R, RegType::HL, RegType::BC}},
    {0x0A, {InstType::LD, AddrMode::R_MR, RegType::A, RegType::BC}},
    {0x0B, {InstType::DEC, AddrMode::R, RegType::BC}},
    {0x0C, {InstType::INC, AddrMode::R, RegType::C}},
    {0x0D, {InstType::DEC, AddrMode::R, RegType::C}},
    {0x0E, {InstType::LD, AddrMode::R_D8, RegType::C}},
    {0x0F, {InstType::RRCA, AddrMode::IMP}},

    {0x10, {InstType::STOP, AddrMode::IMP}},
    {0x11, {InstType::LD, AddrMode::R_D16, RegType::DE}},
    {0x12, {InstType::LD, AddrMode::MR_R, RegType::DE, RegType::A}},
    {0x13, {InstType::INC, AddrMode::R, RegType::DE}},
    {0x14, {InstType::INC, AddrMode::R, RegType::D}},
    {0x15, {InstType::DEC, AddrMode::R, RegType::D}},
    {0x16, {InstType::LD, AddrMode::R_D8, RegType::D}},
    {0x17, {InstType::RLA, AddrMode::IMP}},
    {0x18, {InstType::JR, AddrMode::D8}},
    {0x19, {InstType::ADD, AddrMode::R_R, RegType::HL, RegType::DE}},
    {0x1A, {InstType::LD, AddrMode::R_MR, RegType::A, RegType::DE}},
    {0x1B, {InstType::DEC, AddrMode::R, RegType::DE}},
    {0x1C, {InstType::INC, AddrMode::R, RegType::E}},
    {0x1D, {InstType::DEC, AddrMode::R, RegType::E}},
    {0x1E, {InstType::LD, AddrMode::R_D8, RegType::E}},
    {0x1F, {InstType::RRA, AddrMode::IMP}},

    {0x20, {InstType::JR, AddrMode::D8, RegType::NONE, RegType::NONE, CondType::NZ}},
    {0x21, {InstType::LD, AddrMode::R_D16, RegType::HL}},
    {0x22, {InstType::LD, AddrMode::HLI_R, RegType::HL, RegType::A}},
    {0x23, {InstType::INC, AddrMode::R, RegType::HL}},
    {0x24, {InstType::INC, AddrMode::R, RegType::H}},
    {0x25, {InstType::DEC, AddrMode::R, RegType::H}},
    {0x26, {InstType::LD, AddrMode::R_D8, RegType::H}},
    {0x27, {InstType::DAA, AddrMode::IMP}},
    {0x28, {InstType::JR, AddrMode::D8, RegType::NONE, RegType::NONE, CondType::Z}},
    {0x29, {InstType::ADD, AddrMode::R_R, RegType::HL, RegType::HL}},
    {0x2A, {InstType::LD, AddrMode::R_HLI, RegType::A, RegType::HL}},
    {0x2B, {InstType::DEC, AddrMode::R, RegType::HL}},
    {0x2C, {InstType::INC, AddrMode::R, RegType::L}},
    {0x2D, {InstType::DEC, AddrMode::R, RegType::L}},
    {0x2E, {InstType::LD, AddrMode::R_D8, RegType::L}},
    {0x2F, {InstType::CPL, AddrMode::IMP}},

    {0x30, {InstType::JR, AddrMode::D8, RegType::NONE, RegType::NONE, CondType::NC}},
    {0x31, {InstType::LD, AddrMode::R_D16, RegType::SP}},
    {0x32, {InstType::LD, AddrMode::HLD_R, RegType::HL, RegType::A}},
    {0x33, {InstType::INC, AddrMode::R, RegType::SP}},
    {0x34, {InstType::INC, AddrMode::MR, RegType::HL}},
    {0x35, {InstType::DEC, AddrMode::MR, RegType::HL}},
    {0x36, {InstType::LD, AddrMode::R_D8, RegType::HL}},
    {0x37, {InstType::SCF, AddrMode::IMP}},
    {0x38, {InstType::JR, AddrMode::D8, RegType::NONE, RegType::NONE, CondType::C}},
    {0x39, {InstType::ADD, AddrMode::R_R, RegType::HL, RegType::SP}},
    {0x3A, {InstType::LD, AddrMode::R_HLD, RegType::A, RegType::HL}},
    {0x3B, {InstType::DEC, AddrMode::R, RegType::SP}},
    {0x3C, {InstType::INC, AddrMode::R, RegType::A}},
    {0x3D, {InstType::DEC, AddrMode::R, RegType::A}},
    {0x3E, {InstType::LD, AddrMode::R_D8, RegType::A}},
    {0x3F, {InstType::CCF, AddrMode::IMP}},

    {0x40, {InstType::LD, AddrMode::R_R, RegType::B, RegType::B}},
    {0x41, {InstType::LD, AddrMode::R_R, RegType::B, RegType::C}},
    {0x42, {InstType::LD, AddrMode::R_R, RegType::B, RegType::D}},
    {0x43, {InstType::LD, AddrMode::R_R, RegType::B, RegType::E}},
    {0x44, {InstType::LD, AddrMode::R_R, RegType::B, RegType::H}},
    {0x45, {InstType::LD, AddrMode::R_R, RegType::B, RegType::L}},
    {0x46, {InstType::LD, AddrMode::R_MR, RegType::B, RegType::HL}},
    {0x47, {InstType::LD, AddrMode::R_R, RegType::B, RegType::A}},
    {0x48, {InstType::LD, AddrMode::R_R, RegType::C, RegType::B}},
    {0x49, {InstType::LD, AddrMode::R_R, RegType::C, RegType::C}},
    {0x4A, {InstType::LD, AddrMode::R_R, RegType::C, RegType::D}},
    {0x4B, {InstType::LD, AddrMode::R_R, RegType::C, RegType::E}},
    {0x4C, {InstType::LD, AddrMode::R_R, RegType::C, RegType::H}},
    {0x4D, {InstType::LD, AddrMode::R_R, RegType::C, RegType::L}},
    {0x4E, {InstType::LD, AddrMode::R_MR, RegType::C, RegType::HL}},
    {0x4F, {InstType::LD, AddrMode::R_R, RegType::C, RegType::A}},

    {0x50, {InstType::LD, AddrMode::R_R, RegType::D, RegType::B}},
    {0x51, {InstType::LD, AddrMode::R_R, RegType::D, RegType::C}},
    {0x52, {InstType::LD, AddrMode::R_R, RegType::D, RegType::D}},
    {0x53, {InstType::LD, AddrMode::R_R, RegType::D, RegType::E}},
    {0x54, {InstType::LD, AddrMode::R_R, RegType::D, RegType::H}},
    {0x55, {InstType::LD, AddrMode::R_R, RegType::D, RegType::L}},
    {0x56, {InstType::LD, AddrMode::R_MR, RegType::D, RegType::HL}},
    {0x57, {InstType::LD, AddrMode::R_R, RegType::D, RegType::A}},
    {0x58, {InstType::LD, AddrMode::R_R, RegType::E, RegType::B}},
    {0x59, {InstType::LD, AddrMode::R_R, RegType::E, RegType::C}},
    {0x5A, {InstType::LD, AddrMode::R_R, RegType::E, RegType::D}},
    {0x5B, {InstType::LD, AddrMode::R_R, RegType::E, RegType::E}},
    {0x5C, {InstType::LD, AddrMode::R_R, RegType::E, RegType::H}},
    {0x5D, {InstType::LD, AddrMode::R_R, RegType::E, RegType::L}},
    {0x5E, {InstType::LD, AddrMode::R_MR, RegType::E, RegType::HL}},
    {0x5F, {InstType::LD, AddrMode::R_R, RegType::E, RegType::A}},

    {0x60, {InstType::LD, AddrMode::R_R, RegType::H, RegType::B}},
    {0x61, {InstType::LD, AddrMode::R_R, RegType::H, RegType::C}},
    {0x62, {InstType::LD, AddrMode::R_R, RegType::H, RegType::D}},
    {0x63, {InstType::LD, AddrMode::R_R, RegType::H, RegType::E}},
    {0x64, {InstType::LD, AddrMode::R_R, RegType::H, RegType::H}},
    {0x65, {InstType::LD, AddrMode::R_R, RegType::H, RegType::L}},
    {0x66, {InstType::LD, AddrMode::R_MR, RegType::H, RegType::HL}},
    {0x67, {InstType::LD, AddrMode::R_R, RegType::H, RegType::A}},
    {0x68, {InstType::LD, AddrMode::R_R, RegType::L, RegType::B}},
    {0x69, {InstType::LD, AddrMode::R_R, RegType::L, RegType::C}},
    {0x6A, {InstType::LD, AddrMode::R_R, RegType::L, RegType::D}},
    {0x6B, {InstType::LD, AddrMode::R_R, RegType::L, RegType::E}},
    {0x6C, {InstType::LD, AddrMode::R_R, RegType::L, RegType::H}},
    {0x6D, {InstType::LD, AddrMode::R_R, RegType::L, RegType::L}},
    {0x6E, {InstType::LD, AddrMode::R_MR, RegType::L, RegType::HL}},
    {0x6F, {InstType::LD, AddrMode::R_R, RegType::L, RegType::A}},

    {0x70, {InstType::LD, AddrMode::MR_R, RegType::HL, RegType::B}},
    {0x71, {InstType::LD, AddrMode::MR_R, RegType::HL, RegType::C}},
    {0x72, {InstType::LD, AddrMode::MR_R, RegType::HL, RegType::D}},
    {0x73, {InstType::LD, AddrMode::MR_R, RegType::HL, RegType::E}},
    {0x74, {InstType::LD, AddrMode::MR_R, RegType::HL, RegType::H}},
    {0x75, {InstType::LD, AddrMode::MR_R, RegType::HL, RegType::L}},
    {0x76, {InstType::HALT}},
    {0x77, {InstType::LD, AddrMode::R_R, RegType::H, RegType::A}},
    {0x78, {InstType::LD, AddrMode::R_R, RegType::A, RegType::B}},
    {0x79, {InstType::LD, AddrMode::R_R, RegType::A, RegType::C}},
    {0x7A, {InstType::LD, AddrMode::R_R, RegType::A, RegType::D}},
    {0x7B, {InstType::LD, AddrMode::R_R, RegType::A, RegType::E}},
    {0x7C, {InstType::LD, AddrMode::R_R, RegType::A, RegType::H}},
    {0x7D, {InstType::LD, AddrMode::R_R, RegType::A, RegType::L}},
    {0x7E, {InstType::LD, AddrMode::R_MR, RegType::A, RegType::HL}},
    {0x7F, {InstType::LD, AddrMode::R_R, RegType::A, RegType::A}},

    {0x80, {InstType::ADD, AddrMode::R_R, RegType::A, RegType::B}},
    {0x81, {InstType::ADD, AddrMode::R_R, RegType::A, RegType::C}},
    {0x82, {InstType::ADD, AddrMode::R_R, RegType::A, RegType::D}},
    {0x83, {InstType::ADD, AddrMode::R_R, RegType::A, RegType::E}},
    {0x84, {InstType::ADD, AddrMode::R_R, RegType::A, RegType::H}},
    {0x85, {InstType::ADD, AddrMode::R_R, RegType::A, RegType::L}},
    {0x86, {InstType::ADD, AddrMode::R_MR, RegType::A, RegType::HL}},
    {0x87, {InstType::ADD, AddrMode::R_R, RegType::A, RegType::A}},
    {0x88, {InstType::ADC, AddrMode::R_R, RegType::A, RegType::B}},
    {0x89, {InstType::ADC, AddrMode::R_R, RegType::A, RegType::C}},
    {0x8A, {InstType::ADC, AddrMode::R_R, RegType::A, RegType::D}},
    {0x8B, {InstType::ADC, AddrMode::R_R, RegType::A, RegType::E}},
    {0x8C, {InstType::ADC, AddrMode::R_R, RegType::A, RegType::H}},
    {0x8D, {InstType::ADC, AddrMode::R_R, RegType::A, RegType::L}},
    {0x8E, {InstType::ADC, AddrMode::R_MR, RegType::A, RegType::HL}},
    {0x8F, {InstType::ADC, AddrMode::R_R, RegType::A, RegType::A}},

    {0x90, {InstType::SUB, AddrMode::R_R, RegType::A, RegType::B}},
    {0x91, {InstType::SUB, AddrMode::R_R, RegType::A, RegType::C}},
    {0x92, {InstType::SUB, AddrMode::R_R, RegType::A, RegType::D}},
    {0x93, {InstType::SUB, AddrMode::R_R, RegType::A, RegType::E}},
    {0x94, {InstType::SUB, AddrMode::R_R, RegType::A, RegType::H}},
    {0x95, {InstType::SUB, AddrMode::R_R, RegType::A, RegType::L}},
    {0x96, {InstType::SUB, AddrMode::R_MR, RegType::A, RegType::HL}},
    {0x97, {InstType::SUB, AddrMode::R_R, RegType::A, RegType::A}},
    {0x98, {InstType::SBC, AddrMode::R_R, RegType::A, RegType::B}},
    {0x99, {InstType::SBC, AddrMode::R_R, RegType::A, RegType::C}},
    {0x9A, {InstType::SBC, AddrMode::R_R, RegType::A, RegType::D}},
    {0x9B, {InstType::SBC, AddrMode::R_R, RegType::A, RegType::E}},
    {0x9C, {InstType::SBC, AddrMode::R_R, RegType::A, RegType::H}},
    {0x9D, {InstType::SBC, AddrMode::R_R, RegType::A, RegType::L}},
    {0x9E, {InstType::SBC, AddrMode::R_MR, RegType::A, RegType::HL}},
    {0x9F, {InstType::SBC, AddrMode::R_R, RegType::A, RegType::A}},

    {0xA0, {InstType::AND, AddrMode::R_R, RegType::A, RegType::B}},
    {0xA1, {InstType::AND, AddrMode::R_R, RegType::A, RegType::C}},
    {0xA2, {InstType::AND, AddrMode::R_R, RegType::A, RegType::D}},
    {0xA3, {InstType::AND, AddrMode::R_R, RegType::A, RegType::E}},
    {0xA4, {InstType::AND, AddrMode::R_R, RegType::A, RegType::H}},
    {0xA5, {InstType::AND, AddrMode::R_R, RegType::A, RegType::L}},
    {0xA6, {InstType::AND, AddrMode::R_MR, RegType::A, RegType::HL}},
    {0xA7, {InstType::AND, AddrMode::R_R, RegType::A, RegType::A}},
    {0xA8, {InstType::XOR, AddrMode::R_R, RegType::A, RegType::B}},
    {0xA9, {InstType::XOR, AddrMode::R_R, RegType::A, RegType::C}},
    {0xAA, {InstType::XOR, AddrMode::R_R, RegType::A, RegType::D}},
    {0xAB, {InstType::XOR, AddrMode::R_R, RegType::A, RegType::E}},
    {0xAC, {InstType::XOR, AddrMode::R_R, RegType::A, RegType::H}},
    {0xAD, {InstType::XOR, AddrMode::R_R, RegType::A, RegType::L}},
    {0xAE, {InstType::XOR, AddrMode::R_MR, RegType::A, RegType::HL}},
    {0xAF, {InstType::XOR, AddrMode::R_R, RegType::A, RegType::A}},

    {0xB0, {InstType::OR, AddrMode::R_R, RegType::A, RegType::B}},
    {0xB1, {InstType::OR, AddrMode::R_R, RegType::A, RegType::C}},
    {0xB2, {InstType::OR, AddrMode::R_R, RegType::A, RegType::D}},
    {0xB3, {InstType::OR, AddrMode::R_R, RegType::A, RegType::E}},
    {0xB4, {InstType::OR, AddrMode::R_R, RegType::A, RegType::H}},
    {0xB5, {InstType::OR, AddrMode::R_R, RegType::A, RegType::L}},
    {0xB6, {InstType::OR, AddrMode::R_MR, RegType::A, RegType::HL}},
    {0xB7, {InstType::OR, AddrMode::R_R, RegType::A, RegType::A}},
    {0xB8, {InstType::CP, AddrMode::R_R, RegType::A, RegType::B}},
    {0xB9, {InstType::CP, AddrMode::R_R, RegType::A, RegType::C}},
    {0xBA, {InstType::CP, AddrMode::R_R, RegType::A, RegType::D}},
    {0xBB, {InstType::CP, AddrMode::R_R, RegType::A, RegType::E}},
    {0xBC, {InstType::CP, AddrMode::R_R, RegType::A, RegType::H}},
    {0xBD, {InstType::CP, AddrMode::R_R, RegType::A, RegType::L}},
    {0xBE, {InstType::CP, AddrMode::R_MR, RegType::A, RegType::HL}},
    {0xBF, {InstType::CP, AddrMode::R_R, RegType::A, RegType::A}},

    {0xC0, {InstType::RET, AddrMode::IMP, RegType::NONE, RegType::NONE, CondType::NZ}},
    {0xC1, {InstType::POP, AddrMode::IMP, RegType::BC}},
    {0xC2, {InstType::JP, AddrMode::D16, RegType::NONE, RegType::NONE, CondType::NZ}},
    {0xC3, {InstType::JP, AddrMode::D16}},
    {0xC4, {InstType::CALL, AddrMode::D16, RegType::NONE, RegType::NONE, CondType::NZ}},
    {0xC5, {InstType::PUSH, AddrMode::IMP, RegType::BC}},
    {0xC6, {InstType::ADD, AddrMode::R_A8, RegType::A}},
    {0xC7, {InstType::RST, AddrMode::IMP, RegType::NONE, RegType::NONE, CondType::NONE, 0x00}},
    {0xC8, {InstType::RET, AddrMode::IMP, RegType::NONE, RegType::NONE, CondType::Z}},
    {0xC9, {InstType::RET, AddrMode::IMP}},
    {0xCA, {InstType::JP, AddrMode::D16, RegType::NONE, RegType::NONE, CondType::Z}},
    {0xCB, {InstType::CB, AddrMode::D8}},
    {0xCC, {InstType::CALL, AddrMode::D16, RegType::NONE, RegType::NONE, CondType::Z}},
    {0xCD, {InstType::CALL, AddrMode::D16}},
    {0xCE, {InstType::ADC, AddrMode::R_D8, RegType::A}},
    {0xCF, {InstType::RST, AddrMode::IMP, RegType::NONE, RegType::NONE, CondType::NONE, 0x08}},

    {0xD0, {InstType::RET, AddrMode::IMP, RegType::NONE, RegType::NONE, CondType::NC}},
    {0xD1, {InstType::POP, AddrMode::IMP, RegType::DE}},
    {0xD2, {InstType::JP, AddrMode::D16, RegType::NONE, RegType::NONE, CondType::NC}},
    {0xD4, {InstType::CALL, AddrMode::D16, RegType::NONE, RegType::NONE, CondType::NC}},
    {0xD5, {InstType::PUSH, AddrMode::IMP, RegType::DE}},
    {0xD6, {InstType::SUB, AddrMode::D8}},
    {0xD7, {InstType::RST, AddrMode::IMP, RegType::NONE, RegType::NONE, CondType::NONE, 0x10}},
    {0xD8, {InstType::RET, AddrMode::IMP, RegType::NONE, RegType::NONE, CondType::C}},
    {0xD9, {InstType::RETI, AddrMode::IMP}},
    {0xDA, {InstType::JP, AddrMode::D16, RegType::NONE, RegType::NONE, CondType::C}},
    {0xDC, {InstType::CALL, AddrMode::D16, RegType::NONE, RegType::NONE, CondType::C}},
    {0xDE, {InstType::SBC, AddrMode::R_D8, RegType::A}},
    {0xDF, {InstType::RST, AddrMode::IMP, RegType::NONE, RegType::NONE, CondType::NONE, 0x18}},

    {0xE0, {InstType::LD, AddrMode::HA8_R, RegType::NONE, RegType::A}},
    {0xE1, {InstType::POP, AddrMode::IMP, RegType::HL}},
    {0xE2, {InstType::LD, AddrMode::MC_R, RegType::C, RegType::A}},
    {0xE5, {InstType::PUSH, AddrMode::IMP, RegType::HL}},
    {0xE6, {InstType::AND, AddrMode::D8}},
    {0xE7, {InstType::RST, AddrMode::IMP, RegType::NONE, RegType::NONE, CondType::NONE, 0x20}},
    {0xE8, {InstType::ADD, AddrMode::R_D8, RegType::SP}},
    {0xE9, {InstType::JP, AddrMode::MR, RegType::HL}},
    {0xEA, {InstType::LD, AddrMode::A16_R, RegType::NONE, RegType::A}},
    {0xEE, {InstType::XOR, AddrMode::D8}},
    {0xEF, {InstType::RST, AddrMode::IMP, RegType::NONE, RegType::NONE, CondType::NONE, 0x28}},

    {0xF0, {InstType::LD, AddrMode::R_HA8, RegType::A}},
    {0xF1, {InstType::POP, AddrMode::IMP, RegType::AF}},
    {0xF2, {InstType::LD, AddrMode::R_MC, RegType::A, RegType::C}},
    {0xF3, {InstType::DI, AddrMode::IMP}},
    {0xF5, {InstType::PUSH, AddrMode::IMP, RegType::AF}},
    {0xF6, {InstType::OR, AddrMode::D8}},
    {0xF7, {InstType::RST, AddrMode::IMP, RegType::NONE, RegType::NONE, CondType::NONE, 0x30}},
    {0xF8, {InstType::LD, AddrMode::HL_SPR, RegType::HL, RegType::SP}},
    {0xF9, {InstType::LD, AddrMode::R_R, RegType::SP, RegType::HL}},
    {0xFA, {InstType::LD, AddrMode::R_A16, RegType::A}},
    {0xFB, {InstType::EI, AddrMode::IMP}},
    {0xFE, {InstType::CP, AddrMode::D8}},
    {0xFF, {InstType::RST, AddrMode::IMP, RegType::NONE, RegType::NONE, CondType::NONE, 0x38}}
};

Instruction getInstructionByOpCode(uint8_t opCode) {
    try {
        return INSTRCUTION_SET.at(opCode);
    } catch(...) {
        std::cerr << "Invalid opCode: " << std::hex << (int)opCode << "!\n";
        exit(-7);
    }
}

}

// CPURegister.cpp

#pragma once
#include "Common.hpp"
#include "Instruction.hpp"
#include "CPURegister.hpp"

namespace GBCEmu {
    void CPURegister::setFlags(int z, int n, int h, int c)
    {
        if (z != -1) {
            std::cout << "set z = " << z << "!!!\n";
            setBit(f_, 7, z);
        }
        if (n != -1) {
            setBit(f_, 6, n);
        }
        if (h != -1) {
            setBit(f_, 5, h);
        }
        if (c != -1) {
            setBit(f_, 4, c);
        }
    }

    uint8_t CPURegister::getZFlag()
    {
        return getBit(f_, 7);
    }
    uint8_t CPURegister::getCFlag()
    {
        return getBit(f_, 4);
    }
    uint8_t CPURegister::getHFlag()
    {
        return getBit(f_, 5);
    }
    uint8_t CPURegister::getNFlag()
    {
        return getBit(f_, 6);
    }
    uint16_t CPURegister::readReg(RegType reg)
    {
        switch(reg) {
            case RegType::A: return a_;
            case RegType::B: return b_;
            case RegType::C: return c_;
            case RegType::D: return d_;
            case RegType::E: return e_;
            case RegType::F: return f_;
            case RegType::H: return h_;
            case RegType::L: return l_;
            case RegType::BC: return (b_ << 8) | b_;
            case RegType::DE: return (d_ << 8) | e_;
            case RegType::HL: return (h_ << 8) | l_;
            case RegType::AF: return (a_ << 8) | f_;
            case RegType::SP: return sp_;
            case RegType::PC: return pc_;
            case RegType::IE: return ie_;
        }
        throw std::out_of_range("unknow writeReg type");
    }

    void CPURegister::writeReg(RegType reg, uint16_t val)
    {
        switch(reg) {
            case RegType::A: a_ = val & 0xFF; return;
            case RegType::B: b_ = val & 0xFF; return;
            case RegType::C: c_ = val & 0xFF; return;
            case RegType::D: d_ = val & 0xFF; return;
            case RegType::E: e_ = val & 0xFF; return;
            case RegType::F: f_ = val & 0xFF; return;
            case RegType::H: h_ = val & 0xFF; return;
            case RegType::L: l_ = val & 0xFF; return;
            case RegType::BC: b_ = (val & 0xFF00) >> 8; c_ = val & 0xFF; return;
            case RegType::DE: d_ = (val & 0xFF00) >> 8; e_ = val & 0xFF; return;
            case RegType::HL: h_ = (val & 0xFF00) >> 8; l_ = val & 0xFF; return;
            case RegType::AF: a_ = (val & 0xFF00) >> 8; f_ = val & 0xFF; return;
            case RegType::SP: sp_ = val; return;
            case RegType::PC: pc_ = val; return;
            case RegType::IE: ie_ = val & 0xFF; return;
        }
        throw std::out_of_range("unknow writeReg type");
    }
};

// CPUContext.cpp

#include "CPUContext.hpp"
namespace GBCEmu {

CPUContext::CPUContext(Bus& bus, CPURegister& reg) : bus_(bus), reg_(reg) {
    PROCESSOR_[InstType::NOP] = [this]() { this->nop(); };
    PROCESSOR_[InstType::LD] = [this]() { this->ld(); };
    PROCESSOR_[InstType::ADD] = [this]() { this->add(); };
    PROCESSOR_[InstType::ADC] = [this]() { this->adc(); };
    PROCESSOR_[InstType::SUB] = [this]() { this->sub(); };
    PROCESSOR_[InstType::SBC] = [this]() { this->sbc(); };
    PROCESSOR_[InstType::AND] = [this]() { this->and(); };
    PROCESSOR_[InstType::XOR] = [this]() { this->xor(); };
    PROCESSOR_[InstType::OR] = [this]() { this->or(); };
    PROCESSOR_[InstType::CP] = [this]() { this->cp(); };
    PROCESSOR_[InstType::CB] = [this]() { this->cb(); };
    PROCESSOR_[InstType::INC] = [this]() { this->inc(); };
    PROCESSOR_[InstType::DEC] = [this]() { this->dec(); };
    PROCESSOR_[InstType::EI] = [this]() { this->ei(); };
    PROCESSOR_[InstType::DI] = [this]() { this->di(); };
    PROCESSOR_[InstType::JP] = [this]() { this->jp(); };
    PROCESSOR_[InstType::RET] = [this]() { this->ret(); };
    PROCESSOR_[InstType::RETI] = [this]() { this->reti(); };
    PROCESSOR_[InstType::CALL] = [this]() { this->call(); };
    PROCESSOR_[InstType::RST] = [this]() { this->rst(); };
    PROCESSOR_[InstType::JR] = [this]() { this->jr(); };
    PROCESSOR_[InstType::XOR] = [this]() { this->xor(); };
    PROCESSOR_[InstType::POP] = [this]() { this->pop(); };
    PROCESSOR_[InstType::PUSH] = [this]() { this->push(); };
    PROCESSOR_[InstType::RRCA] = [this]() { this->rrca(); };
    PROCESSOR_[InstType::RLCA] = [this]() { this->rlca(); };
    PROCESSOR_[InstType::RRA] = [this]() { this->rra(); };
    PROCESSOR_[InstType::RLA] = [this]() { this->rla(); };
    PROCESSOR_[InstType::STOP] = [this]() { this->stop(); };
    PROCESSOR_[InstType::DAA] = [this]() { this->daa(); };
    PROCESSOR_[InstType::CPL] = [this]() { this->cpl(); };
    PROCESSOR_[InstType::SCF] = [this]() { this->scf(); };
    PROCESSOR_[InstType::CCF] = [this]() { this->ccf(); };
    PROCESSOR_[InstType::HALT] = [this]() { this->halt(); };
};


// 根据寻址模式准备好数据
bool CPUContext::checkCond()
{
    bool z = reg_.getZFlag();
    bool c = reg_.getCFlag();
    std::cout << "zflag!"  << z << std::endl;
    switch (curInst_.cond) {
        case CondType::NONE: return true;
        case CondType::C: return c;
        case CondType::NC: return !c;
        case CondType::Z: return z;
        case CondType::NZ: return !z;
    }

    return false;
}

void CPUContext::nop()
{
    return;
}
void CPUContext::ld()
{
    if (writeToMemo_) {
        if (is16bitReg(curInst_.reg2)) {
            bus_.write16(memoDest_, fetchedData_);
        } else {
            bus_.write(memoDest_, fetchedData_);
        }
        writeToMemo_ = false;
        return;
    }

    if (curInst_.mode == AddrMode::HL_SPR) {
        uint8_t hFlag = (reg_.readReg(curInst_.reg1) & 0xF) +
            (reg_.readReg(curInst_.reg2) & 0xF) >= 0x10;
        uint8_t cFlag = (reg_.readReg(curInst_.reg1) & 0xFF) +
            (reg_.readReg(curInst_.reg2) & 0xFF) >= 0x100;
        reg_.setFlags(0, 0, hFlag, cFlag);
        reg_.writeReg(curInst_.reg1, reg_.readReg(curInst_.reg2) +
            static_cast<int8_t>(fetchedData_));
        return;
    }
    reg_.writeReg(curInst_.reg1, fetchedData_);
}

void CPUContext::inc()
{
    if (is16bitReg(curInst_.reg1)) {
        // ... emu
    }
    uint16_t val = reg_.readReg(curInst_.reg1) + 1;
    if (writeToMemo_) {
        val = (bus_.read(fetchedData_) & 0xFF) + 1;
        bus_.write(fetchedData_, val);
    } else {
        reg_.writeReg(curInst_.reg1, val);
    }

    if ((curOpcode_ & 0x03) == 0x03) {
        return;
    }

    reg_.setFlags(val == 0, 0, (val & 0x0F) == 0, -1);
}

void CPUContext::dec()
{
    if (is16bitReg(curInst_.reg1)) {
        // ... emu
    }
    uint16_t val = reg_.readReg(curInst_.reg1) - 1;
    if (writeToMemo_) {
        val = (bus_.read(fetchedData_) & 0xFF) - 1;
        bus_.write(fetchedData_, val);
    } else {
        reg_.writeReg(curInst_.reg1, val);
    }

    if ((curOpcode_ & 0x0B) == 0x0B) {
        return;
    }
    std::cout << "dec set flag! val=" << val << std::endl;
    reg_.setFlags(val == 0, 1, (val & 0x0F) == 0x0F, -1);
}

uint8_t CPUContext::stackPop()
{
    return bus_.read(reg_.sp_++);
}

uint16_t CPUContext::stackPop16()
{
    uint16_t lo;
    lo = stackPop();
    uint16_t hi;
    hi = stackPop();
    return (hi << 8) | lo;
}

void CPUContext::stackPush(uint8_t val)
{
    bus_.write(--reg_.sp_, val);
}

void CPUContext::stackPush16(uint16_t val)
{
    stackPush((val >> 8) & 0xFF);
    stackPush(val & 0xFF);
}

void CPUContext::ei()
{
    enablingIME_ = true;
}

void CPUContext::di()
{
    interruptEnabled_ = false;
}

void CPUContext::go2(uint16_t addr, bool pushPC)
{
    if (checkCond()) {
        if (pushPC) {
            stackPush16(reg_.pc_);
        }
        reg_.pc_ = addr;
        // emu_.cycle(1);
    }
}

void CPUContext::jp()
{
    go2(fetchedData_, false);
}

void CPUContext::ret()
{
    if (curInst_.cond != CondType::NONE) {
        // emu_cycle
    }

    if (checkCond()) {
        uint16_t lo;
        lo = stackPop();
        uint16_t hi;
        hi = stackPop();
        uint16_t res = (hi << 8) | lo;
        reg_.pc_ = res;
    }
}

void CPUContext::reti()
{
    interruptEnabled_ = true;
    ret();
}

void CPUContext::call()
{
    go2(fetchedData_, true);
}

void CPUContext::rst()
{
    go2(curInst_.param, true);
}

void CPUContext::jr()
{
    int8_t rel = static_cast<int8_t>(fetchedData_ & 0xFF);
    uint16_t addr = reg_.pc_ + rel;
    go2(addr, false);
}

void CPUContext::pop()
{
    uint16_t lo;
    lo = stackPop();
    uint16_t hi;
    hi = stackPop();
    uint16_t res = (hi << 8) | lo;
    reg_.writeReg(curInst_.reg1,
        res & (curInst_.reg1 == RegType::AF ? 0xFFF0 : 0xFFFF));
}

void CPUContext::push()
{
    uint16_t hi;
    hi = (reg_.readReg(curInst_.reg1) >> 8) & 0xFF;
    stackPush(hi);
    uint16_t lo;
    lo = reg_.readReg(curInst_.reg1) & 0xFF;
    stackPush(lo);
}

void CPUContext::add()
{
    uint16_t val = reg_.readReg(curInst_.reg1) + fetchedData_;
    bool is16bit = is16bitReg(curInst_.reg1);
    if (is16bit) {
        // emu...
    }

    if (curInst_.reg1 == RegType::SP) {
        val = reg_.readReg(curInst_.reg1) + static_cast<int8_t>(fetchedData_);
    }

    int z = (val & 0xFF) == 0;
    int h = ((reg_.readReg(curInst_.reg1) & 0xF) + (fetchedData_ & 0xF)) >= 0x10;
    int c = (static_cast<int>(reg_.readReg(curInst_.reg1) & 0xFF) + static_cast<int>(fetchedData_ & 0xFF)) >= 0x100;
    if (is16bit) {
        z = -1;
        h = ((reg_.readReg(curInst_.reg1) & 0xFFF) + (static_cast<int8_t>(fetchedData_) & 0xFFF)) >= 0x1000;
        c = (static_cast<uint32_t>(reg_.readReg(curInst_.reg1) & 0xFFFF) + static_cast<uint32_t>(fetchedData_ & 0xFFFF)) >= 0x10000;
    }

    if (curInst_.reg1 == RegType::SP) {
        z = 0;
        h = ((reg_.readReg(curInst_.reg1) & 0xF) + (static_cast<int8_t>(fetchedData_) & 0xF)) >= 0x10;
        c = (static_cast<uint16_t>(reg_.readReg(curInst_.reg1) & 0xFF) + static_cast<uint16_t>(fetchedData_ & 0xFF)) >= 0x100;
    }

    reg_.writeReg(curInst_.reg1, val & 0xFFFF);
    reg_.setFlags(z, 0, h, c);
}

void GBCEmu::CPUContext::sub()
{
    uint16_t val = reg_.readReg(curInst_.reg1) - fetchedData_;

    int z = val == 0;
    int h = ((static_cast<int>(reg_.readReg(curInst_.reg1)) & 0xF) - (static_cast<int>(fetchedData_) & 0xF)) < 0;
    int c = (static_cast<int>(reg_.readReg(curInst_.reg1)) - static_cast<int>(fetchedData_)) < 0;

    reg_.writeReg(curInst_.reg1, val);
    reg_.setFlags(z, 1, h, c);
}

void GBCEmu::CPUContext::sbc()
{
    uint8_t val = fetchedData_ + reg_.getCFlag();

    int z = (reg_.readReg(curInst_.reg1) - val) == 0;
    int h = ((static_cast<int>(reg_.readReg(curInst_.reg1)) & 0xF) - (static_cast<int>(fetchedData_) & 0xF) - (static_cast<int>(reg_.getCFlag()))) < 0;
    int c = (static_cast<int>(reg_.readReg(curInst_.reg1)) - static_cast<int>(fetchedData_)) - reg_.getCFlag() < 0;

    reg_.writeReg(curInst_.reg1, (reg_.readReg(curInst_.reg1) - val));
    reg_.setFlags(z, 1, h, c);
}

void GBCEmu::CPUContext::adc()
{
    uint16_t u = fetchedData_;
    uint16_t a = reg_.a_;
    uint16_t c = reg_.getCFlag();

    reg_.a_ = (a + u + c) & 0xFF;
    reg_.setFlags(a == 0, 0, (a & 0xF) + (u & 0xF) + c > 0xF, a + u + c > 0xFF);
}

void CPUContext::and()
{
    reg_.a_ &= fetchedData_;
    reg_.setFlags(reg_.a_ == 0, 0, 1, 0);
}

void CPUContext::xor()
{
    reg_.a_ ^= fetchedData_ & 0xFF;
    reg_.setFlags(reg_.a_ == 0, 0, 0, 0);
}

void CPUContext::or()
{
    reg_.a_ |= fetchedData_ & 0xFF;
    reg_.setFlags(reg_.a_ == 0, 0, 0, 0);
}

void CPUContext::cp()
{
    int n = static_cast<int>(reg_.a_) - static_cast<int>(fetchedData_);
    std::cout << "n: " << n << "\n"; 
    reg_.setFlags(n == 0, 1, (static_cast<int>(reg_.a_) & 0x0F) - (static_cast<int>(fetchedData_) & 0x0F), n < 0);
}

const RegType regTable[8] = {
    RegType::B,
    RegType::C,
    RegType::D,
    RegType::E,
    RegType::H,
    RegType::L,
    RegType::HL,
    RegType::A,
};

RegType CPUContext::decodeReg(uint8_t reg)
{
    return regTable[reg];
}

void CPUContext::cb()
{
    uint8_t opcode = fetchedData_;
    RegType reg = decodeReg(opcode & 0b111);
    uint8_t bit = (opcode >> 3) & 0b111;
    uint8_t bitOp = (opcode >> 6) & 0b111;
    uint8_t regVal = reg_.readReg(reg);

    switch (bitOp) {
        case 1: // BIT
            reg_.setFlags(getBit(regVal, bit) == 0, 0, 1, -1);
            return;
        case 2: // RST
            reg_.writeReg(reg, regVal & ~(1 << bit));
            return;
        case 3: // SET
            reg_.writeReg(reg, regVal | (1 << bit));
            return;
    }

    bool flagC = reg_.getCFlag();
    switch (bitOp) {
        case 0: {// RLC
            uint8_t carry = getBit(regVal, 7);
            uint8_t res = (regVal << 1) | carry & 0xFF;
            reg_.writeReg(reg, res);
            reg_.setFlags(res == 0, 1, -1, carry);
            return;
            }
        case 1: {// RRC
            uint8_t carry = getBit(regVal, 0);
            uint8_t res = (regVal >> 1) | (carry << 7  & 0xFF);
            reg_.writeReg(reg, res);
            reg_.setFlags(res == 0, 0, 0, carry);
            return;
            }
        case 2: {// RL
            uint8_t res = (regVal << 1) | flagC;
            reg_.writeReg(reg, res);
            reg_.setFlags(res == 0, 0, 0, !!(regVal & 0x80));
            return;
            }
        case 3: {// RR
            uint8_t res = (regVal >> 1) | (flagC << 7);
            reg_.writeReg(reg, res);
            reg_.setFlags(res == 0, 0, 0, regVal & 0x1);
            return;
            }
        case 4: {// SLA
            uint8_t res = (regVal << 1);
            reg_.writeReg(reg, res);
            reg_.setFlags(res == 0, 0, 0, !!(regVal & 0x80));
            return;
            }
        case 5: {// SRA
            uint8_t res = (static_cast<int>(regVal) >> 1);
            reg_.writeReg(reg, res);
            reg_.setFlags(res == 0, 0, 0, regVal & 0x1);
            return;}
        case 6: {// SWAP
            uint8_t res = (regVal >> 4) | ((regVal & 0xF) << 4);
            reg_.writeReg(reg, res);
            reg_.setFlags(res == 0, 0, 0, 0);
            return;
            }
        case 7: {// SRL
            uint8_t res = (regVal >> 1);
            reg_.writeReg(reg, res);
            reg_.setFlags(res == 0, 0, 0, regVal & 0x1);
            return;
            }
    }

    std::cerr << "INVALID CB\n";
    NO_IMPL
}

void CPUContext::rlca()
{
    uint8_t res = reg_.a_;
    bool cFlag = (res >> 7) & 1;
    res = (res << 1) | cFlag;
    reg_.a_ = res;
    reg_.setFlags(0, 0, 0, cFlag);
}

void CPUContext::rrca()
{
    uint8_t res = reg_.a_;
    uint8_t lsb = res & 1;
    res = (res >> 1) | (lsb << 7);
    reg_.a_ = res;
    reg_.setFlags(0, 0, 0, lsb);
}

void CPUContext::rla()
{
    uint8_t res = reg_.a_;
    bool cFlag = (res >> 7) & 1;
    res = (res << 1) | reg_.getCFlag();
    reg_.a_ = res;
    reg_.setFlags(0, 0, 0, cFlag);
}

void CPUContext::rra()
{
    uint8_t res = reg_.a_;
    bool cFlag = res & 1;
    res = (res >> 1) | (reg_.getCFlag() << 7);
    reg_.a_ = res;
    reg_.setFlags(0, 0, 0, cFlag);
}

void CPUContext::stop()
{
    std::cerr << "STOP INSTRUCTION!\n";
    exit(0);
}

void CPUContext::daa()
{
    uint8_t res = 0;
    int cFlag = 0;

    if (reg_.getHFlag() || (!reg_.getNFlag() && (reg_.a_ & 0xF) > 9)) {
        res = 6;
    }
    if (reg_.getCFlag() || (!reg_.getNFlag() && reg_.a_ > 0x99)) {
        res |= 0x60;
        cFlag = 1;
    }

    reg_.a_ += reg_.getNFlag() ? -res : res;
    reg_.setFlags(reg_.a_ == 0, -1, 0, cFlag);
}

void CPUContext::cpl()
{
    reg_.a_ = ~reg_.a_;
    reg_.setFlags(-1, 1, 1, -1);
}

void CPUContext::scf()
{
    reg_.setFlags(-1, 0, 0, -1);
}

void CPUContext::ccf()
{
    reg_.setFlags(-1, 0, 0, ~reg_.getCFlag());
}

void CPUContext::halt()
{
    halt_ = true;
}

void CPUContext::process()
{
    auto it = PROCESSOR_.find(curInst_.type);
    if(it != PROCESSOR_.end()) {
        (it->second)();
        return;
    }
    throw std::runtime_error("failed to find processor of instType:" + static_cast<int>(curInst_.type));
}

void CPUContext::fetchData()
{
    FUNC_TRACE("CPU::fetchData");
    uint16_t low, high;
    switch(curInst_.mode) {
        case AddrMode::IMP: return;
        case AddrMode::R:
            fetchedData_ = reg_.readReg(curInst_.reg1);
            return;
        case AddrMode::R_R:
            fetchedData_ = reg_.readReg(curInst_.reg2);
            return;
        case AddrMode::MR_R:
            fetchedData_ = reg_.readReg(curInst_.reg2);
            memoDest_ = bus_.read(reg_.readReg(curInst_.reg1));
            writeToMemo_ = true;
            return;
        case AddrMode::MR:
            memoDest_ = reg_.readReg(curInst_.reg1);
            writeToMemo_ = true;
            fetchedData_ = reg_.readReg(curInst_.reg1);
            return;
        case AddrMode::D8:
            fetchedData_ = bus_.read(reg_.pc_);
            ++reg_.pc_;
            return;
        case AddrMode::MR_D8:
            fetchedData_ = bus_.read(reg_.pc_);
            ++reg_.pc_;
            memoDest_ = reg_.readReg(curInst_.reg1);
            writeToMemo_ = true;
            return;
        case AddrMode::MC_R:
            fetchedData_ = reg_.readReg(curInst_.reg2);
            memoDest_ = reg_.readReg(RegType::C) | 0xFF00;
            writeToMemo_ = true;
            return;
        case AddrMode::R_MC:
            fetchedData_ = bus_.read(reg_.readReg(RegType::C) | 0xFF00);
            return;
        case AddrMode::R_HLI:
            fetchedData_ = bus_.read(reg_.readReg(RegType::HL));
            reg_.writeReg(RegType::HL, reg_.readReg(RegType::HL) + 1);
            return;
        case AddrMode::R_HLD:
            fetchedData_ = bus_.read(reg_.readReg(RegType::HL));
            reg_.writeReg(RegType::HL, reg_.readReg(RegType::HL) - 1);
            return;
        case AddrMode::HLI_R:
            fetchedData_ = reg_.readReg(curInst_.reg2);
            memoDest_ = reg_.readReg(RegType::HL);
            writeToMemo_ = true;
            reg_.writeReg(RegType::HL,reg_.readReg(RegType::HL) + 1);
            return;
        case AddrMode::HLD_R:
            fetchedData_ = reg_.readReg(curInst_.reg2);
            memoDest_ = reg_.readReg(RegType::HL);
            std::cout << "memodest:" << memoDest_ << "\n";
            writeToMemo_ = true;
            reg_.writeReg(RegType::HL, reg_.readReg(RegType::HL) - 1);
            return;
        case AddrMode::R_D8:
            fetchedData_ = bus_.read(reg_.pc_);
            // emu_.cycle(1);
            ++reg_.pc_;
            return;
        case AddrMode::R_A8:
            fetchedData_ = bus_.read(bus_.read(reg_.pc_));
            // emu_.cycle(1);
            ++reg_.pc_;
            return;
        case AddrMode::A8_R:
            memoDest_ = bus_.read(reg_.pc_);
            // fetchedData_ = reg_.readReg(curInst_.reg2);
            writeToMemo_ = true;
            // emu_.cycle(1);
            ++reg_.pc_;
            return;
        case AddrMode::R_HA8:
            fetchedData_ = 0xFF00 | bus_.read(bus_.read(reg_.pc_));
            // emu_.cycle(1);
            ++reg_.pc_;
            return;
        case AddrMode::HA8_R:
            memoDest_ = 0xFF00 | bus_.read(reg_.pc_);
            fetchedData_ = reg_.readReg(curInst_.reg2);
            writeToMemo_ = true;
            // emu_.cycle(1);
            ++reg_.pc_;
            return;
        case AddrMode::A16_R:
            low = bus_.read(reg_.pc_);
            // emu_.cycle(1);
            high = bus_.read(reg_.pc_ + 1);
            // emu_.cycle(1);
            memoDest_ = low | (high << 8);
            writeToMemo_ = true;
            fetchedData_ = reg_.readReg(curInst_.reg2);
            reg_.pc_ += 2;
            return;
        case AddrMode::R_A16:
            low = bus_.read(reg_.pc_);
            // emu_.cycle(1);
            high = bus_.read(reg_.pc_ + 1);
            // emu_.cycle(1);
            fetchedData_ = bus_.read(low | (high << 8));
            reg_.pc_ += 2;
            return;
        case AddrMode::R_D16:
        case AddrMode::D16:
            low = bus_.read(reg_.pc_);
            // emu_.cycle(1);
            high = bus_.read(reg_.pc_ + 1);
            // emu_.cycle(1);
            fetchedData_ = low | (high << 8);
            reg_.pc_ += 2;
            return;
        default:
            std::cout << "UNKNOWN ADDRESSING MODE \n";
            exit(-6);
    }
}
}