48 Commits

Author SHA1 Message Date
8cc4f59b9c add test program for instructions 0x068-0x079 2026-04-08 20:08:39 -06:00
30e0203df4 implement instructions 0x068-0x079: D2I, D2L, trig and exponential functions 2026-04-08 16:11:18 -06:00
7713be5293 feat: implement logic for BRAD instruction checksum algorithm
Implemented the memory integrity scan algorithm. Validates the first 256 bytes of system memory against a security signature.

Signed-off-by: BradleyVergara <2209213@upy.edu.mx>
2026-04-07 23:41:11 +00:00
b61cc6b149 docs: implement formal specification for BRAD memory integrity check
Added Opcode 0xF7 (BRAD) to the instruction set. This instruction performs a 256-byte memory checksum to validate system integrity against a secure MAGIC_SIGNATURE.

Signed-off-by: BradleyVergara <2209213@upy.edu.mx>
2026-04-07 23:26:52 +00:00
7155ad8d5a Finished STB, CRB and TSB instructions 2026-04-06 19:18:30 -06:00
0449074ef6 Finished BOOL, FBT, UDMD and DMOD 2026-04-06 17:56:00 -06:00
484c2a6afe Merge branch 'main' of https://git.sintekanalytics.com/SpiderLang/spider-runtime 2026-04-06 13:02:17 -06:00
6f8a9d80f2 added unfinished code to instructions 2026-04-06 13:02:12 -06:00
36889e160b Merge pull request 'arturo-fixed-files-branch' (#4) from arturo-fixed-files-branch into main
Reviewed-on: #4
2026-04-01 16:38:57 +00:00
4e1a601175 Added unfinished code to instructions 2026-03-31 11:21:35 -06:00
Arturo
f82aa627c4 Fix execute() dispatch, addrModes mask, reg() operand ptr, cast warnings, and Enter key step 2026-03-31 01:19:00 -06:00
Arturo
7d3781681d Implement float math and type conversion instructions (054-067) 2026-03-30 23:44:10 -06:00
6ac82b47e7 Added DIV, UDIV, MOD, UMOD intruction code 2026-03-30 12:54:19 -06:00
48785b6a94 Corrections to MUL and EXS functions 2026-03-30 12:19:41 -06:00
c8bfdf44b6 Merge branch 'main' of https://git.sintekanalytics.com/SpiderLang/spider-runtime 2026-03-30 12:16:22 -06:00
eba69f767e Added INC, DEC, ADD, SUB, MUL, UMUL instructions code 2026-03-30 12:16:18 -06:00
67ed4a7fc4 added signed ints to register, how was this not added before?! 2026-03-30 12:13:55 -06:00
0015387d60 ok ok it compiles. commented a lot too so check that out 2026-03-30 07:43:09 -06:00
15bf03097f Merge branch 'main' of https://git.sintekanalytics.com/SpiderLang/spider-runtime 2026-03-29 07:50:14 -06:00
43f5d26b3d I'm still working on this 2026-03-29 07:50:11 -06:00
f0148dbe45 Implemented EXS instructions 2026-03-29 02:08:56 -06:00
b397371a53 Added COM, NEG instructions 2026-03-28 13:39:53 -06:00
aabcfc6f0c Added all instructions as empty instructions. Compiles on WIN + MSYS2, UCRT64 2026-03-27 19:24:26 -06:00
41dd2b87b4 Merge branch 'main' of https://git.sintekanalytics.com/SpiderLang/spider-runtime 2026-03-27 18:59:38 -06:00
3d80b690c4 better algorithm to load bytes 2026-03-27 18:59:36 -06:00
a077c084a2 code changed 2026-03-27 16:47:50 -06:00
38006fe19a deleted document 2026-03-27 16:40:28 -06:00
6895309679 tested code 2026-03-27 16:39:29 -06:00
08e994ad44 changed code 2026-03-27 16:37:47 -06:00
2f38eb38b8 Merge branch 'main' of https://git.sintekanalytics.com/SpiderLang/spider-runtime 2026-03-27 16:36:04 -06:00
5f342991b0 deleted 2026-03-27 16:35:54 -06:00
a5ffb69565 code chnages 2026-03-27 16:34:23 -06:00
8697b44f53 Added document 2026-03-27 16:05:53 -06:00
c6c63d6391 changes to pygen 2026-03-25 10:56:26 -06:00
c6fdb59791 Merge pull request 'Add InstrMap.cpp generation to pygen' (#2) from diego/instrmap into main
Reviewed-on: #2
2026-03-25 16:34:43 +00:00
Diego De Gante Pérez
291aa0a949 Add InstrMap.cpp generation to pygen 2026-03-25 10:18:29 -06:00
e24e8dfe2d ready for addrm & instr 2026-03-25 10:00:21 -06:00
1c971a4e22 more or less almost done with the instr reels. 2026-03-25 06:59:00 -06:00
4a659b5f0d moved reel to dedicated folder because it was hogging the cpu folder 2026-03-23 22:29:05 -06:00
3a6fc6cfb9 cpu experimentation 2026-03-23 17:08:26 -06:00
d4a1d5ad94 oopsie fixes 2026-03-23 09:17:53 -06:00
da1c090f19 Preparation for building instructions 2026-03-23 07:22:00 -06:00
b4560c208f integrated quaternions into code 2026-03-21 10:08:24 -06:00
3845ebe6fd Merge branch 'main' of https://git.sintekanalytics.com/SpiderLang/spider-runtime 2026-03-21 09:49:46 -06:00
9feef38410 runtime progress 2026-03-21 09:49:42 -06:00
061b297b5c moved 2026-03-20 20:39:53 -06:00
99f423c4a3 upload 2026-03-20 20:38:12 -06:00
18923c4b20 deleted file 2026-03-20 20:28:57 -06:00
57 changed files with 5313 additions and 398 deletions

View File

@@ -1,31 +0,0 @@
#include <iostream>
template<typename T>
struct Quaternion {
T w, x, y, z;
};
template<typename T>
Quaternion<T> quat_multiply(Quaternion<T> A, Quaternion<T> B) {
return {
B.w * A.w - B.x * A.x - B.y * A.y - B.z * A.z,
B.w * A.x + B.x * A.w - B.y * A.z + B.z * A.y,
B.w * A.y + B.x * A.z + B.y * A.w - B.z * A.x,
B.w * A.z - B.x * A.y + B.y * A.x + B.z * A.w
};
}
int main() {
Quaternion<double> q1 = {1.0f, 0.0f, 0.0f, 0.0f};
Quaternion<double> q2 = {0.5f, 0.5f, 0.5f, 0.5f};
Quaternion<double> result = quat_multiply(q1, q2); // Returns the result!
std::cout << "Result: ("
<< result.w << ", "
<< result.x << ", "
<< result.y << ", "
<< result.z << ")" << std::endl;
return 0;
}

View File

@@ -16,107 +16,107 @@ constexpr u8 ADDR_MODE_MASKS[][2] = {
{ 0x1E, 0x00 }, // FIR
{ 0x1E, 0x00 }, // FZR
{ 0x1E, 0x1F }, // LSR
{ 0x00, 0x00 }, // FVR
{ 0x00, 0x00 }, // MOV
{ 0x00, 0x00 }, // MOR
{ 0x04, 0x00 }, // FVR
{ 0x1E, 0xFF }, // MOV
{ 0x04, 0x04 }, // MOR
{ 0x00, 0x00 }, // AMOV
{ 0x04, 0x04 }, // SWP
{ 0x04, 0x00 }, // AHM
{ 0x00, 0x00 }, // COM
{ 0x00, 0x00 }, // NEG
{ 0x00, 0x00 }, // EXS
{ 0x00, 0x00 }, // INC
{ 0x00, 0x00 }, // DEC
{ 0x00, 0x00 }, // ADD
{ 0x00, 0x00 }, // SUB
{ 0x00, 0x00 }, // MUL
{ 0x00, 0x00 }, // UMUL
{ 0x00, 0x00 }, // DIV
{ 0x00, 0x00 }, // UDIV
{ 0x00, 0x00 }, // MOD
{ 0x00, 0x00 }, // UMOD
{ 0x00, 0x00 }, // DMOD
{ 0x00, 0x00 }, // UDMD
{ 0x00, 0x00 }, // FBT
{ 0x00, 0x00 }, // STB
{ 0x00, 0x00 }, // CRB
{ 0x00, 0x00 }, // TSB
{ 0x00, 0x00 }, // BOOL
{ 0x00, 0x00 }, // NOT
{ 0x00, 0x00 }, // AND
{ 0x00, 0x00 }, // OR
{ 0x00, 0x00 }, // XOR
{ 0x00, 0x00 }, // SHL
{ 0x00, 0x00 }, // SHR
{ 0x00, 0x00 }, // SSR
{ 0x00, 0x00 }, // ROL
{ 0x00, 0x00 }, // ROR
{ 0x00, 0x00 }, // CNT
{ 0x00, 0x00 }, // EQ
{ 0x00, 0x00 }, // NE
{ 0x00, 0x00 }, // GT
{ 0x00, 0x00 }, // GE
{ 0x00, 0x00 }, // LT
{ 0x00, 0x00 }, // LE
{ 0x00, 0x00 }, // JMP
{ 0x00, 0x00 }, // JEQ
{ 0x00, 0x00 }, // JNE
{ 0x00, 0x00 }, // JIF
{ 0x00, 0x00 }, // JMR
{ 0x00, 0x00 }, // JER
{ 0x00, 0x00 }, // JNR
{ 0x00, 0x00 }, // JIR
{ 0x00, 0x00 }, // SFB
{ 0x00, 0x00 }, // LFB
{ 0x00, 0x00 }, // JUF
{ 0x00, 0x00 }, // JUR
{ 0x00, 0x00 }, // PUSH
{ 0x00, 0x00 }, // POP
{ 0x00, 0x00 }, // ALLOC
{ 0x00, 0x00 }, // HFREE
{ 0x00, 0x00 }, // CALL
{ 0xFF, 0x00 }, // COM
{ 0xFF, 0x00 }, // NEG
{ 0xFF, 0x00 }, // EXS
{ 0xFF, 0x00 }, // INC
{ 0xFF, 0x00 }, // DEC
{ 0x1E, 0xFF }, // ADD
{ 0x1E, 0xFF }, // SUB
{ 0x1E, 0xFF }, // MUL
{ 0x1E, 0xFF }, // UMUL
{ 0x1E, 0xFF }, // DIV
{ 0x1E, 0xFF }, // UDIV
{ 0x1E, 0xFF }, // MOD
{ 0x1E, 0xFF }, // UMOD
{ 0x1E, 0xFF }, // DMOD
{ 0x1E, 0xFF }, // UDMD
{ 0xFF, 0x00 }, // FBT
{ 0x1E, 0xFF }, // STB
{ 0x1E, 0xFF }, // CRB
{ 0x1E, 0xFF }, // TSB
{ 0xFF, 0x00 }, // BOOL
{ 0xFF, 0x00 }, // NOT
{ 0x1E, 0xFF }, // AND
{ 0x1E, 0xFF }, // OR
{ 0x1E, 0xFF }, // XOR
{ 0x1E, 0xFF }, // SHL
{ 0x1E, 0xFF }, // SHR
{ 0x1E, 0xFF }, // SSR
{ 0x1E, 0xFF }, // ROL
{ 0x1E, 0xFF }, // ROR
{ 0xFF, 0x00 }, // CNT
{ 0x1E, 0xFF }, // EQ
{ 0x1E, 0xFF }, // NE
{ 0x1E, 0xFF }, // GT
{ 0x1E, 0xFF }, // GE
{ 0x1E, 0xFF }, // LT
{ 0x1E, 0xFF }, // LE
{ 0xFF, 0x00 }, // JMP
{ 0xFF, 0x00 }, // JEQ
{ 0xFF, 0x00 }, // JNE
{ 0x1E, 0xFF }, // JIF
{ 0xFF, 0x00 }, // JMR
{ 0xFF, 0x00 }, // JER
{ 0xFF, 0x00 }, // JNR
{ 0x1E, 0xFF }, // JIR
{ 0x1E, 0xFF }, // SFB
{ 0x1E, 0xFF }, // LFB
{ 0x1E, 0xFF }, // JUF
{ 0x1E, 0xFF }, // JUR
{ 0xFF, 0x00 }, // PUSH
{ 0xFF, 0x00 }, // POP
{ 0xFF, 0x00 }, // ALLOC
{ 0xFF, 0x00 }, // HFREE
{ 0xFF, 0x00 }, // CALL
{ 0x00, 0x00 }, // RET
{ 0x00, 0x00 }, // EDI
{ 0x00, 0x00 }, // SHSS
{ 0x00, 0x00 }, // FLI
{ 0x00, 0x00 }, // FNEG
{ 0x00, 0x00 }, // FADD
{ 0x00, 0x00 }, // FSUB
{ 0x00, 0x00 }, // FMUL
{ 0x00, 0x00 }, // FDIV
{ 0x00, 0x00 }, // FMOD
{ 0x00, 0x00 }, // FDMOD
{ 0x00, 0x00 }, // FEPS
{ 0x00, 0x00 }, // FEEP
{ 0x00, 0x00 }, // FEQ
{ 0x00, 0x00 }, // FNE
{ 0x00, 0x00 }, // FGT
{ 0x00, 0x00 }, // FGE
{ 0x00, 0x00 }, // FLT
{ 0x00, 0x00 }, // FLE
{ 0x00, 0x00 }, // F2D
{ 0x00, 0x00 }, // D2F
{ 0x00, 0x00 }, // I2F
{ 0x00, 0x00 }, // I2D
{ 0x00, 0x00 }, // L2F
{ 0x00, 0x00 }, // L2D
{ 0x00, 0x00 }, // F2I
{ 0x00, 0x00 }, // F2L
{ 0x00, 0x00 }, // D2I
{ 0x00, 0x00 }, // D2L
{ 0x00, 0x00 }, // SIN
{ 0x00, 0x00 }, // COS
{ 0x00, 0x00 }, // TAN
{ 0x00, 0x00 }, // ASIN
{ 0x00, 0x00 }, // ACOS
{ 0x00, 0x00 }, // ATAN
{ 0x00, 0x00 }, // ATAN2
{ 0x00, 0x00 }, // EXP
{ 0x00, 0x00 }, // LOG
{ 0x00, 0x00 }, // LOGAB
{ 0x00, 0x00 }, // POW
{ 0x00, 0x00 }, // SQRT
{ 0x00, 0x00 }, // ROOT
{ 0xFF, 0x00 }, // EDI
{ 0xFF, 0x00 }, // SHSS
{ 0xFF, 0x00 }, // FLI
{ 0xFF, 0x00 }, // FNEG
{ 0x1E, 0xFF }, // FADD
{ 0x1E, 0xFF }, // FSUB
{ 0x1E, 0xFF }, // FMUL
{ 0x1E, 0xFF }, // FDIV
{ 0x1E, 0xFF }, // FMOD
{ 0x1E, 0xFF }, // FDMOD
{ 0xFF, 0x00 }, // FEPS
{ 0xFF, 0x00 }, // FEEP
{ 0x1E, 0xFF }, // FEQ
{ 0x1E, 0xFF }, // FNE
{ 0x1E, 0xFF }, // FGT
{ 0x1E, 0xFF }, // FGE
{ 0x1E, 0xFF }, // FLT
{ 0x1E, 0xFF }, // FLE
{ 0xFF, 0x00 }, // F2D
{ 0xFF, 0x00 }, // D2F
{ 0xFF, 0x00 }, // I2F
{ 0xFF, 0x00 }, // I2D
{ 0xFF, 0x00 }, // L2F
{ 0xFF, 0x00 }, // L2D
{ 0xFF, 0x00 }, // F2I
{ 0xFF, 0x00 }, // F2L
{ 0xFF, 0x00 }, // D2I
{ 0xFF, 0x00 }, // D2L
{ 0xFF, 0x00 }, // SIN
{ 0xFF, 0x00 }, // COS
{ 0xFF, 0x00 }, // TAN
{ 0xFF, 0x00 }, // ASIN
{ 0xFF, 0x00 }, // ACOS
{ 0xFF, 0x00 }, // ATAN
{ 0x1E, 0xFF }, // ATAN2
{ 0xFF, 0x00 }, // EXP
{ 0xFF, 0x00 }, // LOG
{ 0x1E, 0xFF }, // LOGAB
{ 0x1E, 0xFF }, // POW
{ 0xFF, 0x00 }, // SQRT
{ 0x1E, 0xFF }, // ROOT
{ 0x00, 0x00 }, // ADC
{ 0x00, 0x00 }, // SWC
{ 0x00, 0x00 }, // MWO
@@ -127,6 +127,8 @@ constexpr u8 ADDR_MODE_MASKS[][2] = {
{ 0x00, 0x00 }, // MINV
{ 0x00, 0x00 }, // MTRA
{ 0x00, 0x00 }, // MDET
{ 0x00, 0x00 }, // QMKA
{ 0x00, 0x00 }, // QMUL
{ 0x00, 0x00 }, // XADD
{ 0x00, 0x00 }, // XSUB
{ 0x00, 0x00 }, // XAMA
@@ -140,18 +142,18 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
0x00, // NOP
0x00, // SPDR
0x01, // MMODE
0x0F, // INT
0x0C, // LRV
0x0F, // FSR
0x0F, // FIR
0x0F, // FZR
0x0F, // LSR
0x0F, // FVR
0x00, // MOV
0x00, // MOR
0x00, // AMOV
0x00, // SWP
0x0F, // AHM
0x08, // INT
0x08, // LRV
0x08, // FSR
0x08, // FIR
0x08, // FZR
0x08, // LSR
0x08, // FVR
0x0F, // MOV
0x08, // MOR
0x08, // AMOV
0x08, // SWP
0x08, // AHM
0x0F, // COM
0x0F, // NEG
0x0F, // EXS
@@ -208,22 +210,22 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
0x0F, // RET
0x0F, // EDI
0x0F, // SHSS
0x00, // FLI
0x00, // FNEG
0x00, // FADD
0x00, // FSUB
0x00, // FMUL
0x00, // FDIV
0x00, // FMOD
0x00, // FDMOD
0x00, // FEPS
0x00, // FEEP
0x00, // FEQ
0x00, // FNE
0x00, // FGT
0x00, // FGE
0x00, // FLT
0x00, // FLE
0x0C, // FLI
0x0C, // FNEG
0x0C, // FADD
0x0C, // FSUB
0x0C, // FMUL
0x0C, // FDIV
0x0C, // FMOD
0x0C, // FDMOD
0x0C, // FEPS
0x0C, // FEEP
0x0C, // FEQ
0x0C, // FNE
0x0C, // FGT
0x0C, // FGE
0x0C, // FLT
0x0C, // FLE
0x00, // F2D
0x00, // D2F
0x00, // I2F
@@ -234,19 +236,19 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
0x00, // F2L
0x00, // D2I
0x00, // D2L
0x00, // SIN
0x00, // COS
0x00, // TAN
0x00, // ASIN
0x00, // ACOS
0x00, // ATAN
0x00, // ATAN2
0x00, // EXP
0x00, // LOG
0x00, // LOGAB
0x00, // POW
0x00, // SQRT
0x00, // ROOT
0x0C, // SIN
0x0C, // COS
0x0C, // TAN
0x0C, // ASIN
0x0C, // ACOS
0x0C, // ATAN
0x0C, // ATAN2
0x0C, // EXP
0x0C, // LOG
0x0C, // LOGAB
0x0C, // POW
0x0C, // SQRT
0x0C, // ROOT
0x00, // ADC
0x00, // SWC
0x00, // MWO
@@ -257,6 +259,8 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
0x00, // MINV
0x00, // MTRA
0x00, // MDET
0x00, // QMKA
0x00, // QMUL
0x00, // XADD
0x00, // XSUB
0x00, // XAMA

Binary file not shown.

View File

@@ -14,8 +14,16 @@ OBJEXT := o
#Flags, Libraries and Includes
ROOT := ./
CFLAGS := -Wall -std=c++20 -DSPIDER_COMPILING
LFLAGS := -Wall -std=c++20 -static
CFLAGS := -std=c++20 -O2 \
-Wall -Werror -Wextra \
-Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align \
-Wunused -Woverloaded-virtual -Wconversion \
-Wsign-conversion -Wnull-dereference -Wdouble-promotion \
-Wformat=2 -Wimplicit-fallthrough -Wsuggest-override \
-Wextra-semi -Wduplicated-cond -Wduplicated-branches \
-Wlogical-op -Wuseless-cast
LFLAGS := -std=c++20 -static-libstdc++ -static-libgcc \
-Wl,--fatal-warnings -Wl,--warn-common
LIB :=
INC := -I./src/

View File

@@ -15,7 +15,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"id": "b0fcd533",
"metadata": {},
"outputs": [
@@ -68,7 +68,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 2,
"id": "b33de8ac",
"metadata": {},
"outputs": [
@@ -144,7 +144,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 4,
"id": "58645013",
"metadata": {},
"outputs": [
@@ -152,7 +152,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Real instructions : 126\n",
"Real instructions : 128\n",
"Reserved slots : 14\n",
"Duplicate check : PASSED\n",
"\n",
@@ -163,13 +163,14 @@
"Bit Wise 14\n",
"Boolean 12\n",
"Branch 12\n",
"Casts 10\n",
"Floating Point 10\n",
"Casts 10\n",
"Memory 9\n",
"Trigonometric 7\n",
"Exponential 6\n",
"Matrix 6\n",
"SIMD 5\n",
"Quaternion 2\n",
"Easter Eggs 1\n",
"\n",
"First 5 instructions:\n",
@@ -177,8 +178,8 @@
"0 000 NOP System 0 00 00\n",
"1 001 SPDR System 0 00 00\n",
"2 002 MMODE System 1 05 01\n",
"3 003 INT System 1 1F 0F\n",
"4 004 LRV System 1 1F 0C\n"
"3 003 INT System 1 1F 08\n",
"4 004 LRV System 1 1F 08\n"
]
}
],
@@ -214,6 +215,7 @@
" 'dis', # addressing mode: Displaced\n",
" 'addr_mask_1', # accepted addressing mode mask for param 1\n",
" 'addr_mask_2', # accepted addressing mode mask for param 2\n",
" 'ignores_addrm',# whether the instruction ignores addressing modes\n",
" 'B', # type size: Byte (1 byte) supported?\n",
" 'S', # type size: Short (2 bytes) supported?\n",
" 'I', # type size: Int (4 bytes) supported?\n",
@@ -221,6 +223,7 @@
" 'F', # type size: Float supported?\n",
" 'D', # type size: Double supported?\n",
" 'type_mask', # combined type size mask as hex string\n",
" 'expensive', # marks computationally expensive instructions\n",
" 'operation', # human-readable description of what the instruction does\n",
" 'skip_2', # trailing empty column\n",
"]\n",
@@ -280,7 +283,7 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 5,
"id": "452bc76c",
"metadata": {},
"outputs": [
@@ -289,7 +292,7 @@
"output_type": "stream",
"text": [
"Masks written to: .//autogen/InstructionMasks.hpp\n",
"Lines generated : 268\n"
"Lines generated : 272\n"
]
}
],
@@ -354,7 +357,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 6,
"id": "5aaebef0",
"metadata": {},
"outputs": [
@@ -362,7 +365,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Instructions formatted: 126\n",
"Instructions formatted: 128\n",
"\n",
"--- Preview (first 2 instructions) ---\n",
" // [System] 0x000 — NOP: No Operation\n",
@@ -377,7 +380,7 @@
"\n",
"\n",
"CPU.hpp updated successfully at: .//src//spider/runtime/cpu/CPU.hpp\n",
"Total lines in updated file: 674\n"
"Total lines in updated file: 883\n"
]
}
],
@@ -445,6 +448,221 @@
"print(f'\\nCPU.hpp updated successfully at: {CPU_HPP_PATH}')\n",
"print(f'Total lines in updated file: {len(updated.splitlines())}')\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "instrmap_gen",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"InstrMap.cpp written to: .//src//spider/runtime/instr/InstrMap.cpp\n",
" Size : 34,157 bytes\n",
" Array entries : 512 (128 populated, 384 nullptr)\n",
" Switch cases : 128\n",
" Line endings : LF-only verified\n"
]
}
],
"source": [
"# ── Generate InstrMap.cpp ────────────────────────────────────────────────────\n",
"# Produces two dispatch implementations in one file:\n",
"# 1. CPUInstr InstrMap[512] — array of member-function pointers\n",
"# 2. void CPU::execute(u16) — switch/case version\n",
"#\n",
"# Both use UPPERCASE method names matching the mnemonic column.\n",
"\n",
"TABLE_SIZE = 512 # 9-bit opcode space\n",
"\n",
"# Build opcode -> mnemonic lookup from the cleaned instruction DataFrame.\n",
"opcode_to_mnem: dict[int, str] = {}\n",
"opcode_to_name: dict[int, str] = {}\n",
"opcode_to_group: dict[int, str] = {}\n",
"\n",
"for _, row in instrs_df.iterrows():\n",
" bc = str(row['byte_code']).strip()\n",
" opc = int(bc, 16)\n",
" opcode_to_mnem[opc] = str(row['mnemonic']).strip()\n",
" opcode_to_name[opc] = str(row['name']).strip()\n",
" opcode_to_group[opc] = str(row['group']).strip()\n",
"\n",
"# Also track reserved slots for annotation.\n",
"reserved_opcodes: set[int] = set()\n",
"for _, row in reserved_df.iterrows():\n",
" bc = str(row['byte_code']).strip()\n",
" if bc and bc != 'nan':\n",
" reserved_opcodes.add(int(bc, 16))\n",
"\n",
"# ── Assemble the file ───────────────────────────────────────────────────────\n",
"L = []\n",
"L.append('/**')\n",
"L.append(' * @file InstrMap.cpp')\n",
"L.append(' * @brief Spider VM instruction dispatch — array and switch implementations.')\n",
"L.append(' *')\n",
"L.append(' * AUTO-GENERATED by pygen.ipynb — DO NOT EDIT BY HAND.')\n",
"L.append(' *')\n",
"L.append(' * This file provides two equivalent dispatch mechanisms:')\n",
"L.append(' *')\n",
"L.append(' * 1. InstrMap[] — A lookup table of member-function pointers indexed by')\n",
"L.append(' * opcode. O(1) dispatch; suitable for platforms where')\n",
"L.append(' * indirect calls through function pointers are efficient.')\n",
"L.append(' *')\n",
"L.append(' * 2. CPU::execute(u16) — A switch/case over every opcode. Lets the')\n",
"L.append(' * compiler emit a jump table or branch tree; may be')\n",
"L.append(' * preferable on microcontrollers or when link-time')\n",
"L.append(' * optimisation can inline the handlers.')\n",
"L.append(' *')\n",
"L.append(' */')\n",
"L.append('') # [CHANGE] Use absolute path to make paths more explicit\n",
"L.append('#include <spider/runtime/cpu/CPU.hpp>')\n",
"L.append('')\n",
"L.append('namespace spider {')\n",
"L.append('')\n",
"\n",
"# ── Version 1: Array: ────────────────────────────────────────────────────────\n",
"L.append('// =============================================================')\n",
"L.append('// Version 1 — Lookup table of member-function pointers')\n",
"L.append('// =============================================================')\n",
"L.append('')\n",
"# [CHANGE] Use CPU::Fn Instead\n",
"#L.append('/** Pointer-to-member type for a zero-argument CPU instruction. */')\n",
"#L.append('using CPUInstr = void (CPU::*)();')\n",
"L.append('')\n",
"L.append('/**')\n",
"L.append(f' * Instruction dispatch table ({TABLE_SIZE} entries, 9-bit opcode space).')\n",
"L.append(' *')\n",
"L.append(' * Usage:')\n",
"L.append(' * u16 opcode = fetch();')\n",
"L.append(' * CPU::Fn fn = InstrMap[opcode];')\n",
"L.append(' * if (fn) (cpu.*fn)();')\n",
"L.append(' */') # [CHANGE] Made it part of the CPU & avoided explicit size.\n",
"L.append(f'CPU::Fn CPU::instrMap[] = {{')\n",
"\n",
"for opc in range(TABLE_SIZE):\n",
" mnem = opcode_to_mnem.get(opc)\n",
" if mnem:\n",
" name = opcode_to_name[opc]\n",
" L.append(f' &CPU::{mnem + \",\":<28s}// 0x{opc:03X} — {name}')\n",
" else:\n",
" tag = ''\n",
" if opc in reserved_opcodes:\n",
" tag = ' (reserved)'\n",
" L.append(f' {\"nullptr,\":<28s}// 0x{opc:03X}{tag}')\n",
"\n",
"L.append('};')\n",
"L.append('')\n",
"L.append('')\n",
"\n",
"# ── Version 2: Switch ──────────────────────────────────────────────────────\n",
"L.append('// =============================================================')\n",
"L.append('// Version 2 — Switch dispatch')\n",
"L.append('// =============================================================')\n",
"L.append('')\n",
"L.append('/**')\n",
"L.append(' * Execute the instruction identified by @p opcode.')\n",
"L.append(' *')\n",
"L.append(' * This is functionally equivalent to the InstrMap[] table above')\n",
"L.append(' * but expressed as a switch so the compiler can choose the best')\n",
"L.append(' * lowering strategy (jump table, binary search, etc.).')\n",
"L.append(' *')\n",
"L.append(' * @param opcode 9-bit instruction opcode (0x000 - 0x1FF).')\n",
"L.append(' */')\n",
"L.append('void CPU::executeSwLk() {')\n",
"L.append(' switch (_opcode) {')\n",
"\n",
"last_group = None\n",
"for opc in sorted(opcode_to_mnem.keys()):\n",
" mnem = opcode_to_mnem[opc]\n",
" group = opcode_to_group[opc]\n",
" if group != last_group:\n",
" L.append('')\n",
" L.append(f' // ── {group} ' + '─' * max(1, 44 - len(group)))\n",
" last_group = group\n",
" L.append(f' case 0x{opc:03X}: {mnem}(); break;')\n",
"\n",
"L.append('')\n",
"L.append(' default:')\n",
"L.append(' break;')\n",
"L.append(' }')\n",
"L.append('}')\n",
"L.append('')\n",
"L.append('} // namespace spider')\n",
"L.append('')\n",
"\n",
"INSTRMAP_SRC = '\\n'.join(L)\n",
"\n",
"# ── Write to file ───────────────────────────────────────────────────────────\n",
"# [CHANGE] Write this in the instructions folder to avoid CPU file bloat\n",
"INSTRMAP_PATH = f'{SRC_ROOT}/spider/runtime/instr/InstrMap.cpp'\n",
"\n",
"with open(INSTRMAP_PATH, 'wb') as f:\n",
" f.write(INSTRMAP_SRC.encode('utf-8'))\n",
"\n",
"# Verify LF-only\n",
"with open(INSTRMAP_PATH, 'rb') as f:\n",
" raw_bytes = f.read()\n",
"assert b'\\r' not in raw_bytes, 'CRLF detected in InstrMap.cpp!'\n",
"\n",
"array_count = INSTRMAP_SRC.count('&CPU::')\n",
"switch_count = INSTRMAP_SRC.count('case 0x')\n",
"\n",
"print(f'InstrMap.cpp written to: {INSTRMAP_PATH}')\n",
"print(f' Size : {len(raw_bytes):,} bytes')\n",
"print(f' Array entries : {TABLE_SIZE} ({array_count} populated, {TABLE_SIZE - array_count} nullptr)')\n",
"print(f' Switch cases : {switch_count}')\n",
"print(f' Line endings : LF-only verified')\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "9f190f4c",
"metadata": {},
"outputs": [],
"source": [
"# ---------- GENERATE INSTR_XX FILES ----------\n",
"INSTR_DIR = f'{SRC_ROOT}/spider/runtime/instr'\n",
"\n",
"# Generate the files\n",
"# Each file goes from 00 to 1F (0-31), 32 instr / file\n",
"for x0 in range(0, TABLE_SIZE, 32):\n",
" x1 = x0 + 31\n",
" fname = f'{INSTR_DIR}/Instr_{x0:03X}-{x1:03X}.cpp'\n",
"\n",
" # TODO: Check if there are missing instructions\n",
" if file_exists(fname):\n",
" continue\n",
"\n",
" # CREATE FILE FROM SCRATCH\n",
" L = []\n",
" L.append('/**')\n",
" L.append(' * @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!')\n",
" L.append(' *')\n",
" L.append(' */')\n",
" L.append('') # [CHANGE] Use absolute path to make paths more explicit\n",
" L.append('#include <spider/runtime/cpu/CPU.hpp>')\n",
" L.append('')\n",
" L.append('namespace spider {')\n",
" L.append('')\n",
"\n",
" for opc in range(x0, x1 + 1):\n",
" mnem = opcode_to_mnem.get(opc)\n",
" if mnem is None: continue\n",
"\n",
" L.append(f' void CPU::{mnem}() {{')\n",
" L.append(f' // TODO: Implement {mnem}')\n",
" L.append(f' }}')\n",
" L.append('')\n",
"\n",
" L.append('}')\n",
" L.append('')\n",
"\n",
" with open(fname, 'wb') as f:\n",
" f.write('\\n'.join(L).encode('utf-8'))\n"
]
}
],
"metadata": {
@@ -463,7 +681,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.7"
"version": "3.14.3"
}
},
"nbformat": 4,

