From 429596af861823eaf460f7abd8cfb436a85b2a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20De=20Gante=20P=C3=A9rez?= Date: Mon, 6 Apr 2026 12:33:43 -0600 Subject: [PATCH 1/3] Implement instructions 0x03C-0x053, add flag constants and fix execute dispatch --- src/spider/runtime/Runtime.cpp | 4 +- src/spider/runtime/cpu/CPU.cpp | 6 +- src/spider/runtime/cpu/CPU.hpp | 8 + src/spider/runtime/instr/Instr_020-03F.cpp | 63 ++++++- src/spider/runtime/instr/Instr_040-05F.cpp | 185 +++++++++++++++++++-- 5 files changed, 244 insertions(+), 22 deletions(-) diff --git a/src/spider/runtime/Runtime.cpp b/src/spider/runtime/Runtime.cpp index ddb008e..7188517 100644 --- a/src/spider/runtime/Runtime.cpp +++ b/src/spider/runtime/Runtime.cpp @@ -17,8 +17,10 @@ namespace spider { // Stepping/Running the Machine // void Runtime::step() { + // fetchInstr() decodes the opcode, addressing mode and type siz cpu.fetchInstr(); - // TODO: Call instruction + // execute() completes the fetch-decode-execute cycle by calling the correct instruction method based on the opcode. + cpu.execute(); } void Runtime::step(u64 n) { diff --git a/src/spider/runtime/cpu/CPU.cpp b/src/spider/runtime/cpu/CPU.cpp index 1a796b1..f43506d 100644 --- a/src/spider/runtime/cpu/CPU.cpp +++ b/src/spider/runtime/cpu/CPU.cpp @@ -95,8 +95,12 @@ namespace spider { _addrm++; } + /** + instrMap[] is the correct 512-entry dispatch + table that maps operation codes to instruction methods. + */ void CPU::execute() { - (this->*(CPU::addrModes[_opcode]))(); + (this->*(CPU::instrMap[_opcode]))(); } // Addressing Modes // diff --git a/src/spider/runtime/cpu/CPU.hpp b/src/spider/runtime/cpu/CPU.hpp index a2e8aa5..948ec2d 100644 --- a/src/spider/runtime/cpu/CPU.hpp +++ b/src/spider/runtime/cpu/CPU.hpp @@ -15,6 +15,14 @@ namespace spider { static constexpr const u64 FLAG_INTERRUPT_REQUEST = 0b0000000000000000000000000000000000000000000000000000000000000100; static constexpr const u64 FLAG_EXCEPTION = 0b0000000000000000000000000000000000000000000000000000000000001000; static constexpr const u64 FLAG_MEMORY_MODE = 0b0000000000000000000000000000000000000000000000000000000000110000; + static constexpr const u64 FLAG_EXT_INT_DISABLE = 0b0000000000000000000000000000000000000000000000000000000010000000; // bit 7 + static constexpr const u64 FLAG_EQUAL = 0b0000000000000000000000000000000000000000000000000000010000000000; // bit 10 + static constexpr const u64 FLAG_EPSILON_ENABLE = 0b0000000000000000000000000000000000000000000000000001000000000000; // bit 12 + static constexpr const u64 FLAG_HOTSWAP_SIGNAL = 0b0000000000000000000000000000000000000000000000010000000000000000; // bit 16 + static constexpr const u64 FLAG_USER_A = 0b0000000000000000000000000000000000000000000100000000000000000000; // bit 20 + static constexpr const u64 FLAG_USER_B = 0b0000000000000000000000000000000000000000001000000000000000000000; // bit 21 + static constexpr const u64 FLAG_USER_C = 0b0000000000000000000000000000000000000000010000000000000000000000; // bit 22 + static constexpr const u64 FLAG_USER_D = 0b0000000000000000000000000000000000000000100000000000000000000000; // bit 23 public: // Map of addressing modes & Instructions diff --git a/src/spider/runtime/instr/Instr_020-03F.cpp b/src/spider/runtime/instr/Instr_020-03F.cpp index 40166f7..3fcb420 100644 --- a/src/spider/runtime/instr/Instr_020-03F.cpp +++ b/src/spider/runtime/instr/Instr_020-03F.cpp @@ -154,20 +154,75 @@ namespace spider { // TODO: Implement JIF } + /** + * 0x03C — Jump Relative. + * Adds a signed offset (Dst) to the instruction register. + */ void CPU::JMR() { - // TODO: Implement JMR + fetchOperDst(); + i64 offset; + switch (_size) { + case 0b00: offset = static_cast(_dst->_i8); break; // 1 byte + case 0b01: offset = static_cast(_dst->_i16); break; // 2 bytes + case 0b10: offset = static_cast(_dst->_i32); break; // 4 bytes + case 0b11: offset = _dst->_i64; break; // 8 bytes + } + RI = static_cast(static_cast(RI) + offset); } + /** + * 0x03D — Jump Relative if Equal. + * Adds a signed offset (Dst) to RI only if the Equal flag (bit 10) is set. + */ void CPU::JER() { - // TODO: Implement JER + fetchOperDst(); + if (RF & CPU::FLAG_EQUAL) { + i64 offset; + switch (_size) { + case 0b00: offset = static_cast(_dst->_i8); break; + case 0b01: offset = static_cast(_dst->_i16); break; + case 0b10: offset = static_cast(_dst->_i32); break; + case 0b11: offset = _dst->_i64; break; + } + RI = static_cast(static_cast(RI) + offset); + } } + /** + * 0x03E — Jump Relative if Not Equal. + * Adds a signed offset (Dst) to RI only if the Equal flag (bit 10) is cleared. + */ void CPU::JNR() { - // TODO: Implement JNR + fetchOperDst(); + if (!(RF & CPU::FLAG_EQUAL)) { + i64 offset; + switch (_size) { + case 0b00: offset = static_cast(_dst->_i8); break; + case 0b01: offset = static_cast(_dst->_i16); break; + case 0b10: offset = static_cast(_dst->_i32); break; + case 0b11: offset = _dst->_i64; break; + } + RI = static_cast(static_cast(RI) + offset); + } } + /** + * 0x03F — Jump Relative if Src is true. + * Adds a signed offset (Dst) to RI only if Src is booleanly true (non-zero). + */ void CPU::JIR() { - // TODO: Implement JIR + fetchOperSrc(); + fetchOperDst(); + if (_src->_u64 != 0) { + i64 offset; + switch (_size) { + case 0b00: offset = static_cast(_dst->_i8); break; + case 0b01: offset = static_cast(_dst->_i16); break; + case 0b10: offset = static_cast(_dst->_i32); break; + case 0b11: offset = _dst->_i64; break; + } + RI = static_cast(static_cast(RI) + offset); + } } } diff --git a/src/spider/runtime/instr/Instr_040-05F.cpp b/src/spider/runtime/instr/Instr_040-05F.cpp index f0c8829..de96aa6 100644 --- a/src/spider/runtime/instr/Instr_040-05F.cpp +++ b/src/spider/runtime/instr/Instr_040-05F.cpp @@ -4,71 +4,224 @@ */ #include +#include namespace spider { +// ── 0x040 — SFB: Store (User) Flag Bit ───────────────────────────── + // bool(Src) -> User Flag at index (Dst & 0x3) + // Flags A-D are bits 20-23 of RF. void CPU::SFB() { - // TODO: Implement SFB + fetchOperSrc(); + fetchOperDst(); + u8 flag_idx = _dst->_u8 & 0x3; + u64 flag_bit = CPU::FLAG_USER_A << flag_idx; + if (_src->_u64 != 0) { + RF |= flag_bit; + } else { + RF &= ~flag_bit; + } } + // ── 0x041 — LFB: Load (User) Flag Bit ────────────────────────────── + // User Flag at index (Src & 0x3) -> Dst void CPU::LFB() { - // TODO: Implement LFB + fetchOperSrc(); + fetchOperDst(); + u8 flag_idx = _src->_u8 & 0x3; + u64 flag_bit = CPU::FLAG_USER_A << flag_idx; + _dst->_u64 = (RF & flag_bit) ? 1 : 0; + (this->*_post)(); } + // ── 0x042 — JUF: Jump absolute if User Flag is true ──────────────── + // Dst -> RI IF User Flag at index (Src & 0x3) is set void CPU::JUF() { - // TODO: Implement JUF + fetchOperSrc(); + fetchOperDst(); + u8 flag_idx = _src->_u8 & 0x3; + u64 flag_bit = CPU::FLAG_USER_A << flag_idx; + if (RF & flag_bit) { + RI = _dst->_u64; + } } + // ── 0x043 — JUR: Jump relative if User Flag is true ──────────────── + // Dst + RI -> RI IF User Flag at index (Src & 0x3) is set void CPU::JUR() { - // TODO: Implement JUR + fetchOperSrc(); + fetchOperDst(); + u8 flag_idx = _src->_u8 & 0x3; + u64 flag_bit = CPU::FLAG_USER_A << flag_idx; + if (RF & flag_bit) { + i64 offset; + switch (_size) { + case 0b00: offset = static_cast(_dst->_i8); break; + case 0b01: offset = static_cast(_dst->_i16); break; + case 0b10: offset = static_cast(_dst->_i32); break; + case 0b11: offset = _dst->_i64; break; + } + RI = static_cast(static_cast(RI) + offset); + } } + // ── 0x044 — PUSH: Push to stack ───────────────────────────────────── + // Dst -> RAM[RS], RS += (1 << _size) + // The stack grows upward from the bottom of memory. void CPU::PUSH() { - // TODO: Implement PUSH + fetchOperDst(); + u8 bytes = 1 << _size; + for (u8 i = 0; i < bytes; i++) { + _ram->at(RS + i) = (*_dst)[i]; + } + RS += bytes; } + // ── 0x045 — POP: Pop from stack ───────────────────────────────────── + // RS -= (1 << _size), RAM[RS] -> Dst void CPU::POP() { - // TODO: Implement POP + fetchOperDst(); + u8 bytes = 1 << _size; + RS -= bytes; + _ram->loadRegister(RS, _size, _dst); + (this->*_post)(); } + // ── 0x046 — ALLOC: Allocate to heap ───────────────────────────────── + // Stub: returns 0 (null) until proper heap management is implemented. void CPU::ALLOC() { - // TODO: Implement ALLOC + fetchOperDst(); + // TODO: Proper heap allocation with gap tracking. + _dst->_u64 = 0; + (this->*_post)(); } + // ── 0x047 — HFREE: Delete from heap ───────────────────────────────── + // Stub: no-op until proper heap management is implemented. void CPU::HFREE() { - // TODO: Implement HFREE + fetchOperDst(); + // TODO: Proper heap deallocation. } + //──────────────────────────────────────────────────────── + + // ── 0x04A — CALL: Call function at instruction index ──────────────── + // Minimal version: saves RZ and RI to the stack, + // updates the stack base, then jumps to Dst. + // The calling convention (parameter passing, caller-saved + // registers) is the compiler's responsibility. void CPU::CALL() { - // TODO: Implement CALL + fetchOperDst(); + u64 target = _dst->_u64; + + // Push old stack base (RZ) — always 8 bytes + register_t rz_save; + rz_save._u64 = RZ; + for (u8 i = 0; i < 8; i++) { + _ram->at(RS + i) = rz_save[i]; + } + RS += 8; + + // Push return address (RI) — always 8 bytes + register_t ri_save; + ri_save._u64 = RI; + for (u8 i = 0; i < 8; i++) { + _ram->at(RS + i) = ri_save[i]; + } + RS += 8; + + // New stack base is the current stack top + RZ = RS; + + // Jump to target + RI = target; } + // ── 0x04B — RET: Return from a function ───────────────────────────── + // Undoes what CALL did: restores RI and RZ from the stack. void CPU::RET() { - // TODO: Implement RET + // Wind the stack back to the current frame base + RS = RZ; + + // Pop return address + RS -= 8; + register_t ri_restore; + _ram->loadRegister(RS, 0b11, &ri_restore); + RI = ri_restore._u64; + + // Pop previous stack base + RS -= 8; + register_t rz_restore; + _ram->loadRegister(RS, 0b11, &rz_restore); + RZ = rz_restore._u64; } + // ── 0x04C — EDI: Enable/Disable External Interrupts ──────────────── + // bool(Dst) == true -> enable (clear the disable bit) + // bool(Dst) == false -> disable (set the disable bit) void CPU::EDI() { - // TODO: Implement EDI + fetchOperDst(); + if (_dst->_u64 != 0) { + RF &= ~CPU::FLAG_EXT_INT_DISABLE; + } else { + RF |= CPU::FLAG_EXT_INT_DISABLE; + } } + // ── 0x04D — SHSS: Set Hotswap Signal Bit ──────────────────────────── + // bool(Dst) -> Hotswap Signal flag (bit 16 of RF) void CPU::SHSS() { - // TODO: Implement SHSS + fetchOperDst(); + if (_dst->_u64 != 0) { + RF |= CPU::FLAG_HOTSWAP_SIGNAL; + } else { + RF &= ~CPU::FLAG_HOTSWAP_SIGNAL; + } } + //──────────────────────────────────────────────────────────────────────────────────── + + // ── 0x050 — FLI: Float Load Immediate ─────────────────────────────── + // The addressing mode already loads the raw bytes into Dst. + // _size == 0b10 for f32, 0b11 for f64. void CPU::FLI() { - // TODO: Implement FLI + fetchOperDst(); + (this->*_post)(); } + // ── 0x051 — FNEG: Float negate ────────────────────────────────────── + // -Dst -> Dst void CPU::FNEG() { - // TODO: Implement FNEG + fetchOperDst(); + switch (_size) { + case 0b10: _dst->_f32 = -_dst->_f32; break; + case 0b11: _dst->_f64 = -_dst->_f64; break; + } + (this->*_post)(); } + // ── 0x052 — FADD: Float add ───────────────────────────────────────── + // Dst + Src -> Dst void CPU::FADD() { - // TODO: Implement FADD + fetchOperSrc(); + fetchOperDst(); + switch (_size) { + case 0b10: _dst->_f32 += _src->_f32; break; + case 0b11: _dst->_f64 += _src->_f64; break; + } + (this->*_post)(); } + // ── 0x053 — FSUB: Float subtract ──────────────────────────────────── + // Dst - Src -> Dst void CPU::FSUB() { - // TODO: Implement FSUB + fetchOperSrc(); + fetchOperDst(); + switch (_size) { + case 0b10: _dst->_f32 -= _src->_f32; break; + case 0b11: _dst->_f64 -= _src->_f64; break; + } + (this->*_post)(); } void CPU::FMUL() { From 6fb7a23e5d8b97703a37e691332fb453b8c05949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20De=20Gante=20P=C3=A9rez?= Date: Mon, 6 Apr 2026 13:12:31 -0600 Subject: [PATCH 2/3] Simplify instruction comments and add default cases to switches --- src/spider/runtime/instr/Instr_020-03F.cpp | 20 ++----- src/spider/runtime/instr/Instr_040-05F.cpp | 67 ++++++---------------- 2 files changed, 22 insertions(+), 65 deletions(-) diff --git a/src/spider/runtime/instr/Instr_020-03F.cpp b/src/spider/runtime/instr/Instr_020-03F.cpp index 3fcb420..aabac35 100644 --- a/src/spider/runtime/instr/Instr_020-03F.cpp +++ b/src/spider/runtime/instr/Instr_020-03F.cpp @@ -154,10 +154,7 @@ namespace spider { // TODO: Implement JIF } - /** - * 0x03C — Jump Relative. - * Adds a signed offset (Dst) to the instruction register. - */ + // ── 0x03C — JMR: Dst + Instruction Register -> Instruction Register ── void CPU::JMR() { fetchOperDst(); i64 offset; @@ -170,10 +167,7 @@ namespace spider { RI = static_cast(static_cast(RI) + offset); } - /** - * 0x03D — Jump Relative if Equal. - * Adds a signed offset (Dst) to RI only if the Equal flag (bit 10) is set. - */ + // ── 0x03D — JER: Dst + Instruction Register -> Instruction Register IF Flags.EQ ── void CPU::JER() { fetchOperDst(); if (RF & CPU::FLAG_EQUAL) { @@ -188,10 +182,7 @@ namespace spider { } } - /** - * 0x03E — Jump Relative if Not Equal. - * Adds a signed offset (Dst) to RI only if the Equal flag (bit 10) is cleared. - */ + // ── 0x03E — JNR: Dst + Instruction Register -> Instruction Register IF NOT Flags.EQ ── void CPU::JNR() { fetchOperDst(); if (!(RF & CPU::FLAG_EQUAL)) { @@ -206,10 +197,7 @@ namespace spider { } } - /** - * 0x03F — Jump Relative if Src is true. - * Adds a signed offset (Dst) to RI only if Src is booleanly true (non-zero). - */ + // ── 0x03F — JIR: Dst + Instruction Register -> Instruction Register IF Src ── void CPU::JIR() { fetchOperSrc(); fetchOperDst(); diff --git a/src/spider/runtime/instr/Instr_040-05F.cpp b/src/spider/runtime/instr/Instr_040-05F.cpp index de96aa6..bfc53e8 100644 --- a/src/spider/runtime/instr/Instr_040-05F.cpp +++ b/src/spider/runtime/instr/Instr_040-05F.cpp @@ -8,9 +8,7 @@ namespace spider { -// ── 0x040 — SFB: Store (User) Flag Bit ───────────────────────────── - // bool(Src) -> User Flag at index (Dst & 0x3) - // Flags A-D are bits 20-23 of RF. + // ── 0x040 — SFB: Store (User) Flag Bit ────────────────────────────── void CPU::SFB() { fetchOperSrc(); fetchOperDst(); @@ -24,7 +22,6 @@ namespace spider { } // ── 0x041 — LFB: Load (User) Flag Bit ────────────────────────────── - // User Flag at index (Src & 0x3) -> Dst void CPU::LFB() { fetchOperSrc(); fetchOperDst(); @@ -34,8 +31,7 @@ namespace spider { (this->*_post)(); } - // ── 0x042 — JUF: Jump absolute if User Flag is true ──────────────── - // Dst -> RI IF User Flag at index (Src & 0x3) is set + // ── 0x042 — JUF: Jump to absolute position, if user flag is true ──── void CPU::JUF() { fetchOperSrc(); fetchOperDst(); @@ -46,8 +42,7 @@ namespace spider { } } - // ── 0x043 — JUR: Jump relative if User Flag is true ──────────────── - // Dst + RI -> RI IF User Flag at index (Src & 0x3) is set + // ── 0x043 — JUR: Jump to relative position, if user flag is true ──── void CPU::JUR() { fetchOperSrc(); fetchOperDst(); @@ -60,14 +55,13 @@ namespace spider { case 0b01: offset = static_cast(_dst->_i16); break; case 0b10: offset = static_cast(_dst->_i32); break; case 0b11: offset = _dst->_i64; break; + default: offset = 0; break; } RI = static_cast(static_cast(RI) + offset); } } - // ── 0x044 — PUSH: Push to stack ───────────────────────────────────── - // Dst -> RAM[RS], RS += (1 << _size) - // The stack grows upward from the bottom of memory. + // ── 0x044 — PUSH: Dst -> pushed into stack ────────────────────────── void CPU::PUSH() { fetchOperDst(); u8 bytes = 1 << _size; @@ -77,8 +71,7 @@ namespace spider { RS += bytes; } - // ── 0x045 — POP: Pop from stack ───────────────────────────────────── - // RS -= (1 << _size), RAM[RS] -> Dst + // ── 0x045 — POP: popped from stack -> Dst ─────────────────────────── void CPU::POP() { fetchOperDst(); u8 bytes = 1 << _size; @@ -87,8 +80,7 @@ namespace spider { (this->*_post)(); } - // ── 0x046 — ALLOC: Allocate to heap ───────────────────────────────── - // Stub: returns 0 (null) until proper heap management is implemented. + // ── 0x046 — ALLOC: Dst -> heap ptr of size Dst ────────────────────── void CPU::ALLOC() { fetchOperDst(); // TODO: Proper heap allocation with gap tracking. @@ -96,25 +88,17 @@ namespace spider { (this->*_post)(); } - // ── 0x047 — HFREE: Delete from heap ───────────────────────────────── - // Stub: no-op until proper heap management is implemented. + // ── 0x047 — HFREE: Frees heap ptr in Dst ──────────────────────────── void CPU::HFREE() { fetchOperDst(); // TODO: Proper heap deallocation. } - //──────────────────────────────────────────────────────── - - // ── 0x04A — CALL: Call function at instruction index ──────────────── - // Minimal version: saves RZ and RI to the stack, - // updates the stack base, then jumps to Dst. - // The calling convention (parameter passing, caller-saved - // registers) is the compiler's responsibility. + // ── 0x04A — CALL: Performs a function call, step XX ────────────────── void CPU::CALL() { fetchOperDst(); u64 target = _dst->_u64; - // Push old stack base (RZ) — always 8 bytes register_t rz_save; rz_save._u64 = RZ; for (u8 i = 0; i < 8; i++) { @@ -122,7 +106,6 @@ namespace spider { } RS += 8; - // Push return address (RI) — always 8 bytes register_t ri_save; ri_save._u64 = RI; for (u8 i = 0; i < 8; i++) { @@ -130,35 +113,26 @@ namespace spider { } RS += 8; - // New stack base is the current stack top RZ = RS; - - // Jump to target RI = target; } - // ── 0x04B — RET: Return from a function ───────────────────────────── - // Undoes what CALL did: restores RI and RZ from the stack. + // ── 0x04B — RET: Undoes a function call, step XX ──────────────────── void CPU::RET() { - // Wind the stack back to the current frame base RS = RZ; - // Pop return address RS -= 8; register_t ri_restore; _ram->loadRegister(RS, 0b11, &ri_restore); RI = ri_restore._u64; - // Pop previous stack base RS -= 8; register_t rz_restore; _ram->loadRegister(RS, 0b11, &rz_restore); RZ = rz_restore._u64; } - // ── 0x04C — EDI: Enable/Disable External Interrupts ──────────────── - // bool(Dst) == true -> enable (clear the disable bit) - // bool(Dst) == false -> disable (set the disable bit) + // ── 0x04C — EDI: bool( Dst ) -> Enable External Interrupts Bit ───── void CPU::EDI() { fetchOperDst(); if (_dst->_u64 != 0) { @@ -168,8 +142,7 @@ namespace spider { } } - // ── 0x04D — SHSS: Set Hotswap Signal Bit ──────────────────────────── - // bool(Dst) -> Hotswap Signal flag (bit 16 of RF) + // ── 0x04D — SHSS: bool( Dst ) -> Hot Swap Signal Bit ──────────────── void CPU::SHSS() { fetchOperDst(); if (_dst->_u64 != 0) { @@ -179,47 +152,43 @@ namespace spider { } } - //──────────────────────────────────────────────────────────────────────────────────── - // ── 0x050 — FLI: Float Load Immediate ─────────────────────────────── - // The addressing mode already loads the raw bytes into Dst. - // _size == 0b10 for f32, 0b11 for f64. void CPU::FLI() { fetchOperDst(); (this->*_post)(); } - // ── 0x051 — FNEG: Float negate ────────────────────────────────────── - // -Dst -> Dst + // ── 0x051 — FNEG: - Dst -> Dst ────────────────────────────────────── void CPU::FNEG() { fetchOperDst(); switch (_size) { case 0b10: _dst->_f32 = -_dst->_f32; break; case 0b11: _dst->_f64 = -_dst->_f64; break; + default: break; } (this->*_post)(); } - // ── 0x052 — FADD: Float add ───────────────────────────────────────── - // Dst + Src -> Dst + // ── 0x052 — FADD: Dst + Src -> Dst ────────────────────────────────── void CPU::FADD() { fetchOperSrc(); fetchOperDst(); switch (_size) { case 0b10: _dst->_f32 += _src->_f32; break; case 0b11: _dst->_f64 += _src->_f64; break; + default: break; } (this->*_post)(); } - // ── 0x053 — FSUB: Float subtract ──────────────────────────────────── - // Dst - Src -> Dst + // ── 0x053 — FSUB: Dst - Src -> Dst ────────────────────────────────── void CPU::FSUB() { fetchOperSrc(); fetchOperDst(); switch (_size) { case 0b10: _dst->_f32 -= _src->_f32; break; case 0b11: _dst->_f64 -= _src->_f64; break; + default: break; } (this->*_post)(); } From 0184ef6394eca35459606248120e60c012685cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20De=20Gante=20P=C3=A9rez?= Date: Wed, 8 Apr 2026 18:38:26 -0600 Subject: [PATCH 3/3] ADD personal DGANT easter egg instruction on 0x0F6 --- src/spider/runtime/cpu/CPU.hpp | 5 +++ src/spider/runtime/instr/InstrMap.cpp | 2 +- src/spider/runtime/instr/Instr_0E0-0FF.cpp | 41 ++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/spider/runtime/cpu/CPU.hpp b/src/spider/runtime/cpu/CPU.hpp index 948ec2d..46bb324 100644 --- a/src/spider/runtime/cpu/CPU.hpp +++ b/src/spider/runtime/cpu/CPU.hpp @@ -884,6 +884,11 @@ namespace spider { // Operation: void UPY(); + // [Easter Eggs] 0x0F6 — DGANT: "In kaaba Spider" (Yucatec Maya: My name is Spider) + // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 + // Operation: Writes "IN KAABA SPIDER" one char per GP register + void DGANT(); + // // }; diff --git a/src/spider/runtime/instr/InstrMap.cpp b/src/spider/runtime/instr/InstrMap.cpp index 6d3e5de..83305f8 100644 --- a/src/spider/runtime/instr/InstrMap.cpp +++ b/src/spider/runtime/instr/InstrMap.cpp @@ -281,7 +281,7 @@ CPU::Fn CPU::instrMap[] = { nullptr, // 0x0F3 nullptr, // 0x0F4 nullptr, // 0x0F5 - nullptr, // 0x0F6 + &CPU::DGANT, // 0x0F6 nullptr, // 0x0F7 nullptr, // 0x0F8 nullptr, // 0x0F9 diff --git a/src/spider/runtime/instr/Instr_0E0-0FF.cpp b/src/spider/runtime/instr/Instr_0E0-0FF.cpp index c305616..f043a49 100644 --- a/src/spider/runtime/instr/Instr_0E0-0FF.cpp +++ b/src/spider/runtime/instr/Instr_0E0-0FF.cpp @@ -4,6 +4,7 @@ */ #include +#include namespace spider { @@ -11,4 +12,44 @@ namespace spider { // TODO: Implement UPY } + // ── 0x0F6 — DGANT: "I'm SpiderLang" in a spider web ──────────── + void CPU::DGANT() { + const char art[] = + R"(\ | //)" + R"( \-+-// )" + R"( -- + --)" + R"( //-+-\ )" + R"(// | \)" + R"( )" + R"( I ' M )" + R"( SPIDER )" + R"( LANG )" + R"( )" + R"(\ | //)" + R"( \-+-// )" + R"(-- + -- )" + R"( /-+-\ )" + R"(/ | \ )" + R"( || )" + R"( || )" + R"( || )" + R"(\ | / )" + R"( \-+-/ )" + R"(-- + -- )" + R"( /-+-\ )" + R"(/ | \ )" + R"( || )" + R"( || )" + R"( || )" + R"(\ | / )" + R"( \-+-/ )" + R"(-- + -- )" + R"( /-+-\ )" + R"(/ | \ )" + R"( || )"; + for (u16 i = 0; i < sizeof(art) - 1; i++) { + _ram->at(i) = static_cast(art[i]); + } + } + }