Compare commits
44 Commits
061b297b5c
...
easter-egg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdf14cf545 | ||
|
|
c3c94583f4 | ||
|
|
1fe555aaba | ||
| 7155ad8d5a | |||
| 0449074ef6 | |||
| 484c2a6afe | |||
| 6f8a9d80f2 | |||
| 36889e160b | |||
| 4e1a601175 | |||
|
|
f82aa627c4 | ||
|
|
7d3781681d | ||
| 6ac82b47e7 | |||
| 48785b6a94 | |||
| c8bfdf44b6 | |||
| eba69f767e | |||
| 67ed4a7fc4 | |||
| 0015387d60 | |||
| 15bf03097f | |||
| 43f5d26b3d | |||
| f0148dbe45 | |||
| b397371a53 | |||
| aabcfc6f0c | |||
| 41dd2b87b4 | |||
| 3d80b690c4 | |||
| a077c084a2 | |||
| 38006fe19a | |||
| 6895309679 | |||
| 08e994ad44 | |||
| 2f38eb38b8 | |||
| 5f342991b0 | |||
| a5ffb69565 | |||
| 8697b44f53 | |||
| c6c63d6391 | |||
| c6fdb59791 | |||
|
|
291aa0a949 | ||
| e24e8dfe2d | |||
| 1c971a4e22 | |||
| 4a659b5f0d | |||
| 3a6fc6cfb9 | |||
| d4a1d5ad94 | |||
| da1c090f19 | |||
| b4560c208f | |||
| 3845ebe6fd | |||
| 9feef38410 |
@@ -16,107 +16,107 @@ constexpr u8 ADDR_MODE_MASKS[][2] = {
|
||||
{ 0x1E, 0x00 }, // FIR
|
||||
{ 0x1E, 0x00 }, // FZR
|
||||
{ 0x1E, 0x1F }, // LSR
|
||||
{ 0x00, 0x00 }, // FVR
|
||||
{ 0x00, 0x00 }, // MOV
|
||||
{ 0x00, 0x00 }, // MOR
|
||||
{ 0x04, 0x00 }, // FVR
|
||||
{ 0x1E, 0xFF }, // MOV
|
||||
{ 0x04, 0x04 }, // MOR
|
||||
{ 0x00, 0x00 }, // AMOV
|
||||
{ 0x04, 0x04 }, // SWP
|
||||
{ 0x04, 0x00 }, // AHM
|
||||
{ 0x00, 0x00 }, // COM
|
||||
{ 0x00, 0x00 }, // NEG
|
||||
{ 0x00, 0x00 }, // EXS
|
||||
{ 0x00, 0x00 }, // INC
|
||||
{ 0x00, 0x00 }, // DEC
|
||||
{ 0x00, 0x00 }, // ADD
|
||||
{ 0x00, 0x00 }, // SUB
|
||||
{ 0x00, 0x00 }, // MUL
|
||||
{ 0x00, 0x00 }, // UMUL
|
||||
{ 0x00, 0x00 }, // DIV
|
||||
{ 0x00, 0x00 }, // UDIV
|
||||
{ 0x00, 0x00 }, // MOD
|
||||
{ 0x00, 0x00 }, // UMOD
|
||||
{ 0x00, 0x00 }, // DMOD
|
||||
{ 0x00, 0x00 }, // UDMD
|
||||
{ 0x00, 0x00 }, // FBT
|
||||
{ 0x00, 0x00 }, // STB
|
||||
{ 0x00, 0x00 }, // CRB
|
||||
{ 0x00, 0x00 }, // TSB
|
||||
{ 0x00, 0x00 }, // BOOL
|
||||
{ 0x00, 0x00 }, // NOT
|
||||
{ 0x00, 0x00 }, // AND
|
||||
{ 0x00, 0x00 }, // OR
|
||||
{ 0x00, 0x00 }, // XOR
|
||||
{ 0x00, 0x00 }, // SHL
|
||||
{ 0x00, 0x00 }, // SHR
|
||||
{ 0x00, 0x00 }, // SSR
|
||||
{ 0x00, 0x00 }, // ROL
|
||||
{ 0x00, 0x00 }, // ROR
|
||||
{ 0x00, 0x00 }, // CNT
|
||||
{ 0x00, 0x00 }, // EQ
|
||||
{ 0x00, 0x00 }, // NE
|
||||
{ 0x00, 0x00 }, // GT
|
||||
{ 0x00, 0x00 }, // GE
|
||||
{ 0x00, 0x00 }, // LT
|
||||
{ 0x00, 0x00 }, // LE
|
||||
{ 0x00, 0x00 }, // JMP
|
||||
{ 0x00, 0x00 }, // JEQ
|
||||
{ 0x00, 0x00 }, // JNE
|
||||
{ 0x00, 0x00 }, // JIF
|
||||
{ 0x00, 0x00 }, // JMR
|
||||
{ 0x00, 0x00 }, // JER
|
||||
{ 0x00, 0x00 }, // JNR
|
||||
{ 0x00, 0x00 }, // JIR
|
||||
{ 0x00, 0x00 }, // SFB
|
||||
{ 0x00, 0x00 }, // LFB
|
||||
{ 0x00, 0x00 }, // JUF
|
||||
{ 0x00, 0x00 }, // JUR
|
||||
{ 0x00, 0x00 }, // PUSH
|
||||
{ 0x00, 0x00 }, // POP
|
||||
{ 0x00, 0x00 }, // ALLOC
|
||||
{ 0x00, 0x00 }, // HFREE
|
||||
{ 0x00, 0x00 }, // CALL
|
||||
{ 0xFF, 0x00 }, // COM
|
||||
{ 0xFF, 0x00 }, // NEG
|
||||
{ 0xFF, 0x00 }, // EXS
|
||||
{ 0xFF, 0x00 }, // INC
|
||||
{ 0xFF, 0x00 }, // DEC
|
||||
{ 0x1E, 0xFF }, // ADD
|
||||
{ 0x1E, 0xFF }, // SUB
|
||||
{ 0x1E, 0xFF }, // MUL
|
||||
{ 0x1E, 0xFF }, // UMUL
|
||||
{ 0x1E, 0xFF }, // DIV
|
||||
{ 0x1E, 0xFF }, // UDIV
|
||||
{ 0x1E, 0xFF }, // MOD
|
||||
{ 0x1E, 0xFF }, // UMOD
|
||||
{ 0x1E, 0xFF }, // DMOD
|
||||
{ 0x1E, 0xFF }, // UDMD
|
||||
{ 0xFF, 0x00 }, // FBT
|
||||
{ 0x1E, 0xFF }, // STB
|
||||
{ 0x1E, 0xFF }, // CRB
|
||||
{ 0x1E, 0xFF }, // TSB
|
||||
{ 0xFF, 0x00 }, // BOOL
|
||||
{ 0xFF, 0x00 }, // NOT
|
||||
{ 0x1E, 0xFF }, // AND
|
||||
{ 0x1E, 0xFF }, // OR
|
||||
{ 0x1E, 0xFF }, // XOR
|
||||
{ 0x1E, 0xFF }, // SHL
|
||||
{ 0x1E, 0xFF }, // SHR
|
||||
{ 0x1E, 0xFF }, // SSR
|
||||
{ 0x1E, 0xFF }, // ROL
|
||||
{ 0x1E, 0xFF }, // ROR
|
||||
{ 0xFF, 0x00 }, // CNT
|
||||
{ 0x1E, 0xFF }, // EQ
|
||||
{ 0x1E, 0xFF }, // NE
|
||||
{ 0x1E, 0xFF }, // GT
|
||||
{ 0x1E, 0xFF }, // GE
|
||||
{ 0x1E, 0xFF }, // LT
|
||||
{ 0x1E, 0xFF }, // LE
|
||||
{ 0xFF, 0x00 }, // JMP
|
||||
{ 0xFF, 0x00 }, // JEQ
|
||||
{ 0xFF, 0x00 }, // JNE
|
||||
{ 0x1E, 0xFF }, // JIF
|
||||
{ 0xFF, 0x00 }, // JMR
|
||||
{ 0xFF, 0x00 }, // JER
|
||||
{ 0xFF, 0x00 }, // JNR
|
||||
{ 0x1E, 0xFF }, // JIR
|
||||
{ 0x1E, 0xFF }, // SFB
|
||||
{ 0x1E, 0xFF }, // LFB
|
||||
{ 0x1E, 0xFF }, // JUF
|
||||
{ 0x1E, 0xFF }, // JUR
|
||||
{ 0xFF, 0x00 }, // PUSH
|
||||
{ 0xFF, 0x00 }, // POP
|
||||
{ 0xFF, 0x00 }, // ALLOC
|
||||
{ 0xFF, 0x00 }, // HFREE
|
||||
{ 0xFF, 0x00 }, // CALL
|
||||
{ 0x00, 0x00 }, // RET
|
||||
{ 0x00, 0x00 }, // EDI
|
||||
{ 0x00, 0x00 }, // SHSS
|
||||
{ 0x00, 0x00 }, // FLI
|
||||
{ 0x00, 0x00 }, // FNEG
|
||||
{ 0x00, 0x00 }, // FADD
|
||||
{ 0x00, 0x00 }, // FSUB
|
||||
{ 0x00, 0x00 }, // FMUL
|
||||
{ 0x00, 0x00 }, // FDIV
|
||||
{ 0x00, 0x00 }, // FMOD
|
||||
{ 0x00, 0x00 }, // FDMOD
|
||||
{ 0x00, 0x00 }, // FEPS
|
||||
{ 0x00, 0x00 }, // FEEP
|
||||
{ 0x00, 0x00 }, // FEQ
|
||||
{ 0x00, 0x00 }, // FNE
|
||||
{ 0x00, 0x00 }, // FGT
|
||||
{ 0x00, 0x00 }, // FGE
|
||||
{ 0x00, 0x00 }, // FLT
|
||||
{ 0x00, 0x00 }, // FLE
|
||||
{ 0x00, 0x00 }, // F2D
|
||||
{ 0x00, 0x00 }, // D2F
|
||||
{ 0x00, 0x00 }, // I2F
|
||||
{ 0x00, 0x00 }, // I2D
|
||||
{ 0x00, 0x00 }, // L2F
|
||||
{ 0x00, 0x00 }, // L2D
|
||||
{ 0x00, 0x00 }, // F2I
|
||||
{ 0x00, 0x00 }, // F2L
|
||||
{ 0x00, 0x00 }, // D2I
|
||||
{ 0x00, 0x00 }, // D2L
|
||||
{ 0x00, 0x00 }, // SIN
|
||||
{ 0x00, 0x00 }, // COS
|
||||
{ 0x00, 0x00 }, // TAN
|
||||
{ 0x00, 0x00 }, // ASIN
|
||||
{ 0x00, 0x00 }, // ACOS
|
||||
{ 0x00, 0x00 }, // ATAN
|
||||
{ 0x00, 0x00 }, // ATAN2
|
||||
{ 0x00, 0x00 }, // EXP
|
||||
{ 0x00, 0x00 }, // LOG
|
||||
{ 0x00, 0x00 }, // LOGAB
|
||||
{ 0x00, 0x00 }, // POW
|
||||
{ 0x00, 0x00 }, // SQRT
|
||||
{ 0x00, 0x00 }, // ROOT
|
||||
{ 0xFF, 0x00 }, // EDI
|
||||
{ 0xFF, 0x00 }, // SHSS
|
||||
{ 0xFF, 0x00 }, // FLI
|
||||
{ 0xFF, 0x00 }, // FNEG
|
||||
{ 0x1E, 0xFF }, // FADD
|
||||
{ 0x1E, 0xFF }, // FSUB
|
||||
{ 0x1E, 0xFF }, // FMUL
|
||||
{ 0x1E, 0xFF }, // FDIV
|
||||
{ 0x1E, 0xFF }, // FMOD
|
||||
{ 0x1E, 0xFF }, // FDMOD
|
||||
{ 0xFF, 0x00 }, // FEPS
|
||||
{ 0xFF, 0x00 }, // FEEP
|
||||
{ 0x1E, 0xFF }, // FEQ
|
||||
{ 0x1E, 0xFF }, // FNE
|
||||
{ 0x1E, 0xFF }, // FGT
|
||||
{ 0x1E, 0xFF }, // FGE
|
||||
{ 0x1E, 0xFF }, // FLT
|
||||
{ 0x1E, 0xFF }, // FLE
|
||||
{ 0xFF, 0x00 }, // F2D
|
||||
{ 0xFF, 0x00 }, // D2F
|
||||
{ 0xFF, 0x00 }, // I2F
|
||||
{ 0xFF, 0x00 }, // I2D
|
||||
{ 0xFF, 0x00 }, // L2F
|
||||
{ 0xFF, 0x00 }, // L2D
|
||||
{ 0xFF, 0x00 }, // F2I
|
||||
{ 0xFF, 0x00 }, // F2L
|
||||
{ 0xFF, 0x00 }, // D2I
|
||||
{ 0xFF, 0x00 }, // D2L
|
||||
{ 0xFF, 0x00 }, // SIN
|
||||
{ 0xFF, 0x00 }, // COS
|
||||
{ 0xFF, 0x00 }, // TAN
|
||||
{ 0xFF, 0x00 }, // ASIN
|
||||
{ 0xFF, 0x00 }, // ACOS
|
||||
{ 0xFF, 0x00 }, // ATAN
|
||||
{ 0x1E, 0xFF }, // ATAN2
|
||||
{ 0xFF, 0x00 }, // EXP
|
||||
{ 0xFF, 0x00 }, // LOG
|
||||
{ 0x1E, 0xFF }, // LOGAB
|
||||
{ 0x1E, 0xFF }, // POW
|
||||
{ 0xFF, 0x00 }, // SQRT
|
||||
{ 0x1E, 0xFF }, // ROOT
|
||||
{ 0x00, 0x00 }, // ADC
|
||||
{ 0x00, 0x00 }, // SWC
|
||||
{ 0x00, 0x00 }, // MWO
|
||||
@@ -127,6 +127,8 @@ constexpr u8 ADDR_MODE_MASKS[][2] = {
|
||||
{ 0x00, 0x00 }, // MINV
|
||||
{ 0x00, 0x00 }, // MTRA
|
||||
{ 0x00, 0x00 }, // MDET
|
||||
{ 0x00, 0x00 }, // QMKA
|
||||
{ 0x00, 0x00 }, // QMUL
|
||||
{ 0x00, 0x00 }, // XADD
|
||||
{ 0x00, 0x00 }, // XSUB
|
||||
{ 0x00, 0x00 }, // XAMA
|
||||
@@ -140,18 +142,18 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
|
||||
0x00, // NOP
|
||||
0x00, // SPDR
|
||||
0x01, // MMODE
|
||||
0x0F, // INT
|
||||
0x0C, // LRV
|
||||
0x0F, // FSR
|
||||
0x0F, // FIR
|
||||
0x0F, // FZR
|
||||
0x0F, // LSR
|
||||
0x0F, // FVR
|
||||
0x00, // MOV
|
||||
0x00, // MOR
|
||||
0x00, // AMOV
|
||||
0x00, // SWP
|
||||
0x0F, // AHM
|
||||
0x08, // INT
|
||||
0x08, // LRV
|
||||
0x08, // FSR
|
||||
0x08, // FIR
|
||||
0x08, // FZR
|
||||
0x08, // LSR
|
||||
0x08, // FVR
|
||||
0x0F, // MOV
|
||||
0x08, // MOR
|
||||
0x08, // AMOV
|
||||
0x08, // SWP
|
||||
0x08, // AHM
|
||||
0x0F, // COM
|
||||
0x0F, // NEG
|
||||
0x0F, // EXS
|
||||
@@ -208,22 +210,22 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
|
||||
0x0F, // RET
|
||||
0x0F, // EDI
|
||||
0x0F, // SHSS
|
||||
0x00, // FLI
|
||||
0x00, // FNEG
|
||||
0x00, // FADD
|
||||
0x00, // FSUB
|
||||
0x00, // FMUL
|
||||
0x00, // FDIV
|
||||
0x00, // FMOD
|
||||
0x00, // FDMOD
|
||||
0x00, // FEPS
|
||||
0x00, // FEEP
|
||||
0x00, // FEQ
|
||||
0x00, // FNE
|
||||
0x00, // FGT
|
||||
0x00, // FGE
|
||||
0x00, // FLT
|
||||
0x00, // FLE
|
||||
0x0C, // FLI
|
||||
0x0C, // FNEG
|
||||
0x0C, // FADD
|
||||
0x0C, // FSUB
|
||||
0x0C, // FMUL
|
||||
0x0C, // FDIV
|
||||
0x0C, // FMOD
|
||||
0x0C, // FDMOD
|
||||
0x0C, // FEPS
|
||||
0x0C, // FEEP
|
||||
0x0C, // FEQ
|
||||
0x0C, // FNE
|
||||
0x0C, // FGT
|
||||
0x0C, // FGE
|
||||
0x0C, // FLT
|
||||
0x0C, // FLE
|
||||
0x00, // F2D
|
||||
0x00, // D2F
|
||||
0x00, // I2F
|
||||
@@ -234,19 +236,19 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
|
||||
0x00, // F2L
|
||||
0x00, // D2I
|
||||
0x00, // D2L
|
||||
0x00, // SIN
|
||||
0x00, // COS
|
||||
0x00, // TAN
|
||||
0x00, // ASIN
|
||||
0x00, // ACOS
|
||||
0x00, // ATAN
|
||||
0x00, // ATAN2
|
||||
0x00, // EXP
|
||||
0x00, // LOG
|
||||
0x00, // LOGAB
|
||||
0x00, // POW
|
||||
0x00, // SQRT
|
||||
0x00, // ROOT
|
||||
0x0C, // SIN
|
||||
0x0C, // COS
|
||||
0x0C, // TAN
|
||||
0x0C, // ASIN
|
||||
0x0C, // ACOS
|
||||
0x0C, // ATAN
|
||||
0x0C, // ATAN2
|
||||
0x0C, // EXP
|
||||
0x0C, // LOG
|
||||
0x0C, // LOGAB
|
||||
0x0C, // POW
|
||||
0x0C, // SQRT
|
||||
0x0C, // ROOT
|
||||
0x00, // ADC
|
||||
0x00, // SWC
|
||||
0x00, // MWO
|
||||
@@ -257,6 +259,8 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
|
||||
0x00, // MINV
|
||||
0x00, // MTRA
|
||||
0x00, // MDET
|
||||
0x00, // QMKA
|
||||
0x00, // QMUL
|
||||
0x00, // XADD
|
||||
0x00, // XSUB
|
||||
0x00, // XAMA
|
||||
|
||||
Binary file not shown.
12
makefile
12
makefile
@@ -14,8 +14,16 @@ OBJEXT := o
|
||||
|
||||
#Flags, Libraries and Includes
|
||||
ROOT := ./
|
||||
CFLAGS := -Wall -std=c++20 -DSPIDER_COMPILING
|
||||
LFLAGS := -Wall -std=c++20 -static
|
||||
CFLAGS := -std=c++20 -O2 \
|
||||
-Wall -Werror -Wextra \
|
||||
-Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align \
|
||||
-Wunused -Woverloaded-virtual -Wconversion \
|
||||
-Wsign-conversion -Wnull-dereference -Wdouble-promotion \
|
||||
-Wformat=2 -Wimplicit-fallthrough -Wsuggest-override \
|
||||
-Wextra-semi -Wduplicated-cond -Wduplicated-branches \
|
||||
-Wlogical-op -Wuseless-cast
|
||||
LFLAGS := -std=c++20 -static-libstdc++ -static-libgcc \
|
||||
-Wl,--fatal-warnings -Wl,--warn-common
|
||||
LIB :=
|
||||
INC := -I./src/
|
||||
|
||||
|
||||
244
pygen.ipynb
244
pygen.ipynb
@@ -15,7 +15,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 1,
|
||||
"id": "b0fcd533",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -68,7 +68,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 2,
|
||||
"id": "b33de8ac",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -144,7 +144,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": 4,
|
||||
"id": "58645013",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -152,7 +152,7 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Real instructions : 126\n",
|
||||
"Real instructions : 128\n",
|
||||
"Reserved slots : 14\n",
|
||||
"Duplicate check : PASSED\n",
|
||||
"\n",
|
||||
@@ -163,13 +163,14 @@
|
||||
"Bit Wise 14\n",
|
||||
"Boolean 12\n",
|
||||
"Branch 12\n",
|
||||
"Casts 10\n",
|
||||
"Floating Point 10\n",
|
||||
"Casts 10\n",
|
||||
"Memory 9\n",
|
||||
"Trigonometric 7\n",
|
||||
"Exponential 6\n",
|
||||
"Matrix 6\n",
|
||||
"SIMD 5\n",
|
||||
"Quaternion 2\n",
|
||||
"Easter Eggs 1\n",
|
||||
"\n",
|
||||
"First 5 instructions:\n",
|
||||
@@ -177,8 +178,8 @@
|
||||
"0 000 NOP System 0 00 00\n",
|
||||
"1 001 SPDR System 0 00 00\n",
|
||||
"2 002 MMODE System 1 05 01\n",
|
||||
"3 003 INT System 1 1F 0F\n",
|
||||
"4 004 LRV System 1 1F 0C\n"
|
||||
"3 003 INT System 1 1F 08\n",
|
||||
"4 004 LRV System 1 1F 08\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -214,6 +215,7 @@
|
||||
" 'dis', # addressing mode: Displaced\n",
|
||||
" 'addr_mask_1', # accepted addressing mode mask for param 1\n",
|
||||
" 'addr_mask_2', # accepted addressing mode mask for param 2\n",
|
||||
" 'ignores_addrm',# whether the instruction ignores addressing modes\n",
|
||||
" 'B', # type size: Byte (1 byte) supported?\n",
|
||||
" 'S', # type size: Short (2 bytes) supported?\n",
|
||||
" 'I', # type size: Int (4 bytes) supported?\n",
|
||||
@@ -221,6 +223,7 @@
|
||||
" 'F', # type size: Float supported?\n",
|
||||
" 'D', # type size: Double supported?\n",
|
||||
" 'type_mask', # combined type size mask as hex string\n",
|
||||
" 'expensive', # marks computationally expensive instructions\n",
|
||||
" 'operation', # human-readable description of what the instruction does\n",
|
||||
" 'skip_2', # trailing empty column\n",
|
||||
"]\n",
|
||||
@@ -280,7 +283,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"execution_count": 5,
|
||||
"id": "452bc76c",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -289,7 +292,7 @@
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Masks written to: .//autogen/InstructionMasks.hpp\n",
|
||||
"Lines generated : 268\n"
|
||||
"Lines generated : 272\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -354,7 +357,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"execution_count": 6,
|
||||
"id": "5aaebef0",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -362,7 +365,7 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Instructions formatted: 126\n",
|
||||
"Instructions formatted: 128\n",
|
||||
"\n",
|
||||
"--- Preview (first 2 instructions) ---\n",
|
||||
" // [System] 0x000 — NOP: No Operation\n",
|
||||
@@ -377,7 +380,7 @@
|
||||
"\n",
|
||||
"\n",
|
||||
"CPU.hpp updated successfully at: .//src//spider/runtime/cpu/CPU.hpp\n",
|
||||
"Total lines in updated file: 674\n"
|
||||
"Total lines in updated file: 883\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -445,6 +448,221 @@
|
||||
"print(f'\\nCPU.hpp updated successfully at: {CPU_HPP_PATH}')\n",
|
||||
"print(f'Total lines in updated file: {len(updated.splitlines())}')\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"id": "instrmap_gen",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"InstrMap.cpp written to: .//src//spider/runtime/instr/InstrMap.cpp\n",
|
||||
" Size : 34,157 bytes\n",
|
||||
" Array entries : 512 (128 populated, 384 nullptr)\n",
|
||||
" Switch cases : 128\n",
|
||||
" Line endings : LF-only verified\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# ── Generate InstrMap.cpp ────────────────────────────────────────────────────\n",
|
||||
"# Produces two dispatch implementations in one file:\n",
|
||||
"# 1. CPUInstr InstrMap[512] — array of member-function pointers\n",
|
||||
"# 2. void CPU::execute(u16) — switch/case version\n",
|
||||
"#\n",
|
||||
"# Both use UPPERCASE method names matching the mnemonic column.\n",
|
||||
"\n",
|
||||
"TABLE_SIZE = 512 # 9-bit opcode space\n",
|
||||
"\n",
|
||||
"# Build opcode -> mnemonic lookup from the cleaned instruction DataFrame.\n",
|
||||
"opcode_to_mnem: dict[int, str] = {}\n",
|
||||
"opcode_to_name: dict[int, str] = {}\n",
|
||||
"opcode_to_group: dict[int, str] = {}\n",
|
||||
"\n",
|
||||
"for _, row in instrs_df.iterrows():\n",
|
||||
" bc = str(row['byte_code']).strip()\n",
|
||||
" opc = int(bc, 16)\n",
|
||||
" opcode_to_mnem[opc] = str(row['mnemonic']).strip()\n",
|
||||
" opcode_to_name[opc] = str(row['name']).strip()\n",
|
||||
" opcode_to_group[opc] = str(row['group']).strip()\n",
|
||||
"\n",
|
||||
"# Also track reserved slots for annotation.\n",
|
||||
"reserved_opcodes: set[int] = set()\n",
|
||||
"for _, row in reserved_df.iterrows():\n",
|
||||
" bc = str(row['byte_code']).strip()\n",
|
||||
" if bc and bc != 'nan':\n",
|
||||
" reserved_opcodes.add(int(bc, 16))\n",
|
||||
"\n",
|
||||
"# ── Assemble the file ───────────────────────────────────────────────────────\n",
|
||||
"L = []\n",
|
||||
"L.append('/**')\n",
|
||||
"L.append(' * @file InstrMap.cpp')\n",
|
||||
"L.append(' * @brief Spider VM instruction dispatch — array and switch implementations.')\n",
|
||||
"L.append(' *')\n",
|
||||
"L.append(' * AUTO-GENERATED by pygen.ipynb — DO NOT EDIT BY HAND.')\n",
|
||||
"L.append(' *')\n",
|
||||
"L.append(' * This file provides two equivalent dispatch mechanisms:')\n",
|
||||
"L.append(' *')\n",
|
||||
"L.append(' * 1. InstrMap[] — A lookup table of member-function pointers indexed by')\n",
|
||||
"L.append(' * opcode. O(1) dispatch; suitable for platforms where')\n",
|
||||
"L.append(' * indirect calls through function pointers are efficient.')\n",
|
||||
"L.append(' *')\n",
|
||||
"L.append(' * 2. CPU::execute(u16) — A switch/case over every opcode. Lets the')\n",
|
||||
"L.append(' * compiler emit a jump table or branch tree; may be')\n",
|
||||
"L.append(' * preferable on microcontrollers or when link-time')\n",
|
||||
"L.append(' * optimisation can inline the handlers.')\n",
|
||||
"L.append(' *')\n",
|
||||
"L.append(' */')\n",
|
||||
"L.append('') # [CHANGE] Use absolute path to make paths more explicit\n",
|
||||
"L.append('#include <spider/runtime/cpu/CPU.hpp>')\n",
|
||||
"L.append('')\n",
|
||||
"L.append('namespace spider {')\n",
|
||||
"L.append('')\n",
|
||||
"\n",
|
||||
"# ── Version 1: Array: ────────────────────────────────────────────────────────\n",
|
||||
"L.append('// =============================================================')\n",
|
||||
"L.append('// Version 1 — Lookup table of member-function pointers')\n",
|
||||
"L.append('// =============================================================')\n",
|
||||
"L.append('')\n",
|
||||
"# [CHANGE] Use CPU::Fn Instead\n",
|
||||
"#L.append('/** Pointer-to-member type for a zero-argument CPU instruction. */')\n",
|
||||
"#L.append('using CPUInstr = void (CPU::*)();')\n",
|
||||
"L.append('')\n",
|
||||
"L.append('/**')\n",
|
||||
"L.append(f' * Instruction dispatch table ({TABLE_SIZE} entries, 9-bit opcode space).')\n",
|
||||
"L.append(' *')\n",
|
||||
"L.append(' * Usage:')\n",
|
||||
"L.append(' * u16 opcode = fetch();')\n",
|
||||
"L.append(' * CPU::Fn fn = InstrMap[opcode];')\n",
|
||||
"L.append(' * if (fn) (cpu.*fn)();')\n",
|
||||
"L.append(' */') # [CHANGE] Made it part of the CPU & avoided explicit size.\n",
|
||||
"L.append(f'CPU::Fn CPU::instrMap[] = {{')\n",
|
||||
"\n",
|
||||
"for opc in range(TABLE_SIZE):\n",
|
||||
" mnem = opcode_to_mnem.get(opc)\n",
|
||||
" if mnem:\n",
|
||||
" name = opcode_to_name[opc]\n",
|
||||
" L.append(f' &CPU::{mnem + \",\":<28s}// 0x{opc:03X} — {name}')\n",
|
||||
" else:\n",
|
||||
" tag = ''\n",
|
||||
" if opc in reserved_opcodes:\n",
|
||||
" tag = ' (reserved)'\n",
|
||||
" L.append(f' {\"nullptr,\":<28s}// 0x{opc:03X}{tag}')\n",
|
||||
"\n",
|
||||
"L.append('};')\n",
|
||||
"L.append('')\n",
|
||||
"L.append('')\n",
|
||||
"\n",
|
||||
"# ── Version 2: Switch ──────────────────────────────────────────────────────\n",
|
||||
"L.append('// =============================================================')\n",
|
||||
"L.append('// Version 2 — Switch dispatch')\n",
|
||||
"L.append('// =============================================================')\n",
|
||||
"L.append('')\n",
|
||||
"L.append('/**')\n",
|
||||
"L.append(' * Execute the instruction identified by @p opcode.')\n",
|
||||
"L.append(' *')\n",
|
||||
"L.append(' * This is functionally equivalent to the InstrMap[] table above')\n",
|
||||
"L.append(' * but expressed as a switch so the compiler can choose the best')\n",
|
||||
"L.append(' * lowering strategy (jump table, binary search, etc.).')\n",
|
||||
"L.append(' *')\n",
|
||||
"L.append(' * @param opcode 9-bit instruction opcode (0x000 - 0x1FF).')\n",
|
||||
"L.append(' */')\n",
|
||||
"L.append('void CPU::executeSwLk() {')\n",
|
||||
"L.append(' switch (_opcode) {')\n",
|
||||
"\n",
|
||||
"last_group = None\n",
|
||||
"for opc in sorted(opcode_to_mnem.keys()):\n",
|
||||
" mnem = opcode_to_mnem[opc]\n",
|
||||
" group = opcode_to_group[opc]\n",
|
||||
" if group != last_group:\n",
|
||||
" L.append('')\n",
|
||||
" L.append(f' // ── {group} ' + '─' * max(1, 44 - len(group)))\n",
|
||||
" last_group = group\n",
|
||||
" L.append(f' case 0x{opc:03X}: {mnem}(); break;')\n",
|
||||
"\n",
|
||||
"L.append('')\n",
|
||||
"L.append(' default:')\n",
|
||||
"L.append(' break;')\n",
|
||||
"L.append(' }')\n",
|
||||
"L.append('}')\n",
|
||||
"L.append('')\n",
|
||||
"L.append('} // namespace spider')\n",
|
||||
"L.append('')\n",
|
||||
"\n",
|
||||
"INSTRMAP_SRC = '\\n'.join(L)\n",
|
||||
"\n",
|
||||
"# ── Write to file ───────────────────────────────────────────────────────────\n",
|
||||
"# [CHANGE] Write this in the instructions folder to avoid CPU file bloat\n",
|
||||
"INSTRMAP_PATH = f'{SRC_ROOT}/spider/runtime/instr/InstrMap.cpp'\n",
|
||||
"\n",
|
||||
"with open(INSTRMAP_PATH, 'wb') as f:\n",
|
||||
" f.write(INSTRMAP_SRC.encode('utf-8'))\n",
|
||||
"\n",
|
||||
"# Verify LF-only\n",
|
||||
"with open(INSTRMAP_PATH, 'rb') as f:\n",
|
||||
" raw_bytes = f.read()\n",
|
||||
"assert b'\\r' not in raw_bytes, 'CRLF detected in InstrMap.cpp!'\n",
|
||||
"\n",
|
||||
"array_count = INSTRMAP_SRC.count('&CPU::')\n",
|
||||
"switch_count = INSTRMAP_SRC.count('case 0x')\n",
|
||||
"\n",
|
||||
"print(f'InstrMap.cpp written to: {INSTRMAP_PATH}')\n",
|
||||
"print(f' Size : {len(raw_bytes):,} bytes')\n",
|
||||
"print(f' Array entries : {TABLE_SIZE} ({array_count} populated, {TABLE_SIZE - array_count} nullptr)')\n",
|
||||
"print(f' Switch cases : {switch_count}')\n",
|
||||
"print(f' Line endings : LF-only verified')\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"id": "9f190f4c",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# ---------- GENERATE INSTR_XX FILES ----------\n",
|
||||
"INSTR_DIR = f'{SRC_ROOT}/spider/runtime/instr'\n",
|
||||
"\n",
|
||||
"# Generate the files\n",
|
||||
"# Each file goes from 00 to 1F (0-31), 32 instr / file\n",
|
||||
"for x0 in range(0, TABLE_SIZE, 32):\n",
|
||||
" x1 = x0 + 31\n",
|
||||
" fname = f'{INSTR_DIR}/Instr_{x0:03X}-{x1:03X}.cpp'\n",
|
||||
"\n",
|
||||
" # TODO: Check if there are missing instructions\n",
|
||||
" if file_exists(fname):\n",
|
||||
" continue\n",
|
||||
"\n",
|
||||
" # CREATE FILE FROM SCRATCH\n",
|
||||
" L = []\n",
|
||||
" L.append('/**')\n",
|
||||
" L.append(' * @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!')\n",
|
||||
" L.append(' *')\n",
|
||||
" L.append(' */')\n",
|
||||
" L.append('') # [CHANGE] Use absolute path to make paths more explicit\n",
|
||||
" L.append('#include <spider/runtime/cpu/CPU.hpp>')\n",
|
||||
" L.append('')\n",
|
||||
" L.append('namespace spider {')\n",
|
||||
" L.append('')\n",
|
||||
"\n",
|
||||
" for opc in range(x0, x1 + 1):\n",
|
||||
" mnem = opcode_to_mnem.get(opc)\n",
|
||||
" if mnem is None: continue\n",
|
||||
"\n",
|
||||
" L.append(f' void CPU::{mnem}() {{')\n",
|
||||
" L.append(f' // TODO: Implement {mnem}')\n",
|
||||
" L.append(f' }}')\n",
|
||||
" L.append('')\n",
|
||||
"\n",
|
||||
" L.append('}')\n",
|
||||
" L.append('')\n",
|
||||
"\n",
|
||||
" with open(fname, 'wb') as f:\n",
|
||||
" f.write('\\n'.join(L).encode('utf-8'))\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
@@ -463,7 +681,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.13.7"
|
||||
"version": "3.14.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
],
|
||||
"C_Cpp.default.includePath": [
|
||||
"./src"
|
||||
]
|
||||
],
|
||||
"terminal.integrated.defaultProfile.windows": "MSYS2 UCRT"
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,18 @@
|
||||
#include "SpiderRuntime.hpp"
|
||||
|
||||
#include <spider/runtime/debug/LiveDebug.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace spider {
|
||||
|
||||
const u32 RUNTIME_VERSION_NO = 0x00000000; // v0.1
|
||||
const std::string RUNTIME_VERSION = "alpha v0.1";
|
||||
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "Hello World" << std::endl;
|
||||
spider::liveDebugMain();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
namespace spider {
|
||||
|
||||
extern const u32 RUNTIME_VERSION_NO;
|
||||
extern const std::string RUNTIME_VERSION;
|
||||
|
||||
class Runtime;
|
||||
class CPU;
|
||||
class RAM;
|
||||
|
||||
@@ -4,21 +4,37 @@ namespace spider {
|
||||
|
||||
// Constructors & Destructors //
|
||||
|
||||
Runtime::Runtime() : ram(0) {}
|
||||
Runtime::Runtime() : Runtime(0) {}
|
||||
|
||||
Runtime::Runtime(u64 ramSize) : ram(ramSize) {}
|
||||
Runtime::Runtime(u64 ramSize) : ram(ramSize), reel(nullptr) {
|
||||
cpu.hookRAM(&ram);
|
||||
}
|
||||
|
||||
Runtime::~Runtime() {}
|
||||
Runtime::~Runtime() {
|
||||
delete reel;
|
||||
}
|
||||
|
||||
// Stepping/Running the Machine //
|
||||
|
||||
void Runtime::step() {}
|
||||
void Runtime::step() {
|
||||
cpu.fetchInstr();
|
||||
// TODO: Call instruction
|
||||
}
|
||||
|
||||
void Runtime::step(u64 n) {}
|
||||
void Runtime::step(u64 n) {
|
||||
while(n >= 4) {
|
||||
step();
|
||||
step();
|
||||
step();
|
||||
step();
|
||||
n -= 4;
|
||||
}
|
||||
while (n--) step();
|
||||
}
|
||||
|
||||
void Runtime::run() {}
|
||||
|
||||
void Runtime::run(u64 n) {}
|
||||
//void Runtime::run(u64 n) {}
|
||||
|
||||
// Misc //
|
||||
|
||||
@@ -26,4 +42,13 @@ namespace spider {
|
||||
ram.resize(length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-owning reel setup.
|
||||
*/
|
||||
void Runtime::hookReel(InstrReel* newReel, bool own) {
|
||||
delete this->reel;
|
||||
cpu.hookInstrReel(newReel);
|
||||
if(own) this->reel = newReel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
#include <spider/runtime/memory/RAM.hpp>
|
||||
|
||||
#include <spider/runtime/reel/InstrReel.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
/**
|
||||
@@ -10,10 +13,11 @@ namespace spider {
|
||||
* This is where the Spider VM (Runtime) lives
|
||||
*/
|
||||
class Runtime {
|
||||
private:
|
||||
public:
|
||||
|
||||
CPU cpu;
|
||||
RAM ram;
|
||||
InstrReel* reel;
|
||||
|
||||
public:
|
||||
|
||||
@@ -68,6 +72,11 @@ namespace spider {
|
||||
*/
|
||||
void resizeRAM(u64 length);
|
||||
|
||||
/**
|
||||
* Non-owning reel setup.
|
||||
*/
|
||||
void hookReel(InstrReel* newReel, bool own = false);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace spider {
|
||||
|
||||
// Absolute Types
|
||||
using u8 = std::uint8_t;
|
||||
using u16 = std::uint16_t;
|
||||
using u32 = std::uint32_t;
|
||||
@@ -25,6 +27,9 @@ namespace spider {
|
||||
static_assert(sizeof(f32) == 4, "The f32 type must be exactly 4 bytes.");
|
||||
static_assert(sizeof(f64) == 8, "The f64 type must be exactly 8 bytes.");
|
||||
|
||||
// Utility types
|
||||
using isize = std::size_t;
|
||||
|
||||
// Utility imports
|
||||
using std::vector;
|
||||
using std::deque;
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
#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);
|
||||
const u16 oc = (i >> 7);
|
||||
_opcode = oc & 0x1FF; // GCC WHY!
|
||||
_addrm = static_cast<u8>((i >> 2) & 0x1F);
|
||||
_size = static_cast<u8>(i & 0x3);
|
||||
RI += 2;
|
||||
}
|
||||
|
||||
void CPU::fetchOperDst() {
|
||||
// Move the operand ptrs
|
||||
_alu = &ALU0;
|
||||
_opers[1] = _opers[0];
|
||||
|
||||
// call specific addressing mode
|
||||
(this->*(CPU::addrModes[_addrm & 0b111]))(); // mask added here too
|
||||
}
|
||||
|
||||
void CPU::fetchOperSrc() {
|
||||
// set ALU
|
||||
_alu = &ALU1;
|
||||
|
||||
// call specific addressing mode
|
||||
(this->*(CPU::addrModes[_addrm & 0b111]))(); // mask keeps index within 0-7
|
||||
|
||||
// modify the _addrm register
|
||||
_addrm = static_cast<u8>((_addrm >> 3) & 0x1F);
|
||||
_addrm++;
|
||||
}
|
||||
|
||||
|
||||
void CPU::execute() {
|
||||
(this->*(CPU::instrMap[_opcode]))(); // no null check needed
|
||||
}
|
||||
|
||||
|
||||
// Addressing Modes //
|
||||
|
||||
/**
|
||||
* Implied Addressing Mode
|
||||
*/
|
||||
void CPU::imp() {
|
||||
// Nothing //
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediate Addressing Mode
|
||||
*/
|
||||
void CPU::imm() {
|
||||
_reel->loadRegister(RI, _size, _alu);
|
||||
_opers[0] = _alu;
|
||||
_post = &CPU::imp;
|
||||
RI += 1 << _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Absolute Addressing Mode
|
||||
*/
|
||||
void CPU::abs() {
|
||||
// Load the actual ptr into the ALU
|
||||
u8 mm = u8(getFlag(CPU::FLAG_MEMORY_MODE));
|
||||
_reel->loadRegister(RI, mm, _alu);
|
||||
RI += 1 << mm;
|
||||
|
||||
// read the memory from RAM
|
||||
_store = _alu->_u64;
|
||||
_ram->loadRegister(_store, _size, _alu);
|
||||
_post = &CPU::psw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Addressing Mode
|
||||
*/
|
||||
void CPU::reg() { // NOT FINISHED
|
||||
// Two consecutive registers can be declared
|
||||
// Shift if the top part will become .reg too
|
||||
u8 sh = ((_addrm & 0b11000) == 0b11000) * 4;
|
||||
u8 use = 1 - (sh >> 2); // (sh / 4)
|
||||
|
||||
// get byte
|
||||
u8 reg = (_reel->readU8(RI) >> sh) & 0xF;
|
||||
_alu = &GPR[reg];
|
||||
_opers[0] = _alu; // explicitly sets _opers[0] = _dst
|
||||
RI += use;
|
||||
|
||||
// store no-op
|
||||
_post = &CPU::imp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
#include <spider/SpiderRuntime.hpp>
|
||||
#include <spider/runtime/cpu/Register.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
class CPU {
|
||||
public: // Helper types
|
||||
using Fn = void (CPU::*)();
|
||||
|
||||
public: // Flag Register Constants //
|
||||
static constexpr const u64 FLAG_ENABLE = 0b0000000000000000000000000000000000000000000000000000000000000001;
|
||||
static constexpr const u64 FLAG_INTERRUPT_SIGNAL = 0b0000000000000000000000000000000000000000000000000000000000000010;
|
||||
static constexpr const u64 FLAG_INTERRUPT_REQUEST = 0b0000000000000000000000000000000000000000000000000000000000000100;
|
||||
static constexpr const u64 FLAG_EXCEPTION = 0b0000000000000000000000000000000000000000000000000000000000001000;
|
||||
static constexpr const u64 FLAG_MEMORY_MODE = 0b0000000000000000000000000000000000000000000000000000000000110000;
|
||||
|
||||
public: // Map of addressing modes & Instructions
|
||||
|
||||
static CPU::Fn addrModes[];
|
||||
static CPU::Fn instrMap[];
|
||||
|
||||
public: // General Purpose Registers
|
||||
register_t RA, RB, RC, RD,
|
||||
RX, RY, R0, R1,
|
||||
R2, R3, R4, R5,
|
||||
R6, R7, R8, R9;
|
||||
union {
|
||||
register_t GPR[16];
|
||||
struct {
|
||||
register_t RA, RB, RC, RD,
|
||||
RX, RY, R0, R1,
|
||||
R2, R3, R4, R5,
|
||||
R6, R7, R8, R9;
|
||||
};
|
||||
};
|
||||
|
||||
public: // System Registers
|
||||
u64 RF;
|
||||
@@ -31,6 +52,55 @@ namespace spider {
|
||||
*/
|
||||
register_t ALU0, ALU1;
|
||||
|
||||
union {
|
||||
struct {
|
||||
register_t* _dst;
|
||||
register_t* _src;
|
||||
register_t* _alu;
|
||||
};
|
||||
register_t* _opers[2];
|
||||
};
|
||||
|
||||
// Holds the current instruction opcode
|
||||
u16 _opcode : 9;
|
||||
|
||||
// Holds the current addressing modes,
|
||||
// before they were used
|
||||
u8 _addrm : 5;
|
||||
|
||||
// Holds the current instruction size.
|
||||
u8 _size : 2;
|
||||
|
||||
// On _post that are not no-ops, it must
|
||||
// write back DST to this memory location.
|
||||
u64 _store;
|
||||
|
||||
// Post execution callback
|
||||
CPU::Fn _post;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Pointer to the current RAM hooked into
|
||||
* the CPU.
|
||||
*
|
||||
* It is unproved whether having the RAM directly
|
||||
* into the CPU is better than not, or whether a
|
||||
* virtual BUS is better.
|
||||
*
|
||||
* Alas, this way we can have a CPU state switch
|
||||
* between memory and instruction banks.
|
||||
*/
|
||||
RAM* _ram;
|
||||
|
||||
/**
|
||||
* Pointer to the current Instruction Reel
|
||||
* hooked into the CPU.
|
||||
*
|
||||
* Ditto as RAM.
|
||||
*/
|
||||
InstrReel* _reel;
|
||||
|
||||
public:
|
||||
|
||||
CPU();
|
||||
@@ -42,11 +112,127 @@ namespace spider {
|
||||
~CPU();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
CPU& operator=(const CPU& other) = default;
|
||||
|
||||
CPU& operator=(CPU&& other) noexcept = default;
|
||||
|
||||
public:
|
||||
|
||||
void hookRAM(RAM* ram);
|
||||
|
||||
void hookInstrReel(InstrReel* reel);
|
||||
|
||||
constexpr u64 getFlag(u64 mask);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Fetches the instruction from the
|
||||
* reel, and advances IR by two.
|
||||
*/
|
||||
void fetchInstr();
|
||||
|
||||
/**
|
||||
* Fetches the destination operand,
|
||||
* by calling the appropriate addressing
|
||||
* mode.
|
||||
*
|
||||
* Will read the bottom 3 bits.
|
||||
* For instructions with two operands,
|
||||
* call Src first.
|
||||
*
|
||||
* The internal variable _addrm
|
||||
* will not be modified. It will
|
||||
* be important when writing
|
||||
* back the result.
|
||||
*/
|
||||
void fetchOperDst();
|
||||
|
||||
/**
|
||||
* Fetches the source operand.
|
||||
*
|
||||
* For use in two operand instructions.
|
||||
*
|
||||
* Will read the bottom 3 bits. It will
|
||||
* then shift the _addrm 3 spaces
|
||||
* to ensure it aligns with the DST
|
||||
* next.
|
||||
*
|
||||
* Additionally, it will add 1 to _addrm
|
||||
* to account with
|
||||
*/
|
||||
void fetchOperSrc();
|
||||
|
||||
/**
|
||||
* Executes an opcode, by means of directly
|
||||
* accessing the instruction map and
|
||||
* calling that function pointer.
|
||||
*/
|
||||
void execute();
|
||||
|
||||
/**
|
||||
* Executes an opcode, by means of using
|
||||
* a large switch statement. Only suitable
|
||||
* for environments where the instruction
|
||||
* map is not possible.
|
||||
*
|
||||
* This has yet to be proved!!!
|
||||
*/
|
||||
void executeSwLk();
|
||||
|
||||
public: // Addressing Modes
|
||||
|
||||
/**
|
||||
* Implied Addressing Mode
|
||||
*/
|
||||
void imp(); // Kept as it is a no-op
|
||||
|
||||
/**
|
||||
* Immediate Addressing Mode
|
||||
*/
|
||||
void imm();
|
||||
|
||||
/**
|
||||
* Absolute Addressing Mode
|
||||
*/
|
||||
void abs();
|
||||
|
||||
/**
|
||||
* Register Addressing Mode
|
||||
*/
|
||||
void reg();
|
||||
|
||||
/**
|
||||
* Indrect Addressing Mode
|
||||
*/
|
||||
void ind();
|
||||
|
||||
/**
|
||||
* Pointer Addressing Mode
|
||||
*/
|
||||
void ptr();
|
||||
|
||||
/**
|
||||
* Indexed Addressing Mode
|
||||
*/
|
||||
void idx();
|
||||
|
||||
/**
|
||||
* Scaled Addressing Mode
|
||||
*/
|
||||
void sca();
|
||||
|
||||
/**
|
||||
* Displaced Addressing Mode
|
||||
*/
|
||||
void dis();
|
||||
|
||||
/**
|
||||
* Post-Write Action
|
||||
*/
|
||||
void psw();
|
||||
|
||||
public:
|
||||
|
||||
// <pygen-target name=cpu-instructions> //
|
||||
@@ -66,327 +252,327 @@ namespace spider {
|
||||
void MMODE();
|
||||
|
||||
// [System] 0x003 — INT: Interrupt
|
||||
// Params: 1 | AddrMask1: 1F AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: 1F AddrMask2: 00 | TypeMask: 08
|
||||
// Operation: Performs system interrupt no. (Dst) (See table)
|
||||
void INT();
|
||||
|
||||
// [System] 0x004 — LRV: Load Interrupt Vector Register
|
||||
// Params: 1 | AddrMask1: 1F AddrMask2: 00 | TypeMask: 0C
|
||||
// Params: 1 | AddrMask1: 1F AddrMask2: 00 | TypeMask: 08
|
||||
// Operation: Dst -> RV
|
||||
void LRV();
|
||||
|
||||
// [System] 0x005 — FSR: Fetch System Register
|
||||
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 08
|
||||
// Operation: System Register at Dst -> Dst
|
||||
void FSR();
|
||||
|
||||
// [System] 0x006 — FIR: Fetch Instruction Register
|
||||
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 08
|
||||
// Operation: Instruction Register -> Dst
|
||||
void FIR();
|
||||
|
||||
// [System] 0x007 — FZR: Fetch Stack Base Register
|
||||
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: 1E AddrMask2: 00 | TypeMask: 08
|
||||
// Operation: Stack Base Register -> Dst
|
||||
void FZR();
|
||||
|
||||
// [System] 0x008 — LSR: Load System Register
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: 1F | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: 1F | TypeMask: 08
|
||||
// Operation: Src -> System Register at Dst
|
||||
void LSR();
|
||||
|
||||
// [System] 0x009 — FVR: Fetch Interrupt Vector Register
|
||||
// Params: 1 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: 04 AddrMask2: 00 | TypeMask: 08
|
||||
// Operation: Interrupt Vector Register -> Dst
|
||||
void FVR();
|
||||
|
||||
// [Memory] 0x00A — MOV: Moves values
|
||||
// Params: 2 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Src -> Dst
|
||||
void MOV();
|
||||
|
||||
// [Memory] 0x00B — MOR: Moves registers
|
||||
// Params: 2 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 04 AddrMask2: 04 | TypeMask: 08
|
||||
// Operation: R Scr -> R Dst
|
||||
void MOR();
|
||||
|
||||
// [Memory] 0x00C — AMOV: Array Move, uses X and Y as ptrs, A as amount
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 08
|
||||
// Operation: Array from X to Y, by A amount
|
||||
void AMOV();
|
||||
|
||||
// [Memory] 0x00D — SWP: Swap registers
|
||||
// Params: 2 | AddrMask1: 04 AddrMask2: 04 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 04 AddrMask2: 04 | TypeMask: 08
|
||||
// Operation: Src <-> Dst
|
||||
void SWP();
|
||||
|
||||
// [Memory] 0x00E — AHM: Ask Host for Memory
|
||||
// Params: 1 | AddrMask1: 04 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: 04 AddrMask2: 00 | TypeMask: 08
|
||||
// Operation: Asks the host for a specific size of memory. Responds with 0 or 1
|
||||
void AHM();
|
||||
|
||||
// [Integer] 0x010 — COM: One's complement
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: ~ Dst -> Dst
|
||||
void COM();
|
||||
|
||||
// [Integer] 0x011 — NEG: Two's complement
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: - Dst -> Dst
|
||||
void NEG();
|
||||
|
||||
// [Integer] 0x012 — EXS: Extend Sign
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Last bit is copied and expanded for the next int size
|
||||
void EXS();
|
||||
|
||||
// [Integer] 0x013 — INC: Increment
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Dst + 1 -> Dst
|
||||
void INC();
|
||||
|
||||
// [Integer] 0x014 — DEC: Decrement
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Dst - 1 -> Dst
|
||||
void DEC();
|
||||
|
||||
// [Integer] 0x015 — ADD: Addition
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst + Src -> Dst
|
||||
void ADD();
|
||||
|
||||
// [Integer] 0x016 — SUB: Subtraction
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst - Src-> Dst
|
||||
void SUB();
|
||||
|
||||
// [Integer] 0x017 — MUL: Multiplication
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Signed Dst * Src -> Dst
|
||||
void MUL();
|
||||
|
||||
// [Integer] 0x018 — UMUL: Unsigned Multiplication
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Unsigned Dst * Src -> Dst
|
||||
void UMUL();
|
||||
|
||||
// [Integer] 0x019 — DIV: Division
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Signed Dst / Src -> Dst
|
||||
void DIV();
|
||||
|
||||
// [Integer] 0x01A — UDIV: Unsigned Division
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Unsigned Dst / Src -> Dst
|
||||
void UDIV();
|
||||
|
||||
// [Integer] 0x01B — MOD: Modulus
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Signed Dst % Src -> Dst
|
||||
void MOD();
|
||||
|
||||
// [Integer] 0x01C — UMOD: Unsigned Modulus
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Unsigned Dst % Src -> Dst
|
||||
void UMOD();
|
||||
|
||||
// [Integer] 0x01D — DMOD: Division and Modulus
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Signed Dst / Src -> X, Dst % Src -> Y
|
||||
void DMOD();
|
||||
|
||||
// [Integer] 0x01E — UDMD: Unsigned Division and Modulus
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Unsigned Dst / Src -> X, Dst % Src -> Y
|
||||
void UDMD();
|
||||
|
||||
// [System] 0x01F — FBT: Test and update Flag Register (Integer) Bits
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Flags of Dst -
|
||||
void FBT();
|
||||
|
||||
// [Bit Wise] 0x020 — STB: Set Bit
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Src# bit is set on Dst
|
||||
void STB();
|
||||
|
||||
// [Bit Wise] 0x021 — CRB: Clear Bit
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Src# bit is cleared on Dst
|
||||
void CRB();
|
||||
|
||||
// [Bit Wise] 0x022 — TSB: Test Bit
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Src# bit is tested against Dst, updates Equal Flag
|
||||
void TSB();
|
||||
|
||||
// [Bit Wise] 0x023 — BOOL: Sets the booleaness of a value
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Tests Dst != 0, updates Equal Flag
|
||||
void BOOL();
|
||||
|
||||
// [Bit Wise] 0x024 — NOT: Sets the inverse booleaness of a value (! BOOL)
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Tests Dst == 0, updates Equal Flag
|
||||
void NOT();
|
||||
|
||||
// [Bit Wise] 0x025 — AND: Boolean AND operation
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst AND Src into Dst
|
||||
void AND();
|
||||
|
||||
// [Bit Wise] 0x026 — OR: Boolean OR operation
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst OR Src into Dst
|
||||
void OR();
|
||||
|
||||
// [Bit Wise] 0x027 — XOR: Boolean XOR operation
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst XOR Src into Dst
|
||||
void XOR();
|
||||
|
||||
// [Bit Wise] 0x028 — SHL: Arithmetic Shift Left
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst << Src into Dst
|
||||
void SHL();
|
||||
|
||||
// [Bit Wise] 0x029 — SHR: Arithmetic Shift Right
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst >> Src into Dst
|
||||
void SHR();
|
||||
|
||||
// [Bit Wise] 0x02A — SSR: Signed Shift Right
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst >>> Src into Dst
|
||||
void SSR();
|
||||
|
||||
// [Bit Wise] 0x02B — ROL: Rotate Left
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst ROL Src into Dst
|
||||
void ROL();
|
||||
|
||||
// [Bit Wise] 0x02C — ROR: Rotate Right
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst ROR Src into Dst
|
||||
void ROR();
|
||||
|
||||
// [Bit Wise] 0x02D — CNT: Counts bits
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: # of 1's into Dst
|
||||
void CNT();
|
||||
|
||||
// [Boolean] 0x030 — EQ: Equal
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst == Src into Dst
|
||||
void EQ();
|
||||
|
||||
// [Boolean] 0x031 — NE: Not Equal
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst != Src into Dst
|
||||
void NE();
|
||||
|
||||
// [Boolean] 0x032 — GT: Greater Than
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst > Src into Dst
|
||||
void GT();
|
||||
|
||||
// [Boolean] 0x033 — GE: Greater or Equal Than
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst >= Src into Dst
|
||||
void GE();
|
||||
|
||||
// [Boolean] 0x034 — LT: Lower Than
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst < Src into Dst
|
||||
void LT();
|
||||
|
||||
// [Boolean] 0x035 — LE: Lower or Equal Than
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst <= Src into Dst
|
||||
void LE();
|
||||
|
||||
// [Branch] 0x038 — JMP: Jump to absolute position
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Dst -> Instruction Register
|
||||
void JMP();
|
||||
|
||||
// [Branch] 0x039 — JEQ: Jumps to position if EQ flag is set
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Dst -> Instruction Register IF Flags.EQ
|
||||
void JEQ();
|
||||
|
||||
// [Branch] 0x03A — JNE: Jumps to position if EQ flag is cleared
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Dst -> Instruction Register IF NOT Flags.EQ
|
||||
void JNE();
|
||||
|
||||
// [Branch] 0x03B — JIF: Jumps if value provided is booleanly true
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst -> Instruction Register IF Src
|
||||
void JIF();
|
||||
|
||||
// [Branch] 0x03C — JMR: Jump Relative
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Dst + Instruction Register -> Instruction Register
|
||||
void JMR();
|
||||
|
||||
// [Branch] 0x03D — JER: Jumps to relative position if EQ flag is set
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Dst + Instruction Register -> Instruction Register IF Flags.EQ
|
||||
void JER();
|
||||
|
||||
// [Branch] 0x03E — JNR: Jumps to relative position if EQ flag is cleared
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Dst + Instruction Register -> Instruction Register IF NOT Flags.EQ
|
||||
void JNR();
|
||||
|
||||
// [Branch] 0x03F — JIR: Jumps to relative position if value provided is booleanly true
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation: Dst + Instruction Register -> Instruction Register IF Src
|
||||
void JIR();
|
||||
|
||||
// [System] 0x040 — SFB: Store (User) Flag Bit
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation:
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation:
|
||||
void SFB();
|
||||
|
||||
// [System] 0x041 — LFB: Load (User) Flag Bit
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation:
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation:
|
||||
void LFB();
|
||||
|
||||
// [Branch] 0x042 — JUF: Jump to absolute position, if user flag is true
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation:
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation:
|
||||
void JUF();
|
||||
|
||||
// [Branch] 0x043 — JUR: Jump to relative position, if user flag is true
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation:
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
|
||||
// Operation:
|
||||
void JUR();
|
||||
|
||||
// [Memory] 0x044 — PUSH: Push to stack
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Dst -> pushed into stack
|
||||
void PUSH();
|
||||
|
||||
// [Memory] 0x045 — POP: Pop from stack
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: popped from stack -> Dst
|
||||
void POP();
|
||||
|
||||
// [Memory] 0x046 — ALLOC: Allocate to heap
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Dst -> heap ptr of size Dst
|
||||
void ALLOC();
|
||||
|
||||
// [Memory] 0x047 — HFREE: Delete from heap
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Frees heap ptr in Dst
|
||||
void HFREE();
|
||||
|
||||
// [Branch] 0x04A — CALL: Call function at instruction index
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: Performs a function call, step XX
|
||||
void CALL();
|
||||
|
||||
@@ -396,207 +582,207 @@ namespace spider {
|
||||
void RET();
|
||||
|
||||
// [System] 0x04C — EDI: Enable/Disable External Interrupts
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: bool( Dst ) -> Enable External Interrupts Bit
|
||||
void EDI();
|
||||
|
||||
// [System] 0x04D — SHSS: Set Hotswap Signal Bit
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 0F
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
|
||||
// Operation: bool( Dst ) -> Hot Swap Signal Bit
|
||||
void SHSS();
|
||||
|
||||
// [Floating Point] 0x050 — FLI: Float Load Immediate
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation:
|
||||
void FLI();
|
||||
|
||||
// [Floating Point] 0x051 — FNEG: Float negate
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation: - Dst -> Dst
|
||||
void FNEG();
|
||||
|
||||
// [Floating Point] 0x052 — FADD: Float add
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: Dst + Src -> Dst
|
||||
void FADD();
|
||||
|
||||
// [Floating Point] 0x053 — FSUB: Float subtract
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: Dst - Src-> Dst
|
||||
void FSUB();
|
||||
|
||||
// [Floating Point] 0x054 — FMUL: Float multiplication
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: Dst * Src -> Dst
|
||||
void FMUL();
|
||||
|
||||
// [Floating Point] 0x055 — FDIV: Float division
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: Dst / Src -> Dst
|
||||
void FDIV();
|
||||
|
||||
// [Floating Point] 0x056 — FMOD: Float modulus
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: Dst % Src -> Dst
|
||||
void FMOD();
|
||||
|
||||
// [Floating Point] 0x057 — FDMOD: Float division and modulus
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: Dst / Src -> X, Dst % Src -> Y
|
||||
void FDMOD();
|
||||
|
||||
// [Floating Point] 0x058 — FEPS: Sets the float epsilon value, for comparison
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation: Dst -> Epsilon Register
|
||||
void FEPS();
|
||||
|
||||
// [Floating Point] 0x059 — FEEP: Float Enable/Disable Epsilon
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation: bool( Dst ) -> Epsilon Enable Bit
|
||||
void FEEP();
|
||||
|
||||
// [Boolean] 0x05A — FEQ: Float Equal
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: Dst == Src into Dst
|
||||
void FEQ();
|
||||
|
||||
// [Boolean] 0x05B — FNE: Float Not Equal
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: Dst != Src into Dst
|
||||
void FNE();
|
||||
|
||||
// [Boolean] 0x05C — FGT: Float Greater Than
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: Dst > Src into Dst
|
||||
void FGT();
|
||||
|
||||
// [Boolean] 0x05D — FGE: Float Greater or Equal Than
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: Dst >= Src into Dst
|
||||
void FGE();
|
||||
|
||||
// [Boolean] 0x05E — FLT: Float Lower Than
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: Dst < Src into Dst
|
||||
void FLT();
|
||||
|
||||
// [Boolean] 0x05F — FLE: Float Lower or Equal Than
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: Dst <= Src into Dst
|
||||
void FLE();
|
||||
|
||||
// [Casts] 0x060 — F2D: F32 (Float) to F64 (Double)
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||
// Operation: (cast) Dst -> Dst
|
||||
void F2D();
|
||||
|
||||
// [Casts] 0x061 — D2F: F64 (Double) to F32 (Float)
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||
// Operation: (cast) Dst -> Dst
|
||||
void D2F();
|
||||
|
||||
// [Casts] 0x062 — I2F: I32 (Integer) to F32 (Float)
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||
// Operation: (cast) Dst -> Dst
|
||||
void I2F();
|
||||
|
||||
// [Casts] 0x063 — I2D: I32 (Integer) to F64 (Double)
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||
// Operation: (cast) Dst -> Dst
|
||||
void I2D();
|
||||
|
||||
// [Casts] 0x064 — L2F: I64 (Long) to F32 (Float)
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||
// Operation: (cast) Dst -> Dst
|
||||
void L2F();
|
||||
|
||||
// [Casts] 0x065 — L2D: I64 (Long) to F64 (Double)
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||
// Operation: (cast) Dst -> Dst
|
||||
void L2D();
|
||||
|
||||
// [Casts] 0x066 — F2I: F32 (Float) to I32 (Integer)
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||
// Operation: (cast) Dst -> Dst
|
||||
void F2I();
|
||||
|
||||
// [Casts] 0x067 — F2L: F32 (Float) to I64 (Long)
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||
// Operation: (cast) Dst -> Dst
|
||||
void F2L();
|
||||
|
||||
// [Casts] 0x068 — D2I: F64 (Double) to I32 (Integer)
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||
// Operation: (cast) Dst -> Dst
|
||||
void D2I();
|
||||
|
||||
// [Casts] 0x069 — D2L: F64 (Double) to I64 (Long)
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 00
|
||||
// Operation: (cast) Dst -> Dst
|
||||
void D2L();
|
||||
|
||||
// [Trigonometric] 0x06C — SIN: Sine Function
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation: sin( Dst ) -> Dst
|
||||
void SIN();
|
||||
|
||||
// [Trigonometric] 0x06D — COS: Cosine Function
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation: cos( Dst ) -> Dst
|
||||
void COS();
|
||||
|
||||
// [Trigonometric] 0x06E — TAN: Tangent Function
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation: tan( Dst ) -> Dst
|
||||
void TAN();
|
||||
|
||||
// [Trigonometric] 0x06F — ASIN: Arc Sine Function
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation: asin( Dst ) -> Dst
|
||||
void ASIN();
|
||||
|
||||
// [Trigonometric] 0x070 — ACOS: Arc Cosine Function
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation: acos( Dst ) -> Dst
|
||||
void ACOS();
|
||||
|
||||
// [Trigonometric] 0x071 — ATAN: Arc Tangent Function
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation: atan( Dst ) -> Dst
|
||||
void ATAN();
|
||||
|
||||
// [Trigonometric] 0x072 — ATAN2: Arc Tangent Function with 2 Arguments
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: atan( Dst, Src ) -> Dst
|
||||
void ATAN2();
|
||||
|
||||
// [Exponential] 0x074 — EXP: Exponential Function
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation: exp( Dst ) -> Dst
|
||||
void EXP();
|
||||
|
||||
// [Exponential] 0x075 — LOG: Natural Logarithm
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation: ln( Dst ) -> Dst
|
||||
void LOG();
|
||||
|
||||
// [Exponential] 0x076 — LOGAB: Logarithm A of B
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: log( Dst, Src ) -> Dst
|
||||
void LOGAB();
|
||||
|
||||
// [Exponential] 0x077 — POW: Power Function
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: pow( Dst, Src ) -> Dst
|
||||
void POW();
|
||||
|
||||
// [Exponential] 0x078 — SQRT: Square Root
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
|
||||
// Operation: sqrt( Dst ) -> Dst
|
||||
void SQRT();
|
||||
|
||||
// [Exponential] 0x079 — ROOT: General Root
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0C
|
||||
// Operation: pow( Dst, 1 / Src ) -> Dst
|
||||
void ROOT();
|
||||
|
||||
@@ -622,66 +808,80 @@ namespace spider {
|
||||
|
||||
// [Matrix] 0x080 — MADD: Matrix Addition
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Operation:
|
||||
void MADD();
|
||||
|
||||
// [Matrix] 0x081 — MSUB: Matrix Subtraction
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Operation:
|
||||
void MSUB();
|
||||
|
||||
// [Matrix] 0x082 — MMUL: Matrix Multiply
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Operation:
|
||||
void MMUL();
|
||||
|
||||
// [Matrix] 0x083 — MINV: Matrix Inverse
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Operation:
|
||||
void MINV();
|
||||
|
||||
// [Matrix] 0x084 — MTRA: Matrix Transpose
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Operation:
|
||||
void MTRA();
|
||||
|
||||
// [Matrix] 0x085 — MDET: Matrix Determinant
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Operation:
|
||||
void MDET();
|
||||
|
||||
// [Quaternion] 0x086 — QMKA: Quaternion Make from Angles
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
void QMKA();
|
||||
|
||||
// [Quaternion] 0x087 — QMUL: Quaternion Multiply
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
void QMUL();
|
||||
|
||||
// [SIMD] 0x08A — XADD: SIMD Addition
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Operation:
|
||||
void XADD();
|
||||
|
||||
// [SIMD] 0x08B — XSUB: SIMD Subtract
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Operation:
|
||||
void XSUB();
|
||||
|
||||
// [SIMD] 0x08C — XAMA: SIMD Alternate Multiply-Add
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Operation:
|
||||
void XAMA();
|
||||
|
||||
// [SIMD] 0x08D — XMUL: SIMD Multiply
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Operation:
|
||||
void XMUL();
|
||||
|
||||
// [SIMD] 0x08E — XDIV: SIMD Divide
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Operation:
|
||||
void XDIV();
|
||||
|
||||
// [Easter Eggs] 0x0F0 — UPY: Will place "YUPI" in memory
|
||||
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
|
||||
// Operation:
|
||||
// Operation:
|
||||
void UPY();
|
||||
|
||||
//[Easter Egg] 0x0F1 - LLGS: Injects the custom 8x4 ASCII spider logo
|
||||
// into RAM [0x80-0x9F] and signs Register RA with the "LLGS" hex literal.
|
||||
void LLGS();
|
||||
|
||||
// </pygen-target> //
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -18,26 +18,13 @@ namespace spider {
|
||||
* type-punning which is the "standard" right now.
|
||||
*/
|
||||
union register_t {
|
||||
|
||||
// -- Un/Signed 64 -- //
|
||||
|
||||
u64 _u64;
|
||||
i64 _i64;
|
||||
f64 _f64;
|
||||
u8 _bytes[8];
|
||||
|
||||
SPIDER_PACKED_STRUCT(struct {
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
u8 _u8; u64 : 56;
|
||||
#else
|
||||
u64 : 56; u8 _u8;
|
||||
#endif
|
||||
});
|
||||
|
||||
SPIDER_PACKED_STRUCT(struct {
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
u16 _u16; u64 : 48;
|
||||
#else
|
||||
u64 : 48; u16 _u16;
|
||||
#endif
|
||||
});
|
||||
// -- Un/Signed 32 -- //
|
||||
|
||||
struct {
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
@@ -47,6 +34,61 @@ namespace spider {
|
||||
#endif
|
||||
};
|
||||
|
||||
struct {
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
i32 _i32; i32 : 32;
|
||||
#else
|
||||
i32 : 32; i32 _i32;
|
||||
#endif
|
||||
};
|
||||
|
||||
// -- Un/Signed 16 -- //
|
||||
|
||||
struct {
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
u16 _u16;
|
||||
u16 : 16; u16 : 16; u16 : 16;
|
||||
#else
|
||||
u16 : 16; u16 : 16; u16 : 16;
|
||||
u16 _u16;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct {
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
i16 _i16;
|
||||
i16 : 16; i16 : 16; i16 : 16;
|
||||
#else
|
||||
i16 : 16; i16 : 16; i16 : 16;
|
||||
i16 _i16;
|
||||
#endif
|
||||
};
|
||||
|
||||
// -- Un/Signed 8 -- //
|
||||
|
||||
struct {
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
u8 _u8; // This looks like a cruel joke
|
||||
u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8;
|
||||
#else
|
||||
u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8; u8 : 8;
|
||||
u8 _u8;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct {
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
i8 _i8; // ditto
|
||||
i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8;
|
||||
#else
|
||||
i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8;
|
||||
i8 _i8;
|
||||
#endif
|
||||
};
|
||||
|
||||
// -- Floating Point -- //
|
||||
|
||||
f64 _f64;
|
||||
struct {
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
f32 _f32; u32 : 32;
|
||||
@@ -55,6 +97,10 @@ namespace spider {
|
||||
#endif
|
||||
};
|
||||
|
||||
// -- Access -- //
|
||||
|
||||
u8 _bytes[8];
|
||||
|
||||
u8& operator[](size_t i) { // 0 is always LSB
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
return _bytes[i];
|
||||
@@ -71,6 +117,7 @@ namespace spider {
|
||||
return _bytes[7 - i];
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
static_assert(sizeof(register_t) == 8, "The register type must be exactly 8 bytes.");
|
||||
|
||||
|
||||
402
src/spider/runtime/debug/LiveDebug.cpp
Normal file
402
src/spider/runtime/debug/LiveDebug.cpp
Normal file
@@ -0,0 +1,402 @@
|
||||
#include "LiveDebug.hpp"
|
||||
|
||||
#include <spider/runtime/reel/InstrReelFixed.hpp>
|
||||
|
||||
#include <spider/runtime/Runtime.hpp>
|
||||
#include <spider/runtime/util/Terminal.hpp>
|
||||
#include <spider/runtime/native/distro.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <format>
|
||||
#include <thread>
|
||||
namespace spider {
|
||||
|
||||
void drawHead(Terminal& t) {
|
||||
t.move(1, 1)
|
||||
.style(Terminal::FG_YELLOW)
|
||||
.print(" Spider Runtime Live Debug ")
|
||||
.style(Terminal::RESET).print(" | ")
|
||||
.style(Terminal::FG_B_CYAN).print(" Sintek Analytics @ 2026 ")
|
||||
.style(Terminal::RESET).print(" | ")
|
||||
.style(Terminal::FG_B_BLACK).print("Press ESC to exit")
|
||||
.style(Terminal::FG_BLACK)
|
||||
.style(Terminal::BG_YELLOW)
|
||||
.move(3, 1).print(" // __ \\\\").print(" ") // 27
|
||||
.move(4, 1).print(" \\\\( )//").print(" SPIDER v0.1 ")
|
||||
.move(5, 1).print(" //()\\\\ ").print(" alpha ")
|
||||
.move(6, 1).print(" \\\\ // ").print(" ")
|
||||
.style(Terminal::RESET)
|
||||
.style(Terminal::FG_B_BLACK) // 4x8 for the menu
|
||||
.move(3, 28).print("[ STEP ]")
|
||||
.move(4, 28).print("[ STOP ]")
|
||||
.move(5, 28).print("[ RUN ]")
|
||||
.move(6, 28).print("[ MENU ]")
|
||||
.style(Terminal::RESET)
|
||||
;
|
||||
}
|
||||
|
||||
void drawCPUTempl(Terminal& t) {
|
||||
i32 r = 8, c = 1;
|
||||
i32 w = 35, h = 31;
|
||||
t.drawBox(r, c, w, h, "CPU");
|
||||
|
||||
const std::string regs[] = {
|
||||
"RA", "RB", "RC", "RD",
|
||||
"RX", "RY", "R0", "R1",
|
||||
"R2", "R3", "R4", "R5",
|
||||
"R6", "R7", "R8", "R9",
|
||||
"RF", "RI", "RS", "RZ",
|
||||
"RE", "RN", "RV", "RM",
|
||||
"ALU0", "ALU1"
|
||||
};
|
||||
const std::string alt[] = {
|
||||
Terminal::FG_WHITE,
|
||||
Terminal::FG_B_BLACK,
|
||||
};
|
||||
|
||||
r++;
|
||||
c++;
|
||||
|
||||
t.move(r++, c);
|
||||
t.style(Terminal::FG_B_YELLOW);
|
||||
t.print_center(w - 2, "GP Registers");
|
||||
t.style(Terminal::RESET);
|
||||
for (i32 i = 0; i < 8; i++) {
|
||||
t.style(alt[i & 1]);
|
||||
t.move(r + i * 2, c);
|
||||
t.print(regs[i * 2]);
|
||||
t.move(r + i * 2, c + 17);
|
||||
t.print(regs[i * 2 + 1]);
|
||||
}
|
||||
|
||||
t.move(r += 16, c);
|
||||
t.style(Terminal::FG_B_CYAN);
|
||||
t.print_center(w - 2, "System Registers");
|
||||
t.style(Terminal::RESET);
|
||||
r++;
|
||||
for (i32 j = 0, i = 8; i < 12; j++, i++) {
|
||||
t.style(alt[j & 1]);
|
||||
t.move(r + j * 2, c);
|
||||
t.print(regs[i * 2]);
|
||||
t.move(r + j * 2, c + 17);
|
||||
t.print(regs[i * 2 + 1]);
|
||||
}
|
||||
|
||||
t.move(r += 8, c);
|
||||
t.style(Terminal::FG_GREEN);
|
||||
t.print_center(w - 2, "Extra Registers");
|
||||
t.style(Terminal::RESET);
|
||||
r++;
|
||||
for (i32 j = 0, i = 12; i < 13; j++, i++) {
|
||||
t.style(alt[j & 1]);
|
||||
t.move(r + j * 2, c);
|
||||
t.print(regs[i * 2]);
|
||||
t.move(r + j * 2, c + 17);
|
||||
t.print(regs[i * 2 + 1]);
|
||||
}
|
||||
|
||||
t.flush();
|
||||
}
|
||||
|
||||
void printU64Hex(u64 n) {
|
||||
std::ios state(nullptr);
|
||||
state.copyfmt(std::cout);
|
||||
std::cout
|
||||
<< std::hex
|
||||
<< std::uppercase
|
||||
<< std::setfill('0')
|
||||
<< std::setw(16)
|
||||
<< n;
|
||||
std::cout.copyfmt(state);
|
||||
}
|
||||
|
||||
void drawCPU(Terminal& t, CPU& cpu) {
|
||||
i32 r = 8, c = 1;
|
||||
|
||||
const register_t* regs[] = {
|
||||
&cpu.RA, &cpu.RB, &cpu.RC, &cpu.RD,
|
||||
&cpu.RX, &cpu.RY, &cpu.R0, &cpu.R1,
|
||||
&cpu.R2, &cpu.R3, &cpu.R4, &cpu.R5,
|
||||
&cpu.R6, &cpu.R7, &cpu.R8, &cpu.R9,
|
||||
//&cpu.RF, &cpu.RI, &cpu.RS, &cpu.RZ,
|
||||
//&cpu.RE, &cpu.RN, &cpu.RV, &cpu.RM,
|
||||
&cpu.ALU0, &cpu.ALU1
|
||||
};
|
||||
const u64* sys_regs[] = {
|
||||
&cpu.RF, &cpu.RI, &cpu.RS, &cpu.RZ,
|
||||
&cpu.RE, &cpu.RN, &cpu.RV, &cpu.RM,
|
||||
};
|
||||
const std::string alt[] = {
|
||||
Terminal::FG_WHITE,
|
||||
Terminal::FG_B_BLACK,
|
||||
};
|
||||
|
||||
r++;
|
||||
c++;
|
||||
t.move(r++, c);
|
||||
t.style(Terminal::RESET);
|
||||
r++;
|
||||
for (i32 i = 0; i < 8; i++) {
|
||||
t.style(alt[i & 1]);
|
||||
t.move(r + i * 2, c);
|
||||
printU64Hex(regs[i * 2]->_u64);
|
||||
t.move(r + i * 2, c + 17);
|
||||
printU64Hex(regs[i * 2 + 1]->_u64);
|
||||
}
|
||||
|
||||
t.move(r += 16, c);
|
||||
r++;
|
||||
for (i32 j = 0; j < 4; j++) {
|
||||
t.style(alt[j & 1]);
|
||||
t.move(r + j * 2, c);
|
||||
printU64Hex(*sys_regs[j * 2]);
|
||||
t.move(r + j * 2, c + 17);
|
||||
printU64Hex(*sys_regs[j * 2 + 1]);
|
||||
}
|
||||
|
||||
t.move(r += 8, c);
|
||||
r++;
|
||||
for (i32 j = 0; j < 1; j++) {
|
||||
t.style(alt[j & 1]);
|
||||
t.move(r + j * 2, c);
|
||||
printU64Hex(regs[16 + j * 2]->_u64);
|
||||
t.move(r + j * 2, c + 17);
|
||||
printU64Hex(regs[16 + j * 2 + 1]->_u64);
|
||||
}
|
||||
|
||||
t.flush();
|
||||
}
|
||||
|
||||
u32 addressWidth(isize ramSize) {
|
||||
if (ramSize == 0) return 1;
|
||||
isize maxAddr = ramSize - 1;
|
||||
u32 digits = 0;
|
||||
// Shift by increments of 4 (one hex nibble)
|
||||
// We use a do-while to ensure at least 1 digit is returned for small RAMs
|
||||
do {
|
||||
digits++;
|
||||
maxAddr >>= 4;
|
||||
} while (maxAddr > 0);
|
||||
|
||||
return digits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a vertical scrollbar
|
||||
* @param x The column where the bar should be placed (usually box_x + width - 1)
|
||||
* @param y The starting row of the track (usually box_y + 1)
|
||||
* @param trackHeight The internal height of the box (box_height - 2)
|
||||
* @param progress The current progress
|
||||
* @param total The total
|
||||
*/
|
||||
void drawScrollThumb(Terminal& term, u32 x, u32 y, u32 trackHeight, isize progress, isize total) {
|
||||
if (total == 0 || trackHeight <= 0) return;
|
||||
|
||||
// 1. Draw the background track (Light Shade: ░)
|
||||
term.style(Terminal::FG_B_BLACK); // Dim the track
|
||||
for (u32 i = 0; i < trackHeight; ++i) {
|
||||
term.move(i32(y + i), i32(x)).print("░");
|
||||
}
|
||||
|
||||
// 2. Calculate Thumb Position
|
||||
// Cap progress to total to avoid overflow
|
||||
if (progress > total) progress = total;
|
||||
|
||||
// Calculate ratio (0.0 to 1.0)
|
||||
f64 ratio = f64(progress) / f64(total);
|
||||
|
||||
// Map to track coordinates
|
||||
u32 thumbOffset = u32(ratio * (trackHeight - 1));
|
||||
|
||||
// 3. Draw the Thumb (Full Block: █)
|
||||
term.move(i32(y + thumbOffset), i32(x));
|
||||
term.style(Terminal::FG_WHITE).print("█");
|
||||
term.style(Terminal::RESET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a hex dump of memory within a styled terminal box.
|
||||
* @param term Reference to your Terminal instance
|
||||
* @param ram The RAM
|
||||
* @param scrollPos The starting address to display
|
||||
* @param x Starting column
|
||||
* @param y Starting row
|
||||
* @param width Width of the box
|
||||
* @param height Height of the box
|
||||
*/
|
||||
void drawRAM(Terminal& term, RAM& ram, u64 scrollPos) {
|
||||
// 1. Draw the container box
|
||||
u32 y = 3;
|
||||
u32 height = 36;
|
||||
|
||||
// 2. Configuration for the hex layout
|
||||
u32 addrWidth = addressWidth(ram.size());
|
||||
u32 bytesPerRow = 8;
|
||||
u32 displayRows = height - 2; // Subtract top/bottom borders
|
||||
u32 width = (2 + 2 + 16 + 7 + 3 + 8 + 4) + addrWidth;
|
||||
u32 x = 37;
|
||||
|
||||
// create box
|
||||
term.drawBox(i32(y), i32(x), i32(width), i32(height), "RAM");
|
||||
drawScrollThumb(term, x + width - 2, y + 1, height - 2, scrollPos, ram.size());
|
||||
|
||||
// Ensure scrollPos is within bounds and aligned
|
||||
//if (scrollPos < 0) scrollPos = 0;
|
||||
if (scrollPos > ram.size()) scrollPos = ram.size();
|
||||
|
||||
for (u32 i = 0; i < displayRows; ++i) {
|
||||
isize currentRowAddr = scrollPos + (i * bytesPerRow);
|
||||
|
||||
// address lock
|
||||
if (currentRowAddr >= ram.size()) {
|
||||
term.move(i32(y + 1 + i), i32(x + 1));
|
||||
term.print(std::string(width - 3, ' '));
|
||||
continue;
|
||||
}
|
||||
|
||||
std::stringstream ssaddr;
|
||||
std::stringstream ss;
|
||||
|
||||
// setup ss
|
||||
ssaddr << std::setfill('0') << std::uppercase << std::hex;
|
||||
ss << std::setfill('0') << std::uppercase << std::hex;
|
||||
|
||||
// address
|
||||
ssaddr << std::setw(i32(addrWidth)) << currentRowAddr << " ";
|
||||
|
||||
// Hex Bytes
|
||||
std::string asciiPart = "";
|
||||
for (u32 j = 0; j < bytesPerRow; ++j) {
|
||||
isize targetAddr = currentRowAddr + j;
|
||||
if (targetAddr >= ram.size()) {
|
||||
ss << ""; // Padding for end of memory
|
||||
asciiPart += "";
|
||||
continue;
|
||||
}
|
||||
|
||||
u8 byte = ram[targetAddr];
|
||||
ss << std::setfill('0') << std::setw(2) << std::hex << u32(byte) << " ";
|
||||
asciiPart += (std::isprint(byte) ? char(byte) : '.');
|
||||
}
|
||||
|
||||
// --- Combine and Print ---
|
||||
term.move(i32(y + 1 + i), i32(x + 2)); // Move inside the box
|
||||
term.style(Terminal::FG_B_CYAN).print(ssaddr.str()); // Hex part in Cyan
|
||||
term.style(Terminal::FG_WHITE).print(ss.str());
|
||||
term.style(Terminal::FG_B_YELLOW).print(" | ");
|
||||
term.style(Terminal::FG_WHITE).print(asciiPart); // ASCII part in White
|
||||
}
|
||||
|
||||
term.style(Terminal::RESET);
|
||||
term.flush();
|
||||
}
|
||||
|
||||
std::string getTimestamp() {
|
||||
std::time_t t = std::time(nullptr);
|
||||
std::tm lt;
|
||||
#if defined(SPIDER_OS_WINDOWS)
|
||||
localtime_s(<, &t);
|
||||
#endif
|
||||
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
|
||||
localtime_r(&t, <);
|
||||
#endif
|
||||
return std::format("{:02}:{:02}:{:02} {:02}/{:02}/{}",
|
||||
lt.tm_hour, lt.tm_min, lt.tm_sec,
|
||||
lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900);
|
||||
}
|
||||
|
||||
void drawTime(Terminal& t) {
|
||||
//auto now = std::chrono::system_clock::now();
|
||||
//auto now_l = std::chrono::current_zone()->to_local(now);
|
||||
//auto now_s = std::chrono::floor<std::chrono::seconds>(now_l);
|
||||
//std::string time_str = std::format("{:%H:%M:%S}", now_s); // Format: HH:mm:ss
|
||||
//std::string date_str = std::format("{:%d/%m/%Y}", now_s); // Format: dd/MM/YYYY
|
||||
|
||||
t.move(1, 76);
|
||||
t.style(Terminal::RESET);
|
||||
t.print(" | ").style(Terminal::FG_GREEN).print(getTimestamp());
|
||||
}
|
||||
|
||||
void redraw(Terminal& t, Runtime& r, u64 scroll) {
|
||||
// draw CPU, RAM
|
||||
drawCPU(t, r.cpu);
|
||||
drawRAM(t, r.ram, scroll);
|
||||
}
|
||||
|
||||
int liveDebugMain() {
|
||||
Terminal t;
|
||||
Runtime runtime(1024);
|
||||
|
||||
|
||||
InstrReelFixed fix(100);
|
||||
|
||||
|
||||
|
||||
runtime.hookReel(&fix, false);
|
||||
|
||||
|
||||
|
||||
bool running = true, update = true;
|
||||
u64 ramScroll = 0;
|
||||
u8 key = Terminal::UNKNOWN;
|
||||
|
||||
t.println("Starting Spider live debug...");
|
||||
t.altbuff(true).cursor(false);
|
||||
|
||||
drawTime(t);
|
||||
drawHead(t);
|
||||
drawCPUTempl(t);
|
||||
|
||||
// delay for time
|
||||
auto last_exec = std::chrono::steady_clock::now();
|
||||
auto delay = std::chrono::milliseconds(1000);
|
||||
|
||||
while (running) {
|
||||
// draw time
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
if (now - last_exec >= delay) {
|
||||
drawTime(t);
|
||||
last_exec = now;
|
||||
}
|
||||
|
||||
// redraw something if it updated
|
||||
if (update) {
|
||||
redraw(t, runtime, ramScroll);
|
||||
update = false;
|
||||
}
|
||||
|
||||
// Handle Input
|
||||
key = t.getKeyNb();
|
||||
switch (key) {
|
||||
case Terminal::ESC:
|
||||
running = false;
|
||||
break;
|
||||
case Terminal::UP:
|
||||
if (ramScroll >= 16) ramScroll -= 16;
|
||||
update = true;
|
||||
break;
|
||||
case Terminal::DOWN:
|
||||
if (runtime.ram.size() >= 16 && ramScroll <= runtime.ram.size() - 16) ramScroll += 16;
|
||||
update = true;
|
||||
break;
|
||||
case Terminal::ENTER:
|
||||
update = true;
|
||||
runtime.cpu.fetchInstr();
|
||||
runtime.cpu.execute(); // looks up instrMap[_opcode] & calls the correct instruction method (e.g. FMUL)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
|
||||
t.altbuff(false).println("Stopped Spider live debug.").flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
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();
|
||||
|
||||
}
|
||||
748
src/spider/runtime/instr/InstrMap.cpp
Normal file
748
src/spider/runtime/instr/InstrMap.cpp
Normal file
@@ -0,0 +1,748 @@
|
||||
/**
|
||||
* @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
|
||||
&CPU::LLGS, // 0x0F1 — Spider ASCII art (LLGS easter egg)
|
||||
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;
|
||||
case 0x0F1: LLGS(); break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace spider
|
||||
@@ -1,9 +0,0 @@
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
void CPU::NOP() {
|
||||
// No Operation //
|
||||
}
|
||||
|
||||
}
|
||||
356
src/spider/runtime/instr/Instr_000-01F.cpp
Normal file
356
src/spider/runtime/instr/Instr_000-01F.cpp
Normal file
@@ -0,0 +1,356 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
void CPU::NOP() {
|
||||
// TODO: Implement NOP
|
||||
}
|
||||
|
||||
void CPU::SPDR() {
|
||||
// TODO: Implement SPDR
|
||||
}
|
||||
|
||||
void CPU::MMODE() {
|
||||
// TODO: Implement MMODE
|
||||
}
|
||||
|
||||
void CPU::INT() {
|
||||
// TODO: Implement INT
|
||||
}
|
||||
|
||||
void CPU::LRV() {
|
||||
// TODO: Implement LRV
|
||||
}
|
||||
|
||||
void CPU::FSR() {
|
||||
// TODO: Implement FSR
|
||||
}
|
||||
|
||||
void CPU::FIR() {
|
||||
// TODO: Implement FIR
|
||||
}
|
||||
|
||||
void CPU::FZR() {
|
||||
// TODO: Implement FZR
|
||||
}
|
||||
|
||||
void CPU::LSR() {
|
||||
// TODO: Implement LSR
|
||||
}
|
||||
|
||||
void CPU::FVR() {
|
||||
// TODO: Implement FVR
|
||||
}
|
||||
|
||||
void CPU::MOV() {
|
||||
// TODO: Implement MOV
|
||||
}
|
||||
|
||||
void CPU::MOR() {
|
||||
// TODO: Implement MOR
|
||||
}
|
||||
|
||||
void CPU::AMOV() {
|
||||
// TODO: Implement AMOV
|
||||
}
|
||||
|
||||
void CPU::SWP() {
|
||||
// TODO: Implement SWP
|
||||
}
|
||||
|
||||
void CPU::AHM() {
|
||||
// TODO: Implement AHM
|
||||
}
|
||||
|
||||
void CPU::COM() {
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_u8 = ~_dst->_u8;
|
||||
break;
|
||||
case 0b01: //short
|
||||
_dst->_u16 = ~_dst->_u16;
|
||||
break;
|
||||
case 0b10: //int
|
||||
_dst->_u32 = ~_dst->_u32;
|
||||
break;
|
||||
case 0b11: //long
|
||||
_dst->_u64 = ~_dst->_u64;
|
||||
break;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::NEG() {
|
||||
// TODO: Implement NEG
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_u8 = 1 + ~_dst->_u8;
|
||||
break;
|
||||
case 0b01: //short
|
||||
_dst->_u16 = 1+ ~_dst->_u16;
|
||||
break;
|
||||
case 0b10: //int
|
||||
_dst->_u32 = 1 + ~_dst->_u32;
|
||||
break;
|
||||
case 0b11: //long
|
||||
_dst->_u64 = 1 + ~_dst->_u64;
|
||||
break;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::EXS() { // THIS IS INCORRECT!!!
|
||||
// TODO: Implement EXS
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_i16 = static_cast<i16>(_dst->_i8);
|
||||
break;
|
||||
case 0b01: //short
|
||||
_dst->_i32 = static_cast<i32>(_dst->_i16);
|
||||
break;
|
||||
case 0b10: //int
|
||||
_dst->_i64 = static_cast<i64>(_dst->_i32);
|
||||
break;
|
||||
case 0b11: //long
|
||||
_dst->_i64 = _dst->_i64;
|
||||
break;
|
||||
}
|
||||
_dst->_u32 = _dst->_u8;
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::INC() {
|
||||
// TODO: Implement INC
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_u8 += 1;
|
||||
case 0b01: //short
|
||||
_dst->_u16 += 1;
|
||||
case 0b10: //int
|
||||
_dst->_u32 += 1;
|
||||
case 0b11: //long
|
||||
_dst->_u64 += 1;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::DEC() {
|
||||
// TODO: Implement DEC
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_u8 -= 1;
|
||||
case 0b01: //short
|
||||
_dst->_u16 -= 1;
|
||||
case 0b10: //int
|
||||
_dst->_u32 -= 1;
|
||||
case 0b11: //long
|
||||
_dst->_u64 -= 1;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::ADD() {
|
||||
// TODO: Implement ADD
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_u8 += _src->_u8;
|
||||
case 0b01: //short
|
||||
_dst->_u16 += _src->_u16;
|
||||
case 0b10: //int
|
||||
_dst->_u32 += _src->_u32;
|
||||
case 0b11: //long
|
||||
_dst->_u64 += _src->_u64;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::SUB() {
|
||||
// TODO: Implement SUB
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_u8 -= _src->_u8;
|
||||
case 0b01: //short
|
||||
_dst->_u16 -= _src->_u16;
|
||||
case 0b10: //int
|
||||
_dst->_u32 -= _src->_u32;
|
||||
case 0b11: //long
|
||||
_dst->_u64 -= _src->_u64;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::MUL() {
|
||||
// TODO: Implement MUL
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_i8 = _src->_i8 * _dst->_i8;
|
||||
case 0b01: //short
|
||||
_dst->_i16 = _src->_i16 * _dst->_i16;
|
||||
case 0b10: //int
|
||||
_dst->_i32 = _src->_i32 * _dst->_i32;
|
||||
case 0b11: //long
|
||||
_dst->_i64 = _src->_i64 * _dst->_i64;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::UMUL() {
|
||||
// TODO: Implement UMUL
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_u8 = _src->_u8 * _dst->_u8;
|
||||
case 0b01: //short
|
||||
_dst->_u16 = _src->_u16 * _dst->_u16;
|
||||
case 0b10: //int
|
||||
_dst->_u32 = _src->_u32 * _dst->_u32;
|
||||
case 0b11: //long
|
||||
_dst->_u64 = _src->_u64 * _dst->_u64;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::DIV() {
|
||||
// TODO: Implement DIV
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_i8 = _dst->_i8 / _src->_i8;
|
||||
case 0b01: //short
|
||||
_dst->_i16 = _dst->_i16 / _src->_i16;
|
||||
case 0b10: //int
|
||||
_dst->_i32 = _dst->_i32 / _src->_i32;
|
||||
case 0b11: //long
|
||||
_dst->_i64 = _dst->_i64 / _src->_i64;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::UDIV() {
|
||||
// TODO: Implement UDIV
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_u8 = _dst->_u8 / _src->_u8;
|
||||
case 0b01: //short
|
||||
_dst->_u16 = _dst->_u16 / _src->_u16;
|
||||
case 0b10: //int
|
||||
_dst->_u32 = _dst->_u32 / _src->_u32;
|
||||
case 0b11: //long
|
||||
_dst->_u64 = _dst->_u64 / _src->_u64;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::MOD() {
|
||||
// TODO: Implement MOD
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_i8 = _dst->_i8 % _src->_i8;
|
||||
case 0b01: //short
|
||||
_dst->_i16 = _dst->_i16 % _src->_i16;
|
||||
case 0b10: //int
|
||||
_dst->_i32 = _dst->_i32 % _src->_i32;
|
||||
case 0b11: //long
|
||||
_dst->_i64 = _dst->_i64 % _src->_i64;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::UMOD() {
|
||||
// TODO: Implement UMOD
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_u8 = _dst->_u8 % _src->_u8;
|
||||
case 0b01: //short
|
||||
_dst->_u16 = _dst->_u16 % _src->_u16;
|
||||
case 0b10: //int
|
||||
_dst->_u32 = _dst->_u32 % _src->_u32;
|
||||
case 0b11: //long
|
||||
_dst->_u64 = _dst->_u64 % _src->_u64;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::DMOD() {
|
||||
// TODO: Implement DMOD
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
RX._i8 = _dst->_i8 / _src->_i8;
|
||||
RY._i8 = _dst->_i8 % _src->_i8;
|
||||
case 0b01: //short
|
||||
RX._i16 = _dst->_i16 / _src->_i16;
|
||||
RY._i16 = _dst->_i16 % _src->_i16;
|
||||
case 0b10: //int
|
||||
RX._i32 = _dst->_i32 / _src->_i32;
|
||||
RY._i32 = _dst->_i32 % _src->_i32;
|
||||
case 0b11: //long
|
||||
RX._i64 = _dst->_i64 / _src->_i64;
|
||||
RY._i64 = _dst->_i64 % _src->_i64;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::UDMD() {
|
||||
// TODO: Implement UDMD
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
RX._u8 = _dst->_u8 / _src->_u8;
|
||||
RY._u8 = _dst->_u8 % _src->_u8;
|
||||
case 0b01: //short
|
||||
RX._u16 = _dst->_u16 / _src->_u16;
|
||||
RY._u16 = _dst->_u16 % _src->_u16;
|
||||
case 0b10: //int
|
||||
RX._u32 = _dst->_u32 / _src->_u32;
|
||||
RY._u32 = _dst->_u32 % _src->_u32;
|
||||
case 0b11: //long
|
||||
RX._u64 = _dst->_u64 / _src->_u64;
|
||||
RY._u64 = _dst->_u64 % _src->_u64;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::FBT() {
|
||||
// TODO: Implement FBT
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
RF = (RF & ~(0x3 << 9)) | ((_dst->_u8 >> 9) & 0x3) << 9;
|
||||
case 0b01: //short
|
||||
RF = (RF & ~(0x3 << 9)) | ((_dst->_u16 >> 9) & 0x3) << 9;
|
||||
case 0b10: //int
|
||||
RF = (RF & ~(0x3 << 9)) | ((_dst->_u32 >> 9) & 0x3) << 9;
|
||||
case 0b11: //long
|
||||
RF = (RF & ~(0x3 << 9)) | ((_dst->_u64 >> 9) & 0x3) << 9;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
}
|
||||
197
src/spider/runtime/instr/Instr_020-03F.cpp
Normal file
197
src/spider/runtime/instr/Instr_020-03F.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
void CPU::STB() {
|
||||
// TODO: Implement STB
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_u8 |= (1 << _src->_u8);
|
||||
case 0b01: //short
|
||||
_dst->_u16 |= (1 << _src->_u16);
|
||||
case 0b10: //int
|
||||
_dst->_u32 |= (1 << _src->_u32);
|
||||
case 0b11: //long
|
||||
_dst->_u64 |= (1 << _src->_u64);
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::CRB() {
|
||||
// TODO: Implement CRB
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_u8 &= ~(1 << _src->_u8);
|
||||
case 0b01: //short
|
||||
_dst->_u16 &= ~(1 << _src->_u16);
|
||||
case 0b10: //int
|
||||
_dst->_u32 &= ~(1 << _src->_u32);
|
||||
case 0b11: //long
|
||||
_dst->_u64 &= ~(1 << _src->_u64);
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::TSB() {
|
||||
// TODO: Implement TSB
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
switch (((RF >> _src->_u8) & 1) != ((_dst->_u8 >> _src->_u8) & 1)){
|
||||
case 1:
|
||||
RF |= (1 << _src->_u8);
|
||||
|
||||
case 0:
|
||||
RF &= ~(1 << _src->_u8);
|
||||
}
|
||||
case 0b01: //short
|
||||
switch (((RF >> _src->_u16) & 1) != ((_dst->_u16 >> _src->_u16) & 1)){
|
||||
case 1:
|
||||
RF |= (1 << _src->_u16);
|
||||
|
||||
case 0:
|
||||
RF &= ~(1 << _src->_u16);
|
||||
}
|
||||
case 0b10: //int
|
||||
switch (((RF >> _src->_u32) & 1) != ((_dst->_u32 >> _src->_u32) & 1)){
|
||||
case 1:
|
||||
RF |= (1 << _src->_u32);
|
||||
|
||||
case 0:
|
||||
RF &= ~(1 << _src->_u32);
|
||||
}
|
||||
case 0b11: //long
|
||||
switch (((RF >> _src->_u64) & 1) != ((_dst->_u64 >> _src->_u64) & 1)){
|
||||
case 1:
|
||||
RF |= (1 << _src->_u64);
|
||||
|
||||
case 0:
|
||||
RF &= ~(1 << _src->_u64);
|
||||
}
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::BOOL() {
|
||||
// TODO: Implement BOOL
|
||||
fetchOperDst();
|
||||
switch(_size){
|
||||
case 0b00: //byte
|
||||
_dst->_u8 = _dst != 0;
|
||||
case 0b01: //short
|
||||
_dst->_u16 = _dst != 0;
|
||||
case 0b10: //int
|
||||
_dst->_u32 = _dst != 0;
|
||||
case 0b11: //long
|
||||
_dst->_u64 = _dst != 0;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::NOT() {
|
||||
// TODO: Implement NOT
|
||||
}
|
||||
|
||||
void CPU::AND() {
|
||||
// TODO: Implement AND
|
||||
}
|
||||
|
||||
void CPU::OR() {
|
||||
// TODO: Implement OR
|
||||
}
|
||||
|
||||
void CPU::XOR() {
|
||||
// TODO: Implement XOR
|
||||
}
|
||||
|
||||
void CPU::SHL() {
|
||||
// TODO: Implement SHL
|
||||
}
|
||||
|
||||
void CPU::SHR() {
|
||||
// TODO: Implement SHR
|
||||
}
|
||||
|
||||
void CPU::SSR() {
|
||||
// TODO: Implement SSR
|
||||
}
|
||||
|
||||
void CPU::ROL() {
|
||||
// TODO: Implement ROL
|
||||
}
|
||||
|
||||
void CPU::ROR() {
|
||||
// TODO: Implement ROR
|
||||
}
|
||||
|
||||
void CPU::CNT() {
|
||||
// TODO: Implement CNT
|
||||
}
|
||||
|
||||
void CPU::EQ() {
|
||||
// TODO: Implement EQ
|
||||
}
|
||||
|
||||
void CPU::NE() {
|
||||
// TODO: Implement NE
|
||||
}
|
||||
|
||||
void CPU::GT() {
|
||||
// TODO: Implement GT
|
||||
}
|
||||
|
||||
void CPU::GE() {
|
||||
// TODO: Implement GE
|
||||
}
|
||||
|
||||
void CPU::LT() {
|
||||
// TODO: Implement LT
|
||||
}
|
||||
|
||||
void CPU::LE() {
|
||||
// TODO: Implement LE
|
||||
}
|
||||
|
||||
void CPU::JMP() {
|
||||
// TODO: Implement JMP
|
||||
}
|
||||
|
||||
void CPU::JEQ() {
|
||||
// TODO: Implement JEQ
|
||||
}
|
||||
|
||||
void CPU::JNE() {
|
||||
// TODO: Implement JNE
|
||||
}
|
||||
|
||||
void CPU::JIF() {
|
||||
// TODO: Implement JIF
|
||||
}
|
||||
|
||||
void CPU::JMR() {
|
||||
// TODO: Implement JMR
|
||||
}
|
||||
|
||||
void CPU::JER() {
|
||||
// TODO: Implement JER
|
||||
}
|
||||
|
||||
void CPU::JNR() {
|
||||
// TODO: Implement JNR
|
||||
}
|
||||
|
||||
void CPU::JIR() {
|
||||
// TODO: Implement JIR
|
||||
}
|
||||
|
||||
}
|
||||
279
src/spider/runtime/instr/Instr_040-05F.cpp
Normal file
279
src/spider/runtime/instr/Instr_040-05F.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
#include <cmath> // provides std::fmod, std::fma and cast support
|
||||
|
||||
|
||||
namespace spider {
|
||||
|
||||
void CPU::SFB() {
|
||||
// TODO: Implement SFB
|
||||
}
|
||||
|
||||
void CPU::LFB() {
|
||||
// TODO: Implement LFB
|
||||
}
|
||||
|
||||
void CPU::JUF() {
|
||||
// TODO: Implement JUF
|
||||
}
|
||||
|
||||
void CPU::JUR() {
|
||||
// TODO: Implement JUR
|
||||
}
|
||||
|
||||
void CPU::PUSH() {
|
||||
// TODO: Implement PUSH
|
||||
}
|
||||
|
||||
void CPU::POP() {
|
||||
// TODO: Implement POP
|
||||
}
|
||||
|
||||
void CPU::ALLOC() {
|
||||
// TODO: Implement ALLOC
|
||||
}
|
||||
|
||||
void CPU::HFREE() {
|
||||
// TODO: Implement HFREE
|
||||
}
|
||||
|
||||
void CPU::CALL() {
|
||||
// TODO: Implement CALL
|
||||
}
|
||||
|
||||
void CPU::RET() {
|
||||
// TODO: Implement RET
|
||||
}
|
||||
|
||||
void CPU::EDI() {
|
||||
// TODO: Implement EDI
|
||||
}
|
||||
|
||||
void CPU::SHSS() {
|
||||
// TODO: Implement SHSS
|
||||
}
|
||||
|
||||
void CPU::FLI() {
|
||||
// TODO: Implement FLI
|
||||
}
|
||||
|
||||
void CPU::FNEG() {
|
||||
// TODO: Implement FNEG
|
||||
}
|
||||
|
||||
void CPU::FADD() {
|
||||
// TODO: Implement FADD
|
||||
}
|
||||
|
||||
void CPU::FSUB() {
|
||||
// TODO: Implement FSUB
|
||||
}
|
||||
|
||||
// ── 0x054 — FMUL: Float Multiplication ───────────────────────────────────
|
||||
void CPU::FMUL() {
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch (_size) {
|
||||
case 0b10: _dst->_f32 *= _src->_f32; break; // f32
|
||||
case 0b11: _dst->_f64 *= _src->_f64; break; // f64
|
||||
default: break; // invalid size
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x055 — FDIV: Float Division ─────────────────────────────────────────
|
||||
void CPU::FDIV() {
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch (_size) {
|
||||
case 0b10: _dst->_f32 /= _src->_f32; break;
|
||||
case 0b11: _dst->_f64 /= _src->_f64; break;
|
||||
default: break;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x056 — FMOD: Float Modulus ──────────────────────────────────────────
|
||||
// C++ has no % for floats — std::fmod performs the equivalent operation
|
||||
void CPU::FMOD() {
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch (_size) {
|
||||
case 0b10: _dst->_f32 = std::fmod(_dst->_f32, _src->_f32); break;
|
||||
case 0b11: _dst->_f64 = std::fmod(_dst->_f64, _src->_f64); break;
|
||||
default: break;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x057 — FDMOD: Float Division and Modulus ────────────────────────────
|
||||
// dst / src = RX (quotient) * src + RY (remainder)
|
||||
void CPU::FDMOD() {
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
switch (_size) {
|
||||
case 0b10: {
|
||||
f32 q = static_cast<f32>(static_cast<i32>(_dst->_f32 / _src->_f32));
|
||||
f32 r = _dst->_f32 - (q * _src->_f32);
|
||||
RX._f32 = q;
|
||||
RY._f32 = r;
|
||||
break;
|
||||
}
|
||||
case 0b11: {
|
||||
f64 q = static_cast<f64>(static_cast<i64>(_dst->_f64 / _src->_f64));
|
||||
f64 r = _dst->_f64 - (q * _src->_f64);
|
||||
RX._f64 = q;
|
||||
RY._f64 = r;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x058 — FEPS: Set Float Epsilon Value ────────────────────────────────
|
||||
// Loads the epsilon value into RN (the epsilon register)
|
||||
void CPU::FEPS() {
|
||||
fetchOperDst();
|
||||
switch (_size) {
|
||||
case 0b10: RN = _dst->_u32; break; // store f32 bits in RN
|
||||
case 0b11: RN = _dst->_u64; break; // store f64 bits in RN
|
||||
default: break;
|
||||
}
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x059 — FEEP: Float Enable/Disable Epsilon ───────────────────────────
|
||||
// Bit 12 of RF is the Epsilon Enable flag
|
||||
void CPU::FEEP() {
|
||||
fetchOperDst();
|
||||
constexpr u64 EPSILON_ENABLE_BIT = (1ULL << 12);
|
||||
if (_dst->_u64) RF |= EPSILON_ENABLE_BIT; // non-zero → enable
|
||||
else RF &= ~EPSILON_ENABLE_BIT; // zero → disable
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x05A — FEQ: Float Equal ──────────────────────────────────────────────
|
||||
// Sets bit 10 (Zero/Equal flag) in RF if dst == src
|
||||
void CPU::FEQ() {
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
constexpr u64 ZERO_FLAG = (1ULL << 10);
|
||||
bool equal = false;
|
||||
switch (_size) {
|
||||
case 0b10: equal = (_dst->_f32 == _src->_f32); break;
|
||||
case 0b11: equal = (_dst->_f64 == _src->_f64); break;
|
||||
default: break;
|
||||
}
|
||||
if (equal) RF |= ZERO_FLAG;
|
||||
else RF &= ~ZERO_FLAG;
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x05B — FNE: Float Not Equal ─────────────────────────────────────────
|
||||
void CPU::FNE() {
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
constexpr u64 ZERO_FLAG = (1ULL << 10);
|
||||
bool notEqual = false;
|
||||
switch (_size) {
|
||||
case 0b10: notEqual = (_dst->_f32 != _src->_f32); break;
|
||||
case 0b11: notEqual = (_dst->_f64 != _src->_f64); break;
|
||||
default: break;
|
||||
}
|
||||
if (notEqual) RF |= ZERO_FLAG;
|
||||
else RF &= ~ZERO_FLAG;
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x05C — FGT: Float Greater Than ──────────────────────────────────────
|
||||
// Sets/clears bit 9 (Negative flag) in RF
|
||||
void CPU::FGT() {
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
constexpr u64 NEGATIVE_FLAG = (1ULL << 9);
|
||||
bool gt = false;
|
||||
switch (_size) {
|
||||
case 0b10: gt = (_dst->_f32 > _src->_f32); break;
|
||||
case 0b11: gt = (_dst->_f64 > _src->_f64); break;
|
||||
default: break;
|
||||
}
|
||||
if (gt) RF &= ~NEGATIVE_FLAG;
|
||||
else RF |= NEGATIVE_FLAG;
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x05D — FGE: Float Greater or Equal ──────────────────────────────────
|
||||
void CPU::FGE() {
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
constexpr u64 NEGATIVE_FLAG = (1ULL << 9);
|
||||
constexpr u64 ZERO_FLAG = (1ULL << 10);
|
||||
bool ge = false;
|
||||
bool eq = false;
|
||||
switch (_size) {
|
||||
case 0b10:
|
||||
ge = (_dst->_f32 >= _src->_f32);
|
||||
eq = (_dst->_f32 == _src->_f32);
|
||||
break;
|
||||
case 0b11:
|
||||
ge = (_dst->_f64 >= _src->_f64);
|
||||
eq = (_dst->_f64 == _src->_f64);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (ge) RF &= ~NEGATIVE_FLAG;
|
||||
else RF |= NEGATIVE_FLAG;
|
||||
if (eq) RF |= ZERO_FLAG;
|
||||
else RF &= ~ZERO_FLAG;
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x05E — FLT: Float Lower Than ────────────────────────────────────────
|
||||
void CPU::FLT() {
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
constexpr u64 NEGATIVE_FLAG = (1ULL << 9);
|
||||
bool lt = false;
|
||||
switch (_size) {
|
||||
case 0b10: lt = (_dst->_f32 < _src->_f32); break;
|
||||
case 0b11: lt = (_dst->_f64 < _src->_f64); break;
|
||||
default: break;
|
||||
}
|
||||
if (lt) RF |= NEGATIVE_FLAG;
|
||||
else RF &= ~NEGATIVE_FLAG;
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x05F — FLE: Float Lower or Equal ────────────────────────────────────
|
||||
void CPU::FLE() {
|
||||
fetchOperSrc();
|
||||
fetchOperDst();
|
||||
constexpr u64 NEGATIVE_FLAG = (1ULL << 9);
|
||||
constexpr u64 ZERO_FLAG = (1ULL << 10);
|
||||
bool le = false;
|
||||
bool eq = false;
|
||||
switch (_size) {
|
||||
case 0b10:
|
||||
le = (_dst->_f32 <= _src->_f32);
|
||||
eq = (_dst->_f32 == _src->_f32);
|
||||
break;
|
||||
case 0b11:
|
||||
le = (_dst->_f64 <= _src->_f64);
|
||||
eq = (_dst->_f64 == _src->_f64);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (le) RF &= ~NEGATIVE_FLAG;
|
||||
else RF |= NEGATIVE_FLAG;
|
||||
if (eq) RF |= ZERO_FLAG;
|
||||
else RF &= ~ZERO_FLAG;
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
148
src/spider/runtime/instr/Instr_060-07F.cpp
Normal file
148
src/spider/runtime/instr/Instr_060-07F.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
#include <cmath> // provides std::fmod, std::fma and cast support
|
||||
|
||||
|
||||
namespace spider {
|
||||
|
||||
// ── 0x060 — F2D: Float (f32) to Double (f64) ─────────────────────────────
|
||||
// Widening conversion — no precision is lost
|
||||
void CPU::F2D() {
|
||||
fetchOperDst();
|
||||
_dst->_f64 = static_cast<f64>(_dst->_f32);
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x061 — D2F: Double (f64) to Float (f32) ─────────────────────────────
|
||||
// Narrowing conversion — precision may be lost
|
||||
void CPU::D2F() {
|
||||
fetchOperDst();
|
||||
_dst->_f32 = static_cast<f32>(_dst->_f64);
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x062 — I2F: Integer (i32) to Float (f32) ────────────────────────────
|
||||
void CPU::I2F() {
|
||||
fetchOperDst();
|
||||
_dst->_f32 = static_cast<f32>(_dst->_u32);
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x063 — I2D: Integer (i32) to Double (f64) ───────────────────────────
|
||||
void CPU::I2D() {
|
||||
fetchOperDst();
|
||||
_dst->_f64 = static_cast<f64>(_dst->_u32);
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x064 — L2F: Long (i64) to Float (f32) ───────────────────────────────
|
||||
void CPU::L2F() {
|
||||
fetchOperDst();
|
||||
_dst->_f32 = static_cast<f32>(_dst->_u64);
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x065 — L2D: Long (i64) to Double (f64) ──────────────────────────────
|
||||
void CPU::L2D() {
|
||||
fetchOperDst();
|
||||
_dst->_f64 = static_cast<f64>(_dst->_u64);
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x066 — F2I: Float (f32) to Integer (i32) ────────────────────────────
|
||||
// Truncates toward zero
|
||||
void CPU::F2I() {
|
||||
fetchOperDst();
|
||||
_dst->_u32 = static_cast<u32>(_dst->_f32);
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
// ── 0x067 — F2L: Float (f32) to Long (i64) ───────────────────────────────
|
||||
// Truncates toward zero
|
||||
void CPU::F2L() {
|
||||
fetchOperDst();
|
||||
_dst->_u64 = static_cast<u64>(_dst->_f32);
|
||||
(this->*_post)();
|
||||
}
|
||||
|
||||
void CPU::D2I() {
|
||||
// TODO: Implement D2I
|
||||
}
|
||||
|
||||
void CPU::D2L() {
|
||||
// TODO: Implement D2L
|
||||
}
|
||||
|
||||
void CPU::SIN() {
|
||||
// TODO: Implement SIN
|
||||
}
|
||||
|
||||
void CPU::COS() {
|
||||
// TODO: Implement COS
|
||||
}
|
||||
|
||||
void CPU::TAN() {
|
||||
// TODO: Implement TAN
|
||||
}
|
||||
|
||||
void CPU::ASIN() {
|
||||
// TODO: Implement ASIN
|
||||
}
|
||||
|
||||
void CPU::ACOS() {
|
||||
// TODO: Implement ACOS
|
||||
}
|
||||
|
||||
void CPU::ATAN() {
|
||||
// TODO: Implement ATAN
|
||||
}
|
||||
|
||||
void CPU::ATAN2() {
|
||||
// TODO: Implement ATAN2
|
||||
}
|
||||
|
||||
void CPU::EXP() {
|
||||
// TODO: Implement EXP
|
||||
}
|
||||
|
||||
void CPU::LOG() {
|
||||
// TODO: Implement LOG
|
||||
}
|
||||
|
||||
void CPU::LOGAB() {
|
||||
// TODO: Implement LOGAB
|
||||
}
|
||||
|
||||
void CPU::POW() {
|
||||
// TODO: Implement POW
|
||||
}
|
||||
|
||||
void CPU::SQRT() {
|
||||
// TODO: Implement SQRT
|
||||
}
|
||||
|
||||
void CPU::ROOT() {
|
||||
// TODO: Implement ROOT
|
||||
}
|
||||
|
||||
void CPU::ADC() {
|
||||
// TODO: Implement ADC
|
||||
}
|
||||
|
||||
void CPU::SWC() {
|
||||
// TODO: Implement SWC
|
||||
}
|
||||
|
||||
void CPU::MWO() {
|
||||
// TODO: Implement MWO
|
||||
}
|
||||
|
||||
void CPU::UMO() {
|
||||
// TODO: Implement UMO
|
||||
}
|
||||
|
||||
}
|
||||
62
src/spider/runtime/instr/Instr_080-09F.cpp
Normal file
62
src/spider/runtime/instr/Instr_080-09F.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
void CPU::MADD() {
|
||||
// TODO: Implement MADD
|
||||
}
|
||||
|
||||
void CPU::MSUB() {
|
||||
// TODO: Implement MSUB
|
||||
}
|
||||
|
||||
void CPU::MMUL() {
|
||||
// TODO: Implement MMUL
|
||||
}
|
||||
|
||||
void CPU::MINV() {
|
||||
// TODO: Implement MINV
|
||||
}
|
||||
|
||||
void CPU::MTRA() {
|
||||
// TODO: Implement MTRA
|
||||
}
|
||||
|
||||
void CPU::MDET() {
|
||||
// TODO: Implement MDET
|
||||
}
|
||||
|
||||
void CPU::QMKA() {
|
||||
// TODO: Implement QMKA
|
||||
}
|
||||
|
||||
void CPU::QMUL() {
|
||||
// TODO: Implement QMUL
|
||||
}
|
||||
|
||||
void CPU::XADD() {
|
||||
// TODO: Implement XADD
|
||||
}
|
||||
|
||||
void CPU::XSUB() {
|
||||
// TODO: Implement XSUB
|
||||
}
|
||||
|
||||
void CPU::XAMA() {
|
||||
// TODO: Implement XAMA
|
||||
}
|
||||
|
||||
void CPU::XMUL() {
|
||||
// TODO: Implement XMUL
|
||||
}
|
||||
|
||||
void CPU::XDIV() {
|
||||
// TODO: Implement XDIV
|
||||
}
|
||||
|
||||
}
|
||||
10
src/spider/runtime/instr/Instr_0A0-0BF.cpp
Normal file
10
src/spider/runtime/instr/Instr_0A0-0BF.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
}
|
||||
10
src/spider/runtime/instr/Instr_0C0-0DF.cpp
Normal file
10
src/spider/runtime/instr/Instr_0C0-0DF.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
}
|
||||
14
src/spider/runtime/instr/Instr_0E0-0FF.cpp
Normal file
14
src/spider/runtime/instr/Instr_0E0-0FF.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
void CPU::UPY() {
|
||||
// TODO: Implement UPY
|
||||
}
|
||||
|
||||
}
|
||||
10
src/spider/runtime/instr/Instr_100-11F.cpp
Normal file
10
src/spider/runtime/instr/Instr_100-11F.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
}
|
||||
10
src/spider/runtime/instr/Instr_120-13F.cpp
Normal file
10
src/spider/runtime/instr/Instr_120-13F.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
}
|
||||
10
src/spider/runtime/instr/Instr_140-15F.cpp
Normal file
10
src/spider/runtime/instr/Instr_140-15F.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
}
|
||||
10
src/spider/runtime/instr/Instr_160-17F.cpp
Normal file
10
src/spider/runtime/instr/Instr_160-17F.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
}
|
||||
10
src/spider/runtime/instr/Instr_180-19F.cpp
Normal file
10
src/spider/runtime/instr/Instr_180-19F.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
}
|
||||
10
src/spider/runtime/instr/Instr_1A0-1BF.cpp
Normal file
10
src/spider/runtime/instr/Instr_1A0-1BF.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
}
|
||||
10
src/spider/runtime/instr/Instr_1C0-1DF.cpp
Normal file
10
src/spider/runtime/instr/Instr_1C0-1DF.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
}
|
||||
10
src/spider/runtime/instr/Instr_1E0-1FF.cpp
Normal file
10
src/spider/runtime/instr/Instr_1E0-1FF.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||
*
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
}
|
||||
61
src/spider/runtime/instr/Instr_LLGS.cpp
Normal file
61
src/spider/runtime/instr/Instr_LLGS.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @brief LLGS — Easter egg by Arturo Balam (Data - 7A)
|
||||
*
|
||||
* Opcode: 0x0F1
|
||||
*
|
||||
* Writes a Spider ASCII art into RAM starting at address 0x00,
|
||||
* and loads the author signature into RA as a packed ASCII string.
|
||||
* This version matches the custom mechanical spider design
|
||||
* and is formatted to fit an 8-byte RAM viewer width.
|
||||
*
|
||||
* RAM layout after LLGS executes (8 characters per row, 4 rows total):
|
||||
* 0x00: "// _ \\" (Row 1)
|
||||
* 0x08: "\\( )// " (Row 2)
|
||||
* 0x10: " //()\\ " (Row 3)
|
||||
* 0x18: " \\ // " (Row 4)
|
||||
*
|
||||
* RA after execution: 0x4C4C475300000000ULL ("LLGS" in ASCII, zero-padded)
|
||||
* (L=0x4C, L=0x4C, G=0x47, S=0x53)
|
||||
*/
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
#include <spider/runtime/memory/RAM.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
void CPU::LLGS() {
|
||||
|
||||
// -- Write Spider ASCII art into RAM ---------------------------------
|
||||
// Padded with exact spaces to ensure it never wraps in an 8-byte viewer
|
||||
|
||||
// Row 0: "// _ \\ "
|
||||
_ram->at(0x00) = '/'; _ram->at(0x01) = '/';
|
||||
_ram->at(0x02) = ' '; _ram->at(0x03) = '_';
|
||||
_ram->at(0x04) = ' '; _ram->at(0x05) = '\\';
|
||||
_ram->at(0x06) = '\\'; _ram->at(0x07) = ' ';
|
||||
|
||||
// Row 1: "\\( )// "
|
||||
_ram->at(0x08) = '\\'; _ram->at(0x09) = '\\';
|
||||
_ram->at(0x0A) = '('; _ram->at(0x0B) = ' ';
|
||||
_ram->at(0x0C) = ')'; _ram->at(0x0D) = '/';
|
||||
_ram->at(0x0E) = '/'; _ram->at(0x0F) = ' ';
|
||||
|
||||
// Row 2: " //()\\ "
|
||||
_ram->at(0x10) = ' '; _ram->at(0x11) = '/';
|
||||
_ram->at(0x12) = '/'; _ram->at(0x13) = '(';
|
||||
_ram->at(0x14) = ')'; _ram->at(0x15) = '\\';
|
||||
_ram->at(0x16) = '\\'; _ram->at(0x17) = ' ';
|
||||
|
||||
// Row 3: " \\ // "
|
||||
_ram->at(0x18) = ' '; _ram->at(0x19) = '\\';
|
||||
_ram->at(0x1A) = '\\'; _ram->at(0x1B) = ' ';
|
||||
_ram->at(0x1C) = ' '; _ram->at(0x1D) = '/';
|
||||
_ram->at(0x1E) = '/'; _ram->at(0x1F) = ' ';
|
||||
|
||||
// -- Load mnemonic into RA ------------------------
|
||||
// "LLGS" packed as ASCII bytes into RA
|
||||
RA._u64 = 0x4C4C475300000000ULL;
|
||||
|
||||
}
|
||||
|
||||
} // namespace spider
|
||||
105
src/spider/runtime/math/Matrix.cpp
Normal file
105
src/spider/runtime/math/Matrix.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
#include "Matrix.hpp"
|
||||
|
||||
#include <immintrin.h>
|
||||
#include <type_traits>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
/*
|
||||
namespace spider {
|
||||
|
||||
template<typename T>
|
||||
void matrix_fill(T diag, Matrix<T> mat) {
|
||||
for (isize i = 0; i < mat.rows; i++) {
|
||||
for (isize j = 0; j < mat.cols; j++) {
|
||||
m.data[i + j * mat.rows] = i == j ? diag : T(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void matrix_mult(Matrix<T> m1, Matrix<T> m2, Matrix<T> mr) {
|
||||
// natural constrains of matrix multiplication
|
||||
if (m1.rows != mr.rows) return;
|
||||
if (m2.cols != mr.cols) return;
|
||||
if (m1.cols != m2.rows) return;
|
||||
|
||||
// fill result with zeroes
|
||||
std::fill(mr.data, mr.data + mr.rows * mr.cols, T(0));
|
||||
|
||||
// Begin Loop
|
||||
for (isize j = 0; j < mr.cols; j++) { // P
|
||||
for (isize n = 0; n < m1.cols; n++) { // N
|
||||
const T val_m2 = m2.data[n + j * m2.rows] * diag;
|
||||
isize i = 0;
|
||||
|
||||
#if defined(__AVX__)
|
||||
if constexpr (std::is_same_v<T, float>) {
|
||||
const __m256 v_m2 = _mm256_set1_ps(val_m2);
|
||||
for (; i <= mr.rows - 8; i += 8) {
|
||||
__m256 v_m1 = _mm256_loadu_ps(&m1.data[i + n * m1.rows]);
|
||||
__m256 v_mr = _mm256_loadu_ps(&mr.data[i + j * mr.rows]);
|
||||
v_mr = _mm256_fmadd_ps(v_m1, v_m2, v_mr);
|
||||
_mm256_storeu_ps(&mr.data[i + j * mr.rows], v_mr);
|
||||
}
|
||||
if (i < mr.rows) {
|
||||
float buf_m1[8] = { 0 }, buf_mr[8] = { 0 };
|
||||
isize rem = mr.rows - i;
|
||||
std::memcpy(buf_m1, &m1.data[i + n * m1.rows], rem * sizeof(T));
|
||||
std::memcpy(buf_mr, &mr.data[i + j * mr.rows], rem * sizeof(T));
|
||||
_mm256_storeu_ps(buf_mr, _mm256_fmadd_ps(_mm256_loadu_ps(buf_m1), v_m2, _mm256_loadu_ps(buf_mr)));
|
||||
std::memcpy(&mr.data[i + j * mr.rows], buf_mr, rem * sizeof(T));
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, double>) {
|
||||
const __m256d v_m2 = _mm256_set1_pd(val_m2);
|
||||
for (; i <= mr.rows - 4; i += 4) {
|
||||
__m256d v_m1 = _mm256_loadu_pd(&m1.data[i + n * m1.rows]);
|
||||
__m256d v_mr = _mm256_loadu_pd(&mr.data[i + j * mr.rows]);
|
||||
v_mr = _mm256_fmadd_pd(v_m1, v_m2, v_mr);
|
||||
_mm256_storeu_pd(&mr.data[i + j * mr.rows], v_mr);
|
||||
}
|
||||
if (i < mr.rows) {
|
||||
double buf_m1[4] = { 0 }, buf_mr[4] = { 0 };
|
||||
isize rem = mr.rows - i;
|
||||
std::memcpy(buf_m1, &m1.data[i + n * m1.rows], rem * sizeof(T));
|
||||
std::memcpy(buf_mr, &mr.data[i + j * mr.rows], rem * sizeof(T));
|
||||
_mm256_storeu_pd(buf_mr, _mm256_fmadd_pd(_mm256_loadu_pd(buf_m1), v_m2, _mm256_loadu_pd(buf_mr)));
|
||||
std::memcpy(&mr.data[i + j * mr.rows], buf_mr, rem * sizeof(T));
|
||||
}
|
||||
}
|
||||
else
|
||||
#elif defined(__SSE2__)
|
||||
if constexpr (std::is_same_v<T, float>) {
|
||||
const __m128 v_m2 = _mm_set1_ps(val_m2);
|
||||
for (; i <= mr.rows - 4; i += 4) {
|
||||
__m128 v_m1 = _mm_loadu_ps(&m1.data[i + n * m1.rows]);
|
||||
__m128 v_mr = _mm_loadu_ps(&mr.data[i + j * mr.rows]);
|
||||
v_mr = _mm_add_ps(v_mr, _mm_mul_ps(v_m1, v_m2));
|
||||
_mm_storeu_ps(&mr.data[i + j * mr.rows], v_mr);
|
||||
}
|
||||
// Tail buffer logic omitted for brevity, same as float AVX but with size 4
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, double>) {
|
||||
const __m128d v_m2 = _mm_set1_pd(val_m2);
|
||||
for (; i <= mr.rows - 2; i += 2) {
|
||||
__m128d v_m1 = _mm_loadu_pd(&m1.data[i + n * m1.rows]);
|
||||
__m128d v_mr = _mm_loadu_pd(&mr.data[i + j * mr.rows]);
|
||||
v_mr = _mm_add_pd(v_mr, _mm_mul_pd(v_m1, v_m2));
|
||||
_mm_storeu_pd(&mr.data[i + j * mr.rows], v_mr);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Fallback for non-SIMD or unsupported types
|
||||
for (; i < mr.rows; i++) {
|
||||
mr.data[i + j * mr.rows] += m1.data[i + n * m1.rows] * val_m2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
31
src/spider/runtime/math/Matrix.hpp
Normal file
31
src/spider/runtime/math/Matrix.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <spider/runtime/common.hpp>
|
||||
|
||||
/*
|
||||
namespace spider {
|
||||
|
||||
template<typename T>
|
||||
struct Matrix {
|
||||
T* data;
|
||||
isize rows, cols;
|
||||
};
|
||||
|
||||
void matrix_fill(f32 diag, Matrix<f32> mat);
|
||||
|
||||
void matrix_fill(f64 diag, Matrix<f64> mat);
|
||||
|
||||
Matrix<f32> matrix_mul(Matrix<f32> m1, Matrix<f32> m2);
|
||||
|
||||
Matrix<f64> matrix_mul(Matrix<f64> m1, Matrix<f64> m2);
|
||||
|
||||
Matrix<f32> matrix_inv(Matrix<f32> mat);
|
||||
|
||||
Matrix<f64> matrix_inv(Matrix<f64> mat);
|
||||
|
||||
f32 matrix_det(Matrix<f32> mat);
|
||||
|
||||
f64 matrix_det(Matrix<f64> mat);
|
||||
|
||||
}
|
||||
*/
|
||||
109
src/spider/runtime/math/Matrix_Multiply.cpp
Normal file
109
src/spider/runtime/math/Matrix_Multiply.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <iostream>
|
||||
|
||||
/*
|
||||
template<typename T, int Rows, int Cols>
|
||||
struct Matrix {
|
||||
T data[Rows][Cols];
|
||||
|
||||
void setZero() {
|
||||
for (int i = 0; i < Rows; i++) {
|
||||
for (int j = 0; j < Cols; j++) {
|
||||
data[i][j] = T();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, int M, int N, int P>
|
||||
Matrix<T, M, P> mat_multiply(Matrix<T, M, N> A, Matrix<T, N, P> B) {
|
||||
//Determination of resulting matrix size
|
||||
// COMPILE-TIME calculation (using constexpr)
|
||||
constexpr int RSize = (M > P) ? M : P;
|
||||
|
||||
// COMPILE-TIME square size calculation
|
||||
constexpr int CSize = (RSize <= 4) ? 4 :
|
||||
(RSize % 4 == 0) ? RSize :
|
||||
4 * (RSize / 4 + 1);
|
||||
|
||||
// SIMD width selection
|
||||
int simd_width;
|
||||
if (RSize > 8) {
|
||||
simd_width = 8;
|
||||
}
|
||||
else if (RSize > 4 && RSize < 8){
|
||||
simd_width = 4;
|
||||
}
|
||||
else {
|
||||
simd_width = RSize;
|
||||
}
|
||||
|
||||
|
||||
// Create result square matrix with size CSize(optimization)
|
||||
Matrix<T, CSize, CSize> tempResult;
|
||||
tempResult.setZero();
|
||||
|
||||
// Matrix multiplication with SIMD-style unrolling
|
||||
for (int i = 0; i < M; i++) { // For each row in A
|
||||
for (int k = 0; k < N; k++) { // For each inner dimension
|
||||
T a_val = A.data[i][k];
|
||||
|
||||
// Process columns in chunks of simd_width
|
||||
int j = 0;
|
||||
while (j < P) {
|
||||
int remaining = P - j;
|
||||
|
||||
if (remaining >= simd_width) {
|
||||
// Full SIMD operation - unrolled loops
|
||||
if (simd_width == 8) {
|
||||
tempResult.data[i][j] += a_val * B.data[k][j];
|
||||
tempResult.data[i][j+1] += a_val * B.data[k][j+1];
|
||||
tempResult.data[i][j+2] += a_val * B.data[k][j+2];
|
||||
tempResult.data[i][j+3] += a_val * B.data[k][j+3];
|
||||
tempResult.data[i][j+4] += a_val * B.data[k][j+4];
|
||||
tempResult.data[i][j+5] += a_val * B.data[k][j+5];
|
||||
tempResult.data[i][j+6] += a_val * B.data[k][j+6];
|
||||
tempResult.data[i][j+7] += a_val * B.data[k][j+7];
|
||||
}
|
||||
else if (simd_width == 4) {
|
||||
tempResult.data[i][j] += a_val * B.data[k][j];
|
||||
tempResult.data[i][j+1] += a_val * B.data[k][j+1];
|
||||
tempResult.data[i][j+2] += a_val * B.data[k][j+2];
|
||||
tempResult.data[i][j+3] += a_val * B.data[k][j+3];
|
||||
}
|
||||
else if (simd_width == 3) {
|
||||
tempResult.data[i][j] += a_val * B.data[k][j];
|
||||
tempResult.data[i][j+1] += a_val * B.data[k][j+1];
|
||||
tempResult.data[i][j+2] += a_val * B.data[k][j+2];
|
||||
}
|
||||
else if (simd_width == 2) {
|
||||
tempResult.data[i][j] += a_val * B.data[k][j];
|
||||
tempResult.data[i][j+1] += a_val * B.data[k][j+1];
|
||||
}
|
||||
else { // simd_width == 1
|
||||
tempResult.data[i][j] += a_val * B.data[k][j];
|
||||
}
|
||||
|
||||
j += simd_width;
|
||||
}
|
||||
else {
|
||||
// Handle remaining columns that don't fit in SIMD width
|
||||
for (int s = 0; s < remaining; s++) {
|
||||
tempResult.data[i][j + s] += a_val * B.data[k][j + s];
|
||||
}
|
||||
j += remaining;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the actual result (M x P) from the temporary square matrix
|
||||
Matrix<T, M, P> result;
|
||||
for (int i = 0; i < M; i++) {
|
||||
for (int j = 0; j < P; j++) {
|
||||
result.data[i][j] = tempResult.data[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
59
src/spider/runtime/math/Quat.cpp
Normal file
59
src/spider/runtime/math/Quat.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "Quat.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace spider {
|
||||
|
||||
/**
|
||||
* Multiplies two quaternions together.
|
||||
* General case, use it when no optimizations exist.
|
||||
*/
|
||||
template<typename T>
|
||||
inline Quat<T> quat_mul_gnrl(Quat<T> A, Quat<T> B) {
|
||||
return {
|
||||
B.w * A.w - B.x * A.x - B.y * A.y - B.z * A.z,
|
||||
B.w * A.x + B.x * A.w - B.y * A.z + B.z * A.y,
|
||||
B.w * A.y + B.x * A.z + B.y * A.w - B.z * A.x,
|
||||
B.w * A.z - B.x * A.y + B.y * A.x + B.z * A.w
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies two quaternions together.
|
||||
* Attempts to use SIMD instructions when available.
|
||||
*/
|
||||
template<typename T>
|
||||
inline Quat<T> quat_mul_smart(Quat<T> A, Quat<T> B) {
|
||||
}
|
||||
|
||||
Quat<f32> quat_mul(Quat<f32> q1, Quat<f32> q2) {
|
||||
return quat_mul_gnrl<f32>(q1, q2);
|
||||
}
|
||||
|
||||
//void quat_mat(Quat<f32> quat, f32* mat) {
|
||||
// // TODO
|
||||
//}
|
||||
|
||||
Quat<f64> quat_mul(Quat<f64> q1, Quat<f64> q2) {
|
||||
return quat_mul_gnrl<f64>(q1, q2);
|
||||
}
|
||||
|
||||
//void quat_mat(Quat<f64> q1, f64* mat) {
|
||||
// // TODO
|
||||
//}
|
||||
|
||||
/*
|
||||
int quatMain() {
|
||||
Quat<double> q1 = { 1.0f, 0.0f, 0.0f, 0.0f };
|
||||
Quat<double> q2 = { 0.5f, 0.5f, 0.5f, 0.5f };
|
||||
Quat<double> result = quat_multiply(q1, q2); // Returns the result!
|
||||
std::cout << "Result: ("
|
||||
<< result.w << ", "
|
||||
<< result.x << ", "
|
||||
<< result.y << ", "
|
||||
<< result.z << ")" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
56
src/spider/runtime/math/Quat.hpp
Normal file
56
src/spider/runtime/math/Quat.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <spider/runtime/common.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
template<typename T>
|
||||
struct Quat {
|
||||
T w, x, y, z;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a quaternion from Euler Angles.
|
||||
*/
|
||||
Quat<f32> quat_make_euler(f32 x, f32 y, f32 z);
|
||||
|
||||
/**
|
||||
* Creates a quaternion from an axis and an angle.
|
||||
*/
|
||||
Quat<f32> quat_make_axis_angle(f32 angle, f32 x, f32 y, f32 z);
|
||||
|
||||
/**
|
||||
* Creates a quaternion from Euler Angles.
|
||||
*/
|
||||
Quat<f64> quat_make_euler(f64 x, f64 y, f64 z);
|
||||
|
||||
/**
|
||||
* Creates a quaternion from an axis and an angle.
|
||||
*/
|
||||
Quat<f64> quat_make_axis_angle(f64 angle, f64 x, f64 y, f64 z);
|
||||
|
||||
/**
|
||||
* Multiples a quaternion with another quaternion.
|
||||
* The result is output to the qr variable.
|
||||
* This pointer can be the same as q1.
|
||||
*/
|
||||
Quat<f32> quat_mul(Quat<f32> q1, Quat<f32> q2);
|
||||
|
||||
/**
|
||||
* Converts a quaternion to a matrix.
|
||||
*/
|
||||
void quat_mat(Quat<f32> quat, f32* mat);
|
||||
|
||||
/**
|
||||
* Multiples a quaternion with another quaternion.
|
||||
* The result is output to the qr variable.
|
||||
* This pointer can be the same as q1.
|
||||
*/
|
||||
Quat<f64> quat_mul(Quat<f64> q1, Quat<f64> q2);
|
||||
|
||||
/**
|
||||
* Converts a quaternion to a matrix.
|
||||
*/
|
||||
void quat_mat(Quat<f64> q1, f64* mat);
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
#include "RAM.hpp"
|
||||
|
||||
#include <spider/runtime/cpu/Register.hpp>
|
||||
|
||||
#include <spider/runtime/memory/Types.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace spider {
|
||||
@@ -72,6 +76,11 @@ namespace spider {
|
||||
return (i < _size) ? _mem[i] : _oob;
|
||||
}
|
||||
|
||||
void RAM::loadRegister(u64 i, u8 size_code, register_t* r) {
|
||||
i = std::min(i, _size);
|
||||
spider::loadRegister[size_code](r, _mem + i, _size - i);
|
||||
}
|
||||
|
||||
// Misc //
|
||||
|
||||
void RAM::resize(u64 new_size) {
|
||||
@@ -111,4 +120,20 @@ namespace spider {
|
||||
return _size;
|
||||
}
|
||||
|
||||
u8* RAM::begin() {
|
||||
return this->_mem;
|
||||
}
|
||||
|
||||
u8* RAM::end() {
|
||||
return this->_mem + this->_size;
|
||||
}
|
||||
|
||||
const u8* RAM::begin() const {
|
||||
return this->_mem;
|
||||
}
|
||||
|
||||
const u8* RAM::end() const {
|
||||
return this->_mem + this->_size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <spider/runtime/common.hpp>
|
||||
|
||||
#include <spider/runtime/cpu/Register.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
/**
|
||||
@@ -43,12 +45,24 @@ namespace spider {
|
||||
|
||||
u8 at(u64 i) const;
|
||||
|
||||
void loadRegister(u64 i, u8 size_code, register_t* r);
|
||||
|
||||
public:
|
||||
|
||||
void resize(u64 new_size);
|
||||
|
||||
u64 size() const;
|
||||
|
||||
public:
|
||||
|
||||
u8* begin();
|
||||
|
||||
u8* end();
|
||||
|
||||
const u8* begin() const;
|
||||
|
||||
const u8* end() const;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
326
src/spider/runtime/memory/Types.hpp
Normal file
326
src/spider/runtime/memory/Types.hpp
Normal file
@@ -0,0 +1,326 @@
|
||||
#pragma once
|
||||
|
||||
#include <spider/runtime/common.hpp>
|
||||
|
||||
#include <spider/runtime/cpu/Register.hpp>
|
||||
|
||||
#include <spider/runtime/native/machine.hpp>
|
||||
|
||||
#if __cplusplus >= 202002L
|
||||
#include <bit>
|
||||
#endif
|
||||
|
||||
#if defined(SPIDER_COMPILER_MSVC)
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace spider {
|
||||
|
||||
/*
|
||||
* This file contains cross platform type juggling.
|
||||
* Optimized for each case.
|
||||
*
|
||||
* General assumtions is that unsigned and signed
|
||||
* integers are the exact same bit representation.
|
||||
*
|
||||
* Floats to and from integers is the focus when
|
||||
* juggling.
|
||||
*
|
||||
* Additionally, provides help selecting a specific
|
||||
* type from raw bytes.
|
||||
*/
|
||||
|
||||
// Utilities //
|
||||
|
||||
#if __cplusplus >= 202002L
|
||||
using std::bit_cast;
|
||||
#else
|
||||
template<typename To, typename From>
|
||||
inline To bit_cast(const From& src) {
|
||||
static_assert(sizeof(To) == sizeof(From), "bit_cast size mismatch");
|
||||
To dst;
|
||||
std::memcpy(&dst, &src, sizeof(To));
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
inline T byteswap(T v) {
|
||||
static_assert(std::is_integral<T>::value, "byteswap requires integral type");
|
||||
|
||||
using U = std::make_unsigned_t<T>;
|
||||
U u = static_cast<U>(v);
|
||||
|
||||
if constexpr (sizeof(T) == 1) {
|
||||
return v;
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
|
||||
#if defined(SPIDER_COMPILER_MSVC)
|
||||
u = _byteswap_ushort(u);
|
||||
#elif defined(SPIDER_COMPILER_GCC_LIKE)
|
||||
u = __builtin_bswap16(u);
|
||||
#else
|
||||
u = (u >> 8) | (u << 8);
|
||||
#endif
|
||||
|
||||
} else if constexpr (sizeof(T) == 4) {
|
||||
|
||||
#if defined(SPIDER_COMPILER_MSVC)
|
||||
u = _byteswap_ulong(u);
|
||||
#elif defined(SPIDER_COMPILER_GCC_LIKE)
|
||||
u = __builtin_bswap32(u);
|
||||
#else
|
||||
u =
|
||||
((u & 0x000000FFu) << 24) |
|
||||
((u & 0x0000FF00u) << 8) |
|
||||
((u & 0x00FF0000u) >> 8) |
|
||||
((u & 0xFF000000u) >> 24);
|
||||
#endif
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
|
||||
#if defined(SPIDER_COMPILER_MSVC)
|
||||
u = _byteswap_uint64(u);
|
||||
#elif defined(SPIDER_COMPILER_GCC_LIKE)
|
||||
u = __builtin_bswap64(u);
|
||||
#else
|
||||
u =
|
||||
((u & 0x00000000000000FFull) << 56) |
|
||||
((u & 0x000000000000FF00ull) << 40) |
|
||||
((u & 0x0000000000FF0000ull) << 24) |
|
||||
((u & 0x00000000FF000000ull) << 8) |
|
||||
((u & 0x000000FF00000000ull) >> 8) |
|
||||
((u & 0x0000FF0000000000ull) >> 24) |
|
||||
((u & 0x00FF000000000000ull) >> 40) |
|
||||
((u & 0xFF00000000000000ull) >> 56);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
// Generic fallback (rare: non 1/2/4/8-byte types)
|
||||
U result = 0;
|
||||
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||
result |= ((u >> (i * 8)) & 0xFF) << ((sizeof(T) - 1 - i) * 8);
|
||||
}
|
||||
u = result;
|
||||
}
|
||||
|
||||
return static_cast<T>(u);
|
||||
}
|
||||
|
||||
// Store Big Endian //
|
||||
|
||||
template<typename T>
|
||||
inline void storeBE(T n, u8* bytes) {
|
||||
static_assert(std::is_trivially_copyable<T>::value);
|
||||
#if SPIDER_BIG_ENDIAN
|
||||
std::memcpy(bytes, &n, sizeof(T));
|
||||
#endif
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
n = byteswap(n);
|
||||
std::memcpy(bytes, &n, sizeof(T));
|
||||
#endif
|
||||
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
|
||||
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||
bytes[i] = static_cast<u8>(
|
||||
(static_cast<std::make_unsigned_t<T>>(n) >> ((sizeof(T) - 1 - i) * 8)) & 0xFF
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void storeBE<f32>(f32 n, u8* bytes) {
|
||||
u32 tmp = bit_cast<u32>(n);
|
||||
storeBE(tmp, bytes);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void storeBE<f64>(f64 n, u8* bytes) {
|
||||
u64 tmp = bit_cast<u64>(n);
|
||||
storeBE(tmp, bytes);
|
||||
}
|
||||
|
||||
// Load Big Endian //
|
||||
|
||||
template<typename T>
|
||||
inline void loadBE(T* n, const u8* bytes) {
|
||||
static_assert(std::is_trivially_copyable<T>::value);
|
||||
#if SPIDER_BIG_ENDIAN
|
||||
std::memcpy(n, bytes, sizeof(T));
|
||||
#endif
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
std::memcpy(&n, bytes, sizeof(T));
|
||||
*n = byteswap(*n);
|
||||
#endif
|
||||
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
|
||||
using U = std::make_unsigned_t<T>;
|
||||
U result = 0;
|
||||
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||
result |= static_cast<U>(bytes[i]) << ((sizeof(T) - 1 - i) * 8);
|
||||
}
|
||||
*n = static_cast<T>(result);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void loadBE<f32>(f32* n, const u8* bytes) {
|
||||
u32 tmp;
|
||||
loadBE(&tmp, bytes);
|
||||
*n = bit_cast<f32>(tmp);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void loadBE<f64>(f64* n, const u8* bytes) {
|
||||
u64 tmp;
|
||||
loadBE(&tmp, bytes);
|
||||
*n = bit_cast<f64>(tmp);
|
||||
}
|
||||
|
||||
// Store Little Endian //
|
||||
|
||||
template<typename T>
|
||||
inline void storeLE(T n, u8* bytes) {
|
||||
static_assert(std::is_trivially_copyable<T>::value);
|
||||
#if SPIDER_BIG_ENDIAN
|
||||
n = byteswap(n);
|
||||
std::memcpy(bytes, &n, sizeof(T));
|
||||
#endif
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
std::memcpy(bytes, &n, sizeof(T));
|
||||
#endif
|
||||
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
|
||||
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||
bytes[i] = static_cast<u8>(
|
||||
(static_cast<std::make_unsigned_t<T>>(n) >> (i * 8)) & 0xFF
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void storeLE<f32>(f32 n, u8* bytes) {
|
||||
u32 tmp = bit_cast<u32>(n);
|
||||
storeLE(tmp, bytes);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void storeLE<f64>(f64 n, u8* bytes) {
|
||||
u64 tmp = bit_cast<u64>(n);
|
||||
storeLE(tmp, bytes);
|
||||
}
|
||||
|
||||
// Load Little Endian //
|
||||
|
||||
template<typename T>
|
||||
inline void loadLE(T* n, const u8* bytes) {
|
||||
static_assert(std::is_trivially_copyable<T>::value);
|
||||
#if SPIDER_BIG_ENDIAN
|
||||
std::memcpy(&n, bytes, sizeof(T));
|
||||
*n = byteswap(n);
|
||||
#endif
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
std::memcpy(n, bytes, sizeof(T));
|
||||
#endif
|
||||
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
|
||||
using U = std::make_unsigned_t<T>;
|
||||
U result = 0;
|
||||
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||
result |= static_cast<U>(bytes[i]) << (i * 8);
|
||||
}
|
||||
*n = static_cast<T>(result);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void loadLE<f32>(f32* n, const u8* bytes) {
|
||||
u32 tmp;
|
||||
loadLE(&tmp, bytes);
|
||||
*n = bit_cast<f32>(tmp);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void loadLE<f64>(f64* n, const u8* bytes) {
|
||||
u64 tmp;
|
||||
loadLE(&tmp, bytes);
|
||||
*n = bit_cast<f64>(tmp);
|
||||
}
|
||||
|
||||
// ADVANCED Load Little Endian //
|
||||
|
||||
/**
|
||||
* Loads LE bytes into a type.
|
||||
* Also considers that the array may end, actually.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void loadPartialLE(T* n, const u8* bytes, isize length) {
|
||||
*n = 0;
|
||||
length = std::min(sizeof(T), length);
|
||||
#if SPIDER_BIG_ENDIAN
|
||||
std::memcpy(n, bytes, length);
|
||||
*n = byteswap(n);
|
||||
#endif
|
||||
#if SPIDER_LITTLE_ENDIAN
|
||||
std::memcpy(n, bytes, length);
|
||||
#endif
|
||||
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
|
||||
using U = std::make_unsigned_t<T>;
|
||||
U result = 0;
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
result |= static_cast<U>(bytes[i]) << (i * 8);
|
||||
}
|
||||
*n = static_cast<T>(result);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void loadPartialLE<f32>(f32* n, const u8* bytes, isize length) {
|
||||
u32 tmp;
|
||||
loadPartialLE(&tmp, bytes, length);
|
||||
*n = bit_cast<f32>(tmp);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void loadPartialLE<f64>(f64* n, const u8* bytes, isize length) {
|
||||
u64 tmp;
|
||||
loadPartialLE(&tmp, bytes, length);
|
||||
*n = bit_cast<f64>(tmp);
|
||||
}
|
||||
|
||||
inline void loadRegisterU8(register_t* r, const u8* bytes, isize length) {
|
||||
loadPartialLE(&r->_u8, bytes, length);
|
||||
}
|
||||
|
||||
inline void loadRegisterU16(register_t* r, const u8* bytes, isize length) {
|
||||
loadPartialLE(&r->_u16, bytes, length);
|
||||
}
|
||||
|
||||
inline void loadRegisterU32(register_t* r, const u8* bytes, isize length) {
|
||||
loadPartialLE(&r->_u32, bytes, length);
|
||||
}
|
||||
|
||||
inline void loadRegisterU64(register_t* r, const u8* bytes, isize length) {
|
||||
loadPartialLE(&r->_u64, bytes, length);
|
||||
}
|
||||
|
||||
using _regload = void (*)(register_t* r, const u8* bytes, isize length);
|
||||
|
||||
inline _regload loadRegister[] = {
|
||||
&loadRegisterU8, &loadRegisterU16,
|
||||
&loadRegisterU32, &loadRegisterU64
|
||||
};
|
||||
|
||||
// MISCs
|
||||
|
||||
inline void loadPartialBytes(const u8* from, isize fromOffset, isize fromLength, u8* to, isize toLength) {
|
||||
size_t safeOffset = std::min(fromOffset, fromLength);
|
||||
from += safeOffset;
|
||||
fromLength -= safeOffset;
|
||||
size_t writable = std::min(fromLength, toLength);
|
||||
std::copy(from, from + writable, to);
|
||||
std::fill(to + writable, to + toLength, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -55,9 +55,9 @@
|
||||
|
||||
// ========================================================== //
|
||||
// PACKING //
|
||||
// (not used now) //
|
||||
// ========================================================== //
|
||||
|
||||
|
||||
// Find out what compiler the user is using
|
||||
#if defined(__clang__)
|
||||
#define SPIDER_COMPILER_CLANG
|
||||
@@ -73,8 +73,9 @@
|
||||
|
||||
// Macros...
|
||||
#if defined(SPIDER_COMPILER_GCC_LIKE)
|
||||
#define SPIDER_ATTRIBUTE_PACKED __attribute__((packed))
|
||||
#define SPIDER_PACKED_STRUCT(decl) decl SPIDER_ATTRIBUTE_PACKED
|
||||
#define SPIDER_PACK_BEGIN
|
||||
#define SPIDER_PACK_END
|
||||
#define SPIDER_PACK_STRUCT __attribute__((packed))
|
||||
|
||||
#elif defined(SPIDER_COMPILER_MSVC)
|
||||
#define SPIDER_BEGIN_PACKED __pragma(pack(push, 1))
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
#include "InstrReel.hpp"
|
||||
|
||||
#include <spider/runtime/cpu/CPU.hpp>
|
||||
|
||||
#include <spider/runtime/memory/Types.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
// Public Interface //
|
||||
|
||||
InstrReel::InstrReel() {}
|
||||
|
||||
InstrReel::~InstrReel() {}
|
||||
|
||||
u16 InstrReel::instrAt(u64 ip) const {}
|
||||
|
||||
u8 InstrReel::dataAt(u64 ip) const {}
|
||||
|
||||
u8 InstrReel::feedNext(CPU& cpu) {}
|
||||
|
||||
// Static Utils //
|
||||
|
||||
u16 InstrReel::unpackInstr(u16 bcode) {
|
||||
78
src/spider/runtime/reel/InstrReel.hpp
Normal file
78
src/spider/runtime/reel/InstrReel.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include <spider/SpiderRuntime.hpp>
|
||||
|
||||
#include <spider/runtime/memory/ByteArray.hpp>
|
||||
|
||||
#include <spider/runtime/cpu/Register.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
/**
|
||||
* Implements an instruction reel.
|
||||
*/
|
||||
class InstrReel {
|
||||
public:
|
||||
|
||||
InstrReel();
|
||||
|
||||
virtual ~InstrReel();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
virtual u8 readU8(u64 ip) = 0;
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
virtual u16 readU16(u64 ip) = 0;
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
virtual u32 readU32(u64 ip) = 0;
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
virtual u64 readU64(u64 ip) = 0;
|
||||
|
||||
/**
|
||||
* Reads a range of data, and
|
||||
* outputs it.
|
||||
*/
|
||||
virtual void readRange(u64 ip, u8* out, u64 length) = 0;
|
||||
|
||||
virtual void loadRegister(u64 ip, u8 size_code, register_t* r) = 0;
|
||||
|
||||
/**
|
||||
* Current size of the instructions.
|
||||
*/
|
||||
virtual u64 size() = 0;
|
||||
|
||||
public: // Static Utils //
|
||||
|
||||
static u16 unpackInstr(u16 bcode);
|
||||
|
||||
static u8 unpackAddrMode(u16 bcode);
|
||||
|
||||
static u8 unpackTypeSize(u16 bcode);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
209
src/spider/runtime/reel/InstrReelDyn.cpp
Normal file
209
src/spider/runtime/reel/InstrReelDyn.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "InstrReelDyn.hpp"
|
||||
|
||||
#include <spider/runtime/memory/Types.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
InstrReelDyn::InstrReelDyn(u64 length) : _size(length) {
|
||||
// Safe int ceil division
|
||||
growTo((length >> 8) + ((length & 255) != 0));
|
||||
}
|
||||
|
||||
//InstrReelDyn::InstrReelDyn(const u8* data, u64 length) {}
|
||||
|
||||
InstrReelDyn::InstrReelDyn(const InstrReelDyn& copy)
|
||||
: _blocks(copy._blocks), _size(copy._size) {
|
||||
}
|
||||
|
||||
InstrReelDyn::InstrReelDyn(InstrReelDyn&& move) noexcept
|
||||
: _blocks(std::move(move._blocks)), _size(std::move(move._size)) {
|
||||
}
|
||||
|
||||
InstrReelDyn::~InstrReelDyn() {
|
||||
// .. //
|
||||
}
|
||||
|
||||
InstrReelDyn& InstrReelDyn::operator=(const InstrReelDyn& copy) {
|
||||
_blocks = copy._blocks;
|
||||
_size = copy._size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
InstrReelDyn& InstrReelDyn::operator=(InstrReelDyn&& move) noexcept {
|
||||
_blocks = std::move(move._blocks);
|
||||
_size = std::move(move._size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void InstrReelDyn::growTo(u64 ip) {
|
||||
u64 b_index = (ip >> 8) + 1;
|
||||
while (_blocks.size() < b_index) {
|
||||
_blocks.emplace_back();
|
||||
}
|
||||
if (ip >= _size) _size = ip + 1;
|
||||
}
|
||||
|
||||
std::pair<u64, u8> InstrReelDyn::indexOf(u64 ip) {
|
||||
return { ip >> 8, ip & 0xFF }; // { ip / 256, ip % 256 };
|
||||
}
|
||||
|
||||
bool InstrReelDyn::continous(u64 ip0, u64 ip1, u64* b_index, u16* s_index) {
|
||||
auto i = indexOf(ip0);
|
||||
*b_index = i.first;
|
||||
*s_index = i.second;
|
||||
return i.first == (ip1 >> 8);
|
||||
}
|
||||
|
||||
// Particular Cases
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
u8 InstrReelDyn::readU8(u64 ip) {
|
||||
if (ip + 1 > _size) return 0;
|
||||
auto i = indexOf(ip);
|
||||
return _blocks[i.first].data[i.second];
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
u16 InstrReelDyn::readU16(u64 ip) {
|
||||
if (ip + 2 > _size) return 0;
|
||||
|
||||
u16 dat;
|
||||
u64 b_index;
|
||||
u16 s_index;
|
||||
|
||||
if (continous(ip, ip + 1, &b_index, &s_index)) {
|
||||
spider::loadLE(&dat, &_blocks[b_index].data[s_index]);
|
||||
return dat;
|
||||
}
|
||||
|
||||
dat = 0;
|
||||
for (isize i = 0; i < sizeof(dat); i++) {
|
||||
auto& b = _blocks[(b_index + s_index) >> 8];
|
||||
dat |= u16(b.data[s_index++ & 0xFF] << (i * 8));
|
||||
}
|
||||
return dat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
u32 InstrReelDyn::readU32(u64 ip) {
|
||||
if (ip + 4 > _size) return 0;
|
||||
|
||||
u32 dat;
|
||||
u64 b_index;
|
||||
u16 s_index;
|
||||
|
||||
if (continous(ip, ip + 3, &b_index, &s_index)) {
|
||||
spider::loadLE(&dat, &_blocks[b_index].data[s_index]);
|
||||
return dat;
|
||||
}
|
||||
|
||||
dat = 0;
|
||||
for (isize i = 0; i < sizeof(dat); i++) {
|
||||
auto& b = _blocks[(b_index + s_index) >> 8];
|
||||
dat |= u32(b.data[s_index++ & 0xFF]) << (i * 8);
|
||||
}
|
||||
return dat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
u64 InstrReelDyn::readU64(u64 ip) {
|
||||
if (ip + 8 > _size) return 0;
|
||||
|
||||
u64 dat;
|
||||
u64 b_index;
|
||||
u16 s_index;
|
||||
|
||||
if (continous(ip, ip + 7, &b_index, &s_index)) {
|
||||
spider::loadLE(&dat, &_blocks[b_index].data[s_index]);
|
||||
return dat;
|
||||
}
|
||||
|
||||
dat = 0;
|
||||
for (isize i = 0; i < sizeof(dat); i++) {
|
||||
auto& b = _blocks[(b_index + s_index) >> 8];
|
||||
dat |= u64(b.data[s_index++ & 0xFF]) << (i * 8);
|
||||
}
|
||||
return dat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a range of data, and
|
||||
* outputs it.
|
||||
*/
|
||||
void InstrReelDyn::readRange(u64 ip, u8* out, u64 length) {
|
||||
if (ip + length > _size) {
|
||||
std::memset(out, 0, length);
|
||||
return;
|
||||
}
|
||||
|
||||
u64 b_index;
|
||||
u16 s_index;
|
||||
|
||||
if (continous(ip, ip + length, &b_index, &s_index)) {
|
||||
std::memcpy(out, &_blocks[b_index].data[s_index], length);
|
||||
return;
|
||||
}
|
||||
|
||||
u64 bytes_read = 0;
|
||||
while (bytes_read < length) {
|
||||
u64 remaining_in_block = 256 - s_index;
|
||||
u64 chunk_size = std::min(remaining_in_block, length - bytes_read);
|
||||
|
||||
// Perform bulk copy for the current segment
|
||||
std::memcpy(out + bytes_read, &_blocks[b_index].data[s_index], chunk_size);
|
||||
|
||||
// Advance pointers
|
||||
bytes_read += chunk_size;
|
||||
b_index++;
|
||||
s_index = 0; // reset
|
||||
}
|
||||
}
|
||||
|
||||
void InstrReelDyn::loadRegister(u64 ip, u8 size_code, register_t* r) {
|
||||
u8 bytes[8];
|
||||
readRange(ip, bytes, 1 << size_code);
|
||||
spider::loadRegister[size_code](r, bytes, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Current size of the instructions.
|
||||
*/
|
||||
u64 InstrReelDyn::size() {
|
||||
return _size;
|
||||
}
|
||||
|
||||
// Mutation //
|
||||
|
||||
// TODO!
|
||||
|
||||
//void InstrReelDyn::writeU8(u64 ip, u8 dat) {}
|
||||
//void InstrReelDyn::writeU16(u64 ip, u16 dat) {}
|
||||
//void InstrReelDyn::writeU32(u64 ip, u32 dat) {}
|
||||
//void InstrReelDyn::writeU64(u64 ip, u64 dat) {}
|
||||
|
||||
/**
|
||||
* Appends instruction at the end.
|
||||
*/
|
||||
//void InstrReelDyn::append(u16 bc) {}
|
||||
|
||||
}
|
||||
112
src/spider/runtime/reel/InstrReelDyn.hpp
Normal file
112
src/spider/runtime/reel/InstrReelDyn.hpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#pragma once
|
||||
|
||||
#include <spider/runtime/reel/InstrReel.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
/**
|
||||
* Implements an instruction reel.
|
||||
*/
|
||||
class InstrReelDyn : public InstrReel {
|
||||
private:
|
||||
|
||||
struct ReelBlock {
|
||||
u8 data[256] = {};
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
deque<ReelBlock> _blocks;
|
||||
u64 _size;
|
||||
|
||||
public:
|
||||
|
||||
InstrReelDyn(u64 length);
|
||||
|
||||
InstrReelDyn(const u8* data, u64 length);
|
||||
|
||||
InstrReelDyn(const InstrReelDyn& copy);
|
||||
|
||||
InstrReelDyn(InstrReelDyn&& move) noexcept;
|
||||
|
||||
virtual ~InstrReelDyn();
|
||||
|
||||
public:
|
||||
|
||||
InstrReelDyn& operator=(const InstrReelDyn& copy);
|
||||
|
||||
InstrReelDyn& operator=(InstrReelDyn&& move) noexcept;
|
||||
|
||||
private:
|
||||
|
||||
std::pair<u64, u8> indexOf(u64 ip);
|
||||
|
||||
bool continous(u64 ip0, u64 ip1, u64* b_index, u16* s_index);
|
||||
|
||||
void growTo(u64 ip);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
virtual u8 readU8(u64 ip) override;
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
virtual u16 readU16(u64 ip) override;
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
virtual u32 readU32(u64 ip) override;
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
virtual u64 readU64(u64 ip) override;
|
||||
|
||||
/**
|
||||
* Reads a range of data, and
|
||||
* outputs it.
|
||||
*/
|
||||
virtual void readRange(u64 ip, u8* out, u64 length) override;
|
||||
|
||||
virtual void loadRegister(u64 ip, u8 size_code, register_t* r) override;
|
||||
|
||||
/**
|
||||
* Current size of the instructions.
|
||||
*/
|
||||
virtual u64 size() override;
|
||||
|
||||
public:
|
||||
|
||||
void writeU8(u64 ip, u8 dat);
|
||||
|
||||
void writeU16(u64 ip, u16 dat);
|
||||
|
||||
void writeU32(u64 ip, u32 dat);
|
||||
|
||||
void writeU64(u64 ip, u64 dat);
|
||||
|
||||
/**
|
||||
* Appends instruction at the end.
|
||||
*/
|
||||
void append(u16 bc);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
0
src/spider/runtime/reel/InstrReelFile.hpp
Normal file
0
src/spider/runtime/reel/InstrReelFile.hpp
Normal file
170
src/spider/runtime/reel/InstrReelFixed.cpp
Normal file
170
src/spider/runtime/reel/InstrReelFixed.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
#include "InstrReelFixed.hpp"
|
||||
|
||||
#include <spider/runtime/memory/Types.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace spider {
|
||||
|
||||
// Constructors & Destructors //
|
||||
|
||||
InstrReelFixed::InstrReelFixed(u64 length)
|
||||
: _mem(nullptr), _size(length) {
|
||||
if (_size > 0) {
|
||||
_mem = new u8[_size];
|
||||
std::memset(_mem, 0, _size);
|
||||
}
|
||||
}
|
||||
|
||||
InstrReelFixed::InstrReelFixed(const u8* data, u64 length)
|
||||
: _mem(nullptr), _size(length) {
|
||||
if (_size > 0) {
|
||||
_mem = new u8[_size];
|
||||
std::copy(data, data + _size, _mem);
|
||||
}
|
||||
}
|
||||
|
||||
InstrReelFixed::InstrReelFixed(const InstrReelFixed& other) {
|
||||
_size = other._size;
|
||||
_mem = new u8[_size];
|
||||
std::copy(other._mem, other._mem + _size, _mem);
|
||||
}
|
||||
|
||||
InstrReelFixed::InstrReelFixed(InstrReelFixed&& other) noexcept {
|
||||
_mem = other._mem;
|
||||
_size = other._size;
|
||||
|
||||
other._mem = nullptr;
|
||||
other._size = 0;
|
||||
}
|
||||
|
||||
InstrReelFixed::~InstrReelFixed() {
|
||||
delete[] _mem;
|
||||
}
|
||||
|
||||
// General Case(s) //
|
||||
|
||||
// Instruction abstraction //
|
||||
|
||||
u8 InstrReelFixed::readU8(u64 ip) {
|
||||
u8 dat;
|
||||
spider::loadPartialLE(&dat, _mem + ip, _size);
|
||||
return dat;
|
||||
}
|
||||
|
||||
u16 InstrReelFixed::readU16(u64 ip) {
|
||||
u16 dat;
|
||||
spider::loadPartialLE(&dat, _mem + ip, _size);
|
||||
return dat;
|
||||
}
|
||||
|
||||
u32 InstrReelFixed::readU32(u64 ip) {
|
||||
u32 dat;
|
||||
spider::loadPartialLE(&dat, _mem + ip, _size);
|
||||
return dat;
|
||||
}
|
||||
|
||||
u64 InstrReelFixed::readU64(u64 ip) {
|
||||
u64 dat;
|
||||
spider::loadPartialLE(&dat, _mem + ip, _size);
|
||||
return dat;
|
||||
}
|
||||
|
||||
void InstrReelFixed::readRange(u64 ip, u8* out, u64 length) {
|
||||
spider::loadPartialBytes(_mem, isize(ip), _size, out, length);
|
||||
}
|
||||
|
||||
void InstrReelFixed::loadRegister(u64 ip, u8 size_code, register_t* r) {
|
||||
ip = std::min(ip, _size);
|
||||
spider::loadRegister[size_code](r, _mem + ip, _size - ip);
|
||||
}
|
||||
|
||||
u64 InstrReelFixed::size() {
|
||||
return _size;
|
||||
}
|
||||
|
||||
// Assign Operators //
|
||||
|
||||
InstrReelFixed& InstrReelFixed::operator=(const InstrReelFixed& other) {
|
||||
if (this == &other) return *this; // lock self
|
||||
|
||||
u8* new_mem = new u8[other._size];
|
||||
std::copy(other._mem, other._mem + other._size, new_mem);
|
||||
|
||||
delete[] _mem;
|
||||
_mem = new_mem;
|
||||
_size = other._size;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
InstrReelFixed& InstrReelFixed::operator=(InstrReelFixed&& other) noexcept {
|
||||
if (this == &other) return *this; // lock self
|
||||
|
||||
delete[] _mem;
|
||||
|
||||
_mem = other._mem; // steal
|
||||
_size = other._size;
|
||||
|
||||
other._mem = nullptr; // leave as husk
|
||||
other._size = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Misc //
|
||||
|
||||
void InstrReelFixed::writeU8(u64 ip, u8 dat) {
|
||||
if(ip + 1 > _size) return;
|
||||
_mem[ip] = dat;
|
||||
}
|
||||
|
||||
void InstrReelFixed::writeU16(u64 ip, u16 dat) {
|
||||
if(ip + 2 > _size) return;
|
||||
spider::storeLE(dat, _mem + ip);
|
||||
}
|
||||
|
||||
void InstrReelFixed::writeU32(u64 ip, u32 dat) {
|
||||
if(ip + 4 > _size) return;
|
||||
spider::storeLE(dat, _mem + ip);
|
||||
}
|
||||
|
||||
void InstrReelFixed::writeU64(u64 ip, u64 dat) {
|
||||
if(ip + 8 > _size) return;
|
||||
spider::storeLE(dat, _mem + ip);
|
||||
}
|
||||
|
||||
void InstrReelFixed::resize(u64 new_size) {
|
||||
// Special case 1
|
||||
if (new_size == _size) return;
|
||||
|
||||
// Special case 2
|
||||
if (new_size == 0) {
|
||||
delete[] _mem;
|
||||
_mem = nullptr;
|
||||
_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Allocate the new block
|
||||
u8* new_mem = new u8[new_size];
|
||||
|
||||
// 2. Zero-initialize
|
||||
std::memset(new_mem, 0, new_size);
|
||||
|
||||
// 3. Preserve data
|
||||
// If shrinking, copy 'new_size' bytes. If growing, copy 'old_size' bytes.
|
||||
u64 bytes_to_copy = (new_size < _size) ? new_size : _size;
|
||||
|
||||
// 3.1 Previous size could be zero, where _mem would be null
|
||||
if (_mem != nullptr) {
|
||||
std::copy(_mem, _mem + bytes_to_copy, new_mem);
|
||||
}
|
||||
|
||||
// 4. Swap and Clean up
|
||||
delete[] _mem;
|
||||
_mem = new_mem;
|
||||
_size = new_size;
|
||||
}
|
||||
|
||||
}
|
||||
94
src/spider/runtime/reel/InstrReelFixed.hpp
Normal file
94
src/spider/runtime/reel/InstrReelFixed.hpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#include <spider/runtime/reel/InstrReel.hpp>
|
||||
|
||||
namespace spider {
|
||||
|
||||
/**
|
||||
* Implements an instruction reel.
|
||||
*/
|
||||
class InstrReelFixed : public InstrReel {
|
||||
private:
|
||||
u8* _mem;
|
||||
u64 _size;
|
||||
|
||||
public:
|
||||
|
||||
InstrReelFixed(u64 length);
|
||||
|
||||
InstrReelFixed(const u8* data, u64 length);
|
||||
|
||||
InstrReelFixed(const InstrReelFixed& copy);
|
||||
|
||||
InstrReelFixed(InstrReelFixed&& move) noexcept;
|
||||
|
||||
virtual ~InstrReelFixed();
|
||||
|
||||
public:
|
||||
|
||||
InstrReelFixed& operator=(const InstrReelFixed& copy);
|
||||
|
||||
InstrReelFixed& operator=(InstrReelFixed&& move) noexcept;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
virtual u8 readU8(u64 ip) override;
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
virtual u16 readU16(u64 ip) override;
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
virtual u32 readU32(u64 ip) override;
|
||||
|
||||
/**
|
||||
* Obtains a byte of data at
|
||||
* the specific location.
|
||||
* Reindexing may occur, continous access
|
||||
* may incurr in less penalties.
|
||||
*/
|
||||
virtual u64 readU64(u64 ip) override;
|
||||
|
||||
/**
|
||||
* Reads a range of data, and
|
||||
* outputs it.
|
||||
*/
|
||||
virtual void readRange(u64 ip, u8* out, u64 length) override;
|
||||
|
||||
virtual void loadRegister(u64 ip, u8 size_code, register_t* r) override;
|
||||
|
||||
/**
|
||||
* Current size of the instructions.
|
||||
*/
|
||||
virtual u64 size() override;
|
||||
|
||||
public:
|
||||
|
||||
void writeU8(u64 ip, u8 dat);
|
||||
|
||||
void writeU16(u64 ip, u16 dat);
|
||||
|
||||
void writeU32(u64 ip, u32 dat);
|
||||
|
||||
void writeU64(u64 ip, u64 dat);
|
||||
|
||||
void resize(u64 new_size);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
286
src/spider/runtime/util/Terminal.cpp
Normal file
286
src/spider/runtime/util/Terminal.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
#include "Terminal.hpp"
|
||||
|
||||
#include <spider/runtime/native/distro.hpp>
|
||||
|
||||
#if defined(SPIDER_OS_WINDOWS)
|
||||
#include <conio.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h> //This was missing,
|
||||
//The ioctl, TIOCGWINSZ and winsize used in getSize() live in that header, but it was never included.
|
||||
#endif
|
||||
|
||||
|
||||
//the Linux includes at the top are inside #if SPIDER_OS_LINUX which IS defined,
|
||||
//but getSize() is inside #if SPIDER_DISTRO_DESKTOP which is NOT defined,
|
||||
//so the compiler sees the ioctl call without the include that would have covered it.
|
||||
|
||||
#if defined(SPIDER_DISTRO_DESKTOP)
|
||||
|
||||
namespace spider {
|
||||
|
||||
// Style //
|
||||
const char* Terminal::RESET = "\033[0m";
|
||||
const char* Terminal::BOLD = "\033[1m";
|
||||
const char* Terminal::ITALIC = "\033[3m";
|
||||
const char* Terminal::FAINT = "\033[2m";
|
||||
const char* Terminal::STRIKE = "\033[9m";
|
||||
|
||||
// Foreground //
|
||||
const char* Terminal::FG_BLACK = "\033[30m"; const char* Terminal::FG_B_BLACK = "\033[90m";
|
||||
const char* Terminal::FG_RED = "\033[31m"; const char* Terminal::FG_B_RED = "\033[91m";
|
||||
const char* Terminal::FG_GREEN = "\033[32m"; const char* Terminal::FG_B_GREEN = "\033[92m";
|
||||
const char* Terminal::FG_YELLOW = "\033[33m"; const char* Terminal::FG_B_YELLOW = "\033[93m";
|
||||
const char* Terminal::FG_BLUE = "\033[34m"; const char* Terminal::FG_B_BLUE = "\033[94m";
|
||||
const char* Terminal::FG_MAGENTA = "\033[35m"; const char* Terminal::FG_B_MAGENTA = "\033[95m";
|
||||
const char* Terminal::FG_CYAN = "\033[36m"; const char* Terminal::FG_B_CYAN = "\033[96m";
|
||||
const char* Terminal::FG_WHITE = "\033[37m"; const char* Terminal::FG_B_WHITE = "\033[97m";
|
||||
|
||||
// Background //
|
||||
const char* Terminal::BG_BLACK = "\033[40m"; const char* Terminal::BG_B_BLACK = "\033[100m";
|
||||
const char* Terminal::BG_RED = "\033[41m"; const char* Terminal::BG_B_RED = "\033[101m";
|
||||
const char* Terminal::BG_GREEN = "\033[42m"; const char* Terminal::BG_B_GREEN = "\033[102m";
|
||||
const char* Terminal::BG_YELLOW = "\033[43m"; const char* Terminal::BG_B_YELLOW = "\033[103m";
|
||||
const char* Terminal::BG_BLUE = "\033[44m"; const char* Terminal::BG_B_BLUE = "\033[104m";
|
||||
const char* Terminal::BG_MAGENTA = "\033[45m"; const char* Terminal::BG_B_MAGENTA = "\033[105m";
|
||||
const char* Terminal::BG_CYAN = "\033[46m"; const char* Terminal::BG_B_CYAN = "\033[106m";
|
||||
const char* Terminal::BG_WHITE = "\033[47m"; const char* Terminal::BG_B_WHITE = "\033[107m";
|
||||
|
||||
Terminal::Terminal() {
|
||||
#if defined(SPIDER_OS_WINDOWS)
|
||||
// Enable UTF-8
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
SetConsoleCP(CP_UTF8);
|
||||
|
||||
// enable vtp
|
||||
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD dwMode = 0;
|
||||
GetConsoleMode(hOut, &dwMode);
|
||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
SetConsoleMode(hOut, dwMode);
|
||||
#endif
|
||||
}
|
||||
|
||||
Terminal::~Terminal() {
|
||||
altbuff(false).style(RESET).cursor(true).flush();
|
||||
}
|
||||
|
||||
Terminal& Terminal::style(const std::string_view code) {
|
||||
std::cout << code;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terminal& Terminal::move(i32 row, i32 col) {
|
||||
std::cout << "\033[" << row << ";" << col << "H";
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terminal& Terminal::altbuff(bool enable) {
|
||||
std::cout << (enable ? "\033[?1049h" : "\033[?1049l");
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terminal& Terminal::cls() {
|
||||
std::cout << "\033[2J";
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terminal& Terminal::scrollRange(i32 start, i32 end) {
|
||||
std::cout << "\033[" << start << ";" << end << "r\033[?6h";
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terminal& Terminal::undoSRange() {
|
||||
std::cout << "\033[r\033[?6l\033[H";
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terminal& Terminal::fill(const std::string_view color) {
|
||||
this->style(color);
|
||||
this->cls();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terminal& Terminal::clearRow(i32 row) {
|
||||
// Move to row, column 1
|
||||
this->move(row, 1);
|
||||
// \033[2K clears the entire line
|
||||
std::cout << "\033[2K";
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terminal& Terminal::clearRows(i32 start, i32 end) {
|
||||
// Ensure we don't loop infinitely if start > end
|
||||
if (start > end) std::swap(start, end);
|
||||
|
||||
for (i32 i = start; i <= end; ++i) {
|
||||
this->clearRow(i);
|
||||
}
|
||||
|
||||
// Optional: Move cursor back to the start of the cleared block
|
||||
this->move(start, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terminal& Terminal::cursor(bool show) {
|
||||
std::cout << (show ? "\033[?25h" : "\033[?25l");
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terminal& Terminal::drawBox(i32 startRow, i32 startCol, i32 width, i32 height, std::string_view title) {
|
||||
// 1. Draw the top border
|
||||
move(startRow, startCol);
|
||||
std::cout << "┌";
|
||||
for (i32 i = 0; i < width - 2; ++i) std::cout << "─";
|
||||
std::cout << "┐";
|
||||
|
||||
// 2. Draw the sides
|
||||
for (i32 i = 1; i < height - 1; ++i) {
|
||||
move(startRow + i, startCol);
|
||||
std::cout << "│";
|
||||
move(startRow + i, startCol + width - 1);
|
||||
std::cout << "│";
|
||||
}
|
||||
|
||||
// 3. Draw the bottom border
|
||||
move(startRow + height - 1, startCol);
|
||||
std::cout << "└";
|
||||
for (i32 i = 0; i < width - 2; ++i) std::cout << "─";
|
||||
std::cout << "┘";
|
||||
|
||||
// 4. Overlay the title if provided
|
||||
if (!title.empty()) {
|
||||
move(startRow, startCol + (width - i32(title.size()) - 2) / 2);
|
||||
std::cout << " " << title << " ";
|
||||
}
|
||||
|
||||
std::cout.flush();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terminal& Terminal::flush() {
|
||||
std::cout << std::flush;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terminal& Terminal::sink() {
|
||||
std::cin.clear();
|
||||
#if defined(SPIDER_OS_WINDOWS)
|
||||
while (_kbhit()) _getch();
|
||||
#endif
|
||||
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
|
||||
tcflush(STDIN_FILENO, TCIFLUSH);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair<i32, i32> Terminal::getSize() {
|
||||
std::pair<i32, i32> pair;
|
||||
#if defined(SPIDER_OS_WINDOWS)
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
|
||||
pair.first = csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
||||
pair.second = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
|
||||
}
|
||||
#endif
|
||||
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
|
||||
struct winsize w;
|
||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
|
||||
pair.first = w.ws_col;
|
||||
pair.second = w.ws_row;
|
||||
}
|
||||
#endif
|
||||
return pair;
|
||||
}
|
||||
|
||||
Terminal& Terminal::wait() {
|
||||
sink();
|
||||
std::cin.get();
|
||||
return *this;
|
||||
}
|
||||
|
||||
u8 Terminal::getKey() {
|
||||
#if defined(SPIDER_OS_WINDOWS)
|
||||
i32 ch = _getch();
|
||||
if (ch == 0 || ch == 224) {
|
||||
switch (_getch()) {
|
||||
case 72: return Terminal::UP;
|
||||
case 80: return Terminal::DOWN;
|
||||
case 75: return Terminal::LEFT;
|
||||
case 77: return Terminal::RIGHT;
|
||||
default: return Terminal::UNKNOWN;
|
||||
}
|
||||
}
|
||||
if (ch == 13) return Terminal::ENTER;
|
||||
if (ch == 27) return Terminal::ESC;
|
||||
if (ch == 8) return Terminal::BACKSPACE;
|
||||
return Terminal::UNKNOWN;
|
||||
#endif
|
||||
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
|
||||
struct termios oldt, newt;
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
newt = oldt;
|
||||
//newt.c_lflag &= ~(ICANON | ECHO);
|
||||
newt.c_lflag &= static_cast<tcflag_t>(~(ICANON | ECHO)); //added this line
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||
|
||||
u8 result = Terminal::UNKNOWN;
|
||||
int ch = getchar();
|
||||
|
||||
if (ch == 27) { // Potential Escape Sequence
|
||||
// Use a small timeout or check if more chars are in buffer
|
||||
// to distinguish between 'Esc' key and 'Arrow' sequence
|
||||
// Another Win for the Win API
|
||||
struct timeval tv = { 0, 10000 }; // 10ms wait
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(STDIN_FILENO, &fds);
|
||||
|
||||
if (select(1, &fds, NULL, NULL, &tv) > 0) {
|
||||
if (getchar() == '[') {
|
||||
switch (getchar()) {
|
||||
case 'A': result = Terminal::UP; break;
|
||||
case 'B': result = Terminal::DOWN; break;
|
||||
case 'D': result = Terminal::LEFT; break;
|
||||
case 'C': result = Terminal::RIGHT; break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = Terminal::ESC;
|
||||
}
|
||||
} else if (ch == 10) result = Terminal::ENTER;
|
||||
else if (ch == 127) result = Terminal::BACKSPACE;
|
||||
else result = static_cast<u8>(ch); //added this line
|
||||
//else result = (u8)ch;
|
||||
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
u8 Terminal::getKeyNb() {
|
||||
#if defined(SPIDER_OS_WINDOWS)
|
||||
if (_kbhit()) return getKey();
|
||||
return Terminal::UNKNOWN;
|
||||
#endif
|
||||
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
|
||||
struct timeval tv = { 0, 0 };
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(STDIN_FILENO, &fds);
|
||||
// select() returns > 0 if there is data to read
|
||||
if (select(1, &fds, NULL, NULL, &tv) > 0) {
|
||||
return getKey();
|
||||
}
|
||||
return Terminal::UNKNOWN;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
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 {
|
||||
isize total_padding = isize(width) - s.length();
|
||||
isize left_padding = total_padding / 2;
|
||||
std::cout << std::string(left_padding, ' ');
|
||||
std::cout << s;
|
||||
std::cout << std::string(total_padding - left_padding, ' ');
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Terminal& read(T& var) {
|
||||
std::cin >> var;
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user