Merge branch 'main' of https://git.sintekanalytics.com/SpiderLang/spider-runtime
This commit is contained in:
@@ -16,107 +16,107 @@ constexpr u8 ADDR_MODE_MASKS[][2] = {
|
|||||||
{ 0x1E, 0x00 }, // FIR
|
{ 0x1E, 0x00 }, // FIR
|
||||||
{ 0x1E, 0x00 }, // FZR
|
{ 0x1E, 0x00 }, // FZR
|
||||||
{ 0x1E, 0x1F }, // LSR
|
{ 0x1E, 0x1F }, // LSR
|
||||||
{ 0x00, 0x00 }, // FVR
|
{ 0x04, 0x00 }, // FVR
|
||||||
{ 0x00, 0x00 }, // MOV
|
{ 0x1E, 0xFF }, // MOV
|
||||||
{ 0x00, 0x00 }, // MOR
|
{ 0x04, 0x04 }, // MOR
|
||||||
{ 0x00, 0x00 }, // AMOV
|
{ 0x00, 0x00 }, // AMOV
|
||||||
{ 0x04, 0x04 }, // SWP
|
{ 0x04, 0x04 }, // SWP
|
||||||
{ 0x04, 0x00 }, // AHM
|
{ 0x04, 0x00 }, // AHM
|
||||||
{ 0x00, 0x00 }, // COM
|
{ 0xFF, 0x00 }, // COM
|
||||||
{ 0x00, 0x00 }, // NEG
|
{ 0xFF, 0x00 }, // NEG
|
||||||
{ 0x00, 0x00 }, // EXS
|
{ 0xFF, 0x00 }, // EXS
|
||||||
{ 0x00, 0x00 }, // INC
|
{ 0xFF, 0x00 }, // INC
|
||||||
{ 0x00, 0x00 }, // DEC
|
{ 0xFF, 0x00 }, // DEC
|
||||||
{ 0x00, 0x00 }, // ADD
|
{ 0x1E, 0xFF }, // ADD
|
||||||
{ 0x00, 0x00 }, // SUB
|
{ 0x1E, 0xFF }, // SUB
|
||||||
{ 0x00, 0x00 }, // MUL
|
{ 0x1E, 0xFF }, // MUL
|
||||||
{ 0x00, 0x00 }, // UMUL
|
{ 0x1E, 0xFF }, // UMUL
|
||||||
{ 0x00, 0x00 }, // DIV
|
{ 0x1E, 0xFF }, // DIV
|
||||||
{ 0x00, 0x00 }, // UDIV
|
{ 0x1E, 0xFF }, // UDIV
|
||||||
{ 0x00, 0x00 }, // MOD
|
{ 0x1E, 0xFF }, // MOD
|
||||||
{ 0x00, 0x00 }, // UMOD
|
{ 0x1E, 0xFF }, // UMOD
|
||||||
{ 0x00, 0x00 }, // DMOD
|
{ 0x1E, 0xFF }, // DMOD
|
||||||
{ 0x00, 0x00 }, // UDMD
|
{ 0x1E, 0xFF }, // UDMD
|
||||||
{ 0x00, 0x00 }, // FBT
|
{ 0xFF, 0x00 }, // FBT
|
||||||
{ 0x00, 0x00 }, // STB
|
{ 0x1E, 0xFF }, // STB
|
||||||
{ 0x00, 0x00 }, // CRB
|
{ 0x1E, 0xFF }, // CRB
|
||||||
{ 0x00, 0x00 }, // TSB
|
{ 0x1E, 0xFF }, // TSB
|
||||||
{ 0x00, 0x00 }, // BOOL
|
{ 0xFF, 0x00 }, // BOOL
|
||||||
{ 0x00, 0x00 }, // NOT
|
{ 0xFF, 0x00 }, // NOT
|
||||||
{ 0x00, 0x00 }, // AND
|
{ 0x1E, 0xFF }, // AND
|
||||||
{ 0x00, 0x00 }, // OR
|
{ 0x1E, 0xFF }, // OR
|
||||||
{ 0x00, 0x00 }, // XOR
|
{ 0x1E, 0xFF }, // XOR
|
||||||
{ 0x00, 0x00 }, // SHL
|
{ 0x1E, 0xFF }, // SHL
|
||||||
{ 0x00, 0x00 }, // SHR
|
{ 0x1E, 0xFF }, // SHR
|
||||||
{ 0x00, 0x00 }, // SSR
|
{ 0x1E, 0xFF }, // SSR
|
||||||
{ 0x00, 0x00 }, // ROL
|
{ 0x1E, 0xFF }, // ROL
|
||||||
{ 0x00, 0x00 }, // ROR
|
{ 0x1E, 0xFF }, // ROR
|
||||||
{ 0x00, 0x00 }, // CNT
|
{ 0xFF, 0x00 }, // CNT
|
||||||
{ 0x00, 0x00 }, // EQ
|
{ 0x1E, 0xFF }, // EQ
|
||||||
{ 0x00, 0x00 }, // NE
|
{ 0x1E, 0xFF }, // NE
|
||||||
{ 0x00, 0x00 }, // GT
|
{ 0x1E, 0xFF }, // GT
|
||||||
{ 0x00, 0x00 }, // GE
|
{ 0x1E, 0xFF }, // GE
|
||||||
{ 0x00, 0x00 }, // LT
|
{ 0x1E, 0xFF }, // LT
|
||||||
{ 0x00, 0x00 }, // LE
|
{ 0x1E, 0xFF }, // LE
|
||||||
{ 0x00, 0x00 }, // JMP
|
{ 0xFF, 0x00 }, // JMP
|
||||||
{ 0x00, 0x00 }, // JEQ
|
{ 0xFF, 0x00 }, // JEQ
|
||||||
{ 0x00, 0x00 }, // JNE
|
{ 0xFF, 0x00 }, // JNE
|
||||||
{ 0x00, 0x00 }, // JIF
|
{ 0x1E, 0xFF }, // JIF
|
||||||
{ 0x00, 0x00 }, // JMR
|
{ 0xFF, 0x00 }, // JMR
|
||||||
{ 0x00, 0x00 }, // JER
|
{ 0xFF, 0x00 }, // JER
|
||||||
{ 0x00, 0x00 }, // JNR
|
{ 0xFF, 0x00 }, // JNR
|
||||||
{ 0x00, 0x00 }, // JIR
|
{ 0x1E, 0xFF }, // JIR
|
||||||
{ 0x00, 0x00 }, // SFB
|
{ 0x1E, 0xFF }, // SFB
|
||||||
{ 0x00, 0x00 }, // LFB
|
{ 0x1E, 0xFF }, // LFB
|
||||||
{ 0x00, 0x00 }, // JUF
|
{ 0x1E, 0xFF }, // JUF
|
||||||
{ 0x00, 0x00 }, // JUR
|
{ 0x1E, 0xFF }, // JUR
|
||||||
{ 0x00, 0x00 }, // PUSH
|
{ 0xFF, 0x00 }, // PUSH
|
||||||
{ 0x00, 0x00 }, // POP
|
{ 0xFF, 0x00 }, // POP
|
||||||
{ 0x00, 0x00 }, // ALLOC
|
{ 0xFF, 0x00 }, // ALLOC
|
||||||
{ 0x00, 0x00 }, // HFREE
|
{ 0xFF, 0x00 }, // HFREE
|
||||||
{ 0x00, 0x00 }, // CALL
|
{ 0xFF, 0x00 }, // CALL
|
||||||
{ 0x00, 0x00 }, // RET
|
{ 0x00, 0x00 }, // RET
|
||||||
{ 0x00, 0x00 }, // EDI
|
{ 0xFF, 0x00 }, // EDI
|
||||||
{ 0x00, 0x00 }, // SHSS
|
{ 0xFF, 0x00 }, // SHSS
|
||||||
{ 0x00, 0x00 }, // FLI
|
{ 0xFF, 0x00 }, // FLI
|
||||||
{ 0x00, 0x00 }, // FNEG
|
{ 0xFF, 0x00 }, // FNEG
|
||||||
{ 0x00, 0x00 }, // FADD
|
{ 0x1E, 0xFF }, // FADD
|
||||||
{ 0x00, 0x00 }, // FSUB
|
{ 0x1E, 0xFF }, // FSUB
|
||||||
{ 0x00, 0x00 }, // FMUL
|
{ 0x1E, 0xFF }, // FMUL
|
||||||
{ 0x00, 0x00 }, // FDIV
|
{ 0x1E, 0xFF }, // FDIV
|
||||||
{ 0x00, 0x00 }, // FMOD
|
{ 0x1E, 0xFF }, // FMOD
|
||||||
{ 0x00, 0x00 }, // FDMOD
|
{ 0x1E, 0xFF }, // FDMOD
|
||||||
{ 0x00, 0x00 }, // FEPS
|
{ 0xFF, 0x00 }, // FEPS
|
||||||
{ 0x00, 0x00 }, // FEEP
|
{ 0xFF, 0x00 }, // FEEP
|
||||||
{ 0x00, 0x00 }, // FEQ
|
{ 0x1E, 0xFF }, // FEQ
|
||||||
{ 0x00, 0x00 }, // FNE
|
{ 0x1E, 0xFF }, // FNE
|
||||||
{ 0x00, 0x00 }, // FGT
|
{ 0x1E, 0xFF }, // FGT
|
||||||
{ 0x00, 0x00 }, // FGE
|
{ 0x1E, 0xFF }, // FGE
|
||||||
{ 0x00, 0x00 }, // FLT
|
{ 0x1E, 0xFF }, // FLT
|
||||||
{ 0x00, 0x00 }, // FLE
|
{ 0x1E, 0xFF }, // FLE
|
||||||
{ 0x00, 0x00 }, // F2D
|
{ 0xFF, 0x00 }, // F2D
|
||||||
{ 0x00, 0x00 }, // D2F
|
{ 0xFF, 0x00 }, // D2F
|
||||||
{ 0x00, 0x00 }, // I2F
|
{ 0xFF, 0x00 }, // I2F
|
||||||
{ 0x00, 0x00 }, // I2D
|
{ 0xFF, 0x00 }, // I2D
|
||||||
{ 0x00, 0x00 }, // L2F
|
{ 0xFF, 0x00 }, // L2F
|
||||||
{ 0x00, 0x00 }, // L2D
|
{ 0xFF, 0x00 }, // L2D
|
||||||
{ 0x00, 0x00 }, // F2I
|
{ 0xFF, 0x00 }, // F2I
|
||||||
{ 0x00, 0x00 }, // F2L
|
{ 0xFF, 0x00 }, // F2L
|
||||||
{ 0x00, 0x00 }, // D2I
|
{ 0xFF, 0x00 }, // D2I
|
||||||
{ 0x00, 0x00 }, // D2L
|
{ 0xFF, 0x00 }, // D2L
|
||||||
{ 0x00, 0x00 }, // SIN
|
{ 0xFF, 0x00 }, // SIN
|
||||||
{ 0x00, 0x00 }, // COS
|
{ 0xFF, 0x00 }, // COS
|
||||||
{ 0x00, 0x00 }, // TAN
|
{ 0xFF, 0x00 }, // TAN
|
||||||
{ 0x00, 0x00 }, // ASIN
|
{ 0xFF, 0x00 }, // ASIN
|
||||||
{ 0x00, 0x00 }, // ACOS
|
{ 0xFF, 0x00 }, // ACOS
|
||||||
{ 0x00, 0x00 }, // ATAN
|
{ 0xFF, 0x00 }, // ATAN
|
||||||
{ 0x00, 0x00 }, // ATAN2
|
{ 0x1E, 0xFF }, // ATAN2
|
||||||
{ 0x00, 0x00 }, // EXP
|
{ 0xFF, 0x00 }, // EXP
|
||||||
{ 0x00, 0x00 }, // LOG
|
{ 0xFF, 0x00 }, // LOG
|
||||||
{ 0x00, 0x00 }, // LOGAB
|
{ 0x1E, 0xFF }, // LOGAB
|
||||||
{ 0x00, 0x00 }, // POW
|
{ 0x1E, 0xFF }, // POW
|
||||||
{ 0x00, 0x00 }, // SQRT
|
{ 0xFF, 0x00 }, // SQRT
|
||||||
{ 0x00, 0x00 }, // ROOT
|
{ 0x1E, 0xFF }, // ROOT
|
||||||
{ 0x00, 0x00 }, // ADC
|
{ 0x00, 0x00 }, // ADC
|
||||||
{ 0x00, 0x00 }, // SWC
|
{ 0x00, 0x00 }, // SWC
|
||||||
{ 0x00, 0x00 }, // MWO
|
{ 0x00, 0x00 }, // MWO
|
||||||
@@ -127,6 +127,8 @@ constexpr u8 ADDR_MODE_MASKS[][2] = {
|
|||||||
{ 0x00, 0x00 }, // MINV
|
{ 0x00, 0x00 }, // MINV
|
||||||
{ 0x00, 0x00 }, // MTRA
|
{ 0x00, 0x00 }, // MTRA
|
||||||
{ 0x00, 0x00 }, // MDET
|
{ 0x00, 0x00 }, // MDET
|
||||||
|
{ 0x00, 0x00 }, // QMKA
|
||||||
|
{ 0x00, 0x00 }, // QMUL
|
||||||
{ 0x00, 0x00 }, // XADD
|
{ 0x00, 0x00 }, // XADD
|
||||||
{ 0x00, 0x00 }, // XSUB
|
{ 0x00, 0x00 }, // XSUB
|
||||||
{ 0x00, 0x00 }, // XAMA
|
{ 0x00, 0x00 }, // XAMA
|
||||||
@@ -140,18 +142,18 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
|
|||||||
0x00, // NOP
|
0x00, // NOP
|
||||||
0x00, // SPDR
|
0x00, // SPDR
|
||||||
0x01, // MMODE
|
0x01, // MMODE
|
||||||
0x0F, // INT
|
0x08, // INT
|
||||||
0x0C, // LRV
|
0x08, // LRV
|
||||||
0x0F, // FSR
|
0x08, // FSR
|
||||||
0x0F, // FIR
|
0x08, // FIR
|
||||||
0x0F, // FZR
|
0x08, // FZR
|
||||||
0x0F, // LSR
|
0x08, // LSR
|
||||||
0x0F, // FVR
|
0x08, // FVR
|
||||||
0x00, // MOV
|
0x0F, // MOV
|
||||||
0x00, // MOR
|
0x08, // MOR
|
||||||
0x00, // AMOV
|
0x08, // AMOV
|
||||||
0x00, // SWP
|
0x08, // SWP
|
||||||
0x0F, // AHM
|
0x08, // AHM
|
||||||
0x0F, // COM
|
0x0F, // COM
|
||||||
0x0F, // NEG
|
0x0F, // NEG
|
||||||
0x0F, // EXS
|
0x0F, // EXS
|
||||||
@@ -208,22 +210,22 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
|
|||||||
0x0F, // RET
|
0x0F, // RET
|
||||||
0x0F, // EDI
|
0x0F, // EDI
|
||||||
0x0F, // SHSS
|
0x0F, // SHSS
|
||||||
0x00, // FLI
|
0x0C, // FLI
|
||||||
0x00, // FNEG
|
0x0C, // FNEG
|
||||||
0x00, // FADD
|
0x0C, // FADD
|
||||||
0x00, // FSUB
|
0x0C, // FSUB
|
||||||
0x00, // FMUL
|
0x0C, // FMUL
|
||||||
0x00, // FDIV
|
0x0C, // FDIV
|
||||||
0x00, // FMOD
|
0x0C, // FMOD
|
||||||
0x00, // FDMOD
|
0x0C, // FDMOD
|
||||||
0x00, // FEPS
|
0x0C, // FEPS
|
||||||
0x00, // FEEP
|
0x0C, // FEEP
|
||||||
0x00, // FEQ
|
0x0C, // FEQ
|
||||||
0x00, // FNE
|
0x0C, // FNE
|
||||||
0x00, // FGT
|
0x0C, // FGT
|
||||||
0x00, // FGE
|
0x0C, // FGE
|
||||||
0x00, // FLT
|
0x0C, // FLT
|
||||||
0x00, // FLE
|
0x0C, // FLE
|
||||||
0x00, // F2D
|
0x00, // F2D
|
||||||
0x00, // D2F
|
0x00, // D2F
|
||||||
0x00, // I2F
|
0x00, // I2F
|
||||||
@@ -234,19 +236,19 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
|
|||||||
0x00, // F2L
|
0x00, // F2L
|
||||||
0x00, // D2I
|
0x00, // D2I
|
||||||
0x00, // D2L
|
0x00, // D2L
|
||||||
0x00, // SIN
|
0x0C, // SIN
|
||||||
0x00, // COS
|
0x0C, // COS
|
||||||
0x00, // TAN
|
0x0C, // TAN
|
||||||
0x00, // ASIN
|
0x0C, // ASIN
|
||||||
0x00, // ACOS
|
0x0C, // ACOS
|
||||||
0x00, // ATAN
|
0x0C, // ATAN
|
||||||
0x00, // ATAN2
|
0x0C, // ATAN2
|
||||||
0x00, // EXP
|
0x0C, // EXP
|
||||||
0x00, // LOG
|
0x0C, // LOG
|
||||||
0x00, // LOGAB
|
0x0C, // LOGAB
|
||||||
0x00, // POW
|
0x0C, // POW
|
||||||
0x00, // SQRT
|
0x0C, // SQRT
|
||||||
0x00, // ROOT
|
0x0C, // ROOT
|
||||||
0x00, // ADC
|
0x00, // ADC
|
||||||
0x00, // SWC
|
0x00, // SWC
|
||||||
0x00, // MWO
|
0x00, // MWO
|
||||||
@@ -257,6 +259,8 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
|
|||||||
0x00, // MINV
|
0x00, // MINV
|
||||||
0x00, // MTRA
|
0x00, // MTRA
|
||||||
0x00, // MDET
|
0x00, // MDET
|
||||||
|
0x00, // QMKA
|
||||||
|
0x00, // QMUL
|
||||||
0x00, // XADD
|
0x00, // XADD
|
||||||
0x00, // XSUB
|
0x00, // XSUB
|
||||||
0x00, // XAMA
|
0x00, // XAMA
|
||||||
|
|||||||
Binary file not shown.
12
makefile
12
makefile
@@ -14,8 +14,16 @@ OBJEXT := o
|
|||||||
|
|
||||||
#Flags, Libraries and Includes
|
#Flags, Libraries and Includes
|
||||||
ROOT := ./
|
ROOT := ./
|
||||||
CFLAGS := -Wall -std=c++20 -DSPIDER_COMPILING
|
CFLAGS := -std=c++20 -O2 \
|
||||||
LFLAGS := -Wall -std=c++20 -static
|
-Wall -Wextra \
|
||||||
|
-Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align \
|
||||||
|
-Wunused -Woverloaded-virtual -Wconversion \
|
||||||
|
-Wsign-conversion -Wnull-dereference -Wdouble-promotion \
|
||||||
|
-Wformat=2 -Wimplicit-fallthrough -Wsuggest-override \
|
||||||
|
-Wextra-semi -Wduplicated-cond -Wduplicated-branches \
|
||||||
|
-Wlogical-op -Wuseless-cast
|
||||||
|
LFLAGS := -std=c++20 -static-libstdc++ -static-libgcc \
|
||||||
|
-Wl,--fatal-warnings -Wl,--warn-common
|
||||||
LIB :=
|
LIB :=
|
||||||
INC := -I./src/
|
INC := -I./src/
|
||||||
|
|
||||||
|
|||||||
194
pygen.ipynb
194
pygen.ipynb
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": null,
|
"execution_count": 1,
|
||||||
"id": "b0fcd533",
|
"id": "b0fcd533",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 5,
|
"execution_count": 2,
|
||||||
"id": "b33de8ac",
|
"id": "b33de8ac",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 6,
|
"execution_count": 3,
|
||||||
"id": "58645013",
|
"id": "58645013",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
@@ -152,7 +152,7 @@
|
|||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
"Real instructions : 126\n",
|
"Real instructions : 128\n",
|
||||||
"Reserved slots : 14\n",
|
"Reserved slots : 14\n",
|
||||||
"Duplicate check : PASSED\n",
|
"Duplicate check : PASSED\n",
|
||||||
"\n",
|
"\n",
|
||||||
@@ -163,13 +163,14 @@
|
|||||||
"Bit Wise 14\n",
|
"Bit Wise 14\n",
|
||||||
"Boolean 12\n",
|
"Boolean 12\n",
|
||||||
"Branch 12\n",
|
"Branch 12\n",
|
||||||
"Casts 10\n",
|
|
||||||
"Floating Point 10\n",
|
"Floating Point 10\n",
|
||||||
|
"Casts 10\n",
|
||||||
"Memory 9\n",
|
"Memory 9\n",
|
||||||
"Trigonometric 7\n",
|
"Trigonometric 7\n",
|
||||||
"Exponential 6\n",
|
"Exponential 6\n",
|
||||||
"Matrix 6\n",
|
"Matrix 6\n",
|
||||||
"SIMD 5\n",
|
"SIMD 5\n",
|
||||||
|
"Quaternion 2\n",
|
||||||
"Easter Eggs 1\n",
|
"Easter Eggs 1\n",
|
||||||
"\n",
|
"\n",
|
||||||
"First 5 instructions:\n",
|
"First 5 instructions:\n",
|
||||||
@@ -177,8 +178,8 @@
|
|||||||
"0 000 NOP System 0 00 00\n",
|
"0 000 NOP System 0 00 00\n",
|
||||||
"1 001 SPDR System 0 00 00\n",
|
"1 001 SPDR System 0 00 00\n",
|
||||||
"2 002 MMODE System 1 05 01\n",
|
"2 002 MMODE System 1 05 01\n",
|
||||||
"3 003 INT System 1 1F 0F\n",
|
"3 003 INT System 1 1F 08\n",
|
||||||
"4 004 LRV System 1 1F 0C\n"
|
"4 004 LRV System 1 1F 08\n"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -214,6 +215,7 @@
|
|||||||
" 'dis', # addressing mode: Displaced\n",
|
" 'dis', # addressing mode: Displaced\n",
|
||||||
" 'addr_mask_1', # accepted addressing mode mask for param 1\n",
|
" 'addr_mask_1', # accepted addressing mode mask for param 1\n",
|
||||||
" 'addr_mask_2', # accepted addressing mode mask for param 2\n",
|
" 'addr_mask_2', # accepted addressing mode mask for param 2\n",
|
||||||
|
" 'ignores_addrm',# whether the instruction ignores addressing modes\n",
|
||||||
" 'B', # type size: Byte (1 byte) supported?\n",
|
" 'B', # type size: Byte (1 byte) supported?\n",
|
||||||
" 'S', # type size: Short (2 bytes) supported?\n",
|
" 'S', # type size: Short (2 bytes) supported?\n",
|
||||||
" 'I', # type size: Int (4 bytes) supported?\n",
|
" 'I', # type size: Int (4 bytes) supported?\n",
|
||||||
@@ -221,6 +223,7 @@
|
|||||||
" 'F', # type size: Float supported?\n",
|
" 'F', # type size: Float supported?\n",
|
||||||
" 'D', # type size: Double supported?\n",
|
" 'D', # type size: Double supported?\n",
|
||||||
" 'type_mask', # combined type size mask as hex string\n",
|
" 'type_mask', # combined type size mask as hex string\n",
|
||||||
|
" 'expensive', # marks computationally expensive instructions\n",
|
||||||
" 'operation', # human-readable description of what the instruction does\n",
|
" 'operation', # human-readable description of what the instruction does\n",
|
||||||
" 'skip_2', # trailing empty column\n",
|
" 'skip_2', # trailing empty column\n",
|
||||||
"]\n",
|
"]\n",
|
||||||
@@ -280,7 +283,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 7,
|
"execution_count": 4,
|
||||||
"id": "452bc76c",
|
"id": "452bc76c",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
@@ -289,7 +292,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 : 268\n"
|
"Lines generated : 272\n"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -354,7 +357,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 8,
|
"execution_count": 5,
|
||||||
"id": "5aaebef0",
|
"id": "5aaebef0",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
@@ -362,7 +365,7 @@
|
|||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
"Instructions formatted: 126\n",
|
"Instructions formatted: 128\n",
|
||||||
"\n",
|
"\n",
|
||||||
"--- Preview (first 2 instructions) ---\n",
|
"--- Preview (first 2 instructions) ---\n",
|
||||||
" // [System] 0x000 — NOP: No Operation\n",
|
" // [System] 0x000 — NOP: No Operation\n",
|
||||||
@@ -377,7 +380,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: 674\n"
|
"Total lines in updated file: 883\n"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -445,6 +448,173 @@
|
|||||||
"print(f'\\nCPU.hpp updated successfully at: {CPU_HPP_PATH}')\n",
|
"print(f'\\nCPU.hpp updated successfully at: {CPU_HPP_PATH}')\n",
|
||||||
"print(f'Total lines in updated file: {len(updated.splitlines())}')\n"
|
"print(f'Total lines in updated file: {len(updated.splitlines())}')\n"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 8,
|
||||||
|
"id": "instrmap_gen",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"InstrMap.cpp written to: .//src//spider/runtime/instr/InstrMap.cpp\n",
|
||||||
|
" Size : 34,157 bytes\n",
|
||||||
|
" Array entries : 512 (128 populated, 384 nullptr)\n",
|
||||||
|
" Switch cases : 128\n",
|
||||||
|
" Line endings : LF-only verified\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# ── Generate InstrMap.cpp ────────────────────────────────────────────────────\n",
|
||||||
|
"# Produces two dispatch implementations in one file:\n",
|
||||||
|
"# 1. CPUInstr InstrMap[512] — array of member-function pointers\n",
|
||||||
|
"# 2. void CPU::execute(u16) — switch/case version\n",
|
||||||
|
"#\n",
|
||||||
|
"# Both use UPPERCASE method names matching the mnemonic column.\n",
|
||||||
|
"\n",
|
||||||
|
"TABLE_SIZE = 512 # 9-bit opcode space\n",
|
||||||
|
"\n",
|
||||||
|
"# Build opcode -> mnemonic lookup from the cleaned instruction DataFrame.\n",
|
||||||
|
"opcode_to_mnem: dict[int, str] = {}\n",
|
||||||
|
"opcode_to_name: dict[int, str] = {}\n",
|
||||||
|
"opcode_to_group: dict[int, str] = {}\n",
|
||||||
|
"\n",
|
||||||
|
"for _, row in instrs_df.iterrows():\n",
|
||||||
|
" bc = str(row['byte_code']).strip()\n",
|
||||||
|
" opc = int(bc, 16)\n",
|
||||||
|
" opcode_to_mnem[opc] = str(row['mnemonic']).strip()\n",
|
||||||
|
" opcode_to_name[opc] = str(row['name']).strip()\n",
|
||||||
|
" opcode_to_group[opc] = str(row['group']).strip()\n",
|
||||||
|
"\n",
|
||||||
|
"# Also track reserved slots for annotation.\n",
|
||||||
|
"reserved_opcodes: set[int] = set()\n",
|
||||||
|
"for _, row in reserved_df.iterrows():\n",
|
||||||
|
" bc = str(row['byte_code']).strip()\n",
|
||||||
|
" if bc and bc != 'nan':\n",
|
||||||
|
" reserved_opcodes.add(int(bc, 16))\n",
|
||||||
|
"\n",
|
||||||
|
"# ── Assemble the file ───────────────────────────────────────────────────────\n",
|
||||||
|
"L = []\n",
|
||||||
|
"L.append('/**')\n",
|
||||||
|
"L.append(' * @file InstrMap.cpp')\n",
|
||||||
|
"L.append(' * @brief Spider VM instruction dispatch — array and switch implementations.')\n",
|
||||||
|
"L.append(' *')\n",
|
||||||
|
"L.append(' * AUTO-GENERATED by pygen.ipynb — DO NOT EDIT BY HAND.')\n",
|
||||||
|
"L.append(' *')\n",
|
||||||
|
"L.append(' * This file provides two equivalent dispatch mechanisms:')\n",
|
||||||
|
"L.append(' *')\n",
|
||||||
|
"L.append(' * 1. InstrMap[] — A lookup table of member-function pointers indexed by')\n",
|
||||||
|
"L.append(' * opcode. O(1) dispatch; suitable for platforms where')\n",
|
||||||
|
"L.append(' * indirect calls through function pointers are efficient.')\n",
|
||||||
|
"L.append(' *')\n",
|
||||||
|
"L.append(' * 2. CPU::execute(u16) — A switch/case over every opcode. Lets the')\n",
|
||||||
|
"L.append(' * compiler emit a jump table or branch tree; may be')\n",
|
||||||
|
"L.append(' * preferable on microcontrollers or when link-time')\n",
|
||||||
|
"L.append(' * optimisation can inline the handlers.')\n",
|
||||||
|
"L.append(' *')\n",
|
||||||
|
"L.append(' */')\n",
|
||||||
|
"L.append('') # [CHANGE] Use absolute path to make paths more explicit\n",
|
||||||
|
"L.append('#include <spider/runtime/cpu/CPU.hpp>')\n",
|
||||||
|
"L.append('')\n",
|
||||||
|
"L.append('namespace spider {')\n",
|
||||||
|
"L.append('')\n",
|
||||||
|
"\n",
|
||||||
|
"# ── Version 1: Array: ────────────────────────────────────────────────────────\n",
|
||||||
|
"L.append('// =============================================================')\n",
|
||||||
|
"L.append('// Version 1 — Lookup table of member-function pointers')\n",
|
||||||
|
"L.append('// =============================================================')\n",
|
||||||
|
"L.append('')\n",
|
||||||
|
"# [CHANGE] Use CPU::Fn Instead\n",
|
||||||
|
"#L.append('/** Pointer-to-member type for a zero-argument CPU instruction. */')\n",
|
||||||
|
"#L.append('using CPUInstr = void (CPU::*)();')\n",
|
||||||
|
"L.append('')\n",
|
||||||
|
"L.append('/**')\n",
|
||||||
|
"L.append(f' * Instruction dispatch table ({TABLE_SIZE} entries, 9-bit opcode space).')\n",
|
||||||
|
"L.append(' *')\n",
|
||||||
|
"L.append(' * Usage:')\n",
|
||||||
|
"L.append(' * u16 opcode = fetch();')\n",
|
||||||
|
"L.append(' * CPU::Fn fn = InstrMap[opcode];')\n",
|
||||||
|
"L.append(' * if (fn) (cpu.*fn)();')\n",
|
||||||
|
"L.append(' */') # [CHANGE] Made it part of the CPU & avoided explicit size.\n",
|
||||||
|
"L.append(f'CPU::Fn CPU::instrMap[] = {{')\n",
|
||||||
|
"\n",
|
||||||
|
"for opc in range(TABLE_SIZE):\n",
|
||||||
|
" mnem = opcode_to_mnem.get(opc)\n",
|
||||||
|
" if mnem:\n",
|
||||||
|
" name = opcode_to_name[opc]\n",
|
||||||
|
" L.append(f' &CPU::{mnem + \",\":<28s}// 0x{opc:03X} — {name}')\n",
|
||||||
|
" else:\n",
|
||||||
|
" tag = ''\n",
|
||||||
|
" if opc in reserved_opcodes:\n",
|
||||||
|
" tag = ' (reserved)'\n",
|
||||||
|
" L.append(f' {\"nullptr,\":<28s}// 0x{opc:03X}{tag}')\n",
|
||||||
|
"\n",
|
||||||
|
"L.append('};')\n",
|
||||||
|
"L.append('')\n",
|
||||||
|
"L.append('')\n",
|
||||||
|
"\n",
|
||||||
|
"# ── Version 2: Switch ──────────────────────────────────────────────────────\n",
|
||||||
|
"L.append('// =============================================================')\n",
|
||||||
|
"L.append('// Version 2 — Switch dispatch')\n",
|
||||||
|
"L.append('// =============================================================')\n",
|
||||||
|
"L.append('')\n",
|
||||||
|
"L.append('/**')\n",
|
||||||
|
"L.append(' * Execute the instruction identified by @p opcode.')\n",
|
||||||
|
"L.append(' *')\n",
|
||||||
|
"L.append(' * This is functionally equivalent to the InstrMap[] table above')\n",
|
||||||
|
"L.append(' * but expressed as a switch so the compiler can choose the best')\n",
|
||||||
|
"L.append(' * lowering strategy (jump table, binary search, etc.).')\n",
|
||||||
|
"L.append(' *')\n",
|
||||||
|
"L.append(' * @param opcode 9-bit instruction opcode (0x000 - 0x1FF).')\n",
|
||||||
|
"L.append(' */')\n",
|
||||||
|
"L.append('void CPU::executeSwLk() {')\n",
|
||||||
|
"L.append(' switch (_opcode) {')\n",
|
||||||
|
"\n",
|
||||||
|
"last_group = None\n",
|
||||||
|
"for opc in sorted(opcode_to_mnem.keys()):\n",
|
||||||
|
" mnem = opcode_to_mnem[opc]\n",
|
||||||
|
" group = opcode_to_group[opc]\n",
|
||||||
|
" if group != last_group:\n",
|
||||||
|
" L.append('')\n",
|
||||||
|
" L.append(f' // ── {group} ' + '─' * max(1, 44 - len(group)))\n",
|
||||||
|
" last_group = group\n",
|
||||||
|
" L.append(f' case 0x{opc:03X}: {mnem}(); break;')\n",
|
||||||
|
"\n",
|
||||||
|
"L.append('')\n",
|
||||||
|
"L.append(' default:')\n",
|
||||||
|
"L.append(' break;')\n",
|
||||||
|
"L.append(' }')\n",
|
||||||
|
"L.append('}')\n",
|
||||||
|
"L.append('')\n",
|
||||||
|
"L.append('} // namespace spider')\n",
|
||||||
|
"L.append('')\n",
|
||||||
|
"\n",
|
||||||
|
"INSTRMAP_SRC = '\\n'.join(L)\n",
|
||||||
|
"\n",
|
||||||
|
"# ── Write to file ───────────────────────────────────────────────────────────\n",
|
||||||
|
"# [CHANGE] Write this in the instructions folder to avoid CPU file bloat\n",
|
||||||
|
"INSTRMAP_PATH = f'{SRC_ROOT}/spider/runtime/instr/InstrMap.cpp'\n",
|
||||||
|
"\n",
|
||||||
|
"with open(INSTRMAP_PATH, 'wb') as f:\n",
|
||||||
|
" f.write(INSTRMAP_SRC.encode('utf-8'))\n",
|
||||||
|
"\n",
|
||||||
|
"# Verify LF-only\n",
|
||||||
|
"with open(INSTRMAP_PATH, 'rb') as f:\n",
|
||||||
|
" raw_bytes = f.read()\n",
|
||||||
|
"assert b'\\r' not in raw_bytes, 'CRLF detected in InstrMap.cpp!'\n",
|
||||||
|
"\n",
|
||||||
|
"array_count = INSTRMAP_SRC.count('&CPU::')\n",
|
||||||
|
"switch_count = INSTRMAP_SRC.count('case 0x')\n",
|
||||||
|
"\n",
|
||||||
|
"print(f'InstrMap.cpp written to: {INSTRMAP_PATH}')\n",
|
||||||
|
"print(f' Size : {len(raw_bytes):,} bytes')\n",
|
||||||
|
"print(f' Array entries : {TABLE_SIZE} ({array_count} populated, {TABLE_SIZE - array_count} nullptr)')\n",
|
||||||
|
"print(f' Switch cases : {switch_count}')\n",
|
||||||
|
"print(f' Line endings : LF-only verified')\n"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
],
|
],
|
||||||
"C_Cpp.default.includePath": [
|
"C_Cpp.default.includePath": [
|
||||||
"./src"
|
"./src"
|
||||||
]
|
],
|
||||||
|
"terminal.integrated.defaultProfile.windows": "MSYS2 UCRT"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
#include "SpiderRuntime.hpp"
|
#include "SpiderRuntime.hpp"
|
||||||
|
|
||||||
|
#include <spider/runtime/debug/LiveDebug.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace spider {
|
namespace spider {
|
||||||
|
|
||||||
|
const u32 RUNTIME_VERSION_NO = 0x00000000; // v0.1
|
||||||
|
const std::string RUNTIME_VERSION = "alpha v0.1";
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
std::cout << "Hello World" << std::endl;
|
spider::liveDebugMain();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
namespace spider {
|
namespace spider {
|
||||||
|
|
||||||
|
extern const u32 RUNTIME_VERSION_NO;
|
||||||
|
extern const std::string RUNTIME_VERSION;
|
||||||
|
|
||||||
class Runtime;
|
class Runtime;
|
||||||
class CPU;
|
class CPU;
|
||||||
class RAM;
|
class RAM;
|
||||||
|
|||||||
@@ -4,17 +4,33 @@ namespace spider {
|
|||||||
|
|
||||||
// Constructors & Destructors //
|
// Constructors & Destructors //
|
||||||
|
|
||||||
Runtime::Runtime() : ram(0) {}
|
Runtime::Runtime() : Runtime(0) {}
|
||||||
|
|
||||||
Runtime::Runtime(u64 ramSize) : ram(ramSize) {}
|
Runtime::Runtime(u64 ramSize) : ram(ramSize), reel(nullptr) {
|
||||||
|
cpu.hookRAM(&ram);
|
||||||
|
}
|
||||||
|
|
||||||
Runtime::~Runtime() {}
|
Runtime::~Runtime() {
|
||||||
|
delete reel;
|
||||||
|
}
|
||||||
|
|
||||||
// Stepping/Running the Machine //
|
// Stepping/Running the Machine //
|
||||||
|
|
||||||
void Runtime::step() {}
|
void Runtime::step() {
|
||||||
|
cpu.fetchInstr();
|
||||||
|
// TODO: Call instruction
|
||||||
|
}
|
||||||
|
|
||||||
void Runtime::step(u64 n) {}
|
void Runtime::step(u64 n) {
|
||||||
|
while(n >= 4) {
|
||||||
|
step();
|
||||||
|
step();
|
||||||
|
step();
|
||||||
|
step();
|
||||||
|
n -= 4;
|
||||||
|
}
|
||||||
|
while (n--) step();
|
||||||
|
}
|
||||||
|
|
||||||
void Runtime::run() {}
|
void Runtime::run() {}
|
||||||
|
|
||||||
@@ -26,4 +42,12 @@ namespace spider {
|
|||||||
ram.resize(length);
|
ram.resize(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-owning reel setup.
|
||||||
|
*/
|
||||||
|
void Runtime::hookReel(InstrReel* reel, bool own) {
|
||||||
|
cpu.hookInstrReel(reel);
|
||||||
|
if(own) this->reel = reel;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <spider/runtime/cpu/CPU.hpp>
|
#include <spider/runtime/cpu/CPU.hpp>
|
||||||
|
|
||||||
#include <spider/runtime/memory/RAM.hpp>
|
#include <spider/runtime/memory/RAM.hpp>
|
||||||
|
|
||||||
|
#include <spider/runtime/reel/InstrReel.hpp>
|
||||||
|
|
||||||
namespace spider {
|
namespace spider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -10,10 +13,11 @@ namespace spider {
|
|||||||
* This is where the Spider VM (Runtime) lives
|
* This is where the Spider VM (Runtime) lives
|
||||||
*/
|
*/
|
||||||
class Runtime {
|
class Runtime {
|
||||||
private:
|
public:
|
||||||
|
|
||||||
CPU cpu;
|
CPU cpu;
|
||||||
RAM ram;
|
RAM ram;
|
||||||
|
InstrReel* reel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -68,6 +72,11 @@ namespace spider {
|
|||||||
*/
|
*/
|
||||||
void resizeRAM(u64 length);
|
void resizeRAM(u64 length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-owning reel setup.
|
||||||
|
*/
|
||||||
|
void hookReel(InstrReel* reel, bool own = false);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace spider {
|
namespace spider {
|
||||||
|
|
||||||
|
// Absolute Types
|
||||||
using u8 = std::uint8_t;
|
using u8 = std::uint8_t;
|
||||||
using u16 = std::uint16_t;
|
using u16 = std::uint16_t;
|
||||||
using u32 = std::uint32_t;
|
using u32 = std::uint32_t;
|
||||||
@@ -25,6 +27,9 @@ namespace spider {
|
|||||||
static_assert(sizeof(f32) == 4, "The f32 type must be exactly 4 bytes.");
|
static_assert(sizeof(f32) == 4, "The f32 type must be exactly 4 bytes.");
|
||||||
static_assert(sizeof(f64) == 8, "The f64 type must be exactly 8 bytes.");
|
static_assert(sizeof(f64) == 8, "The f64 type must be exactly 8 bytes.");
|
||||||
|
|
||||||
|
// Utility types
|
||||||
|
using isize = std::size_t;
|
||||||
|
|
||||||
// Utility imports
|
// Utility imports
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::deque;
|
using std::deque;
|
||||||
|
|||||||
@@ -0,0 +1,214 @@
|
|||||||
|
#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 {
|
||||||
|
|
||||||
|
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{},
|
||||||
|
ALU0{}, ALU1{},
|
||||||
|
_dst(nullptr), _src(nullptr),
|
||||||
|
_opcode(0), _addrm(0), _size(0),
|
||||||
|
_store(0), _post(&CPU::imp),
|
||||||
|
_ram(nullptr), _reel(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CPU::~CPU() {}
|
||||||
|
|
||||||
|
// Setup & Configuration //
|
||||||
|
|
||||||
|
void CPU::hookRAM(RAM* ram) {
|
||||||
|
this->_ram = ram;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::hookInstrReel(InstrReel* reel) {
|
||||||
|
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);
|
||||||
|
_opcode = (i >> 7) & 0x1FF;
|
||||||
|
_addrm = (i >> 2) & 0x1F;
|
||||||
|
_size = i & 0x3;
|
||||||
|
RI += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::fetchOperDst() {
|
||||||
|
// Move the operand ptrs
|
||||||
|
_alu = &ALU0;
|
||||||
|
_opers[1] = _opers[0];
|
||||||
|
|
||||||
|
// call specific addressing mode
|
||||||
|
(this->*(CPU::addrModes[_addrm]))();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::fetchOperSrc() {
|
||||||
|
// set ALU
|
||||||
|
_alu = &ALU1;
|
||||||
|
|
||||||
|
// call specific addressing mode
|
||||||
|
(this->*(CPU::addrModes[_addrm]))();
|
||||||
|
|
||||||
|
// modify the _addrm register
|
||||||
|
_addrm >>= 3;
|
||||||
|
_addrm++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::execute() {
|
||||||
|
(this->*(CPU::addrModes[_opcode]))();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Addressing Modes //
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implied Addressing Mode
|
||||||
|
*/
|
||||||
|
void CPU::imp() {
|
||||||
|
// Nothing //
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immediate Addressing Mode
|
||||||
|
*/
|
||||||
|
void CPU::imm() {
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00:
|
||||||
|
_alu->_u8 = _reel->readU8(RI);
|
||||||
|
break;
|
||||||
|
case 0b01:
|
||||||
|
_alu->_u16 = _reel->readU16(RI);
|
||||||
|
break;
|
||||||
|
case 0b10:
|
||||||
|
_alu->_u32 = _reel->readU32(RI);
|
||||||
|
break;
|
||||||
|
case 0b11:
|
||||||
|
_alu->_u64 = _reel->readU64(RI);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_opers[0] = _alu;
|
||||||
|
_post = &CPU::imp;
|
||||||
|
RI += 1 << _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute Addressing Mode
|
||||||
|
*/
|
||||||
|
void CPU::abs() { // TODO cache ptr size
|
||||||
|
u8 dat_size = 1 << _size;
|
||||||
|
u8 ptr_size = 1 << getFlag(CPU::FLAG_MEMORY_MODE);
|
||||||
|
u64 ptr = 0;
|
||||||
|
|
||||||
|
if(ptr_size + dat_size > _ram->size()) return; // TODO: avoid overflow
|
||||||
|
|
||||||
|
switch(ptr_size) {
|
||||||
|
case 1:
|
||||||
|
ptr = _reel->readU8(RI);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ptr = _reel->readU16(RI);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
ptr = _reel->readU32(RI);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
ptr = _reel->readU64(RI);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00:
|
||||||
|
spider::loadLE(&_alu->_u8, &(*_ram)[ptr]);
|
||||||
|
break;
|
||||||
|
case 0b01:
|
||||||
|
spider::loadLE(&_alu->_u16, &(*_ram)[ptr]);
|
||||||
|
break;
|
||||||
|
case 0b10:
|
||||||
|
spider::loadLE(&_alu->_u32, &(*_ram)[ptr]);
|
||||||
|
break;
|
||||||
|
case 0b11:
|
||||||
|
spider::loadLE(&_alu->_u64, &(*_ram)[ptr]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RI += dat_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register Addressing Mode
|
||||||
|
*/
|
||||||
|
void CPU::reg() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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() {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,15 +1,36 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <spider/SpiderRuntime.hpp>
|
||||||
#include <spider/runtime/cpu/Register.hpp>
|
#include <spider/runtime/cpu/Register.hpp>
|
||||||
|
|
||||||
namespace spider {
|
namespace spider {
|
||||||
|
|
||||||
class CPU {
|
class CPU {
|
||||||
|
public: // Helper types
|
||||||
|
using Fn = void (CPU::*)();
|
||||||
|
|
||||||
|
public: // Flag Register Constants //
|
||||||
|
static constexpr const u64 FLAG_ENABLE = 0b0000000000000000000000000000000000000000000000000000000000000001;
|
||||||
|
static constexpr const u64 FLAG_INTERRUPT_SIGNAL = 0b0000000000000000000000000000000000000000000000000000000000000010;
|
||||||
|
static constexpr const u64 FLAG_INTERRUPT_REQUEST = 0b0000000000000000000000000000000000000000000000000000000000000100;
|
||||||
|
static constexpr const u64 FLAG_EXCEPTION = 0b0000000000000000000000000000000000000000000000000000000000001000;
|
||||||
|
static constexpr const u64 FLAG_MEMORY_MODE = 0b0000000000000000000000000000000000000000000000000000000000110000;
|
||||||
|
|
||||||
|
public: // Map of addressing modes & Instructions
|
||||||
|
|
||||||
|
static CPU::Fn addrModes[];
|
||||||
|
static CPU::Fn instrMap[];
|
||||||
|
|
||||||
public: // General Purpose Registers
|
public: // General Purpose Registers
|
||||||
|
union {
|
||||||
|
register_t GPR[16];
|
||||||
|
struct {
|
||||||
register_t RA, RB, RC, RD,
|
register_t 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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
public: // System Registers
|
public: // System Registers
|
||||||
u64 RF;
|
u64 RF;
|
||||||
@@ -31,6 +52,55 @@ namespace spider {
|
|||||||
*/
|
*/
|
||||||
register_t ALU0, ALU1;
|
register_t ALU0, ALU1;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
register_t* _dst;
|
||||||
|
register_t* _src;
|
||||||
|
register_t* _alu;
|
||||||
|
};
|
||||||
|
register_t* _opers[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Holds the current instruction opcode
|
||||||
|
u16 _opcode : 9;
|
||||||
|
|
||||||
|
// Holds the current addressing modes,
|
||||||
|
// before they were used
|
||||||
|
u8 _addrm : 5;
|
||||||
|
|
||||||
|
// Holds the current instruction size.
|
||||||
|
u8 _size : 2;
|
||||||
|
|
||||||
|
// On _post that are not no-ops, it must
|
||||||
|
// write back DST to this memory location.
|
||||||
|
u64 _store;
|
||||||
|
|
||||||
|
// Post execution callback
|
||||||
|
CPU::Fn _post;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to the current RAM hooked into
|
||||||
|
* the CPU.
|
||||||
|
*
|
||||||
|
* It is unproved whether having the RAM directly
|
||||||
|
* into the CPU is better than not, or whether a
|
||||||
|
* virtual BUS is better.
|
||||||
|
*
|
||||||
|
* Alas, this way we can have a CPU state switch
|
||||||
|
* between memory and instruction banks.
|
||||||
|
*/
|
||||||
|
RAM* _ram;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to the current Instruction Reel
|
||||||
|
* hooked into the CPU.
|
||||||
|
*
|
||||||
|
* Ditto as RAM.
|
||||||
|
*/
|
||||||
|
InstrReel* _reel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CPU();
|
CPU();
|
||||||
@@ -47,6 +117,122 @@ namespace spider {
|
|||||||
|
|
||||||
CPU& operator=(CPU&& other) noexcept = default;
|
CPU& operator=(CPU&& other) noexcept = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void hookRAM(RAM* ram);
|
||||||
|
|
||||||
|
void hookInstrReel(InstrReel* reel);
|
||||||
|
|
||||||
|
constexpr u64 getFlag(u64 mask);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the instruction from the
|
||||||
|
* reel, and advances IR by two.
|
||||||
|
*/
|
||||||
|
void fetchInstr();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the destination operand,
|
||||||
|
* by calling the appropriate addressing
|
||||||
|
* mode.
|
||||||
|
*
|
||||||
|
* Will read the bottom 3 bits.
|
||||||
|
* For instructions with two operands,
|
||||||
|
* call Src first.
|
||||||
|
*
|
||||||
|
* The internal variable _addrm
|
||||||
|
* will not be modified. It will
|
||||||
|
* be important when writing
|
||||||
|
* back the result.
|
||||||
|
*/
|
||||||
|
void fetchOperDst();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the source operand.
|
||||||
|
*
|
||||||
|
* For use in two operand instructions.
|
||||||
|
*
|
||||||
|
* Will read the bottom 3 bits. It will
|
||||||
|
* then shift the _addrm 3 spaces
|
||||||
|
* to ensure it aligns with the DST
|
||||||
|
* next.
|
||||||
|
*
|
||||||
|
* Additionally, it will add 1 to _addrm
|
||||||
|
* to account with
|
||||||
|
*/
|
||||||
|
void fetchOperSrc();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes an opcode, by means of directly
|
||||||
|
* accessing the instruction map and
|
||||||
|
* calling that function pointer.
|
||||||
|
*/
|
||||||
|
void execute();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes an opcode, by means of using
|
||||||
|
* a large switch statement. Only suitable
|
||||||
|
* for environments where the instruction
|
||||||
|
* map is not possible.
|
||||||
|
*
|
||||||
|
* This has yet to be proved!!!
|
||||||
|
*/
|
||||||
|
void executeSwLk();
|
||||||
|
|
||||||
|
public: // Addressing Modes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implied Addressing Mode
|
||||||
|
*/
|
||||||
|
void imp(); // Kept as it is a no-op
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immediate Addressing Mode
|
||||||
|
*/
|
||||||
|
void imm();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute Addressing Mode
|
||||||
|
*/
|
||||||
|
void abs();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register Addressing Mode
|
||||||
|
*/
|
||||||
|
void reg();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indrect Addressing Mode
|
||||||
|
*/
|
||||||
|
void ind();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer Addressing Mode
|
||||||
|
*/
|
||||||
|
void ptr();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indexed Addressing Mode
|
||||||
|
*/
|
||||||
|
void idx();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scaled Addressing Mode
|
||||||
|
*/
|
||||||
|
void sca();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displaced Addressing Mode
|
||||||
|
*/
|
||||||
|
void dis();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post-Write Action
|
||||||
|
*/
|
||||||
|
void psw();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// <pygen-target name=cpu-instructions> //
|
// <pygen-target name=cpu-instructions> //
|
||||||
@@ -66,327 +252,327 @@ namespace spider {
|
|||||||
void MMODE();
|
void MMODE();
|
||||||
|
|
||||||
// [System] 0x003 — INT: Interrupt
|
// [System] 0x003 — INT: Interrupt
|
||||||
// Params: 1 | AddrMask1: 1F AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: 1F AddrMask2: 00 | TypeMask: 08
|
||||||
// Operation: Performs system interrupt no. (Dst) (See table)
|
// Operation: Performs system interrupt no. (Dst) (See table)
|
||||||
void INT();
|
void INT();
|
||||||
|
|
||||||
// [System] 0x004 — LRV: Load Interrupt Vector Register
|
// [System] 0x004 — LRV: Load Interrupt Vector Register
|
||||||
// Params: 1 | AddrMask1: 1F AddrMask2: 00 | TypeMask: 0C
|
// Params: 1 | AddrMask1: 1F AddrMask2: 00 | TypeMask: 08
|
||||||
// Operation: Dst -> RV
|
// Operation: Dst -> RV
|
||||||
void LRV();
|
void LRV();
|
||||||
|
|
||||||
// [System] 0x005 — FSR: Fetch System Register
|
// [System] 0x005 — FSR: Fetch System Register
|
||||||
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 08
|
||||||
// Operation: System Register at Dst -> Dst
|
// Operation: System Register at Dst -> Dst
|
||||||
void FSR();
|
void FSR();
|
||||||
|
|
||||||
// [System] 0x006 — FIR: Fetch Instruction Register
|
// [System] 0x006 — FIR: Fetch Instruction Register
|
||||||
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 08
|
||||||
// Operation: Instruction Register -> Dst
|
// Operation: Instruction Register -> Dst
|
||||||
void FIR();
|
void FIR();
|
||||||
|
|
||||||
// [System] 0x007 — FZR: Fetch Stack Base Register
|
// [System] 0x007 — FZR: Fetch Stack Base Register
|
||||||
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 08
|
||||||
// Operation: Stack Base Register -> Dst
|
// Operation: Stack Base Register -> Dst
|
||||||
void FZR();
|
void FZR();
|
||||||
|
|
||||||
// [System] 0x008 — LSR: Load System Register
|
// [System] 0x008 — LSR: Load System Register
|
||||||
// Params: 2 | AddrMask1: 1E AddrMask2: 1F | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: 1F | TypeMask: 08
|
||||||
// Operation: Src -> System Register at Dst
|
// Operation: Src -> System Register at Dst
|
||||||
void LSR();
|
void LSR();
|
||||||
|
|
||||||
// [System] 0x009 — FVR: Fetch Interrupt Vector Register
|
// [System] 0x009 — FVR: Fetch Interrupt Vector Register
|
||||||
// Params: 1 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: 04 AddrMask2: 00 | TypeMask: 08
|
||||||
// Operation: Interrupt Vector Register -> Dst
|
// Operation: Interrupt Vector Register -> Dst
|
||||||
void FVR();
|
void FVR();
|
||||||
|
|
||||||
// [Memory] 0x00A — MOV: Moves values
|
// [Memory] 0x00A — MOV: Moves values
|
||||||
// Params: 2 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Src -> Dst
|
// Operation: Src -> Dst
|
||||||
void MOV();
|
void MOV();
|
||||||
|
|
||||||
// [Memory] 0x00B — MOR: Moves registers
|
// [Memory] 0x00B — MOR: Moves registers
|
||||||
// Params: 2 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 04 AddrMask2: 04 | TypeMask: 08
|
||||||
// Operation: R Scr -> R Dst
|
// Operation: R Scr -> R Dst
|
||||||
void MOR();
|
void MOR();
|
||||||
|
|
||||||
// [Memory] 0x00C — AMOV: Array Move, uses X and Y as ptrs, A as amount
|
// [Memory] 0x00C — AMOV: Array Move, uses X and Y as ptrs, A as amount
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 08
|
||||||
// Operation: Array from X to Y, by A amount
|
// Operation: Array from X to Y, by A amount
|
||||||
void AMOV();
|
void AMOV();
|
||||||
|
|
||||||
// [Memory] 0x00D — SWP: Swap registers
|
// [Memory] 0x00D — SWP: Swap registers
|
||||||
// Params: 2 | AddrMask1: 04 AddrMask2: 04 | TypeMask: 00
|
// Params: 2 | AddrMask1: 04 AddrMask2: 04 | TypeMask: 08
|
||||||
// Operation: Src <-> Dst
|
// Operation: Src <-> Dst
|
||||||
void SWP();
|
void SWP();
|
||||||
|
|
||||||
// [Memory] 0x00E — AHM: Ask Host for Memory
|
// [Memory] 0x00E — AHM: Ask Host for Memory
|
||||||
// Params: 1 | AddrMask1: 04 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: 04 AddrMask2: 00 | TypeMask: 08
|
||||||
// Operation: Asks the host for a specific size of memory. Responds with 0 or 1
|
// Operation: Asks the host for a specific size of memory. Responds with 0 or 1
|
||||||
void AHM();
|
void AHM();
|
||||||
|
|
||||||
// [Integer] 0x010 — COM: One's complement
|
// [Integer] 0x010 — COM: One's complement
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: ~ Dst -> Dst
|
// Operation: ~ Dst -> Dst
|
||||||
void COM();
|
void COM();
|
||||||
|
|
||||||
// [Integer] 0x011 — NEG: Two's complement
|
// [Integer] 0x011 — NEG: Two's complement
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: - Dst -> Dst
|
// Operation: - Dst -> Dst
|
||||||
void NEG();
|
void NEG();
|
||||||
|
|
||||||
// [Integer] 0x012 — EXS: Extend Sign
|
// [Integer] 0x012 — EXS: Extend Sign
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Last bit is copied and expanded for the next int size
|
// Operation: Last bit is copied and expanded for the next int size
|
||||||
void EXS();
|
void EXS();
|
||||||
|
|
||||||
// [Integer] 0x013 — INC: Increment
|
// [Integer] 0x013 — INC: Increment
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Dst + 1 -> Dst
|
// Operation: Dst + 1 -> Dst
|
||||||
void INC();
|
void INC();
|
||||||
|
|
||||||
// [Integer] 0x014 — DEC: Decrement
|
// [Integer] 0x014 — DEC: Decrement
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Dst - 1 -> Dst
|
// Operation: Dst - 1 -> Dst
|
||||||
void DEC();
|
void DEC();
|
||||||
|
|
||||||
// [Integer] 0x015 — ADD: Addition
|
// [Integer] 0x015 — ADD: Addition
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst + Src -> Dst
|
// Operation: Dst + Src -> Dst
|
||||||
void ADD();
|
void ADD();
|
||||||
|
|
||||||
// [Integer] 0x016 — SUB: Subtraction
|
// [Integer] 0x016 — SUB: Subtraction
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst - Src-> Dst
|
// Operation: Dst - Src-> Dst
|
||||||
void SUB();
|
void SUB();
|
||||||
|
|
||||||
// [Integer] 0x017 — MUL: Multiplication
|
// [Integer] 0x017 — MUL: Multiplication
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Signed Dst * Src -> Dst
|
// Operation: Signed Dst * Src -> Dst
|
||||||
void MUL();
|
void MUL();
|
||||||
|
|
||||||
// [Integer] 0x018 — UMUL: Unsigned Multiplication
|
// [Integer] 0x018 — UMUL: Unsigned Multiplication
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Unsigned Dst * Src -> Dst
|
// Operation: Unsigned Dst * Src -> Dst
|
||||||
void UMUL();
|
void UMUL();
|
||||||
|
|
||||||
// [Integer] 0x019 — DIV: Division
|
// [Integer] 0x019 — DIV: Division
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Signed Dst / Src -> Dst
|
// Operation: Signed Dst / Src -> Dst
|
||||||
void DIV();
|
void DIV();
|
||||||
|
|
||||||
// [Integer] 0x01A — UDIV: Unsigned Division
|
// [Integer] 0x01A — UDIV: Unsigned Division
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Unsigned Dst / Src -> Dst
|
// Operation: Unsigned Dst / Src -> Dst
|
||||||
void UDIV();
|
void UDIV();
|
||||||
|
|
||||||
// [Integer] 0x01B — MOD: Modulus
|
// [Integer] 0x01B — MOD: Modulus
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Signed Dst % Src -> Dst
|
// Operation: Signed Dst % Src -> Dst
|
||||||
void MOD();
|
void MOD();
|
||||||
|
|
||||||
// [Integer] 0x01C — UMOD: Unsigned Modulus
|
// [Integer] 0x01C — UMOD: Unsigned Modulus
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Unsigned Dst % Src -> Dst
|
// Operation: Unsigned Dst % Src -> Dst
|
||||||
void UMOD();
|
void UMOD();
|
||||||
|
|
||||||
// [Integer] 0x01D — DMOD: Division and Modulus
|
// [Integer] 0x01D — DMOD: Division and Modulus
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Signed Dst / Src -> X, Dst % Src -> Y
|
// Operation: Signed Dst / Src -> X, Dst % Src -> Y
|
||||||
void DMOD();
|
void DMOD();
|
||||||
|
|
||||||
// [Integer] 0x01E — UDMD: Unsigned Division and Modulus
|
// [Integer] 0x01E — UDMD: Unsigned Division and Modulus
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Unsigned Dst / Src -> X, Dst % Src -> Y
|
// Operation: Unsigned Dst / Src -> X, Dst % Src -> Y
|
||||||
void UDMD();
|
void UDMD();
|
||||||
|
|
||||||
// [System] 0x01F — FBT: Test and update Flag Register (Integer) Bits
|
// [System] 0x01F — FBT: Test and update Flag Register (Integer) Bits
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Flags of Dst -
|
// Operation: Flags of Dst -
|
||||||
void FBT();
|
void FBT();
|
||||||
|
|
||||||
// [Bit Wise] 0x020 — STB: Set Bit
|
// [Bit Wise] 0x020 — STB: Set Bit
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Src# bit is set on Dst
|
// Operation: Src# bit is set on Dst
|
||||||
void STB();
|
void STB();
|
||||||
|
|
||||||
// [Bit Wise] 0x021 — CRB: Clear Bit
|
// [Bit Wise] 0x021 — CRB: Clear Bit
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Src# bit is cleared on Dst
|
// Operation: Src# bit is cleared on Dst
|
||||||
void CRB();
|
void CRB();
|
||||||
|
|
||||||
// [Bit Wise] 0x022 — TSB: Test Bit
|
// [Bit Wise] 0x022 — TSB: Test Bit
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Src# bit is tested against Dst, updates Equal Flag
|
// Operation: Src# bit is tested against Dst, updates Equal Flag
|
||||||
void TSB();
|
void TSB();
|
||||||
|
|
||||||
// [Bit Wise] 0x023 — BOOL: Sets the booleaness of a value
|
// [Bit Wise] 0x023 — BOOL: Sets the booleaness of a value
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Tests Dst != 0, updates Equal Flag
|
// Operation: Tests Dst != 0, updates Equal Flag
|
||||||
void BOOL();
|
void BOOL();
|
||||||
|
|
||||||
// [Bit Wise] 0x024 — NOT: Sets the inverse booleaness of a value (! BOOL)
|
// [Bit Wise] 0x024 — NOT: Sets the inverse booleaness of a value (! BOOL)
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Tests Dst == 0, updates Equal Flag
|
// Operation: Tests Dst == 0, updates Equal Flag
|
||||||
void NOT();
|
void NOT();
|
||||||
|
|
||||||
// [Bit Wise] 0x025 — AND: Boolean AND operation
|
// [Bit Wise] 0x025 — AND: Boolean AND operation
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst AND Src into Dst
|
// Operation: Dst AND Src into Dst
|
||||||
void AND();
|
void AND();
|
||||||
|
|
||||||
// [Bit Wise] 0x026 — OR: Boolean OR operation
|
// [Bit Wise] 0x026 — OR: Boolean OR operation
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst OR Src into Dst
|
// Operation: Dst OR Src into Dst
|
||||||
void OR();
|
void OR();
|
||||||
|
|
||||||
// [Bit Wise] 0x027 — XOR: Boolean XOR operation
|
// [Bit Wise] 0x027 — XOR: Boolean XOR operation
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst XOR Src into Dst
|
// Operation: Dst XOR Src into Dst
|
||||||
void XOR();
|
void XOR();
|
||||||
|
|
||||||
// [Bit Wise] 0x028 — SHL: Arithmetic Shift Left
|
// [Bit Wise] 0x028 — SHL: Arithmetic Shift Left
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst << Src into Dst
|
// Operation: Dst << Src into Dst
|
||||||
void SHL();
|
void SHL();
|
||||||
|
|
||||||
// [Bit Wise] 0x029 — SHR: Arithmetic Shift Right
|
// [Bit Wise] 0x029 — SHR: Arithmetic Shift Right
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst >> Src into Dst
|
// Operation: Dst >> Src into Dst
|
||||||
void SHR();
|
void SHR();
|
||||||
|
|
||||||
// [Bit Wise] 0x02A — SSR: Signed Shift Right
|
// [Bit Wise] 0x02A — SSR: Signed Shift Right
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst >>> Src into Dst
|
// Operation: Dst >>> Src into Dst
|
||||||
void SSR();
|
void SSR();
|
||||||
|
|
||||||
// [Bit Wise] 0x02B — ROL: Rotate Left
|
// [Bit Wise] 0x02B — ROL: Rotate Left
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst ROL Src into Dst
|
// Operation: Dst ROL Src into Dst
|
||||||
void ROL();
|
void ROL();
|
||||||
|
|
||||||
// [Bit Wise] 0x02C — ROR: Rotate Right
|
// [Bit Wise] 0x02C — ROR: Rotate Right
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst ROR Src into Dst
|
// Operation: Dst ROR Src into Dst
|
||||||
void ROR();
|
void ROR();
|
||||||
|
|
||||||
// [Bit Wise] 0x02D — CNT: Counts bits
|
// [Bit Wise] 0x02D — CNT: Counts bits
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: # of 1's into Dst
|
// Operation: # of 1's into Dst
|
||||||
void CNT();
|
void CNT();
|
||||||
|
|
||||||
// [Boolean] 0x030 — EQ: Equal
|
// [Boolean] 0x030 — EQ: Equal
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst == Src into Dst
|
// Operation: Dst == Src into Dst
|
||||||
void EQ();
|
void EQ();
|
||||||
|
|
||||||
// [Boolean] 0x031 — NE: Not Equal
|
// [Boolean] 0x031 — NE: Not Equal
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst != Src into Dst
|
// Operation: Dst != Src into Dst
|
||||||
void NE();
|
void NE();
|
||||||
|
|
||||||
// [Boolean] 0x032 — GT: Greater Than
|
// [Boolean] 0x032 — GT: Greater Than
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst > Src into Dst
|
// Operation: Dst > Src into Dst
|
||||||
void GT();
|
void GT();
|
||||||
|
|
||||||
// [Boolean] 0x033 — GE: Greater or Equal Than
|
// [Boolean] 0x033 — GE: Greater or Equal Than
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst >= Src into Dst
|
// Operation: Dst >= Src into Dst
|
||||||
void GE();
|
void GE();
|
||||||
|
|
||||||
// [Boolean] 0x034 — LT: Lower Than
|
// [Boolean] 0x034 — LT: Lower Than
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst < Src into Dst
|
// Operation: Dst < Src into Dst
|
||||||
void LT();
|
void LT();
|
||||||
|
|
||||||
// [Boolean] 0x035 — LE: Lower or Equal Than
|
// [Boolean] 0x035 — LE: Lower or Equal Than
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst <= Src into Dst
|
// Operation: Dst <= Src into Dst
|
||||||
void LE();
|
void LE();
|
||||||
|
|
||||||
// [Branch] 0x038 — JMP: Jump to absolute position
|
// [Branch] 0x038 — JMP: Jump to absolute position
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Dst -> Instruction Register
|
// Operation: Dst -> Instruction Register
|
||||||
void JMP();
|
void JMP();
|
||||||
|
|
||||||
// [Branch] 0x039 — JEQ: Jumps to position if EQ flag is set
|
// [Branch] 0x039 — JEQ: Jumps to position if EQ flag is set
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Dst -> Instruction Register IF Flags.EQ
|
// Operation: Dst -> Instruction Register IF Flags.EQ
|
||||||
void JEQ();
|
void JEQ();
|
||||||
|
|
||||||
// [Branch] 0x03A — JNE: Jumps to position if EQ flag is cleared
|
// [Branch] 0x03A — JNE: Jumps to position if EQ flag is cleared
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Dst -> Instruction Register IF NOT Flags.EQ
|
// Operation: Dst -> Instruction Register IF NOT Flags.EQ
|
||||||
void JNE();
|
void JNE();
|
||||||
|
|
||||||
// [Branch] 0x03B — JIF: Jumps if value provided is booleanly true
|
// [Branch] 0x03B — JIF: Jumps if value provided is booleanly true
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst -> Instruction Register IF Src
|
// Operation: Dst -> Instruction Register IF Src
|
||||||
void JIF();
|
void JIF();
|
||||||
|
|
||||||
// [Branch] 0x03C — JMR: Jump Relative
|
// [Branch] 0x03C — JMR: Jump Relative
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Dst + Instruction Register -> Instruction Register
|
// Operation: Dst + Instruction Register -> Instruction Register
|
||||||
void JMR();
|
void JMR();
|
||||||
|
|
||||||
// [Branch] 0x03D — JER: Jumps to relative position if EQ flag is set
|
// [Branch] 0x03D — JER: Jumps to relative position if EQ flag is set
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Dst + Instruction Register -> Instruction Register IF Flags.EQ
|
// Operation: Dst + Instruction Register -> Instruction Register IF Flags.EQ
|
||||||
void JER();
|
void JER();
|
||||||
|
|
||||||
// [Branch] 0x03E — JNR: Jumps to relative position if EQ flag is cleared
|
// [Branch] 0x03E — JNR: Jumps to relative position if EQ flag is cleared
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Dst + Instruction Register -> Instruction Register IF NOT Flags.EQ
|
// Operation: Dst + Instruction Register -> Instruction Register IF NOT Flags.EQ
|
||||||
void JNR();
|
void JNR();
|
||||||
|
|
||||||
// [Branch] 0x03F — JIR: Jumps to relative position if value provided is booleanly true
|
// [Branch] 0x03F — JIR: Jumps to relative position if value provided is booleanly true
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation: Dst + Instruction Register -> Instruction Register IF Src
|
// Operation: Dst + Instruction Register -> Instruction Register IF Src
|
||||||
void JIR();
|
void JIR();
|
||||||
|
|
||||||
// [System] 0x040 — SFB: Store (User) Flag Bit
|
// [System] 0x040 — SFB: Store (User) Flag Bit
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation:
|
// Operation:
|
||||||
void SFB();
|
void SFB();
|
||||||
|
|
||||||
// [System] 0x041 — LFB: Load (User) Flag Bit
|
// [System] 0x041 — LFB: Load (User) Flag Bit
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation:
|
// Operation:
|
||||||
void LFB();
|
void LFB();
|
||||||
|
|
||||||
// [Branch] 0x042 — JUF: Jump to absolute position, if user flag is true
|
// [Branch] 0x042 — JUF: Jump to absolute position, if user flag is true
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation:
|
// Operation:
|
||||||
void JUF();
|
void JUF();
|
||||||
|
|
||||||
// [Branch] 0x043 — JUR: Jump to relative position, if user flag is true
|
// [Branch] 0x043 — JUR: Jump to relative position, if user flag is true
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||||
// Operation:
|
// Operation:
|
||||||
void JUR();
|
void JUR();
|
||||||
|
|
||||||
// [Memory] 0x044 — PUSH: Push to stack
|
// [Memory] 0x044 — PUSH: Push to stack
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Dst -> pushed into stack
|
// Operation: Dst -> pushed into stack
|
||||||
void PUSH();
|
void PUSH();
|
||||||
|
|
||||||
// [Memory] 0x045 — POP: Pop from stack
|
// [Memory] 0x045 — POP: Pop from stack
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: popped from stack -> Dst
|
// Operation: popped from stack -> Dst
|
||||||
void POP();
|
void POP();
|
||||||
|
|
||||||
// [Memory] 0x046 — ALLOC: Allocate to heap
|
// [Memory] 0x046 — ALLOC: Allocate to heap
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Dst -> heap ptr of size Dst
|
// Operation: Dst -> heap ptr of size Dst
|
||||||
void ALLOC();
|
void ALLOC();
|
||||||
|
|
||||||
// [Memory] 0x047 — HFREE: Delete from heap
|
// [Memory] 0x047 — HFREE: Delete from heap
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Frees heap ptr in Dst
|
// Operation: Frees heap ptr in Dst
|
||||||
void HFREE();
|
void HFREE();
|
||||||
|
|
||||||
// [Branch] 0x04A — CALL: Call function at instruction index
|
// [Branch] 0x04A — CALL: Call function at instruction index
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: Performs a function call, step XX
|
// Operation: Performs a function call, step XX
|
||||||
void CALL();
|
void CALL();
|
||||||
|
|
||||||
@@ -396,207 +582,207 @@ namespace spider {
|
|||||||
void RET();
|
void RET();
|
||||||
|
|
||||||
// [System] 0x04C — EDI: Enable/Disable External Interrupts
|
// [System] 0x04C — EDI: Enable/Disable External Interrupts
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: bool( Dst ) -> Enable External Interrupts Bit
|
// Operation: bool( Dst ) -> Enable External Interrupts Bit
|
||||||
void EDI();
|
void EDI();
|
||||||
|
|
||||||
// [System] 0x04D — SHSS: Set Hotswap Signal Bit
|
// [System] 0x04D — SHSS: Set Hotswap Signal Bit
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||||
// Operation: bool( Dst ) -> Hot Swap Signal Bit
|
// Operation: bool( Dst ) -> Hot Swap Signal Bit
|
||||||
void SHSS();
|
void SHSS();
|
||||||
|
|
||||||
// [Floating Point] 0x050 — FLI: Float Load Immediate
|
// [Floating Point] 0x050 — FLI: Float Load Immediate
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation:
|
// Operation:
|
||||||
void FLI();
|
void FLI();
|
||||||
|
|
||||||
// [Floating Point] 0x051 — FNEG: Float negate
|
// [Floating Point] 0x051 — FNEG: Float negate
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation: - Dst -> Dst
|
// Operation: - Dst -> Dst
|
||||||
void FNEG();
|
void FNEG();
|
||||||
|
|
||||||
// [Floating Point] 0x052 — FADD: Float add
|
// [Floating Point] 0x052 — FADD: Float add
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: Dst + Src -> Dst
|
// Operation: Dst + Src -> Dst
|
||||||
void FADD();
|
void FADD();
|
||||||
|
|
||||||
// [Floating Point] 0x053 — FSUB: Float subtract
|
// [Floating Point] 0x053 — FSUB: Float subtract
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: Dst - Src-> Dst
|
// Operation: Dst - Src-> Dst
|
||||||
void FSUB();
|
void FSUB();
|
||||||
|
|
||||||
// [Floating Point] 0x054 — FMUL: Float multiplication
|
// [Floating Point] 0x054 — FMUL: Float multiplication
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: Dst * Src -> Dst
|
// Operation: Dst * Src -> Dst
|
||||||
void FMUL();
|
void FMUL();
|
||||||
|
|
||||||
// [Floating Point] 0x055 — FDIV: Float division
|
// [Floating Point] 0x055 — FDIV: Float division
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: Dst / Src -> Dst
|
// Operation: Dst / Src -> Dst
|
||||||
void FDIV();
|
void FDIV();
|
||||||
|
|
||||||
// [Floating Point] 0x056 — FMOD: Float modulus
|
// [Floating Point] 0x056 — FMOD: Float modulus
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: Dst % Src -> Dst
|
// Operation: Dst % Src -> Dst
|
||||||
void FMOD();
|
void FMOD();
|
||||||
|
|
||||||
// [Floating Point] 0x057 — FDMOD: Float division and modulus
|
// [Floating Point] 0x057 — FDMOD: Float division and modulus
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: Dst / Src -> X, Dst % Src -> Y
|
// Operation: Dst / Src -> X, Dst % Src -> Y
|
||||||
void FDMOD();
|
void FDMOD();
|
||||||
|
|
||||||
// [Floating Point] 0x058 — FEPS: Sets the float epsilon value, for comparison
|
// [Floating Point] 0x058 — FEPS: Sets the float epsilon value, for comparison
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation: Dst -> Epsilon Register
|
// Operation: Dst -> Epsilon Register
|
||||||
void FEPS();
|
void FEPS();
|
||||||
|
|
||||||
// [Floating Point] 0x059 — FEEP: Float Enable/Disable Epsilon
|
// [Floating Point] 0x059 — FEEP: Float Enable/Disable Epsilon
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation: bool( Dst ) -> Epsilon Enable Bit
|
// Operation: bool( Dst ) -> Epsilon Enable Bit
|
||||||
void FEEP();
|
void FEEP();
|
||||||
|
|
||||||
// [Boolean] 0x05A — FEQ: Float Equal
|
// [Boolean] 0x05A — FEQ: Float Equal
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: Dst == Src into Dst
|
// Operation: Dst == Src into Dst
|
||||||
void FEQ();
|
void FEQ();
|
||||||
|
|
||||||
// [Boolean] 0x05B — FNE: Float Not Equal
|
// [Boolean] 0x05B — FNE: Float Not Equal
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: Dst != Src into Dst
|
// Operation: Dst != Src into Dst
|
||||||
void FNE();
|
void FNE();
|
||||||
|
|
||||||
// [Boolean] 0x05C — FGT: Float Greater Than
|
// [Boolean] 0x05C — FGT: Float Greater Than
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: Dst > Src into Dst
|
// Operation: Dst > Src into Dst
|
||||||
void FGT();
|
void FGT();
|
||||||
|
|
||||||
// [Boolean] 0x05D — FGE: Float Greater or Equal Than
|
// [Boolean] 0x05D — FGE: Float Greater or Equal Than
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: Dst >= Src into Dst
|
// Operation: Dst >= Src into Dst
|
||||||
void FGE();
|
void FGE();
|
||||||
|
|
||||||
// [Boolean] 0x05E — FLT: Float Lower Than
|
// [Boolean] 0x05E — FLT: Float Lower Than
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: Dst < Src into Dst
|
// Operation: Dst < Src into Dst
|
||||||
void FLT();
|
void FLT();
|
||||||
|
|
||||||
// [Boolean] 0x05F — FLE: Float Lower or Equal Than
|
// [Boolean] 0x05F — FLE: Float Lower or Equal Than
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: Dst <= Src into Dst
|
// Operation: Dst <= Src into Dst
|
||||||
void FLE();
|
void FLE();
|
||||||
|
|
||||||
// [Casts] 0x060 — F2D: F32 (Float) to F64 (Double)
|
// [Casts] 0x060 — F2D: F32 (Float) to F64 (Double)
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||||
// Operation: (cast) Dst -> Dst
|
// Operation: (cast) Dst -> Dst
|
||||||
void F2D();
|
void F2D();
|
||||||
|
|
||||||
// [Casts] 0x061 — D2F: F64 (Double) to F32 (Float)
|
// [Casts] 0x061 — D2F: F64 (Double) to F32 (Float)
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||||
// Operation: (cast) Dst -> Dst
|
// Operation: (cast) Dst -> Dst
|
||||||
void D2F();
|
void D2F();
|
||||||
|
|
||||||
// [Casts] 0x062 — I2F: I32 (Integer) to F32 (Float)
|
// [Casts] 0x062 — I2F: I32 (Integer) to F32 (Float)
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||||
// Operation: (cast) Dst -> Dst
|
// Operation: (cast) Dst -> Dst
|
||||||
void I2F();
|
void I2F();
|
||||||
|
|
||||||
// [Casts] 0x063 — I2D: I32 (Integer) to F64 (Double)
|
// [Casts] 0x063 — I2D: I32 (Integer) to F64 (Double)
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||||
// Operation: (cast) Dst -> Dst
|
// Operation: (cast) Dst -> Dst
|
||||||
void I2D();
|
void I2D();
|
||||||
|
|
||||||
// [Casts] 0x064 — L2F: I64 (Long) to F32 (Float)
|
// [Casts] 0x064 — L2F: I64 (Long) to F32 (Float)
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||||
// Operation: (cast) Dst -> Dst
|
// Operation: (cast) Dst -> Dst
|
||||||
void L2F();
|
void L2F();
|
||||||
|
|
||||||
// [Casts] 0x065 — L2D: I64 (Long) to F64 (Double)
|
// [Casts] 0x065 — L2D: I64 (Long) to F64 (Double)
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||||
// Operation: (cast) Dst -> Dst
|
// Operation: (cast) Dst -> Dst
|
||||||
void L2D();
|
void L2D();
|
||||||
|
|
||||||
// [Casts] 0x066 — F2I: F32 (Float) to I32 (Integer)
|
// [Casts] 0x066 — F2I: F32 (Float) to I32 (Integer)
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||||
// Operation: (cast) Dst -> Dst
|
// Operation: (cast) Dst -> Dst
|
||||||
void F2I();
|
void F2I();
|
||||||
|
|
||||||
// [Casts] 0x067 — F2L: F32 (Float) to I64 (Long)
|
// [Casts] 0x067 — F2L: F32 (Float) to I64 (Long)
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||||
// Operation: (cast) Dst -> Dst
|
// Operation: (cast) Dst -> Dst
|
||||||
void F2L();
|
void F2L();
|
||||||
|
|
||||||
// [Casts] 0x068 — D2I: F64 (Double) to I32 (Integer)
|
// [Casts] 0x068 — D2I: F64 (Double) to I32 (Integer)
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||||
// Operation: (cast) Dst -> Dst
|
// Operation: (cast) Dst -> Dst
|
||||||
void D2I();
|
void D2I();
|
||||||
|
|
||||||
// [Casts] 0x069 — D2L: F64 (Double) to I64 (Long)
|
// [Casts] 0x069 — D2L: F64 (Double) to I64 (Long)
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||||
// Operation: (cast) Dst -> Dst
|
// Operation: (cast) Dst -> Dst
|
||||||
void D2L();
|
void D2L();
|
||||||
|
|
||||||
// [Trigonometric] 0x06C — SIN: Sine Function
|
// [Trigonometric] 0x06C — SIN: Sine Function
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation: sin( Dst ) -> Dst
|
// Operation: sin( Dst ) -> Dst
|
||||||
void SIN();
|
void SIN();
|
||||||
|
|
||||||
// [Trigonometric] 0x06D — COS: Cosine Function
|
// [Trigonometric] 0x06D — COS: Cosine Function
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation: cos( Dst ) -> Dst
|
// Operation: cos( Dst ) -> Dst
|
||||||
void COS();
|
void COS();
|
||||||
|
|
||||||
// [Trigonometric] 0x06E — TAN: Tangent Function
|
// [Trigonometric] 0x06E — TAN: Tangent Function
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation: tan( Dst ) -> Dst
|
// Operation: tan( Dst ) -> Dst
|
||||||
void TAN();
|
void TAN();
|
||||||
|
|
||||||
// [Trigonometric] 0x06F — ASIN: Arc Sine Function
|
// [Trigonometric] 0x06F — ASIN: Arc Sine Function
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation: asin( Dst ) -> Dst
|
// Operation: asin( Dst ) -> Dst
|
||||||
void ASIN();
|
void ASIN();
|
||||||
|
|
||||||
// [Trigonometric] 0x070 — ACOS: Arc Cosine Function
|
// [Trigonometric] 0x070 — ACOS: Arc Cosine Function
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation: acos( Dst ) -> Dst
|
// Operation: acos( Dst ) -> Dst
|
||||||
void ACOS();
|
void ACOS();
|
||||||
|
|
||||||
// [Trigonometric] 0x071 — ATAN: Arc Tangent Function
|
// [Trigonometric] 0x071 — ATAN: Arc Tangent Function
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation: atan( Dst ) -> Dst
|
// Operation: atan( Dst ) -> Dst
|
||||||
void ATAN();
|
void ATAN();
|
||||||
|
|
||||||
// [Trigonometric] 0x072 — ATAN2: Arc Tangent Function with 2 Arguments
|
// [Trigonometric] 0x072 — ATAN2: Arc Tangent Function with 2 Arguments
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: atan( Dst, Src ) -> Dst
|
// Operation: atan( Dst, Src ) -> Dst
|
||||||
void ATAN2();
|
void ATAN2();
|
||||||
|
|
||||||
// [Exponential] 0x074 — EXP: Exponential Function
|
// [Exponential] 0x074 — EXP: Exponential Function
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation: exp( Dst ) -> Dst
|
// Operation: exp( Dst ) -> Dst
|
||||||
void EXP();
|
void EXP();
|
||||||
|
|
||||||
// [Exponential] 0x075 — LOG: Natural Logarithm
|
// [Exponential] 0x075 — LOG: Natural Logarithm
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation: ln( Dst ) -> Dst
|
// Operation: ln( Dst ) -> Dst
|
||||||
void LOG();
|
void LOG();
|
||||||
|
|
||||||
// [Exponential] 0x076 — LOGAB: Logarithm A of B
|
// [Exponential] 0x076 — LOGAB: Logarithm A of B
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: log( Dst, Src ) -> Dst
|
// Operation: log( Dst, Src ) -> Dst
|
||||||
void LOGAB();
|
void LOGAB();
|
||||||
|
|
||||||
// [Exponential] 0x077 — POW: Power Function
|
// [Exponential] 0x077 — POW: Power Function
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: pow( Dst, Src ) -> Dst
|
// Operation: pow( Dst, Src ) -> Dst
|
||||||
void POW();
|
void POW();
|
||||||
|
|
||||||
// [Exponential] 0x078 — SQRT: Square Root
|
// [Exponential] 0x078 — SQRT: Square Root
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||||
// Operation: sqrt( Dst ) -> Dst
|
// Operation: sqrt( Dst ) -> Dst
|
||||||
void SQRT();
|
void SQRT();
|
||||||
|
|
||||||
// [Exponential] 0x079 — ROOT: General Root
|
// [Exponential] 0x079 — ROOT: General Root
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||||
// Operation: pow( Dst, 1 / Src ) -> Dst
|
// Operation: pow( Dst, 1 / Src ) -> Dst
|
||||||
void ROOT();
|
void ROOT();
|
||||||
|
|
||||||
@@ -650,6 +836,16 @@ namespace spider {
|
|||||||
// Operation:
|
// Operation:
|
||||||
void MDET();
|
void MDET();
|
||||||
|
|
||||||
|
// [Quaternion] 0x086 — QMKA: Quaternion Make from Angles
|
||||||
|
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||||
|
// Operation:
|
||||||
|
void QMKA();
|
||||||
|
|
||||||
|
// [Quaternion] 0x087 — QMUL: Quaternion Multiply
|
||||||
|
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||||
|
// Operation:
|
||||||
|
void QMUL();
|
||||||
|
|
||||||
// [SIMD] 0x08A — XADD: SIMD Addition
|
// [SIMD] 0x08A — XADD: SIMD Addition
|
||||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||||
// Operation:
|
// Operation:
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <spider/SpiderRuntime.hpp>
|
|
||||||
|
|
||||||
namespace spider {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements an instruction reel.
|
|
||||||
*/
|
|
||||||
class InstrReel {
|
|
||||||
private:
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
InstrReel();
|
|
||||||
|
|
||||||
~InstrReel();
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the two-byte instruction at the
|
|
||||||
* specific byte location.
|
|
||||||
*/
|
|
||||||
u16 instrAt(u64 ip) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtains a byte of data at
|
|
||||||
* the specific location.
|
|
||||||
*/
|
|
||||||
u8 dataAt(u64 ip) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the data, and then
|
|
||||||
* feeds the instruction into the
|
|
||||||
* CPU.
|
|
||||||
*
|
|
||||||
* Returns how many steps it should
|
|
||||||
* move after.
|
|
||||||
*/
|
|
||||||
u8 feedNext(CPU& cpu);
|
|
||||||
|
|
||||||
public: // Static Utils //
|
|
||||||
|
|
||||||
static u16 unpackInstr(u16 bcode);
|
|
||||||
|
|
||||||
static u8 unpackAddrMode(u16 bcode);
|
|
||||||
|
|
||||||
static u8 unpackTypeSize(u16 bcode);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -23,21 +23,25 @@ namespace spider {
|
|||||||
f64 _f64;
|
f64 _f64;
|
||||||
u8 _bytes[8];
|
u8 _bytes[8];
|
||||||
|
|
||||||
SPIDER_PACKED_STRUCT(struct {
|
struct {
|
||||||
#if SPIDER_LITTLE_ENDIAN
|
#if SPIDER_LITTLE_ENDIAN
|
||||||
u8 _u8; u64 : 56;
|
u8 _u8; // This looks like a cruel joke
|
||||||
|
u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8;
|
||||||
#else
|
#else
|
||||||
u64 : 56; u8 _u8;
|
u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8;
|
||||||
|
u8 _u8;
|
||||||
#endif
|
#endif
|
||||||
});
|
};
|
||||||
|
|
||||||
SPIDER_PACKED_STRUCT(struct {
|
struct {
|
||||||
#if SPIDER_LITTLE_ENDIAN
|
#if SPIDER_LITTLE_ENDIAN
|
||||||
u16 _u16; u64 : 48;
|
u16 _u16;
|
||||||
|
u16 : 16; u16 : 16; u16 : 16;
|
||||||
#else
|
#else
|
||||||
u64 : 48; u16 _u16;
|
u16 : 16; u16 : 16; u16 : 16;
|
||||||
|
u16 _u16;
|
||||||
#endif
|
#endif
|
||||||
});
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
#if SPIDER_LITTLE_ENDIAN
|
#if SPIDER_LITTLE_ENDIAN
|
||||||
|
|||||||
404
src/spider/runtime/debug/LiveDebug.cpp
Normal file
404
src/spider/runtime/debug/LiveDebug.cpp
Normal file
@@ -0,0 +1,404 @@
|
|||||||
|
#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, CPU& cpu) {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 addressWidth(isize ramSize) {
|
||||||
|
if (ramSize == 0) return 1;
|
||||||
|
isize maxAddr = ramSize - 1;
|
||||||
|
i32 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, i32 x, i32 y, i32 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 (int i = 0; i < trackHeight; ++i) {
|
||||||
|
term.move(y + i, 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
|
||||||
|
i32 thumbOffset = i32(ratio * (trackHeight - 1));
|
||||||
|
|
||||||
|
// 3. Draw the Thumb (Full Block: █)
|
||||||
|
term.move(y + thumbOffset, 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
|
||||||
|
i32 y = 3;
|
||||||
|
i32 height = 36;
|
||||||
|
|
||||||
|
// 2. Configuration for the hex layout
|
||||||
|
int addrWidth = addressWidth(ram.size());
|
||||||
|
int bytesPerRow = 8;
|
||||||
|
int displayRows = height - 2; // Subtract top/bottom borders
|
||||||
|
i32 width = (2 + 2 + 16 + 7 + 3 + 8 + 4) + addrWidth;
|
||||||
|
i32 x = 37;
|
||||||
|
|
||||||
|
// create box
|
||||||
|
term.drawBox(y, x, width, 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 (int i = 0; i < displayRows; ++i) {
|
||||||
|
isize currentRowAddr = scrollPos + (i * bytesPerRow);
|
||||||
|
|
||||||
|
// address lock
|
||||||
|
if (currentRowAddr >= ram.size()) {
|
||||||
|
term.move(y + 1 + i, 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(addrWidth) << currentRowAddr << " ";
|
||||||
|
|
||||||
|
// Hex Bytes
|
||||||
|
std::string asciiPart = "";
|
||||||
|
for (int 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(y + 1 + i, 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.ram[0] = 0xFF;
|
||||||
|
runtime.ram[1] = 0xEE;
|
||||||
|
runtime.ram[2] = 0xDD;
|
||||||
|
runtime.ram[3] = 0xCC;
|
||||||
|
runtime.ram[4] = 0xBB;
|
||||||
|
runtime.ram[5] = 0xAA;
|
||||||
|
runtime.ram[6] = 0x99;
|
||||||
|
runtime.ram[7] = 0x88;
|
||||||
|
fix.writeU16(0, 0b0000111);
|
||||||
|
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, runtime.cpu);
|
||||||
|
|
||||||
|
// 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.fetchOperDst();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
t.altbuff(false).println("Stopped Spider live debug.").flush();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
7
src/spider/runtime/debug/LiveDebug.hpp
Normal file
7
src/spider/runtime/debug/LiveDebug.hpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
int liveDebugMain();
|
||||||
|
|
||||||
|
}
|
||||||
746
src/spider/runtime/instr/InstrMap.cpp
Normal file
746
src/spider/runtime/instr/InstrMap.cpp
Normal file
@@ -0,0 +1,746 @@
|
|||||||
|
/**
|
||||||
|
* @file InstrMap.cpp
|
||||||
|
* @brief Spider VM instruction dispatch — array and switch implementations.
|
||||||
|
*
|
||||||
|
* AUTO-GENERATED by pygen.ipynb — DO NOT EDIT BY HAND.
|
||||||
|
*
|
||||||
|
* This file provides two equivalent dispatch mechanisms:
|
||||||
|
*
|
||||||
|
* 1. InstrMap[] — A lookup table of member-function pointers indexed by
|
||||||
|
* opcode. O(1) dispatch; suitable for platforms where
|
||||||
|
* indirect calls through function pointers are efficient.
|
||||||
|
*
|
||||||
|
* 2. CPU::execute(u16) — A switch/case over every opcode. Lets the
|
||||||
|
* compiler emit a jump table or branch tree; may be
|
||||||
|
* preferable on microcontrollers or when link-time
|
||||||
|
* optimisation can inline the handlers.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <spider/runtime/cpu/CPU.hpp>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
// =============================================================
|
||||||
|
// Version 1 — Lookup table of member-function pointers
|
||||||
|
// =============================================================
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruction dispatch table (512 entries, 9-bit opcode space).
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* u16 opcode = fetch();
|
||||||
|
* CPU::Fn fn = InstrMap[opcode];
|
||||||
|
* if (fn) (cpu.*fn)();
|
||||||
|
*/
|
||||||
|
CPU::Fn CPU::instrMap[] = {
|
||||||
|
&CPU::NOP, // 0x000 — No Operation
|
||||||
|
&CPU::SPDR, // 0x001 — Will place the Spider version of the interpreter in RA
|
||||||
|
&CPU::MMODE, // 0x002 — Set Memory Mode
|
||||||
|
&CPU::INT, // 0x003 — Interrupt
|
||||||
|
&CPU::LRV, // 0x004 — Load Interrupt Vector Register
|
||||||
|
&CPU::FSR, // 0x005 — Fetch System Register
|
||||||
|
&CPU::FIR, // 0x006 — Fetch Instruction Register
|
||||||
|
&CPU::FZR, // 0x007 — Fetch Stack Base Register
|
||||||
|
&CPU::LSR, // 0x008 — Load System Register
|
||||||
|
&CPU::FVR, // 0x009 — Fetch Interrupt Vector Register
|
||||||
|
&CPU::MOV, // 0x00A — Moves values
|
||||||
|
&CPU::MOR, // 0x00B — Moves registers
|
||||||
|
&CPU::AMOV, // 0x00C — Array Move, uses X and Y as ptrs, A as amount
|
||||||
|
&CPU::SWP, // 0x00D — Swap registers
|
||||||
|
&CPU::AHM, // 0x00E — Ask Host for Memory
|
||||||
|
nullptr, // 0x00F (reserved)
|
||||||
|
&CPU::COM, // 0x010 — One's complement
|
||||||
|
&CPU::NEG, // 0x011 — Two's complement
|
||||||
|
&CPU::EXS, // 0x012 — Extend Sign
|
||||||
|
&CPU::INC, // 0x013 — Increment
|
||||||
|
&CPU::DEC, // 0x014 — Decrement
|
||||||
|
&CPU::ADD, // 0x015 — Addition
|
||||||
|
&CPU::SUB, // 0x016 — Subtraction
|
||||||
|
&CPU::MUL, // 0x017 — Multiplication
|
||||||
|
&CPU::UMUL, // 0x018 — Unsigned Multiplication
|
||||||
|
&CPU::DIV, // 0x019 — Division
|
||||||
|
&CPU::UDIV, // 0x01A — Unsigned Division
|
||||||
|
&CPU::MOD, // 0x01B — Modulus
|
||||||
|
&CPU::UMOD, // 0x01C — Unsigned Modulus
|
||||||
|
&CPU::DMOD, // 0x01D — Division and Modulus
|
||||||
|
&CPU::UDMD, // 0x01E — Unsigned Division and Modulus
|
||||||
|
&CPU::FBT, // 0x01F — Test and update Flag Register (Integer) Bits
|
||||||
|
&CPU::STB, // 0x020 — Set Bit
|
||||||
|
&CPU::CRB, // 0x021 — Clear Bit
|
||||||
|
&CPU::TSB, // 0x022 — Test Bit
|
||||||
|
&CPU::BOOL, // 0x023 — Sets the booleaness of a value
|
||||||
|
&CPU::NOT, // 0x024 — Sets the inverse booleaness of a value (! BOOL)
|
||||||
|
&CPU::AND, // 0x025 — Boolean AND operation
|
||||||
|
&CPU::OR, // 0x026 — Boolean OR operation
|
||||||
|
&CPU::XOR, // 0x027 — Boolean XOR operation
|
||||||
|
&CPU::SHL, // 0x028 — Arithmetic Shift Left
|
||||||
|
&CPU::SHR, // 0x029 — Arithmetic Shift Right
|
||||||
|
&CPU::SSR, // 0x02A — Signed Shift Right
|
||||||
|
&CPU::ROL, // 0x02B — Rotate Left
|
||||||
|
&CPU::ROR, // 0x02C — Rotate Right
|
||||||
|
&CPU::CNT, // 0x02D — Counts bits
|
||||||
|
nullptr, // 0x02E (reserved)
|
||||||
|
nullptr, // 0x02F (reserved)
|
||||||
|
&CPU::EQ, // 0x030 — Equal
|
||||||
|
&CPU::NE, // 0x031 — Not Equal
|
||||||
|
&CPU::GT, // 0x032 — Greater Than
|
||||||
|
&CPU::GE, // 0x033 — Greater or Equal Than
|
||||||
|
&CPU::LT, // 0x034 — Lower Than
|
||||||
|
&CPU::LE, // 0x035 — Lower or Equal Than
|
||||||
|
nullptr, // 0x036 (reserved)
|
||||||
|
nullptr, // 0x037 (reserved)
|
||||||
|
&CPU::JMP, // 0x038 — Jump to absolute position
|
||||||
|
&CPU::JEQ, // 0x039 — Jumps to position if EQ flag is set
|
||||||
|
&CPU::JNE, // 0x03A — Jumps to position if EQ flag is cleared
|
||||||
|
&CPU::JIF, // 0x03B — Jumps if value provided is booleanly true
|
||||||
|
&CPU::JMR, // 0x03C — Jump Relative
|
||||||
|
&CPU::JER, // 0x03D — Jumps to relative position if EQ flag is set
|
||||||
|
&CPU::JNR, // 0x03E — Jumps to relative position if EQ flag is cleared
|
||||||
|
&CPU::JIR, // 0x03F — Jumps to relative position if value provided is booleanly true
|
||||||
|
&CPU::SFB, // 0x040 — Store (User) Flag Bit
|
||||||
|
&CPU::LFB, // 0x041 — Load (User) Flag Bit
|
||||||
|
&CPU::JUF, // 0x042 — Jump to absolute position, if user flag is true
|
||||||
|
&CPU::JUR, // 0x043 — Jump to relative position, if user flag is true
|
||||||
|
&CPU::PUSH, // 0x044 — Push to stack
|
||||||
|
&CPU::POP, // 0x045 — Pop from stack
|
||||||
|
&CPU::ALLOC, // 0x046 — Allocate to heap
|
||||||
|
&CPU::HFREE, // 0x047 — Delete from heap
|
||||||
|
nullptr, // 0x048 (reserved)
|
||||||
|
nullptr, // 0x049 (reserved)
|
||||||
|
&CPU::CALL, // 0x04A — Call function at instruction index
|
||||||
|
&CPU::RET, // 0x04B — Return from a function
|
||||||
|
&CPU::EDI, // 0x04C — Enable/Disable External Interrupts
|
||||||
|
&CPU::SHSS, // 0x04D — Set Hotswap Signal Bit
|
||||||
|
nullptr, // 0x04E (reserved)
|
||||||
|
nullptr, // 0x04F (reserved)
|
||||||
|
&CPU::FLI, // 0x050 — Float Load Immediate
|
||||||
|
&CPU::FNEG, // 0x051 — Float negate
|
||||||
|
&CPU::FADD, // 0x052 — Float add
|
||||||
|
&CPU::FSUB, // 0x053 — Float subtract
|
||||||
|
&CPU::FMUL, // 0x054 — Float multiplication
|
||||||
|
&CPU::FDIV, // 0x055 — Float division
|
||||||
|
&CPU::FMOD, // 0x056 — Float modulus
|
||||||
|
&CPU::FDMOD, // 0x057 — Float division and modulus
|
||||||
|
&CPU::FEPS, // 0x058 — Sets the float epsilon value, for comparison
|
||||||
|
&CPU::FEEP, // 0x059 — Float Enable/Disable Epsilon
|
||||||
|
&CPU::FEQ, // 0x05A — Float Equal
|
||||||
|
&CPU::FNE, // 0x05B — Float Not Equal
|
||||||
|
&CPU::FGT, // 0x05C — Float Greater Than
|
||||||
|
&CPU::FGE, // 0x05D — Float Greater or Equal Than
|
||||||
|
&CPU::FLT, // 0x05E — Float Lower Than
|
||||||
|
&CPU::FLE, // 0x05F — Float Lower or Equal Than
|
||||||
|
&CPU::F2D, // 0x060 — F32 (Float) to F64 (Double)
|
||||||
|
&CPU::D2F, // 0x061 — F64 (Double) to F32 (Float)
|
||||||
|
&CPU::I2F, // 0x062 — I32 (Integer) to F32 (Float)
|
||||||
|
&CPU::I2D, // 0x063 — I32 (Integer) to F64 (Double)
|
||||||
|
&CPU::L2F, // 0x064 — I64 (Long) to F32 (Float)
|
||||||
|
&CPU::L2D, // 0x065 — I64 (Long) to F64 (Double)
|
||||||
|
&CPU::F2I, // 0x066 — F32 (Float) to I32 (Integer)
|
||||||
|
&CPU::F2L, // 0x067 — F32 (Float) to I64 (Long)
|
||||||
|
&CPU::D2I, // 0x068 — F64 (Double) to I32 (Integer)
|
||||||
|
&CPU::D2L, // 0x069 — F64 (Double) to I64 (Long)
|
||||||
|
nullptr, // 0x06A (reserved)
|
||||||
|
nullptr, // 0x06B (reserved)
|
||||||
|
&CPU::SIN, // 0x06C — Sine Function
|
||||||
|
&CPU::COS, // 0x06D — Cosine Function
|
||||||
|
&CPU::TAN, // 0x06E — Tangent Function
|
||||||
|
&CPU::ASIN, // 0x06F — Arc Sine Function
|
||||||
|
&CPU::ACOS, // 0x070 — Arc Cosine Function
|
||||||
|
&CPU::ATAN, // 0x071 — Arc Tangent Function
|
||||||
|
&CPU::ATAN2, // 0x072 — Arc Tangent Function with 2 Arguments
|
||||||
|
nullptr, // 0x073 (reserved)
|
||||||
|
&CPU::EXP, // 0x074 — Exponential Function
|
||||||
|
&CPU::LOG, // 0x075 — Natural Logarithm
|
||||||
|
&CPU::LOGAB, // 0x076 — Logarithm A of B
|
||||||
|
&CPU::POW, // 0x077 — Power Function
|
||||||
|
&CPU::SQRT, // 0x078 — Square Root
|
||||||
|
&CPU::ROOT, // 0x079 — General Root
|
||||||
|
nullptr, // 0x07A (reserved)
|
||||||
|
nullptr, // 0x07B (reserved)
|
||||||
|
&CPU::ADC, // 0x07C — Add with Carry
|
||||||
|
&CPU::SWC, // 0x07D — Subtract with Carry (Borrow)
|
||||||
|
&CPU::MWO, // 0x07E — Multiply with Overflow
|
||||||
|
&CPU::UMO, // 0x07F — Unsigned Multiply with Overflow
|
||||||
|
&CPU::MADD, // 0x080 — Matrix Addition
|
||||||
|
&CPU::MSUB, // 0x081 — Matrix Subtraction
|
||||||
|
&CPU::MMUL, // 0x082 — Matrix Multiply
|
||||||
|
&CPU::MINV, // 0x083 — Matrix Inverse
|
||||||
|
&CPU::MTRA, // 0x084 — Matrix Transpose
|
||||||
|
&CPU::MDET, // 0x085 — Matrix Determinant
|
||||||
|
&CPU::QMKA, // 0x086 — Quaternion Make from Angles
|
||||||
|
&CPU::QMUL, // 0x087 — Quaternion Multiply
|
||||||
|
nullptr, // 0x088
|
||||||
|
nullptr, // 0x089
|
||||||
|
&CPU::XADD, // 0x08A — SIMD Addition
|
||||||
|
&CPU::XSUB, // 0x08B — SIMD Subtract
|
||||||
|
&CPU::XAMA, // 0x08C — SIMD Alternate Multiply-Add
|
||||||
|
&CPU::XMUL, // 0x08D — SIMD Multiply
|
||||||
|
&CPU::XDIV, // 0x08E — SIMD Divide
|
||||||
|
nullptr, // 0x08F
|
||||||
|
nullptr, // 0x090
|
||||||
|
nullptr, // 0x091
|
||||||
|
nullptr, // 0x092
|
||||||
|
nullptr, // 0x093
|
||||||
|
nullptr, // 0x094
|
||||||
|
nullptr, // 0x095
|
||||||
|
nullptr, // 0x096
|
||||||
|
nullptr, // 0x097
|
||||||
|
nullptr, // 0x098
|
||||||
|
nullptr, // 0x099
|
||||||
|
nullptr, // 0x09A
|
||||||
|
nullptr, // 0x09B
|
||||||
|
nullptr, // 0x09C
|
||||||
|
nullptr, // 0x09D
|
||||||
|
nullptr, // 0x09E
|
||||||
|
nullptr, // 0x09F
|
||||||
|
nullptr, // 0x0A0
|
||||||
|
nullptr, // 0x0A1
|
||||||
|
nullptr, // 0x0A2
|
||||||
|
nullptr, // 0x0A3
|
||||||
|
nullptr, // 0x0A4
|
||||||
|
nullptr, // 0x0A5
|
||||||
|
nullptr, // 0x0A6
|
||||||
|
nullptr, // 0x0A7
|
||||||
|
nullptr, // 0x0A8
|
||||||
|
nullptr, // 0x0A9
|
||||||
|
nullptr, // 0x0AA
|
||||||
|
nullptr, // 0x0AB
|
||||||
|
nullptr, // 0x0AC
|
||||||
|
nullptr, // 0x0AD
|
||||||
|
nullptr, // 0x0AE
|
||||||
|
nullptr, // 0x0AF
|
||||||
|
nullptr, // 0x0B0
|
||||||
|
nullptr, // 0x0B1
|
||||||
|
nullptr, // 0x0B2
|
||||||
|
nullptr, // 0x0B3
|
||||||
|
nullptr, // 0x0B4
|
||||||
|
nullptr, // 0x0B5
|
||||||
|
nullptr, // 0x0B6
|
||||||
|
nullptr, // 0x0B7
|
||||||
|
nullptr, // 0x0B8
|
||||||
|
nullptr, // 0x0B9
|
||||||
|
nullptr, // 0x0BA
|
||||||
|
nullptr, // 0x0BB
|
||||||
|
nullptr, // 0x0BC
|
||||||
|
nullptr, // 0x0BD
|
||||||
|
nullptr, // 0x0BE
|
||||||
|
nullptr, // 0x0BF
|
||||||
|
nullptr, // 0x0C0
|
||||||
|
nullptr, // 0x0C1
|
||||||
|
nullptr, // 0x0C2
|
||||||
|
nullptr, // 0x0C3
|
||||||
|
nullptr, // 0x0C4
|
||||||
|
nullptr, // 0x0C5
|
||||||
|
nullptr, // 0x0C6
|
||||||
|
nullptr, // 0x0C7
|
||||||
|
nullptr, // 0x0C8
|
||||||
|
nullptr, // 0x0C9
|
||||||
|
nullptr, // 0x0CA
|
||||||
|
nullptr, // 0x0CB
|
||||||
|
nullptr, // 0x0CC
|
||||||
|
nullptr, // 0x0CD
|
||||||
|
nullptr, // 0x0CE
|
||||||
|
nullptr, // 0x0CF
|
||||||
|
nullptr, // 0x0D0
|
||||||
|
nullptr, // 0x0D1
|
||||||
|
nullptr, // 0x0D2
|
||||||
|
nullptr, // 0x0D3
|
||||||
|
nullptr, // 0x0D4
|
||||||
|
nullptr, // 0x0D5
|
||||||
|
nullptr, // 0x0D6
|
||||||
|
nullptr, // 0x0D7
|
||||||
|
nullptr, // 0x0D8
|
||||||
|
nullptr, // 0x0D9
|
||||||
|
nullptr, // 0x0DA
|
||||||
|
nullptr, // 0x0DB
|
||||||
|
nullptr, // 0x0DC
|
||||||
|
nullptr, // 0x0DD
|
||||||
|
nullptr, // 0x0DE
|
||||||
|
nullptr, // 0x0DF
|
||||||
|
nullptr, // 0x0E0
|
||||||
|
nullptr, // 0x0E1
|
||||||
|
nullptr, // 0x0E2
|
||||||
|
nullptr, // 0x0E3
|
||||||
|
nullptr, // 0x0E4
|
||||||
|
nullptr, // 0x0E5
|
||||||
|
nullptr, // 0x0E6
|
||||||
|
nullptr, // 0x0E7
|
||||||
|
nullptr, // 0x0E8
|
||||||
|
nullptr, // 0x0E9
|
||||||
|
nullptr, // 0x0EA
|
||||||
|
nullptr, // 0x0EB
|
||||||
|
nullptr, // 0x0EC
|
||||||
|
nullptr, // 0x0ED
|
||||||
|
nullptr, // 0x0EE
|
||||||
|
nullptr, // 0x0EF
|
||||||
|
&CPU::UPY, // 0x0F0 — Will place "YUPI" in memory
|
||||||
|
nullptr, // 0x0F1
|
||||||
|
nullptr, // 0x0F2
|
||||||
|
nullptr, // 0x0F3
|
||||||
|
nullptr, // 0x0F4
|
||||||
|
nullptr, // 0x0F5
|
||||||
|
nullptr, // 0x0F6
|
||||||
|
nullptr, // 0x0F7
|
||||||
|
nullptr, // 0x0F8
|
||||||
|
nullptr, // 0x0F9
|
||||||
|
nullptr, // 0x0FA
|
||||||
|
nullptr, // 0x0FB
|
||||||
|
nullptr, // 0x0FC
|
||||||
|
nullptr, // 0x0FD
|
||||||
|
nullptr, // 0x0FE
|
||||||
|
nullptr, // 0x0FF
|
||||||
|
nullptr, // 0x100
|
||||||
|
nullptr, // 0x101
|
||||||
|
nullptr, // 0x102
|
||||||
|
nullptr, // 0x103
|
||||||
|
nullptr, // 0x104
|
||||||
|
nullptr, // 0x105
|
||||||
|
nullptr, // 0x106
|
||||||
|
nullptr, // 0x107
|
||||||
|
nullptr, // 0x108
|
||||||
|
nullptr, // 0x109
|
||||||
|
nullptr, // 0x10A
|
||||||
|
nullptr, // 0x10B
|
||||||
|
nullptr, // 0x10C
|
||||||
|
nullptr, // 0x10D
|
||||||
|
nullptr, // 0x10E
|
||||||
|
nullptr, // 0x10F
|
||||||
|
nullptr, // 0x110
|
||||||
|
nullptr, // 0x111
|
||||||
|
nullptr, // 0x112
|
||||||
|
nullptr, // 0x113
|
||||||
|
nullptr, // 0x114
|
||||||
|
nullptr, // 0x115
|
||||||
|
nullptr, // 0x116
|
||||||
|
nullptr, // 0x117
|
||||||
|
nullptr, // 0x118
|
||||||
|
nullptr, // 0x119
|
||||||
|
nullptr, // 0x11A
|
||||||
|
nullptr, // 0x11B
|
||||||
|
nullptr, // 0x11C
|
||||||
|
nullptr, // 0x11D
|
||||||
|
nullptr, // 0x11E
|
||||||
|
nullptr, // 0x11F
|
||||||
|
nullptr, // 0x120
|
||||||
|
nullptr, // 0x121
|
||||||
|
nullptr, // 0x122
|
||||||
|
nullptr, // 0x123
|
||||||
|
nullptr, // 0x124
|
||||||
|
nullptr, // 0x125
|
||||||
|
nullptr, // 0x126
|
||||||
|
nullptr, // 0x127
|
||||||
|
nullptr, // 0x128
|
||||||
|
nullptr, // 0x129
|
||||||
|
nullptr, // 0x12A
|
||||||
|
nullptr, // 0x12B
|
||||||
|
nullptr, // 0x12C
|
||||||
|
nullptr, // 0x12D
|
||||||
|
nullptr, // 0x12E
|
||||||
|
nullptr, // 0x12F
|
||||||
|
nullptr, // 0x130
|
||||||
|
nullptr, // 0x131
|
||||||
|
nullptr, // 0x132
|
||||||
|
nullptr, // 0x133
|
||||||
|
nullptr, // 0x134
|
||||||
|
nullptr, // 0x135
|
||||||
|
nullptr, // 0x136
|
||||||
|
nullptr, // 0x137
|
||||||
|
nullptr, // 0x138
|
||||||
|
nullptr, // 0x139
|
||||||
|
nullptr, // 0x13A
|
||||||
|
nullptr, // 0x13B
|
||||||
|
nullptr, // 0x13C
|
||||||
|
nullptr, // 0x13D
|
||||||
|
nullptr, // 0x13E
|
||||||
|
nullptr, // 0x13F
|
||||||
|
nullptr, // 0x140
|
||||||
|
nullptr, // 0x141
|
||||||
|
nullptr, // 0x142
|
||||||
|
nullptr, // 0x143
|
||||||
|
nullptr, // 0x144
|
||||||
|
nullptr, // 0x145
|
||||||
|
nullptr, // 0x146
|
||||||
|
nullptr, // 0x147
|
||||||
|
nullptr, // 0x148
|
||||||
|
nullptr, // 0x149
|
||||||
|
nullptr, // 0x14A
|
||||||
|
nullptr, // 0x14B
|
||||||
|
nullptr, // 0x14C
|
||||||
|
nullptr, // 0x14D
|
||||||
|
nullptr, // 0x14E
|
||||||
|
nullptr, // 0x14F
|
||||||
|
nullptr, // 0x150
|
||||||
|
nullptr, // 0x151
|
||||||
|
nullptr, // 0x152
|
||||||
|
nullptr, // 0x153
|
||||||
|
nullptr, // 0x154
|
||||||
|
nullptr, // 0x155
|
||||||
|
nullptr, // 0x156
|
||||||
|
nullptr, // 0x157
|
||||||
|
nullptr, // 0x158
|
||||||
|
nullptr, // 0x159
|
||||||
|
nullptr, // 0x15A
|
||||||
|
nullptr, // 0x15B
|
||||||
|
nullptr, // 0x15C
|
||||||
|
nullptr, // 0x15D
|
||||||
|
nullptr, // 0x15E
|
||||||
|
nullptr, // 0x15F
|
||||||
|
nullptr, // 0x160
|
||||||
|
nullptr, // 0x161
|
||||||
|
nullptr, // 0x162
|
||||||
|
nullptr, // 0x163
|
||||||
|
nullptr, // 0x164
|
||||||
|
nullptr, // 0x165
|
||||||
|
nullptr, // 0x166
|
||||||
|
nullptr, // 0x167
|
||||||
|
nullptr, // 0x168
|
||||||
|
nullptr, // 0x169
|
||||||
|
nullptr, // 0x16A
|
||||||
|
nullptr, // 0x16B
|
||||||
|
nullptr, // 0x16C
|
||||||
|
nullptr, // 0x16D
|
||||||
|
nullptr, // 0x16E
|
||||||
|
nullptr, // 0x16F
|
||||||
|
nullptr, // 0x170
|
||||||
|
nullptr, // 0x171
|
||||||
|
nullptr, // 0x172
|
||||||
|
nullptr, // 0x173
|
||||||
|
nullptr, // 0x174
|
||||||
|
nullptr, // 0x175
|
||||||
|
nullptr, // 0x176
|
||||||
|
nullptr, // 0x177
|
||||||
|
nullptr, // 0x178
|
||||||
|
nullptr, // 0x179
|
||||||
|
nullptr, // 0x17A
|
||||||
|
nullptr, // 0x17B
|
||||||
|
nullptr, // 0x17C
|
||||||
|
nullptr, // 0x17D
|
||||||
|
nullptr, // 0x17E
|
||||||
|
nullptr, // 0x17F
|
||||||
|
nullptr, // 0x180
|
||||||
|
nullptr, // 0x181
|
||||||
|
nullptr, // 0x182
|
||||||
|
nullptr, // 0x183
|
||||||
|
nullptr, // 0x184
|
||||||
|
nullptr, // 0x185
|
||||||
|
nullptr, // 0x186
|
||||||
|
nullptr, // 0x187
|
||||||
|
nullptr, // 0x188
|
||||||
|
nullptr, // 0x189
|
||||||
|
nullptr, // 0x18A
|
||||||
|
nullptr, // 0x18B
|
||||||
|
nullptr, // 0x18C
|
||||||
|
nullptr, // 0x18D
|
||||||
|
nullptr, // 0x18E
|
||||||
|
nullptr, // 0x18F
|
||||||
|
nullptr, // 0x190
|
||||||
|
nullptr, // 0x191
|
||||||
|
nullptr, // 0x192
|
||||||
|
nullptr, // 0x193
|
||||||
|
nullptr, // 0x194
|
||||||
|
nullptr, // 0x195
|
||||||
|
nullptr, // 0x196
|
||||||
|
nullptr, // 0x197
|
||||||
|
nullptr, // 0x198
|
||||||
|
nullptr, // 0x199
|
||||||
|
nullptr, // 0x19A
|
||||||
|
nullptr, // 0x19B
|
||||||
|
nullptr, // 0x19C
|
||||||
|
nullptr, // 0x19D
|
||||||
|
nullptr, // 0x19E
|
||||||
|
nullptr, // 0x19F
|
||||||
|
nullptr, // 0x1A0
|
||||||
|
nullptr, // 0x1A1
|
||||||
|
nullptr, // 0x1A2
|
||||||
|
nullptr, // 0x1A3
|
||||||
|
nullptr, // 0x1A4
|
||||||
|
nullptr, // 0x1A5
|
||||||
|
nullptr, // 0x1A6
|
||||||
|
nullptr, // 0x1A7
|
||||||
|
nullptr, // 0x1A8
|
||||||
|
nullptr, // 0x1A9
|
||||||
|
nullptr, // 0x1AA
|
||||||
|
nullptr, // 0x1AB
|
||||||
|
nullptr, // 0x1AC
|
||||||
|
nullptr, // 0x1AD
|
||||||
|
nullptr, // 0x1AE
|
||||||
|
nullptr, // 0x1AF
|
||||||
|
nullptr, // 0x1B0
|
||||||
|
nullptr, // 0x1B1
|
||||||
|
nullptr, // 0x1B2
|
||||||
|
nullptr, // 0x1B3
|
||||||
|
nullptr, // 0x1B4
|
||||||
|
nullptr, // 0x1B5
|
||||||
|
nullptr, // 0x1B6
|
||||||
|
nullptr, // 0x1B7
|
||||||
|
nullptr, // 0x1B8
|
||||||
|
nullptr, // 0x1B9
|
||||||
|
nullptr, // 0x1BA
|
||||||
|
nullptr, // 0x1BB
|
||||||
|
nullptr, // 0x1BC
|
||||||
|
nullptr, // 0x1BD
|
||||||
|
nullptr, // 0x1BE
|
||||||
|
nullptr, // 0x1BF
|
||||||
|
nullptr, // 0x1C0
|
||||||
|
nullptr, // 0x1C1
|
||||||
|
nullptr, // 0x1C2
|
||||||
|
nullptr, // 0x1C3
|
||||||
|
nullptr, // 0x1C4
|
||||||
|
nullptr, // 0x1C5
|
||||||
|
nullptr, // 0x1C6
|
||||||
|
nullptr, // 0x1C7
|
||||||
|
nullptr, // 0x1C8
|
||||||
|
nullptr, // 0x1C9
|
||||||
|
nullptr, // 0x1CA
|
||||||
|
nullptr, // 0x1CB
|
||||||
|
nullptr, // 0x1CC
|
||||||
|
nullptr, // 0x1CD
|
||||||
|
nullptr, // 0x1CE
|
||||||
|
nullptr, // 0x1CF
|
||||||
|
nullptr, // 0x1D0
|
||||||
|
nullptr, // 0x1D1
|
||||||
|
nullptr, // 0x1D2
|
||||||
|
nullptr, // 0x1D3
|
||||||
|
nullptr, // 0x1D4
|
||||||
|
nullptr, // 0x1D5
|
||||||
|
nullptr, // 0x1D6
|
||||||
|
nullptr, // 0x1D7
|
||||||
|
nullptr, // 0x1D8
|
||||||
|
nullptr, // 0x1D9
|
||||||
|
nullptr, // 0x1DA
|
||||||
|
nullptr, // 0x1DB
|
||||||
|
nullptr, // 0x1DC
|
||||||
|
nullptr, // 0x1DD
|
||||||
|
nullptr, // 0x1DE
|
||||||
|
nullptr, // 0x1DF
|
||||||
|
nullptr, // 0x1E0
|
||||||
|
nullptr, // 0x1E1
|
||||||
|
nullptr, // 0x1E2
|
||||||
|
nullptr, // 0x1E3
|
||||||
|
nullptr, // 0x1E4
|
||||||
|
nullptr, // 0x1E5
|
||||||
|
nullptr, // 0x1E6
|
||||||
|
nullptr, // 0x1E7
|
||||||
|
nullptr, // 0x1E8
|
||||||
|
nullptr, // 0x1E9
|
||||||
|
nullptr, // 0x1EA
|
||||||
|
nullptr, // 0x1EB
|
||||||
|
nullptr, // 0x1EC
|
||||||
|
nullptr, // 0x1ED
|
||||||
|
nullptr, // 0x1EE
|
||||||
|
nullptr, // 0x1EF
|
||||||
|
nullptr, // 0x1F0
|
||||||
|
nullptr, // 0x1F1
|
||||||
|
nullptr, // 0x1F2
|
||||||
|
nullptr, // 0x1F3
|
||||||
|
nullptr, // 0x1F4
|
||||||
|
nullptr, // 0x1F5
|
||||||
|
nullptr, // 0x1F6
|
||||||
|
nullptr, // 0x1F7
|
||||||
|
nullptr, // 0x1F8
|
||||||
|
nullptr, // 0x1F9
|
||||||
|
nullptr, // 0x1FA
|
||||||
|
nullptr, // 0x1FB
|
||||||
|
nullptr, // 0x1FC
|
||||||
|
nullptr, // 0x1FD
|
||||||
|
nullptr, // 0x1FE
|
||||||
|
nullptr, // 0x1FF
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// =============================================================
|
||||||
|
// Version 2 — Switch dispatch
|
||||||
|
// =============================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the instruction identified by @p opcode.
|
||||||
|
*
|
||||||
|
* This is functionally equivalent to the InstrMap[] table above
|
||||||
|
* but expressed as a switch so the compiler can choose the best
|
||||||
|
* lowering strategy (jump table, binary search, etc.).
|
||||||
|
*
|
||||||
|
* @param opcode 9-bit instruction opcode (0x000 - 0x1FF).
|
||||||
|
*/
|
||||||
|
void CPU::executeSwLk() {
|
||||||
|
switch (_opcode) {
|
||||||
|
|
||||||
|
// ── System ──────────────────────────────────────
|
||||||
|
case 0x000: NOP(); break;
|
||||||
|
case 0x001: SPDR(); break;
|
||||||
|
case 0x002: MMODE(); break;
|
||||||
|
case 0x003: INT(); break;
|
||||||
|
case 0x004: LRV(); break;
|
||||||
|
case 0x005: FSR(); break;
|
||||||
|
case 0x006: FIR(); break;
|
||||||
|
case 0x007: FZR(); break;
|
||||||
|
case 0x008: LSR(); break;
|
||||||
|
case 0x009: FVR(); break;
|
||||||
|
|
||||||
|
// ── Memory ──────────────────────────────────────
|
||||||
|
case 0x00A: MOV(); break;
|
||||||
|
case 0x00B: MOR(); break;
|
||||||
|
case 0x00C: AMOV(); break;
|
||||||
|
case 0x00D: SWP(); break;
|
||||||
|
case 0x00E: AHM(); break;
|
||||||
|
|
||||||
|
// ── Integer ─────────────────────────────────────
|
||||||
|
case 0x010: COM(); break;
|
||||||
|
case 0x011: NEG(); break;
|
||||||
|
case 0x012: EXS(); break;
|
||||||
|
case 0x013: INC(); break;
|
||||||
|
case 0x014: DEC(); break;
|
||||||
|
case 0x015: ADD(); break;
|
||||||
|
case 0x016: SUB(); break;
|
||||||
|
case 0x017: MUL(); break;
|
||||||
|
case 0x018: UMUL(); break;
|
||||||
|
case 0x019: DIV(); break;
|
||||||
|
case 0x01A: UDIV(); break;
|
||||||
|
case 0x01B: MOD(); break;
|
||||||
|
case 0x01C: UMOD(); break;
|
||||||
|
case 0x01D: DMOD(); break;
|
||||||
|
case 0x01E: UDMD(); break;
|
||||||
|
|
||||||
|
// ── System ──────────────────────────────────────
|
||||||
|
case 0x01F: FBT(); break;
|
||||||
|
|
||||||
|
// ── Bit Wise ────────────────────────────────────
|
||||||
|
case 0x020: STB(); break;
|
||||||
|
case 0x021: CRB(); break;
|
||||||
|
case 0x022: TSB(); break;
|
||||||
|
case 0x023: BOOL(); break;
|
||||||
|
case 0x024: NOT(); break;
|
||||||
|
case 0x025: AND(); break;
|
||||||
|
case 0x026: OR(); break;
|
||||||
|
case 0x027: XOR(); break;
|
||||||
|
case 0x028: SHL(); break;
|
||||||
|
case 0x029: SHR(); break;
|
||||||
|
case 0x02A: SSR(); break;
|
||||||
|
case 0x02B: ROL(); break;
|
||||||
|
case 0x02C: ROR(); break;
|
||||||
|
case 0x02D: CNT(); break;
|
||||||
|
|
||||||
|
// ── Boolean ─────────────────────────────────────
|
||||||
|
case 0x030: EQ(); break;
|
||||||
|
case 0x031: NE(); break;
|
||||||
|
case 0x032: GT(); break;
|
||||||
|
case 0x033: GE(); break;
|
||||||
|
case 0x034: LT(); break;
|
||||||
|
case 0x035: LE(); break;
|
||||||
|
|
||||||
|
// ── Branch ──────────────────────────────────────
|
||||||
|
case 0x038: JMP(); break;
|
||||||
|
case 0x039: JEQ(); break;
|
||||||
|
case 0x03A: JNE(); break;
|
||||||
|
case 0x03B: JIF(); break;
|
||||||
|
case 0x03C: JMR(); break;
|
||||||
|
case 0x03D: JER(); break;
|
||||||
|
case 0x03E: JNR(); break;
|
||||||
|
case 0x03F: JIR(); break;
|
||||||
|
|
||||||
|
// ── System ──────────────────────────────────────
|
||||||
|
case 0x040: SFB(); break;
|
||||||
|
case 0x041: LFB(); break;
|
||||||
|
|
||||||
|
// ── Branch ──────────────────────────────────────
|
||||||
|
case 0x042: JUF(); break;
|
||||||
|
case 0x043: JUR(); break;
|
||||||
|
|
||||||
|
// ── Memory ──────────────────────────────────────
|
||||||
|
case 0x044: PUSH(); break;
|
||||||
|
case 0x045: POP(); break;
|
||||||
|
case 0x046: ALLOC(); break;
|
||||||
|
case 0x047: HFREE(); break;
|
||||||
|
|
||||||
|
// ── Branch ──────────────────────────────────────
|
||||||
|
case 0x04A: CALL(); break;
|
||||||
|
case 0x04B: RET(); break;
|
||||||
|
|
||||||
|
// ── System ──────────────────────────────────────
|
||||||
|
case 0x04C: EDI(); break;
|
||||||
|
case 0x04D: SHSS(); break;
|
||||||
|
|
||||||
|
// ── Floating Point ──────────────────────────────
|
||||||
|
case 0x050: FLI(); break;
|
||||||
|
case 0x051: FNEG(); break;
|
||||||
|
case 0x052: FADD(); break;
|
||||||
|
case 0x053: FSUB(); break;
|
||||||
|
case 0x054: FMUL(); break;
|
||||||
|
case 0x055: FDIV(); break;
|
||||||
|
case 0x056: FMOD(); break;
|
||||||
|
case 0x057: FDMOD(); break;
|
||||||
|
case 0x058: FEPS(); break;
|
||||||
|
case 0x059: FEEP(); break;
|
||||||
|
|
||||||
|
// ── Boolean ─────────────────────────────────────
|
||||||
|
case 0x05A: FEQ(); break;
|
||||||
|
case 0x05B: FNE(); break;
|
||||||
|
case 0x05C: FGT(); break;
|
||||||
|
case 0x05D: FGE(); break;
|
||||||
|
case 0x05E: FLT(); break;
|
||||||
|
case 0x05F: FLE(); break;
|
||||||
|
|
||||||
|
// ── Casts ───────────────────────────────────────
|
||||||
|
case 0x060: F2D(); break;
|
||||||
|
case 0x061: D2F(); break;
|
||||||
|
case 0x062: I2F(); break;
|
||||||
|
case 0x063: I2D(); break;
|
||||||
|
case 0x064: L2F(); break;
|
||||||
|
case 0x065: L2D(); break;
|
||||||
|
case 0x066: F2I(); break;
|
||||||
|
case 0x067: F2L(); break;
|
||||||
|
case 0x068: D2I(); break;
|
||||||
|
case 0x069: D2L(); break;
|
||||||
|
|
||||||
|
// ── Trigonometric ───────────────────────────────
|
||||||
|
case 0x06C: SIN(); break;
|
||||||
|
case 0x06D: COS(); break;
|
||||||
|
case 0x06E: TAN(); break;
|
||||||
|
case 0x06F: ASIN(); break;
|
||||||
|
case 0x070: ACOS(); break;
|
||||||
|
case 0x071: ATAN(); break;
|
||||||
|
case 0x072: ATAN2(); break;
|
||||||
|
|
||||||
|
// ── Exponential ─────────────────────────────────
|
||||||
|
case 0x074: EXP(); break;
|
||||||
|
case 0x075: LOG(); break;
|
||||||
|
case 0x076: LOGAB(); break;
|
||||||
|
case 0x077: POW(); break;
|
||||||
|
case 0x078: SQRT(); break;
|
||||||
|
case 0x079: ROOT(); break;
|
||||||
|
|
||||||
|
// ── Integer ─────────────────────────────────────
|
||||||
|
case 0x07C: ADC(); break;
|
||||||
|
case 0x07D: SWC(); break;
|
||||||
|
case 0x07E: MWO(); break;
|
||||||
|
case 0x07F: UMO(); break;
|
||||||
|
|
||||||
|
// ── Matrix ──────────────────────────────────────
|
||||||
|
case 0x080: MADD(); break;
|
||||||
|
case 0x081: MSUB(); break;
|
||||||
|
case 0x082: MMUL(); break;
|
||||||
|
case 0x083: MINV(); break;
|
||||||
|
case 0x084: MTRA(); break;
|
||||||
|
case 0x085: MDET(); break;
|
||||||
|
|
||||||
|
// ── Quaternion ──────────────────────────────────
|
||||||
|
case 0x086: QMKA(); break;
|
||||||
|
case 0x087: QMUL(); break;
|
||||||
|
|
||||||
|
// ── SIMD ────────────────────────────────────────
|
||||||
|
case 0x08A: XADD(); break;
|
||||||
|
case 0x08B: XSUB(); break;
|
||||||
|
case 0x08C: XAMA(); break;
|
||||||
|
case 0x08D: XMUL(); break;
|
||||||
|
case 0x08E: XDIV(); break;
|
||||||
|
|
||||||
|
// ── Easter Eggs ─────────────────────────────────
|
||||||
|
case 0x0F0: UPY(); break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace spider
|
||||||
22
src/spider/runtime/math/Quat.cpp
Normal file
22
src/spider/runtime/math/Quat.cpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include "Quat.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
int quatMain() {
|
||||||
|
Quat<double> q1 = { 1.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
Quat<double> q2 = { 0.5f, 0.5f, 0.5f, 0.5f };
|
||||||
|
|
||||||
|
Quat<double> result = quat_multiply(q1, q2); // Returns the result!
|
||||||
|
|
||||||
|
std::cout << "Result: ("
|
||||||
|
<< result.w << ", "
|
||||||
|
<< result.x << ", "
|
||||||
|
<< result.y << ", "
|
||||||
|
<< result.z << ")" << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
24
src/spider/runtime/math/Quat.hpp
Normal file
24
src/spider/runtime/math/Quat.hpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <spider/runtime/common.hpp>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Quat {
|
||||||
|
T w, x, y, z;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplies two quaternions together.
|
||||||
|
*/
|
||||||
|
template<typename T> inline Quat<T> quat_multiply(Quat<T> A, Quat<T> B) {
|
||||||
|
return {
|
||||||
|
B.w * A.w - B.x * A.x - B.y * A.y - B.z * A.z,
|
||||||
|
B.w * A.x + B.x * A.w - B.y * A.z + B.z * A.y,
|
||||||
|
B.w * A.y + B.x * A.z + B.y * A.w - B.z * A.x,
|
||||||
|
B.w * A.z - B.x * A.y + B.y * A.x + B.z * A.w
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct Quaternion {
|
|
||||||
T w, x, y, z;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
Quaternion<T> quat_multiply(Quaternion<T> A, Quaternion<T> B) {
|
|
||||||
return {
|
|
||||||
B.w * A.w - B.x * A.x - B.y * A.y - B.z * A.z,
|
|
||||||
B.w * A.x + B.x * A.w - B.y * A.z + B.z * A.y,
|
|
||||||
B.w * A.y + B.x * A.z + B.y * A.w - B.z * A.x,
|
|
||||||
B.w * A.z - B.x * A.y + B.y * A.x + B.z * A.w
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
Quaternion<double> q1 = {1.0f, 0.0f, 0.0f, 0.0f};
|
|
||||||
Quaternion<double> q2 = {0.5f, 0.5f, 0.5f, 0.5f};
|
|
||||||
|
|
||||||
Quaternion<double> result = quat_multiply(q1, q2); // Returns the result!
|
|
||||||
|
|
||||||
std::cout << "Result: ("
|
|
||||||
<< result.w << ", "
|
|
||||||
<< result.x << ", "
|
|
||||||
<< result.y << ", "
|
|
||||||
<< result.z << ")" << std::endl;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
74
src/spider/runtime/memory/ByteArray.cpp
Normal file
74
src/spider/runtime/memory/ByteArray.cpp
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#include "ByteArray.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
ByteArray::ByteArray(isize length) : _mem(nullptr), _size(length) {
|
||||||
|
if (_size > 0) {
|
||||||
|
_mem = new u8[_size];
|
||||||
|
std::memset(_mem, 0, _size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArray::ByteArray(const ByteArray& other) : _mem(new u8[other._size]), _size(other._size) {
|
||||||
|
std::copy(other._mem, other._mem + _size, _mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArray::ByteArray(ByteArray&& other) noexcept : _mem(other._mem), _size(other._size) {
|
||||||
|
other._mem = nullptr;
|
||||||
|
other._size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArray::~ByteArray() {
|
||||||
|
delete[] _mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArray& ByteArray::operator=(const ByteArray& other) {
|
||||||
|
if (this == &other) return *this; // lock self
|
||||||
|
|
||||||
|
u8* new_mem = new u8[other._size];
|
||||||
|
std::copy(other._mem, other._mem + other._size, new_mem);
|
||||||
|
|
||||||
|
delete[] _mem;
|
||||||
|
_mem = new_mem;
|
||||||
|
_size = other._size;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArray& ByteArray::operator=(ByteArray&& other) noexcept {
|
||||||
|
if (this == &other) return *this; // lock self
|
||||||
|
|
||||||
|
delete[] _mem;
|
||||||
|
|
||||||
|
_mem = other._mem; // time to steal!
|
||||||
|
_size = other._size;
|
||||||
|
|
||||||
|
other._mem = nullptr; // leave as a husk
|
||||||
|
other._size = 0;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8& ByteArray::operator[](isize index) {
|
||||||
|
return _mem[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 ByteArray::operator[](isize index) const {
|
||||||
|
return _mem[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
u8* ByteArray::data() {
|
||||||
|
return _mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8* ByteArray::data() const {
|
||||||
|
return _mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
isize ByteArray::size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
49
src/spider/runtime/memory/ByteArray.hpp
Normal file
49
src/spider/runtime/memory/ByteArray.hpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <spider/runtime/common.hpp>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A general purpose byte array
|
||||||
|
* with RAII semantics.
|
||||||
|
*/
|
||||||
|
class ByteArray {
|
||||||
|
private:
|
||||||
|
|
||||||
|
u8* _mem;
|
||||||
|
isize _size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ByteArray(isize length);
|
||||||
|
|
||||||
|
ByteArray(const ByteArray& other);
|
||||||
|
|
||||||
|
ByteArray(ByteArray&& other) noexcept;
|
||||||
|
|
||||||
|
~ByteArray();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ByteArray& operator=(const ByteArray& other);
|
||||||
|
|
||||||
|
ByteArray& operator=(ByteArray&& other) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
u8& operator[](isize index);
|
||||||
|
|
||||||
|
u8 operator[](isize index) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
u8* data();
|
||||||
|
|
||||||
|
const u8* data() const;
|
||||||
|
|
||||||
|
isize size() const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -111,4 +111,20 @@ namespace spider {
|
|||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8* RAM::begin() {
|
||||||
|
return this->_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8* RAM::end() {
|
||||||
|
return this->_mem + this->_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8* RAM::begin() const {
|
||||||
|
return this->_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8* RAM::end() const {
|
||||||
|
return this->_mem + this->_size;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,16 @@ namespace spider {
|
|||||||
|
|
||||||
u64 size() const;
|
u64 size() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
u8* begin();
|
||||||
|
|
||||||
|
u8* end();
|
||||||
|
|
||||||
|
const u8* begin() const;
|
||||||
|
|
||||||
|
const u8* end() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
253
src/spider/runtime/memory/Types.hpp
Normal file
253
src/spider/runtime/memory/Types.hpp
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <spider/runtime/common.hpp>
|
||||||
|
|
||||||
|
#include <spider/runtime/cpu/Register.hpp>
|
||||||
|
|
||||||
|
#include <spider/runtime/native/machine.hpp>
|
||||||
|
|
||||||
|
#if __cplusplus >= 202002L
|
||||||
|
#include <bit>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(SPIDER_COMPILER_MSVC)
|
||||||
|
#include <cstdlib>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains cross platform type juggling.
|
||||||
|
* Optimized for each case.
|
||||||
|
*
|
||||||
|
* General assumtions is that unsigned and signed
|
||||||
|
* integers are the exact same bit representation.
|
||||||
|
*
|
||||||
|
* Floats to and from integers is the focus when
|
||||||
|
* juggling.
|
||||||
|
*
|
||||||
|
* Additionally, provides help selecting a specific
|
||||||
|
* type from raw bytes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Utilities //
|
||||||
|
|
||||||
|
#if __cplusplus >= 202002L
|
||||||
|
using std::bit_cast;
|
||||||
|
#else
|
||||||
|
template<typename To, typename From>
|
||||||
|
inline To bit_cast(const From& src) {
|
||||||
|
static_assert(sizeof(To) == sizeof(From), "bit_cast size mismatch");
|
||||||
|
To dst;
|
||||||
|
std::memcpy(&dst, &src, sizeof(To));
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline T byteswap(T v) {
|
||||||
|
static_assert(std::is_integral<T>::value, "byteswap requires integral type");
|
||||||
|
|
||||||
|
using U = std::make_unsigned_t<T>;
|
||||||
|
U u = static_cast<U>(v);
|
||||||
|
|
||||||
|
if constexpr (sizeof(T) == 1) {
|
||||||
|
return v;
|
||||||
|
} else if constexpr (sizeof(T) == 2) {
|
||||||
|
|
||||||
|
#if defined(SPIDER_COMPILER_MSVC)
|
||||||
|
u = _byteswap_ushort(u);
|
||||||
|
#elif defined(SPIDER_COMPILER_GCC_LIKE)
|
||||||
|
u = __builtin_bswap16(u);
|
||||||
|
#else
|
||||||
|
u = (u >> 8) | (u << 8);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if constexpr (sizeof(T) == 4) {
|
||||||
|
|
||||||
|
#if defined(SPIDER_COMPILER_MSVC)
|
||||||
|
u = _byteswap_ulong(u);
|
||||||
|
#elif defined(SPIDER_COMPILER_GCC_LIKE)
|
||||||
|
u = __builtin_bswap32(u);
|
||||||
|
#else
|
||||||
|
u =
|
||||||
|
((u & 0x000000FFu) << 24) |
|
||||||
|
((u & 0x0000FF00u) << 8) |
|
||||||
|
((u & 0x00FF0000u) >> 8) |
|
||||||
|
((u & 0xFF000000u) >> 24);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if constexpr (sizeof(T) == 8) {
|
||||||
|
|
||||||
|
#if defined(SPIDER_COMPILER_MSVC)
|
||||||
|
u = _byteswap_uint64(u);
|
||||||
|
#elif defined(SPIDER_COMPILER_GCC_LIKE)
|
||||||
|
u = __builtin_bswap64(u);
|
||||||
|
#else
|
||||||
|
u =
|
||||||
|
((u & 0x00000000000000FFull) << 56) |
|
||||||
|
((u & 0x000000000000FF00ull) << 40) |
|
||||||
|
((u & 0x0000000000FF0000ull) << 24) |
|
||||||
|
((u & 0x00000000FF000000ull) << 8) |
|
||||||
|
((u & 0x000000FF00000000ull) >> 8) |
|
||||||
|
((u & 0x0000FF0000000000ull) >> 24) |
|
||||||
|
((u & 0x00FF000000000000ull) >> 40) |
|
||||||
|
((u & 0xFF00000000000000ull) >> 56);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Generic fallback (rare: non 1/2/4/8-byte types)
|
||||||
|
U result = 0;
|
||||||
|
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||||
|
result |= ((u >> (i * 8)) & 0xFF) << ((sizeof(T) - 1 - i) * 8);
|
||||||
|
}
|
||||||
|
u = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<T>(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store Big Endian //
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void storeBE(T n, u8* bytes) {
|
||||||
|
static_assert(std::is_trivially_copyable<T>::value);
|
||||||
|
#if SPIDER_BIG_ENDIAN
|
||||||
|
std::memcpy(bytes, &n, sizeof(T));
|
||||||
|
#endif
|
||||||
|
#if SPIDER_LITTLE_ENDIAN
|
||||||
|
T tmp = byteswap(n);
|
||||||
|
std::memcpy(bytes, &tmp, sizeof(T));
|
||||||
|
#endif
|
||||||
|
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
|
||||||
|
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||||
|
bytes[i] = static_cast<u8>(
|
||||||
|
(static_cast<std::make_unsigned_t<T>>(n) >> ((sizeof(T) - 1 - i) * 8)) & 0xFF
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void storeBE<f32>(f32 n, u8* bytes) {
|
||||||
|
u32 tmp = bit_cast<u32>(n);
|
||||||
|
storeBE(tmp, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void storeBE<f64>(f64 n, u8* bytes) {
|
||||||
|
u64 tmp = bit_cast<u64>(n);
|
||||||
|
storeBE(tmp, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load Big Endian //
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void loadBE(T* n, const u8* bytes) {
|
||||||
|
static_assert(std::is_trivially_copyable<T>::value);
|
||||||
|
#if SPIDER_BIG_ENDIAN
|
||||||
|
std::memcpy(n, bytes, sizeof(T));
|
||||||
|
#endif
|
||||||
|
#if SPIDER_LITTLE_ENDIAN
|
||||||
|
T tmp;
|
||||||
|
std::memcpy(&tmp, bytes, sizeof(T));
|
||||||
|
*n = byteswap(tmp);
|
||||||
|
#endif
|
||||||
|
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
|
||||||
|
using U = std::make_unsigned_t<T>;
|
||||||
|
U result = 0;
|
||||||
|
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||||
|
result |= static_cast<U>(bytes[i]) << ((sizeof(T) - 1 - i) * 8);
|
||||||
|
}
|
||||||
|
*n = static_cast<T>(result);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void loadBE<f32>(f32* n, const u8* bytes) {
|
||||||
|
u32 tmp;
|
||||||
|
loadBE(&tmp, bytes);
|
||||||
|
*n = bit_cast<f32>(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void loadBE<f64>(f64* n, const u8* bytes) {
|
||||||
|
u64 tmp;
|
||||||
|
loadBE(&tmp, bytes);
|
||||||
|
*n = bit_cast<f64>(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store Little Endian //
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void storeLE(T n, u8* bytes) {
|
||||||
|
static_assert(std::is_trivially_copyable<T>::value);
|
||||||
|
#if SPIDER_BIG_ENDIAN
|
||||||
|
T tmp = byteswap(n);
|
||||||
|
std::memcpy(bytes, &tmp, sizeof(T));
|
||||||
|
#endif
|
||||||
|
#if SPIDER_LITTLE_ENDIAN
|
||||||
|
std::memcpy(bytes, &n, sizeof(T));
|
||||||
|
#endif
|
||||||
|
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
|
||||||
|
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||||
|
bytes[i] = static_cast<u8>(
|
||||||
|
(static_cast<std::make_unsigned_t<T>>(n) >> (i * 8)) & 0xFF
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void storeLE<f32>(f32 n, u8* bytes) {
|
||||||
|
u32 tmp = bit_cast<u32>(n);
|
||||||
|
storeLE(tmp, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void storeLE<f64>(f64 n, u8* bytes) {
|
||||||
|
u64 tmp = bit_cast<u64>(n);
|
||||||
|
storeLE(tmp, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load Little Endian //
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void loadLE(T* n, const u8* bytes) {
|
||||||
|
static_assert(std::is_trivially_copyable<T>::value);
|
||||||
|
#if SPIDER_BIG_ENDIAN
|
||||||
|
T tmp;
|
||||||
|
std::memcpy(&tmp, bytes, sizeof(T));
|
||||||
|
*n = byteswap(tmp);
|
||||||
|
#endif
|
||||||
|
#if SPIDER_LITTLE_ENDIAN
|
||||||
|
std::memcpy(n, bytes, sizeof(T));
|
||||||
|
#endif
|
||||||
|
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
|
||||||
|
using U = std::make_unsigned_t<T>;
|
||||||
|
U result = 0;
|
||||||
|
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||||
|
result |= static_cast<U>(bytes[i]) << (i * 8);
|
||||||
|
}
|
||||||
|
*n = static_cast<T>(result);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void loadLE<f32>(f32* n, const u8* bytes) {
|
||||||
|
u32 tmp;
|
||||||
|
loadLE(&tmp, bytes);
|
||||||
|
*n = bit_cast<f32>(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void loadLE<f64>(f64* n, const u8* bytes) {
|
||||||
|
u64 tmp;
|
||||||
|
loadLE(&tmp, bytes);
|
||||||
|
*n = bit_cast<f64>(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -55,9 +55,9 @@
|
|||||||
|
|
||||||
// ========================================================== //
|
// ========================================================== //
|
||||||
// PACKING //
|
// PACKING //
|
||||||
|
// (not used now) //
|
||||||
// ========================================================== //
|
// ========================================================== //
|
||||||
|
|
||||||
|
|
||||||
// Find out what compiler the user is using
|
// Find out what compiler the user is using
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#define SPIDER_COMPILER_CLANG
|
#define SPIDER_COMPILER_CLANG
|
||||||
@@ -73,8 +73,9 @@
|
|||||||
|
|
||||||
// Macros...
|
// Macros...
|
||||||
#if defined(SPIDER_COMPILER_GCC_LIKE)
|
#if defined(SPIDER_COMPILER_GCC_LIKE)
|
||||||
#define SPIDER_ATTRIBUTE_PACKED __attribute__((packed))
|
#define SPIDER_PACK_BEGIN
|
||||||
#define SPIDER_PACKED_STRUCT(decl) decl SPIDER_ATTRIBUTE_PACKED
|
#define SPIDER_PACK_END
|
||||||
|
#define SPIDER_PACK_STRUCT __attribute__((packed))
|
||||||
|
|
||||||
#elif defined(SPIDER_COMPILER_MSVC)
|
#elif defined(SPIDER_COMPILER_MSVC)
|
||||||
#define SPIDER_BEGIN_PACKED __pragma(pack(push, 1))
|
#define SPIDER_BEGIN_PACKED __pragma(pack(push, 1))
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
#include "InstrReel.hpp"
|
#include "InstrReel.hpp"
|
||||||
|
|
||||||
|
#include <spider/runtime/cpu/CPU.hpp>
|
||||||
|
|
||||||
|
#include <spider/runtime/memory/Types.hpp>
|
||||||
|
|
||||||
namespace spider {
|
namespace spider {
|
||||||
|
|
||||||
|
// Public Interface //
|
||||||
|
|
||||||
InstrReel::InstrReel() {}
|
InstrReel::InstrReel() {}
|
||||||
|
|
||||||
InstrReel::~InstrReel() {}
|
InstrReel::~InstrReel() {}
|
||||||
|
|
||||||
u16 InstrReel::instrAt(u64 ip) const {}
|
|
||||||
|
|
||||||
u8 InstrReel::dataAt(u64 ip) const {}
|
|
||||||
|
|
||||||
u8 InstrReel::feedNext(CPU& cpu) {}
|
|
||||||
|
|
||||||
// Static Utils //
|
// Static Utils //
|
||||||
|
|
||||||
u16 InstrReel::unpackInstr(u16 bcode) {
|
u16 InstrReel::unpackInstr(u16 bcode) {
|
||||||
73
src/spider/runtime/reel/InstrReel.hpp
Normal file
73
src/spider/runtime/reel/InstrReel.hpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <spider/SpiderRuntime.hpp>
|
||||||
|
#include <spider/runtime/memory/ByteArray.hpp>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements an instruction reel.
|
||||||
|
*/
|
||||||
|
class InstrReel {
|
||||||
|
public:
|
||||||
|
|
||||||
|
InstrReel();
|
||||||
|
|
||||||
|
virtual ~InstrReel();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
virtual u8 readU8(u64 ip) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
virtual u16 readU16(u64 ip) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
virtual u32 readU32(u64 ip) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
virtual u64 readU64(u64 ip) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a range of data, and
|
||||||
|
* outputs it.
|
||||||
|
*/
|
||||||
|
virtual void readRange(u64 ip, u8* out, u64 length) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current size of the instructions.
|
||||||
|
*/
|
||||||
|
virtual u64 size() = 0;
|
||||||
|
|
||||||
|
public: // Static Utils //
|
||||||
|
|
||||||
|
static u16 unpackInstr(u16 bcode);
|
||||||
|
|
||||||
|
static u8 unpackAddrMode(u16 bcode);
|
||||||
|
|
||||||
|
static u8 unpackTypeSize(u16 bcode);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
206
src/spider/runtime/reel/InstrReelDyn.cpp
Normal file
206
src/spider/runtime/reel/InstrReelDyn.cpp
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
#include "InstrReelDyn.hpp"
|
||||||
|
|
||||||
|
#include <spider/runtime/memory/Types.hpp>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
InstrReelDyn::InstrReelDyn(u64 length) : _size(length) {
|
||||||
|
// Safe int ceil division
|
||||||
|
growTo((length >> 8) + ((length & 255) != 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrReelDyn::InstrReelDyn(const u8* data, u64 length) {}
|
||||||
|
|
||||||
|
InstrReelDyn::InstrReelDyn(const InstrReelDyn& copy)
|
||||||
|
: _blocks(copy._blocks), _size(copy._size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrReelDyn::InstrReelDyn(InstrReelDyn&& move) noexcept
|
||||||
|
: _blocks(std::move(move._blocks)), _size(std::move(move._size)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrReelDyn::~InstrReelDyn() {
|
||||||
|
// .. //
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrReelDyn& InstrReelDyn::operator=(const InstrReelDyn& copy) {
|
||||||
|
_blocks = copy._blocks;
|
||||||
|
_size = copy._size;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrReelDyn& InstrReelDyn::operator=(InstrReelDyn&& move) noexcept {
|
||||||
|
_blocks = std::move(move._blocks);
|
||||||
|
_size = std::move(move._size);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrReelDyn::growTo(u64 ip) {
|
||||||
|
u64 b_index = (ip >> 8) + 1;
|
||||||
|
while (_blocks.size() < b_index) {
|
||||||
|
_blocks.emplace_back();
|
||||||
|
}
|
||||||
|
if (ip >= _size) _size = ip + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<u64, u8> InstrReelDyn::indexOf(u64 ip) {
|
||||||
|
return { ip >> 8, ip & 0xFF }; // { ip / 256, ip % 256 };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstrReelDyn::continous(u64 ip0, u64 ip1, u64* b_index, u16* s_index) {
|
||||||
|
auto i = indexOf(ip0);
|
||||||
|
*b_index = i.first;
|
||||||
|
*s_index = i.second;
|
||||||
|
return i.first == (ip1 >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Particular Cases
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
u8 InstrReelDyn::readU8(u64 ip) {
|
||||||
|
if (ip + 1 > _size) return 0;
|
||||||
|
auto i = indexOf(ip);
|
||||||
|
return _blocks[i.first].data[i.second];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
u16 InstrReelDyn::readU16(u64 ip) {
|
||||||
|
if (ip + 2 > _size) return 0;
|
||||||
|
|
||||||
|
u16 dat;
|
||||||
|
u64 b_index;
|
||||||
|
u16 s_index;
|
||||||
|
|
||||||
|
if (continous(ip, ip + 1, &b_index, &s_index)) {
|
||||||
|
spider::loadLE(&dat, &_blocks[b_index].data[s_index]);
|
||||||
|
return dat;
|
||||||
|
}
|
||||||
|
|
||||||
|
dat = 0;
|
||||||
|
for (isize i = 0; i < sizeof(dat); i++) {
|
||||||
|
auto& b = _blocks[(b_index + s_index) >> 8];
|
||||||
|
dat |= u16(b.data[s_index++ & 0xFF]) << (i * 8);
|
||||||
|
}
|
||||||
|
return dat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
u32 InstrReelDyn::readU32(u64 ip) {
|
||||||
|
if (ip + 4 > _size) return 0;
|
||||||
|
|
||||||
|
u32 dat;
|
||||||
|
u64 b_index;
|
||||||
|
u16 s_index;
|
||||||
|
|
||||||
|
if (continous(ip, ip + 3, &b_index, &s_index)) {
|
||||||
|
spider::loadLE(&dat, &_blocks[b_index].data[s_index]);
|
||||||
|
return dat;
|
||||||
|
}
|
||||||
|
|
||||||
|
dat = 0;
|
||||||
|
for (isize i = 0; i < sizeof(dat); i++) {
|
||||||
|
auto& b = _blocks[(b_index + s_index) >> 8];
|
||||||
|
dat |= u32(b.data[s_index++ & 0xFF]) << (i * 8);
|
||||||
|
}
|
||||||
|
return dat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
u64 InstrReelDyn::readU64(u64 ip) {
|
||||||
|
if (ip + 8 > _size) return 0;
|
||||||
|
|
||||||
|
u64 dat;
|
||||||
|
u64 b_index;
|
||||||
|
u16 s_index;
|
||||||
|
|
||||||
|
if (continous(ip, ip + 7, &b_index, &s_index)) {
|
||||||
|
spider::loadLE(&dat, &_blocks[b_index].data[s_index]);
|
||||||
|
return dat;
|
||||||
|
}
|
||||||
|
|
||||||
|
dat = 0;
|
||||||
|
for (isize i = 0; i < sizeof(dat); i++) {
|
||||||
|
auto& b = _blocks[(b_index + s_index) >> 8];
|
||||||
|
dat |= u64(b.data[s_index++ & 0xFF]) << (i * 8);
|
||||||
|
}
|
||||||
|
return dat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a range of data, and
|
||||||
|
* outputs it.
|
||||||
|
*/
|
||||||
|
void InstrReelDyn::readRange(u64 ip, u8* out, u64 length) {
|
||||||
|
if (ip + length > _size) {
|
||||||
|
std::memset(out, 0, length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 b_index;
|
||||||
|
u16 s_index;
|
||||||
|
|
||||||
|
if (continous(ip, ip + length, &b_index, &s_index)) {
|
||||||
|
std::memcpy(out, &_blocks[b_index].data[s_index], length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 bytes_read = 0;
|
||||||
|
while (bytes_read < length) {
|
||||||
|
u64 remaining_in_block = 256 - s_index;
|
||||||
|
u64 chunk_size = std::min(remaining_in_block, length - bytes_read);
|
||||||
|
|
||||||
|
// Perform bulk copy for the current segment
|
||||||
|
std::memcpy(out + bytes_read, &_blocks[b_index].data[s_index], chunk_size);
|
||||||
|
|
||||||
|
// Advance pointers
|
||||||
|
bytes_read += chunk_size;
|
||||||
|
b_index++;
|
||||||
|
s_index = 0; // reset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current size of the instructions.
|
||||||
|
*/
|
||||||
|
u64 InstrReelDyn::size() {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutation //
|
||||||
|
|
||||||
|
// TODO!
|
||||||
|
|
||||||
|
void InstrReelDyn::writeU8(u64 ip, u8 dat) {}
|
||||||
|
|
||||||
|
void InstrReelDyn::writeU16(u64 ip, u16 dat) {}
|
||||||
|
|
||||||
|
void InstrReelDyn::writeU32(u64 ip, u32 dat) {}
|
||||||
|
|
||||||
|
void InstrReelDyn::writeU64(u64 ip, u64 dat) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends instruction at the end.
|
||||||
|
*/
|
||||||
|
void InstrReelDyn::append(u16 bc) {}
|
||||||
|
|
||||||
|
}
|
||||||
110
src/spider/runtime/reel/InstrReelDyn.hpp
Normal file
110
src/spider/runtime/reel/InstrReelDyn.hpp
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <spider/runtime/reel/InstrReel.hpp>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements an instruction reel.
|
||||||
|
*/
|
||||||
|
class InstrReelDyn : public InstrReel {
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct ReelBlock {
|
||||||
|
u8 data[256] = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
deque<ReelBlock> _blocks;
|
||||||
|
u64 _size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
InstrReelDyn(u64 length);
|
||||||
|
|
||||||
|
InstrReelDyn(const u8* data, u64 length);
|
||||||
|
|
||||||
|
InstrReelDyn(const InstrReelDyn& copy);
|
||||||
|
|
||||||
|
InstrReelDyn(InstrReelDyn&& move) noexcept;
|
||||||
|
|
||||||
|
virtual ~InstrReelDyn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
InstrReelDyn& operator=(const InstrReelDyn& copy);
|
||||||
|
|
||||||
|
InstrReelDyn& operator=(InstrReelDyn&& move) noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::pair<u64, u8> indexOf(u64 ip);
|
||||||
|
|
||||||
|
bool continous(u64 ip0, u64 ip1, u64* b_index, u16* s_index);
|
||||||
|
|
||||||
|
void growTo(u64 ip);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
virtual u8 readU8(u64 ip) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
virtual u16 readU16(u64 ip) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
virtual u32 readU32(u64 ip) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
virtual u64 readU64(u64 ip) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a range of data, and
|
||||||
|
* outputs it.
|
||||||
|
*/
|
||||||
|
virtual void readRange(u64 ip, u8* out, u64 length) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current size of the instructions.
|
||||||
|
*/
|
||||||
|
virtual u64 size() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void writeU8(u64 ip, u8 dat);
|
||||||
|
|
||||||
|
void writeU16(u64 ip, u16 dat);
|
||||||
|
|
||||||
|
void writeU32(u64 ip, u32 dat);
|
||||||
|
|
||||||
|
void writeU64(u64 ip, u64 dat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends instruction at the end.
|
||||||
|
*/
|
||||||
|
void append(u16 bc);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
0
src/spider/runtime/reel/InstrReelFile.hpp
Normal file
0
src/spider/runtime/reel/InstrReelFile.hpp
Normal file
183
src/spider/runtime/reel/InstrReelFixed.cpp
Normal file
183
src/spider/runtime/reel/InstrReelFixed.cpp
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
#include "InstrReelFixed.hpp"
|
||||||
|
|
||||||
|
#include <spider/runtime/memory/Types.hpp>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
// Constructors & Destructors //
|
||||||
|
|
||||||
|
InstrReelFixed::InstrReelFixed(u64 length)
|
||||||
|
: _mem(nullptr), _size(length) {
|
||||||
|
if (_size > 0) {
|
||||||
|
_mem = new u8[_size];
|
||||||
|
std::memset(_mem, 0, _size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrReelFixed::InstrReelFixed(const u8* data, u64 length)
|
||||||
|
: _mem(nullptr), _size(length) {
|
||||||
|
if (_size > 0) {
|
||||||
|
_mem = new u8[_size];
|
||||||
|
std::copy(data, data + _size, _mem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrReelFixed::InstrReelFixed(const InstrReelFixed& other) {
|
||||||
|
_size = other._size;
|
||||||
|
_mem = new u8[_size];
|
||||||
|
std::copy(other._mem, other._mem + _size, _mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrReelFixed::InstrReelFixed(InstrReelFixed&& other) noexcept {
|
||||||
|
_mem = other._mem;
|
||||||
|
_size = other._size;
|
||||||
|
|
||||||
|
other._mem = nullptr;
|
||||||
|
other._size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrReelFixed::~InstrReelFixed() {
|
||||||
|
delete[] _mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// General Case(s) //
|
||||||
|
|
||||||
|
// Instruction abstraction //
|
||||||
|
|
||||||
|
u8 InstrReelFixed::readU8(u64 ip) {
|
||||||
|
// guard against access
|
||||||
|
if(ip + 1 > _size) return 0;
|
||||||
|
|
||||||
|
// send byte
|
||||||
|
return _mem[ip];
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 InstrReelFixed::readU16(u64 ip) {
|
||||||
|
// guard against access
|
||||||
|
if(ip + 2 > _size) return 0;
|
||||||
|
|
||||||
|
// build a 16-bit big endian number
|
||||||
|
u16 dat;
|
||||||
|
spider::loadLE(&dat, _mem + ip);
|
||||||
|
return dat;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 InstrReelFixed::readU32(u64 ip) {
|
||||||
|
// guard against access
|
||||||
|
if(ip + 4 > _size) return 0;
|
||||||
|
|
||||||
|
// build a 32-bit big endian number
|
||||||
|
u32 dat;
|
||||||
|
spider::loadLE(&dat, _mem + ip);
|
||||||
|
return dat;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 InstrReelFixed::readU64(u64 ip) {
|
||||||
|
// guard against access
|
||||||
|
if(ip + 8 > _size) return 0;
|
||||||
|
|
||||||
|
// build a 64-bit big endian number
|
||||||
|
u64 dat;
|
||||||
|
spider::loadLE(&dat, _mem + ip);
|
||||||
|
return dat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrReelFixed::readRange(u64 ip, u8* out, u64 length) {
|
||||||
|
if(ip + length > _size) {
|
||||||
|
std::memset(out, 0, length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::memcpy(out, _mem + ip, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 InstrReelFixed::size() {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign Operators //
|
||||||
|
|
||||||
|
InstrReelFixed& InstrReelFixed::operator=(const InstrReelFixed& other) {
|
||||||
|
if (this == &other) return *this; // lock self
|
||||||
|
|
||||||
|
u8* new_mem = new u8[other._size];
|
||||||
|
std::copy(other._mem, other._mem + other._size, new_mem);
|
||||||
|
|
||||||
|
delete[] _mem;
|
||||||
|
_mem = new_mem;
|
||||||
|
_size = other._size;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrReelFixed& InstrReelFixed::operator=(InstrReelFixed&& other) noexcept {
|
||||||
|
if (this == &other) return *this; // lock self
|
||||||
|
|
||||||
|
delete[] _mem;
|
||||||
|
|
||||||
|
_mem = other._mem; // steal
|
||||||
|
_size = other._size;
|
||||||
|
|
||||||
|
other._mem = nullptr; // leave as husk
|
||||||
|
other._size = 0;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Misc //
|
||||||
|
|
||||||
|
void InstrReelFixed::writeU8(u64 ip, u8 dat) {
|
||||||
|
if(ip + 1 > _size) return;
|
||||||
|
_mem[ip] = dat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrReelFixed::writeU16(u64 ip, u16 dat) {
|
||||||
|
if(ip + 2 > _size) return;
|
||||||
|
spider::storeLE(dat, _mem + ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrReelFixed::writeU32(u64 ip, u32 dat) {
|
||||||
|
if(ip + 4 > _size) return;
|
||||||
|
spider::storeLE(dat, _mem + ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrReelFixed::writeU64(u64 ip, u64 dat) {
|
||||||
|
if(ip + 8 > _size) return;
|
||||||
|
spider::storeLE(dat, _mem + ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrReelFixed::resize(u64 new_size) {
|
||||||
|
// Special case 1
|
||||||
|
if (new_size == _size) return;
|
||||||
|
|
||||||
|
// Special case 2
|
||||||
|
if (new_size == 0) {
|
||||||
|
delete[] _mem;
|
||||||
|
_mem = nullptr;
|
||||||
|
_size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Allocate the new block
|
||||||
|
u8* new_mem = new u8[new_size];
|
||||||
|
|
||||||
|
// 2. Zero-initialize
|
||||||
|
std::memset(new_mem, 0, new_size);
|
||||||
|
|
||||||
|
// 3. Preserve data
|
||||||
|
// If shrinking, copy 'new_size' bytes. If growing, copy 'old_size' bytes.
|
||||||
|
u64 bytes_to_copy = (new_size < _size) ? new_size : _size;
|
||||||
|
|
||||||
|
// 3.1 Previous size could be zero, where _mem would be null
|
||||||
|
if (_mem != nullptr) {
|
||||||
|
std::copy(_mem, _mem + bytes_to_copy, new_mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Swap and Clean up
|
||||||
|
delete[] _mem;
|
||||||
|
_mem = new_mem;
|
||||||
|
_size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
92
src/spider/runtime/reel/InstrReelFixed.hpp
Normal file
92
src/spider/runtime/reel/InstrReelFixed.hpp
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <spider/runtime/reel/InstrReel.hpp>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements an instruction reel.
|
||||||
|
*/
|
||||||
|
class InstrReelFixed : public InstrReel {
|
||||||
|
private:
|
||||||
|
u8* _mem;
|
||||||
|
u64 _size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
InstrReelFixed(u64 length);
|
||||||
|
|
||||||
|
InstrReelFixed(const u8* data, u64 length);
|
||||||
|
|
||||||
|
InstrReelFixed(const InstrReelFixed& copy);
|
||||||
|
|
||||||
|
InstrReelFixed(InstrReelFixed&& move) noexcept;
|
||||||
|
|
||||||
|
virtual ~InstrReelFixed();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
InstrReelFixed& operator=(const InstrReelFixed& copy);
|
||||||
|
|
||||||
|
InstrReelFixed& operator=(InstrReelFixed&& move) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
virtual u8 readU8(u64 ip) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
virtual u16 readU16(u64 ip) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
virtual u32 readU32(u64 ip) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a byte of data at
|
||||||
|
* the specific location.
|
||||||
|
* Reindexing may occur, continous access
|
||||||
|
* may incurr in less penalties.
|
||||||
|
*/
|
||||||
|
virtual u64 readU64(u64 ip) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a range of data, and
|
||||||
|
* outputs it.
|
||||||
|
*/
|
||||||
|
virtual void readRange(u64 ip, u8* out, u64 length) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current size of the instructions.
|
||||||
|
*/
|
||||||
|
virtual u64 size() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void writeU8(u64 ip, u8 dat);
|
||||||
|
|
||||||
|
void writeU16(u64 ip, u16 dat);
|
||||||
|
|
||||||
|
void writeU32(u64 ip, u32 dat);
|
||||||
|
|
||||||
|
void writeU64(u64 ip, u64 dat);
|
||||||
|
|
||||||
|
void resize(u64 new_size);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
277
src/spider/runtime/util/Terminal.cpp
Normal file
277
src/spider/runtime/util/Terminal.cpp
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
#include "Terminal.hpp"
|
||||||
|
|
||||||
|
#include <spider/runtime/native/distro.hpp>
|
||||||
|
|
||||||
|
#if defined(SPIDER_OS_WINDOWS)
|
||||||
|
#include <conio.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(SPIDER_DISTRO_DESKTOP)
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
// Style //
|
||||||
|
const char* Terminal::RESET = "\033[0m";
|
||||||
|
const char* Terminal::BOLD = "\033[1m";
|
||||||
|
const char* Terminal::ITALIC = "\033[3m";
|
||||||
|
const char* Terminal::FAINT = "\033[2m";
|
||||||
|
const char* Terminal::STRIKE = "\033[9m";
|
||||||
|
|
||||||
|
// Foreground //
|
||||||
|
const char* Terminal::FG_BLACK = "\033[30m"; const char* Terminal::FG_B_BLACK = "\033[90m";
|
||||||
|
const char* Terminal::FG_RED = "\033[31m"; const char* Terminal::FG_B_RED = "\033[91m";
|
||||||
|
const char* Terminal::FG_GREEN = "\033[32m"; const char* Terminal::FG_B_GREEN = "\033[92m";
|
||||||
|
const char* Terminal::FG_YELLOW = "\033[33m"; const char* Terminal::FG_B_YELLOW = "\033[93m";
|
||||||
|
const char* Terminal::FG_BLUE = "\033[34m"; const char* Terminal::FG_B_BLUE = "\033[94m";
|
||||||
|
const char* Terminal::FG_MAGENTA = "\033[35m"; const char* Terminal::FG_B_MAGENTA = "\033[95m";
|
||||||
|
const char* Terminal::FG_CYAN = "\033[36m"; const char* Terminal::FG_B_CYAN = "\033[96m";
|
||||||
|
const char* Terminal::FG_WHITE = "\033[37m"; const char* Terminal::FG_B_WHITE = "\033[97m";
|
||||||
|
|
||||||
|
// Background //
|
||||||
|
const char* Terminal::BG_BLACK = "\033[40m"; const char* Terminal::BG_B_BLACK = "\033[100m";
|
||||||
|
const char* Terminal::BG_RED = "\033[41m"; const char* Terminal::BG_B_RED = "\033[101m";
|
||||||
|
const char* Terminal::BG_GREEN = "\033[42m"; const char* Terminal::BG_B_GREEN = "\033[102m";
|
||||||
|
const char* Terminal::BG_YELLOW = "\033[43m"; const char* Terminal::BG_B_YELLOW = "\033[103m";
|
||||||
|
const char* Terminal::BG_BLUE = "\033[44m"; const char* Terminal::BG_B_BLUE = "\033[104m";
|
||||||
|
const char* Terminal::BG_MAGENTA = "\033[45m"; const char* Terminal::BG_B_MAGENTA = "\033[105m";
|
||||||
|
const char* Terminal::BG_CYAN = "\033[46m"; const char* Terminal::BG_B_CYAN = "\033[106m";
|
||||||
|
const char* Terminal::BG_WHITE = "\033[47m"; const char* Terminal::BG_B_WHITE = "\033[107m";
|
||||||
|
|
||||||
|
Terminal::Terminal() {
|
||||||
|
#if defined(SPIDER_OS_WINDOWS)
|
||||||
|
// Enable UTF-8
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
SetConsoleCP(CP_UTF8);
|
||||||
|
|
||||||
|
// enable vtp
|
||||||
|
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
DWORD dwMode = 0;
|
||||||
|
GetConsoleMode(hOut, &dwMode);
|
||||||
|
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
SetConsoleMode(hOut, dwMode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal::~Terminal() {
|
||||||
|
altbuff(false).style(RESET).cursor(true).flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::style(const std::string_view code) {
|
||||||
|
std::cout << code;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::move(i32 row, i32 col) {
|
||||||
|
std::cout << "\033[" << row << ";" << col << "H";
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::altbuff(bool enable) {
|
||||||
|
std::cout << (enable ? "\033[?1049h" : "\033[?1049l");
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::cls() {
|
||||||
|
std::cout << "\033[2J";
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::scrollRange(i32 start, i32 end) {
|
||||||
|
std::cout << "\033[" << start << ";" << end << "r\033[?6h";
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::undoSRange() {
|
||||||
|
std::cout << "\033[r\033[?6l\033[H";
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::fill(const std::string_view color) {
|
||||||
|
this->style(color);
|
||||||
|
this->cls();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::clearRow(i32 row) {
|
||||||
|
// Move to row, column 1
|
||||||
|
this->move(row, 1);
|
||||||
|
// \033[2K clears the entire line
|
||||||
|
std::cout << "\033[2K";
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::clearRows(i32 start, i32 end) {
|
||||||
|
// Ensure we don't loop infinitely if start > end
|
||||||
|
if (start > end) std::swap(start, end);
|
||||||
|
|
||||||
|
for (i32 i = start; i <= end; ++i) {
|
||||||
|
this->clearRow(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional: Move cursor back to the start of the cleared block
|
||||||
|
this->move(start, 1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::cursor(bool show) {
|
||||||
|
std::cout << (show ? "\033[?25h" : "\033[?25l");
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::drawBox(i32 startRow, i32 startCol, i32 width, i32 height, std::string_view title) {
|
||||||
|
// 1. Draw the top border
|
||||||
|
move(startRow, startCol);
|
||||||
|
std::cout << "┌";
|
||||||
|
for (i32 i = 0; i < width - 2; ++i) std::cout << "─";
|
||||||
|
std::cout << "┐";
|
||||||
|
|
||||||
|
// 2. Draw the sides
|
||||||
|
for (i32 i = 1; i < height - 1; ++i) {
|
||||||
|
move(startRow + i, startCol);
|
||||||
|
std::cout << "│";
|
||||||
|
move(startRow + i, startCol + width - 1);
|
||||||
|
std::cout << "│";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Draw the bottom border
|
||||||
|
move(startRow + height - 1, startCol);
|
||||||
|
std::cout << "└";
|
||||||
|
for (i32 i = 0; i < width - 2; ++i) std::cout << "─";
|
||||||
|
std::cout << "┘";
|
||||||
|
|
||||||
|
// 4. Overlay the title if provided
|
||||||
|
if (!title.empty()) {
|
||||||
|
move(startRow, startCol + (width - title.size() - 2) / 2);
|
||||||
|
std::cout << " " << title << " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout.flush();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::flush() {
|
||||||
|
std::cout << std::flush;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::sink() {
|
||||||
|
std::cin.clear();
|
||||||
|
#if defined(SPIDER_OS_WINDOWS)
|
||||||
|
while (_kbhit()) _getch();
|
||||||
|
#endif
|
||||||
|
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
|
||||||
|
tcflush(STDIN_FILENO, TCIFLUSH);
|
||||||
|
#endif
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<i32, i32> Terminal::getSize() {
|
||||||
|
std::pair<i32, i32> pair;
|
||||||
|
#if defined(SPIDER_OS_WINDOWS)
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||||
|
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
|
||||||
|
pair.first = csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
||||||
|
pair.second = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
|
||||||
|
struct winsize w;
|
||||||
|
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
|
||||||
|
pair.first = w.ws_col;
|
||||||
|
pair.second = w.ws_row;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal& Terminal::wait() {
|
||||||
|
sink();
|
||||||
|
std::cin.get();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 Terminal::getKey() {
|
||||||
|
#if defined(SPIDER_OS_WINDOWS)
|
||||||
|
i32 ch = _getch();
|
||||||
|
if (ch == 0 || ch == 224) {
|
||||||
|
switch (_getch()) {
|
||||||
|
case 72: return Terminal::UP;
|
||||||
|
case 80: return Terminal::DOWN;
|
||||||
|
case 75: return Terminal::LEFT;
|
||||||
|
case 77: return Terminal::RIGHT;
|
||||||
|
default: return Terminal::UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch == 13) return Terminal::ENTER;
|
||||||
|
if (ch == 27) return Terminal::ESC;
|
||||||
|
if (ch == 8) return Terminal::BACKSPACE;
|
||||||
|
return Terminal::UNKNOWN;
|
||||||
|
#endif
|
||||||
|
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
|
||||||
|
struct termios oldt, newt;
|
||||||
|
tcgetattr(STDIN_FILENO, &oldt);
|
||||||
|
newt = oldt;
|
||||||
|
newt.c_lflag &= ~(ICANON | ECHO);
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||||
|
|
||||||
|
u8 result = Terminal::UNKNOWN;
|
||||||
|
int ch = getchar();
|
||||||
|
|
||||||
|
if (ch == 27) { // Potential Escape Sequence
|
||||||
|
// Use a small timeout or check if more chars are in buffer
|
||||||
|
// to distinguish between 'Esc' key and 'Arrow' sequence
|
||||||
|
// Another Win for the Win API
|
||||||
|
struct timeval tv = { 0, 10000 }; // 10ms wait
|
||||||
|
fd_set fds;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(STDIN_FILENO, &fds);
|
||||||
|
|
||||||
|
if (select(1, &fds, NULL, NULL, &tv) > 0) {
|
||||||
|
if (getchar() == '[') {
|
||||||
|
switch (getchar()) {
|
||||||
|
case 'A': result = Terminal::UP; break;
|
||||||
|
case 'B': result = Terminal::DOWN; break;
|
||||||
|
case 'D': result = Terminal::LEFT; break;
|
||||||
|
case 'C': result = Terminal::RIGHT; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = Terminal::ESC;
|
||||||
|
}
|
||||||
|
} else if (ch == 10) result = Terminal::ENTER;
|
||||||
|
else if (ch == 127) result = Terminal::BACKSPACE;
|
||||||
|
else result = (u8)ch;
|
||||||
|
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 Terminal::getKeyNb() {
|
||||||
|
#if defined(SPIDER_OS_WINDOWS)
|
||||||
|
if (_kbhit()) return getKey();
|
||||||
|
return Terminal::UNKNOWN;
|
||||||
|
#endif
|
||||||
|
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
|
||||||
|
struct timeval tv = { 0, 0 };
|
||||||
|
fd_set fds;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(STDIN_FILENO, &fds);
|
||||||
|
// select() returns > 0 if there is data to read
|
||||||
|
if (select(1, &fds, NULL, NULL, &tv) > 0) {
|
||||||
|
return getKey();
|
||||||
|
}
|
||||||
|
return Terminal::UNKNOWN;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
176
src/spider/runtime/util/Terminal.hpp
Normal file
176
src/spider/runtime/util/Terminal.hpp
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <spider/runtime/common.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
class Terminal {
|
||||||
|
public:
|
||||||
|
|
||||||
|
static const char* RESET;
|
||||||
|
static const char* BOLD;
|
||||||
|
static const char* ITALIC;
|
||||||
|
static const char* FAINT;
|
||||||
|
static const char* STRIKE;
|
||||||
|
|
||||||
|
static const char* FG_BLACK; static const char* FG_B_BLACK;
|
||||||
|
static const char* FG_RED; static const char* FG_B_RED;
|
||||||
|
static const char* FG_GREEN; static const char* FG_B_GREEN;
|
||||||
|
static const char* FG_YELLOW; static const char* FG_B_YELLOW;
|
||||||
|
static const char* FG_BLUE; static const char* FG_B_BLUE;
|
||||||
|
static const char* FG_MAGENTA; static const char* FG_B_MAGENTA;
|
||||||
|
static const char* FG_CYAN; static const char* FG_B_CYAN;
|
||||||
|
static const char* FG_WHITE; static const char* FG_B_WHITE;
|
||||||
|
|
||||||
|
static const char* BG_BLACK; static const char* BG_B_BLACK;
|
||||||
|
static const char* BG_RED; static const char* BG_B_RED;
|
||||||
|
static const char* BG_GREEN; static const char* BG_B_GREEN;
|
||||||
|
static const char* BG_YELLOW; static const char* BG_B_YELLOW;
|
||||||
|
static const char* BG_BLUE; static const char* BG_B_BLUE;
|
||||||
|
static const char* BG_MAGENTA; static const char* BG_B_MAGENTA;
|
||||||
|
static const char* BG_CYAN; static const char* BG_B_CYAN;
|
||||||
|
static const char* BG_WHITE; static const char* BG_B_WHITE;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Key Definitions (ASCII OK) //
|
||||||
|
static constexpr const u8 UP = 0x80;
|
||||||
|
static constexpr const u8 DOWN = 0x81;
|
||||||
|
static constexpr const u8 LEFT = 0x82;
|
||||||
|
static constexpr const u8 RIGHT = 0x83;
|
||||||
|
static constexpr const u8 ENTER = 0x84;
|
||||||
|
static constexpr const u8 ESC = 0x85;
|
||||||
|
static constexpr const u8 BACKSPACE = 0x86;
|
||||||
|
static constexpr const u8 UNKNOWN = 0xFF;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Terminal();
|
||||||
|
|
||||||
|
~Terminal();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a style
|
||||||
|
*/
|
||||||
|
Terminal& style(const std::string_view code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills the screen with a specific background color.
|
||||||
|
* @param color The background color constant (e.g., Terminal::BG_BLUE)
|
||||||
|
*/
|
||||||
|
Terminal& fill(const std::string_view color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the cursor.
|
||||||
|
*/
|
||||||
|
Terminal& move(i32 row, i32 col);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the screen
|
||||||
|
*/
|
||||||
|
Terminal& cls();
|
||||||
|
|
||||||
|
Terminal& altbuff(bool enable);
|
||||||
|
|
||||||
|
Terminal& scrollRange(i32 start, i32 end);
|
||||||
|
|
||||||
|
Terminal& undoSRange();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears a specific row.
|
||||||
|
* @param row The 1-based index of the row to clear.
|
||||||
|
*/
|
||||||
|
Terminal& clearRow(i32 row);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears a range of rows (inclusive).
|
||||||
|
* @param start The first row.
|
||||||
|
* @param end The last row.
|
||||||
|
*/
|
||||||
|
Terminal& clearRows(i32 start, i32 end);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows / Hides the cursor.
|
||||||
|
*/
|
||||||
|
Terminal& cursor(bool show);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Terminal& drawBox(i32 startRow, i32 startCol, i32 width, i32 height, std::string_view title);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flushes the output buffer
|
||||||
|
*/
|
||||||
|
Terminal& flush();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the input buffer.
|
||||||
|
* Useful for some specific input cases
|
||||||
|
*/
|
||||||
|
Terminal& sink();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Terminal& wait();
|
||||||
|
|
||||||
|
u8 getKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get key non blocking
|
||||||
|
*/
|
||||||
|
u8 getKeyNb();
|
||||||
|
|
||||||
|
std::pair<i32, i32> getSize();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Terminal& print(const T& msg) {
|
||||||
|
std::cout << msg;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Terminal& println(const T& msg) {
|
||||||
|
std::cout << msg << "\n";
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Terminal& print_center(i32 width, const T& msg) {
|
||||||
|
// to string
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << msg;
|
||||||
|
std::string s = oss.str();
|
||||||
|
|
||||||
|
// then print
|
||||||
|
if (s.length() >= isize(width)) {
|
||||||
|
std::cout << s;
|
||||||
|
} else {
|
||||||
|
i32 total_padding = width - s.length();
|
||||||
|
i32 left_padding = total_padding / 2;
|
||||||
|
std::cout << std::string(left_padding, ' ');
|
||||||
|
std::cout << s;
|
||||||
|
std::cout << std::string(total_padding - left_padding, ' ');
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Terminal& read(T& var) {
|
||||||
|
std::cin >> var;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user