Compare commits

..

31 Commits

Author SHA1 Message Date
Kittycannon 017a3f5f6d debug things 2026-06-16 10:59:48 -06:00
Kittycannon 708c4ab593 updated runtiem 2026-06-14 23:39:17 -06:00
Kittycannon 869ce0c7bf overengineered piece of shit, but compiles fine 2026-06-14 18:15:44 -06:00
Kittycannon 5f4c2abec8 fixed for library use 2026-06-13 13:12:06 -06:00
Kittycannon 0c21587e15 added interns easter eggs, compiles now 2026-06-13 12:45:29 -06:00
Kittycannon a36705a931 removed unnecessary things, updated and audited the code 2026-06-13 11:31:07 -06:00
AlmediaDaniel 29797fb707 test changes 2026-06-11 18:19:37 -06:00
AlmediaDaniel 22d7b0afbe test changes 2026-06-11 18:09:42 -06:00
AlmediaDaniel c3cf293bc9 test changes 2026-06-11 17:35:49 -06:00
AlmediaDaniel bc8fb3435d test changes 2026-06-11 17:34:45 -06:00
AlmediaDaniel 309b823f19 test changes 2026-06-11 17:33:28 -06:00
AlmediaDaniel 31dd45c932 test changes 2026-06-11 17:31:48 -06:00
AlmediaDaniel c018c2c668 undo changes 2026-06-11 17:13:24 -06:00
AlmediaDaniel 2d89f489ae test changes 2026-06-11 17:12:23 -06:00
AlmediaDaniel f1bb779e86 added breaks and removed (this -> *post) 2026-06-11 16:52:51 -06:00
AlmediaDaniel 56114dc1b6 deletion of instructions file outside instr folder. intruction changes 2026-06-11 16:05:06 -06:00
AlmediaDaniel 417bef1aa5 TSB changes 2026-06-11 15:44:53 -06:00
AlmediaDaniel 7cddb55469 TSB changes 2026-06-11 15:43:42 -06:00
AlmediaDaniel 7722e450d4 test changes 2026-06-11 15:25:20 -06:00
AlmediaDaniel 3f6b064e32 Merge branch 'main' of git.sintekanalytics.com:SpiderLang/spider-runtime 2026-06-08 11:37:38 -06:00
AlmediaDaniel 525a9d806b deletion of (this -> *post)() and addition of breaks 2026-06-08 11:37:31 -06:00
Kittycannon 0ad9172dce more changes 2026-06-07 14:45:10 -06:00
Kittycannon ccd6248973 working changes 2026-06-07 14:41:17 -06:00
Kittycannon 51b644cf79 Merge remote-tracking branch 'origin/intr-024-03B'
merging different bases
hold on to your butts
2026-06-07 12:58:33 -06:00
Kittycannon a11732abda Merge remote-tracking branch 'origin/easter-egg-arturo-branch' 2026-06-07 12:53:17 -06:00
Joel-Perez b0b7fa0ebb Implement instructions 0x024-0x03B 2026-04-11 20:49:48 -06:00
Arturo cdf14cf545 added LLGS instruction to CPU.hpp 2026-04-11 11:50:37 -06:00
Arturo c3c94583f4 Map LLGS instruction to opcode 0xF1 2026-04-11 11:35:27 -06:00
Arturo 1fe555aaba Added easter egg by Arturo Balam for 0F1 (slot 1) 2026-04-11 10:02:30 -06:00
Joel-Perez 9cd0570edd feat: implement Spider VM 0.1 ABI and interrupt system 2026-03-24 16:50:07 -06:00
JoelPerez 057ed48df1 first test - function call 2026-03-07 03:04:42 -06:00
22 changed files with 1779 additions and 1339 deletions
+20 -4
View File
@@ -21,7 +21,6 @@ constexpr u8 ADDR_MODE_MASKS[][2] = {
{ 0x04, 0x04 }, // MOR { 0x04, 0x04 }, // MOR
{ 0x00, 0x00 }, // AMOV { 0x00, 0x00 }, // AMOV
{ 0x04, 0x04 }, // SWP { 0x04, 0x04 }, // SWP
{ 0x04, 0x00 }, // AHM
{ 0xFF, 0x00 }, // COM { 0xFF, 0x00 }, // COM
{ 0xFF, 0x00 }, // NEG { 0xFF, 0x00 }, // NEG
{ 0xFF, 0x00 }, // EXS { 0xFF, 0x00 }, // EXS
@@ -37,7 +36,6 @@ constexpr u8 ADDR_MODE_MASKS[][2] = {
{ 0x1E, 0xFF }, // UMOD { 0x1E, 0xFF }, // UMOD
{ 0x1E, 0xFF }, // DMOD { 0x1E, 0xFF }, // DMOD
{ 0x1E, 0xFF }, // UDMD { 0x1E, 0xFF }, // UDMD
{ 0xFF, 0x00 }, // FBT
{ 0x1E, 0xFF }, // STB { 0x1E, 0xFF }, // STB
{ 0x1E, 0xFF }, // CRB { 0x1E, 0xFF }, // CRB
{ 0x1E, 0xFF }, // TSB { 0x1E, 0xFF }, // TSB
@@ -58,6 +56,10 @@ constexpr u8 ADDR_MODE_MASKS[][2] = {
{ 0x1E, 0xFF }, // GE { 0x1E, 0xFF }, // GE
{ 0x1E, 0xFF }, // LT { 0x1E, 0xFF }, // LT
{ 0x1E, 0xFF }, // LE { 0x1E, 0xFF }, // LE
{ 0x1E, 0xFF }, // GTU
{ 0x1E, 0xFF }, // GEU
{ 0x1E, 0xFF }, // LTU
{ 0x1E, 0xFF }, // LEU
{ 0xFF, 0x00 }, // JMP { 0xFF, 0x00 }, // JMP
{ 0xFF, 0x00 }, // JEQ { 0xFF, 0x00 }, // JEQ
{ 0xFF, 0x00 }, // JNE { 0xFF, 0x00 }, // JNE
@@ -135,6 +137,12 @@ constexpr u8 ADDR_MODE_MASKS[][2] = {
{ 0x00, 0x00 }, // XMUL { 0x00, 0x00 }, // XMUL
{ 0x00, 0x00 }, // XDIV { 0x00, 0x00 }, // XDIV
{ 0x00, 0x00 }, // UPY { 0x00, 0x00 }, // UPY
{ 0x00, 0x00 }, // INT_1_SLOT
{ 0x00, 0x00 }, // INT_2_SLOT
{ 0x00, 0x00 }, // INT_3_SLOT
{ 0x00, 0x00 }, // INT_4_SLOT
{ 0x00, 0x00 }, // BRAD
{ 0x00, 0x00 }, // DGANT
}; };
// Type size masks — indexed by opcode. // Type size masks — indexed by opcode.
@@ -153,7 +161,6 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
0x08, // MOR 0x08, // MOR
0x08, // AMOV 0x08, // AMOV
0x08, // SWP 0x08, // SWP
0x08, // AHM
0x0F, // COM 0x0F, // COM
0x0F, // NEG 0x0F, // NEG
0x0F, // EXS 0x0F, // EXS
@@ -169,7 +176,6 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
0x0F, // UMOD 0x0F, // UMOD
0x0F, // DMOD 0x0F, // DMOD
0x0F, // UDMD 0x0F, // UDMD
0x0F, // FBT
0x0F, // STB 0x0F, // STB
0x0F, // CRB 0x0F, // CRB
0x0F, // TSB 0x0F, // TSB
@@ -190,6 +196,10 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
0x0F, // GE 0x0F, // GE
0x0F, // LT 0x0F, // LT
0x0F, // LE 0x0F, // LE
0x0F, // GTU
0x0F, // GEU
0x0F, // LTU
0x0F, // LEU
0x0F, // JMP 0x0F, // JMP
0x0F, // JEQ 0x0F, // JEQ
0x0F, // JNE 0x0F, // JNE
@@ -267,6 +277,12 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
0x00, // XMUL 0x00, // XMUL
0x00, // XDIV 0x00, // XDIV
0x00, // UPY 0x00, // UPY
0x00, // INT_1_SLOT
0x00, // INT_2_SLOT
0x00, // INT_3_SLOT
0x00, // INT_4_SLOT
0x00, // BRAD
0x00, // DGANT
}; };
} // namespace spider } // namespace spider
Binary file not shown.
+19 -23
View File
@@ -1,8 +1,10 @@
#Compiler and Linker #Compiler, Archiver and Linker
CC := g++ CC := g++
AR := ar
ARFLAGS := rcs
#The Target Binary Program # The Target Static Library
TARGET := out.exe TARGET := libspider-runtime.a
#The Directories, Source, Includes, Objects, Binary and Resources #The Directories, Source, Includes, Objects, Binary and Resources
SRCDIR := src SRCDIR := src
@@ -15,49 +17,43 @@ OBJEXT := o
#Flags, Libraries and Includes #Flags, Libraries and Includes
ROOT := ./ ROOT := ./
CFLAGS := -std=c++20 -O2 \ CFLAGS := -std=c++20 -O2 \
-Wall -Werror -Wextra \ -Wall -Werror -Wextra \
-Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align \ -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align \
-Wunused -Woverloaded-virtual -Wconversion \ -Wunused -Woverloaded-virtual -Wconversion \
-Wsign-conversion -Wnull-dereference -Wdouble-promotion \ -Wsign-conversion -Wnull-dereference -Wdouble-promotion \
-Wformat=2 -Wimplicit-fallthrough -Wsuggest-override \ -Wformat=2 -Wimplicit-fallthrough -Wsuggest-override \
-Wextra-semi -Wduplicated-cond -Wduplicated-branches \ -Wextra-semi -Wduplicated-cond -Wduplicated-branches \
-Wlogical-op -Wuseless-cast -Wlogical-op -Wuseless-cast
LFLAGS := -std=c++20 -static-libstdc++ -static-libgcc \
-Wl,--fatal-warnings -Wl,--warn-common
LIB :=
INC := -I./src/ INC := -I./src/
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
#DO NOT EDIT BELOW THIS LINE #DO NOT EDIT BELOW THIS LINE
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT))) OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)))
#Defauilt Make #Default Make
all: directories $(TARGET) all: directories $(TARGET)
#Remake #Remake
remake: cleaner all remake: clean all
#Make the Directories #Make the Directories
directories: directories:
@mkdir -p $(TARGETDIR) @mkdir -p $(TARGETDIR)
@mkdir -p $(BUILDDIR) @mkdir -p $(BUILDDIR)
#Clean only Objecst #Clean only Objects
clean: clean:
@$(RM) -rf $(BUILDDIR) @$(RM) -rf $(BUILDDIR)
#Full Clean, Objects and Binaries
cleaner: clean
@$(RM) -rf $(TARGETDIR)
#Pull in dependency info for *existing* .o files #Pull in dependency info for *existing* .o files
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) -include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))
#Link #Create Static Library (Archive)
$(TARGET): $(OBJECTS) $(TARGET): $(OBJECTS)
$(CC) $(LFLAGS) -o $(TARGETDIR)/$(TARGET) $^ $(LIB) $(AR) $(ARFLAGS) $(TARGETDIR)/$(TARGET) $^
#Compile #Compile
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
@@ -70,4 +66,4 @@ $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
@rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp
#Non-File Targets #Non-File Targets
.PHONY: all remake clean cleaner resources .PHONY: all remake clean
+363 -18
View File
@@ -152,26 +152,26 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Real instructions : 128\n", "Real instructions : 136\n",
"Reserved slots : 14\n", "Reserved slots : 12\n",
"Duplicate check : PASSED\n", "Duplicate check : PASSED\n",
"\n", "\n",
"Groups found:\n", "Groups found:\n",
"group\n", "group\n",
"Integer 19\n", "Integer 19\n",
"System 15\n", "Boolean 16\n",
"Bit Wise 14\n", "Bit Wise 14\n",
"Boolean 12\n", "System 14\n",
"Branch 12\n", "Branch 12\n",
"Floating Point 10\n", "Floating Point 10\n",
"Casts 10\n", "Casts 10\n",
"Memory 9\n", "Memory 8\n",
"Trigonometric 7\n", "Trigonometric 7\n",
"Easter Eggs 7\n",
"Exponential 6\n", "Exponential 6\n",
"Matrix 6\n", "Matrix 6\n",
"SIMD 5\n", "SIMD 5\n",
"Quaternion 2\n", "Quaternion 2\n",
"Easter Eggs 1\n",
"\n", "\n",
"First 5 instructions:\n", "First 5 instructions:\n",
" byte_code mnemonic group params addr_mask_1 type_mask\n", " byte_code mnemonic group params addr_mask_1 type_mask\n",
@@ -284,6 +284,351 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 5,
"id": "ac8bb791",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>skip_0</th>\n",
" <th>skip_1</th>\n",
" <th>byte_code</th>\n",
" <th>mnemonic</th>\n",
" <th>name</th>\n",
" <th>group</th>\n",
" <th>params</th>\n",
" <th>imp</th>\n",
" <th>imm</th>\n",
" <th>abs</th>\n",
" <th>...</th>\n",
" <th>B</th>\n",
" <th>S</th>\n",
" <th>I</th>\n",
" <th>L</th>\n",
" <th>F</th>\n",
" <th>D</th>\n",
" <th>type_mask</th>\n",
" <th>expensive</th>\n",
" <th>operation</th>\n",
" <th>skip_2</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>140</th>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>08C</td>\n",
" <td>XAMA</td>\n",
" <td>SIMD Alternate Multiply-Add</td>\n",
" <td>SIMD</td>\n",
" <td>0</td>\n",
" <td>1.0</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>...</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>00</td>\n",
" <td>NaN</td>\n",
" <td></td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>141</th>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>08D</td>\n",
" <td>XMUL</td>\n",
" <td>SIMD Multiply</td>\n",
" <td>SIMD</td>\n",
" <td>0</td>\n",
" <td>1.0</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>...</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>00</td>\n",
" <td>NaN</td>\n",
" <td></td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>142</th>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>08E</td>\n",
" <td>XDIV</td>\n",
" <td>SIMD Divide</td>\n",
" <td>SIMD</td>\n",
" <td>0</td>\n",
" <td>1.0</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>...</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>00</td>\n",
" <td>NaN</td>\n",
" <td></td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>240</th>\n",
" <td>NaN</td>\n",
" <td>Easter Eggs</td>\n",
" <td>0F0</td>\n",
" <td>UPY</td>\n",
" <td>Will place \"YUPI\" in memory</td>\n",
" <td>Easter Eggs</td>\n",
" <td>0</td>\n",
" <td>1.0</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>...</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>00</td>\n",
" <td>NaN</td>\n",
" <td></td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>241</th>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>0F1</td>\n",
" <td>INT_1_SLOT</td>\n",
" <td></td>\n",
" <td>Easter Eggs</td>\n",
" <td>0</td>\n",
" <td>1.0</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>...</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>00</td>\n",
" <td>NaN</td>\n",
" <td></td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>242</th>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>0F2</td>\n",
" <td>INT_2_SLOT</td>\n",
" <td></td>\n",
" <td>Easter Eggs</td>\n",
" <td>0</td>\n",
" <td>1.0</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>...</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>00</td>\n",
" <td>NaN</td>\n",
" <td></td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>243</th>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>0F3</td>\n",
" <td>INT_3_SLOT</td>\n",
" <td></td>\n",
" <td>Easter Eggs</td>\n",
" <td>0</td>\n",
" <td>1.0</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>...</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>00</td>\n",
" <td>NaN</td>\n",
" <td></td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>244</th>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>0F4</td>\n",
" <td>INT_4_SLOT</td>\n",
" <td></td>\n",
" <td>Easter Eggs</td>\n",
" <td>0</td>\n",
" <td>1.0</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>...</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>00</td>\n",
" <td>NaN</td>\n",
" <td></td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>245</th>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>0F5</td>\n",
" <td>BRAD</td>\n",
" <td></td>\n",
" <td>Easter Eggs</td>\n",
" <td>0</td>\n",
" <td>1.0</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>...</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>00</td>\n",
" <td>NaN</td>\n",
" <td></td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>246</th>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>0F6</td>\n",
" <td>DGANT</td>\n",
" <td></td>\n",
" <td>Easter Eggs</td>\n",
" <td>0</td>\n",
" <td>1.0</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>...</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>X</td>\n",
" <td>00</td>\n",
" <td>NaN</td>\n",
" <td></td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>10 rows × 29 columns</p>\n",
"</div>"
],
"text/plain": [
" skip_0 skip_1 byte_code mnemonic name \\\n",
"140 NaN NaN 08C XAMA SIMD Alternate Multiply-Add \n",
"141 NaN NaN 08D XMUL SIMD Multiply \n",
"142 NaN NaN 08E XDIV SIMD Divide \n",
"240 NaN Easter Eggs 0F0 UPY Will place \"YUPI\" in memory \n",
"241 NaN NaN 0F1 INT_1_SLOT \n",
"242 NaN NaN 0F2 INT_2_SLOT \n",
"243 NaN NaN 0F3 INT_3_SLOT \n",
"244 NaN NaN 0F4 INT_4_SLOT \n",
"245 NaN NaN 0F5 BRAD \n",
"246 NaN NaN 0F6 DGANT \n",
"\n",
" group params imp imm abs ... B S I L F D type_mask \\\n",
"140 SIMD 0 1.0 X X ... X X X X X X 00 \n",
"141 SIMD 0 1.0 X X ... X X X X X X 00 \n",
"142 SIMD 0 1.0 X X ... X X X X X X 00 \n",
"240 Easter Eggs 0 1.0 X X ... X X X X X X 00 \n",
"241 Easter Eggs 0 1.0 X X ... X X X X X X 00 \n",
"242 Easter Eggs 0 1.0 X X ... X X X X X X 00 \n",
"243 Easter Eggs 0 1.0 X X ... X X X X X X 00 \n",
"244 Easter Eggs 0 1.0 X X ... X X X X X X 00 \n",
"245 Easter Eggs 0 1.0 X X ... X X X X X X 00 \n",
"246 Easter Eggs 0 1.0 X X ... X X X X X X 00 \n",
"\n",
" expensive operation skip_2 \n",
"140 NaN NaN \n",
"141 NaN NaN \n",
"142 NaN NaN \n",
"240 NaN NaN \n",
"241 NaN NaN \n",
"242 NaN NaN \n",
"243 NaN NaN \n",
"244 NaN NaN \n",
"245 NaN NaN \n",
"246 NaN NaN \n",
"\n",
"[10 rows x 29 columns]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"instrs_df.tail(10)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "452bc76c", "id": "452bc76c",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -292,7 +637,7 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Masks written to: .//autogen/InstructionMasks.hpp\n", "Masks written to: .//autogen/InstructionMasks.hpp\n",
"Lines generated : 272\n" "Lines generated : 288\n"
] ]
} }
], ],
@@ -357,7 +702,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 7,
"id": "5aaebef0", "id": "5aaebef0",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -365,7 +710,7 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Instructions formatted: 128\n", "Instructions formatted: 136\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",
@@ -380,7 +725,7 @@
"\n", "\n",
"\n", "\n",
"CPU.hpp updated successfully at: .//src//spider/runtime/cpu/CPU.hpp\n", "CPU.hpp updated successfully at: .//src//spider/runtime/cpu/CPU.hpp\n",
"Total lines in updated file: 883\n" "Total lines in updated file: 942\n"
] ]
} }
], ],
@@ -451,7 +796,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": 8,
"id": "instrmap_gen", "id": "instrmap_gen",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -460,9 +805,9 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"InstrMap.cpp written to: .//src//spider/runtime/instr/InstrMap.cpp\n", "InstrMap.cpp written to: .//src//spider/runtime/instr/InstrMap.cpp\n",
" Size : 34,157 bytes\n", " Size : 33,582 bytes\n",
" Array entries : 512 (128 populated, 384 nullptr)\n", " Array entries : 512 (136 populated, 376 nullptr)\n",
" Switch cases : 128\n", " Switch cases : 136\n",
" Line endings : LF-only verified\n" " Line endings : LF-only verified\n"
] ]
} }
@@ -545,11 +890,11 @@
" mnem = opcode_to_mnem.get(opc)\n", " mnem = opcode_to_mnem.get(opc)\n",
" if mnem:\n", " if mnem:\n",
" name = opcode_to_name[opc]\n", " name = opcode_to_name[opc]\n",
" L.append(f' &CPU::{mnem + \",\":<28s}// 0x{opc:03X} — {name}')\n", " L.append(f' &CPU::{mnem + \",\":<22s}// 0x{opc:03X} — {name}')\n",
" else:\n", " else:\n",
" tag = ''\n", " tag = ''\n",
" if opc in reserved_opcodes:\n", " if opc in reserved_opcodes:\n",
" tag = ' (reserved)'\n", " tag = ' (reserved)'\n",
" L.append(f' {\"nullptr,\":<28s}// 0x{opc:03X}{tag}')\n", " L.append(f' {\"nullptr,\":<28s}// 0x{opc:03X}{tag}')\n",
"\n", "\n",
"L.append('};')\n", "L.append('};')\n",
@@ -618,7 +963,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": 9,
"id": "9f190f4c", "id": "9f190f4c",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
@@ -681,7 +1026,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.14.3" "version": "3.13.7"
} }
}, },
"nbformat": 4, "nbformat": 4,
+2 -10
View File
@@ -1,18 +1,10 @@
#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 u32 RUNTIME_VERSION_NO = 0x00000001; // v0.1
const std::string RUNTIME_VERSION = "alpha v0.1"; const std::string RUNTIME_VERSION = "alpha v0.1";
} }
int main() {
spider::liveDebugMain();
return 0;
}
+36 -6
View File
@@ -1,5 +1,7 @@
#include "Runtime.hpp" #include "Runtime.hpp"
#include <chrono>
namespace spider { namespace spider {
// Constructors & Destructors // // Constructors & Destructors //
@@ -17,14 +19,17 @@ namespace spider {
// Stepping/Running the Machine // // Stepping/Running the Machine //
void Runtime::step() { void Runtime::step() {
// fetchInstr() decodes the opcode, addressing mode and type siz // fetchInstr() decodes the opcode,
// addressing mode and type size
cpu.fetchInstr(); cpu.fetchInstr();
// execute() completes the fetch-decode-execute cycle by calling the correct instruction method based on the opcode. // execute() completes the fetch-decode-execute
// cycle by calling the correct instruction
// method based on the opcode.
cpu.execute(); cpu.execute();
} }
void Runtime::step(u64 n) { void Runtime::step(u64 n) {
while(n >= 4) { while (n >= 4) {
step(); step();
step(); step();
step(); step();
@@ -34,9 +39,34 @@ namespace spider {
while (n--) step(); while (n--) step();
} }
void Runtime::run() {} u64 Runtime::run() {
// TODO: Must use the flag register
// for the enabled bit.
return 0;
}
//void Runtime::run(u64 n) {} u64 Runtime::run(u64 n) {
using namespace std::chrono;
u64 total_steps = 0;
auto start_time = high_resolution_clock::now();
// TODO: Must use the flag register
// for the enabled bit.
while (true) {
step();
step();
step();
step();
total_steps += 4;
// measure time!
auto current_time = high_resolution_clock::now();
auto elapsed = duration_cast<milliseconds>(current_time - start_time).count();
if (static_cast<u64>(elapsed) >= n) break;
}
return total_steps;
}
// Misc // // Misc //
@@ -50,7 +80,7 @@ namespace spider {
void Runtime::hookReel(InstrReel* newReel, bool own) { void Runtime::hookReel(InstrReel* newReel, bool own) {
delete this->reel; delete this->reel;
cpu.hookInstrReel(newReel); cpu.hookInstrReel(newReel);
if(own) this->reel = newReel; if (own) this->reel = newReel;
} }
} }
+6 -2
View File
@@ -55,14 +55,18 @@ namespace spider {
* Sets the machine to run continously. * Sets the machine to run continously.
* If interrupts occur, they will be handled * If interrupts occur, they will be handled
* automatically. * automatically.
*
* Returns the amount of cycles ran.
*/ */
void run(); u64 run();
/** /**
* Runs this machine for a set amount of * Runs this machine for a set amount of
* milliseconds. * milliseconds.
*
* Returns the amount of cycles ran.
*/ */
void run(u64 ms); u64 run(u64 ms);
public: public:
+188 -23
View File
@@ -1,33 +1,198 @@
#include "CPU.hpp" #include "CPU.hpp"
#include <spider/runtime/native/machine.hpp>
#include <spider/runtime/memory/RAM.hpp>
#include <spider/runtime/memory/Types.hpp>
#include <spider/runtime/reel/InstrReel.hpp>
#if __cplusplus >= 202002L
#include <bit>
#endif
namespace spider { namespace spider {
CPU::CPU() CPU::CPU()
: RA{}, RB{}, RC{}, RD{}, : RA{}, RB{}, RC{}, RD{},
RX{}, RY{}, R0{}, R1{}, RX{}, RY{}, R0{}, R1{},
R2{}, R3{}, R4{}, R5{}, R2{}, R3{}, R4{}, R5{},
R6{}, R7{}, R8{}, R9{}, R6{}, R7{}, R8{}, R9{},
RF{}, RI{}, RS{}, RZ{}, RF{}, RI{}, RS{}, RZ{},
RE{}, RN{}, RV{}, RM{} RE{}, RN{}, RV{}, RM{},
{} ALU0{}, ALU1{},
_dst(nullptr), _src(nullptr),
_opcode(0), _addrm(0), _size(0),
_store(0), _post(&CPU::imp),
_ram(nullptr), _reel(nullptr) {
}
CPU::~CPU() {} CPU::~CPU() {}
} // Setup & Configuration //
/**
* @brief BRAD (0xF7) - Memory Integrity Checksum void CPU::hookRAM(RAM* ram) {
* Escanea los primeros 256 bytes de memoria y valida contra una firma de seguridad. this->_ram = ram;
* 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) void CPU::hookInstrReel(InstrReel* reel) {
RA = (checksum == MAGIC_SIGNATURE) ? 1 : 0; this->_reel = reel;
} }
constexpr u64 CPU::getFlag(u64 mask) {
if (!mask) return 0;
#if __cplusplus >= 202002L
return (RF & mask) >> std::countr_zero(mask);
#elif defined(SPIDER_COMPILER_GCC_LIKE)
return (RF & mask) >> __builtin_ctzll(mask);
#elif defined(SPIDER_COMPILER_MSVC)
return (RF & mask) >> _BitScanForward64(mask);
#else
// If you have reached this part,
// please come up with a better alternative.
u64 bits = RF & mask;
while (mask && (mask >>= 1)) bits >>= 1;
return bits;
#endif
}
// Interaction with Reel //
CPU::Fn CPU::addrModes[] = {
&CPU::imm, &CPU::abs,
&CPU::reg, &CPU::ind,
&CPU::ptr, &CPU::idx,
&CPU::sca, &CPU::dis
};
void CPU::fetchInstr() {
u16 i = _reel->readU16(RI);
RX._u16 = i;
const u16 oc = (i >> 7);
RY._u16 = oc;
_opcode = oc & 0x1FF; // GCC WHY!
_addrm = static_cast<u8>((i >> 2) & 0x1F);
_size = static_cast<u8>(i & 0x3);
RI += 2;
}
void CPU::fetchOperDst() {
// Move the operand ptrs
_opers[1] = _opers[0];
_opers[0] = &ALU0;
// call specific addressing mode
(this->*(CPU::addrModes[_addrm & 0b111]))(); // mask added here too
}
void CPU::fetchOperSrc() {
// set ALU
_opers[0] = &ALU1;
// call specific addressing mode
(this->*(CPU::addrModes[_addrm & 0b111]))(); // mask keeps index within 0-7
// modify the _addrm register
_addrm = static_cast<u8>((_addrm >> 3) & 0x1F);
_addrm++;
}
void CPU::fetchOperReg() {
_dst = &GPR[_reel->readU8(RI++) & 0xF];
}
void CPU::fetchOperRegReg() {
// read the full byte
u8 reg = _reel->readU8(RI++);
_src = &GPR[(reg >> 4) & 0xF];
_dst = &GPR[ reg & 0xF];
}
void CPU::execute() {
(this->*(CPU::instrMap[_opcode]))(); // no null check needed
// vvv MUST PROFILE: Is this faster than executing an empty function?
if(_post) (this->*_post)();
}
// Addressing Modes //
/**
* Implied Addressing Mode
*/
void CPU::imp() {
// Nothing //
}
/**
* Immediate Addressing Mode
*/
void CPU::imm() {
_reel->loadRegister(RI, _size, _opers[0]);
_post = &CPU::imp;
RI += 1 << _size;
}
/**
* Absolute Addressing Mode
*/
void CPU::abs() {
// Load the actual ptr into the ALU
u8 mm = u8(getFlag(CPU::FLAG_MEMORY_MODE));
_reel->loadRegister(RI, mm, _opers[0]);
RI += 1 << mm;
// read the memory from RAM
_store = _opers[0]->_u64;
_ram->loadRegister(_store, _size, _opers[0]);
_post = &CPU::psw;
}
/**
* Register Addressing Mode
*/
void CPU::reg() {
// Two consecutive registers can be declared
// Shift if the top part will become .reg too
u8 sh = ((_addrm & 0b11000) == 0b11000) * 4;
u8 use = 1 - (sh >> 2); // (sh / 4)
// get byte
u8 reg = (_reel->readU8(RI) >> sh) & 0xF;
_opers[0] = &GPR[reg]; // explicitly sets _opers[0] = _dst
RI += use;
// store no-op
_post = nullptr;
}
/**
* Indrect Addressing Mode
*/
void CPU::ind() {}
/**
* Pointer Addressing Mode
*/
void CPU::ptr() {}
/**
* Indexed Addressing Mode
*/
void CPU::idx() {}
/**
* Scaled Addressing Mode
*/
void CPU::sca() {}
/**
* Displaced Addressing Mode
*/
void CPU::dis() {}
/**
* Post Write Action
*/
void CPU::psw() {}
}
+82 -36
View File
@@ -64,7 +64,6 @@ namespace spider {
struct { struct {
register_t* _dst; register_t* _dst;
register_t* _src; register_t* _src;
register_t* _alu;
}; };
register_t* _opers[2]; register_t* _opers[2];
}; };
@@ -91,11 +90,11 @@ namespace spider {
/** /**
* Pointer to the current RAM hooked into * Pointer to the current RAM hooked into
* the CPU. * the CPU.
* *
* It is unproved whether having the RAM directly * It is unproved whether having the RAM directly
* into the CPU is better than not, or whether a * into the CPU is better than not, or whether a
* virtual BUS is better. * virtual BUS is better.
* *
* Alas, this way we can have a CPU state switch * Alas, this way we can have a CPU state switch
* between memory and instruction banks. * between memory and instruction banks.
*/ */
@@ -104,7 +103,7 @@ namespace spider {
/** /**
* Pointer to the current Instruction Reel * Pointer to the current Instruction Reel
* hooked into the CPU. * hooked into the CPU.
* *
* Ditto as RAM. * Ditto as RAM.
*/ */
InstrReel* _reel; InstrReel* _reel;
@@ -120,7 +119,7 @@ namespace spider {
~CPU(); ~CPU();
public: public:
CPU& operator=(const CPU& other) = default; CPU& operator=(const CPU& other) = default;
CPU& operator=(CPU&& other) noexcept = default; CPU& operator=(CPU&& other) noexcept = default;
@@ -132,7 +131,7 @@ namespace spider {
void hookInstrReel(InstrReel* reel); void hookInstrReel(InstrReel* reel);
constexpr u64 getFlag(u64 mask); constexpr u64 getFlag(u64 mask);
public: public:
/** /**
@@ -145,11 +144,11 @@ namespace spider {
* Fetches the destination operand, * Fetches the destination operand,
* by calling the appropriate addressing * by calling the appropriate addressing
* mode. * mode.
* *
* Will read the bottom 3 bits. * Will read the bottom 3 bits.
* For instructions with two operands, * For instructions with two operands,
* call Src first. * call Src first.
* *
* The internal variable _addrm * The internal variable _addrm
* will not be modified. It will * will not be modified. It will
* be important when writing * be important when writing
@@ -159,19 +158,31 @@ namespace spider {
/** /**
* Fetches the source operand. * Fetches the source operand.
* *
* For use in two operand instructions. * For use in two operand instructions.
* *
* Will read the bottom 3 bits. It will * Will read the bottom 3 bits. It will
* then shift the _addrm 3 spaces * then shift the _addrm 3 spaces
* to ensure it aligns with the DST * to ensure it aligns with the DST
* next. * next.
* *
* Additionally, it will add 1 to _addrm * Additionally, it will add 1 to _addrm
* to account with * to account with
*/ */
void fetchOperSrc(); void fetchOperSrc();
/**
* Fetches special addressing where
* one register is addressed.
*/
void fetchOperReg();
/**
* Fetches special addressing where
* two registers are addressed.
*/
void fetchOperRegReg();
/** /**
* Executes an opcode, by means of directly * Executes an opcode, by means of directly
* accessing the instruction map and * accessing the instruction map and
@@ -184,7 +195,7 @@ namespace spider {
* a large switch statement. Only suitable * a large switch statement. Only suitable
* for environments where the instruction * for environments where the instruction
* map is not possible. * map is not possible.
* *
* This has yet to be proved!!! * This has yet to be proved!!!
*/ */
void executeSwLk(); void executeSwLk();
@@ -205,32 +216,32 @@ namespace spider {
* Absolute Addressing Mode * Absolute Addressing Mode
*/ */
void abs(); void abs();
/** /**
* Register Addressing Mode * Register Addressing Mode
*/ */
void reg(); void reg();
/** /**
* Indrect Addressing Mode * Indrect Addressing Mode
*/ */
void ind(); void ind();
/** /**
* Pointer Addressing Mode * Pointer Addressing Mode
*/ */
void ptr(); void ptr();
/** /**
* Indexed Addressing Mode * Indexed Addressing Mode
*/ */
void idx(); void idx();
/** /**
* Scaled Addressing Mode * Scaled Addressing Mode
*/ */
void sca(); void sca();
/** /**
* Displaced Addressing Mode * Displaced Addressing Mode
*/ */
@@ -314,11 +325,6 @@ namespace spider {
// Operation: Src <-> Dst // Operation: Src <-> Dst
void SWP(); 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 // [Integer] 0x010 — COM: One's complement
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F // Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: ~ Dst -> Dst // Operation: ~ Dst -> Dst
@@ -394,11 +400,6 @@ namespace spider {
// Operation: Unsigned Dst / Src -> X, Dst % Src -> Y // Operation: Unsigned Dst / Src -> X, Dst % Src -> Y
void UDMD(); 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 // [Bit Wise] 0x020 — STB: Set Bit
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Src# bit is set on Dst // Operation: Src# bit is set on Dst
@@ -469,36 +470,56 @@ namespace spider {
// Operation: # of 1's into Dst // Operation: # of 1's into Dst
void CNT(); void CNT();
// [Boolean] 0x030 — EQ: Equal // [Boolean] 0x02E — EQ: Equal
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst == Src into Dst // Operation: Dst == Src into Dst
void EQ(); void EQ();
// [Boolean] 0x031 — NE: Not Equal // [Boolean] 0x02F — NE: Not Equal
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst != Src into Dst // Operation: Dst != Src into Dst
void NE(); void NE();
// [Boolean] 0x032 — GT: Greater Than // [Boolean] 0x030 — GT: Greater Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst > Src into Dst // Operation: Dst > Src into Dst
void GT(); void GT();
// [Boolean] 0x033 — GE: Greater or Equal Than // [Boolean] 0x031 — GE: Greater or Equal Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst >= Src into Dst // Operation: Dst >= Src into Dst
void GE(); void GE();
// [Boolean] 0x034 — LT: Lower Than // [Boolean] 0x032 — LT: Lower Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst < Src into Dst // Operation: Dst < Src into Dst
void LT(); void LT();
// [Boolean] 0x035 — LE: Lower or Equal Than // [Boolean] 0x033 — LE: Lower or Equal Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst <= Src into Dst // Operation: Dst <= Src into Dst
void LE(); void LE();
// [Boolean] 0x034 — GTU: Greater Than, Unsigned
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst > Src into Dst
void GTU();
// [Boolean] 0x035 — GEU: Greater or Equal Than, Unsigned
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst >= Src into Dst
void GEU();
// [Boolean] 0x036 — LTU: Lower Than, Unsigned
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst < Src into Dst
void LTU();
// [Boolean] 0x037 — LEU: Lower or Equal Than, Unsigned
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst <= Src into Dst
void LEU();
// [Branch] 0x038 — JMP: Jump to absolute position // [Branch] 0x038 — JMP: Jump to absolute position
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F // Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst -> Instruction Register // Operation: Dst -> Instruction Register
@@ -884,9 +905,34 @@ namespace spider {
// Operation: // Operation:
void UPY(); void UPY();
// [Easter Eggs] 0x0F6DGANT: "In kaaba Spider" (Yucatec Maya: My name is Spider) // [Easter Eggs] 0x0F1INT_1_SLOT:
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: Writes "IN KAABA SPIDER" one char per GP register // Operation:
void INT_1_SLOT();
// [Easter Eggs] 0x0F2 — INT_2_SLOT:
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void INT_2_SLOT();
// [Easter Eggs] 0x0F3 — INT_3_SLOT:
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void INT_3_SLOT();
// [Easter Eggs] 0x0F4 — INT_4_SLOT:
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void INT_4_SLOT();
// [Easter Eggs] 0x0F5 — BRAD:
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void BRAD();
// [Easter Eggs] 0x0F6 — DGANT:
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation:
void DGANT(); void DGANT();
// </pygen-target> // // </pygen-target> //
-25
View File
@@ -1,25 +0,0 @@
#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() {}
}
-402
View File
@@ -1,402 +0,0 @@
#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;
}
}
-7
View File
@@ -1,7 +0,0 @@
#pragma once
namespace spider {
int liveDebugMain();
}
+164 -158
View File
@@ -35,149 +35,149 @@ namespace spider {
* if (fn) (cpu.*fn)(); * if (fn) (cpu.*fn)();
*/ */
CPU::Fn CPU::instrMap[] = { CPU::Fn CPU::instrMap[] = {
&CPU::NOP, // 0x000 — No Operation &CPU::NOP, // 0x000 — No Operation
&CPU::SPDR, // 0x001 — Will place the Spider version of the interpreter in RA &CPU::SPDR, // 0x001 — Will place the Spider version of the interpreter in RA
&CPU::MMODE, // 0x002 — Set Memory Mode &CPU::MMODE, // 0x002 — Set Memory Mode
&CPU::INT, // 0x003 — Interrupt &CPU::INT, // 0x003 — Interrupt
&CPU::LRV, // 0x004 — Load Interrupt Vector Register &CPU::LRV, // 0x004 — Load Interrupt Vector Register
&CPU::FSR, // 0x005 — Fetch System Register &CPU::FSR, // 0x005 — Fetch System Register
&CPU::FIR, // 0x006 — Fetch Instruction Register &CPU::FIR, // 0x006 — Fetch Instruction Register
&CPU::FZR, // 0x007 — Fetch Stack Base Register &CPU::FZR, // 0x007 — Fetch Stack Base Register
&CPU::LSR, // 0x008 — Load System Register &CPU::LSR, // 0x008 — Load System Register
&CPU::FVR, // 0x009 — Fetch Interrupt Vector Register &CPU::FVR, // 0x009 — Fetch Interrupt Vector Register
&CPU::MOV, // 0x00A — Moves values &CPU::MOV, // 0x00A — Moves values
&CPU::MOR, // 0x00B — Moves registers &CPU::MOR, // 0x00B — Moves registers
&CPU::AMOV, // 0x00C — Array Move, uses X and Y as ptrs, A as amount &CPU::AMOV, // 0x00C — Array Move, uses X and Y as ptrs, A as amount
&CPU::SWP, // 0x00D — Swap registers &CPU::SWP, // 0x00D — Swap registers
&CPU::AHM, // 0x00E — Ask Host for Memory nullptr, // 0x00E (reserved)
nullptr, // 0x00F (reserved) nullptr, // 0x00F (reserved)
&CPU::COM, // 0x010 — One's complement &CPU::COM, // 0x010 — One's complement
&CPU::NEG, // 0x011 — Two's complement &CPU::NEG, // 0x011 — Two's complement
&CPU::EXS, // 0x012 — Extend Sign &CPU::EXS, // 0x012 — Extend Sign
&CPU::INC, // 0x013 — Increment &CPU::INC, // 0x013 — Increment
&CPU::DEC, // 0x014 — Decrement &CPU::DEC, // 0x014 — Decrement
&CPU::ADD, // 0x015 — Addition &CPU::ADD, // 0x015 — Addition
&CPU::SUB, // 0x016 — Subtraction &CPU::SUB, // 0x016 — Subtraction
&CPU::MUL, // 0x017 — Multiplication &CPU::MUL, // 0x017 — Multiplication
&CPU::UMUL, // 0x018 — Unsigned Multiplication &CPU::UMUL, // 0x018 — Unsigned Multiplication
&CPU::DIV, // 0x019 — Division &CPU::DIV, // 0x019 — Division
&CPU::UDIV, // 0x01A — Unsigned Division &CPU::UDIV, // 0x01A — Unsigned Division
&CPU::MOD, // 0x01B — Modulus &CPU::MOD, // 0x01B — Modulus
&CPU::UMOD, // 0x01C — Unsigned Modulus &CPU::UMOD, // 0x01C — Unsigned Modulus
&CPU::DMOD, // 0x01D — Division and Modulus &CPU::DMOD, // 0x01D — Division and Modulus
&CPU::UDMD, // 0x01E — Unsigned Division and Modulus &CPU::UDMD, // 0x01E — Unsigned Division and Modulus
&CPU::FBT, // 0x01F — Test and update Flag Register (Integer) Bits nullptr, // 0x01F (reserved)
&CPU::STB, // 0x020 — Set Bit &CPU::STB, // 0x020 — Set Bit
&CPU::CRB, // 0x021 — Clear Bit &CPU::CRB, // 0x021 — Clear Bit
&CPU::TSB, // 0x022 — Test Bit &CPU::TSB, // 0x022 — Test Bit
&CPU::BOOL, // 0x023 — Sets the booleaness of a value &CPU::BOOL, // 0x023 — Sets the booleaness of a value
&CPU::NOT, // 0x024 — Sets the inverse booleaness of a value (! BOOL) &CPU::NOT, // 0x024 — Sets the inverse booleaness of a value (! BOOL)
&CPU::AND, // 0x025 — Boolean AND operation &CPU::AND, // 0x025 — Boolean AND operation
&CPU::OR, // 0x026 — Boolean OR operation &CPU::OR, // 0x026 — Boolean OR operation
&CPU::XOR, // 0x027 — Boolean XOR operation &CPU::XOR, // 0x027 — Boolean XOR operation
&CPU::SHL, // 0x028 — Arithmetic Shift Left &CPU::SHL, // 0x028 — Arithmetic Shift Left
&CPU::SHR, // 0x029 — Arithmetic Shift Right &CPU::SHR, // 0x029 — Arithmetic Shift Right
&CPU::SSR, // 0x02A — Signed Shift Right &CPU::SSR, // 0x02A — Signed Shift Right
&CPU::ROL, // 0x02B — Rotate Left &CPU::ROL, // 0x02B — Rotate Left
&CPU::ROR, // 0x02C — Rotate Right &CPU::ROR, // 0x02C — Rotate Right
&CPU::CNT, // 0x02D — Counts bits &CPU::CNT, // 0x02D — Counts bits
nullptr, // 0x02E (reserved) &CPU::EQ, // 0x02E — Equal
nullptr, // 0x02F (reserved) &CPU::NE, // 0x02F — Not Equal
&CPU::EQ, // 0x030 — Equal &CPU::GT, // 0x030 — Greater Than
&CPU::NE, // 0x031 — Not Equal &CPU::GE, // 0x031 — Greater or Equal Than
&CPU::GT, // 0x032 — Greater Than &CPU::LT, // 0x032 — Lower Than
&CPU::GE, // 0x033 — Greater or Equal Than &CPU::LE, // 0x033 — Lower or Equal Than
&CPU::LT, // 0x034 — Lower Than &CPU::GTU, // 0x034 — Greater Than, Unsigned
&CPU::LE, // 0x035 — Lower or Equal Than &CPU::GEU, // 0x035 — Greater or Equal Than, Unsigned
nullptr, // 0x036 (reserved) &CPU::LTU, // 0x036 — Lower Than, Unsigned
nullptr, // 0x037 (reserved) &CPU::LEU, // 0x037 — Lower or Equal Than, Unsigned
&CPU::JMP, // 0x038 — Jump to absolute position &CPU::JMP, // 0x038 — Jump to absolute position
&CPU::JEQ, // 0x039 — Jumps to position if EQ flag is set &CPU::JEQ, // 0x039 — Jumps to position if EQ flag is set
&CPU::JNE, // 0x03A — Jumps to position if EQ flag is cleared &CPU::JNE, // 0x03A — Jumps to position if EQ flag is cleared
&CPU::JIF, // 0x03B — Jumps if value provided is booleanly true &CPU::JIF, // 0x03B — Jumps if value provided is booleanly true
&CPU::JMR, // 0x03C — Jump Relative &CPU::JMR, // 0x03C — Jump Relative
&CPU::JER, // 0x03D — Jumps to relative position if EQ flag is set &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::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::JIR, // 0x03F — Jumps to relative position if value provided is booleanly true
&CPU::SFB, // 0x040 — Store (User) Flag Bit &CPU::SFB, // 0x040 — Store (User) Flag Bit
&CPU::LFB, // 0x041 — Load (User) Flag Bit &CPU::LFB, // 0x041 — Load (User) Flag Bit
&CPU::JUF, // 0x042 — Jump to absolute position, if user flag is true &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::JUR, // 0x043 — Jump to relative position, if user flag is true
&CPU::PUSH, // 0x044 — Push to stack &CPU::PUSH, // 0x044 — Push to stack
&CPU::POP, // 0x045 — Pop from stack &CPU::POP, // 0x045 — Pop from stack
&CPU::ALLOC, // 0x046 — Allocate to heap &CPU::ALLOC, // 0x046 — Allocate to heap
&CPU::HFREE, // 0x047 — Delete from heap &CPU::HFREE, // 0x047 — Delete from heap
nullptr, // 0x048 (reserved) nullptr, // 0x048 (reserved)
nullptr, // 0x049 (reserved) nullptr, // 0x049 (reserved)
&CPU::CALL, // 0x04A — Call function at instruction index &CPU::CALL, // 0x04A — Call function at instruction index
&CPU::RET, // 0x04B — Return from a function &CPU::RET, // 0x04B — Return from a function
&CPU::EDI, // 0x04C — Enable/Disable External Interrupts &CPU::EDI, // 0x04C — Enable/Disable External Interrupts
&CPU::SHSS, // 0x04D — Set Hotswap Signal Bit &CPU::SHSS, // 0x04D — Set Hotswap Signal Bit
nullptr, // 0x04E (reserved) nullptr, // 0x04E (reserved)
nullptr, // 0x04F (reserved) nullptr, // 0x04F (reserved)
&CPU::FLI, // 0x050 — Float Load Immediate &CPU::FLI, // 0x050 — Float Load Immediate
&CPU::FNEG, // 0x051 — Float negate &CPU::FNEG, // 0x051 — Float negate
&CPU::FADD, // 0x052 — Float add &CPU::FADD, // 0x052 — Float add
&CPU::FSUB, // 0x053 — Float subtract &CPU::FSUB, // 0x053 — Float subtract
&CPU::FMUL, // 0x054 — Float multiplication &CPU::FMUL, // 0x054 — Float multiplication
&CPU::FDIV, // 0x055 — Float division &CPU::FDIV, // 0x055 — Float division
&CPU::FMOD, // 0x056 — Float modulus &CPU::FMOD, // 0x056 — Float modulus
&CPU::FDMOD, // 0x057 — Float division and modulus &CPU::FDMOD, // 0x057 — Float division and modulus
&CPU::FEPS, // 0x058 — Sets the float epsilon value, for comparison &CPU::FEPS, // 0x058 — Sets the float epsilon value, for comparison
&CPU::FEEP, // 0x059 — Float Enable/Disable Epsilon &CPU::FEEP, // 0x059 — Float Enable/Disable Epsilon
&CPU::FEQ, // 0x05A — Float Equal &CPU::FEQ, // 0x05A — Float Equal
&CPU::FNE, // 0x05B — Float Not Equal &CPU::FNE, // 0x05B — Float Not Equal
&CPU::FGT, // 0x05C — Float Greater Than &CPU::FGT, // 0x05C — Float Greater Than
&CPU::FGE, // 0x05D — Float Greater or Equal Than &CPU::FGE, // 0x05D — Float Greater or Equal Than
&CPU::FLT, // 0x05E — Float Lower Than &CPU::FLT, // 0x05E — Float Lower Than
&CPU::FLE, // 0x05F — Float Lower or Equal Than &CPU::FLE, // 0x05F — Float Lower or Equal Than
&CPU::F2D, // 0x060 — F32 (Float) to F64 (Double) &CPU::F2D, // 0x060 — F32 (Float) to F64 (Double)
&CPU::D2F, // 0x061 — F64 (Double) to F32 (Float) &CPU::D2F, // 0x061 — F64 (Double) to F32 (Float)
&CPU::I2F, // 0x062 — I32 (Integer) to F32 (Float) &CPU::I2F, // 0x062 — I32 (Integer) to F32 (Float)
&CPU::I2D, // 0x063 — I32 (Integer) to F64 (Double) &CPU::I2D, // 0x063 — I32 (Integer) to F64 (Double)
&CPU::L2F, // 0x064 — I64 (Long) to F32 (Float) &CPU::L2F, // 0x064 — I64 (Long) to F32 (Float)
&CPU::L2D, // 0x065 — I64 (Long) to F64 (Double) &CPU::L2D, // 0x065 — I64 (Long) to F64 (Double)
&CPU::F2I, // 0x066 — F32 (Float) to I32 (Integer) &CPU::F2I, // 0x066 — F32 (Float) to I32 (Integer)
&CPU::F2L, // 0x067 — F32 (Float) to I64 (Long) &CPU::F2L, // 0x067 — F32 (Float) to I64 (Long)
&CPU::D2I, // 0x068 — F64 (Double) to I32 (Integer) &CPU::D2I, // 0x068 — F64 (Double) to I32 (Integer)
&CPU::D2L, // 0x069 — F64 (Double) to I64 (Long) &CPU::D2L, // 0x069 — F64 (Double) to I64 (Long)
nullptr, // 0x06A (reserved) nullptr, // 0x06A (reserved)
nullptr, // 0x06B (reserved) nullptr, // 0x06B (reserved)
&CPU::SIN, // 0x06C — Sine Function &CPU::SIN, // 0x06C — Sine Function
&CPU::COS, // 0x06D — Cosine Function &CPU::COS, // 0x06D — Cosine Function
&CPU::TAN, // 0x06E — Tangent Function &CPU::TAN, // 0x06E — Tangent Function
&CPU::ASIN, // 0x06F — Arc Sine Function &CPU::ASIN, // 0x06F — Arc Sine Function
&CPU::ACOS, // 0x070 — Arc Cosine Function &CPU::ACOS, // 0x070 — Arc Cosine Function
&CPU::ATAN, // 0x071 — Arc Tangent Function &CPU::ATAN, // 0x071 — Arc Tangent Function
&CPU::ATAN2, // 0x072 — Arc Tangent Function with 2 Arguments &CPU::ATAN2, // 0x072 — Arc Tangent Function with 2 Arguments
nullptr, // 0x073 (reserved) nullptr, // 0x073 (reserved)
&CPU::EXP, // 0x074 — Exponential Function &CPU::EXP, // 0x074 — Exponential Function
&CPU::LOG, // 0x075 — Natural Logarithm &CPU::LOG, // 0x075 — Natural Logarithm
&CPU::LOGAB, // 0x076 — Logarithm A of B &CPU::LOGAB, // 0x076 — Logarithm A of B
&CPU::POW, // 0x077 — Power Function &CPU::POW, // 0x077 — Power Function
&CPU::SQRT, // 0x078 — Square Root &CPU::SQRT, // 0x078 — Square Root
&CPU::ROOT, // 0x079 — General Root &CPU::ROOT, // 0x079 — General Root
nullptr, // 0x07A (reserved) nullptr, // 0x07A (reserved)
nullptr, // 0x07B (reserved) nullptr, // 0x07B (reserved)
&CPU::ADC, // 0x07C — Add with Carry &CPU::ADC, // 0x07C — Add with Carry
&CPU::SWC, // 0x07D — Subtract with Carry (Borrow) &CPU::SWC, // 0x07D — Subtract with Carry (Borrow)
&CPU::MWO, // 0x07E — Multiply with Overflow &CPU::MWO, // 0x07E — Multiply with Overflow
&CPU::UMO, // 0x07F — Unsigned Multiply with Overflow &CPU::UMO, // 0x07F — Unsigned Multiply with Overflow
&CPU::MADD, // 0x080 — Matrix Addition &CPU::MADD, // 0x080 — Matrix Addition
&CPU::MSUB, // 0x081 — Matrix Subtraction &CPU::MSUB, // 0x081 — Matrix Subtraction
&CPU::MMUL, // 0x082 — Matrix Multiply &CPU::MMUL, // 0x082 — Matrix Multiply
&CPU::MINV, // 0x083 — Matrix Inverse &CPU::MINV, // 0x083 — Matrix Inverse
&CPU::MTRA, // 0x084 — Matrix Transpose &CPU::MTRA, // 0x084 — Matrix Transpose
&CPU::MDET, // 0x085 — Matrix Determinant &CPU::MDET, // 0x085 — Matrix Determinant
&CPU::QMKA, // 0x086 — Quaternion Make from Angles &CPU::QMKA, // 0x086 — Quaternion Make from Angles
&CPU::QMUL, // 0x087 — Quaternion Multiply &CPU::QMUL, // 0x087 — Quaternion Multiply
nullptr, // 0x088 nullptr, // 0x088
nullptr, // 0x089 nullptr, // 0x089
&CPU::XADD, // 0x08A — SIMD Addition &CPU::XADD, // 0x08A — SIMD Addition
&CPU::XSUB, // 0x08B — SIMD Subtract &CPU::XSUB, // 0x08B — SIMD Subtract
&CPU::XAMA, // 0x08C — SIMD Alternate Multiply-Add &CPU::XAMA, // 0x08C — SIMD Alternate Multiply-Add
&CPU::XMUL, // 0x08D — SIMD Multiply &CPU::XMUL, // 0x08D — SIMD Multiply
&CPU::XDIV, // 0x08E — SIMD Divide &CPU::XDIV, // 0x08E — SIMD Divide
nullptr, // 0x08F nullptr, // 0x08F
nullptr, // 0x090 nullptr, // 0x090
nullptr, // 0x091 nullptr, // 0x091
@@ -275,13 +275,13 @@ CPU::Fn CPU::instrMap[] = {
nullptr, // 0x0ED nullptr, // 0x0ED
nullptr, // 0x0EE nullptr, // 0x0EE
nullptr, // 0x0EF nullptr, // 0x0EF
&CPU::UPY, // 0x0F0 — Will place "YUPI" in memory &CPU::UPY, // 0x0F0 — Will place "YUPI" in memory
nullptr, // 0x0F1 &CPU::INT_1_SLOT, // 0x0F1
nullptr, // 0x0F2 &CPU::INT_2_SLOT, // 0x0F2
nullptr, // 0x0F3 &CPU::INT_3_SLOT, // 0x0F3
nullptr, // 0x0F4 &CPU::INT_4_SLOT, // 0x0F4
nullptr, // 0x0F5 &CPU::BRAD, // 0x0F5
&CPU::DGANT, // 0x0F6 &CPU::DGANT, // 0x0F6
nullptr, // 0x0F7 nullptr, // 0x0F7
nullptr, // 0x0F8 nullptr, // 0x0F8
nullptr, // 0x0F9 nullptr, // 0x0F9
@@ -583,7 +583,6 @@ void CPU::executeSwLk() {
case 0x00B: MOR(); break; case 0x00B: MOR(); break;
case 0x00C: AMOV(); break; case 0x00C: AMOV(); break;
case 0x00D: SWP(); break; case 0x00D: SWP(); break;
case 0x00E: AHM(); break;
// ── Integer ───────────────────────────────────── // ── Integer ─────────────────────────────────────
case 0x010: COM(); break; case 0x010: COM(); break;
@@ -602,9 +601,6 @@ void CPU::executeSwLk() {
case 0x01D: DMOD(); break; case 0x01D: DMOD(); break;
case 0x01E: UDMD(); break; case 0x01E: UDMD(); break;
// ── System ──────────────────────────────────────
case 0x01F: FBT(); break;
// ── Bit Wise ──────────────────────────────────── // ── Bit Wise ────────────────────────────────────
case 0x020: STB(); break; case 0x020: STB(); break;
case 0x021: CRB(); break; case 0x021: CRB(); break;
@@ -622,12 +618,16 @@ void CPU::executeSwLk() {
case 0x02D: CNT(); break; case 0x02D: CNT(); break;
// ── Boolean ───────────────────────────────────── // ── Boolean ─────────────────────────────────────
case 0x030: EQ(); break; case 0x02E: EQ(); break;
case 0x031: NE(); break; case 0x02F: NE(); break;
case 0x032: GT(); break; case 0x030: GT(); break;
case 0x033: GE(); break; case 0x031: GE(); break;
case 0x034: LT(); break; case 0x032: LT(); break;
case 0x035: LE(); break; case 0x033: LE(); break;
case 0x034: GTU(); break;
case 0x035: GEU(); break;
case 0x036: LTU(); break;
case 0x037: LEU(); break;
// ── Branch ────────────────────────────────────── // ── Branch ──────────────────────────────────────
case 0x038: JMP(); break; case 0x038: JMP(); break;
@@ -737,6 +737,12 @@ void CPU::executeSwLk() {
// ── Easter Eggs ───────────────────────────────── // ── Easter Eggs ─────────────────────────────────
case 0x0F0: UPY(); break; case 0x0F0: UPY(); break;
case 0x0F1: INT_1_SLOT(); break;
case 0x0F2: INT_2_SLOT(); break;
case 0x0F3: INT_3_SLOT(); break;
case 0x0F4: INT_4_SLOT(); break;
case 0x0F5: BRAD(); break;
case 0x0F6: DGANT(); break;
default: default:
break; break;
+260 -216
View File
@@ -4,15 +4,16 @@
*/ */
#include <spider/runtime/cpu/CPU.hpp> #include <spider/runtime/cpu/CPU.hpp>
#include <spider/runtime/memory/RAM.hpp>
namespace spider { namespace spider {
void CPU::NOP() { void CPU::NOP() {
// TODO: Implement NOP // DONE ! //
} }
void CPU::SPDR() { void CPU::SPDR() {
// TODO: Implement SPDR RA._u64 = spider::RUNTIME_VERSION_NO;
} }
void CPU::MMODE() { void CPU::MMODE() {
@@ -21,10 +22,13 @@ namespace spider {
void CPU::INT() { void CPU::INT() {
// TODO: Implement INT // TODO: Implement INT
// We need to implement an interrupt
// table and interrupt system!
} }
void CPU::LRV() { void CPU::LRV() {
// TODO: Implement LRV fetchOperReg();
RV = _dst->_u64;
} }
void CPU::FSR() { void CPU::FSR() {
@@ -32,11 +36,13 @@ namespace spider {
} }
void CPU::FIR() { void CPU::FIR() {
// TODO: Implement FIR fetchOperReg();
_dst->_u64 = RI;
} }
void CPU::FZR() { void CPU::FZR() {
// TODO: Implement FZR fetchOperReg();
_dst->_u64 = RZ;
} }
void CPU::LSR() { void CPU::LSR() {
@@ -44,313 +50,351 @@ namespace spider {
} }
void CPU::FVR() { void CPU::FVR() {
// TODO: Implement FVR fetchOperReg();
_dst->_u64 = RV;
} }
void CPU::MOV() { void CPU::MOV() {
// TODO: Implement MOV fetchOperSrc();
fetchOperDst();
switch (_size) {
case 0b00: //byte
_dst->_u8 = _src->_u8;
break;
case 0b01: //short
_dst->_u16 = _src->_u16;
break;
case 0b10: //int
_dst->_u32 = _src->_u32;
break;
case 0b11: //long
_dst->_u64 = _src->_u64;
break;
}
} }
void CPU::MOR() { void CPU::MOR() {
// TODO: Implement MOR fetchOperRegReg();
*_dst = *_src;
} }
void CPU::AMOV() { void CPU::AMOV() {
// TODO: Implement AMOV // AMOV potential is capped at 256 bytes!
u64 amt = RA._u16;
u64 from = RX._u64;
u64 to = RY._u64;
if(amt > 256) return;
// are RX and RY in valid regions of memory?
u64 ramsize = _ram->size();
if (from >= ramsize || amt > (ramsize - from)) return;
if (to >= ramsize || amt > (ramsize - to)) return;
// Use std::copy_backward if destination overlaps ahead of source
auto ram_begin = _ram->begin();
if (to > from && to < from + amt) {
// Overlap case where destination is ahead of source: copy from back to front
std::copy_backward(ram_begin + from, ram_begin + from + amt, ram_begin + to + amt);
} else {
// No overlap, or destination is behind source: copy front to back
std::copy(ram_begin + from, ram_begin + from + amt, ram_begin + to);
}
} }
void CPU::SWP() { void CPU::SWP() {
// TODO: Implement SWP // get registers in _dst and _src
} fetchOperRegReg();
ALU0 = *_dst;
void CPU::AHM() { *_dst = *_src;
// TODO: Implement AHM *_src = ALU0;
} }
void CPU::COM() { void CPU::COM() {
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 = ~_dst->_u8; _dst->_u8 = ~_dst->_u8;
break; break;
case 0b01: //short case 0b01: //short
_dst->_u16 = ~_dst->_u16; _dst->_u16 = ~_dst->_u16;
break; break;
case 0b10: //int case 0b10: //int
_dst->_u32 = ~_dst->_u32; _dst->_u32 = ~_dst->_u32;
break; break;
case 0b11: //long case 0b11: //long
_dst->_u64 = ~_dst->_u64; _dst->_u64 = ~_dst->_u64;
break; break;
} }
(this->*_post)();
} }
void CPU::NEG() { void CPU::NEG() {
// TODO: Implement NEG
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 = 1 + ~_dst->_u8; _dst->_u8 = 1 + ~_dst->_u8;
break; break;
case 0b01: //short case 0b01: //short
_dst->_u16 = 1+ ~_dst->_u16; _dst->_u16 = 1 + ~_dst->_u16;
break; break;
case 0b10: //int case 0b10: //int
_dst->_u32 = 1 + ~_dst->_u32; _dst->_u32 = 1 + ~_dst->_u32;
break; break;
case 0b11: //long case 0b11: //long
_dst->_u64 = 1 + ~_dst->_u64; _dst->_u64 = 1 + ~_dst->_u64;
break; break;
} }
(this->*_post)();
} }
void CPU::EXS() { // THIS IS INCORRECT!!! void CPU::EXS() {
// TODO: Implement EXS
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_i16 = static_cast<i16>(_dst->_i8); _dst->_i16 = static_cast<i16>(_dst->_i8);
break; break;
case 0b01: //short case 0b01: //short
_dst->_i32 = static_cast<i32>(_dst->_i16); _dst->_i32 = static_cast<i32>(_dst->_i16);
break; break;
case 0b10: //int case 0b10: //int
_dst->_i64 = static_cast<i64>(_dst->_i32); _dst->_i64 = static_cast<i64>(_dst->_i32);
break; break;
case 0b11: //long case 0b11: //long
_dst->_i64 = _dst->_i64; _dst->_i64 = _dst->_i64;
break; break;
} }
_dst->_u32 = _dst->_u8;
(this->*_post)();
} }
void CPU::INC() { void CPU::INC() {
// TODO: Implement INC
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 += 1; _dst->_u8 += 1;
case 0b01: //short break;
_dst->_u16 += 1; case 0b01: //short
case 0b10: //int _dst->_u16 += 1;
_dst->_u32 += 1; break;
case 0b11: //long case 0b10: //int
_dst->_u64 += 1; _dst->_u32 += 1;
break;
case 0b11: //long
_dst->_u64 += 1;
break;
} }
(this->*_post)();
} }
void CPU::DEC() { void CPU::DEC() {
// TODO: Implement DEC
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 -= 1; _dst->_u8 -= 1;
case 0b01: //short break;
_dst->_u16 -= 1; case 0b01: //short
case 0b10: //int _dst->_u16 -= 1;
_dst->_u32 -= 1; break;
case 0b11: //long case 0b10: //int
_dst->_u64 -= 1; _dst->_u32 -= 1;
break;
case 0b11: //long
_dst->_u64 -= 1;
break;
} }
(this->*_post)();
} }
void CPU::ADD() { void CPU::ADD() {
// TODO: Implement ADD
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 += _src->_u8; _dst->_u8 += _src->_u8;
case 0b01: //short break;
_dst->_u16 += _src->_u16; case 0b01: //short
case 0b10: //int _dst->_u16 += _src->_u16;
_dst->_u32 += _src->_u32; break;
case 0b11: //long case 0b10: //int
_dst->_u64 += _src->_u64; _dst->_u32 += _src->_u32;
break;
case 0b11: //long
_dst->_u64 += _src->_u64;
break;
} }
(this->*_post)();
} }
void CPU::SUB() { void CPU::SUB() {
// TODO: Implement SUB
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 -= _src->_u8; _dst->_u8 -= _src->_u8;
case 0b01: //short break;
_dst->_u16 -= _src->_u16; case 0b01: //short
case 0b10: //int _dst->_u16 -= _src->_u16;
_dst->_u32 -= _src->_u32; break;
case 0b11: //long case 0b10: //int
_dst->_u64 -= _src->_u64; _dst->_u32 -= _src->_u32;
break;
case 0b11: //long
_dst->_u64 -= _src->_u64;
break;
} }
(this->*_post)();
} }
void CPU::MUL() { void CPU::MUL() {
// TODO: Implement MUL
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_i8 = _src->_i8 * _dst->_i8; _dst->_i8 = _src->_i8 * _dst->_i8;
case 0b01: //short break;
_dst->_i16 = _src->_i16 * _dst->_i16; case 0b01: //short
case 0b10: //int _dst->_i16 = _src->_i16 * _dst->_i16;
_dst->_i32 = _src->_i32 * _dst->_i32; break;
case 0b11: //long case 0b10: //int
_dst->_i64 = _src->_i64 * _dst->_i64; _dst->_i32 = _src->_i32 * _dst->_i32;
break;
case 0b11: //long
_dst->_i64 = _src->_i64 * _dst->_i64;
break;
} }
(this->*_post)();
} }
void CPU::UMUL() { void CPU::UMUL() {
// TODO: Implement UMUL
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 = _src->_u8 * _dst->_u8; _dst->_u8 = _src->_u8 * _dst->_u8;
case 0b01: //short break;
_dst->_u16 = _src->_u16 * _dst->_u16; case 0b01: //short
case 0b10: //int _dst->_u16 = _src->_u16 * _dst->_u16;
_dst->_u32 = _src->_u32 * _dst->_u32; break;
case 0b11: //long case 0b10: //int
_dst->_u64 = _src->_u64 * _dst->_u64; _dst->_u32 = _src->_u32 * _dst->_u32;
break;
case 0b11: //long
_dst->_u64 = _src->_u64 * _dst->_u64;
break;
} }
(this->*_post)();
} }
void CPU::DIV() { void CPU::DIV() {
// TODO: Implement DIV
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_i8 = _dst->_i8 / _src->_i8; _dst->_i8 = _dst->_i8 / _src->_i8;
case 0b01: //short break;
_dst->_i16 = _dst->_i16 / _src->_i16; case 0b01: //short
case 0b10: //int _dst->_i16 = _dst->_i16 / _src->_i16;
_dst->_i32 = _dst->_i32 / _src->_i32; break;
case 0b11: //long case 0b10: //int
_dst->_i64 = _dst->_i64 / _src->_i64; _dst->_i32 = _dst->_i32 / _src->_i32;
break;
case 0b11: //long
_dst->_i64 = _dst->_i64 / _src->_i64;
break;
} }
(this->*_post)();
} }
void CPU::UDIV() { void CPU::UDIV() {
// TODO: Implement UDIV
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 = _dst->_u8 / _src->_u8; _dst->_u8 = _dst->_u8 / _src->_u8;
case 0b01: //short break;
_dst->_u16 = _dst->_u16 / _src->_u16; case 0b01: //short
case 0b10: //int _dst->_u16 = _dst->_u16 / _src->_u16;
_dst->_u32 = _dst->_u32 / _src->_u32; break;
case 0b11: //long case 0b10: //int
_dst->_u64 = _dst->_u64 / _src->_u64; _dst->_u32 = _dst->_u32 / _src->_u32;
break;
case 0b11: //long
_dst->_u64 = _dst->_u64 / _src->_u64;
break;
} }
(this->*_post)();
} }
void CPU::MOD() { void CPU::MOD() {
// TODO: Implement MOD
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_i8 = _dst->_i8 % _src->_i8; _dst->_i8 = _dst->_i8 % _src->_i8;
case 0b01: //short break;
_dst->_i16 = _dst->_i16 % _src->_i16; case 0b01: //short
case 0b10: //int _dst->_i16 = _dst->_i16 % _src->_i16;
_dst->_i32 = _dst->_i32 % _src->_i32; break;
case 0b11: //long case 0b10: //int
_dst->_i64 = _dst->_i64 % _src->_i64; _dst->_i32 = _dst->_i32 % _src->_i32;
break;
case 0b11: //long
_dst->_i64 = _dst->_i64 % _src->_i64;
break;
} }
(this->*_post)();
} }
void CPU::UMOD() { void CPU::UMOD() {
// TODO: Implement UMOD
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 = _dst->_u8 % _src->_u8; _dst->_u8 = _dst->_u8 % _src->_u8;
case 0b01: //short break;
_dst->_u16 = _dst->_u16 % _src->_u16; case 0b01: //short
case 0b10: //int _dst->_u16 = _dst->_u16 % _src->_u16;
_dst->_u32 = _dst->_u32 % _src->_u32; break;
case 0b11: //long case 0b10: //int
_dst->_u64 = _dst->_u64 % _src->_u64; _dst->_u32 = _dst->_u32 % _src->_u32;
break;
case 0b11: //long
_dst->_u64 = _dst->_u64 % _src->_u64;
break;
} }
(this->*_post)();
} }
void CPU::DMOD() { void CPU::DMOD() {
// TODO: Implement DMOD
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
RX._i8 = _dst->_i8 / _src->_i8; RX._i8 = _dst->_i8 / _src->_i8;
RY._i8 = _dst->_i8 % _src->_i8; RY._i8 = _dst->_i8 % _src->_i8;
case 0b01: //short break;
RX._i16 = _dst->_i16 / _src->_i16; case 0b01: //short
RY._i16 = _dst->_i16 % _src->_i16; RX._i16 = _dst->_i16 / _src->_i16;
case 0b10: //int RY._i16 = _dst->_i16 % _src->_i16;
RX._i32 = _dst->_i32 / _src->_i32; break;
RY._i32 = _dst->_i32 % _src->_i32; case 0b10: //int
case 0b11: //long RX._i32 = _dst->_i32 / _src->_i32;
RX._i64 = _dst->_i64 / _src->_i64; RY._i32 = _dst->_i32 % _src->_i32;
RY._i64 = _dst->_i64 % _src->_i64; break;
case 0b11: //long
RX._i64 = _dst->_i64 / _src->_i64;
RY._i64 = _dst->_i64 % _src->_i64;
break;
} }
(this->*_post)();
} }
void CPU::UDMD() { void CPU::UDMD() {
// TODO: Implement UDMD
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
RX._u8 = _dst->_u8 / _src->_u8; RX._u8 = _dst->_u8 / _src->_u8;
RY._u8 = _dst->_u8 % _src->_u8; RY._u8 = _dst->_u8 % _src->_u8;
case 0b01: //short break;
RX._u16 = _dst->_u16 / _src->_u16; case 0b01: //short
RY._u16 = _dst->_u16 % _src->_u16; RX._u16 = _dst->_u16 / _src->_u16;
case 0b10: //int RY._u16 = _dst->_u16 % _src->_u16;
RX._u32 = _dst->_u32 / _src->_u32; break;
RY._u32 = _dst->_u32 % _src->_u32; case 0b10: //int
case 0b11: //long RX._u32 = _dst->_u32 / _src->_u32;
RX._u64 = _dst->_u64 / _src->_u64; RY._u32 = _dst->_u32 % _src->_u32;
RY._u64 = _dst->_u64 % _src->_u64; break;
case 0b11: //long
RX._u64 = _dst->_u64 / _src->_u64;
RY._u64 = _dst->_u64 % _src->_u64;
break;
} }
(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)();
} }
} }
+304 -73
View File
@@ -8,174 +8,405 @@
namespace spider { namespace spider {
void CPU::STB() { void CPU::STB() {
// TODO: Implement STB
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch(_size){
case 0b00: //byte case 0b00: //byte
_dst->_u8 |= (1 << _src->_u8); _dst->_u8 |= (1 << _src->_u8);
break;
case 0b01: //short case 0b01: //short
_dst->_u16 |= (1 << _src->_u16); _dst->_u16 |= (1 << _src->_u16);
break;
case 0b10: //int case 0b10: //int
_dst->_u32 |= (1 << _src->_u32); _dst->_u32 |= (1 << _src->_u32);
break;
case 0b11: //long case 0b11: //long
_dst->_u64 |= (1 << _src->_u64); _dst->_u64 |= (1 << _src->_u64);
break;
} }
(this->*_post)();
} }
void CPU::CRB() { void CPU::CRB() {
// TODO: Implement CRB
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch(_size){
case 0b00: //byte case 0b00: //byte
_dst->_u8 &= ~(1 << _src->_u8); _dst->_u8 &= u8(~(u8(1) << _src->_u8));
break;
case 0b01: //short case 0b01: //short
_dst->_u16 &= ~(1 << _src->_u16); _dst->_u16 &= u16(~(u16(1) << _src->_u16));
break;
case 0b10: //int case 0b10: //int
_dst->_u32 &= ~(1 << _src->_u32); _dst->_u32 &= ~(u32(1) << _src->_u32);
break;
case 0b11: //long case 0b11: //long
_dst->_u64 &= ~(1 << _src->_u64); _dst->_u64 &= ~(u64(1) << _src->_u64);
break;
} }
(this->*_post)();
} }
void CPU::TSB() { void CPU::TSB() {
// TODO: Implement TSB
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){
case 0b00: //byte u64 s, d;
switch (((RF >> _src->_u8) & 1) != ((_dst->_u8 >> _src->_u8) & 1)){ switch(_size) {
case 1: case 0b00: // byte
RF |= (1 << _src->_u8); s = _src->_u8;
d = _dst->_u8;
case 0: break;
RF &= ~(1 << _src->_u8); case 0b01: // short
} s = _src->_u16;
case 0b01: //short d = _dst->_u16;
switch (((RF >> _src->_u16) & 1) != ((_dst->_u16 >> _src->_u16) & 1)){ break;
case 1: case 0b10: // int
RF |= (1 << _src->_u16); s = _src->_u32;
d = _dst->_u32;
case 0: break;
RF &= ~(1 << _src->_u16); case 0b11: // long
} s = _src->_u64;
case 0b10: //int d = _dst->_u64;
switch (((RF >> _src->_u32) & 1) != ((_dst->_u32 >> _src->_u32) & 1)){ break;
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)();
d >>= s;
d &= 1;
} }
void CPU::BOOL() { void CPU::BOOL() {
// TODO: Implement BOOL
fetchOperDst(); fetchOperDst();
switch(_size){ switch(_size){
case 0b00: //byte case 0b00: // byte
_dst->_u8 = _dst != 0; _dst->_u8 = _dst->_u8 != 0;
case 0b01: //short break;
_dst->_u16 = _dst != 0; case 0b01: // short
case 0b10: //int _dst->_u16 = _dst->_u16 != 0;
_dst->_u32 = _dst != 0; break;
case 0b11: //long case 0b10: // int
_dst->_u64 = _dst != 0; _dst->_u32 = _dst->_u32 != 0;
break;
case 0b11: // long
_dst->_u64 = _dst->_u64 != 0;
break;
} }
(this->*_post)();
} }
// ── 0x024 — NOT: Tests Dst == 0, updates Equal Flag ──
void CPU::NOT() { void CPU::NOT() {
// TODO: Implement NOT fetchOperDst();
bool isZero = false;
switch(_size) {
case 0b00: isZero = (_dst->_u8 == 0); break;
case 0b01: isZero = (_dst->_u16 == 0); break;
case 0b10: isZero = (_dst->_u32 == 0); break;
case 0b11: isZero = (_dst->_u64 == 0); break;
}
if (isZero) {
RF |= CPU::FLAG_EQUAL; // Si es 0, el resultado de !0 es true (1), actualizamos bandera
// Dependiendo de la implementación de BOOL, podrías querer guardar el resultado en Dst
_dst->_u64 = 1;
} else {
RF &= ~CPU::FLAG_EQUAL;
_dst->_u64 = 0;
}
} }
// ── 0x025 — AND
void CPU::AND() { void CPU::AND() {
// TODO: Implement AND fetchOperSrc();
fetchOperDst();
switch(_size) {
case 0b00: _dst->_u8 &= _src->_u8; break;
case 0b01: _dst->_u16 &= _src->_u16; break;
case 0b10: _dst->_u32 &= _src->_u32; break;
case 0b11: _dst->_u64 &= _src->_u64; break;
}
} }
// ── 0x026 — OR
void CPU::OR() { void CPU::OR() {
// TODO: Implement OR fetchOperSrc();
fetchOperDst();
switch(_size) {
case 0b00: _dst->_u8 |= _src->_u8; break;
case 0b01: _dst->_u16 |= _src->_u16; break;
case 0b10: _dst->_u32 |= _src->_u32; break;
case 0b11: _dst->_u64 |= _src->_u64; break;
}
} }
// ── 0x027 — XOR
void CPU::XOR() { void CPU::XOR() {
// TODO: Implement XOR fetchOperSrc();
fetchOperDst();
switch(_size) {
case 0b00: _dst->_u8 ^= _src->_u8; break;
case 0b01: _dst->_u16 ^= _src->_u16; break;
case 0b10: _dst->_u32 ^= _src->_u32; break;
case 0b11: _dst->_u64 ^= _src->_u64; break;
}
} }
// ── 0x028 — SHL
void CPU::SHL() { void CPU::SHL() {
// TODO: Implement SHL fetchOperSrc();
fetchOperDst();
switch(_size) {
case 0b00: _dst->_u8 <<= _src->_u8; break;
case 0b01: _dst->_u16 <<= _src->_u16; break;
case 0b10: _dst->_u32 <<= _src->_u32; break;
case 0b11: _dst->_u64 <<= _src->_u64; break;
}
} }
// ── 0x029 — SHR
void CPU::SHR() { void CPU::SHR() {
// TODO: Implement SHR fetchOperSrc();
fetchOperDst();
switch(_size) {
case 0b00: _dst->_u8 >>= _src->_u8; break;
case 0b01: _dst->_u16 >>= _src->_u16; break;
case 0b10: _dst->_u32 >>= _src->_u32; break;
case 0b11: _dst->_u64 >>= _src->_u64; break;
}
} }
// ── 0x02A — SSR
void CPU::SSR() { void CPU::SSR() {
// TODO: Implement SSR fetchOperSrc();
fetchOperDst();
switch(_size) {
case 0b00: _dst->_i8 >>= _src->_u8; break;
case 0b01: _dst->_i16 >>= _src->_u8; break;
case 0b10: _dst->_i32 >>= _src->_u8; break;
case 0b11: _dst->_i64 >>= _src->_u8; break;
}
} }
// ── 0x02B — ROL: Rotate Left ──
void CPU::ROL() { void CPU::ROL() {
// TODO: Implement ROL fetchOperSrc();
fetchOperDst();
switch(_size) {
case 0b00: _dst->_u8 = (_dst->_u8 << _src->_u8) | (_dst->_u8 >> (8 - _src->_u8)); break;
case 0b01: _dst->_u16 = (_dst->_u16 << _src->_u8) | (_dst->_u16 >> (16 - _src->_u8)); break;
case 0b10: _dst->_u32 = (_dst->_u32 << _src->_u8) | (_dst->_u32 >> (32 - _src->_u8)); break;
case 0b11: _dst->_u64 = (_dst->_u64 << _src->_u8) | (_dst->_u64 >> (64 - _src->_u8)); break;
}
} }
// ── 0x02C — ROR: Rotate Right ──
void CPU::ROR() { void CPU::ROR() {
// TODO: Implement ROR fetchOperSrc();
fetchOperDst();
switch(_size) {
case 0b00: _dst->_u8 = (_dst->_u8 >> _src->_u8) | (_dst->_u8 << (8 - _src->_u8)); break;
case 0b01: _dst->_u16 = (_dst->_u16 >> _src->_u8) | (_dst->_u16 << (16 - _src->_u8)); break;
case 0b10: _dst->_u32 = (_dst->_u32 >> _src->_u8) | (_dst->_u32 << (32 - _src->_u8)); break;
case 0b11: _dst->_u64 = (_dst->_u64 >> _src->_u8) | (_dst->_u64 << (64 - _src->_u8)); break;
}
} }
// ── 0x02D — CNT: Counts bits (# of 1's into Dst) ──
void CPU::CNT() { void CPU::CNT() {
// TODO: Implement CNT fetchOperDst();
switch(_size) { // C++20 cross compatible version!!
case 0b00: _dst->_u8 = u8( std::popcount(_dst->_u8) ); break;
case 0b01: _dst->_u16 = u16(std::popcount(_dst->_u16)); break;
case 0b10: _dst->_u32 = u32(std::popcount(_dst->_u32)); break;
case 0b11: _dst->_u64 = u64(std::popcount(_dst->_u64)); break;
}
} }
void CPU::EQ() { void CPU::EQ() {
// TODO: Implement EQ fetchOperSrc();
fetchOperDst();
bool res = false;
switch(_size) {
case 0b00: res = (_dst->_u8 == _src->_u8); break;
case 0b01: res = (_dst->_u16 == _src->_u16); break;
case 0b10: res = (_dst->_u32 == _src->_u32); break;
case 0b11: res = (_dst->_u64 == _src->_u64); break;
}
_dst->_u64 = res ? 1 : 0;
} }
void CPU::NE() { void CPU::NE() {
// TODO: Implement NE fetchOperSrc();
fetchOperDst();
bool res = false;
switch(_size) {
case 0b00: res = (_dst->_u8 != _src->_u8); break;
case 0b01: res = (_dst->_u16 != _src->_u16); break;
case 0b10: res = (_dst->_u32 != _src->_u32); break;
case 0b11: res = (_dst->_u64 != _src->_u64); break;
}
_dst->_u64 = res ? 1 : 0;
} }
void CPU::GT() { void CPU::GT() {
// TODO: Implement GT fetchOperSrc();
fetchOperDst();
bool res = false;
switch(_size) {
case 0b00: res = (_dst->_i8 > _src->_i8); break;
case 0b01: res = (_dst->_i16 > _src->_i16); break;
case 0b10: res = (_dst->_i32 > _src->_i32); break;
case 0b11: res = (_dst->_i64 > _src->_i64); break;
}
_dst->_u64 = res ? 1 : 0;
} }
void CPU::GE() { void CPU::GE() {
// TODO: Implement GE fetchOperSrc();
fetchOperDst();
bool res = false;
switch(_size) {
case 0b00: res = (_dst->_i8 >= _src->_i8); break;
case 0b01: res = (_dst->_i16 >= _src->_i16); break;
case 0b10: res = (_dst->_i32 >= _src->_i32); break;
case 0b11: res = (_dst->_i64 >= _src->_i64); break;
}
_dst->_u64 = res ? 1 : 0;
} }
void CPU::LT() { void CPU::LT() {
// TODO: Implement LT fetchOperSrc();
fetchOperDst();
bool res = false;
switch(_size) {
case 0b00: res = (_dst->_i8 < _src->_i8); break;
case 0b01: res = (_dst->_i16 < _src->_i16); break;
case 0b10: res = (_dst->_i32 < _src->_i32); break;
case 0b11: res = (_dst->_i64 < _src->_i64); break;
}
_dst->_u64 = res ? 1 : 0;
} }
void CPU::LE() { void CPU::LE() {
// TODO: Implement LE fetchOperSrc();
fetchOperDst();
bool res = false;
switch(_size) {
case 0b00: res = (_dst->_i8 <= _src->_i8); break;
case 0b01: res = (_dst->_i16 <= _src->_i16); break;
case 0b10: res = (_dst->_i32 <= _src->_i32); break;
case 0b11: res = (_dst->_i64 <= _src->_i64); break;
}
_dst->_u64 = res ? 1 : 0;
} }
void CPU::GTU() {
fetchOperSrc();
fetchOperDst();
bool res = false;
switch(_size) {
case 0b00: res = (_dst->_u8 > _src->_u8); break;
case 0b01: res = (_dst->_u16 > _src->_u16); break;
case 0b10: res = (_dst->_u32 > _src->_u32); break;
case 0b11: res = (_dst->_u64 > _src->_u64); break;
}
_dst->_u64 = res ? 1 : 0;
}
void CPU::GEU() {
fetchOperSrc();
fetchOperDst();
bool res = false;
switch(_size) {
case 0b00: res = (_dst->_u8 >= _src->_u8); break;
case 0b01: res = (_dst->_u16 >= _src->_u16); break;
case 0b10: res = (_dst->_u32 >= _src->_u32); break;
case 0b11: res = (_dst->_u64 >= _src->_u64); break;
}
_dst->_u64 = res ? 1 : 0;
}
void CPU::LTU() {
fetchOperSrc();
fetchOperDst();
bool res = false;
switch(_size) {
case 0b00: res = (_dst->_u8 < _src->_u8); break;
case 0b01: res = (_dst->_u16 < _src->_u16); break;
case 0b10: res = (_dst->_u32 < _src->_u32); break;
case 0b11: res = (_dst->_u64 < _src->_u64); break;
}
_dst->_u64 = res ? 1 : 0;
}
void CPU::LEU() {
fetchOperSrc();
fetchOperDst();
bool res = false;
switch(_size) {
case 0b00: res = (_dst->_u8 <= _src->_u8); break;
case 0b01: res = (_dst->_u16 <= _src->_u16); break;
case 0b10: res = (_dst->_u32 <= _src->_u32); break;
case 0b11: res = (_dst->_u64 <= _src->_u64); break;
}
_dst->_u64 = res ? 1 : 0;
}
// ── 0x038 — JMP: Dst -> Instruction Register (PC) ──
// The IR adds 1 at the end, so we subtract 1 to compensate.
void CPU::JMP() { void CPU::JMP() {
// TODO: Implement JMP fetchOperDst();
u64 target;
switch(_size) {
case 0b00: target = static_cast<u64>(_dst->_u8); break;
case 0b01: target = static_cast<u64>(_dst->_u16); break;
case 0b10: target = static_cast<u64>(_dst->_u32); break;
case 0b11: target = _dst->_u64; break;
}
RI = target - 1;
} }
// ── 0x039 — JEQ: Jump if EQ flag is set ──
void CPU::JEQ() { void CPU::JEQ() {
// TODO: Implement JEQ fetchOperDst();
if (RF & CPU::FLAG_EQUAL) {
u64 target;
switch(_size) {
case 0b00: target = static_cast<u64>(_dst->_u8); break;
case 0b01: target = static_cast<u64>(_dst->_u16); break;
case 0b10: target = static_cast<u64>(_dst->_u32); break;
case 0b11: target = _dst->_u64; break;
}
RI = target - 1;
}
} }
// ── 0x03A — JNE: Jumps if EQ flag is cleared ──
void CPU::JNE() { void CPU::JNE() {
// TODO: Implement JNE fetchOperDst();
if (!(RF & CPU::FLAG_EQUAL)) {
u64 target;
switch(_size) {
case 0b00: target = static_cast<u64>(_dst->_u8); break;
case 0b01: target = static_cast<u64>(_dst->_u16); break;
case 0b10: target = static_cast<u64>(_dst->_u32); break;
case 0b11: target = _dst->_u64; break;
}
RI = target - 1;
}
} }
// ── 0x03B — JIF: Jumps if Src is booleanly true ──
void CPU::JIF() { void CPU::JIF() {
// TODO: Implement JIF fetchOperSrc();
fetchOperDst();
if (_src->_u64 != 0) {
u64 target;
switch(_size) {
case 0b00: target = static_cast<u64>(_dst->_u8); break;
case 0b01: target = static_cast<u64>(_dst->_u16); break;
case 0b10: target = static_cast<u64>(_dst->_u32); break;
case 0b11: target = _dst->_u64; break;
}
RI = target - 1;
}
} }
// ── 0x03C — JMR: Dst + Instruction Register -> Instruction Register ── // ── 0x03C — JMR: Dst + Instruction Register -> Instruction Register ──
@@ -12,6 +12,14 @@ namespace spider {
// TODO: Implement UPY // TODO: Implement UPY
} }
void CPU::INT_1_SLOT() {}
void CPU::INT_2_SLOT() {}
void CPU::INT_3_SLOT() {}
void CPU::INT_4_SLOT() {}
// ── 0x0F6 — DGANT: "I'm SpiderLang" in a spider web ──────────── // ── 0x0F6 — DGANT: "I'm SpiderLang" in a spider web ────────────
void CPU::DGANT() { void CPU::DGANT() {
const char art[] = const char art[] =
@@ -52,4 +60,22 @@ namespace spider {
} }
} }
/**
* @brief BRAD (0xF5) - 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 += _ram->at(i);
}
// Si el checksum coincide, RA = 1 (OK), si no RA = 0 (Error)
RA._u8 = (checksum == MAGIC_SIGNATURE) ? 1 : 0;
}
} }
+7 -7
View File
@@ -26,7 +26,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u8 readU8(u64 ip) = 0; virtual u8 readU8(u64 ip) const = 0;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -34,7 +34,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u16 readU16(u64 ip) = 0; virtual u16 readU16(u64 ip) const = 0;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -42,7 +42,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u32 readU32(u64 ip) = 0; virtual u32 readU32(u64 ip) const = 0;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -50,20 +50,20 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u64 readU64(u64 ip) = 0; virtual u64 readU64(u64 ip) const = 0;
/** /**
* Reads a range of data, and * Reads a range of data, and
* outputs it. * outputs it.
*/ */
virtual void readRange(u64 ip, u8* out, u64 length) = 0; virtual void readRange(u64 ip, u8* out, u64 length) const = 0;
virtual void loadRegister(u64 ip, u8 size_code, register_t* r) = 0; virtual void loadRegister(u64 ip, u8 size_code, register_t* r) const = 0;
/** /**
* Current size of the instructions. * Current size of the instructions.
*/ */
virtual u64 size() = 0; virtual u64 size() const = 0;
public: // Static Utils // public: // Static Utils //
+268 -167
View File
@@ -5,181 +5,69 @@
namespace spider { namespace spider {
InstrReelDyn::InstrReelDyn(u64 length) : _size(length) { InstrReelDyn::InstrReelDyn(u64 length) : _size(length) {
// Safe int ceil division if (_size == 0) return;
growTo((length >> 8) + ((length & 255) != 0));
// 1. Allocate and fill the buffer with zeroed blocks
grow(_size);
_buffer.assign(_size, 0);
// 2. Pad the physical vector to match block alignment
if (_buffer.size() % _blocksize != 0) {
u64 padding = _blocksize - (_buffer.size() % _blocksize);
_buffer.insert(_buffer.end(), padding, 0);
}
// 3. Manifest the initial blank part in our orchestration
_pieces.push_back({ 0, _size });
} }
//InstrReelDyn::InstrReelDyn(const u8* data, u64 length) {} InstrReelDyn::InstrReelDyn(const u8* data, u64 length) : _size(0) {
if (length == 0) return;
grow(length);
write(0, data, length);
}
InstrReelDyn::InstrReelDyn(const InstrReelDyn& copy) InstrReelDyn::InstrReelDyn(const InstrReelDyn& copy)
: _blocks(copy._blocks), _size(copy._size) { : _buffer(copy._buffer),
} _pieces(copy._pieces),
_size(copy._size) {}
// No-throw Move Constructor
InstrReelDyn::InstrReelDyn(InstrReelDyn&& move) noexcept InstrReelDyn::InstrReelDyn(InstrReelDyn&& move) noexcept
: _blocks(std::move(move._blocks)), _size(std::move(move._size)) { : _buffer(std::move(move._buffer)),
_pieces(std::move(move._pieces)),
_size(move._size) {
move._size = 0;
} }
// Explicit Destructor execution
InstrReelDyn::~InstrReelDyn() { InstrReelDyn::~InstrReelDyn() {
// .. // _pieces.clear();
_buffer.clear();
} }
// Deep Copy Assignment Operator
InstrReelDyn& InstrReelDyn::operator=(const InstrReelDyn& copy) { InstrReelDyn& InstrReelDyn::operator=(const InstrReelDyn& copy) {
_blocks = copy._blocks; if (this != &copy) {
_size = copy._size; _buffer = copy._buffer;
_pieces = copy._pieces;
_size = copy._size;
}
return *this; return *this;
} }
// No-throw Move Assignment Operator
InstrReelDyn& InstrReelDyn::operator=(InstrReelDyn&& move) noexcept { InstrReelDyn& InstrReelDyn::operator=(InstrReelDyn&& move) noexcept {
_blocks = std::move(move._blocks); if (this != &move) {
_size = std::move(move._size); _buffer = std::move(move._buffer);
_pieces = std::move(move._pieces);
_size = move._size;
move._size = 0;
}
return *this; return *this;
} }
void InstrReelDyn::growTo(u64 ip) { void InstrReelDyn::loadRegister(u64 ip, u8 size_code, register_t* r) const {
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]; u8 bytes[8];
readRange(ip, bytes, 1 << size_code); readRange(ip, bytes, 1 << size_code);
spider::loadRegister[size_code](r, bytes, 8); spider::loadRegister[size_code](r, bytes, 8);
@@ -188,22 +76,235 @@ namespace spider {
/** /**
* Current size of the instructions. * Current size of the instructions.
*/ */
u64 InstrReelDyn::size() { u64 InstrReelDyn::size() const {
return _size; return _size;
} }
// Reading, Prepared //
u8 InstrReelDyn::readU8(u64 ip) const {
u8 dat;
u8 arr[sizeof(dat)];
readRange(ip, arr, sizeof(arr));
spider::loadPartialLE(&dat, arr, sizeof(arr));
return dat;
}
u16 InstrReelDyn::readU16(u64 ip) const {
u16 dat;
u8 arr[sizeof(dat)];
readRange(ip, arr, sizeof(arr));
spider::loadPartialLE(&dat, arr, sizeof(arr));
return dat;
}
u32 InstrReelDyn::readU32(u64 ip) const {
u32 dat;
u8 arr[sizeof(dat)];
readRange(ip, arr, sizeof(arr));
spider::loadPartialLE(&dat, arr, sizeof(arr));
return dat;
}
u64 InstrReelDyn::readU64(u64 ip) const {
u64 dat;
u8 arr[sizeof(dat)];
readRange(ip, arr, sizeof(arr));
spider::loadPartialLE(&dat, arr, sizeof(arr));
return dat;
}
// Mutation // // Mutation //
// TODO! void InstrReelDyn::readRange(u64 ip, u8* dat, const u64 len) const {
// 1. Boundary Guard
if (len == 0 || ip + len > _size || dat == nullptr) return;
//void InstrReelDyn::writeU8(u64 ip, u8 dat) {} u64 bytes_copied = 0;
//void InstrReelDyn::writeU16(u64 ip, u16 dat) {} u64 current_ip = 0;
//void InstrReelDyn::writeU32(u64 ip, u32 dat) {}
//void InstrReelDyn::writeU64(u64 ip, u64 dat) {}
/** for (const auto& p : _pieces) {
* Appends instruction at the end. u64 piece_start = current_ip;
*/ u64 piece_end = current_ip + p.length;
//void InstrReelDyn::append(u16 bc) {}
// 2. Determine if the requested read window overlaps with this piece
if (ip + bytes_copied < piece_end && (ip + len) > piece_start) {
// Calculate where inside this specific piece our read window begins
u64 read_start_logical = std::max(ip + bytes_copied, piece_start);
u64 local_offset_within_piece = read_start_logical - piece_start;
// Calculate how many remaining bytes can be extracted from this piece
u64 available_in_piece = p.length - local_offset_within_piece;
u64 bytes_to_copy = std::min(len - bytes_copied, available_in_piece);
// 3. Perform safe unaligned copy from our master buffer to the user's destination
const u8* src_ptr = _buffer.data() + p.offset + local_offset_within_piece;
std::memcpy(dat + bytes_copied, src_ptr, bytes_to_copy);
bytes_copied += bytes_to_copy;
// 4. Optimization: Break early if we've completely satisfied the read request
if (bytes_copied == len) {
break;
}
}
current_ip += p.length;
}
}
void InstrReelDyn::write(u64 ip, const u8* dat, const u64 len) {
if (len == 0) return;
// If writing inside existing data, we OVERWRITE by removing the old section first.
// If ip >= _size, it naturally appends, so remove does nothing.
if (ip < _size) {
u64 bytes_to_overwrite = std::min(len, _size - ip);
remove(ip, bytes_to_overwrite);
}
// 1. Capture the exact physical offset BEFORE inserting data or padding
grow(len);
u64 write_offset = _buffer.size();
_buffer.insert(_buffer.end(), dat, dat + len);
// Apply padding immediately so _buffer.size() is always clean for the next run
if (_buffer.size() % _blocksize != 0) {
u64 padding = _blocksize - (_buffer.size() % _blocksize);
_buffer.insert(_buffer.end(), padding, 0);
}
// 2. Orchestrate Pieces (This is strictly an Insertion now because Old Data was removed)
if (_pieces.empty() || ip >= _size) {
_pieces.push_back({ write_offset, len });
_size += len;
return;
}
u64 current_ip = 0;
for (auto it = _pieces.begin(); it != _pieces.end(); ++it) {
if (current_ip + it->length >= ip) {
u64 local_offset = ip - current_ip;
if (local_offset == 0) {
_pieces.insert(it, { write_offset, len });
} else {
// Split the piece cleanly
piece left = { it->offset, local_offset };
piece right = { it->offset + local_offset, it->length - local_offset };
*it = left; // Update existing piece to be the 'left' side
auto next_it = std::next(it);
next_it = _pieces.insert(next_it, { write_offset, len });
_pieces.insert(std::next(next_it), right);
}
break; // Essential: stop processing once the piece is handled!
}
current_ip += it->length;
}
_size += len;
}
void InstrReelDyn::remove(u64 ip, const u64 len) {
if (len == 0 || ip + len > _size) return;
u64 current_ip = 0;
u64 bytes_to_remove = len;
for (auto it = _pieces.begin(); it != _pieces.end() && bytes_to_remove > 0;) {
u64 piece_start = current_ip;
u64 piece_end = current_ip + it->length;
if (ip < piece_end && (ip + bytes_to_remove) > piece_start) {
u64 overlap_start = std::max(ip, piece_start);
u64 overlap_end = std::min(ip + bytes_to_remove, piece_end);
u64 overlap_len = overlap_end - overlap_start;
u64 local_offset = overlap_start - piece_start;
if (local_offset == 0 && overlap_len == it->length) {
it = _pieces.erase(it); // Returns next valid iterator safely
} else if (local_offset == 0) {
it->offset += overlap_len;
it->length -= overlap_len;
++it;
} else if (local_offset + overlap_len == it->length) {
it->length -= overlap_len;
++it;
} else {
// Slice a hole out of the middle
piece right = { it->offset + local_offset + overlap_len, it->length - (local_offset + overlap_len) };
it->length = local_offset;
_pieces.insert(std::next(it), right);
break;
}
bytes_to_remove -= overlap_len;
} else {
current_ip += it->length;
++it;
}
}
_size -= len;
}
void InstrReelDyn::defragment() {
// 1. Edge Case: If the buffer is completely empty, reset states cleanly
if (_size == 0) {
_pieces.clear();
_buffer.clear();
_size = 0;
return;
}
// 2. Optimization: If there is only 1 piece and it's already aligned at physical offset 0,
// then the buffer is already perfectly defragmented. Skip the work entirely.
if (_pieces.size() == 1 && _pieces.front().offset == 0) {
return;
}
// 3. Allocate a fresh, temporary vector aligned perfectly to your 256-byte blocks
std::vector<u8> clean_buffer;
// We use the same rounding formula to ensure clean_buffer matches block boundaries
u64 blocks_needed = (_size + _blocksize - 1) / _blocksize;
clean_buffer.reserve(blocks_needed * _blocksize);
// 4. Linearly stream only the ACTIVE byte chunks into our clean buffer
for (const auto& p : _pieces) {
const u8* src_ptr = _buffer.data() + p.offset;
clean_buffer.insert(clean_buffer.end(), src_ptr, src_ptr + p.length);
}
// 5. Enforce trailing block alignment padding
if (clean_buffer.size() % _blocksize != 0) {
u64 padding = _blocksize - (clean_buffer.size() % _blocksize);
clean_buffer.insert(clean_buffer.end(), padding, 0);
}
// 6. Fast O(1) swap to point your class to the new optimized buffer
_buffer = std::move(clean_buffer);
// 7. Reset piece orchestration to a single monolithic piece mapping 1:1
_pieces.clear();
_pieces.push_back({ 0, _size });
}
void InstrReelDyn::grow(u64 len) {
u64 current_capacity = _buffer.capacity();
// Account for requested bytes PLUS up to a block's worth of trailing alignment padding
u64 minimum_needed = _buffer.size() + len + (_blocksize - 1);
if (minimum_needed > current_capacity) {
// Grow exponentially (1.5x). If empty, seed it with 1 full block minimum.
u64 raw_growth = (current_capacity == 0) ? _blocksize : current_capacity + (current_capacity / 2);
u64 target_capacity = std::max(minimum_needed, raw_growth);
// Round the final target UP to the nearest 256-byte block
u64 blocks = (target_capacity + _blocksize - 1) / _blocksize;
_buffer.reserve(blocks * _blocksize);
}
}
} }
+20 -28
View File
@@ -2,6 +2,8 @@
#include <spider/runtime/reel/InstrReel.hpp> #include <spider/runtime/reel/InstrReel.hpp>
#include <list>
namespace spider { namespace spider {
/** /**
@@ -10,13 +12,14 @@ namespace spider {
class InstrReelDyn : public InstrReel { class InstrReelDyn : public InstrReel {
private: private:
struct ReelBlock { struct piece {
u8 data[256] = {}; u64 offset;
u64 length;
}; };
private: static constexpr u64 _blocksize = 256;
std::vector<u8> _buffer;
deque<ReelBlock> _blocks; std::list<piece> _pieces;
u64 _size; u64 _size;
public: public:
@@ -37,14 +40,6 @@ namespace spider {
InstrReelDyn& operator=(InstrReelDyn&& move) noexcept; 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: public:
/** /**
@@ -53,7 +48,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u8 readU8(u64 ip) override; virtual u8 readU8(u64 ip) const override;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -61,7 +56,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u16 readU16(u64 ip) override; virtual u16 readU16(u64 ip) const override;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -69,7 +64,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u32 readU32(u64 ip) override; virtual u32 readU32(u64 ip) const override;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -77,35 +72,32 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u64 readU64(u64 ip) override; virtual u64 readU64(u64 ip) const override;
/** /**
* Reads a range of data, and * Reads a range of data, and
* outputs it. * outputs it.
*/ */
virtual void readRange(u64 ip, u8* out, u64 length) override; virtual void readRange(u64 ip, u8* out, u64 length) const override;
virtual void loadRegister(u64 ip, u8 size_code, register_t* r) override; virtual void loadRegister(u64 ip, u8 size_code, register_t* r) const override;
/** /**
* Current size of the instructions. * Current size of the instructions.
*/ */
virtual u64 size() override; virtual u64 size() const override;
public: public:
void writeU8(u64 ip, u8 dat); void write(u64 ip, const u8* dat, const u64 len);
void writeU16(u64 ip, u16 dat); void remove(u64 ip, const u64 len);
void writeU32(u64 ip, u32 dat); void defragment();
void writeU64(u64 ip, u64 dat); private:
/** void grow(u64 len);
* Appends instruction at the end.
*/
void append(u16 bc);
}; };
+7 -9
View File
@@ -42,44 +42,42 @@ namespace spider {
delete[] _mem; delete[] _mem;
} }
// General Case(s) //
// Instruction abstraction // // Instruction abstraction //
u8 InstrReelFixed::readU8(u64 ip) { u8 InstrReelFixed::readU8(u64 ip) const {
u8 dat; u8 dat;
spider::loadPartialLE(&dat, _mem + ip, _size); spider::loadPartialLE(&dat, _mem + ip, _size);
return dat; return dat;
} }
u16 InstrReelFixed::readU16(u64 ip) { u16 InstrReelFixed::readU16(u64 ip) const {
u16 dat; u16 dat;
spider::loadPartialLE(&dat, _mem + ip, _size); spider::loadPartialLE(&dat, _mem + ip, _size);
return dat; return dat;
} }
u32 InstrReelFixed::readU32(u64 ip) { u32 InstrReelFixed::readU32(u64 ip) const {
u32 dat; u32 dat;
spider::loadPartialLE(&dat, _mem + ip, _size); spider::loadPartialLE(&dat, _mem + ip, _size);
return dat; return dat;
} }
u64 InstrReelFixed::readU64(u64 ip) { u64 InstrReelFixed::readU64(u64 ip) const {
u64 dat; u64 dat;
spider::loadPartialLE(&dat, _mem + ip, _size); spider::loadPartialLE(&dat, _mem + ip, _size);
return dat; return dat;
} }
void InstrReelFixed::readRange(u64 ip, u8* out, u64 length) { void InstrReelFixed::readRange(u64 ip, u8* out, u64 length) const {
spider::loadPartialBytes(_mem, isize(ip), _size, out, length); spider::loadPartialBytes(_mem, isize(ip), _size, out, length);
} }
void InstrReelFixed::loadRegister(u64 ip, u8 size_code, register_t* r) { void InstrReelFixed::loadRegister(u64 ip, u8 size_code, register_t* r) const {
ip = std::min(ip, _size); ip = std::min(ip, _size);
spider::loadRegister[size_code](r, _mem + ip, _size - ip); spider::loadRegister[size_code](r, _mem + ip, _size - ip);
} }
u64 InstrReelFixed::size() { u64 InstrReelFixed::size() const {
return _size; return _size;
} }
+7 -7
View File
@@ -38,7 +38,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u8 readU8(u64 ip) override; virtual u8 readU8(u64 ip) const override;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -46,7 +46,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u16 readU16(u64 ip) override; virtual u16 readU16(u64 ip) const override;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -54,7 +54,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u32 readU32(u64 ip) override; virtual u32 readU32(u64 ip) const override;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -62,20 +62,20 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u64 readU64(u64 ip) override; virtual u64 readU64(u64 ip) const override;
/** /**
* Reads a range of data, and * Reads a range of data, and
* outputs it. * outputs it.
*/ */
virtual void readRange(u64 ip, u8* out, u64 length) override; virtual void readRange(u64 ip, u8* out, u64 length) const override;
virtual void loadRegister(u64 ip, u8 size_code, register_t* r) override; virtual void loadRegister(u64 ip, u8 size_code, register_t* r) const override;
/** /**
* Current size of the instructions. * Current size of the instructions.
*/ */
virtual u64 size() override; virtual u64 size() const override;
public: public:
-118
View File
@@ -1,118 +0,0 @@
#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;
}