View File

@@ -15,6 +15,7 @@
],
"C_Cpp.default.includePath": [
"./src"
]
],
"terminal.integrated.defaultProfile.windows": "MSYS2 UCRT"
}
}

View File

@@ -1,14 +1,18 @@
#include "SpiderRuntime.hpp"
#include <spider/runtime/debug/LiveDebug.hpp>
#include <iostream>
namespace spider {
const u32 RUNTIME_VERSION_NO = 0x00000000; // v0.1
const std::string RUNTIME_VERSION = "alpha v0.1";
}
int main() {
std::cout << "Hello World" << std::endl;
spider::liveDebugMain();
return 0;
}

View File

@@ -4,6 +4,9 @@
namespace spider {
extern const u32 RUNTIME_VERSION_NO;
extern const std::string RUNTIME_VERSION;
class Runtime;
class CPU;
class RAM;

View File

@@ -4,21 +4,37 @@ namespace spider {
// Constructors & Destructors //
Runtime::Runtime() : ram(0) {}
Runtime::Runtime() : Runtime(0) {}
Runtime::Runtime(u64 ramSize) : ram(ramSize) {}
Runtime::Runtime(u64 ramSize) : ram(ramSize), reel(nullptr) {
cpu.hookRAM(&ram);
}
Runtime::~Runtime() {}
Runtime::~Runtime() {
delete reel;
}
// Stepping/Running the Machine //
void Runtime::step() {}
void Runtime::step() {
cpu.fetchInstr();
// TODO: Call instruction
}
void Runtime::step(u64 n) {}
void Runtime::step(u64 n) {
while(n >= 4) {
step();
step();
step();
step();
n -= 4;
}
while (n--) step();
}
void Runtime::run() {}
void Runtime::run(u64 n) {}
//void Runtime::run(u64 n) {}
// Misc //
@@ -26,4 +42,13 @@ namespace spider {
ram.resize(length);
}
/**
* Non-owning reel setup.
*/
void Runtime::hookReel(InstrReel* newReel, bool own) {
delete this->reel;
cpu.hookInstrReel(newReel);
if(own) this->reel = newReel;
}
}

View File

@@ -1,8 +1,11 @@
#pragma once
#include <spider/runtime/cpu/CPU.hpp>
#include <spider/runtime/memory/RAM.hpp>
#include <spider/runtime/reel/InstrReel.hpp>
namespace spider {
/**
@@ -10,10 +13,11 @@ namespace spider {
* This is where the Spider VM (Runtime) lives
*/
class Runtime {
private:
public:
CPU cpu;
RAM ram;
InstrReel* reel;
public:
@@ -68,6 +72,11 @@ namespace spider {
*/
void resizeRAM(u64 length);
/**
* Non-owning reel setup.
*/
void hookReel(InstrReel* newReel, bool own = false);
};
}

View File

@@ -5,9 +5,11 @@
#include <deque>
#include <map>
#include <optional>
#include <string>
namespace spider {
// Absolute Types
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
@@ -25,6 +27,9 @@ namespace spider {
static_assert(sizeof(f32) == 4, "The f32 type must be exactly 4 bytes.");
static_assert(sizeof(f64) == 8, "The f64 type must be exactly 8 bytes.");
// Utility types
using isize = std::size_t;
// Utility imports
using std::vector;
using std::deque;

View File

@@ -0,0 +1,33 @@
#include "CPU.hpp"
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{}
{}
CPU::~CPU() {}
}
/**
* @brief BRAD (0xF7) - Memory Integrity Checksum
* Escanea los primeros 256 bytes de memoria y valida contra una firma de seguridad.
* Implementado por Bradley Vergara Lara - Estancia 2026.
*/
void CPU::BRAD() {
u32 checksum = 0;
const u32 MAGIC_SIGNATURE = 0x504944; // Firma de integridad "PID"
// Recorre la memoria base del sistema
for (u16 i = 0; i < 256; i++) {
checksum += memory.read8(i);
}
// Si el checksum coincide, RA = 1 (OK), si no RA = 0 (Error)
RA = (checksum == MAGIC_SIGNATURE) ? 1 : 0;
}

View File

@@ -1,15 +1,36 @@
#pragma once
#include <spider/SpiderRuntime.hpp>
#include <spider/runtime/cpu/Register.hpp>
namespace spider {
class CPU {
public: // Helper types
using Fn = void (CPU::*)();
public: // Flag Register Constants //
static constexpr const u64 FLAG_ENABLE = 0b0000000000000000000000000000000000000000000000000000000000000001;
static constexpr const u64 FLAG_INTERRUPT_SIGNAL = 0b0000000000000000000000000000000000000000000000000000000000000010;
static constexpr const u64 FLAG_INTERRUPT_REQUEST = 0b0000000000000000000000000000000000000000000000000000000000000100;
static constexpr const u64 FLAG_EXCEPTION = 0b0000000000000000000000000000000000000000000000000000000000001000;
static constexpr const u64 FLAG_MEMORY_MODE = 0b0000000000000000000000000000000000000000000000000000000000110000;
public: // Map of addressing modes & Instructions
static CPU::Fn addrModes[];
static CPU::Fn instrMap[];
public: // General Purpose Registers
register_t RA, RB, RC, RD,
RX, RY, R0, R1,
R2, R3, R4, R5,
R6, R7, R8, R9;
union {
register_t GPR[16];
struct {
register_t RA, RB, RC, RD,
RX, RY, R0, R1,
R2, R3, R4, R5,
R6, R7, R8, R9;
};
};
public: // System Registers
u64 RF;
@@ -31,6 +52,55 @@ namespace spider {
*/
register_t ALU0, ALU1;
union {
struct {
register_t* _dst;
register_t* _src;
register_t* _alu;
};
register_t* _opers[2];
};
// Holds the current instruction opcode
u16 _opcode : 9;
// Holds the current addressing modes,
// before they were used
u8 _addrm : 5;
// Holds the current instruction size.
u8 _size : 2;
// On _post that are not no-ops, it must
// write back DST to this memory location.
u64 _store;
// Post execution callback
CPU::Fn _post;
private:
/**
* Pointer to the current RAM hooked into
* the CPU.
*
* It is unproved whether having the RAM directly
* into the CPU is better than not, or whether a
* virtual BUS is better.
*
* Alas, this way we can have a CPU state switch
* between memory and instruction banks.
*/
RAM* _ram;
/**
* Pointer to the current Instruction Reel
* hooked into the CPU.
*
* Ditto as RAM.
*/
InstrReel* _reel;
public:
CPU();
@@ -47,6 +117,122 @@ namespace spider {
CPU& operator=(CPU&& other) noexcept = default;
public:
void hookRAM(RAM* ram);
void hookInstrReel(InstrReel* reel);
constexpr u64 getFlag(u64 mask);
public:
/**
* Fetches the instruction from the
* reel, and advances IR by two.
*/
void fetchInstr();
/**
* Fetches the destination operand,
* by calling the appropriate addressing
* mode.
*
* Will read the bottom 3 bits.
* For instructions with two operands,
* call Src first.
*
* The internal variable _addrm
* will not be modified. It will
* be important when writing
* back the result.
*/
void fetchOperDst();
/**
* Fetches the source operand.
*
* For use in two operand instructions.
*
* Will read the bottom 3 bits. It will
* then shift the _addrm 3 spaces
* to ensure it aligns with the DST
* next.
*
* Additionally, it will add 1 to _addrm
* to account with
*/
void fetchOperSrc();
/**
* Executes an opcode, by means of directly
* accessing the instruction map and
* calling that function pointer.
*/
void execute();
/**
* Executes an opcode, by means of using
* a large switch statement. Only suitable
* for environments where the instruction
* map is not possible.
*
* This has yet to be proved!!!
*/
void executeSwLk();
public: // Addressing Modes
/**
* Implied Addressing Mode
*/
void imp(); // Kept as it is a no-op
/**
* Immediate Addressing Mode
*/
void imm();
/**
* Absolute Addressing Mode
*/
void abs();
/**
* Register Addressing Mode
*/
void reg();
/**
* Indrect Addressing Mode
*/
void ind();
/**
* Pointer Addressing Mode
*/
void ptr();
/**
* Indexed Addressing Mode
*/
void idx();
/**
* Scaled Addressing Mode
*/
void sca();
/**
* Displaced Addressing Mode
*/
void dis();
/**
* Post-Write Action
*/
void psw();
public:
// <pygen-target name=cpu-instructions> //
@@ -66,327 +252,327 @@ namespace spider {
void MMODE();
// [System] 0x003 — INT: Interrupt
// Params: 1 | AddrMask1: 1F AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: 1F AddrMask2: 00 | TypeMask: 08
// Operation: Performs system interrupt no. (Dst) (See table)
void INT();
// [System] 0x004 — LRV: Load Interrupt Vector Register
// Params: 1 | AddrMask1: 1F AddrMask2: 00 | TypeMask: 0C
// Params: 1 | AddrMask1: 1F AddrMask2: 00 | TypeMask: 08
// Operation: Dst -> RV
void LRV();
// [System] 0x005 — FSR: Fetch System Register
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 08
// Operation: System Register at Dst -> Dst
void FSR();
// [System] 0x006 — FIR: Fetch Instruction Register
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 08
// Operation: Instruction Register -> Dst
void FIR();
// [System] 0x007 — FZR: Fetch Stack Base Register
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 08
// Operation: Stack Base Register -> Dst
void FZR();
// [System] 0x008 — LSR: Load System Register
// Params: 2 | AddrMask1: 1E AddrMask2: 1F | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: 1F | TypeMask: 08
// Operation: Src -> System Register at Dst
void LSR();
// [System] 0x009 — FVR: Fetch Interrupt Vector Register
// Params: 1 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: 04 AddrMask2: 00 | TypeMask: 08
// Operation: Interrupt Vector Register -> Dst
void FVR();
// [Memory] 0x00A — MOV: Moves values
// Params: 2 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Src -> Dst
void MOV();
// [Memory] 0x00B — MOR: Moves registers
// Params: 2 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 04 AddrMask2: 04 | TypeMask: 08
// Operation: R Scr -> R Dst
void MOR();
// [Memory] 0x00C — AMOV: Array Move, uses X and Y as ptrs, A as amount
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 08
// Operation: Array from X to Y, by A amount
void AMOV();
// [Memory] 0x00D — SWP: Swap registers
// Params: 2 | AddrMask1: 04 AddrMask2: 04 | TypeMask: 00
// Params: 2 | AddrMask1: 04 AddrMask2: 04 | TypeMask: 08
// Operation: Src <-> Dst
void SWP();
// [Memory] 0x00E — AHM: Ask Host for Memory
// Params: 1 | AddrMask1: 04 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: 04 AddrMask2: 00 | TypeMask: 08
// Operation: Asks the host for a specific size of memory. Responds with 0 or 1
void AHM();
// [Integer] 0x010 — COM: One's complement
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: ~ Dst -> Dst
void COM();
// [Integer] 0x011 — NEG: Two's complement
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: - Dst -> Dst
void NEG();
// [Integer] 0x012 — EXS: Extend Sign
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Last bit is copied and expanded for the next int size
void EXS();
// [Integer] 0x013 — INC: Increment
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst + 1 -> Dst
void INC();
// [Integer] 0x014 — DEC: Decrement
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst - 1 -> Dst
void DEC();
// [Integer] 0x015 — ADD: Addition
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst + Src -> Dst
void ADD();
// [Integer] 0x016 — SUB: Subtraction
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst - Src-> Dst
void SUB();
// [Integer] 0x017 — MUL: Multiplication
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Signed Dst * Src -> Dst
void MUL();
// [Integer] 0x018 — UMUL: Unsigned Multiplication
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Unsigned Dst * Src -> Dst
void UMUL();
// [Integer] 0x019 — DIV: Division
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Signed Dst / Src -> Dst
void DIV();
// [Integer] 0x01A — UDIV: Unsigned Division
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Unsigned Dst / Src -> Dst
void UDIV();
// [Integer] 0x01B — MOD: Modulus
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Signed Dst % Src -> Dst
void MOD();
// [Integer] 0x01C — UMOD: Unsigned Modulus
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Unsigned Dst % Src -> Dst
void UMOD();
// [Integer] 0x01D — DMOD: Division and Modulus
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Signed Dst / Src -> X, Dst % Src -> Y
void DMOD();
// [Integer] 0x01E — UDMD: Unsigned Division and Modulus
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Unsigned Dst / Src -> X, Dst % Src -> Y
void UDMD();
// [System] 0x01F — FBT: Test and update Flag Register (Integer) Bits
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Flags of Dst -
void FBT();
// [Bit Wise] 0x020 — STB: Set Bit
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Src# bit is set on Dst
void STB();
// [Bit Wise] 0x021 — CRB: Clear Bit
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Src# bit is cleared on Dst
void CRB();
// [Bit Wise] 0x022 — TSB: Test Bit
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Src# bit is tested against Dst, updates Equal Flag
void TSB();
// [Bit Wise] 0x023 — BOOL: Sets the booleaness of a value
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Tests Dst != 0, updates Equal Flag
void BOOL();
// [Bit Wise] 0x024 — NOT: Sets the inverse booleaness of a value (! BOOL)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Tests Dst == 0, updates Equal Flag
void NOT();
// [Bit Wise] 0x025 — AND: Boolean AND operation
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst AND Src into Dst
void AND();
// [Bit Wise] 0x026 — OR: Boolean OR operation
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst OR Src into Dst
void OR();
// [Bit Wise] 0x027 — XOR: Boolean XOR operation
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst XOR Src into Dst
void XOR();
// [Bit Wise] 0x028 — SHL: Arithmetic Shift Left
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst << Src into Dst
void SHL();
// [Bit Wise] 0x029 — SHR: Arithmetic Shift Right
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst >> Src into Dst
void SHR();
// [Bit Wise] 0x02A — SSR: Signed Shift Right
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst >>> Src into Dst
void SSR();
// [Bit Wise] 0x02B — ROL: Rotate Left
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst ROL Src into Dst
void ROL();
// [Bit Wise] 0x02C — ROR: Rotate Right
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst ROR Src into Dst
void ROR();
// [Bit Wise] 0x02D — CNT: Counts bits
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: # of 1's into Dst
void CNT();
// [Boolean] 0x030 — EQ: Equal
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst == Src into Dst
void EQ();
// [Boolean] 0x031 — NE: Not Equal
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst != Src into Dst
void NE();
// [Boolean] 0x032 — GT: Greater Than
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst > Src into Dst
void GT();
// [Boolean] 0x033 — GE: Greater or Equal Than
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst >= Src into Dst
void GE();
// [Boolean] 0x034 — LT: Lower Than
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst < Src into Dst
void LT();
// [Boolean] 0x035 — LE: Lower or Equal Than
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst <= Src into Dst
void LE();
// [Branch] 0x038 — JMP: Jump to absolute position
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst -> Instruction Register
void JMP();
// [Branch] 0x039 — JEQ: Jumps to position if EQ flag is set
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst -> Instruction Register IF Flags.EQ
void JEQ();
// [Branch] 0x03A — JNE: Jumps to position if EQ flag is cleared
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst -> Instruction Register IF NOT Flags.EQ
void JNE();
// [Branch] 0x03B — JIF: Jumps if value provided is booleanly true
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst -> Instruction Register IF Src
void JIF();
// [Branch] 0x03C — JMR: Jump Relative
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst + Instruction Register -> Instruction Register
void JMR();
// [Branch] 0x03D — JER: Jumps to relative position if EQ flag is set
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst + Instruction Register -> Instruction Register IF Flags.EQ
void JER();
// [Branch] 0x03E — JNR: Jumps to relative position if EQ flag is cleared
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst + Instruction Register -> Instruction Register IF NOT Flags.EQ
void JNR();
// [Branch] 0x03F — JIR: Jumps to relative position if value provided is booleanly true
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst + Instruction Register -> Instruction Register IF Src
void JIR();
// [System] 0x040 — SFB: Store (User) Flag Bit
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation:
void SFB();
// [System] 0x041 — LFB: Load (User) Flag Bit
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation:
void LFB();
// [Branch] 0x042 — JUF: Jump to absolute position, if user flag is true
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation:
void JUF();
// [Branch] 0x043 — JUR: Jump to relative position, if user flag is true
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation:
void JUR();
// [Memory] 0x044 — PUSH: Push to stack
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst -> pushed into stack
void PUSH();
// [Memory] 0x045 — POP: Pop from stack
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: popped from stack -> Dst
void POP();
// [Memory] 0x046 — ALLOC: Allocate to heap
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst -> heap ptr of size Dst
void ALLOC();
// [Memory] 0x047 — HFREE: Delete from heap
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Frees heap ptr in Dst
void HFREE();
// [Branch] 0x04A — CALL: Call function at instruction index
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Performs a function call, step XX
void CALL();
@@ -396,207 +582,207 @@ namespace spider {
void RET();
// [System] 0x04C — EDI: Enable/Disable External Interrupts
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: bool( Dst ) -> Enable External Interrupts Bit
void EDI();
// [System] 0x04D — SHSS: Set Hotswap Signal Bit
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: bool( Dst ) -> Hot Swap Signal Bit
void SHSS();
// [Floating Point] 0x050 — FLI: Float Load Immediate
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation:
void FLI();
// [Floating Point] 0x051 — FNEG: Float negate
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: - Dst -> Dst
void FNEG();
// [Floating Point] 0x052 — FADD: Float add
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst + Src -> Dst
void FADD();
// [Floating Point] 0x053 — FSUB: Float subtract
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst - Src-> Dst
void FSUB();
// [Floating Point] 0x054 — FMUL: Float multiplication
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst * Src -> Dst
void FMUL();
// [Floating Point] 0x055 — FDIV: Float division
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst / Src -> Dst
void FDIV();
// [Floating Point] 0x056 — FMOD: Float modulus
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst % Src -> Dst
void FMOD();
// [Floating Point] 0x057 — FDMOD: Float division and modulus
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst / Src -> X, Dst % Src -> Y
void FDMOD();
// [Floating Point] 0x058 — FEPS: Sets the float epsilon value, for comparison
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: Dst -> Epsilon Register
void FEPS();
// [Floating Point] 0x059 — FEEP: Float Enable/Disable Epsilon
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: bool( Dst ) -> Epsilon Enable Bit
void FEEP();
// [Boolean] 0x05A — FEQ: Float Equal
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst == Src into Dst
void FEQ();
// [Boolean] 0x05B — FNE: Float Not Equal
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst != Src into Dst
void FNE();
// [Boolean] 0x05C — FGT: Float Greater Than
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst > Src into Dst
void FGT();
// [Boolean] 0x05D — FGE: Float Greater or Equal Than
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst >= Src into Dst
void FGE();
// [Boolean] 0x05E — FLT: Float Lower Than
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst < Src into Dst
void FLT();
// [Boolean] 0x05F — FLE: Float Lower or Equal Than
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst <= Src into Dst
void FLE();
// [Casts] 0x060 — F2D: F32 (Float) to F64 (Double)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void F2D();
// [Casts] 0x061 — D2F: F64 (Double) to F32 (Float)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void D2F();
// [Casts] 0x062 — I2F: I32 (Integer) to F32 (Float)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void I2F();
// [Casts] 0x063 — I2D: I32 (Integer) to F64 (Double)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void I2D();
// [Casts] 0x064 — L2F: I64 (Long) to F32 (Float)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void L2F();
// [Casts] 0x065 — L2D: I64 (Long) to F64 (Double)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void L2D();
// [Casts] 0x066 — F2I: F32 (Float) to I32 (Integer)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void F2I();
// [Casts] 0x067 — F2L: F32 (Float) to I64 (Long)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void F2L();
// [Casts] 0x068 — D2I: F64 (Double) to I32 (Integer)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void D2I();
// [Casts] 0x069 — D2L: F64 (Double) to I64 (Long)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void D2L();
// [Trigonometric] 0x06C — SIN: Sine Function
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: sin( Dst ) -> Dst
void SIN();
// [Trigonometric] 0x06D — COS: Cosine Function
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: cos( Dst ) -> Dst
void COS();
// [Trigonometric] 0x06E — TAN: Tangent Function
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: tan( Dst ) -> Dst
void TAN();
// [Trigonometric] 0x06F — ASIN: Arc Sine Function
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: asin( Dst ) -> Dst
void ASIN();
// [Trigonometric] 0x070 — ACOS: Arc Cosine Function
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: acos( Dst ) -> Dst
void ACOS();
// [Trigonometric] 0x071 — ATAN: Arc Tangent Function
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: atan( Dst ) -> Dst
void ATAN();
// [Trigonometric] 0x072 — ATAN2: Arc Tangent Function with 2 Arguments
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: atan( Dst, Src ) -> Dst
void ATAN2();
// [Exponential] 0x074 — EXP: Exponential Function
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: exp( Dst ) -> Dst
void EXP();
// [Exponential] 0x075 — LOG: Natural Logarithm
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: ln( Dst ) -> Dst
void LOG();
// [Exponential] 0x076 — LOGAB: Logarithm A of B
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: log( Dst, Src ) -> Dst
void LOGAB();
// [Exponential] 0x077 — POW: Power Function
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: pow( Dst, Src ) -> Dst
void POW();
// [Exponential] 0x078 — SQRT: Square Root
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: sqrt( Dst ) -> Dst
void SQRT();
// [Exponential] 0x079 — ROOT: General Root
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: pow( Dst, 1 / Src ) -> Dst
void ROOT();
@@ -650,6 +836,16 @@ namespace spider {
// Operation:
void MDET();
// [Quaternion] 0x086 — QMKA: Quaternion Make from Angles
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void QMKA();
// [Quaternion] 0x087 — QMUL: Quaternion Multiply
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void QMUL();
// [SIMD] 0x08A — XADD: SIMD Addition
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
@@ -684,4 +880,4 @@ namespace spider {
};
}
}

View File

@@ -0,0 +1,25 @@
#include "CPU.hpp"
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{}
{}
CPU::~CPU() {}
// Stubs for testing
void CPU::fetchOperDst() { /* _dst already set manually in tests */ }
void CPU::fetchOperSrc() { /* _src already set manually in tests */ }
void CPU::imp() { /* no-op post action */ }
void CPU::hookRAM(RAM*) {}
void CPU::hookInstrReel(InstrReel*) {}
void CPU::fetchInstr() {}
void CPU::execute() {}
void CPU::psw() {}
}

View File

@@ -1,59 +0,0 @@
#pragma once
#include <spider/SpiderRuntime.hpp>
namespace spider {
/**
* Implements an instruction reel.
*/
class InstrReel {
private:
public:
InstrReel();
~InstrReel();
public:
public:
/**
* Returns the two-byte instruction at the
* specific byte location.
*/
u16 instrAt(u64 ip) const;
/**
* Obtains a byte of data at
* the specific location.
*/
u8 dataAt(u64 ip) const;
public:
/**
* Fetches the data, and then
* feeds the instruction into the
* CPU.
*
* Returns how many steps it should
* move after.
*/
u8 feedNext(CPU& cpu);
public: // Static Utils //
static u16 unpackInstr(u16 bcode);
static u8 unpackAddrMode(u16 bcode);
static u8 unpackTypeSize(u16 bcode);
};
}

View File

@@ -18,26 +18,13 @@ namespace spider {
* type-punning which is the "standard" right now.
*/
union register_t {
// -- Un/Signed 64 -- //
u64 _u64;
i64 _i64;
f64 _f64;
u8 _bytes[8];
SPIDER_PACKED_STRUCT(struct {
#if SPIDER_LITTLE_ENDIAN
u8 _u8; u64 : 56;
#else
u64 : 56; u8 _u8;
#endif
});
SPIDER_PACKED_STRUCT(struct {
#if SPIDER_LITTLE_ENDIAN
u16 _u16; u64 : 48;
#else
u64 : 48; u16 _u16;
#endif
});
// -- Un/Signed 32 -- //
struct {
#if SPIDER_LITTLE_ENDIAN
@@ -47,6 +34,61 @@ namespace spider {
#endif
};
struct {
#if SPIDER_LITTLE_ENDIAN
i32 _i32; i32 : 32;
#else
i32 : 32; i32 _i32;
#endif
};
// -- Un/Signed 16 -- //
struct {
#if SPIDER_LITTLE_ENDIAN
u16 _u16;
u16 : 16; u16 : 16; u16 : 16;
#else
u16 : 16; u16 : 16; u16 : 16;
u16 _u16;
#endif
};
struct {
#if SPIDER_LITTLE_ENDIAN
i16 _i16;
i16 : 16; i16 : 16; i16 : 16;
#else
i16 : 16; i16 : 16; i16 : 16;
i16 _i16;
#endif
};
// -- Un/Signed 8 -- //
struct {
#if SPIDER_LITTLE_ENDIAN
u8 _u8; // This looks like a cruel joke
u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8;
#else
u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8;
u8 _u8;
#endif
};
struct {
#if SPIDER_LITTLE_ENDIAN
i8 _i8; // ditto
i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8;
#else
i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8;
i8 _i8;
#endif
};
// -- Floating Point -- //
f64 _f64;
struct {
#if SPIDER_LITTLE_ENDIAN
f32 _f32; u32 : 32;
@@ -55,6 +97,10 @@ namespace spider {
#endif
};
// -- Access -- //
u8 _bytes[8];
u8& operator[](size_t i) { // 0 is always LSB
#if SPIDER_LITTLE_ENDIAN
return _bytes[i];
@@ -71,6 +117,7 @@ namespace spider {
return _bytes[7 - i];
#endif
}
};
static_assert(sizeof(register_t) == 8, "The register type must be exactly 8 bytes.");

View File

@@ -0,0 +1,402 @@
#include "LiveDebug.hpp"
#include <spider/runtime/reel/InstrReelFixed.hpp>
#include <spider/runtime/Runtime.hpp>
#include <spider/runtime/util/Terminal.hpp>
#include <spider/runtime/native/distro.hpp>
#include <vector>
#include <string>
#include <iomanip>
#include <iostream>
#include <chrono>
#include <format>
#include <thread>
namespace spider {
void drawHead(Terminal& t) {
t.move(1, 1)
.style(Terminal::FG_YELLOW)
.print(" Spider Runtime Live Debug ")
.style(Terminal::RESET).print(" | ")
.style(Terminal::FG_B_CYAN).print(" Sintek Analytics @ 2026 ")
.style(Terminal::RESET).print(" | ")
.style(Terminal::FG_B_BLACK).print("Press ESC to exit")
.style(Terminal::FG_BLACK)
.style(Terminal::BG_YELLOW)
.move(3, 1).print(" // __ \\\\").print(" ") // 27
.move(4, 1).print(" \\\\( )//").print(" SPIDER v0.1 ")
.move(5, 1).print(" //()\\\\ ").print(" alpha ")
.move(6, 1).print(" \\\\ // ").print(" ")
.style(Terminal::RESET)
.style(Terminal::FG_B_BLACK) // 4x8 for the menu
.move(3, 28).print("[ STEP ]")
.move(4, 28).print("[ STOP ]")
.move(5, 28).print("[ RUN ]")
.move(6, 28).print("[ MENU ]")
.style(Terminal::RESET)
;
}
void drawCPUTempl(Terminal& t) {
i32 r = 8, c = 1;
i32 w = 35, h = 31;
t.drawBox(r, c, w, h, "CPU");
const std::string regs[] = {
"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"
};
const std::string alt[] = {
Terminal::FG_WHITE,
Terminal::FG_B_BLACK,
};
r++;
c++;
t.move(r++, c);
t.style(Terminal::FG_B_YELLOW);
t.print_center(w - 2, "GP Registers");
t.style(Terminal::RESET);
for (i32 i = 0; i < 8; i++) {
t.style(alt[i & 1]);
t.move(r + i * 2, c);
t.print(regs[i * 2]);
t.move(r + i * 2, c + 17);
t.print(regs[i * 2 + 1]);
}
t.move(r += 16, c);
t.style(Terminal::FG_B_CYAN);
t.print_center(w - 2, "System Registers");
t.style(Terminal::RESET);
r++;
for (i32 j = 0, i = 8; i < 12; j++, i++) {
t.style(alt[j & 1]);
t.move(r + j * 2, c);
t.print(regs[i * 2]);
t.move(r + j * 2, c + 17);
t.print(regs[i * 2 + 1]);
}
t.move(r += 8, c);
t.style(Terminal::FG_GREEN);
t.print_center(w - 2, "Extra Registers");
t.style(Terminal::RESET);
r++;
for (i32 j = 0, i = 12; i < 13; j++, i++) {
t.style(alt[j & 1]);
t.move(r + j * 2, c);
t.print(regs[i * 2]);
t.move(r + j * 2, c + 17);
t.print(regs[i * 2 + 1]);
}
t.flush();
}
void printU64Hex(u64 n) {
std::ios state(nullptr);
state.copyfmt(std::cout);
std::cout
<< std::hex
<< std::uppercase
<< std::setfill('0')
<< std::setw(16)
<< n;
std::cout.copyfmt(state);
}
void drawCPU(Terminal& t, CPU& cpu) {
i32 r = 8, c = 1;
const register_t* regs[] = {
&cpu.RA, &cpu.RB, &cpu.RC, &cpu.RD,
&cpu.RX, &cpu.RY, &cpu.R0, &cpu.R1,
&cpu.R2, &cpu.R3, &cpu.R4, &cpu.R5,
&cpu.R6, &cpu.R7, &cpu.R8, &cpu.R9,
//&cpu.RF, &cpu.RI, &cpu.RS, &cpu.RZ,
//&cpu.RE, &cpu.RN, &cpu.RV, &cpu.RM,
&cpu.ALU0, &cpu.ALU1
};
const u64* sys_regs[] = {
&cpu.RF, &cpu.RI, &cpu.RS, &cpu.RZ,
&cpu.RE, &cpu.RN, &cpu.RV, &cpu.RM,
};
const std::string alt[] = {
Terminal::FG_WHITE,
Terminal::FG_B_BLACK,
};
r++;
c++;
t.move(r++, c);
t.style(Terminal::RESET);
r++;
for (i32 i = 0; i < 8; i++) {
t.style(alt[i & 1]);
t.move(r + i * 2, c);
printU64Hex(regs[i * 2]->_u64);
t.move(r + i * 2, c + 17);
printU64Hex(regs[i * 2 + 1]->_u64);
}
t.move(r += 16, c);
r++;
for (i32 j = 0; j < 4; j++) {
t.style(alt[j & 1]);
t.move(r + j * 2, c);
printU64Hex(*sys_regs[j * 2]);
t.move(r + j * 2, c + 17);
printU64Hex(*sys_regs[j * 2 + 1]);
}
t.move(r += 8, c);
r++;
for (i32 j = 0; j < 1; j++) {
t.style(alt[j & 1]);
t.move(r + j * 2, c);
printU64Hex(regs[16 + j * 2]->_u64);
t.move(r + j * 2, c + 17);
printU64Hex(regs[16 + j * 2 + 1]->_u64);
}
t.flush();
}
u32 addressWidth(isize ramSize) {
if (ramSize == 0) return 1;
isize maxAddr = ramSize - 1;
u32 digits = 0;
// Shift by increments of 4 (one hex nibble)
// We use a do-while to ensure at least 1 digit is returned for small RAMs
do {
digits++;
maxAddr >>= 4;
} while (maxAddr > 0);
return digits;
}
/**
* Draws a vertical scrollbar
* @param x The column where the bar should be placed (usually box_x + width - 1)
* @param y The starting row of the track (usually box_y + 1)
* @param trackHeight The internal height of the box (box_height - 2)
* @param progress The current progress
* @param total The total
*/
void drawScrollThumb(Terminal& term, u32 x, u32 y, u32 trackHeight, isize progress, isize total) {
if (total == 0 || trackHeight <= 0) return;
// 1. Draw the background track (Light Shade: ░)
term.style(Terminal::FG_B_BLACK); // Dim the track
for (u32 i = 0; i < trackHeight; ++i) {
term.move(i32(y + i), i32(x)).print("");
}
// 2. Calculate Thumb Position
// Cap progress to total to avoid overflow
if (progress > total) progress = total;
// Calculate ratio (0.0 to 1.0)
f64 ratio = f64(progress) / f64(total);
// Map to track coordinates
u32 thumbOffset = u32(ratio * (trackHeight - 1));
// 3. Draw the Thumb (Full Block: █)
term.move(i32(y + thumbOffset), i32(x));
term.style(Terminal::FG_WHITE).print("");
term.style(Terminal::RESET);
}
/**
* Draws a hex dump of memory within a styled terminal box.
* @param term Reference to your Terminal instance
* @param ram The RAM
* @param scrollPos The starting address to display
* @param x Starting column
* @param y Starting row
* @param width Width of the box
* @param height Height of the box
*/
void drawRAM(Terminal& term, RAM& ram, u64 scrollPos) {
// 1. Draw the container box
u32 y = 3;
u32 height = 36;
// 2. Configuration for the hex layout
u32 addrWidth = addressWidth(ram.size());
u32 bytesPerRow = 8;
u32 displayRows = height - 2; // Subtract top/bottom borders
u32 width = (2 + 2 + 16 + 7 + 3 + 8 + 4) + addrWidth;
u32 x = 37;
// create box
term.drawBox(i32(y), i32(x), i32(width), i32(height), "RAM");
drawScrollThumb(term, x + width - 2, y + 1, height - 2, scrollPos, ram.size());
// Ensure scrollPos is within bounds and aligned
//if (scrollPos < 0) scrollPos = 0;
if (scrollPos > ram.size()) scrollPos = ram.size();
for (u32 i = 0; i < displayRows; ++i) {
isize currentRowAddr = scrollPos + (i * bytesPerRow);
// address lock
if (currentRowAddr >= ram.size()) {
term.move(i32(y + 1 + i), i32(x + 1));
term.print(std::string(width - 3, ' '));
continue;
}
std::stringstream ssaddr;
std::stringstream ss;
// setup ss
ssaddr << std::setfill('0') << std::uppercase << std::hex;
ss << std::setfill('0') << std::uppercase << std::hex;
// address
ssaddr << std::setw(i32(addrWidth)) << currentRowAddr << " ";
// Hex Bytes
std::string asciiPart = "";
for (u32 j = 0; j < bytesPerRow; ++j) {
isize targetAddr = currentRowAddr + j;
if (targetAddr >= ram.size()) {
ss << ""; // Padding for end of memory
asciiPart += "";
continue;
}
u8 byte = ram[targetAddr];
ss << std::setfill('0') << std::setw(2) << std::hex << u32(byte) << " ";
asciiPart += (std::isprint(byte) ? char(byte) : '.');
}
// --- Combine and Print ---
term.move(i32(y + 1 + i), i32(x + 2)); // Move inside the box
term.style(Terminal::FG_B_CYAN).print(ssaddr.str()); // Hex part in Cyan
term.style(Terminal::FG_WHITE).print(ss.str());
term.style(Terminal::FG_B_YELLOW).print(" | ");
term.style(Terminal::FG_WHITE).print(asciiPart); // ASCII part in White
}
term.style(Terminal::RESET);
term.flush();
}
std::string getTimestamp() {
std::time_t t = std::time(nullptr);
std::tm lt;
#if defined(SPIDER_OS_WINDOWS)
localtime_s(&lt, &t);
#endif
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
localtime_r(&t, &lt);
#endif
return std::format("{:02}:{:02}:{:02} {:02}/{:02}/{}",
lt.tm_hour, lt.tm_min, lt.tm_sec,
lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900);
}
void drawTime(Terminal& t) {
//auto now = std::chrono::system_clock::now();
//auto now_l = std::chrono::current_zone()->to_local(now);
//auto now_s = std::chrono::floor<std::chrono::seconds>(now_l);
//std::string time_str = std::format("{:%H:%M:%S}", now_s); // Format: HH:mm:ss
//std::string date_str = std::format("{:%d/%m/%Y}", now_s); // Format: dd/MM/YYYY
t.move(1, 76);
t.style(Terminal::RESET);
t.print(" | ").style(Terminal::FG_GREEN).print(getTimestamp());
}
void redraw(Terminal& t, Runtime& r, u64 scroll) {
// draw CPU, RAM
drawCPU(t, r.cpu);
drawRAM(t, r.ram, scroll);
}
int liveDebugMain() {
Terminal t;
Runtime runtime(1024);
InstrReelFixed fix(100);
runtime.hookReel(&fix, false);
bool running = true, update = true;
u64 ramScroll = 0;
u8 key = Terminal::UNKNOWN;
t.println("Starting Spider live debug...");
t.altbuff(true).cursor(false);
drawTime(t);
drawHead(t);
drawCPUTempl(t);
// delay for time
auto last_exec = std::chrono::steady_clock::now();
auto delay = std::chrono::milliseconds(1000);
while (running) {
// draw time
auto now = std::chrono::steady_clock::now();
if (now - last_exec >= delay) {
drawTime(t);
last_exec = now;
}
// redraw something if it updated
if (update) {
redraw(t, runtime, ramScroll);
update = false;
}
// Handle Input
key = t.getKeyNb();
switch (key) {
case Terminal::ESC:
running = false;
break;
case Terminal::UP:
if (ramScroll >= 16) ramScroll -= 16;
update = true;
break;
case Terminal::DOWN:
if (runtime.ram.size() >= 16 && ramScroll <= runtime.ram.size() - 16) ramScroll += 16;
update = true;
break;
case Terminal::ENTER:
update = true;
runtime.cpu.fetchInstr();
runtime.cpu.execute(); // looks up instrMap[_opcode] & calls the correct instruction method (e.g. FMUL)
break;
default:
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
t.altbuff(false).println("Stopped Spider live debug.").flush();
return 0;
}
}

View File

@@ -0,0 +1,7 @@
#pragma once
namespace spider {
int liveDebugMain();
}

View File

@@ -0,0 +1,746 @@
/**
* @file InstrMap.cpp
* @brief Spider VM instruction dispatch — array and switch implementations.
*
* AUTO-GENERATED by pygen.ipynb — DO NOT EDIT BY HAND.
*
* This file provides two equivalent dispatch mechanisms:
*
* 1. InstrMap[] — A lookup table of member-function pointers indexed by
* opcode. O(1) dispatch; suitable for platforms where
* indirect calls through function pointers are efficient.
*
* 2. CPU::execute(u16) — A switch/case over every opcode. Lets the
* compiler emit a jump table or branch tree; may be
* preferable on microcontrollers or when link-time
* optimisation can inline the handlers.
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
// =============================================================
// Version 1 — Lookup table of member-function pointers
// =============================================================
/**
* Instruction dispatch table (512 entries, 9-bit opcode space).
*
* Usage:
* u16 opcode = fetch();
* CPU::Fn fn = InstrMap[opcode];
* if (fn) (cpu.*fn)();
*/
CPU::Fn CPU::instrMap[] = {
&CPU::NOP, // 0x000 — No Operation
&CPU::SPDR, // 0x001 — Will place the Spider version of the interpreter in RA
&CPU::MMODE, // 0x002 — Set Memory Mode
&CPU::INT, // 0x003 — Interrupt
&CPU::LRV, // 0x004 — Load Interrupt Vector Register
&CPU::FSR, // 0x005 — Fetch System Register
&CPU::FIR, // 0x006 — Fetch Instruction Register
&CPU::FZR, // 0x007 — Fetch Stack Base Register
&CPU::LSR, // 0x008 — Load System Register
&CPU::FVR, // 0x009 — Fetch Interrupt Vector Register
&CPU::MOV, // 0x00A — Moves values
&CPU::MOR, // 0x00B — Moves registers
&CPU::AMOV, // 0x00C — Array Move, uses X and Y as ptrs, A as amount
&CPU::SWP, // 0x00D — Swap registers
&CPU::AHM, // 0x00E — Ask Host for Memory
nullptr, // 0x00F (reserved)
&CPU::COM, // 0x010 — One's complement
&CPU::NEG, // 0x011 — Two's complement
&CPU::EXS, // 0x012 — Extend Sign
&CPU::INC, // 0x013 — Increment
&CPU::DEC, // 0x014 — Decrement
&CPU::ADD, // 0x015 — Addition
&CPU::SUB, // 0x016 — Subtraction
&CPU::MUL, // 0x017 — Multiplication
&CPU::UMUL, // 0x018 — Unsigned Multiplication
&CPU::DIV, // 0x019 — Division
&CPU::UDIV, // 0x01A — Unsigned Division
&CPU::MOD, // 0x01B — Modulus
&CPU::UMOD, // 0x01C — Unsigned Modulus
&CPU::DMOD, // 0x01D — Division and Modulus
&CPU::UDMD, // 0x01E — Unsigned Division and Modulus
&CPU::FBT, // 0x01F — Test and update Flag Register (Integer) Bits
&CPU::STB, // 0x020 — Set Bit
&CPU::CRB, // 0x021 — Clear Bit
&CPU::TSB, // 0x022 — Test Bit
&CPU::BOOL, // 0x023 — Sets the booleaness of a value
&CPU::NOT, // 0x024 — Sets the inverse booleaness of a value (! BOOL)
&CPU::AND, // 0x025 — Boolean AND operation
&CPU::OR, // 0x026 — Boolean OR operation
&CPU::XOR, // 0x027 — Boolean XOR operation
&CPU::SHL, // 0x028 — Arithmetic Shift Left
&CPU::SHR, // 0x029 — Arithmetic Shift Right
&CPU::SSR, // 0x02A — Signed Shift Right
&CPU::ROL, // 0x02B — Rotate Left
&CPU::ROR, // 0x02C — Rotate Right
&CPU::CNT, // 0x02D — Counts bits
nullptr, // 0x02E (reserved)
nullptr, // 0x02F (reserved)
&CPU::EQ, // 0x030 — Equal
&CPU::NE, // 0x031 — Not Equal
&CPU::GT, // 0x032 — Greater Than
&CPU::GE, // 0x033 — Greater or Equal Than
&CPU::LT, // 0x034 — Lower Than
&CPU::LE, // 0x035 — Lower or Equal Than
nullptr, // 0x036 (reserved)
nullptr, // 0x037 (reserved)
&CPU::JMP, // 0x038 — Jump to absolute position
&CPU::JEQ, // 0x039 — Jumps to position if EQ flag is set
&CPU::JNE, // 0x03A — Jumps to position if EQ flag is cleared
&CPU::JIF, // 0x03B — Jumps if value provided is booleanly true
&CPU::JMR, // 0x03C — Jump Relative
&CPU::JER, // 0x03D — Jumps to relative position if EQ flag is set
&CPU::JNR, // 0x03E — Jumps to relative position if EQ flag is cleared
&CPU::JIR, // 0x03F — Jumps to relative position if value provided is booleanly true
&CPU::SFB, // 0x040 — Store (User) Flag Bit
&CPU::LFB, // 0x041 — Load (User) Flag Bit
&CPU::JUF, // 0x042 — Jump to absolute position, if user flag is true
&CPU::JUR, // 0x043 — Jump to relative position, if user flag is true
&CPU::PUSH, // 0x044 — Push to stack
&CPU::POP, // 0x045 — Pop from stack
&CPU::ALLOC, // 0x046 — Allocate to heap
&CPU::HFREE, // 0x047 — Delete from heap
nullptr, // 0x048 (reserved)
nullptr, // 0x049 (reserved)
&CPU::CALL, // 0x04A — Call function at instruction index
&CPU::RET, // 0x04B — Return from a function
&CPU::EDI, // 0x04C — Enable/Disable External Interrupts
&CPU::SHSS, // 0x04D — Set Hotswap Signal Bit
nullptr, // 0x04E (reserved)
nullptr, // 0x04F (reserved)
&CPU::FLI, // 0x050 — Float Load Immediate
&CPU::FNEG, // 0x051 — Float negate
&CPU::FADD, // 0x052 — Float add
&CPU::FSUB, // 0x053 — Float subtract
&CPU::FMUL, // 0x054 — Float multiplication
&CPU::FDIV, // 0x055 — Float division
&CPU::FMOD, // 0x056 — Float modulus
&CPU::FDMOD, // 0x057 — Float division and modulus
&CPU::FEPS, // 0x058 — Sets the float epsilon value, for comparison
&CPU::FEEP, // 0x059 — Float Enable/Disable Epsilon
&CPU::FEQ, // 0x05A — Float Equal
&CPU::FNE, // 0x05B — Float Not Equal
&CPU::FGT, // 0x05C — Float Greater Than
&CPU::FGE, // 0x05D — Float Greater or Equal Than
&CPU::FLT, // 0x05E — Float Lower Than
&CPU::FLE, // 0x05F — Float Lower or Equal Than
&CPU::F2D, // 0x060 — F32 (Float) to F64 (Double)
&CPU::D2F, // 0x061 — F64 (Double) to F32 (Float)
&CPU::I2F, // 0x062 — I32 (Integer) to F32 (Float)
&CPU::I2D, // 0x063 — I32 (Integer) to F64 (Double)
&CPU::L2F, // 0x064 — I64 (Long) to F32 (Float)
&CPU::L2D, // 0x065 — I64 (Long) to F64 (Double)
&CPU::F2I, // 0x066 — F32 (Float) to I32 (Integer)
&CPU::F2L, // 0x067 — F32 (Float) to I64 (Long)
&CPU::D2I, // 0x068 — F64 (Double) to I32 (Integer)
&CPU::D2L, // 0x069 — F64 (Double) to I64 (Long)
nullptr, // 0x06A (reserved)
nullptr, // 0x06B (reserved)
&CPU::SIN, // 0x06C — Sine Function
&CPU::COS, // 0x06D — Cosine Function
&CPU::TAN, // 0x06E — Tangent Function
&CPU::ASIN, // 0x06F — Arc Sine Function
&CPU::ACOS, // 0x070 — Arc Cosine Function
&CPU::ATAN, // 0x071 — Arc Tangent Function
&CPU::ATAN2, // 0x072 — Arc Tangent Function with 2 Arguments
nullptr, // 0x073 (reserved)
&CPU::EXP, // 0x074 — Exponential Function
&CPU::LOG, // 0x075 — Natural Logarithm
&CPU::LOGAB, // 0x076 — Logarithm A of B
&CPU::POW, // 0x077 — Power Function
&CPU::SQRT, // 0x078 — Square Root
&CPU::ROOT, // 0x079 — General Root
nullptr, // 0x07A (reserved)
nullptr, // 0x07B (reserved)
&CPU::ADC, // 0x07C — Add with Carry
&CPU::SWC, // 0x07D — Subtract with Carry (Borrow)
&CPU::MWO, // 0x07E — Multiply with Overflow
&CPU::UMO, // 0x07F — Unsigned Multiply with Overflow
&CPU::MADD, // 0x080 — Matrix Addition
&CPU::MSUB, // 0x081 — Matrix Subtraction
&CPU::MMUL, // 0x082 — Matrix Multiply
&CPU::MINV, // 0x083 — Matrix Inverse
&CPU::MTRA, // 0x084 — Matrix Transpose
&CPU::MDET, // 0x085 — Matrix Determinant
&CPU::QMKA, // 0x086 — Quaternion Make from Angles
&CPU::QMUL, // 0x087 — Quaternion Multiply
nullptr, // 0x088
nullptr, // 0x089
&CPU::XADD, // 0x08A — SIMD Addition
&CPU::XSUB, // 0x08B — SIMD Subtract
&CPU::XAMA, // 0x08C — SIMD Alternate Multiply-Add
&CPU::XMUL, // 0x08D — SIMD Multiply
&CPU::XDIV, // 0x08E — SIMD Divide
nullptr, // 0x08F
nullptr, // 0x090
nullptr, // 0x091
nullptr, // 0x092
nullptr, // 0x093
nullptr, // 0x094
nullptr, // 0x095
nullptr, // 0x096
nullptr, // 0x097
nullptr, // 0x098
nullptr, // 0x099
nullptr, // 0x09A
nullptr, // 0x09B
nullptr, // 0x09C
nullptr, // 0x09D
nullptr, // 0x09E
nullptr, // 0x09F
nullptr, // 0x0A0
nullptr, // 0x0A1
nullptr, // 0x0A2
nullptr, // 0x0A3
nullptr, // 0x0A4
nullptr, // 0x0A5
nullptr, // 0x0A6
nullptr, // 0x0A7
nullptr, // 0x0A8
nullptr, // 0x0A9
nullptr, // 0x0AA
nullptr, // 0x0AB
nullptr, // 0x0AC
nullptr, // 0x0AD
nullptr, // 0x0AE
nullptr, // 0x0AF
nullptr, // 0x0B0
nullptr, // 0x0B1
nullptr, // 0x0B2
nullptr, // 0x0B3
nullptr, // 0x0B4
nullptr, // 0x0B5
nullptr, // 0x0B6
nullptr, // 0x0B7
nullptr, // 0x0B8
nullptr, // 0x0B9
nullptr, // 0x0BA
nullptr, // 0x0BB
nullptr, // 0x0BC
nullptr, // 0x0BD
nullptr, // 0x0BE
nullptr, // 0x0BF
nullptr, // 0x0C0
nullptr, // 0x0C1
nullptr, // 0x0C2
nullptr, // 0x0C3
nullptr, // 0x0C4
nullptr, // 0x0C5
nullptr, // 0x0C6
nullptr, // 0x0C7
nullptr, // 0x0C8
nullptr, // 0x0C9
nullptr, // 0x0CA
nullptr, // 0x0CB
nullptr, // 0x0CC
nullptr, // 0x0CD
nullptr, // 0x0CE
nullptr, // 0x0CF
nullptr, // 0x0D0
nullptr, // 0x0D1
nullptr, // 0x0D2
nullptr, // 0x0D3
nullptr, // 0x0D4
nullptr, // 0x0D5
nullptr, // 0x0D6
nullptr, // 0x0D7
nullptr, // 0x0D8
nullptr, // 0x0D9
nullptr, // 0x0DA
nullptr, // 0x0DB
nullptr, // 0x0DC
nullptr, // 0x0DD
nullptr, // 0x0DE
nullptr, // 0x0DF
nullptr, // 0x0E0
nullptr, // 0x0E1
nullptr, // 0x0E2
nullptr, // 0x0E3
nullptr, // 0x0E4
nullptr, // 0x0E5
nullptr, // 0x0E6
nullptr, // 0x0E7
nullptr, // 0x0E8
nullptr, // 0x0E9
nullptr, // 0x0EA
nullptr, // 0x0EB
nullptr, // 0x0EC
nullptr, // 0x0ED
nullptr, // 0x0EE
nullptr, // 0x0EF
&CPU::UPY, // 0x0F0 — Will place "YUPI" in memory
nullptr, // 0x0F1
nullptr, // 0x0F2
nullptr, // 0x0F3
nullptr, // 0x0F4
nullptr, // 0x0F5
nullptr, // 0x0F6
nullptr, // 0x0F7
nullptr, // 0x0F8
nullptr, // 0x0F9
nullptr, // 0x0FA
nullptr, // 0x0FB
nullptr, // 0x0FC
nullptr, // 0x0FD
nullptr, // 0x0FE
nullptr, // 0x0FF
nullptr, // 0x100
nullptr, // 0x101
nullptr, // 0x102
nullptr, // 0x103
nullptr, // 0x104
nullptr, // 0x105
nullptr, // 0x106
nullptr, // 0x107
nullptr, // 0x108
nullptr, // 0x109
nullptr, // 0x10A
nullptr, // 0x10B
nullptr, // 0x10C
nullptr, // 0x10D
nullptr, // 0x10E
nullptr, // 0x10F
nullptr, // 0x110
nullptr, // 0x111
nullptr, // 0x112
nullptr, // 0x113
nullptr, // 0x114
nullptr, // 0x115
nullptr, // 0x116
nullptr, // 0x117
nullptr, // 0x118
nullptr, // 0x119
nullptr, // 0x11A
nullptr, // 0x11B
nullptr, // 0x11C
nullptr, // 0x11D
nullptr, // 0x11E
nullptr, // 0x11F
nullptr, // 0x120
nullptr, // 0x121
nullptr, // 0x122
nullptr, // 0x123
nullptr, // 0x124
nullptr, // 0x125
nullptr, // 0x126
nullptr, // 0x127
nullptr, // 0x128
nullptr, // 0x129
nullptr, // 0x12A
nullptr, // 0x12B
nullptr, // 0x12C
nullptr, // 0x12D
nullptr, // 0x12E
nullptr, // 0x12F
nullptr, // 0x130
nullptr, // 0x131
nullptr, // 0x132
nullptr, // 0x133
nullptr, // 0x134
nullptr, // 0x135
nullptr, // 0x136
nullptr, // 0x137
nullptr, // 0x138
nullptr, // 0x139
nullptr, // 0x13A
nullptr, // 0x13B
nullptr, // 0x13C
nullptr, // 0x13D
nullptr, // 0x13E
nullptr, // 0x13F
nullptr, // 0x140
nullptr, // 0x141
nullptr, // 0x142
nullptr, // 0x143
nullptr, // 0x144
nullptr, // 0x145
nullptr, // 0x146
nullptr, // 0x147
nullptr, // 0x148
nullptr, // 0x149
nullptr, // 0x14A
nullptr, // 0x14B
nullptr, // 0x14C
nullptr, // 0x14D
nullptr, // 0x14E
nullptr, // 0x14F
nullptr, // 0x150
nullptr, // 0x151
nullptr, // 0x152
nullptr, // 0x153
nullptr, // 0x154
nullptr, // 0x155
nullptr, // 0x156
nullptr, // 0x157
nullptr, // 0x158
nullptr, // 0x159
nullptr, // 0x15A
nullptr, // 0x15B
nullptr, // 0x15C
nullptr, // 0x15D
nullptr, // 0x15E
nullptr, // 0x15F
nullptr, // 0x160
nullptr, // 0x161
nullptr, // 0x162
nullptr, // 0x163
nullptr, // 0x164
nullptr, // 0x165
nullptr, // 0x166
nullptr, // 0x167
nullptr, // 0x168
nullptr, // 0x169
nullptr, // 0x16A
nullptr, // 0x16B
nullptr, // 0x16C
nullptr, // 0x16D
nullptr, // 0x16E
nullptr, // 0x16F
nullptr, // 0x170
nullptr, // 0x171
nullptr, // 0x172
nullptr, // 0x173
nullptr, // 0x174
nullptr, // 0x175
nullptr, // 0x176
nullptr, // 0x177
nullptr, // 0x178
nullptr, // 0x179
nullptr, // 0x17A
nullptr, // 0x17B
nullptr, // 0x17C
nullptr, // 0x17D
nullptr, // 0x17E
nullptr, // 0x17F
nullptr, // 0x180
nullptr, // 0x181
nullptr, // 0x182
nullptr, // 0x183
nullptr, // 0x184
nullptr, // 0x185
nullptr, // 0x186
nullptr, // 0x187
nullptr, // 0x188
nullptr, // 0x189
nullptr, // 0x18A
nullptr, // 0x18B
nullptr, // 0x18C
nullptr, // 0x18D
nullptr, // 0x18E
nullptr, // 0x18F
nullptr, // 0x190
nullptr, // 0x191
nullptr, // 0x192
nullptr, // 0x193
nullptr, // 0x194
nullptr, // 0x195
nullptr, // 0x196
nullptr, // 0x197
nullptr, // 0x198
nullptr, // 0x199
nullptr, // 0x19A
nullptr, // 0x19B
nullptr, // 0x19C
nullptr, // 0x19D
nullptr, // 0x19E
nullptr, // 0x19F
nullptr, // 0x1A0
nullptr, // 0x1A1
nullptr, // 0x1A2
nullptr, // 0x1A3
nullptr, // 0x1A4
nullptr, // 0x1A5
nullptr, // 0x1A6
nullptr, // 0x1A7
nullptr, // 0x1A8
nullptr, // 0x1A9
nullptr, // 0x1AA
nullptr, // 0x1AB
nullptr, // 0x1AC
nullptr, // 0x1AD
nullptr, // 0x1AE
nullptr, // 0x1AF
nullptr, // 0x1B0
nullptr, // 0x1B1
nullptr, // 0x1B2
nullptr, // 0x1B3
nullptr, // 0x1B4
nullptr, // 0x1B5
nullptr, // 0x1B6
nullptr, // 0x1B7
nullptr, // 0x1B8
nullptr, // 0x1B9
nullptr, // 0x1BA
nullptr, // 0x1BB
nullptr, // 0x1BC
nullptr, // 0x1BD
nullptr, // 0x1BE
nullptr, // 0x1BF
nullptr, // 0x1C0
nullptr, // 0x1C1
nullptr, // 0x1C2
nullptr, // 0x1C3
nullptr, // 0x1C4
nullptr, // 0x1C5
nullptr, // 0x1C6
nullptr, // 0x1C7
nullptr, // 0x1C8
nullptr, // 0x1C9
nullptr, // 0x1CA
nullptr, // 0x1CB
nullptr, // 0x1CC
nullptr, // 0x1CD
nullptr, // 0x1CE
nullptr, // 0x1CF
nullptr, // 0x1D0
nullptr, // 0x1D1
nullptr, // 0x1D2
nullptr, // 0x1D3
nullptr, // 0x1D4
nullptr, // 0x1D5
nullptr, // 0x1D6
nullptr, // 0x1D7
nullptr, // 0x1D8
nullptr, // 0x1D9
nullptr, // 0x1DA
nullptr, // 0x1DB
nullptr, // 0x1DC
nullptr, // 0x1DD
nullptr, // 0x1DE
nullptr, // 0x1DF
nullptr, // 0x1E0
nullptr, // 0x1E1
nullptr, // 0x1E2
nullptr, // 0x1E3
nullptr, // 0x1E4
nullptr, // 0x1E5
nullptr, // 0x1E6
nullptr, // 0x1E7
nullptr, // 0x1E8
nullptr, // 0x1E9
nullptr, // 0x1EA
nullptr, // 0x1EB
nullptr, // 0x1EC
nullptr, // 0x1ED
nullptr, // 0x1EE
nullptr, // 0x1EF
nullptr, // 0x1F0
nullptr, // 0x1F1
nullptr, // 0x1F2
nullptr, // 0x1F3
nullptr, // 0x1F4
nullptr, // 0x1F5
nullptr, // 0x1F6
nullptr, // 0x1F7
nullptr, // 0x1F8
nullptr, // 0x1F9
nullptr, // 0x1FA
nullptr, // 0x1FB
nullptr, // 0x1FC
nullptr, // 0x1FD
nullptr, // 0x1FE
nullptr, // 0x1FF
};
// =============================================================
// Version 2 — Switch dispatch
// =============================================================
/**
* Execute the instruction identified by @p opcode.
*
* This is functionally equivalent to the InstrMap[] table above
* but expressed as a switch so the compiler can choose the best
* lowering strategy (jump table, binary search, etc.).
*
* @param opcode 9-bit instruction opcode (0x000 - 0x1FF).
*/
void CPU::executeSwLk() {
switch (_opcode) {
// ── System ──────────────────────────────────────
case 0x000: NOP(); break;
case 0x001: SPDR(); break;
case 0x002: MMODE(); break;
case 0x003: INT(); break;
case 0x004: LRV(); break;
case 0x005: FSR(); break;
case 0x006: FIR(); break;
case 0x007: FZR(); break;
case 0x008: LSR(); break;
case 0x009: FVR(); break;
// ── Memory ──────────────────────────────────────
case 0x00A: MOV(); break;
case 0x00B: MOR(); break;
case 0x00C: AMOV(); break;
case 0x00D: SWP(); break;
case 0x00E: AHM(); break;
// ── Integer ─────────────────────────────────────
case 0x010: COM(); break;
case 0x011: NEG(); break;
case 0x012: EXS(); break;
case 0x013: INC(); break;
case 0x014: DEC(); break;
case 0x015: ADD(); break;
case 0x016: SUB(); break;
case 0x017: MUL(); break;
case 0x018: UMUL(); break;
case 0x019: DIV(); break;
case 0x01A: UDIV(); break;
case 0x01B: MOD(); break;
case 0x01C: UMOD(); break;
case 0x01D: DMOD(); break;
case 0x01E: UDMD(); break;
// ── System ──────────────────────────────────────
case 0x01F: FBT(); break;
// ── Bit Wise ────────────────────────────────────
case 0x020: STB(); break;
case 0x021: CRB(); break;
case 0x022: TSB(); break;
case 0x023: BOOL(); break;
case 0x024: NOT(); break;
case 0x025: AND(); break;
case 0x026: OR(); break;
case 0x027: XOR(); break;
case 0x028: SHL(); break;
case 0x029: SHR(); break;
case 0x02A: SSR(); break;
case 0x02B: ROL(); break;
case 0x02C: ROR(); break;
case 0x02D: CNT(); break;
// ── Boolean ─────────────────────────────────────
case 0x030: EQ(); break;
case 0x031: NE(); break;
case 0x032: GT(); break;
case 0x033: GE(); break;
case 0x034: LT(); break;
case 0x035: LE(); break;
// ── Branch ──────────────────────────────────────
case 0x038: JMP(); break;
case 0x039: JEQ(); break;
case 0x03A: JNE(); break;
case 0x03B: JIF(); break;
case 0x03C: JMR(); break;
case 0x03D: JER(); break;
case 0x03E: JNR(); break;
case 0x03F: JIR(); break;
// ── System ──────────────────────────────────────
case 0x040: SFB(); break;
case 0x041: LFB(); break;
// ── Branch ──────────────────────────────────────
case 0x042: JUF(); break;
case 0x043: JUR(); break;
// ── Memory ──────────────────────────────────────
case 0x044: PUSH(); break;
case 0x045: POP(); break;
case 0x046: ALLOC(); break;
case 0x047: HFREE(); break;
// ── Branch ──────────────────────────────────────
case 0x04A: CALL(); break;
case 0x04B: RET(); break;
// ── System ──────────────────────────────────────
case 0x04C: EDI(); break;
case 0x04D: SHSS(); break;
// ── Floating Point ──────────────────────────────
case 0x050: FLI(); break;
case 0x051: FNEG(); break;
case 0x052: FADD(); break;
case 0x053: FSUB(); break;
case 0x054: FMUL(); break;
case 0x055: FDIV(); break;
case 0x056: FMOD(); break;
case 0x057: FDMOD(); break;
case 0x058: FEPS(); break;
case 0x059: FEEP(); break;
// ── Boolean ─────────────────────────────────────
case 0x05A: FEQ(); break;
case 0x05B: FNE(); break;
case 0x05C: FGT(); break;
case 0x05D: FGE(); break;
case 0x05E: FLT(); break;
case 0x05F: FLE(); break;
// ── Casts ───────────────────────────────────────
case 0x060: F2D(); break;
case 0x061: D2F(); break;
case 0x062: I2F(); break;
case 0x063: I2D(); break;
case 0x064: L2F(); break;
case 0x065: L2D(); break;
case 0x066: F2I(); break;
case 0x067: F2L(); break;
case 0x068: D2I(); break;
case 0x069: D2L(); break;
// ── Trigonometric ───────────────────────────────
case 0x06C: SIN(); break;
case 0x06D: COS(); break;
case 0x06E: TAN(); break;
case 0x06F: ASIN(); break;
case 0x070: ACOS(); break;
case 0x071: ATAN(); break;
case 0x072: ATAN2(); break;
// ── Exponential ─────────────────────────────────
case 0x074: EXP(); break;
case 0x075: LOG(); break;
case 0x076: LOGAB(); break;
case 0x077: POW(); break;
case 0x078: SQRT(); break;
case 0x079: ROOT(); break;
// ── Integer ─────────────────────────────────────
case 0x07C: ADC(); break;
case 0x07D: SWC(); break;
case 0x07E: MWO(); break;
case 0x07F: UMO(); break;
// ── Matrix ──────────────────────────────────────
case 0x080: MADD(); break;
case 0x081: MSUB(); break;
case 0x082: MMUL(); break;
case 0x083: MINV(); break;
case 0x084: MTRA(); break;
case 0x085: MDET(); break;
// ── Quaternion ──────────────────────────────────
case 0x086: QMKA(); break;
case 0x087: QMUL(); break;
// ── SIMD ────────────────────────────────────────
case 0x08A: XADD(); break;
case 0x08B: XSUB(); break;
case 0x08C: XAMA(); break;
case 0x08D: XMUL(); break;
case 0x08E: XDIV(); break;
// ── Easter Eggs ─────────────────────────────────
case 0x0F0: UPY(); break;
default:
break;
}
}
} // namespace spider

View File

@@ -1,9 +0,0 @@
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
void CPU::NOP() {
// No Operation //
}
}

View File

@@ -0,0 +1,356 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
void CPU::NOP() {
// TODO: Implement NOP
}
void CPU::SPDR() {
// TODO: Implement SPDR
}
void CPU::MMODE() {
// TODO: Implement MMODE
}
void CPU::INT() {
// TODO: Implement INT
}
void CPU::LRV() {
// TODO: Implement LRV
}
void CPU::FSR() {
// TODO: Implement FSR
}
void CPU::FIR() {
// TODO: Implement FIR
}
void CPU::FZR() {
// TODO: Implement FZR
}
void CPU::LSR() {
// TODO: Implement LSR
}
void CPU::FVR() {
// TODO: Implement FVR
}
void CPU::MOV() {
// TODO: Implement MOV
}
void CPU::MOR() {
// TODO: Implement MOR
}
void CPU::AMOV() {
// TODO: Implement AMOV
}
void CPU::SWP() {
// TODO: Implement SWP
}
void CPU::AHM() {
// TODO: Implement AHM
}
void CPU::COM() {
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 = ~_dst->_u8;
break;
case 0b01: //short
_dst->_u16 = ~_dst->_u16;
break;
case 0b10: //int
_dst->_u32 = ~_dst->_u32;
break;
case 0b11: //long
_dst->_u64 = ~_dst->_u64;
break;
}
(this->*_post)();
}
void CPU::NEG() {
// TODO: Implement NEG
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 = 1 + ~_dst->_u8;
break;
case 0b01: //short
_dst->_u16 = 1+ ~_dst->_u16;
break;
case 0b10: //int
_dst->_u32 = 1 + ~_dst->_u32;
break;
case 0b11: //long
_dst->_u64 = 1 + ~_dst->_u64;
break;
}
(this->*_post)();
}
void CPU::EXS() { // THIS IS INCORRECT!!!
// TODO: Implement EXS
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_i16 = static_cast<i16>(_dst->_i8);
break;
case 0b01: //short
_dst->_i32 = static_cast<i32>(_dst->_i16);
break;
case 0b10: //int
_dst->_i64 = static_cast<i64>(_dst->_i32);
break;
case 0b11: //long
_dst->_i64 = _dst->_i64;
break;
}
_dst->_u32 = _dst->_u8;
(this->*_post)();
}
void CPU::INC() {
// TODO: Implement INC
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 += 1;
case 0b01: //short
_dst->_u16 += 1;
case 0b10: //int
_dst->_u32 += 1;
case 0b11: //long
_dst->_u64 += 1;
}
(this->*_post)();
}
void CPU::DEC() {
// TODO: Implement DEC
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 -= 1;
case 0b01: //short
_dst->_u16 -= 1;
case 0b10: //int
_dst->_u32 -= 1;
case 0b11: //long
_dst->_u64 -= 1;
}
(this->*_post)();
}
void CPU::ADD() {
// TODO: Implement ADD
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 += _src->_u8;
case 0b01: //short
_dst->_u16 += _src->_u16;
case 0b10: //int
_dst->_u32 += _src->_u32;
case 0b11: //long
_dst->_u64 += _src->_u64;
}
(this->*_post)();
}
void CPU::SUB() {
// TODO: Implement SUB
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 -= _src->_u8;
case 0b01: //short
_dst->_u16 -= _src->_u16;
case 0b10: //int
_dst->_u32 -= _src->_u32;
case 0b11: //long
_dst->_u64 -= _src->_u64;
}
(this->*_post)();
}
void CPU::MUL() {
// TODO: Implement MUL
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_i8 = _src->_i8 * _dst->_i8;
case 0b01: //short
_dst->_i16 = _src->_i16 * _dst->_i16;
case 0b10: //int
_dst->_i32 = _src->_i32 * _dst->_i32;
case 0b11: //long
_dst->_i64 = _src->_i64 * _dst->_i64;
}
(this->*_post)();
}
void CPU::UMUL() {
// TODO: Implement UMUL
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 = _src->_u8 * _dst->_u8;
case 0b01: //short
_dst->_u16 = _src->_u16 * _dst->_u16;
case 0b10: //int
_dst->_u32 = _src->_u32 * _dst->_u32;
case 0b11: //long
_dst->_u64 = _src->_u64 * _dst->_u64;
}
(this->*_post)();
}
void CPU::DIV() {
// TODO: Implement DIV
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_i8 = _dst->_i8 / _src->_i8;
case 0b01: //short
_dst->_i16 = _dst->_i16 / _src->_i16;
case 0b10: //int
_dst->_i32 = _dst->_i32 / _src->_i32;
case 0b11: //long
_dst->_i64 = _dst->_i64 / _src->_i64;
}
(this->*_post)();
}
void CPU::UDIV() {
// TODO: Implement UDIV
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 = _dst->_u8 / _src->_u8;
case 0b01: //short
_dst->_u16 = _dst->_u16 / _src->_u16;
case 0b10: //int
_dst->_u32 = _dst->_u32 / _src->_u32;
case 0b11: //long
_dst->_u64 = _dst->_u64 / _src->_u64;
}
(this->*_post)();
}
void CPU::MOD() {
// TODO: Implement MOD
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_i8 = _dst->_i8 % _src->_i8;
case 0b01: //short
_dst->_i16 = _dst->_i16 % _src->_i16;
case 0b10: //int
_dst->_i32 = _dst->_i32 % _src->_i32;
case 0b11: //long
_dst->_i64 = _dst->_i64 % _src->_i64;
}
(this->*_post)();
}
void CPU::UMOD() {
// TODO: Implement UMOD
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 = _dst->_u8 % _src->_u8;
case 0b01: //short
_dst->_u16 = _dst->_u16 % _src->_u16;
case 0b10: //int
_dst->_u32 = _dst->_u32 % _src->_u32;
case 0b11: //long
_dst->_u64 = _dst->_u64 % _src->_u64;
}
(this->*_post)();
}
void CPU::DMOD() {
// TODO: Implement DMOD
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
RX._i8 = _dst->_i8 / _src->_i8;
RY._i8 = _dst->_i8 % _src->_i8;
case 0b01: //short
RX._i16 = _dst->_i16 / _src->_i16;
RY._i16 = _dst->_i16 % _src->_i16;
case 0b10: //int
RX._i32 = _dst->_i32 / _src->_i32;
RY._i32 = _dst->_i32 % _src->_i32;
case 0b11: //long
RX._i64 = _dst->_i64 / _src->_i64;
RY._i64 = _dst->_i64 % _src->_i64;
}
(this->*_post)();
}
void CPU::UDMD() {
// TODO: Implement UDMD
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
RX._u8 = _dst->_u8 / _src->_u8;
RY._u8 = _dst->_u8 % _src->_u8;
case 0b01: //short
RX._u16 = _dst->_u16 / _src->_u16;
RY._u16 = _dst->_u16 % _src->_u16;
case 0b10: //int
RX._u32 = _dst->_u32 / _src->_u32;
RY._u32 = _dst->_u32 % _src->_u32;
case 0b11: //long
RX._u64 = _dst->_u64 / _src->_u64;
RY._u64 = _dst->_u64 % _src->_u64;
}
(this->*_post)();
}
void CPU::FBT() {
// TODO: Implement FBT
fetchOperDst();
switch(_size){
case 0b00: //byte
RF = (RF & ~(0x3 << 9)) | ((_dst->_u8 >> 9) & 0x3) << 9;
case 0b01: //short
RF = (RF & ~(0x3 << 9)) | ((_dst->_u16 >> 9) & 0x3) << 9;
case 0b10: //int
RF = (RF & ~(0x3 << 9)) | ((_dst->_u32 >> 9) & 0x3) << 9;
case 0b11: //long
RF = (RF & ~(0x3 << 9)) | ((_dst->_u64 >> 9) & 0x3) << 9;
}
(this->*_post)();
}
}

