Compare commits
31 Commits
1e2524a4cb
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 017a3f5f6d | |||
| 708c4ab593 | |||
| 869ce0c7bf | |||
| 5f4c2abec8 | |||
| 0c21587e15 | |||
| a36705a931 | |||
| 29797fb707 | |||
| 22d7b0afbe | |||
| c3cf293bc9 | |||
| bc8fb3435d | |||
| 309b823f19 | |||
| 31dd45c932 | |||
| c018c2c668 | |||
| 2d89f489ae | |||
| f1bb779e86 | |||
| 56114dc1b6 | |||
| 417bef1aa5 | |||
| 7cddb55469 | |||
| 7722e450d4 | |||
| 3f6b064e32 | |||
| 525a9d806b | |||
| 0ad9172dce | |||
| ccd6248973 | |||
| 51b644cf79 | |||
| a11732abda | |||
| b0b7fa0ebb | |||
| cdf14cf545 | |||
| c3c94583f4 | |||
| 1fe555aaba | |||
| 9cd0570edd | |||
| 057ed48df1 |
@@ -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.
@@ -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
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|
||||||
|
|||||||
+186
-21
@@ -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
|
|
||||||
* 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
|
void CPU::hookRAM(RAM* ram) {
|
||||||
for (u16 i = 0; i < 256; i++) {
|
this->_ram = ram;
|
||||||
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() {}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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];
|
||||||
};
|
};
|
||||||
@@ -172,6 +171,18 @@ namespace spider {
|
|||||||
*/
|
*/
|
||||||
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
|
||||||
@@ -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] 0x0F6 — DGANT: "In kaaba Spider" (Yucatec Maya: My name is Spider)
|
// [Easter Eggs] 0x0F1 — INT_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> //
|
||||||
|
|||||||
@@ -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() {}
|
|
||||||
}
|
|
||||||
@@ -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(<, &t);
|
|
||||||
#endif
|
|
||||||
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
|
|
||||||
localtime_r(&t, <);
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace spider {
|
|
||||||
|
|
||||||
int liveDebugMain();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
switch (((RF >> _src->_u8) & 1) != ((_dst->_u8 >> _src->_u8) & 1)){
|
|
||||||
case 1:
|
|
||||||
RF |= (1 << _src->_u8);
|
|
||||||
|
|
||||||
case 0:
|
u64 s, d;
|
||||||
RF &= ~(1 << _src->_u8);
|
switch(_size) {
|
||||||
}
|
case 0b00: // byte
|
||||||
case 0b01: //short
|
s = _src->_u8;
|
||||||
switch (((RF >> _src->_u16) & 1) != ((_dst->_u16 >> _src->_u16) & 1)){
|
d = _dst->_u8;
|
||||||
case 1:
|
break;
|
||||||
RF |= (1 << _src->_u16);
|
case 0b01: // short
|
||||||
|
s = _src->_u16;
|
||||||
case 0:
|
d = _dst->_u16;
|
||||||
RF &= ~(1 << _src->_u16);
|
break;
|
||||||
}
|
case 0b10: // int
|
||||||
case 0b10: //int
|
s = _src->_u32;
|
||||||
switch (((RF >> _src->_u32) & 1) != ((_dst->_u32 >> _src->_u32) & 1)){
|
d = _dst->_u32;
|
||||||
case 1:
|
break;
|
||||||
RF |= (1 << _src->_u32);
|
case 0b11: // long
|
||||||
|
s = _src->_u64;
|
||||||
case 0:
|
d = _dst->_u64;
|
||||||
RF &= ~(1 << _src->_u32);
|
break;
|
||||||
}
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 //
|
||||||
|
|
||||||
|
|||||||
@@ -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 != ©) {
|
||||||
_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user