52 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
6dfec7c256 Upload files to "Math" 2026-03-21 02:13:05 +00:00
5a4eb66c78 ram, instr reel, runtime, etc 2026-03-20 16:53:02 -06:00
16fa0bf3ea executed pygen, we now have cpu instructions yay, made some changes to pygen 2026-03-20 11:04:37 -06:00
0d8fef5ef9 Merge pull request 'arturo-pygen-branch' (#1) from arturo-pygen-branch into main
Reviewed-on: #1
2026-03-20 16:49:37 +00:00
56 changed files with 6301 additions and 78 deletions

View File

@@ -0,0 +1,272 @@
#pragma once
// AUTO-GENERATED by pygen.ipynb — DO NOT EDIT MANUALLY
#include <spider/runtime/common.hpp>
namespace spider {
// Addressing mode masks — indexed by opcode.
// [opcode][0] = mask for param 1, [opcode][1] = mask for param 2
constexpr u8 ADDR_MODE_MASKS[][2] = {
{ 0x00, 0x00 }, // NOP
{ 0x00, 0x00 }, // SPDR
{ 0x05, 0x00 }, // MMODE
{ 0x1F, 0x00 }, // INT
{ 0x1F, 0x00 }, // LRV
{ 0x1E, 0x00 }, // FSR
{ 0x1E, 0x00 }, // FIR
{ 0x1E, 0x00 }, // FZR
{ 0x1E, 0x1F }, // LSR
{ 0x04, 0x00 }, // FVR
{ 0x1E, 0xFF }, // MOV
{ 0x04, 0x04 }, // MOR
{ 0x00, 0x00 }, // AMOV
{ 0x04, 0x04 }, // SWP
{ 0x04, 0x00 }, // AHM
{ 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
{ 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
{ 0x00, 0x00 }, // UMO
{ 0x00, 0x00 }, // MADD
{ 0x00, 0x00 }, // MSUB
{ 0x00, 0x00 }, // MMUL
{ 0x00, 0x00 }, // MINV
{ 0x00, 0x00 }, // MTRA
{ 0x00, 0x00 }, // MDET
{ 0x00, 0x00 }, // QMKA
{ 0x00, 0x00 }, // QMUL
{ 0x00, 0x00 }, // XADD
{ 0x00, 0x00 }, // XSUB
{ 0x00, 0x00 }, // XAMA
{ 0x00, 0x00 }, // XMUL
{ 0x00, 0x00 }, // XDIV
{ 0x00, 0x00 }, // UPY
};
// Type size masks — indexed by opcode.
constexpr u8 TYPE_SIZE_MASKS[] = {
0x00, // NOP
0x00, // SPDR
0x01, // MMODE
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
0x0F, // INC
0x0F, // DEC
0x0F, // ADD
0x0F, // SUB
0x0F, // MUL
0x0F, // UMUL
0x0F, // DIV
0x0F, // UDIV
0x0F, // MOD
0x0F, // UMOD
0x0F, // DMOD
0x0F, // UDMD
0x0F, // FBT
0x0F, // STB
0x0F, // CRB
0x0F, // TSB
0x0F, // BOOL
0x0F, // NOT
0x0F, // AND
0x0F, // OR
0x0F, // XOR
0x0F, // SHL
0x0F, // SHR
0x0F, // SSR
0x0F, // ROL
0x0F, // ROR
0x0F, // CNT
0x0F, // EQ
0x0F, // NE
0x0F, // GT
0x0F, // GE
0x0F, // LT
0x0F, // LE
0x0F, // JMP
0x0F, // JEQ
0x0F, // JNE
0x0F, // JIF
0x0F, // JMR
0x0F, // JER
0x0F, // JNR
0x0F, // JIR
0x0F, // SFB
0x0F, // LFB
0x0F, // JUF
0x0F, // JUR
0x0F, // PUSH
0x0F, // POP
0x0F, // ALLOC
0x0F, // HFREE
0x0F, // CALL
0x0F, // RET
0x0F, // EDI
0x0F, // SHSS
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
0x00, // I2D
0x00, // L2F
0x00, // L2D
0x00, // F2I
0x00, // F2L
0x00, // D2I
0x00, // D2L
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
0x00, // UMO
0x00, // MADD
0x00, // MSUB
0x00, // MMUL
0x00, // MINV
0x00, // MTRA
0x00, // MDET
0x00, // QMKA
0x00, // QMUL
0x00, // XADD
0x00, // XSUB
0x00, // XAMA
0x00, // XMUL
0x00, // XDIV
0x00, // UPY
};
} // namespace spider

Binary file not shown.

View File

@@ -14,8 +14,16 @@ OBJEXT := o
#Flags, Libraries and Includes #Flags, Libraries and Includes
ROOT := ./ ROOT := ./
CFLAGS := -Wall -std=c++20 -DSPIDER_COMPILING CFLAGS := -std=c++20 -O2 \
LFLAGS := -Wall -std=c++20 -static -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 := LIB :=
INC := -I./src/ INC := -I./src/

View File

@@ -15,7 +15,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 1,
"id": "b0fcd533", "id": "b0fcd533",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -23,43 +23,52 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Repo root : /home/arturobalam/Documents/7thQuarter/Estancia_2/internship-repo/ArturoBalam-Internship2-repo/spider-runtime-folder/spider-runtime\n", "Repo root : ./ -> (True)\n",
"CPU.hpp : /home/arturobalam/Documents/7thQuarter/Estancia_2/internship-repo/ArturoBalam-Internship2-repo/spider-runtime-folder/spider-runtime/src/spider/runtime/cpu/CPU.hpp\n", "CPU.hpp : .//src//spider/runtime/cpu/CPU.hpp -> (True)\n",
"XLSX : /home/arturobalam/Documents/7thQuarter/Estancia_2/internship-repo/ArturoBalam-Internship2-repo/spider-runtime-folder/spider-runtime/Spider_Instructions.xlsx\n", "XLSX : .//docs//Spider Instructions.xlsx -> (True)\n",
"Output dir: /home/arturobalam/Documents/7thQuarter/Estancia_2/internship-repo/ArturoBalam-Internship2-repo/spider-runtime-folder/spider-runtime/pygen_out\n" "Output dir: .//autogen/ -> (True)\n"
] ]
} }
], ],
"source": [ "source": [
"# setup directories\n", "# setup directories\n",
"\n",
"import os\n", "import os\n",
"\n", "\n",
"# Root of the Spider runtime repo — adjust this path to match your machine (folder where spider-runtime lives).\n", "# [CHANGE]\n",
"REPO_ROOT = os.path.abspath('/home/arturobalam/Documents/7thQuarter/Estancia_2/internship-repo/ArturoBalam-Internship2-repo/spider-runtime-folder/spider-runtime')\n", "# Since we're running on a local environment (i hope)\n",
"# we can just signal a relative directory.\n",
"REPO_ROOT = './'\n",
"DOCS_ROOT = f'{REPO_ROOT}/docs/'\n",
"SRC_ROOT = f'{REPO_ROOT}/src/'\n",
"\n", "\n",
"# Where CPU.hpp lives — this is the file we will inject generated code into.\n", "# Where CPU.hpp lives — this is the file we will inject generated code into.\n",
"CPU_HPP_PATH = os.path.join(REPO_ROOT, 'src', 'spider', 'runtime', 'cpu', 'CPU.hpp')\n", "CPU_HPP_PATH = f'{SRC_ROOT}/spider/runtime/cpu/CPU.hpp'\n",
"\n", "\n",
"# Where the Excel instruction sheet lives. Allocate the .xlsx file in the project's root folder.\n", "# Where the Excel instruction sheet lives. Allocate the .xlsx file in the project's root folder.\n",
"XLSX_PATH = os.path.join(REPO_ROOT, 'Spider_Instructions.xlsx')\n", "# NOTE: The file I uploaded has a space instead of underscore!\n",
"XLSX_PATH = f'{DOCS_ROOT}/Spider Instructions.xlsx'\n",
"\n", "\n",
"# Output folder for any standalone generated files.\n", "# Output folder for any standalone generated files.\n",
"OUT_DIR = os.path.join(REPO_ROOT, 'pygen_out')\n", "OUT_DIR = f'{REPO_ROOT}/autogen/'\n",
"\n", "\n",
"# Create the output directory if it does not exist yet.\n", "# Create the output directory if it does not exist yet.\n",
"# exist_ok=True means no error if it already exists.\n", "# exist_ok=True means no error if it already exists.\n",
"os.makedirs(OUT_DIR, exist_ok=True)\n", "os.makedirs(OUT_DIR, exist_ok=True)\n",
"\n", "\n",
"print(f'Repo root : {REPO_ROOT}')\n", "def dir_exists(path:str):\n",
"print(f'CPU.hpp : {CPU_HPP_PATH}')\n", " return os.path.exists(path) and os.path.isdir(path)\n",
"print(f'XLSX : {XLSX_PATH}')\n", "def file_exists(path:str):\n",
"print(f'Output dir: {OUT_DIR}')\n" " return os.path.exists(path) and os.path.isfile(path)\n",
"\n",
"print(f'Repo root : {REPO_ROOT } -> ({ dir_exists(REPO_ROOT )})')\n",
"print(f'CPU.hpp : {CPU_HPP_PATH} -> ({file_exists(CPU_HPP_PATH)})')\n",
"print(f'XLSX : {XLSX_PATH } -> ({file_exists(XLSX_PATH )})')\n",
"print(f'Output dir: {OUT_DIR } -> ({ dir_exists(OUT_DIR )})')\n"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 2,
"id": "b33de8ac", "id": "b33de8ac",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -135,7 +144,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 4,
"id": "58645013", "id": "58645013",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -143,7 +152,7 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Real instructions : 126\n", "Real instructions : 128\n",
"Reserved slots : 14\n", "Reserved slots : 14\n",
"Duplicate check : PASSED\n", "Duplicate check : PASSED\n",
"\n", "\n",
@@ -161,6 +170,7 @@
"Exponential 6\n", "Exponential 6\n",
"Matrix 6\n", "Matrix 6\n",
"SIMD 5\n", "SIMD 5\n",
"Quaternion 2\n",
"Easter Eggs 1\n", "Easter Eggs 1\n",
"\n", "\n",
"First 5 instructions:\n", "First 5 instructions:\n",
@@ -168,8 +178,8 @@
"0 000 NOP System 0 00 00\n", "0 000 NOP System 0 00 00\n",
"1 001 SPDR System 0 00 00\n", "1 001 SPDR System 0 00 00\n",
"2 002 MMODE System 1 05 01\n", "2 002 MMODE System 1 05 01\n",
"3 003 INT System 1 1F 0F\n", "3 003 INT System 1 1F 08\n",
"4 004 LRV System 1 1F 0C\n" "4 004 LRV System 1 1F 08\n"
] ]
} }
], ],
@@ -205,6 +215,7 @@
" 'dis', # addressing mode: Displaced\n", " 'dis', # addressing mode: Displaced\n",
" 'addr_mask_1', # accepted addressing mode mask for param 1\n", " 'addr_mask_1', # accepted addressing mode mask for param 1\n",
" 'addr_mask_2', # accepted addressing mode mask for param 2\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", " 'B', # type size: Byte (1 byte) supported?\n",
" 'S', # type size: Short (2 bytes) supported?\n", " 'S', # type size: Short (2 bytes) supported?\n",
" 'I', # type size: Int (4 bytes) supported?\n", " 'I', # type size: Int (4 bytes) supported?\n",
@@ -212,6 +223,7 @@
" 'F', # type size: Float supported?\n", " 'F', # type size: Float supported?\n",
" 'D', # type size: Double supported?\n", " 'D', # type size: Double supported?\n",
" 'type_mask', # combined type size mask as hex string\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", " 'operation', # human-readable description of what the instruction does\n",
" 'skip_2', # trailing empty column\n", " 'skip_2', # trailing empty column\n",
"]\n", "]\n",
@@ -271,7 +283,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 5,
"id": "452bc76c", "id": "452bc76c",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -279,8 +291,8 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Masks written to: /home/arturobalam/Documents/7thQuarter/Estancia_2/internship-repo/ArturoBalam-Internship2-repo/spider-runtime-folder/spider-runtime/pygen_out/InstructionMasks.hpp\n", "Masks written to: .//autogen/InstructionMasks.hpp\n",
"Lines generated : 268\n" "Lines generated : 272\n"
] ]
} }
], ],
@@ -345,7 +357,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": 6,
"id": "5aaebef0", "id": "5aaebef0",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -353,7 +365,7 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Instructions formatted: 126\n", "Instructions formatted: 128\n",
"\n", "\n",
"--- Preview (first 2 instructions) ---\n", "--- Preview (first 2 instructions) ---\n",
" // [System] 0x000 — NOP: No Operation\n", " // [System] 0x000 — NOP: No Operation\n",
@@ -367,8 +379,8 @@
" void SPDR();\n", " void SPDR();\n",
"\n", "\n",
"\n", "\n",
"CPU.hpp updated successfully at: /home/arturobalam/Documents/7thQuarter/Estancia_2/internship-repo/ArturoBalam-Internship2-repo/spider-runtime-folder/spider-runtime/src/spider/runtime/cpu/CPU.hpp\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"
] ]
} }
], ],
@@ -436,11 +448,226 @@
"print(f'\\nCPU.hpp updated successfully at: {CPU_HPP_PATH}')\n", "print(f'\\nCPU.hpp updated successfully at: {CPU_HPP_PATH}')\n",
"print(f'Total lines in updated file: {len(updated.splitlines())}')\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": { "metadata": {
"kernelspec": { "kernelspec": {
"display_name": "spider-rntm-env", "display_name": "Python 3",
"language": "python", "language": "python",
"name": "python3" "name": "python3"
}, },
@@ -454,7 +681,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.12.3" "version": "3.14.3"
} }
}, },
"nbformat": 4, "nbformat": 4,

