Spider VM · Instruction Set Implementation · 2026

Implementing
Spider VM Instructions

Cast conversions, trigonometric and exponential functions for the Spider Virtual Machine — opcodes 0x068 through 0x079.

Diego Alberto López  ·  spider-runtime  ·  April 2026

Context background

The Spider VM instruction set is organized in a 9-bit opcode space (512 slots), divided among team members. My assigned range covers 15 instructions: two type cast conversions and thirteen math functions.

Instructions are defined in Instr_060-07F.cpp, which already contained the previous range (0x060–0x067) implemented by another team member. My work begins at 0x068.

Assigned Instructions 0x068 → 0x079

Cast Conversions
0x068
D2I
Double (f64) → Integer (i32), truncates toward zero
0x069
D2L
Double (f64) → Long (i64), truncates toward zero
Trigonometric
0x06C
SIN
Sine — sin(Dst) → Dst
0x06D
COS
Cosine — cos(Dst) → Dst
0x06E
TAN
Tangent — tan(Dst) → Dst
0x06F
ASIN
Arc sine — asin(Dst) → Dst
0x070
ACOS
Arc cosine — acos(Dst) → Dst
0x071
ATAN
Arc tangent — atan(Dst) → Dst
0x072
ATAN2
Arc tangent 2-argument — atan2(Dst, Src) → Dst
Exponential
0x074
EXP
Natural exponential — eˣ → Dst
0x075
LOG
Natural logarithm — ln(Dst) → Dst
0x076
LOGAB
Logarithm base A of B — log_Src(Dst) → Dst
0x077
POW
Power — Dst^Src → Dst
0x078
SQRT
Square root — √Dst → Dst
0x079
ROOT
General root — Dst^(1/Src) → Dst

Implementation Pattern how it works

Every instruction in the Spider VM follows the same three-step pattern: fetch the operand(s), perform the operation, and call the post-execution hook.

Single-operand pattern
fetchOperDst();           // points _dst to the destination register
_dst->_f64 = std::sin(_dst->_f64);
(this->*_post)();          // post-execution hook (write-back if needed)
Two-operand pattern (ATAN2, LOGAB, POW, ROOT)
fetchOperDst();           // _dst ← destination
fetchOperSrc();           // _src ← source
_dst->_f64 = std::atan2(_dst->_f64, _src->_f64);
(this->*_post)();

The register_t union allows each register to be read as any type (_f64, _u32, _u64, etc.) without casting overhead. The type modifier in the instruction header determines which field is active.

Notable special cases:

LOGAB uses the change-of-base formula: loga(b) = ln(b) / ln(a), where Dst is b and Src is a.

ROOT uses the identity: ⁿ√x = x^(1/n), implemented as std::pow(dst, 1.0 / src).

The full implementation in C++20:

void CPU::D2I() {
    fetchOperDst();
    _dst->_u32 = static_cast<u32>(_dst->_f64);
    (this->*_post)();
}

void CPU::SIN() {
    fetchOperDst();
    _dst->_f64 = std::sin(_dst->_f64);
    (this->*_post)();
}

void CPU::LOGAB() {
    fetchOperDst();
    fetchOperSrc();
    _dst->_f64 = std::log(_dst->_f64) / std::log(_src->_f64);
    (this->*_post)();
}

void CPU::ROOT() {
    fetchOperDst();
    fetchOperSrc();
    _dst->_f64 = std::pow(_dst->_f64, 1.0 / _src->_f64);
    (this->*_post)();
}

Verification test results

A test program was written to call each instruction directly on the CPU and verify the output against mathematically known values. Since fetchInstr() and execute() are not yet implemented in the Runtime, operands are set manually before each call.

-- Cast Instructions -- [PASS] D2I (3.9 -> 3) = 3 (expected 3)
[PASS] D2L (1e12) = 1e+12 (expected 1e+12) -- Trigonometric Instructions -- [PASS] SIN(pi/2) = 1 (expected 1)
[PASS] COS(0) = 1 (expected 1)
[PASS] TAN(pi/4) = 1 (expected 1)
[PASS] ASIN(1.0) = 1.5708 (expected 1.5708)
[PASS] ACOS(1.0) = 0 (expected 0)
[PASS] ATAN(1.0) = 0.785398 (expected 0.785398)
[PASS] ATAN2(1,1) = 0.785398 (expected 0.785398) -- Exponential Instructions -- [PASS] EXP(1) = 2.71828 (expected 2.71828)
[PASS] LOG(e) = 1 (expected 1)
[PASS] LOGAB(100,10) = 2 (expected 2)
[PASS] POW(2,10) = 1024 (expected 1024)
[PASS] SQRT(9) = 3 (expected 3)
[PASS] ROOT(27,3) = 3 (expected 3)
Note on testing approach: The test program uses stub implementations of fetchOperDst(), fetchOperSrc(), and imp() as no-ops, and sets _dst and _src manually. This isolates the instruction logic completely from the unimplemented CPU dispatch system.