View File

@@ -0,0 +1,197 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
void CPU::STB() {
// TODO: Implement STB
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 |= (1 << _src->_u8);
case 0b01: //short
_dst->_u16 |= (1 << _src->_u16);
case 0b10: //int
_dst->_u32 |= (1 << _src->_u32);
case 0b11: //long
_dst->_u64 |= (1 << _src->_u64);
}
(this->*_post)();
}
void CPU::CRB() {
// TODO: Implement CRB
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 &= ~(1 << _src->_u8);
case 0b01: //short
_dst->_u16 &= ~(1 << _src->_u16);
case 0b10: //int
_dst->_u32 &= ~(1 << _src->_u32);
case 0b11: //long
_dst->_u64 &= ~(1 << _src->_u64);
}
(this->*_post)();
}
void CPU::TSB() {
// TODO: Implement TSB
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
switch (((RF >> _src->_u8) & 1) != ((_dst->_u8 >> _src->_u8) & 1)){
case 1:
RF |= (1 << _src->_u8);
case 0:
RF &= ~(1 << _src->_u8);
}
case 0b01: //short
switch (((RF >> _src->_u16) & 1) != ((_dst->_u16 >> _src->_u16) & 1)){
case 1:
RF |= (1 << _src->_u16);
case 0:
RF &= ~(1 << _src->_u16);
}
case 0b10: //int
switch (((RF >> _src->_u32) & 1) != ((_dst->_u32 >> _src->_u32) & 1)){
case 1:
RF |= (1 << _src->_u32);
case 0:
RF &= ~(1 << _src->_u32);
}
case 0b11: //long
switch (((RF >> _src->_u64) & 1) != ((_dst->_u64 >> _src->_u64) & 1)){
case 1:
RF |= (1 << _src->_u64);
case 0:
RF &= ~(1 << _src->_u64);
}
}
(this->*_post)();
}
void CPU::BOOL() {
// TODO: Implement BOOL
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 = _dst != 0;
case 0b01: //short
_dst->_u16 = _dst != 0;
case 0b10: //int
_dst->_u32 = _dst != 0;
case 0b11: //long
_dst->_u64 = _dst != 0;
}
(this->*_post)();
}
void CPU::NOT() {
// TODO: Implement NOT
}
void CPU::AND() {
// TODO: Implement AND
}
void CPU::OR() {
// TODO: Implement OR
}
void CPU::XOR() {
// TODO: Implement XOR
}
void CPU::SHL() {
// TODO: Implement SHL
}
void CPU::SHR() {
// TODO: Implement SHR
}
void CPU::SSR() {
// TODO: Implement SSR
}
void CPU::ROL() {
// TODO: Implement ROL
}
void CPU::ROR() {
// TODO: Implement ROR
}
void CPU::CNT() {
// TODO: Implement CNT
}
void CPU::EQ() {
// TODO: Implement EQ
}
void CPU::NE() {
// TODO: Implement NE
}
void CPU::GT() {
// TODO: Implement GT
}
void CPU::GE() {
// TODO: Implement GE
}
void CPU::LT() {
// TODO: Implement LT
}
void CPU::LE() {
// TODO: Implement LE
}
void CPU::JMP() {
// TODO: Implement JMP
}
void CPU::JEQ() {
// TODO: Implement JEQ
}
void CPU::JNE() {
// TODO: Implement JNE
}
void CPU::JIF() {
// TODO: Implement JIF
}
void CPU::JMR() {
// TODO: Implement JMR
}
void CPU::JER() {
// TODO: Implement JER
}
void CPU::JNR() {
// TODO: Implement JNR
}
void CPU::JIR() {
// TODO: Implement JIR
}
}