View File

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

View File

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

View File

@@ -4,8 +4,12 @@
namespace spider { namespace spider {
extern const u32 RUNTIME_VERSION_NO;
extern const std::string RUNTIME_VERSION;
class Runtime; class Runtime;
class CPU; class CPU;
class RAM; class RAM;
class InstrReel;
} }

View File

@@ -0,0 +1,54 @@
#include "Runtime.hpp"
namespace spider {
// Constructors & Destructors //
Runtime::Runtime() : Runtime(0) {}
Runtime::Runtime(u64 ramSize) : ram(ramSize), reel(nullptr) {
cpu.hookRAM(&ram);
}
Runtime::~Runtime() {
delete reel;
}
// Stepping/Running the Machine //
void Runtime::step() {
cpu.fetchInstr();
// TODO: Call instruction
}
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) {}
// Misc //
void Runtime::resizeRAM(u64 length) {
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

@@ -0,0 +1,82 @@
#pragma once
#include <spider/runtime/cpu/CPU.hpp>
#include <spider/runtime/memory/RAM.hpp>
#include <spider/runtime/reel/InstrReel.hpp>
namespace spider {
/**
* The main runtime class.
* This is where the Spider VM (Runtime) lives
*/
class Runtime {
public:
CPU cpu;
RAM ram;
InstrReel* reel;
public:
/**
* Creates a new runtime, with no memory.
*/
Runtime();
/**
* Creates a new runtime, with a specific
* amount of memory.
*/
Runtime(u64 ramSize);
/**
* Runtime Destructor.
*/
~Runtime();
public:
/**
* Steps the clock of the VM once.
*/
void step();
/**
* Steps n-times the clock of the VM.
*/
void step(u64 n);
public:
/**
* Sets the machine to run continously.
* If interrupts occur, they will be handled
* automatically.
*/
void run();
/**
* Runs this machine for a set amount of
* milliseconds.
*/
void run(u64 ms);
public:
/**
* Resizes the ram, which will preserve
* data inside the next length.
*/
void resizeRAM(u64 length);
/**
* Non-owning reel setup.
*/
void hookReel(InstrReel* newReel, bool own = false);
};
}

View File

@@ -5,9 +5,11 @@
#include <deque> #include <deque>
#include <map> #include <map>
#include <optional> #include <optional>
#include <string>
namespace spider { namespace spider {
// Absolute Types
using u8 = std::uint8_t; using u8 = std::uint8_t;
using u16 = std::uint16_t; using u16 = std::uint16_t;
using u32 = std::uint32_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(f32) == 4, "The f32 type must be exactly 4 bytes.");
static_assert(sizeof(f64) == 8, "The f64 type must be exactly 8 bytes."); static_assert(sizeof(f64) == 8, "The f64 type must be exactly 8 bytes.");
// Utility types
using isize = std::size_t;
// Utility imports // Utility imports
using std::vector; using std::vector;
using std::deque; 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 #pragma once
#include <spider/SpiderRuntime.hpp>
#include <spider/runtime/cpu/Register.hpp> #include <spider/runtime/cpu/Register.hpp>
namespace spider { namespace spider {
class CPU { 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 public: // General Purpose Registers
register_t RA, RB, RC, RD, union {
RX, RY, R0, R1, register_t GPR[16];
R2, R3, R4, R5, struct {
R6, R7, R8, R9; register_t RA, RB, RC, RD,
RX, RY, R0, R1,
R2, R3, R4, R5,
R6, R7, R8, R9;
};
};
public: // System Registers public: // System Registers
u64 RF; u64 RF;
@@ -22,6 +43,7 @@ namespace spider {
u64 RM; u64 RM;
public: public:
/** /**
* These are private registers, which are only used * These are private registers, which are only used
* whenever constant things are used. * whenever constant things are used.
@@ -30,15 +52,832 @@ namespace spider {
*/ */
register_t ALU0, ALU1; 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: public:
CPU(); CPU();
CPU(const CPU& other) = default;
CPU(CPU&& other) noexcept = default;
~CPU(); ~CPU();
public:
CPU& operator=(const CPU& other) = default;
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: public:
// <pygen-target name=cpu-instructions> // // <pygen-target name=cpu-instructions> //
// [System] 0x000 — NOP: No Operation
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: Nothing
void NOP();
// [System] 0x001 — SPDR: Will place the Spider version of the interpreter in RA
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: (Spider Version) -> RA
void SPDR();
// [System] 0x002 — MMODE: Set Memory Mode
// Params: 1 | AddrMask1: 05 AddrMask2: 00 | TypeMask: 01
// Operation: Dst -> Memory Mode Bits
void MMODE();
// [System] 0x003 — INT: Interrupt
// 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: 08
// Operation: Dst -> RV
void LRV();
// [System] 0x005 — FSR: Fetch System Register
// 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: 08
// Operation: Instruction Register -> Dst
void FIR();
// [System] 0x007 — FZR: Fetch Stack Base Register
// 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: 08
// Operation: Src -> System Register at Dst
void LSR();
// [System] 0x009 — FVR: Fetch Interrupt Vector Register
// Params: 1 | AddrMask1: 04 AddrMask2: 00 | TypeMask: 08
// Operation: Interrupt Vector Register -> Dst
void FVR();
// [Memory] 0x00A — MOV: Moves values
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Src -> Dst
void MOV();
// [Memory] 0x00B — MOR: Moves registers
// 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: 08
// Operation: Array from X to Y, by A amount
void AMOV();
// [Memory] 0x00D — SWP: Swap registers
// 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: 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: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: ~ Dst -> Dst
void COM();
// [Integer] 0x011 — NEG: Two's complement
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: - Dst -> Dst
void NEG();
// [Integer] 0x012 — EXS: Extend Sign
// 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: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst + 1 -> Dst
void INC();
// [Integer] 0x014 — DEC: Decrement
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst - 1 -> Dst
void DEC();
// [Integer] 0x015 — ADD: Addition
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst + Src -> Dst
void ADD();
// [Integer] 0x016 — SUB: Subtraction
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst - Src-> Dst
void SUB();
// [Integer] 0x017 — MUL: Multiplication
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Signed Dst * Src -> Dst
void MUL();
// [Integer] 0x018 — UMUL: Unsigned Multiplication
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Unsigned Dst * Src -> Dst
void UMUL();
// [Integer] 0x019 — DIV: Division
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Signed Dst / Src -> Dst
void DIV();
// [Integer] 0x01A — UDIV: Unsigned Division
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Unsigned Dst / Src -> Dst
void UDIV();
// [Integer] 0x01B — MOD: Modulus
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Signed Dst % Src -> Dst
void MOD();
// [Integer] 0x01C — UMOD: Unsigned Modulus
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Unsigned Dst % Src -> Dst
void UMOD();
// [Integer] 0x01D — DMOD: Division and Modulus
// 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: 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: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Flags of Dst -
void FBT();
// [Bit Wise] 0x020 — STB: Set Bit
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Src# bit is set on Dst
void STB();
// [Bit Wise] 0x021 — CRB: Clear Bit
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Src# bit is cleared on Dst
void CRB();
// [Bit Wise] 0x022 — TSB: Test Bit
// 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: 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: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Tests Dst == 0, updates Equal Flag
void NOT();
// [Bit Wise] 0x025 — AND: Boolean AND operation
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst AND Src into Dst
void AND();
// [Bit Wise] 0x026 — OR: Boolean OR operation
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst OR Src into Dst
void OR();
// [Bit Wise] 0x027 — XOR: Boolean XOR operation
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst XOR Src into Dst
void XOR();
// [Bit Wise] 0x028 — SHL: Arithmetic Shift Left
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst << Src into Dst
void SHL();
// [Bit Wise] 0x029 — SHR: Arithmetic Shift Right
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst >> Src into Dst
void SHR();
// [Bit Wise] 0x02A — SSR: Signed Shift Right
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst >>> Src into Dst
void SSR();
// [Bit Wise] 0x02B — ROL: Rotate Left
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst ROL Src into Dst
void ROL();
// [Bit Wise] 0x02C — ROR: Rotate Right
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst ROR Src into Dst
void ROR();
// [Bit Wise] 0x02D — CNT: Counts bits
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: # of 1's into Dst
void CNT();
// [Boolean] 0x030 — EQ: Equal
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst == Src into Dst
void EQ();
// [Boolean] 0x031 — NE: Not Equal
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst != Src into Dst
void NE();
// [Boolean] 0x032 — GT: Greater Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst > Src into Dst
void GT();
// [Boolean] 0x033 — GE: Greater or Equal Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst >= Src into Dst
void GE();
// [Boolean] 0x034 — LT: Lower Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst < Src into Dst
void LT();
// [Boolean] 0x035 — LE: Lower or Equal Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst <= Src into Dst
void LE();
// [Branch] 0x038 — JMP: Jump to absolute position
// 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: 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: 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: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst -> Instruction Register IF Src
void JIF();
// [Branch] 0x03C — JMR: Jump Relative
// 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: 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: 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: 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: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation:
void SFB();
// [System] 0x041 — LFB: Load (User) Flag Bit
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation:
void LFB();
// [Branch] 0x042 — JUF: Jump to absolute position, if user flag is true
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation:
void JUF();
// [Branch] 0x043 — JUR: Jump to relative position, if user flag is true
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation:
void JUR();
// [Memory] 0x044 — PUSH: Push to stack
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst -> pushed into stack
void PUSH();
// [Memory] 0x045 — POP: Pop from stack
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: popped from stack -> Dst
void POP();
// [Memory] 0x046 — ALLOC: Allocate to heap
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst -> heap ptr of size Dst
void ALLOC();
// [Memory] 0x047 — HFREE: Delete from heap
// 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: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Performs a function call, step XX
void CALL();
// [Branch] 0x04B — RET: Return from a function
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
// Operation: Undoes a function call, step XX
void RET();
// [System] 0x04C — EDI: Enable/Disable External Interrupts
// 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: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: bool( Dst ) -> Hot Swap Signal Bit
void SHSS();
// [Floating Point] 0x050 — FLI: Float Load Immediate
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation:
void FLI();
// [Floating Point] 0x051 — FNEG: Float negate
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: - Dst -> Dst
void FNEG();
// [Floating Point] 0x052 — FADD: Float add
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst + Src -> Dst
void FADD();
// [Floating Point] 0x053 — FSUB: Float subtract
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst - Src-> Dst
void FSUB();
// [Floating Point] 0x054 — FMUL: Float multiplication
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst * Src -> Dst
void FMUL();
// [Floating Point] 0x055 — FDIV: Float division
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst / Src -> Dst
void FDIV();
// [Floating Point] 0x056 — FMOD: Float modulus
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst % Src -> Dst
void FMOD();
// [Floating Point] 0x057 — FDMOD: Float division and modulus
// 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: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: Dst -> Epsilon Register
void FEPS();
// [Floating Point] 0x059 — FEEP: Float Enable/Disable Epsilon
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: bool( Dst ) -> Epsilon Enable Bit
void FEEP();
// [Boolean] 0x05A — FEQ: Float Equal
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst == Src into Dst
void FEQ();
// [Boolean] 0x05B — FNE: Float Not Equal
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst != Src into Dst
void FNE();
// [Boolean] 0x05C — FGT: Float Greater Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst > Src into Dst
void FGT();
// [Boolean] 0x05D — FGE: Float Greater or Equal Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst >= Src into Dst
void FGE();
// [Boolean] 0x05E — FLT: Float Lower Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst < Src into Dst
void FLT();
// [Boolean] 0x05F — FLE: Float Lower or Equal Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: Dst <= Src into Dst
void FLE();
// [Casts] 0x060 — F2D: F32 (Float) to F64 (Double)
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void F2D();
// [Casts] 0x061 — D2F: F64 (Double) to F32 (Float)
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void D2F();
// [Casts] 0x062 — I2F: I32 (Integer) to F32 (Float)
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void I2F();
// [Casts] 0x063 — I2D: I32 (Integer) to F64 (Double)
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void I2D();
// [Casts] 0x064 — L2F: I64 (Long) to F32 (Float)
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void L2F();
// [Casts] 0x065 — L2D: I64 (Long) to F64 (Double)
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void L2D();
// [Casts] 0x066 — F2I: F32 (Float) to I32 (Integer)
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void F2I();
// [Casts] 0x067 — F2L: F32 (Float) to I64 (Long)
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void F2L();
// [Casts] 0x068 — D2I: F64 (Double) to I32 (Integer)
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void D2I();
// [Casts] 0x069 — D2L: F64 (Double) to I64 (Long)
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
// Operation: (cast) Dst -> Dst
void D2L();
// [Trigonometric] 0x06C — SIN: Sine Function
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: sin( Dst ) -> Dst
void SIN();
// [Trigonometric] 0x06D — COS: Cosine Function
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: cos( Dst ) -> Dst
void COS();
// [Trigonometric] 0x06E — TAN: Tangent Function
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: tan( Dst ) -> Dst
void TAN();
// [Trigonometric] 0x06F — ASIN: Arc Sine Function
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: asin( Dst ) -> Dst
void ASIN();
// [Trigonometric] 0x070 — ACOS: Arc Cosine Function
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: acos( Dst ) -> Dst
void ACOS();
// [Trigonometric] 0x071 — ATAN: Arc Tangent Function
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: atan( Dst ) -> Dst
void ATAN();
// [Trigonometric] 0x072 — ATAN2: Arc Tangent Function with 2 Arguments
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: atan( Dst, Src ) -> Dst
void ATAN2();
// [Exponential] 0x074 — EXP: Exponential Function
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: exp( Dst ) -> Dst
void EXP();
// [Exponential] 0x075 — LOG: Natural Logarithm
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: ln( Dst ) -> Dst
void LOG();
// [Exponential] 0x076 — LOGAB: Logarithm A of B
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: log( Dst, Src ) -> Dst
void LOGAB();
// [Exponential] 0x077 — POW: Power Function
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: pow( Dst, Src ) -> Dst
void POW();
// [Exponential] 0x078 — SQRT: Square Root
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: sqrt( Dst ) -> Dst
void SQRT();
// [Exponential] 0x079 — ROOT: General Root
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
// Operation: pow( Dst, 1 / Src ) -> Dst
void ROOT();
// [Integer] 0x07C — ADC: Add with Carry
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: Dst + Src + Flags.Carry -> Dst, Flags.Carry
void ADC();
// [Integer] 0x07D — SWC: Subtract with Carry (Borrow)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: Dst - Src - Flags.Carry -> Dst, Flags.Carry
void SWC();
// [Integer] 0x07E — MWO: Multiply with Overflow
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: Signed Dst * Src -> Dst, Flags.Carry
void MWO();
// [Integer] 0x07F — UMO: Unsigned Multiply with Overflow
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: Unsigned Dst * Src -> Dst, Flags.Carry
void UMO();
// [Matrix] 0x080 — MADD: Matrix Addition
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void MADD();
// [Matrix] 0x081 — MSUB: Matrix Subtraction
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void MSUB();
// [Matrix] 0x082 — MMUL: Matrix Multiply
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void MMUL();
// [Matrix] 0x083 — MINV: Matrix Inverse
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void MINV();
// [Matrix] 0x084 — MTRA: Matrix Transpose
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void MTRA();
// [Matrix] 0x085 — MDET: Matrix Determinant
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// 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:
void XADD();
// [SIMD] 0x08B — XSUB: SIMD Subtract
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void XSUB();
// [SIMD] 0x08C — XAMA: SIMD Alternate Multiply-Add
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void XAMA();
// [SIMD] 0x08D — XMUL: SIMD Multiply
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void XMUL();
// [SIMD] 0x08E — XDIV: SIMD Divide
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void XDIV();
// [Easter Eggs] 0x0F0 — UPY: Will place "YUPI" in memory
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void UPY();
// </pygen-target> // // </pygen-target> //
}; };
} }

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

@@ -18,26 +18,13 @@ namespace spider {
* type-punning which is the "standard" right now. * type-punning which is the "standard" right now.
*/ */
union register_t { union register_t {
// -- Un/Signed 64 -- //
u64 _u64; u64 _u64;
i64 _i64; i64 _i64;
f64 _f64;
u8 _bytes[8];
SPIDER_PACKED_STRUCT(struct { // -- Un/Signed 32 -- //
#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
});
struct { struct {
#if SPIDER_LITTLE_ENDIAN #if SPIDER_LITTLE_ENDIAN
@@ -47,6 +34,61 @@ namespace spider {
#endif #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 { struct {
#if SPIDER_LITTLE_ENDIAN #if SPIDER_LITTLE_ENDIAN
f32 _f32; u32 : 32; f32 _f32; u32 : 32;
@@ -55,6 +97,10 @@ namespace spider {
#endif #endif
}; };
// -- Access -- //
u8 _bytes[8];
u8& operator[](size_t i) { // 0 is always LSB u8& operator[](size_t i) { // 0 is always LSB
#if SPIDER_LITTLE_ENDIAN #if SPIDER_LITTLE_ENDIAN
return _bytes[i]; return _bytes[i];
@@ -71,6 +117,7 @@ namespace spider {
return _bytes[7 - i]; return _bytes[7 - i];
#endif #endif
} }
}; };
static_assert(sizeof(register_t) == 8, "The register type must be exactly 8 bytes."); 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

@@ -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

@@ -0,0 +1,139 @@
#include "RAM.hpp"
#include <spider/runtime/cpu/Register.hpp>
#include <spider/runtime/memory/Types.hpp>
#include <cstring>
namespace spider {
// Constructors & Destructors //
RAM::RAM(u64 length) : _mem(nullptr), _size(length), _oob(0) {
if (_size > 0) {
_mem = new u8[_size];
std::memset(_mem, 0, _size);
}
}
RAM::RAM(const RAM& other) : _size(other._size), _oob(0) {
_mem = new u8[_size];
std::copy(other._mem, other._mem + _size, _mem);
}
RAM::RAM(RAM&& other) noexcept : _mem(other._mem), _size(other._size), _oob(0) {
other._mem = nullptr;
other._size = 0;
}
RAM::~RAM() {
delete[] _mem;
}
// Assign Operators //
RAM& RAM::operator=(const RAM& 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;
}
RAM& RAM::operator=(RAM&& 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;
}
// Unsafe Access //
u8& RAM::operator[](u64 i) { return _mem[i]; }
u8 RAM::operator[](u64 i) const { return _mem[i]; }
// Managed Access //
u8& RAM::at(u64 i) {
return (i < _size) ? _mem[i] : _oob;
}
u8 RAM::at(u64 i) const {
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) {
// 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;
}
u64 RAM::size() const {
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/common.hpp>
#include <spider/runtime/cpu/Register.hpp>
namespace spider { namespace spider {
/** /**
@@ -12,13 +14,25 @@ namespace spider {
class RAM { class RAM {
private: private:
u8* _mem; u8* _mem;
u64 _size;
u8 _oob; // Out of bounds reference
public: public:
RAM(u64 length); RAM(u64 length);
RAM(const RAM& other);
RAM(RAM&& other) noexcept;
~RAM(); ~RAM();
public:
RAM& operator=(const RAM& other);
RAM& operator=(RAM&& other) noexcept;
public: // Unsafe access public: // Unsafe access
u8& operator[](u64 i); u8& operator[](u64 i);
@@ -31,6 +45,24 @@ namespace spider {
u8 at(u64 i) const; 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

@@ -1,17 +1,5 @@
#pragma once #pragma once
// ========================================================== //
// Compiling or Writing? //
// ========================================================== //
#ifdef SPIDER_WRITING
#error "[Spider Distro] Please do not set this macro."
#endif
#ifndef SPIDER_COMPILING
#define SPIDER_WRITING
#endif
// ========================================================== // // ========================================================== //
// Distro // // Distro //
// ========================================================== // // ========================================================== //
@@ -43,11 +31,9 @@
#define SPIDER_DISTRO_DESKTOP #define SPIDER_DISTRO_DESKTOP
#define SPIDER_OS_LINUX #define SPIDER_OS_LINUX
#else #else
// ========================================================== // // === MUST be a microcontroller! === //
// MUST be a microcontroller! // #include <spider/runtime/native/distro_mcu.hpp>
// ========================================================== // #ifndef SPIDER_DISTRO_MICRO
#include <spider/config_mcu.hpp>
#ifdef SPIDER_DISTRO_MICRO
#error "[Spider Distro] Could not autodetect. Please select a distro and OS manually." #error "[Spider Distro] Could not autodetect. Please select a distro and OS manually."
#endif #endif
#endif #endif
@@ -107,8 +93,6 @@
#elif defined(SPIDER_DISTRO_MICRO) #elif defined(SPIDER_DISTRO_MICRO)
#include <spider/runtime/native/distro_mcu.hpp>
#define SPIDER_DISTRO_NAME "Micro" #define SPIDER_DISTRO_NAME "Micro"
#if !defined(SPIDER_USE_ICU) && !defined(SPIDER_NO_ICU) #if !defined(SPIDER_USE_ICU) && !defined(SPIDER_NO_ICU)
@@ -127,4 +111,5 @@
#endif #endif
// === Include Distro Defaults === //
#include <spider/runtime/native/distro_defs.hpp>

View File

@@ -0,0 +1,40 @@
#pragma once
// ========================================================== //
// SPIDER DEFAULT SETTINGS, PER DISTRO //
// ========================================================== //
// ================== MEMORY FOOTPRINT ================== //
/**
* Use a normal amount of memory, assuming there
* is like 100KB free of it.
*/
#define SPIDER_MEMFOOTPRINT_NORMAL 0
/**
* Attempt to reduce the memory footprint
* where possible, but without doing
* extreme adaptations.
*/
#define SPIDER_MEMFOOTPRINT_REDUCED 1
/**
* Will deliverately convert things from memory
* to functions in order to free as much memory
* as possible, even if it slows things down.
*/
#define SPIDER_MEMFOOTPRINT_MINIMAL 2
#ifndef SPIDER_MEMFOOTPRINT
#if defined(SPIDER_DISTRO_MOBILE) || defined(SPIDER_DISTRO_BROWSER)
#define SPIDER_MEMFOOTPRINT SPIDER_MEMFOOTPRINT_REDUCED
#elif defined(SPIDER_DISTRO_MICRO)
#define SPIDER_MEMFOOTPRINT SPIDER_MEMFOOTPRINT_MINIMAL
#else
#define SPIDER_MEMFOOTPRINT SPIDER_MEMFOOTPRINT_NORMAL
#endif
#endif
// ================== MISC ================== //

View File

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

View File

@@ -0,0 +1,29 @@
#include "InstrReel.hpp"
#include <spider/runtime/cpu/CPU.hpp>
#include <spider/runtime/memory/Types.hpp>
namespace spider {
// Public Interface //
InstrReel::InstrReel() {}
InstrReel::~InstrReel() {}
// Static Utils //
u16 InstrReel::unpackInstr(u16 bcode) {
return (bcode >> 5) & 0x1FF;
}
u8 InstrReel::unpackAddrMode(u16 bcode) {
return (bcode >> 2) & 0x1F;
}
u8 InstrReel::unpackTypeSize(u16 bcode) {
return bcode & 0x3;
}
}

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;
}