#include "CPU.hpp" #include #include #include #include #if __cplusplus >= 202002L #include #endif namespace spider { CPU::CPU() : RA{}, RB{}, RC{}, RD{}, RX{}, RY{}, R0{}, R1{}, R2{}, R3{}, R4{}, R5{}, R6{}, R7{}, R8{}, R9{}, RF{}, RI{}, RS{}, RZ{}, RE{}, RN{}, RV{}, RM{}, ALU0{}, ALU1{}, _dst(nullptr), _src(nullptr), _opcode(0), _addrm(0), _size(0), _store(0), _post(&CPU::imp), _ram(nullptr), _reel(nullptr) { } CPU::~CPU() {} // Setup & Configuration // void CPU::hookRAM(RAM* ram) { this->_ram = ram; } void CPU::hookInstrReel(InstrReel* reel) { this->_reel = reel; } constexpr u64 CPU::getFlag(u64 mask) { if (!mask) return 0; #if __cplusplus >= 202002L return (RF & mask) >> std::countr_zero(mask); #elif defined(SPIDER_COMPILER_GCC_LIKE) return (RF & mask) >> __builtin_ctzll(mask); #elif defined(SPIDER_COMPILER_MSVC) return (RF & mask) >> _BitScanForward64(mask); #else // If you have reached this part, // please come up with a better alternative. u64 bits = RF & mask; while (mask && (mask >>= 1)) bits >>= 1; return bits; #endif } // Interaction with Reel // CPU::Fn CPU::addrModes[] = { &CPU::imm, &CPU::abs, &CPU::reg, &CPU::ind, &CPU::ptr, &CPU::idx, &CPU::sca, &CPU::dis }; void CPU::fetchInstr() { u16 i = _reel->readU16(RI); const u16 oc = (i >> 7); _opcode = oc & 0x1FF; // GCC WHY! _addrm = static_cast((i >> 2) & 0x1F); _size = static_cast(i & 0x3); RI += 2; } void CPU::fetchOperDst() { // Move the operand ptrs _alu = &ALU0; _opers[1] = _opers[0]; // call specific addressing mode (this->*(CPU::addrModes[_addrm]))(); } void CPU::fetchOperSrc() { // set ALU _alu = &ALU1; // call specific addressing mode (this->*(CPU::addrModes[_addrm]))(); // modify the _addrm register _addrm = static_cast((_addrm >> 3) & 0x1F); _addrm++; } void CPU::execute() { (this->*(CPU::addrModes[_opcode]))(); } // Addressing Modes // /** * Implied Addressing Mode */ void CPU::imp() { // Nothing // } /** * Immediate Addressing Mode */ void CPU::imm() { _reel->loadRegister(RI, _size, _alu); _opers[0] = _alu; _post = &CPU::imp; RI += 1 << _size; } /** * Absolute Addressing Mode */ void CPU::abs() { // Load the actual ptr into the ALU u8 mm = u8(getFlag(CPU::FLAG_MEMORY_MODE)); _reel->loadRegister(RI, mm, _alu); RI += 1 << mm; // read the memory from RAM _store = _alu->_u64; _ram->loadRegister(_store, _size, _alu); _post = &CPU::psw; } /** * Register Addressing Mode */ void CPU::reg() { // NOT FINISHED // Two consecutive registers can be declared // Shift if the top part will become .reg too u8 sh = ((_addrm & 0b11000) == 0b11000) * 4; u8 use = 1 - (sh >> 2); // (sh / 4) // get byte u8 reg = (_reel->readU8(RI) >> sh) & 0xF; _alu = &GPR[reg]; RI += use; // store no-op _post = &CPU::imp; } /** * Indrect Addressing Mode */ void CPU::ind() {} /** * Pointer Addressing Mode */ void CPU::ptr() {} /** * Indexed Addressing Mode */ void CPU::idx() {} /** * Scaled Addressing Mode */ void CPU::sca() {} /** * Displaced Addressing Mode */ void CPU::dis() {} /** * Post Write Action */ void CPU::psw() {} }