View File

@@ -0,0 +1,279 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
#include <cmath> // provides std::fmod, std::fma and cast support
namespace spider {
void CPU::SFB() {
// TODO: Implement SFB
}
void CPU::LFB() {
// TODO: Implement LFB
}
void CPU::JUF() {
// TODO: Implement JUF
}
void CPU::JUR() {
// TODO: Implement JUR
}
void CPU::PUSH() {
// TODO: Implement PUSH
}
void CPU::POP() {
// TODO: Implement POP
}
void CPU::ALLOC() {
// TODO: Implement ALLOC
}
void CPU::HFREE() {
// TODO: Implement HFREE
}
void CPU::CALL() {
// TODO: Implement CALL
}
void CPU::RET() {
// TODO: Implement RET
}
void CPU::EDI() {
// TODO: Implement EDI
}
void CPU::SHSS() {
// TODO: Implement SHSS
}
void CPU::FLI() {
// TODO: Implement FLI
}
void CPU::FNEG() {
// TODO: Implement FNEG
}
void CPU::FADD() {
// TODO: Implement FADD
}
void CPU::FSUB() {
// TODO: Implement FSUB
}
// ── 0x054 — FMUL: Float Multiplication ───────────────────────────────────
void CPU::FMUL() {
fetchOperSrc();
fetchOperDst();
switch (_size) {
case 0b10: _dst->_f32 *= _src->_f32; break; // f32
case 0b11: _dst->_f64 *= _src->_f64; break; // f64
default: break; // invalid size
}
(this->*_post)();
}
// ── 0x055 — FDIV: Float Division ─────────────────────────────────────────
void CPU::FDIV() {
fetchOperSrc();
fetchOperDst();
switch (_size) {
case 0b10: _dst->_f32 /= _src->_f32; break;
case 0b11: _dst->_f64 /= _src->_f64; break;
default: break;
}
(this->*_post)();
}
// ── 0x056 — FMOD: Float Modulus ──────────────────────────────────────────
// C++ has no % for floats — std::fmod performs the equivalent operation
void CPU::FMOD() {
fetchOperSrc();
fetchOperDst();
switch (_size) {
case 0b10: _dst->_f32 = std::fmod(_dst->_f32, _src->_f32); break;
case 0b11: _dst->_f64 = std::fmod(_dst->_f64, _src->_f64); break;
default: break;
}
(this->*_post)();
}
// ── 0x057 — FDMOD: Float Division and Modulus ────────────────────────────
// dst / src = RX (quotient) * src + RY (remainder)
void CPU::FDMOD() {
fetchOperSrc();
fetchOperDst();
switch (_size) {
case 0b10: {
f32 q = static_cast<f32>(static_cast<i32>(_dst->_f32 / _src->_f32));
f32 r = _dst->_f32 - (q * _src->_f32);
RX._f32 = q;
RY._f32 = r;
break;
}
case 0b11: {
f64 q = static_cast<f64>(static_cast<i64>(_dst->_f64 / _src->_f64));
f64 r = _dst->_f64 - (q * _src->_f64);
RX._f64 = q;
RY._f64 = r;
break;
}
default: break;
}
(this->*_post)();
}
// ── 0x058 — FEPS: Set Float Epsilon Value ────────────────────────────────
// Loads the epsilon value into RN (the epsilon register)
void CPU::FEPS() {
fetchOperDst();
switch (_size) {
case 0b10: RN = _dst->_u32; break; // store f32 bits in RN
case 0b11: RN = _dst->_u64; break; // store f64 bits in RN
default: break;
}
(this->*_post)();
}
// ── 0x059 — FEEP: Float Enable/Disable Epsilon ───────────────────────────
// Bit 12 of RF is the Epsilon Enable flag
void CPU::FEEP() {
fetchOperDst();
constexpr u64 EPSILON_ENABLE_BIT = (1ULL << 12);
if (_dst->_u64) RF |= EPSILON_ENABLE_BIT; // non-zero → enable
else RF &= ~EPSILON_ENABLE_BIT; // zero → disable
(this->*_post)();
}
// ── 0x05A — FEQ: Float Equal ──────────────────────────────────────────────
// Sets bit 10 (Zero/Equal flag) in RF if dst == src
void CPU::FEQ() {
fetchOperSrc();
fetchOperDst();
constexpr u64 ZERO_FLAG = (1ULL << 10);
bool equal = false;
switch (_size) {
case 0b10: equal = (_dst->_f32 == _src->_f32); break;
case 0b11: equal = (_dst->_f64 == _src->_f64); break;
default: break;
}
if (equal) RF |= ZERO_FLAG;
else RF &= ~ZERO_FLAG;
(this->*_post)();
}
// ── 0x05B — FNE: Float Not Equal ─────────────────────────────────────────
void CPU::FNE() {
fetchOperSrc();
fetchOperDst();
constexpr u64 ZERO_FLAG = (1ULL << 10);
bool notEqual = false;
switch (_size) {
case 0b10: notEqual = (_dst->_f32 != _src->_f32); break;
case 0b11: notEqual = (_dst->_f64 != _src->_f64); break;
default: break;
}
if (notEqual) RF |= ZERO_FLAG;
else RF &= ~ZERO_FLAG;
(this->*_post)();
}
// ── 0x05C — FGT: Float Greater Than ──────────────────────────────────────
// Sets/clears bit 9 (Negative flag) in RF
void CPU::FGT() {
fetchOperSrc();
fetchOperDst();
constexpr u64 NEGATIVE_FLAG = (1ULL << 9);
bool gt = false;
switch (_size) {
case 0b10: gt = (_dst->_f32 > _src->_f32); break;
case 0b11: gt = (_dst->_f64 > _src->_f64); break;
default: break;
}
if (gt) RF &= ~NEGATIVE_FLAG;
else RF |= NEGATIVE_FLAG;
(this->*_post)();
}
// ── 0x05D — FGE: Float Greater or Equal ──────────────────────────────────
void CPU::FGE() {
fetchOperSrc();
fetchOperDst();
constexpr u64 NEGATIVE_FLAG = (1ULL << 9);
constexpr u64 ZERO_FLAG = (1ULL << 10);
bool ge = false;
bool eq = false;
switch (_size) {
case 0b10:
ge = (_dst->_f32 >= _src->_f32);
eq = (_dst->_f32 == _src->_f32);
break;
case 0b11:
ge = (_dst->_f64 >= _src->_f64);
eq = (_dst->_f64 == _src->_f64);
break;
default: break;
}
if (ge) RF &= ~NEGATIVE_FLAG;
else RF |= NEGATIVE_FLAG;
if (eq) RF |= ZERO_FLAG;
else RF &= ~ZERO_FLAG;
(this->*_post)();
}
// ── 0x05E — FLT: Float Lower Than ────────────────────────────────────────
void CPU::FLT() {
fetchOperSrc();
fetchOperDst();
constexpr u64 NEGATIVE_FLAG = (1ULL << 9);
bool lt = false;
switch (_size) {
case 0b10: lt = (_dst->_f32 < _src->_f32); break;
case 0b11: lt = (_dst->_f64 < _src->_f64); break;
default: break;
}
if (lt) RF |= NEGATIVE_FLAG;
else RF &= ~NEGATIVE_FLAG;
(this->*_post)();
}
// ── 0x05F — FLE: Float Lower or Equal ────────────────────────────────────
void CPU::FLE() {
fetchOperSrc();
fetchOperDst();
constexpr u64 NEGATIVE_FLAG = (1ULL << 9);
constexpr u64 ZERO_FLAG = (1ULL << 10);
bool le = false;
bool eq = false;
switch (_size) {
case 0b10:
le = (_dst->_f32 <= _src->_f32);
eq = (_dst->_f32 == _src->_f32);
break;
case 0b11:
le = (_dst->_f64 <= _src->_f64);
eq = (_dst->_f64 == _src->_f64);
break;
default: break;
}
if (le) RF &= ~NEGATIVE_FLAG;
else RF |= NEGATIVE_FLAG;
if (eq) RF |= ZERO_FLAG;
else RF &= ~ZERO_FLAG;
(this->*_post)();
}
}

View File

@@ -0,0 +1,181 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
#include <cmath> // provides std::fmod, std::fma and cast support
namespace spider {
// ── 0x060 — F2D: Float (f32) to Double (f64) ─────────────────────────────
// Widening conversion — no precision is lost
void CPU::F2D() {
fetchOperDst();
_dst->_f64 = static_cast<f64>(_dst->_f32);
(this->*_post)();
}
// ── 0x061 — D2F: Double (f64) to Float (f32) ─────────────────────────────
// Narrowing conversion — precision may be lost
void CPU::D2F() {
fetchOperDst();
_dst->_f32 = static_cast<f32>(_dst->_f64);
(this->*_post)();
}
// ── 0x062 — I2F: Integer (i32) to Float (f32) ────────────────────────────
void CPU::I2F() {
fetchOperDst();
_dst->_f32 = static_cast<f32>(_dst->_u32);
(this->*_post)();
}
// ── 0x063 — I2D: Integer (i32) to Double (f64) ───────────────────────────
void CPU::I2D() {
fetchOperDst();
_dst->_f64 = static_cast<f64>(_dst->_u32);
(this->*_post)();
}
// ── 0x064 — L2F: Long (i64) to Float (f32) ───────────────────────────────
void CPU::L2F() {
fetchOperDst();
_dst->_f32 = static_cast<f32>(_dst->_u64);
(this->*_post)();
}
// ── 0x065 — L2D: Long (i64) to Double (f64) ──────────────────────────────
void CPU::L2D() {
fetchOperDst();
_dst->_f64 = static_cast<f64>(_dst->_u64);
(this->*_post)();
}
// ── 0x066 — F2I: Float (f32) to Integer (i32) ────────────────────────────
// Truncates toward zero
void CPU::F2I() {
fetchOperDst();
_dst->_u32 = static_cast<u32>(_dst->_f32);
(this->*_post)();
}
// ── 0x067 — F2L: Float (f32) to Long (i64) ───────────────────────────────
// Truncates toward zero
void CPU::F2L() {
fetchOperDst();
_dst->_u64 = static_cast<u64>(_dst->_f32);
(this->*_post)();
}
void CPU::D2I() {
fetchOperDst();
_dst->_u32 = static_cast<u32>(_dst->_f64);
(this->*_post)();
}
void CPU::D2L() {
fetchOperDst();
_dst->_u64 = static_cast<u64>(_dst->_f64);
(this->*_post)();
}
void CPU::SIN() {
fetchOperDst();
_dst->_f64 = std::sin(_dst->_f64);
(this->*_post)();
}
void CPU::COS() {
fetchOperDst();
_dst->_f64 = std::cos(_dst->_f64);
(this->*_post)();
}
void CPU::TAN() {
fetchOperDst();
_dst->_f64 = std::tan(_dst->_f64);
(this->*_post)();
}
void CPU::ASIN() {
fetchOperDst();
_dst->_f64 = std::asin(_dst->_f64);
(this->*_post)();
}
void CPU::ACOS() {
fetchOperDst();
_dst->_f64 = std::acos(_dst->_f64);
(this->*_post)();
}
void CPU::ATAN() {
fetchOperDst();
_dst->_f64 = std::atan(_dst->_f64);
(this->*_post)();
}
void CPU::ATAN2() {
fetchOperDst();
fetchOperSrc();
_dst->_f64 = std::atan2(_dst->_f64, _src->_f64);
(this->*_post)();
}
void CPU::EXP() {
fetchOperDst();
_dst->_f64 = std::exp(_dst->_f64);
(this->*_post)();
}
void CPU::LOG() {
fetchOperDst();
_dst->_f64 = std::log(_dst->_f64);
(this->*_post)();
}
void CPU::LOGAB() {
fetchOperDst();
fetchOperSrc();
_dst->_f64 = std::log(_dst->_f64) / std::log(_src->_f64);
(this->*_post)();
}
void CPU::POW() {
fetchOperDst();
fetchOperSrc();
_dst->_f64 = std::pow(_dst->_f64, _src->_f64);
(this->*_post)();
}
void CPU::SQRT() {
fetchOperDst();
_dst->_f64 = std::sqrt(_dst->_f64);
(this->*_post)();
}
void CPU::ROOT() {
fetchOperDst();
fetchOperSrc();
_dst->_f64 = std::pow(_dst->_f64, 1.0 / _src->_f64);
}
void CPU::ADC() {
// TODO: Implement ADC
}
void CPU::SWC() {
// TODO: Implement SWC
}
void CPU::MWO() {
// TODO: Implement MWO
}
void CPU::UMO() {
// TODO: Implement UMO
}
}

View File

@@ -0,0 +1,62 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
void CPU::MADD() {
// TODO: Implement MADD
}
void CPU::MSUB() {
// TODO: Implement MSUB
}
void CPU::MMUL() {
// TODO: Implement MMUL
}
void CPU::MINV() {
// TODO: Implement MINV
}
void CPU::MTRA() {
// TODO: Implement MTRA
}
void CPU::MDET() {
// TODO: Implement MDET
}
void CPU::QMKA() {
// TODO: Implement QMKA
}
void CPU::QMUL() {
// TODO: Implement QMUL
}
void CPU::XADD() {
// TODO: Implement XADD
}
void CPU::XSUB() {
// TODO: Implement XSUB
}
void CPU::XAMA() {
// TODO: Implement XAMA
}
void CPU::XMUL() {
// TODO: Implement XMUL
}
void CPU::XDIV() {
// TODO: Implement XDIV
}
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,14 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
void CPU::UPY() {
// TODO: Implement UPY
}
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,105 @@
#include "Matrix.hpp"
#include <immintrin.h>
#include <type_traits>
#include <algorithm>
#include <cstring>
/*
namespace spider {
template<typename T>
void matrix_fill(T diag, Matrix<T> mat) {
for (isize i = 0; i < mat.rows; i++) {
for (isize j = 0; j < mat.cols; j++) {
m.data[i + j * mat.rows] = i == j ? diag : T(0);
}
}
}
template<typename T>
void matrix_mult(Matrix<T> m1, Matrix<T> m2, Matrix<T> mr) {
// natural constrains of matrix multiplication
if (m1.rows != mr.rows) return;
if (m2.cols != mr.cols) return;
if (m1.cols != m2.rows) return;
// fill result with zeroes
std::fill(mr.data, mr.data + mr.rows * mr.cols, T(0));
// Begin Loop
for (isize j = 0; j < mr.cols; j++) { // P
for (isize n = 0; n < m1.cols; n++) { // N
const T val_m2 = m2.data[n + j * m2.rows] * diag;
isize i = 0;
#if defined(__AVX__)
if constexpr (std::is_same_v<T, float>) {
const __m256 v_m2 = _mm256_set1_ps(val_m2);
for (; i <= mr.rows - 8; i += 8) {
__m256 v_m1 = _mm256_loadu_ps(&m1.data[i + n * m1.rows]);
__m256 v_mr = _mm256_loadu_ps(&mr.data[i + j * mr.rows]);
v_mr = _mm256_fmadd_ps(v_m1, v_m2, v_mr);
_mm256_storeu_ps(&mr.data[i + j * mr.rows], v_mr);
}
if (i < mr.rows) {
float buf_m1[8] = { 0 }, buf_mr[8] = { 0 };
isize rem = mr.rows - i;
std::memcpy(buf_m1, &m1.data[i + n * m1.rows], rem * sizeof(T));
std::memcpy(buf_mr, &mr.data[i + j * mr.rows], rem * sizeof(T));
_mm256_storeu_ps(buf_mr, _mm256_fmadd_ps(_mm256_loadu_ps(buf_m1), v_m2, _mm256_loadu_ps(buf_mr)));
std::memcpy(&mr.data[i + j * mr.rows], buf_mr, rem * sizeof(T));
}
}
else if constexpr (std::is_same_v<T, double>) {
const __m256d v_m2 = _mm256_set1_pd(val_m2);
for (; i <= mr.rows - 4; i += 4) {
__m256d v_m1 = _mm256_loadu_pd(&m1.data[i + n * m1.rows]);
__m256d v_mr = _mm256_loadu_pd(&mr.data[i + j * mr.rows]);
v_mr = _mm256_fmadd_pd(v_m1, v_m2, v_mr);
_mm256_storeu_pd(&mr.data[i + j * mr.rows], v_mr);
}
if (i < mr.rows) {
double buf_m1[4] = { 0 }, buf_mr[4] = { 0 };
isize rem = mr.rows - i;
std::memcpy(buf_m1, &m1.data[i + n * m1.rows], rem * sizeof(T));
std::memcpy(buf_mr, &mr.data[i + j * mr.rows], rem * sizeof(T));
_mm256_storeu_pd(buf_mr, _mm256_fmadd_pd(_mm256_loadu_pd(buf_m1), v_m2, _mm256_loadu_pd(buf_mr)));
std::memcpy(&mr.data[i + j * mr.rows], buf_mr, rem * sizeof(T));
}
}
else
#elif defined(__SSE2__)
if constexpr (std::is_same_v<T, float>) {
const __m128 v_m2 = _mm_set1_ps(val_m2);
for (; i <= mr.rows - 4; i += 4) {
__m128 v_m1 = _mm_loadu_ps(&m1.data[i + n * m1.rows]);
__m128 v_mr = _mm_loadu_ps(&mr.data[i + j * mr.rows]);
v_mr = _mm_add_ps(v_mr, _mm_mul_ps(v_m1, v_m2));
_mm_storeu_ps(&mr.data[i + j * mr.rows], v_mr);
}
// Tail buffer logic omitted for brevity, same as float AVX but with size 4
}
else if constexpr (std::is_same_v<T, double>) {
const __m128d v_m2 = _mm_set1_pd(val_m2);
for (; i <= mr.rows - 2; i += 2) {
__m128d v_m1 = _mm_loadu_pd(&m1.data[i + n * m1.rows]);
__m128d v_mr = _mm_loadu_pd(&mr.data[i + j * mr.rows]);
v_mr = _mm_add_pd(v_mr, _mm_mul_pd(v_m1, v_m2));
_mm_storeu_pd(&mr.data[i + j * mr.rows], v_mr);
}
}
else
#endif
{
// Fallback for non-SIMD or unsupported types
for (; i < mr.rows; i++) {
mr.data[i + j * mr.rows] += m1.data[i + n * m1.rows] * val_m2;
}
}
}
}
}
}
*/

View File

@@ -0,0 +1,31 @@
#pragma once
#include <spider/runtime/common.hpp>
/*
namespace spider {
template<typename T>
struct Matrix {
T* data;
isize rows, cols;
};
void matrix_fill(f32 diag, Matrix<f32> mat);
void matrix_fill(f64 diag, Matrix<f64> mat);
Matrix<f32> matrix_mul(Matrix<f32> m1, Matrix<f32> m2);
Matrix<f64> matrix_mul(Matrix<f64> m1, Matrix<f64> m2);
Matrix<f32> matrix_inv(Matrix<f32> mat);
Matrix<f64> matrix_inv(Matrix<f64> mat);
f32 matrix_det(Matrix<f32> mat);
f64 matrix_det(Matrix<f64> mat);
}
*/

View File

@@ -0,0 +1,109 @@
#include <iostream>
/*
template<typename T, int Rows, int Cols>
struct Matrix {
T data[Rows][Cols];
void setZero() {
for (int i = 0; i < Rows; i++) {
for (int j = 0; j < Cols; j++) {
data[i][j] = T();
}
}
}
};
template<typename T, int M, int N, int P>
Matrix<T, M, P> mat_multiply(Matrix<T, M, N> A, Matrix<T, N, P> B) {
//Determination of resulting matrix size
// COMPILE-TIME calculation (using constexpr)
constexpr int RSize = (M > P) ? M : P;
// COMPILE-TIME square size calculation
constexpr int CSize = (RSize <= 4) ? 4 :
(RSize % 4 == 0) ? RSize :
4 * (RSize / 4 + 1);
// SIMD width selection
int simd_width;
if (RSize > 8) {
simd_width = 8;
}
else if (RSize > 4 && RSize < 8){
simd_width = 4;
}
else {
simd_width = RSize;
}
// Create result square matrix with size CSize(optimization)
Matrix<T, CSize, CSize> tempResult;
tempResult.setZero();
// Matrix multiplication with SIMD-style unrolling
for (int i = 0; i < M; i++) { // For each row in A
for (int k = 0; k < N; k++) { // For each inner dimension
T a_val = A.data[i][k];
// Process columns in chunks of simd_width
int j = 0;
while (j < P) {
int remaining = P - j;
if (remaining >= simd_width) {
// Full SIMD operation - unrolled loops
if (simd_width == 8) {
tempResult.data[i][j] += a_val * B.data[k][j];
tempResult.data[i][j+1] += a_val * B.data[k][j+1];
tempResult.data[i][j+2] += a_val * B.data[k][j+2];
tempResult.data[i][j+3] += a_val * B.data[k][j+3];
tempResult.data[i][j+4] += a_val * B.data[k][j+4];
tempResult.data[i][j+5] += a_val * B.data[k][j+5];
tempResult.data[i][j+6] += a_val * B.data[k][j+6];
tempResult.data[i][j+7] += a_val * B.data[k][j+7];
}
else if (simd_width == 4) {
tempResult.data[i][j] += a_val * B.data[k][j];
tempResult.data[i][j+1] += a_val * B.data[k][j+1];
tempResult.data[i][j+2] += a_val * B.data[k][j+2];
tempResult.data[i][j+3] += a_val * B.data[k][j+3];
}
else if (simd_width == 3) {
tempResult.data[i][j] += a_val * B.data[k][j];
tempResult.data[i][j+1] += a_val * B.data[k][j+1];
tempResult.data[i][j+2] += a_val * B.data[k][j+2];
}
else if (simd_width == 2) {
tempResult.data[i][j] += a_val * B.data[k][j];
tempResult.data[i][j+1] += a_val * B.data[k][j+1];
}
else { // simd_width == 1
tempResult.data[i][j] += a_val * B.data[k][j];
}
j += simd_width;
}
else {
// Handle remaining columns that don't fit in SIMD width
for (int s = 0; s < remaining; s++) {
tempResult.data[i][j + s] += a_val * B.data[k][j + s];
}
j += remaining;
}
}
}
}
// Extract the actual result (M x P) from the temporary square matrix
Matrix<T, M, P> result;
for (int i = 0; i < M; i++) {
for (int j = 0; j < P; j++) {
result.data[i][j] = tempResult.data[i][j];
}
}
return result;
}
*/

View File

@@ -0,0 +1,59 @@
#include "Quat.hpp"
#include <iostream>
namespace spider {
/**
* Multiplies two quaternions together.
* General case, use it when no optimizations exist.
*/
template<typename T>
inline Quat<T> quat_mul_gnrl(Quat<T> A, Quat<T> B) {
return {
B.w * A.w - B.x * A.x - B.y * A.y - B.z * A.z,
B.w * A.x + B.x * A.w - B.y * A.z + B.z * A.y,
B.w * A.y + B.x * A.z + B.y * A.w - B.z * A.x,
B.w * A.z - B.x * A.y + B.y * A.x + B.z * A.w
};
}
/**
* Multiplies two quaternions together.
* Attempts to use SIMD instructions when available.
*/
template<typename T>
inline Quat<T> quat_mul_smart(Quat<T> A, Quat<T> B) {
}
Quat<f32> quat_mul(Quat<f32> q1, Quat<f32> q2) {
return quat_mul_gnrl<f32>(q1, q2);
}
//void quat_mat(Quat<f32> quat, f32* mat) {
// // TODO
//}
Quat<f64> quat_mul(Quat<f64> q1, Quat<f64> q2) {
return quat_mul_gnrl<f64>(q1, q2);
}
//void quat_mat(Quat<f64> q1, f64* mat) {
// // TODO
//}
/*
int quatMain() {
Quat<double> q1 = { 1.0f, 0.0f, 0.0f, 0.0f };
Quat<double> q2 = { 0.5f, 0.5f, 0.5f, 0.5f };
Quat<double> result = quat_multiply(q1, q2); // Returns the result!
std::cout << "Result: ("
<< result.w << ", "
<< result.x << ", "
<< result.y << ", "
<< result.z << ")" << std::endl;
return 0;
}
*/
}

View File

@@ -0,0 +1,56 @@
#pragma once
#include <spider/runtime/common.hpp>
namespace spider {
template<typename T>
struct Quat {
T w, x, y, z;
};
/**
* Creates a quaternion from Euler Angles.
*/
Quat<f32> quat_make_euler(f32 x, f32 y, f32 z);
/**
* Creates a quaternion from an axis and an angle.
*/
Quat<f32> quat_make_axis_angle(f32 angle, f32 x, f32 y, f32 z);
/**
* Creates a quaternion from Euler Angles.
*/
Quat<f64> quat_make_euler(f64 x, f64 y, f64 z);
/**
* Creates a quaternion from an axis and an angle.
*/
Quat<f64> quat_make_axis_angle(f64 angle, f64 x, f64 y, f64 z);
/**
* Multiples a quaternion with another quaternion.
* The result is output to the qr variable.
* This pointer can be the same as q1.
*/
Quat<f32> quat_mul(Quat<f32> q1, Quat<f32> q2);
/**
* Converts a quaternion to a matrix.
*/
void quat_mat(Quat<f32> quat, f32* mat);
/**
* Multiples a quaternion with another quaternion.
* The result is output to the qr variable.
* This pointer can be the same as q1.
*/
Quat<f64> quat_mul(Quat<f64> q1, Quat<f64> q2);
/**
* Converts a quaternion to a matrix.
*/
void quat_mat(Quat<f64> q1, f64* mat);
}

View File

@@ -0,0 +1,74 @@
#include "ByteArray.hpp"
#include <cstring>
namespace spider {
ByteArray::ByteArray(isize length) : _mem(nullptr), _size(length) {
if (_size > 0) {
_mem = new u8[_size];
std::memset(_mem, 0, _size);
}
}
ByteArray::ByteArray(const ByteArray& other) : _mem(new u8[other._size]), _size(other._size) {
std::copy(other._mem, other._mem + _size, _mem);
}
ByteArray::ByteArray(ByteArray&& other) noexcept : _mem(other._mem), _size(other._size) {
other._mem = nullptr;
other._size = 0;
}
ByteArray::~ByteArray() {
delete[] _mem;
}
ByteArray& ByteArray::operator=(const ByteArray& other) {
if (this == &other) return *this; // lock self
u8* new_mem = new u8[other._size];
std::copy(other._mem, other._mem + other._size, new_mem);
delete[] _mem;
_mem = new_mem;
_size = other._size;
return *this;
}
ByteArray& ByteArray::operator=(ByteArray&& other) noexcept {
if (this == &other) return *this; // lock self
delete[] _mem;
_mem = other._mem; // time to steal!
_size = other._size;
other._mem = nullptr; // leave as a husk
other._size = 0;
return *this;
}
u8& ByteArray::operator[](isize index) {
return _mem[index];
}
u8 ByteArray::operator[](isize index) const {
return _mem[index];
}
u8* ByteArray::data() {
return _mem;
}
const u8* ByteArray::data() const {
return _mem;
}
isize ByteArray::size() const {
return _size;
}
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include <spider/runtime/common.hpp>
namespace spider {
/**
* A general purpose byte array
* with RAII semantics.
*/
class ByteArray {
private:
u8* _mem;
isize _size;
public:
ByteArray(isize length);
ByteArray(const ByteArray& other);
ByteArray(ByteArray&& other) noexcept;
~ByteArray();
public:
ByteArray& operator=(const ByteArray& other);
ByteArray& operator=(ByteArray&& other) noexcept;
public:
u8& operator[](isize index);
u8 operator[](isize index) const;
public:
u8* data();
const u8* data() const;
isize size() const;
};
}

View File

@@ -1,5 +1,9 @@
#include "RAM.hpp"
#include <spider/runtime/cpu/Register.hpp>
#include <spider/runtime/memory/Types.hpp>
#include <cstring>
namespace spider {
@@ -72,6 +76,11 @@ namespace spider {
return (i < _size) ? _mem[i] : _oob;
}
void RAM::loadRegister(u64 i, u8 size_code, register_t* r) {
i = std::min(i, _size);
spider::loadRegister[size_code](r, _mem + i, _size - i);
}
// Misc //
void RAM::resize(u64 new_size) {
@@ -111,4 +120,20 @@ namespace spider {
return _size;
}
u8* RAM::begin() {
return this->_mem;
}
u8* RAM::end() {
return this->_mem + this->_size;
}
const u8* RAM::begin() const {
return this->_mem;
}
const u8* RAM::end() const {
return this->_mem + this->_size;
}
}

View File

@@ -2,6 +2,8 @@
#include <spider/runtime/common.hpp>
#include <spider/runtime/cpu/Register.hpp>
namespace spider {
/**
@@ -43,12 +45,24 @@ namespace spider {
u8 at(u64 i) const;
void loadRegister(u64 i, u8 size_code, register_t* r);
public:
void resize(u64 new_size);
u64 size() const;
public:
u8* begin();
u8* end();
const u8* begin() const;
const u8* end() const;
};
}

View File

@@ -0,0 +1,326 @@
#pragma once
#include <spider/runtime/common.hpp>
#include <spider/runtime/cpu/Register.hpp>
#include <spider/runtime/native/machine.hpp>
#if __cplusplus >= 202002L
#include <bit>
#endif
#if defined(SPIDER_COMPILER_MSVC)
#include <cstdlib>
#endif
#include <cstring>
namespace spider {
/*
* This file contains cross platform type juggling.
* Optimized for each case.
*
* General assumtions is that unsigned and signed
* integers are the exact same bit representation.
*
* Floats to and from integers is the focus when
* juggling.
*
* Additionally, provides help selecting a specific
* type from raw bytes.
*/
// Utilities //
#if __cplusplus >= 202002L
using std::bit_cast;
#else
template<typename To, typename From>
inline To bit_cast(const From& src) {
static_assert(sizeof(To) == sizeof(From), "bit_cast size mismatch");
To dst;
std::memcpy(&dst, &src, sizeof(To));
return dst;
}
#endif
template<typename T>
inline T byteswap(T v) {
static_assert(std::is_integral<T>::value, "byteswap requires integral type");
using U = std::make_unsigned_t<T>;
U u = static_cast<U>(v);
if constexpr (sizeof(T) == 1) {
return v;
} else if constexpr (sizeof(T) == 2) {
#if defined(SPIDER_COMPILER_MSVC)
u = _byteswap_ushort(u);
#elif defined(SPIDER_COMPILER_GCC_LIKE)
u = __builtin_bswap16(u);
#else
u = (u >> 8) | (u << 8);
#endif
} else if constexpr (sizeof(T) == 4) {
#if defined(SPIDER_COMPILER_MSVC)
u = _byteswap_ulong(u);
#elif defined(SPIDER_COMPILER_GCC_LIKE)
u = __builtin_bswap32(u);
#else
u =
((u & 0x000000FFu) << 24) |
((u & 0x0000FF00u) << 8) |
((u & 0x00FF0000u) >> 8) |
((u & 0xFF000000u) >> 24);
#endif
} else if constexpr (sizeof(T) == 8) {
#if defined(SPIDER_COMPILER_MSVC)
u = _byteswap_uint64(u);
#elif defined(SPIDER_COMPILER_GCC_LIKE)
u = __builtin_bswap64(u);
#else
u =
((u & 0x00000000000000FFull) << 56) |
((u & 0x000000000000FF00ull) << 40) |
((u & 0x0000000000FF0000ull) << 24) |
((u & 0x00000000FF000000ull) << 8) |
((u & 0x000000FF00000000ull) >> 8) |
((u & 0x0000FF0000000000ull) >> 24) |
((u & 0x00FF000000000000ull) >> 40) |
((u & 0xFF00000000000000ull) >> 56);
#endif
} else {
// Generic fallback (rare: non 1/2/4/8-byte types)
U result = 0;
for (size_t i = 0; i < sizeof(T); ++i) {
result |= ((u >> (i * 8)) & 0xFF) << ((sizeof(T) - 1 - i) * 8);
}
u = result;
}
return static_cast<T>(u);
}
// Store Big Endian //
template<typename T>
inline void storeBE(T n, u8* bytes) {
static_assert(std::is_trivially_copyable<T>::value);
#if SPIDER_BIG_ENDIAN
std::memcpy(bytes, &n, sizeof(T));
#endif
#if SPIDER_LITTLE_ENDIAN
n = byteswap(n);
std::memcpy(bytes, &n, sizeof(T));
#endif
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
for (size_t i = 0; i < sizeof(T); ++i) {
bytes[i] = static_cast<u8>(
(static_cast<std::make_unsigned_t<T>>(n) >> ((sizeof(T) - 1 - i) * 8)) & 0xFF
);
}
#endif
}
template<>
inline void storeBE<f32>(f32 n, u8* bytes) {
u32 tmp = bit_cast<u32>(n);
storeBE(tmp, bytes);
}
template<>
inline void storeBE<f64>(f64 n, u8* bytes) {
u64 tmp = bit_cast<u64>(n);
storeBE(tmp, bytes);
}
// Load Big Endian //
template<typename T>
inline void loadBE(T* n, const u8* bytes) {
static_assert(std::is_trivially_copyable<T>::value);
#if SPIDER_BIG_ENDIAN
std::memcpy(n, bytes, sizeof(T));
#endif
#if SPIDER_LITTLE_ENDIAN
std::memcpy(&n, bytes, sizeof(T));
*n = byteswap(*n);
#endif
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
using U = std::make_unsigned_t<T>;
U result = 0;
for (size_t i = 0; i < sizeof(T); ++i) {
result |= static_cast<U>(bytes[i]) << ((sizeof(T) - 1 - i) * 8);
}
*n = static_cast<T>(result);
#endif
}
template<>
inline void loadBE<f32>(f32* n, const u8* bytes) {
u32 tmp;
loadBE(&tmp, bytes);
*n = bit_cast<f32>(tmp);
}
template<>
inline void loadBE<f64>(f64* n, const u8* bytes) {
u64 tmp;
loadBE(&tmp, bytes);
*n = bit_cast<f64>(tmp);
}
// Store Little Endian //
template<typename T>
inline void storeLE(T n, u8* bytes) {
static_assert(std::is_trivially_copyable<T>::value);
#if SPIDER_BIG_ENDIAN
n = byteswap(n);
std::memcpy(bytes, &n, sizeof(T));
#endif
#if SPIDER_LITTLE_ENDIAN
std::memcpy(bytes, &n, sizeof(T));
#endif
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
for (size_t i = 0; i < sizeof(T); ++i) {
bytes[i] = static_cast<u8>(
(static_cast<std::make_unsigned_t<T>>(n) >> (i * 8)) & 0xFF
);
}
#endif
}
template<>
inline void storeLE<f32>(f32 n, u8* bytes) {
u32 tmp = bit_cast<u32>(n);
storeLE(tmp, bytes);
}
template<>
inline void storeLE<f64>(f64 n, u8* bytes) {
u64 tmp = bit_cast<u64>(n);
storeLE(tmp, bytes);
}
// Load Little Endian //
template<typename T>
inline void loadLE(T* n, const u8* bytes) {
static_assert(std::is_trivially_copyable<T>::value);
#if SPIDER_BIG_ENDIAN
std::memcpy(&n, bytes, sizeof(T));
*n = byteswap(n);
#endif
#if SPIDER_LITTLE_ENDIAN
std::memcpy(n, bytes, sizeof(T));
#endif
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
using U = std::make_unsigned_t<T>;
U result = 0;
for (size_t i = 0; i < sizeof(T); ++i) {
result |= static_cast<U>(bytes[i]) << (i * 8);
}
*n = static_cast<T>(result);
#endif
}
template<>
inline void loadLE<f32>(f32* n, const u8* bytes) {
u32 tmp;
loadLE(&tmp, bytes);
*n = bit_cast<f32>(tmp);
}
template<>
inline void loadLE<f64>(f64* n, const u8* bytes) {
u64 tmp;
loadLE(&tmp, bytes);
*n = bit_cast<f64>(tmp);
}
// ADVANCED Load Little Endian //
/**
* Loads LE bytes into a type.
* Also considers that the array may end, actually.
*/
template<typename T>
inline void loadPartialLE(T* n, const u8* bytes, isize length) {
*n = 0;
length = std::min(sizeof(T), length);
#if SPIDER_BIG_ENDIAN
std::memcpy(n, bytes, length);
*n = byteswap(n);
#endif
#if SPIDER_LITTLE_ENDIAN
std::memcpy(n, bytes, length);
#endif
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
using U = std::make_unsigned_t<T>;
U result = 0;
for (size_t i = 0; i < length; ++i) {
result |= static_cast<U>(bytes[i]) << (i * 8);
}
*n = static_cast<T>(result);
#endif
}
template<>
inline void loadPartialLE<f32>(f32* n, const u8* bytes, isize length) {
u32 tmp;
loadPartialLE(&tmp, bytes, length);
*n = bit_cast<f32>(tmp);
}
template<>
inline void loadPartialLE<f64>(f64* n, const u8* bytes, isize length) {
u64 tmp;
loadPartialLE(&tmp, bytes, length);
*n = bit_cast<f64>(tmp);
}
inline void loadRegisterU8(register_t* r, const u8* bytes, isize length) {
loadPartialLE(&r->_u8, bytes, length);
}
inline void loadRegisterU16(register_t* r, const u8* bytes, isize length) {
loadPartialLE(&r->_u16, bytes, length);
}
inline void loadRegisterU32(register_t* r, const u8* bytes, isize length) {
loadPartialLE(&r->_u32, bytes, length);
}
inline void loadRegisterU64(register_t* r, const u8* bytes, isize length) {
loadPartialLE(&r->_u64, bytes, length);
}
using _regload = void (*)(register_t* r, const u8* bytes, isize length);
inline _regload loadRegister[] = {
&loadRegisterU8, &loadRegisterU16,
&loadRegisterU32, &loadRegisterU64
};
// MISCs
inline void loadPartialBytes(const u8* from, isize fromOffset, isize fromLength, u8* to, isize toLength) {
size_t safeOffset = std::min(fromOffset, fromLength);
from += safeOffset;
fromLength -= safeOffset;
size_t writable = std::min(fromLength, toLength);
std::copy(from, from + writable, to);
std::fill(to + writable, to + toLength, 0);
}
}

View File

@@ -55,9 +55,9 @@
// ========================================================== //
// PACKING //
// (not used now) //
// ========================================================== //
// Find out what compiler the user is using
#if defined(__clang__)
#define SPIDER_COMPILER_CLANG
@@ -73,8 +73,9 @@
// Macros...
#if defined(SPIDER_COMPILER_GCC_LIKE)
#define SPIDER_ATTRIBUTE_PACKED __attribute__((packed))
#define SPIDER_PACKED_STRUCT(decl) decl SPIDER_ATTRIBUTE_PACKED
#define SPIDER_PACK_BEGIN
#define SPIDER_PACK_END
#define SPIDER_PACK_STRUCT __attribute__((packed))
#elif defined(SPIDER_COMPILER_MSVC)
#define SPIDER_BEGIN_PACKED __pragma(pack(push, 1))

View File

@@ -1,17 +1,17 @@
#include "InstrReel.hpp"
#include <spider/runtime/cpu/CPU.hpp>
#include <spider/runtime/memory/Types.hpp>
namespace spider {
// Public Interface //
InstrReel::InstrReel() {}
InstrReel::~InstrReel() {}
u16 InstrReel::instrAt(u64 ip) const {}
u8 InstrReel::dataAt(u64 ip) const {}
u8 InstrReel::feedNext(CPU& cpu) {}
// Static Utils //
u16 InstrReel::unpackInstr(u16 bcode) {

View File

@@ -0,0 +1,78 @@
#pragma once
#include <spider/SpiderRuntime.hpp>
#include <spider/runtime/memory/ByteArray.hpp>
#include <spider/runtime/cpu/Register.hpp>
namespace spider {
/**
* Implements an instruction reel.
*/
class InstrReel {
public:
InstrReel();
virtual ~InstrReel();
public:
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
virtual u8 readU8(u64 ip) = 0;
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
virtual u16 readU16(u64 ip) = 0;
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
virtual u32 readU32(u64 ip) = 0;
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
virtual u64 readU64(u64 ip) = 0;
/**
* Reads a range of data, and
* outputs it.
*/
virtual void readRange(u64 ip, u8* out, u64 length) = 0;
virtual void loadRegister(u64 ip, u8 size_code, register_t* r) = 0;
/**
* Current size of the instructions.
*/
virtual u64 size() = 0;
public: // Static Utils //
static u16 unpackInstr(u16 bcode);
static u8 unpackAddrMode(u16 bcode);
static u8 unpackTypeSize(u16 bcode);
};
}

View File

@@ -0,0 +1,209 @@
#include "InstrReelDyn.hpp"
#include <spider/runtime/memory/Types.hpp>
namespace spider {
InstrReelDyn::InstrReelDyn(u64 length) : _size(length) {
// Safe int ceil division
growTo((length >> 8) + ((length & 255) != 0));
}
//InstrReelDyn::InstrReelDyn(const u8* data, u64 length) {}
InstrReelDyn::InstrReelDyn(const InstrReelDyn& copy)
: _blocks(copy._blocks), _size(copy._size) {
}
InstrReelDyn::InstrReelDyn(InstrReelDyn&& move) noexcept
: _blocks(std::move(move._blocks)), _size(std::move(move._size)) {
}
InstrReelDyn::~InstrReelDyn() {
// .. //
}
InstrReelDyn& InstrReelDyn::operator=(const InstrReelDyn& copy) {
_blocks = copy._blocks;
_size = copy._size;
return *this;
}
InstrReelDyn& InstrReelDyn::operator=(InstrReelDyn&& move) noexcept {
_blocks = std::move(move._blocks);
_size = std::move(move._size);
return *this;
}
void InstrReelDyn::growTo(u64 ip) {
u64 b_index = (ip >> 8) + 1;
while (_blocks.size() < b_index) {
_blocks.emplace_back();
}
if (ip >= _size) _size = ip + 1;
}
std::pair<u64, u8> InstrReelDyn::indexOf(u64 ip) {
return { ip >> 8, ip & 0xFF }; // { ip / 256, ip % 256 };
}
bool InstrReelDyn::continous(u64 ip0, u64 ip1, u64* b_index, u16* s_index) {
auto i = indexOf(ip0);
*b_index = i.first;
*s_index = i.second;
return i.first == (ip1 >> 8);
}
// Particular Cases
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
u8 InstrReelDyn::readU8(u64 ip) {
if (ip + 1 > _size) return 0;
auto i = indexOf(ip);
return _blocks[i.first].data[i.second];
}
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
u16 InstrReelDyn::readU16(u64 ip) {
if (ip + 2 > _size) return 0;
u16 dat;
u64 b_index;
u16 s_index;
if (continous(ip, ip + 1, &b_index, &s_index)) {
spider::loadLE(&dat, &_blocks[b_index].data[s_index]);
return dat;
}
dat = 0;
for (isize i = 0; i < sizeof(dat); i++) {
auto& b = _blocks[(b_index + s_index) >> 8];
dat |= u16(b.data[s_index++ & 0xFF] << (i * 8));
}
return dat;
}
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
u32 InstrReelDyn::readU32(u64 ip) {
if (ip + 4 > _size) return 0;
u32 dat;
u64 b_index;
u16 s_index;
if (continous(ip, ip + 3, &b_index, &s_index)) {
spider::loadLE(&dat, &_blocks[b_index].data[s_index]);
return dat;
}
dat = 0;
for (isize i = 0; i < sizeof(dat); i++) {
auto& b = _blocks[(b_index + s_index) >> 8];
dat |= u32(b.data[s_index++ & 0xFF]) << (i * 8);
}
return dat;
}
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
u64 InstrReelDyn::readU64(u64 ip) {
if (ip + 8 > _size) return 0;
u64 dat;
u64 b_index;
u16 s_index;
if (continous(ip, ip + 7, &b_index, &s_index)) {
spider::loadLE(&dat, &_blocks[b_index].data[s_index]);
return dat;
}
dat = 0;
for (isize i = 0; i < sizeof(dat); i++) {
auto& b = _blocks[(b_index + s_index) >> 8];
dat |= u64(b.data[s_index++ & 0xFF]) << (i * 8);
}
return dat;
}
/**
* Reads a range of data, and
* outputs it.
*/
void InstrReelDyn::readRange(u64 ip, u8* out, u64 length) {
if (ip + length > _size) {
std::memset(out, 0, length);
return;
}
u64 b_index;
u16 s_index;
if (continous(ip, ip + length, &b_index, &s_index)) {
std::memcpy(out, &_blocks[b_index].data[s_index], length);
return;
}
u64 bytes_read = 0;
while (bytes_read < length) {
u64 remaining_in_block = 256 - s_index;
u64 chunk_size = std::min(remaining_in_block, length - bytes_read);
// Perform bulk copy for the current segment
std::memcpy(out + bytes_read, &_blocks[b_index].data[s_index], chunk_size);
// Advance pointers
bytes_read += chunk_size;
b_index++;
s_index = 0; // reset
}
}
void InstrReelDyn::loadRegister(u64 ip, u8 size_code, register_t* r) {
u8 bytes[8];
readRange(ip, bytes, 1 << size_code);
spider::loadRegister[size_code](r, bytes, 8);
}
/**
* Current size of the instructions.
*/
u64 InstrReelDyn::size() {
return _size;
}
// Mutation //
// TODO!
//void InstrReelDyn::writeU8(u64 ip, u8 dat) {}
//void InstrReelDyn::writeU16(u64 ip, u16 dat) {}
//void InstrReelDyn::writeU32(u64 ip, u32 dat) {}
//void InstrReelDyn::writeU64(u64 ip, u64 dat) {}
/**
* Appends instruction at the end.
*/
//void InstrReelDyn::append(u16 bc) {}
}

View File

@@ -0,0 +1,112 @@
#pragma once
#include <spider/runtime/reel/InstrReel.hpp>
namespace spider {
/**
* Implements an instruction reel.
*/
class InstrReelDyn : public InstrReel {
private:
struct ReelBlock {
u8 data[256] = {};
};
private:
deque<ReelBlock> _blocks;
u64 _size;
public:
InstrReelDyn(u64 length);
InstrReelDyn(const u8* data, u64 length);
InstrReelDyn(const InstrReelDyn& copy);
InstrReelDyn(InstrReelDyn&& move) noexcept;
virtual ~InstrReelDyn();
public:
InstrReelDyn& operator=(const InstrReelDyn& copy);
InstrReelDyn& operator=(InstrReelDyn&& move) noexcept;
private:
std::pair<u64, u8> indexOf(u64 ip);
bool continous(u64 ip0, u64 ip1, u64* b_index, u16* s_index);
void growTo(u64 ip);
public:
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
virtual u8 readU8(u64 ip) override;
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
virtual u16 readU16(u64 ip) override;
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
virtual u32 readU32(u64 ip) override;
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
virtual u64 readU64(u64 ip) override;
/**
* Reads a range of data, and
* outputs it.
*/
virtual void readRange(u64 ip, u8* out, u64 length) override;
virtual void loadRegister(u64 ip, u8 size_code, register_t* r) override;
/**
* Current size of the instructions.
*/
virtual u64 size() override;
public:
void writeU8(u64 ip, u8 dat);
void writeU16(u64 ip, u16 dat);
void writeU32(u64 ip, u32 dat);
void writeU64(u64 ip, u64 dat);
/**
* Appends instruction at the end.
*/
void append(u16 bc);
};
}

View File

@@ -0,0 +1,170 @@
#include "InstrReelFixed.hpp"
#include <spider/runtime/memory/Types.hpp>
#include <cstring>
namespace spider {
// Constructors & Destructors //
InstrReelFixed::InstrReelFixed(u64 length)
: _mem(nullptr), _size(length) {
if (_size > 0) {
_mem = new u8[_size];
std::memset(_mem, 0, _size);
}
}
InstrReelFixed::InstrReelFixed(const u8* data, u64 length)
: _mem(nullptr), _size(length) {
if (_size > 0) {
_mem = new u8[_size];
std::copy(data, data + _size, _mem);
}
}
InstrReelFixed::InstrReelFixed(const InstrReelFixed& other) {
_size = other._size;
_mem = new u8[_size];
std::copy(other._mem, other._mem + _size, _mem);
}
InstrReelFixed::InstrReelFixed(InstrReelFixed&& other) noexcept {
_mem = other._mem;
_size = other._size;
other._mem = nullptr;
other._size = 0;
}
InstrReelFixed::~InstrReelFixed() {
delete[] _mem;
}
// General Case(s) //
// Instruction abstraction //
u8 InstrReelFixed::readU8(u64 ip) {
u8 dat;
spider::loadPartialLE(&dat, _mem + ip, _size);
return dat;
}
u16 InstrReelFixed::readU16(u64 ip) {
u16 dat;
spider::loadPartialLE(&dat, _mem + ip, _size);
return dat;
}
u32 InstrReelFixed::readU32(u64 ip) {
u32 dat;
spider::loadPartialLE(&dat, _mem + ip, _size);
return dat;
}
u64 InstrReelFixed::readU64(u64 ip) {
u64 dat;
spider::loadPartialLE(&dat, _mem + ip, _size);
return dat;
}
void InstrReelFixed::readRange(u64 ip, u8* out, u64 length) {
spider::loadPartialBytes(_mem, isize(ip), _size, out, length);
}
void InstrReelFixed::loadRegister(u64 ip, u8 size_code, register_t* r) {
ip = std::min(ip, _size);
spider::loadRegister[size_code](r, _mem + ip, _size - ip);
}
u64 InstrReelFixed::size() {
return _size;
}
// Assign Operators //
InstrReelFixed& InstrReelFixed::operator=(const InstrReelFixed& other) {
if (this == &other) return *this; // lock self
u8* new_mem = new u8[other._size];
std::copy(other._mem, other._mem + other._size, new_mem);
delete[] _mem;
_mem = new_mem;
_size = other._size;
return *this;
}
InstrReelFixed& InstrReelFixed::operator=(InstrReelFixed&& other) noexcept {
if (this == &other) return *this; // lock self
delete[] _mem;
_mem = other._mem; // steal
_size = other._size;
other._mem = nullptr; // leave as husk
other._size = 0;
return *this;
}
// Misc //
void InstrReelFixed::writeU8(u64 ip, u8 dat) {
if(ip + 1 > _size) return;
_mem[ip] = dat;
}
void InstrReelFixed::writeU16(u64 ip, u16 dat) {
if(ip + 2 > _size) return;
spider::storeLE(dat, _mem + ip);
}
void InstrReelFixed::writeU32(u64 ip, u32 dat) {
if(ip + 4 > _size) return;
spider::storeLE(dat, _mem + ip);
}
void InstrReelFixed::writeU64(u64 ip, u64 dat) {
if(ip + 8 > _size) return;
spider::storeLE(dat, _mem + ip);
}
void InstrReelFixed::resize(u64 new_size) {
// Special case 1
if (new_size == _size) return;
// Special case 2
if (new_size == 0) {
delete[] _mem;
_mem = nullptr;
_size = 0;
return;
}
// 1. Allocate the new block
u8* new_mem = new u8[new_size];
// 2. Zero-initialize
std::memset(new_mem, 0, new_size);
// 3. Preserve data
// If shrinking, copy 'new_size' bytes. If growing, copy 'old_size' bytes.
u64 bytes_to_copy = (new_size < _size) ? new_size : _size;
// 3.1 Previous size could be zero, where _mem would be null
if (_mem != nullptr) {
std::copy(_mem, _mem + bytes_to_copy, new_mem);
}
// 4. Swap and Clean up
delete[] _mem;
_mem = new_mem;
_size = new_size;
}
}

View File

@@ -0,0 +1,94 @@
#pragma once
#include <spider/runtime/reel/InstrReel.hpp>
namespace spider {
/**
* Implements an instruction reel.
*/
class InstrReelFixed : public InstrReel {
private:
u8* _mem;
u64 _size;
public:
InstrReelFixed(u64 length);
InstrReelFixed(const u8* data, u64 length);
InstrReelFixed(const InstrReelFixed& copy);
InstrReelFixed(InstrReelFixed&& move) noexcept;
virtual ~InstrReelFixed();
public:
InstrReelFixed& operator=(const InstrReelFixed& copy);
InstrReelFixed& operator=(InstrReelFixed&& move) noexcept;
public:
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
virtual u8 readU8(u64 ip) override;
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
virtual u16 readU16(u64 ip) override;
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
virtual u32 readU32(u64 ip) override;
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
virtual u64 readU64(u64 ip) override;
/**
* Reads a range of data, and
* outputs it.
*/
virtual void readRange(u64 ip, u8* out, u64 length) override;
virtual void loadRegister(u64 ip, u8 size_code, register_t* r) override;
/**
* Current size of the instructions.
*/
virtual u64 size() override;
public:
void writeU8(u64 ip, u8 dat);
void writeU16(u64 ip, u16 dat);
void writeU32(u64 ip, u32 dat);
void writeU64(u64 ip, u64 dat);
void resize(u64 new_size);
};
}

View File

@@ -0,0 +1,286 @@
#include "Terminal.hpp"
#include <spider/runtime/native/distro.hpp>
#if defined(SPIDER_OS_WINDOWS)
#include <conio.h>
#include <windows.h>
#endif
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ioctl.h> //This was missing,
//The ioctl, TIOCGWINSZ and winsize used in getSize() live in that header, but it was never included.
#endif
//the Linux includes at the top are inside #if SPIDER_OS_LINUX which IS defined,
//but getSize() is inside #if SPIDER_DISTRO_DESKTOP which is NOT defined,
//so the compiler sees the ioctl call without the include that would have covered it.
#if defined(SPIDER_DISTRO_DESKTOP)
namespace spider {
// Style //
const char* Terminal::RESET = "\033[0m";
const char* Terminal::BOLD = "\033[1m";
const char* Terminal::ITALIC = "\033[3m";
const char* Terminal::FAINT = "\033[2m";
const char* Terminal::STRIKE = "\033[9m";
// Foreground //
const char* Terminal::FG_BLACK = "\033[30m"; const char* Terminal::FG_B_BLACK = "\033[90m";
const char* Terminal::FG_RED = "\033[31m"; const char* Terminal::FG_B_RED = "\033[91m";
const char* Terminal::FG_GREEN = "\033[32m"; const char* Terminal::FG_B_GREEN = "\033[92m";
const char* Terminal::FG_YELLOW = "\033[33m"; const char* Terminal::FG_B_YELLOW = "\033[93m";
const char* Terminal::FG_BLUE = "\033[34m"; const char* Terminal::FG_B_BLUE = "\033[94m";
const char* Terminal::FG_MAGENTA = "\033[35m"; const char* Terminal::FG_B_MAGENTA = "\033[95m";
const char* Terminal::FG_CYAN = "\033[36m"; const char* Terminal::FG_B_CYAN = "\033[96m";
const char* Terminal::FG_WHITE = "\033[37m"; const char* Terminal::FG_B_WHITE = "\033[97m";
// Background //
const char* Terminal::BG_BLACK = "\033[40m"; const char* Terminal::BG_B_BLACK = "\033[100m";
const char* Terminal::BG_RED = "\033[41m"; const char* Terminal::BG_B_RED = "\033[101m";
const char* Terminal::BG_GREEN = "\033[42m"; const char* Terminal::BG_B_GREEN = "\033[102m";
const char* Terminal::BG_YELLOW = "\033[43m"; const char* Terminal::BG_B_YELLOW = "\033[103m";
const char* Terminal::BG_BLUE = "\033[44m"; const char* Terminal::BG_B_BLUE = "\033[104m";
const char* Terminal::BG_MAGENTA = "\033[45m"; const char* Terminal::BG_B_MAGENTA = "\033[105m";
const char* Terminal::BG_CYAN = "\033[46m"; const char* Terminal::BG_B_CYAN = "\033[106m";
const char* Terminal::BG_WHITE = "\033[47m"; const char* Terminal::BG_B_WHITE = "\033[107m";
Terminal::Terminal() {
#if defined(SPIDER_OS_WINDOWS)
// Enable UTF-8
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
// enable vtp
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD dwMode = 0;
GetConsoleMode(hOut, &dwMode);
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hOut, dwMode);
#endif
}
Terminal::~Terminal() {
altbuff(false).style(RESET).cursor(true).flush();
}
Terminal& Terminal::style(const std::string_view code) {
std::cout << code;
return *this;
}
Terminal& Terminal::move(i32 row, i32 col) {
std::cout << "\033[" << row << ";" << col << "H";
return *this;
}
Terminal& Terminal::altbuff(bool enable) {
std::cout << (enable ? "\033[?1049h" : "\033[?1049l");
return *this;
}
Terminal& Terminal::cls() {
std::cout << "\033[2J";
return *this;
}
Terminal& Terminal::scrollRange(i32 start, i32 end) {
std::cout << "\033[" << start << ";" << end << "r\033[?6h";
return *this;
}
Terminal& Terminal::undoSRange() {
std::cout << "\033[r\033[?6l\033[H";
return *this;
}
Terminal& Terminal::fill(const std::string_view color) {
this->style(color);
this->cls();
return *this;
}
Terminal& Terminal::clearRow(i32 row) {
// Move to row, column 1
this->move(row, 1);
// \033[2K clears the entire line
std::cout << "\033[2K";
return *this;
}
Terminal& Terminal::clearRows(i32 start, i32 end) {
// Ensure we don't loop infinitely if start > end
if (start > end) std::swap(start, end);
for (i32 i = start; i <= end; ++i) {
this->clearRow(i);
}
// Optional: Move cursor back to the start of the cleared block
this->move(start, 1);
return *this;
}
Terminal& Terminal::cursor(bool show) {
std::cout << (show ? "\033[?25h" : "\033[?25l");
return *this;
}
Terminal& Terminal::drawBox(i32 startRow, i32 startCol, i32 width, i32 height, std::string_view title) {
// 1. Draw the top border
move(startRow, startCol);
std::cout << "";
for (i32 i = 0; i < width - 2; ++i) std::cout << "";
std::cout << "";
// 2. Draw the sides
for (i32 i = 1; i < height - 1; ++i) {
move(startRow + i, startCol);
std::cout << "";
move(startRow + i, startCol + width - 1);
std::cout << "";
}
// 3. Draw the bottom border
move(startRow + height - 1, startCol);
std::cout << "";
for (i32 i = 0; i < width - 2; ++i) std::cout << "";
std::cout << "";
// 4. Overlay the title if provided
if (!title.empty()) {
move(startRow, startCol + (width - i32(title.size()) - 2) / 2);
std::cout << " " << title << " ";
}
std::cout.flush();
return *this;
}
Terminal& Terminal::flush() {
std::cout << std::flush;
return *this;
}
Terminal& Terminal::sink() {
std::cin.clear();
#if defined(SPIDER_OS_WINDOWS)
while (_kbhit()) _getch();
#endif
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
tcflush(STDIN_FILENO, TCIFLUSH);
#endif
return *this;
}
std::pair<i32, i32> Terminal::getSize() {
std::pair<i32, i32> pair;
#if defined(SPIDER_OS_WINDOWS)
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
pair.first = csbi.srWindow.Right - csbi.srWindow.Left + 1;
pair.second = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
}
#endif
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
struct winsize w;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
pair.first = w.ws_col;
pair.second = w.ws_row;
}
#endif
return pair;
}
Terminal& Terminal::wait() {
sink();
std::cin.get();
return *this;
}
u8 Terminal::getKey() {
#if defined(SPIDER_OS_WINDOWS)
i32 ch = _getch();
if (ch == 0 || ch == 224) {
switch (_getch()) {
case 72: return Terminal::UP;
case 80: return Terminal::DOWN;
case 75: return Terminal::LEFT;
case 77: return Terminal::RIGHT;
default: return Terminal::UNKNOWN;
}
}
if (ch == 13) return Terminal::ENTER;
if (ch == 27) return Terminal::ESC;
if (ch == 8) return Terminal::BACKSPACE;
return Terminal::UNKNOWN;
#endif
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
struct termios oldt, newt;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
//newt.c_lflag &= ~(ICANON | ECHO);
newt.c_lflag &= static_cast<tcflag_t>(~(ICANON | ECHO)); //added this line
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
u8 result = Terminal::UNKNOWN;
int ch = getchar();
if (ch == 27) { // Potential Escape Sequence
// Use a small timeout or check if more chars are in buffer
// to distinguish between 'Esc' key and 'Arrow' sequence
// Another Win for the Win API
struct timeval tv = { 0, 10000 }; // 10ms wait
fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
if (select(1, &fds, NULL, NULL, &tv) > 0) {
if (getchar() == '[') {
switch (getchar()) {
case 'A': result = Terminal::UP; break;
case 'B': result = Terminal::DOWN; break;
case 'D': result = Terminal::LEFT; break;
case 'C': result = Terminal::RIGHT; break;
}
}
} else {
result = Terminal::ESC;
}
} else if (ch == 10) result = Terminal::ENTER;
else if (ch == 127) result = Terminal::BACKSPACE;
else result = static_cast<u8>(ch); //added this line
//else result = (u8)ch;
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return result;
#endif
}
u8 Terminal::getKeyNb() {
#if defined(SPIDER_OS_WINDOWS)
if (_kbhit()) return getKey();
return Terminal::UNKNOWN;
#endif
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
struct timeval tv = { 0, 0 };
fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
// select() returns > 0 if there is data to read
if (select(1, &fds, NULL, NULL, &tv) > 0) {
return getKey();
}
return Terminal::UNKNOWN;
#endif
}
}
#endif

View File

@@ -0,0 +1,176 @@
#pragma once
#include <spider/runtime/common.hpp>
#include <iostream>
#include <string>
#include <string_view>
#include <sstream>
namespace spider {
class Terminal {
public:
static const char* RESET;
static const char* BOLD;
static const char* ITALIC;
static const char* FAINT;
static const char* STRIKE;
static const char* FG_BLACK; static const char* FG_B_BLACK;
static const char* FG_RED; static const char* FG_B_RED;
static const char* FG_GREEN; static const char* FG_B_GREEN;
static const char* FG_YELLOW; static const char* FG_B_YELLOW;
static const char* FG_BLUE; static const char* FG_B_BLUE;
static const char* FG_MAGENTA; static const char* FG_B_MAGENTA;
static const char* FG_CYAN; static const char* FG_B_CYAN;
static const char* FG_WHITE; static const char* FG_B_WHITE;
static const char* BG_BLACK; static const char* BG_B_BLACK;
static const char* BG_RED; static const char* BG_B_RED;
static const char* BG_GREEN; static const char* BG_B_GREEN;
static const char* BG_YELLOW; static const char* BG_B_YELLOW;
static const char* BG_BLUE; static const char* BG_B_BLUE;
static const char* BG_MAGENTA; static const char* BG_B_MAGENTA;
static const char* BG_CYAN; static const char* BG_B_CYAN;
static const char* BG_WHITE; static const char* BG_B_WHITE;
public:
// Key Definitions (ASCII OK) //
static constexpr const u8 UP = 0x80;
static constexpr const u8 DOWN = 0x81;
static constexpr const u8 LEFT = 0x82;
static constexpr const u8 RIGHT = 0x83;
static constexpr const u8 ENTER = 0x84;
static constexpr const u8 ESC = 0x85;
static constexpr const u8 BACKSPACE = 0x86;
static constexpr const u8 UNKNOWN = 0xFF;
public:
Terminal();
~Terminal();
public:
/**
* Sets a style
*/
Terminal& style(const std::string_view code);
/**
* Fills the screen with a specific background color.
* @param color The background color constant (e.g., Terminal::BG_BLUE)
*/
Terminal& fill(const std::string_view color);
/**
* Moves the cursor.
*/
Terminal& move(i32 row, i32 col);
/**
* Clears the screen
*/
Terminal& cls();
Terminal& altbuff(bool enable);
Terminal& scrollRange(i32 start, i32 end);
Terminal& undoSRange();
/**
* Clears a specific row.
* @param row The 1-based index of the row to clear.
*/
Terminal& clearRow(i32 row);
/**
* Clears a range of rows (inclusive).
* @param start The first row.
* @param end The last row.
*/
Terminal& clearRows(i32 start, i32 end);
/**
* Shows / Hides the cursor.
*/
Terminal& cursor(bool show);
public:
Terminal& drawBox(i32 startRow, i32 startCol, i32 width, i32 height, std::string_view title);
public:
/**
* Flushes the output buffer
*/
Terminal& flush();
/**
* Clears the input buffer.
* Useful for some specific input cases
*/
Terminal& sink();
public:
Terminal& wait();
u8 getKey();
/**
* Get key non blocking
*/
u8 getKeyNb();
std::pair<i32, i32> getSize();
public:
template <typename T>
Terminal& print(const T& msg) {
std::cout << msg;
return *this;
}
template <typename T>
Terminal& println(const T& msg) {
std::cout << msg << "\n";
return *this;
}
template <typename T>
Terminal& print_center(i32 width, const T& msg) {
// to string
std::ostringstream oss;
oss << msg;
std::string s = oss.str();
// then print
if (s.length() >= isize(width)) {
std::cout << s;
} else {
isize total_padding = isize(width) - s.length();
isize left_padding = total_padding / 2;
std::cout << std::string(left_padding, ' ');
std::cout << s;
std::cout << std::string(total_padding - left_padding, ' ');
}
return *this;
}
template <typename T>
Terminal& read(T& var) {
std::cin >> var;
return *this;
}
};
}

View File

@@ -0,0 +1,118 @@
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef M_E
#define M_E 2.71828182845904523536
#endif
#include <spider/runtime/cpu/CPU.hpp>
#include <iostream>
#include <cmath>
using namespace spider;
void check(const char* name, double result, double expected, double tolerance = 1e-9) {
bool ok = std::abs(result - expected) <= tolerance;
std::cout << (ok ? "[PASS] " : "[FAIL] ") << name
<< " = " << result
<< " (expected " << expected << ")\n";
}
int main() {
std::cout << "=== Spider VM Instruction Test: 0x068-0x079 ===\n\n";
CPU cpu;
cpu._post = &CPU::imp;
std::cout << "-- Cast Instructions --\n";
cpu.RA._f64 = 3.9;
cpu._dst = &cpu.RA;
cpu.D2I();
check("D2I (3.9 -> 3)", cpu.RA._u32, 3.0);
cpu.RA._f64 = 1e12;
cpu._dst = &cpu.RA;
cpu.D2L();
check("D2L (1e12)", (double)cpu.RA._u64, 1e12);
std::cout << "\n-- Trigonometric Instructions --\n";
cpu.RA._f64 = M_PI / 2.0;
cpu._dst = &cpu.RA;
cpu.SIN();
check("SIN(pi/2)", cpu.RA._f64, 1.0);
cpu.RA._f64 = 0.0;
cpu._dst = &cpu.RA;
cpu.COS();
check("COS(0)", cpu.RA._f64, 1.0);
cpu.RA._f64 = M_PI / 4.0;
cpu._dst = &cpu.RA;
cpu.TAN();
check("TAN(pi/4)", cpu.RA._f64, 1.0);
cpu.RA._f64 = 1.0;
cpu._dst = &cpu.RA;
cpu.ASIN();
check("ASIN(1.0)", cpu.RA._f64, M_PI / 2.0);
cpu.RA._f64 = 1.0;
cpu._dst = &cpu.RA;
cpu.ACOS();
check("ACOS(1.0)", cpu.RA._f64, 0.0);
cpu.RA._f64 = 1.0;
cpu._dst = &cpu.RA;
cpu.ATAN();
check("ATAN(1.0)", cpu.RA._f64, M_PI / 4.0);
cpu.RA._f64 = 1.0;
cpu.RB._f64 = 1.0;
cpu._dst = &cpu.RA;
cpu._src = &cpu.RB;
cpu.ATAN2();
check("ATAN2(1,1)", cpu.RA._f64, M_PI / 4.0);
std::cout << "\n-- Exponential Instructions --\n";
cpu.RA._f64 = 1.0;
cpu._dst = &cpu.RA;
cpu.EXP();
check("EXP(1)", cpu.RA._f64, M_E);
cpu.RA._f64 = M_E;
cpu._dst = &cpu.RA;
cpu.LOG();
check("LOG(e)", cpu.RA._f64, 1.0);
cpu.RA._f64 = 100.0;
cpu.RB._f64 = 10.0;
cpu._dst = &cpu.RA;
cpu._src = &cpu.RB;
cpu.LOGAB();
check("LOGAB(100,10)", cpu.RA._f64, 2.0);
cpu.RA._f64 = 2.0;
cpu.RB._f64 = 10.0;
cpu._dst = &cpu.RA;
cpu._src = &cpu.RB;
cpu.POW();
check("POW(2,10)", cpu.RA._f64, 1024.0);
cpu.RA._f64 = 9.0;
cpu._dst = &cpu.RA;
cpu.SQRT();
check("SQRT(9)", cpu.RA._f64, 3.0);
cpu.RA._f64 = 27.0;
cpu.RB._f64 = 3.0;
cpu._dst = &cpu.RA;
cpu._src = &cpu.RB;
cpu.ROOT();
check("ROOT(27,3)", cpu.RA._f64, 3.0);
std::cout << "\n=== Tests complete ===\n";
return 0;
}