38 Commits

Author SHA1 Message Date
dd1cd03026 Merge pull request 'Implement instructions 0x03C-0x053, add flag constants and fix execute pipeline' (#5) from diego/instruc-03c-053 into main
Reviewed-on: #5
2026-04-09 01:14:03 +00:00
75f4b160bf Merge pull request 'Implement instructions 0x068-0x079: casts and math functions' (#6) from diego/instruc-068-079 into main
Reviewed-on: #6
2026-04-09 01:12:41 +00:00
Diego De Gante Pérez
0184ef6394 ADD personal DGANT easter egg instruction on 0x0F6 2026-04-08 18:38:26 -06:00
30e0203df4 implement instructions 0x068-0x079: D2I, D2L, trig and exponential functions 2026-04-08 16:11:18 -06:00
7713be5293 feat: implement logic for BRAD instruction checksum algorithm
Implemented the memory integrity scan algorithm. Validates the first 256 bytes of system memory against a security signature.

Signed-off-by: BradleyVergara <2209213@upy.edu.mx>
2026-04-07 23:41:11 +00:00
b61cc6b149 docs: implement formal specification for BRAD memory integrity check
Added Opcode 0xF7 (BRAD) to the instruction set. This instruction performs a 256-byte memory checksum to validate system integrity against a secure MAGIC_SIGNATURE.

Signed-off-by: BradleyVergara <2209213@upy.edu.mx>
2026-04-07 23:26:52 +00:00
7155ad8d5a Finished STB, CRB and TSB instructions 2026-04-06 19:18:30 -06:00
0449074ef6 Finished BOOL, FBT, UDMD and DMOD 2026-04-06 17:56:00 -06:00
Diego De Gante Pérez
d2ce5ea4bd Merge main and resolve conflicts 2026-04-06 13:41:49 -06:00
Diego De Gante Pérez
6fb7a23e5d Simplify instruction comments and add default cases to switches 2026-04-06 13:12:31 -06:00
484c2a6afe Merge branch 'main' of https://git.sintekanalytics.com/SpiderLang/spider-runtime 2026-04-06 13:02:17 -06:00
6f8a9d80f2 added unfinished code to instructions 2026-04-06 13:02:12 -06:00
Diego De Gante Pérez
429596af86 Implement instructions 0x03C-0x053, add flag constants and fix execute dispatch 2026-04-06 12:33:43 -06:00
36889e160b Merge pull request 'arturo-fixed-files-branch' (#4) from arturo-fixed-files-branch into main
Reviewed-on: #4
2026-04-01 16:38:57 +00:00
4e1a601175 Added unfinished code to instructions 2026-03-31 11:21:35 -06:00
Arturo
f82aa627c4 Fix execute() dispatch, addrModes mask, reg() operand ptr, cast warnings, and Enter key step 2026-03-31 01:19:00 -06:00
Arturo
7d3781681d Implement float math and type conversion instructions (054-067) 2026-03-30 23:44:10 -06:00
6ac82b47e7 Added DIV, UDIV, MOD, UMOD intruction code 2026-03-30 12:54:19 -06:00
48785b6a94 Corrections to MUL and EXS functions 2026-03-30 12:19:41 -06:00
c8bfdf44b6 Merge branch 'main' of https://git.sintekanalytics.com/SpiderLang/spider-runtime 2026-03-30 12:16:22 -06:00
eba69f767e Added INC, DEC, ADD, SUB, MUL, UMUL instructions code 2026-03-30 12:16:18 -06:00
67ed4a7fc4 added signed ints to register, how was this not added before?! 2026-03-30 12:13:55 -06:00
0015387d60 ok ok it compiles. commented a lot too so check that out 2026-03-30 07:43:09 -06:00
15bf03097f Merge branch 'main' of https://git.sintekanalytics.com/SpiderLang/spider-runtime 2026-03-29 07:50:14 -06:00
43f5d26b3d I'm still working on this 2026-03-29 07:50:11 -06:00
f0148dbe45 Implemented EXS instructions 2026-03-29 02:08:56 -06:00
b397371a53 Added COM, NEG instructions 2026-03-28 13:39:53 -06:00
aabcfc6f0c Added all instructions as empty instructions. Compiles on WIN + MSYS2, UCRT64 2026-03-27 19:24:26 -06:00
41dd2b87b4 Merge branch 'main' of https://git.sintekanalytics.com/SpiderLang/spider-runtime 2026-03-27 18:59:38 -06:00
3d80b690c4 better algorithm to load bytes 2026-03-27 18:59:36 -06:00
a077c084a2 code changed 2026-03-27 16:47:50 -06:00
38006fe19a deleted document 2026-03-27 16:40:28 -06:00
6895309679 tested code 2026-03-27 16:39:29 -06:00
08e994ad44 changed code 2026-03-27 16:37:47 -06:00
2f38eb38b8 Merge branch 'main' of https://git.sintekanalytics.com/SpiderLang/spider-runtime 2026-03-27 16:36:04 -06:00
5f342991b0 deleted 2026-03-27 16:35:54 -06:00
a5ffb69565 code chnages 2026-03-27 16:34:23 -06:00
8697b44f53 Added document 2026-03-27 16:05:53 -06:00
42 changed files with 2055 additions and 337 deletions

Binary file not shown.

View File

@@ -15,7 +15,7 @@ OBJEXT := o
#Flags, Libraries and Includes
ROOT := ./
CFLAGS := -std=c++20 -O2 \
-Wall -Wextra \
-Wall -Werror -Wextra \
-Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align \
-Wunused -Woverloaded-virtual -Wconversion \
-Wsign-conversion -Wnull-dereference -Wdouble-promotion \

View File

@@ -144,7 +144,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"id": "58645013",
"metadata": {},
"outputs": [
@@ -283,7 +283,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 5,
"id": "452bc76c",
"metadata": {},
"outputs": [
@@ -357,7 +357,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 6,
"id": "5aaebef0",
"metadata": {},
"outputs": [
@@ -451,7 +451,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 7,
"id": "instrmap_gen",
"metadata": {},
"outputs": [
@@ -615,6 +615,54 @@
"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": {
@@ -633,7 +681,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.7"
"version": "3.14.3"
}
},
"nbformat": 4,

View File

@@ -17,8 +17,10 @@ namespace spider {
// Stepping/Running the Machine //
void Runtime::step() {
// fetchInstr() decodes the opcode, addressing mode and type siz
cpu.fetchInstr();
// TODO: Call instruction
// execute() completes the fetch-decode-execute cycle by calling the correct instruction method based on the opcode.
cpu.execute();
}
void Runtime::step(u64 n) {
@@ -34,7 +36,7 @@ namespace spider {
void Runtime::run() {}
void Runtime::run(u64 n) {}
//void Runtime::run(u64 n) {}
// Misc //
@@ -45,9 +47,10 @@ namespace spider {
/**
* Non-owning reel setup.
*/
void Runtime::hookReel(InstrReel* reel, bool own) {
cpu.hookInstrReel(reel);
if(own) this->reel = reel;
void Runtime::hookReel(InstrReel* newReel, bool own) {
delete this->reel;
cpu.hookInstrReel(newReel);
if(own) this->reel = newReel;
}
}

View File

@@ -75,7 +75,7 @@ namespace spider {
/**
* Non-owning reel setup.
*/
void hookReel(InstrReel* reel, bool own = false);
void hookReel(InstrReel* newReel, bool own = false);
};

View File

@@ -1,214 +1,33 @@
#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) {
}
: RA{}, RB{}, RC{}, RD{},
RX{}, RY{}, R0{}, R1{},
R2{}, R3{}, R4{}, R5{},
R6{}, R7{}, R8{}, R9{},
RF{}, RI{}, RS{}, RZ{},
RE{}, RN{}, RV{}, RM{}
{}
CPU::~CPU() {}
// Setup & Configuration //
void CPU::hookRAM(RAM* ram) {
this->_ram = ram;
}
void CPU::hookInstrReel(InstrReel* reel) {
this->_reel = reel;
}
constexpr u64 CPU::getFlag(u64 mask) {
if (!mask) return 0;
#if __cplusplus >= 202002L
return (RF & mask) >> std::countr_zero(mask);
#elif defined(SPIDER_COMPILER_GCC_LIKE)
return (RF & mask) >> __builtin_ctzll(mask);
#elif defined(SPIDER_COMPILER_MSVC)
return (RF & mask) >> _BitScanForward64(mask);
#else
// If you have reached this part,
// please come up with a better alternative.
u64 bits = RF & mask;
while (mask && (mask >>= 1)) bits >>= 1;
return bits;
#endif
}
// Interaction with Reel //
CPU::Fn CPU::addrModes[] = {
&CPU::imm, &CPU::abs,
&CPU::reg, &CPU::ind,
&CPU::ptr, &CPU::idx,
&CPU::sca, &CPU::dis
};
void CPU::fetchInstr() {
u16 i = _reel->readU16(RI);
_opcode = (i >> 7) & 0x1FF;
_addrm = (i >> 2) & 0x1F;
_size = i & 0x3;
RI += 2;
}
void CPU::fetchOperDst() {
// Move the operand ptrs
_alu = &ALU0;
_opers[1] = _opers[0];
// call specific addressing mode
(this->*(CPU::addrModes[_addrm]))();
}
void CPU::fetchOperSrc() {
// set ALU
_alu = &ALU1;
// call specific addressing mode
(this->*(CPU::addrModes[_addrm]))();
// modify the _addrm register
_addrm >>= 3;
_addrm++;
}
void CPU::execute() {
(this->*(CPU::addrModes[_opcode]))();
}
// Addressing Modes //
/**
* Implied Addressing Mode
*/
void CPU::imp() {
// Nothing //
}
/**
* Immediate Addressing Mode
*/
void CPU::imm() {
switch(_size) {
case 0b00:
_alu->_u8 = _reel->readU8(RI);
break;
case 0b01:
_alu->_u16 = _reel->readU16(RI);
break;
case 0b10:
_alu->_u32 = _reel->readU32(RI);
break;
case 0b11:
_alu->_u64 = _reel->readU64(RI);
break;
}
_opers[0] = _alu;
_post = &CPU::imp;
RI += 1 << _size;
}
/**
* Absolute Addressing Mode
*/
void CPU::abs() { // TODO cache ptr size
u8 dat_size = 1 << _size;
u8 ptr_size = 1 << getFlag(CPU::FLAG_MEMORY_MODE);
u64 ptr = 0;
if(ptr_size + dat_size > _ram->size()) return; // TODO: avoid overflow
switch(ptr_size) {
case 1:
ptr = _reel->readU8(RI);
break;
case 2:
ptr = _reel->readU16(RI);
break;
case 4:
ptr = _reel->readU32(RI);
break;
case 8:
ptr = _reel->readU64(RI);
break;
}
switch(_size) {
case 0b00:
spider::loadLE(&_alu->_u8, &(*_ram)[ptr]);
break;
case 0b01:
spider::loadLE(&_alu->_u16, &(*_ram)[ptr]);
break;
case 0b10:
spider::loadLE(&_alu->_u32, &(*_ram)[ptr]);
break;
case 0b11:
spider::loadLE(&_alu->_u64, &(*_ram)[ptr]);
break;
}
RI += dat_size;
}
/**
* Register Addressing Mode
*/
void CPU::reg() {
}
/**
* Indrect Addressing Mode
*/
void CPU::ind() {}
/**
* Pointer Addressing Mode
*/
void CPU::ptr() {}
/**
* Indexed Addressing Mode
*/
void CPU::idx() {}
/**
* Scaled Addressing Mode
*/
void CPU::sca() {}
/**
* Displaced Addressing Mode
*/
void CPU::dis() {}
/**
* Post Write Action
*/
void CPU::psw() {}
}
/**
* @brief BRAD (0xF7) - Memory Integrity Checksum
* Escanea los primeros 256 bytes de memoria y valida contra una firma de seguridad.
* Implementado por Bradley Vergara Lara - Estancia 2026.
*/
void CPU::BRAD() {
u32 checksum = 0;
const u32 MAGIC_SIGNATURE = 0x504944; // Firma de integridad "PID"
// Recorre la memoria base del sistema
for (u16 i = 0; i < 256; i++) {
checksum += memory.read8(i);
}
// Si el checksum coincide, RA = 1 (OK), si no RA = 0 (Error)
RA = (checksum == MAGIC_SIGNATURE) ? 1 : 0;
}

View File

@@ -15,6 +15,14 @@ namespace spider {
static constexpr const u64 FLAG_INTERRUPT_REQUEST = 0b0000000000000000000000000000000000000000000000000000000000000100;
static constexpr const u64 FLAG_EXCEPTION = 0b0000000000000000000000000000000000000000000000000000000000001000;
static constexpr const u64 FLAG_MEMORY_MODE = 0b0000000000000000000000000000000000000000000000000000000000110000;
static constexpr const u64 FLAG_EXT_INT_DISABLE = 0b0000000000000000000000000000000000000000000000000000000010000000; // bit 7
static constexpr const u64 FLAG_EQUAL = 0b0000000000000000000000000000000000000000000000000000010000000000; // bit 10
static constexpr const u64 FLAG_EPSILON_ENABLE = 0b0000000000000000000000000000000000000000000000000001000000000000; // bit 12
static constexpr const u64 FLAG_HOTSWAP_SIGNAL = 0b0000000000000000000000000000000000000000000000010000000000000000; // bit 16
static constexpr const u64 FLAG_USER_A = 0b0000000000000000000000000000000000000000000100000000000000000000; // bit 20
static constexpr const u64 FLAG_USER_B = 0b0000000000000000000000000000000000000000001000000000000000000000; // bit 21
static constexpr const u64 FLAG_USER_C = 0b0000000000000000000000000000000000000000010000000000000000000000; // bit 22
static constexpr const u64 FLAG_USER_D = 0b0000000000000000000000000000000000000000100000000000000000000000; // bit 23
public: // Map of addressing modes & Instructions
@@ -876,6 +884,11 @@ namespace spider {
// Operation:
void UPY();
// [Easter Eggs] 0x0F6 — DGANT: "In kaaba Spider" (Yucatec Maya: My name is Spider)
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: Writes "IN KAABA SPIDER" one char per GP register
void DGANT();
// </pygen-target> //
};

View File

@@ -18,10 +18,53 @@ 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];
// -- Un/Signed 32 -- //
struct {
#if SPIDER_LITTLE_ENDIAN
u32 _u32; u32 : 32;
#else
u32 : 32; u32 _u32;
#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
@@ -35,22 +78,17 @@ namespace spider {
struct {
#if SPIDER_LITTLE_ENDIAN
u16 _u16;
u16 : 16; u16 : 16; u16 : 16;
i8 _i8; // ditto
i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8;
#else
u16 : 16; u16 : 16; u16 : 16;
u16 _u16;
i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8; i8 : 8;
i8 _i8;
#endif
};
struct {
#if SPIDER_LITTLE_ENDIAN
u32 _u32; u32 : 32;
#else
u32 : 32; u32 _u32;
#endif
};
// -- Floating Point -- //
f64 _f64;
struct {
#if SPIDER_LITTLE_ENDIAN
f32 _f32; u32 : 32;
@@ -59,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];
@@ -75,6 +117,7 @@ namespace spider {
return _bytes[7 - i];
#endif
}
};
static_assert(sizeof(register_t) == 8, "The register type must be exactly 8 bytes.");

View File

@@ -39,7 +39,7 @@ namespace spider {
;
}
void drawCPUTempl(Terminal& t, CPU& cpu) {
void drawCPUTempl(Terminal& t) {
i32 r = 8, c = 1;
i32 w = 35, h = 31;
t.drawBox(r, c, w, h, "CPU");
@@ -171,10 +171,10 @@ namespace spider {
t.flush();
}
i32 addressWidth(isize ramSize) {
u32 addressWidth(isize ramSize) {
if (ramSize == 0) return 1;
isize maxAddr = ramSize - 1;
i32 digits = 0;
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 {
@@ -193,13 +193,13 @@ namespace spider {
* @param progress The current progress
* @param total The total
*/
void drawScrollThumb(Terminal& term, i32 x, i32 y, i32 trackHeight, isize progress, isize 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 (int i = 0; i < trackHeight; ++i) {
term.move(y + i, x).print("");
for (u32 i = 0; i < trackHeight; ++i) {
term.move(i32(y + i), i32(x)).print("");
}
// 2. Calculate Thumb Position
@@ -210,10 +210,10 @@ namespace spider {
f64 ratio = f64(progress) / f64(total);
// Map to track coordinates
i32 thumbOffset = i32(ratio * (trackHeight - 1));
u32 thumbOffset = u32(ratio * (trackHeight - 1));
// 3. Draw the Thumb (Full Block: █)
term.move(y + thumbOffset, x);
term.move(i32(y + thumbOffset), i32(x));
term.style(Terminal::FG_WHITE).print("");
term.style(Terminal::RESET);
}
@@ -230,30 +230,30 @@ namespace spider {
*/
void drawRAM(Terminal& term, RAM& ram, u64 scrollPos) {
// 1. Draw the container box
i32 y = 3;
i32 height = 36;
u32 y = 3;
u32 height = 36;
// 2. Configuration for the hex layout
int addrWidth = addressWidth(ram.size());
int bytesPerRow = 8;
int displayRows = height - 2; // Subtract top/bottom borders
i32 width = (2 + 2 + 16 + 7 + 3 + 8 + 4) + addrWidth;
i32 x = 37;
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(y, x, width, height, "RAM");
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 < 0) scrollPos = 0;
if (scrollPos > ram.size()) scrollPos = ram.size();
for (int i = 0; i < displayRows; ++i) {
for (u32 i = 0; i < displayRows; ++i) {
isize currentRowAddr = scrollPos + (i * bytesPerRow);
// address lock
if (currentRowAddr >= ram.size()) {
term.move(y + 1 + i, x + 1);
term.move(i32(y + 1 + i), i32(x + 1));
term.print(std::string(width - 3, ' '));
continue;
}
@@ -266,11 +266,11 @@ namespace spider {
ss << std::setfill('0') << std::uppercase << std::hex;
// address
ssaddr << std::setw(addrWidth) << currentRowAddr << " ";
ssaddr << std::setw(i32(addrWidth)) << currentRowAddr << " ";
// Hex Bytes
std::string asciiPart = "";
for (int j = 0; j < bytesPerRow; ++j) {
for (u32 j = 0; j < bytesPerRow; ++j) {
isize targetAddr = currentRowAddr + j;
if (targetAddr >= ram.size()) {
ss << ""; // Padding for end of memory
@@ -279,12 +279,12 @@ namespace spider {
}
u8 byte = ram[targetAddr];
ss << std::setfill('0') << std::setw(2) << std::hex << (u32)byte << " ";
asciiPart += (std::isprint(byte) ? (char)byte : '.');
ss << std::setfill('0') << std::setw(2) << std::hex << u32(byte) << " ";
asciiPart += (std::isprint(byte) ? char(byte) : '.');
}
// --- Combine and Print ---
term.move(y + 1 + i, x + 2); // Move inside the box
term.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(" | ");
@@ -330,18 +330,16 @@ namespace spider {
int liveDebugMain() {
Terminal t;
Runtime runtime(1024);
InstrReelFixed fix(100);
runtime.ram[0] = 0xFF;
runtime.ram[1] = 0xEE;
runtime.ram[2] = 0xDD;
runtime.ram[3] = 0xCC;
runtime.ram[4] = 0xBB;
runtime.ram[5] = 0xAA;
runtime.ram[6] = 0x99;
runtime.ram[7] = 0x88;
fix.writeU16(0, 0b0000111);
runtime.hookReel(&fix, false);
bool running = true, update = true;
u64 ramScroll = 0;
u8 key = Terminal::UNKNOWN;
@@ -351,7 +349,7 @@ namespace spider {
drawTime(t);
drawHead(t);
drawCPUTempl(t, runtime.cpu);
drawCPUTempl(t);
// delay for time
auto last_exec = std::chrono::steady_clock::now();
@@ -388,7 +386,7 @@ namespace spider {
case Terminal::ENTER:
update = true;
runtime.cpu.fetchInstr();
runtime.cpu.fetchOperDst();
runtime.cpu.execute(); // looks up instrMap[_opcode] & calls the correct instruction method (e.g. FMUL)
break;
default:
break;

View File

@@ -281,7 +281,7 @@ CPU::Fn CPU::instrMap[] = {
nullptr, // 0x0F3
nullptr, // 0x0F4
nullptr, // 0x0F5
nullptr, // 0x0F6
&CPU::DGANT, // 0x0F6
nullptr, // 0x0F7
nullptr, // 0x0F8
nullptr, // 0x0F9

View File

@@ -1,9 +0,0 @@
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
void CPU::NOP() {
// No Operation //
}
}

View File

@@ -0,0 +1,356 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
void CPU::NOP() {
// TODO: Implement NOP
}
void CPU::SPDR() {
// TODO: Implement SPDR
}
void CPU::MMODE() {
// TODO: Implement MMODE
}
void CPU::INT() {
// TODO: Implement INT
}
void CPU::LRV() {
// TODO: Implement LRV
}
void CPU::FSR() {
// TODO: Implement FSR
}
void CPU::FIR() {
// TODO: Implement FIR
}
void CPU::FZR() {
// TODO: Implement FZR
}
void CPU::LSR() {
// TODO: Implement LSR
}
void CPU::FVR() {
// TODO: Implement FVR
}
void CPU::MOV() {
// TODO: Implement MOV
}
void CPU::MOR() {
// TODO: Implement MOR
}
void CPU::AMOV() {
// TODO: Implement AMOV
}
void CPU::SWP() {
// TODO: Implement SWP
}
void CPU::AHM() {
// TODO: Implement AHM
}
void CPU::COM() {
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 = ~_dst->_u8;
break;
case 0b01: //short
_dst->_u16 = ~_dst->_u16;
break;
case 0b10: //int
_dst->_u32 = ~_dst->_u32;
break;
case 0b11: //long
_dst->_u64 = ~_dst->_u64;
break;
}
(this->*_post)();
}
void CPU::NEG() {
// TODO: Implement NEG
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 = 1 + ~_dst->_u8;
break;
case 0b01: //short
_dst->_u16 = 1+ ~_dst->_u16;
break;
case 0b10: //int
_dst->_u32 = 1 + ~_dst->_u32;
break;
case 0b11: //long
_dst->_u64 = 1 + ~_dst->_u64;
break;
}
(this->*_post)();
}
void CPU::EXS() { // THIS IS INCORRECT!!!
// TODO: Implement EXS
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_i16 = static_cast<i16>(_dst->_i8);
break;
case 0b01: //short
_dst->_i32 = static_cast<i32>(_dst->_i16);
break;
case 0b10: //int
_dst->_i64 = static_cast<i64>(_dst->_i32);
break;
case 0b11: //long
_dst->_i64 = _dst->_i64;
break;
}
_dst->_u32 = _dst->_u8;
(this->*_post)();
}
void CPU::INC() {
// TODO: Implement INC
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 += 1;
case 0b01: //short
_dst->_u16 += 1;
case 0b10: //int
_dst->_u32 += 1;
case 0b11: //long
_dst->_u64 += 1;
}
(this->*_post)();
}
void CPU::DEC() {
// TODO: Implement DEC
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 -= 1;
case 0b01: //short
_dst->_u16 -= 1;
case 0b10: //int
_dst->_u32 -= 1;
case 0b11: //long
_dst->_u64 -= 1;
}
(this->*_post)();
}
void CPU::ADD() {
// TODO: Implement ADD
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 += _src->_u8;
case 0b01: //short
_dst->_u16 += _src->_u16;
case 0b10: //int
_dst->_u32 += _src->_u32;
case 0b11: //long
_dst->_u64 += _src->_u64;
}
(this->*_post)();
}
void CPU::SUB() {
// TODO: Implement SUB
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 -= _src->_u8;
case 0b01: //short
_dst->_u16 -= _src->_u16;
case 0b10: //int
_dst->_u32 -= _src->_u32;
case 0b11: //long
_dst->_u64 -= _src->_u64;
}
(this->*_post)();
}
void CPU::MUL() {
// TODO: Implement MUL
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_i8 = _src->_i8 * _dst->_i8;
case 0b01: //short
_dst->_i16 = _src->_i16 * _dst->_i16;
case 0b10: //int
_dst->_i32 = _src->_i32 * _dst->_i32;
case 0b11: //long
_dst->_i64 = _src->_i64 * _dst->_i64;
}
(this->*_post)();
}
void CPU::UMUL() {
// TODO: Implement UMUL
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 = _src->_u8 * _dst->_u8;
case 0b01: //short
_dst->_u16 = _src->_u16 * _dst->_u16;
case 0b10: //int
_dst->_u32 = _src->_u32 * _dst->_u32;
case 0b11: //long
_dst->_u64 = _src->_u64 * _dst->_u64;
}
(this->*_post)();
}
void CPU::DIV() {
// TODO: Implement DIV
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_i8 = _dst->_i8 / _src->_i8;
case 0b01: //short
_dst->_i16 = _dst->_i16 / _src->_i16;
case 0b10: //int
_dst->_i32 = _dst->_i32 / _src->_i32;
case 0b11: //long
_dst->_i64 = _dst->_i64 / _src->_i64;
}
(this->*_post)();
}
void CPU::UDIV() {
// TODO: Implement UDIV
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 = _dst->_u8 / _src->_u8;
case 0b01: //short
_dst->_u16 = _dst->_u16 / _src->_u16;
case 0b10: //int
_dst->_u32 = _dst->_u32 / _src->_u32;
case 0b11: //long
_dst->_u64 = _dst->_u64 / _src->_u64;
}
(this->*_post)();
}
void CPU::MOD() {
// TODO: Implement MOD
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_i8 = _dst->_i8 % _src->_i8;
case 0b01: //short
_dst->_i16 = _dst->_i16 % _src->_i16;
case 0b10: //int
_dst->_i32 = _dst->_i32 % _src->_i32;
case 0b11: //long
_dst->_i64 = _dst->_i64 % _src->_i64;
}
(this->*_post)();
}
void CPU::UMOD() {
// TODO: Implement UMOD
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
_dst->_u8 = _dst->_u8 % _src->_u8;
case 0b01: //short
_dst->_u16 = _dst->_u16 % _src->_u16;
case 0b10: //int
_dst->_u32 = _dst->_u32 % _src->_u32;
case 0b11: //long
_dst->_u64 = _dst->_u64 % _src->_u64;
}
(this->*_post)();
}
void CPU::DMOD() {
// TODO: Implement DMOD
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
RX._i8 = _dst->_i8 / _src->_i8;
RY._i8 = _dst->_i8 % _src->_i8;
case 0b01: //short
RX._i16 = _dst->_i16 / _src->_i16;
RY._i16 = _dst->_i16 % _src->_i16;
case 0b10: //int
RX._i32 = _dst->_i32 / _src->_i32;
RY._i32 = _dst->_i32 % _src->_i32;
case 0b11: //long
RX._i64 = _dst->_i64 / _src->_i64;
RY._i64 = _dst->_i64 % _src->_i64;
}
(this->*_post)();
}
void CPU::UDMD() {
// TODO: Implement UDMD
fetchOperSrc();
fetchOperDst();
switch(_size){
case 0b00: //byte
RX._u8 = _dst->_u8 / _src->_u8;
RY._u8 = _dst->_u8 % _src->_u8;
case 0b01: //short
RX._u16 = _dst->_u16 / _src->_u16;
RY._u16 = _dst->_u16 % _src->_u16;
case 0b10: //int
RX._u32 = _dst->_u32 / _src->_u32;
RY._u32 = _dst->_u32 % _src->_u32;
case 0b11: //long
RX._u64 = _dst->_u64 / _src->_u64;
RY._u64 = _dst->_u64 % _src->_u64;
}
(this->*_post)();
}
void CPU::FBT() {
// TODO: Implement FBT
fetchOperDst();
switch(_size){
case 0b00: //byte
RF = (RF & ~(0x3 << 9)) | ((_dst->_u8 >> 9) & 0x3) << 9;
case 0b01: //short
RF = (RF & ~(0x3 << 9)) | ((_dst->_u16 >> 9) & 0x3) << 9;
case 0b10: //int
RF = (RF & ~(0x3 << 9)) | ((_dst->_u32 >> 9) & 0x3) << 9;
case 0b11: //long
RF = (RF & ~(0x3 << 9)) | ((_dst->_u64 >> 9) & 0x3) << 9;
}
(this->*_post)();
}
}

View File

@@ -0,0 +1,240 @@
/**
* @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
}
// ── 0x03C — JMR: Dst + Instruction Register -> Instruction Register ──
void CPU::JMR() {
fetchOperDst();
i64 offset;
switch (_size) {
case 0b00: offset = static_cast<i64>(_dst->_i8); break; // 1 byte
case 0b01: offset = static_cast<i64>(_dst->_i16); break; // 2 bytes
case 0b10: offset = static_cast<i64>(_dst->_i32); break; // 4 bytes
case 0b11: offset = _dst->_i64; break; // 8 bytes
}
RI = static_cast<u64>(static_cast<i64>(RI) + offset);
}
// ── 0x03D — JER: Dst + Instruction Register -> Instruction Register IF Flags.EQ ──
void CPU::JER() {
fetchOperDst();
if (RF & CPU::FLAG_EQUAL) {
i64 offset;
switch (_size) {
case 0b00: offset = static_cast<i64>(_dst->_i8); break;
case 0b01: offset = static_cast<i64>(_dst->_i16); break;
case 0b10: offset = static_cast<i64>(_dst->_i32); break;
case 0b11: offset = _dst->_i64; break;
}
RI = static_cast<u64>(static_cast<i64>(RI) + offset);
}
}
// ── 0x03E — JNR: Dst + Instruction Register -> Instruction Register IF NOT Flags.EQ ──
void CPU::JNR() {
fetchOperDst();
if (!(RF & CPU::FLAG_EQUAL)) {
i64 offset;
switch (_size) {
case 0b00: offset = static_cast<i64>(_dst->_i8); break;
case 0b01: offset = static_cast<i64>(_dst->_i16); break;
case 0b10: offset = static_cast<i64>(_dst->_i32); break;
case 0b11: offset = _dst->_i64; break;
}
RI = static_cast<u64>(static_cast<i64>(RI) + offset);
}
}
// ── 0x03F — JIR: Dst + Instruction Register -> Instruction Register IF Src ──
void CPU::JIR() {
fetchOperSrc();
fetchOperDst();
if (_src->_u64 != 0) {
i64 offset;
switch (_size) {
case 0b00: offset = static_cast<i64>(_dst->_i8); break;
case 0b01: offset = static_cast<i64>(_dst->_i16); break;
case 0b10: offset = static_cast<i64>(_dst->_i32); break;
case 0b11: offset = _dst->_i64; break;
}
RI = static_cast<u64>(static_cast<i64>(RI) + offset);
}
}
}

View File

@@ -0,0 +1,401 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
#include <spider/runtime/memory/RAM.hpp>
#include <cmath> // provides std::fmod, std::fma and cast support
namespace spider {
// ── 0x040 — SFB: Store (User) Flag Bit ──────────────────────────────
void CPU::SFB() {
fetchOperSrc();
fetchOperDst();
u8 flag_idx = _dst->_u8 & 0x3;
u64 flag_bit = CPU::FLAG_USER_A << flag_idx;
if (_src->_u64 != 0) {
RF |= flag_bit;
} else {
RF &= ~flag_bit;
}
}
// ── 0x041 — LFB: Load (User) Flag Bit ──────────────────────────────
void CPU::LFB() {
fetchOperSrc();
fetchOperDst();
u8 flag_idx = _src->_u8 & 0x3;
u64 flag_bit = CPU::FLAG_USER_A << flag_idx;
_dst->_u64 = (RF & flag_bit) ? 1 : 0;
(this->*_post)();
}
// ── 0x042 — JUF: Jump to absolute position, if user flag is true ────
void CPU::JUF() {
fetchOperSrc();
fetchOperDst();
u8 flag_idx = _src->_u8 & 0x3;
u64 flag_bit = CPU::FLAG_USER_A << flag_idx;
if (RF & flag_bit) {
RI = _dst->_u64;
}
}
// ── 0x043 — JUR: Jump to relative position, if user flag is true ────
void CPU::JUR() {
fetchOperSrc();
fetchOperDst();
u8 flag_idx = _src->_u8 & 0x3;
u64 flag_bit = CPU::FLAG_USER_A << flag_idx;
if (RF & flag_bit) {
i64 offset;
switch (_size) {
case 0b00: offset = static_cast<i64>(_dst->_i8); break;
case 0b01: offset = static_cast<i64>(_dst->_i16); break;
case 0b10: offset = static_cast<i64>(_dst->_i32); break;
case 0b11: offset = _dst->_i64; break;
default: offset = 0; break;
}
RI = static_cast<u64>(static_cast<i64>(RI) + offset);
}
}
// ── 0x044 — PUSH: Dst -> pushed into stack ──────────────────────────
void CPU::PUSH() {
fetchOperDst();
u8 bytes = 1 << _size;
for (u8 i = 0; i < bytes; i++) {
_ram->at(RS + i) = (*_dst)[i];
}
RS += bytes;
}
// ── 0x045 — POP: popped from stack -> Dst ───────────────────────────
void CPU::POP() {
fetchOperDst();
u8 bytes = 1 << _size;
RS -= bytes;
_ram->loadRegister(RS, _size, _dst);
(this->*_post)();
}
// ── 0x046 — ALLOC: Dst -> heap ptr of size Dst ──────────────────────
void CPU::ALLOC() {
fetchOperDst();
// TODO: Proper heap allocation with gap tracking.
_dst->_u64 = 0;
(this->*_post)();
}
// ── 0x047 — HFREE: Frees heap ptr in Dst ────────────────────────────
void CPU::HFREE() {
fetchOperDst();
// TODO: Proper heap deallocation.
}
// ── 0x04A — CALL: Performs a function call, step XX ──────────────────
void CPU::CALL() {
fetchOperDst();
u64 target = _dst->_u64;
register_t rz_save;
rz_save._u64 = RZ;
for (u8 i = 0; i < 8; i++) {
_ram->at(RS + i) = rz_save[i];
}
RS += 8;
register_t ri_save;
ri_save._u64 = RI;
for (u8 i = 0; i < 8; i++) {
_ram->at(RS + i) = ri_save[i];
}
RS += 8;
RZ = RS;
RI = target;
}
// ── 0x04B — RET: Undoes a function call, step XX ────────────────────
void CPU::RET() {
RS = RZ;
RS -= 8;
register_t ri_restore;
_ram->loadRegister(RS, 0b11, &ri_restore);
RI = ri_restore._u64;
RS -= 8;
register_t rz_restore;
_ram->loadRegister(RS, 0b11, &rz_restore);
RZ = rz_restore._u64;
}
// ── 0x04C — EDI: bool( Dst ) -> Enable External Interrupts Bit ─────
void CPU::EDI() {
fetchOperDst();
if (_dst->_u64 != 0) {
RF &= ~CPU::FLAG_EXT_INT_DISABLE;
} else {
RF |= CPU::FLAG_EXT_INT_DISABLE;
}
}
// ── 0x04D — SHSS: bool( Dst ) -> Hot Swap Signal Bit ────────────────
void CPU::SHSS() {
fetchOperDst();
if (_dst->_u64 != 0) {
RF |= CPU::FLAG_HOTSWAP_SIGNAL;
} else {
RF &= ~CPU::FLAG_HOTSWAP_SIGNAL;
}
}
// ── 0x050 — FLI: Float Load Immediate ───────────────────────────────
void CPU::FLI() {
fetchOperDst();
(this->*_post)();
}
// ── 0x051 — FNEG: - Dst -> Dst ──────────────────────────────────────
void CPU::FNEG() {
fetchOperDst();
switch (_size) {
case 0b10: _dst->_f32 = -_dst->_f32; break;
case 0b11: _dst->_f64 = -_dst->_f64; break;
default: break;
}
(this->*_post)();
}
// ── 0x052 — FADD: Dst + Src -> Dst ──────────────────────────────────
void CPU::FADD() {
fetchOperSrc();
fetchOperDst();
switch (_size) {
case 0b10: _dst->_f32 += _src->_f32; break;
case 0b11: _dst->_f64 += _src->_f64; break;
default: break;
}
(this->*_post)();
}
// ── 0x053 — FSUB: Dst - Src -> Dst ──────────────────────────────────
void CPU::FSUB() {
fetchOperSrc();
fetchOperDst();
switch (_size) {
case 0b10: _dst->_f32 -= _src->_f32; break;
case 0b11: _dst->_f64 -= _src->_f64; break;
default: break;
}
(this->*_post)();
}
// ── 0x054 — FMUL: Float Multiplication ───────────────────────────────────
void CPU::FMUL() {
fetchOperSrc();
fetchOperDst();
switch (_size) {
case 0b10: _dst->_f32 *= _src->_f32; break; // f32
case 0b11: _dst->_f64 *= _src->_f64; break; // f64
default: break; // invalid size
}
(this->*_post)();
}
// ── 0x055 — FDIV: Float Division ─────────────────────────────────────────
void CPU::FDIV() {
fetchOperSrc();
fetchOperDst();
switch (_size) {
case 0b10: _dst->_f32 /= _src->_f32; break;
case 0b11: _dst->_f64 /= _src->_f64; break;
default: break;
}
(this->*_post)();
}
// ── 0x056 — FMOD: Float Modulus ──────────────────────────────────────────
// C++ has no % for floats — std::fmod performs the equivalent operation
void CPU::FMOD() {
fetchOperSrc();
fetchOperDst();
switch (_size) {
case 0b10: _dst->_f32 = std::fmod(_dst->_f32, _src->_f32); break;
case 0b11: _dst->_f64 = std::fmod(_dst->_f64, _src->_f64); break;
default: break;
}
(this->*_post)();
}
// ── 0x057 — FDMOD: Float Division and Modulus ────────────────────────────
// dst / src = RX (quotient) * src + RY (remainder)
void CPU::FDMOD() {
fetchOperSrc();
fetchOperDst();
switch (_size) {
case 0b10: {
f32 q = static_cast<f32>(static_cast<i32>(_dst->_f32 / _src->_f32));
f32 r = _dst->_f32 - (q * _src->_f32);
RX._f32 = q;
RY._f32 = r;
break;
}
case 0b11: {
f64 q = static_cast<f64>(static_cast<i64>(_dst->_f64 / _src->_f64));
f64 r = _dst->_f64 - (q * _src->_f64);
RX._f64 = q;
RY._f64 = r;
break;
}
default: break;
}
(this->*_post)();
}
// ── 0x058 — FEPS: Set Float Epsilon Value ────────────────────────────────
// Loads the epsilon value into RN (the epsilon register)
void CPU::FEPS() {
fetchOperDst();
switch (_size) {
case 0b10: RN = _dst->_u32; break; // store f32 bits in RN
case 0b11: RN = _dst->_u64; break; // store f64 bits in RN
default: break;
}
(this->*_post)();
}
// ── 0x059 — FEEP: Float Enable/Disable Epsilon ───────────────────────────
// Bit 12 of RF is the Epsilon Enable flag
void CPU::FEEP() {
fetchOperDst();
constexpr u64 EPSILON_ENABLE_BIT = (1ULL << 12);
if (_dst->_u64) RF |= EPSILON_ENABLE_BIT; // non-zero → enable
else RF &= ~EPSILON_ENABLE_BIT; // zero → disable
(this->*_post)();
}
// ── 0x05A — FEQ: Float Equal ──────────────────────────────────────────────
// Sets bit 10 (Zero/Equal flag) in RF if dst == src
void CPU::FEQ() {
fetchOperSrc();
fetchOperDst();
constexpr u64 ZERO_FLAG = (1ULL << 10);
bool equal = false;
switch (_size) {
case 0b10: equal = (_dst->_f32 == _src->_f32); break;
case 0b11: equal = (_dst->_f64 == _src->_f64); break;
default: break;
}
if (equal) RF |= ZERO_FLAG;
else RF &= ~ZERO_FLAG;
(this->*_post)();
}
// ── 0x05B — FNE: Float Not Equal ─────────────────────────────────────────
void CPU::FNE() {
fetchOperSrc();
fetchOperDst();
constexpr u64 ZERO_FLAG = (1ULL << 10);
bool notEqual = false;
switch (_size) {
case 0b10: notEqual = (_dst->_f32 != _src->_f32); break;
case 0b11: notEqual = (_dst->_f64 != _src->_f64); break;
default: break;
}
if (notEqual) RF |= ZERO_FLAG;
else RF &= ~ZERO_FLAG;
(this->*_post)();
}
// ── 0x05C — FGT: Float Greater Than ──────────────────────────────────────
// Sets/clears bit 9 (Negative flag) in RF
void CPU::FGT() {
fetchOperSrc();
fetchOperDst();
constexpr u64 NEGATIVE_FLAG = (1ULL << 9);
bool gt = false;
switch (_size) {
case 0b10: gt = (_dst->_f32 > _src->_f32); break;
case 0b11: gt = (_dst->_f64 > _src->_f64); break;
default: break;
}
if (gt) RF &= ~NEGATIVE_FLAG;
else RF |= NEGATIVE_FLAG;
(this->*_post)();
}
// ── 0x05D — FGE: Float Greater or Equal ──────────────────────────────────
void CPU::FGE() {
fetchOperSrc();
fetchOperDst();
constexpr u64 NEGATIVE_FLAG = (1ULL << 9);
constexpr u64 ZERO_FLAG = (1ULL << 10);
bool ge = false;
bool eq = false;
switch (_size) {
case 0b10:
ge = (_dst->_f32 >= _src->_f32);
eq = (_dst->_f32 == _src->_f32);
break;
case 0b11:
ge = (_dst->_f64 >= _src->_f64);
eq = (_dst->_f64 == _src->_f64);
break;
default: break;
}
if (ge) RF &= ~NEGATIVE_FLAG;
else RF |= NEGATIVE_FLAG;
if (eq) RF |= ZERO_FLAG;
else RF &= ~ZERO_FLAG;
(this->*_post)();
}
// ── 0x05E — FLT: Float Lower Than ────────────────────────────────────────
void CPU::FLT() {
fetchOperSrc();
fetchOperDst();
constexpr u64 NEGATIVE_FLAG = (1ULL << 9);
bool lt = false;
switch (_size) {
case 0b10: lt = (_dst->_f32 < _src->_f32); break;
case 0b11: lt = (_dst->_f64 < _src->_f64); break;
default: break;
}
if (lt) RF |= NEGATIVE_FLAG;
else RF &= ~NEGATIVE_FLAG;
(this->*_post)();
}
// ── 0x05F — FLE: Float Lower or Equal ────────────────────────────────────
void CPU::FLE() {
fetchOperSrc();
fetchOperDst();
constexpr u64 NEGATIVE_FLAG = (1ULL << 9);
constexpr u64 ZERO_FLAG = (1ULL << 10);
bool le = false;
bool eq = false;
switch (_size) {
case 0b10:
le = (_dst->_f32 <= _src->_f32);
eq = (_dst->_f32 == _src->_f32);
break;
case 0b11:
le = (_dst->_f64 <= _src->_f64);
eq = (_dst->_f64 == _src->_f64);
break;
default: break;
}
if (le) RF &= ~NEGATIVE_FLAG;
else RF |= NEGATIVE_FLAG;
if (eq) RF |= ZERO_FLAG;
else RF &= ~ZERO_FLAG;
(this->*_post)();
}
}

View File

@@ -0,0 +1,181 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
#include <cmath> // provides std::fmod, std::fma and cast support
namespace spider {
// ── 0x060 — F2D: Float (f32) to Double (f64) ─────────────────────────────
// Widening conversion — no precision is lost
void CPU::F2D() {
fetchOperDst();
_dst->_f64 = static_cast<f64>(_dst->_f32);
(this->*_post)();
}
// ── 0x061 — D2F: Double (f64) to Float (f32) ─────────────────────────────
// Narrowing conversion — precision may be lost
void CPU::D2F() {
fetchOperDst();
_dst->_f32 = static_cast<f32>(_dst->_f64);
(this->*_post)();
}
// ── 0x062 — I2F: Integer (i32) to Float (f32) ────────────────────────────
void CPU::I2F() {
fetchOperDst();
_dst->_f32 = static_cast<f32>(_dst->_u32);
(this->*_post)();
}
// ── 0x063 — I2D: Integer (i32) to Double (f64) ───────────────────────────
void CPU::I2D() {
fetchOperDst();
_dst->_f64 = static_cast<f64>(_dst->_u32);
(this->*_post)();
}
// ── 0x064 — L2F: Long (i64) to Float (f32) ───────────────────────────────
void CPU::L2F() {
fetchOperDst();
_dst->_f32 = static_cast<f32>(_dst->_u64);
(this->*_post)();
}
// ── 0x065 — L2D: Long (i64) to Double (f64) ──────────────────────────────
void CPU::L2D() {
fetchOperDst();
_dst->_f64 = static_cast<f64>(_dst->_u64);
(this->*_post)();
}
// ── 0x066 — F2I: Float (f32) to Integer (i32) ────────────────────────────
// Truncates toward zero
void CPU::F2I() {
fetchOperDst();
_dst->_u32 = static_cast<u32>(_dst->_f32);
(this->*_post)();
}
// ── 0x067 — F2L: Float (f32) to Long (i64) ───────────────────────────────
// Truncates toward zero
void CPU::F2L() {
fetchOperDst();
_dst->_u64 = static_cast<u64>(_dst->_f32);
(this->*_post)();
}
void CPU::D2I() {
fetchOperDst();
_dst->_u32 = static_cast<u32>(_dst->_f64);
(this->*_post)();
}
void CPU::D2L() {
fetchOperDst();
_dst->_u64 = static_cast<u64>(_dst->_f64);
(this->*_post)();
}
void CPU::SIN() {
fetchOperDst();
_dst->_f64 = std::sin(_dst->_f64);
(this->*_post)();
}
void CPU::COS() {
fetchOperDst();
_dst->_f64 = std::cos(_dst->_f64);
(this->*_post)();
}
void CPU::TAN() {
fetchOperDst();
_dst->_f64 = std::tan(_dst->_f64);
(this->*_post)();
}
void CPU::ASIN() {
fetchOperDst();
_dst->_f64 = std::asin(_dst->_f64);
(this->*_post)();
}
void CPU::ACOS() {
fetchOperDst();
_dst->_f64 = std::acos(_dst->_f64);
(this->*_post)();
}
void CPU::ATAN() {
fetchOperDst();
_dst->_f64 = std::atan(_dst->_f64);
(this->*_post)();
}
void CPU::ATAN2() {
fetchOperDst();
fetchOperSrc();
_dst->_f64 = std::atan2(_dst->_f64, _src->_f64);
(this->*_post)();
}
void CPU::EXP() {
fetchOperDst();
_dst->_f64 = std::exp(_dst->_f64);
(this->*_post)();
}
void CPU::LOG() {
fetchOperDst();
_dst->_f64 = std::log(_dst->_f64);
(this->*_post)();
}
void CPU::LOGAB() {
fetchOperDst();
fetchOperSrc();
_dst->_f64 = std::log(_dst->_f64) / std::log(_src->_f64);
(this->*_post)();
}
void CPU::POW() {
fetchOperDst();
fetchOperSrc();
_dst->_f64 = std::pow(_dst->_f64, _src->_f64);
(this->*_post)();
}
void CPU::SQRT() {
fetchOperDst();
_dst->_f64 = std::sqrt(_dst->_f64);
(this->*_post)();
}
void CPU::ROOT() {
fetchOperDst();
fetchOperSrc();
_dst->_f64 = std::pow(_dst->_f64, 1.0 / _src->_f64);
}
void CPU::ADC() {
// TODO: Implement ADC
}
void CPU::SWC() {
// TODO: Implement SWC
}
void CPU::MWO() {
// TODO: Implement MWO
}
void CPU::UMO() {
// TODO: Implement UMO
}
}

View File

@@ -0,0 +1,62 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
void CPU::MADD() {
// TODO: Implement MADD
}
void CPU::MSUB() {
// TODO: Implement MSUB
}
void CPU::MMUL() {
// TODO: Implement MMUL
}
void CPU::MINV() {
// TODO: Implement MINV
}
void CPU::MTRA() {
// TODO: Implement MTRA
}
void CPU::MDET() {
// TODO: Implement MDET
}
void CPU::QMKA() {
// TODO: Implement QMKA
}
void CPU::QMUL() {
// TODO: Implement QMUL
}
void CPU::XADD() {
// TODO: Implement XADD
}
void CPU::XSUB() {
// TODO: Implement XSUB
}
void CPU::XAMA() {
// TODO: Implement XAMA
}
void CPU::XMUL() {
// TODO: Implement XMUL
}
void CPU::XDIV() {
// TODO: Implement XDIV
}
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,55 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
#include <spider/runtime/memory/RAM.hpp>
namespace spider {
void CPU::UPY() {
// TODO: Implement UPY
}
// ── 0x0F6 — DGANT: "I'm SpiderLang" in a spider web ────────────
void CPU::DGANT() {
const char art[] =
R"(\ | //)"
R"( \-+-// )"
R"( -- + --)"
R"( //-+-\ )"
R"(// | \)"
R"( )"
R"( I ' M )"
R"( SPIDER )"
R"( LANG )"
R"( )"
R"(\ | //)"
R"( \-+-// )"
R"(-- + -- )"
R"( /-+-\ )"
R"(/ | \ )"
R"( || )"
R"( || )"
R"( || )"
R"(\ | / )"
R"( \-+-/ )"
R"(-- + -- )"
R"( /-+-\ )"
R"(/ | \ )"
R"( || )"
R"( || )"
R"( || )"
R"(\ | / )"
R"( \-+-/ )"
R"(-- + -- )"
R"( /-+-\ )"
R"(/ | \ )"
R"( || )";
for (u16 i = 0; i < sizeof(art) - 1; i++) {
_ram->at(i) = static_cast<u8>(art[i]);
}
}
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,10 @@
/**
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
*
*/
#include <spider/runtime/cpu/CPU.hpp>
namespace spider {
}

View File

@@ -0,0 +1,105 @@
#include "Matrix.hpp"
#include <immintrin.h>
#include <type_traits>
#include <algorithm>
#include <cstring>
/*
namespace spider {
template<typename T>
void matrix_fill(T diag, Matrix<T> mat) {
for (isize i = 0; i < mat.rows; i++) {
for (isize j = 0; j < mat.cols; j++) {
m.data[i + j * mat.rows] = i == j ? diag : T(0);
}
}
}
template<typename T>
void matrix_mult(Matrix<T> m1, Matrix<T> m2, Matrix<T> mr) {
// natural constrains of matrix multiplication
if (m1.rows != mr.rows) return;
if (m2.cols != mr.cols) return;
if (m1.cols != m2.rows) return;
// fill result with zeroes
std::fill(mr.data, mr.data + mr.rows * mr.cols, T(0));
// Begin Loop
for (isize j = 0; j < mr.cols; j++) { // P
for (isize n = 0; n < m1.cols; n++) { // N
const T val_m2 = m2.data[n + j * m2.rows] * diag;
isize i = 0;
#if defined(__AVX__)
if constexpr (std::is_same_v<T, float>) {
const __m256 v_m2 = _mm256_set1_ps(val_m2);
for (; i <= mr.rows - 8; i += 8) {
__m256 v_m1 = _mm256_loadu_ps(&m1.data[i + n * m1.rows]);
__m256 v_mr = _mm256_loadu_ps(&mr.data[i + j * mr.rows]);
v_mr = _mm256_fmadd_ps(v_m1, v_m2, v_mr);
_mm256_storeu_ps(&mr.data[i + j * mr.rows], v_mr);
}
if (i < mr.rows) {
float buf_m1[8] = { 0 }, buf_mr[8] = { 0 };
isize rem = mr.rows - i;
std::memcpy(buf_m1, &m1.data[i + n * m1.rows], rem * sizeof(T));
std::memcpy(buf_mr, &mr.data[i + j * mr.rows], rem * sizeof(T));
_mm256_storeu_ps(buf_mr, _mm256_fmadd_ps(_mm256_loadu_ps(buf_m1), v_m2, _mm256_loadu_ps(buf_mr)));
std::memcpy(&mr.data[i + j * mr.rows], buf_mr, rem * sizeof(T));
}
}
else if constexpr (std::is_same_v<T, double>) {
const __m256d v_m2 = _mm256_set1_pd(val_m2);
for (; i <= mr.rows - 4; i += 4) {
__m256d v_m1 = _mm256_loadu_pd(&m1.data[i + n * m1.rows]);
__m256d v_mr = _mm256_loadu_pd(&mr.data[i + j * mr.rows]);
v_mr = _mm256_fmadd_pd(v_m1, v_m2, v_mr);
_mm256_storeu_pd(&mr.data[i + j * mr.rows], v_mr);
}
if (i < mr.rows) {
double buf_m1[4] = { 0 }, buf_mr[4] = { 0 };
isize rem = mr.rows - i;
std::memcpy(buf_m1, &m1.data[i + n * m1.rows], rem * sizeof(T));
std::memcpy(buf_mr, &mr.data[i + j * mr.rows], rem * sizeof(T));
_mm256_storeu_pd(buf_mr, _mm256_fmadd_pd(_mm256_loadu_pd(buf_m1), v_m2, _mm256_loadu_pd(buf_mr)));
std::memcpy(&mr.data[i + j * mr.rows], buf_mr, rem * sizeof(T));
}
}
else
#elif defined(__SSE2__)
if constexpr (std::is_same_v<T, float>) {
const __m128 v_m2 = _mm_set1_ps(val_m2);
for (; i <= mr.rows - 4; i += 4) {
__m128 v_m1 = _mm_loadu_ps(&m1.data[i + n * m1.rows]);
__m128 v_mr = _mm_loadu_ps(&mr.data[i + j * mr.rows]);
v_mr = _mm_add_ps(v_mr, _mm_mul_ps(v_m1, v_m2));
_mm_storeu_ps(&mr.data[i + j * mr.rows], v_mr);
}
// Tail buffer logic omitted for brevity, same as float AVX but with size 4
}
else if constexpr (std::is_same_v<T, double>) {
const __m128d v_m2 = _mm_set1_pd(val_m2);
for (; i <= mr.rows - 2; i += 2) {
__m128d v_m1 = _mm_loadu_pd(&m1.data[i + n * m1.rows]);
__m128d v_mr = _mm_loadu_pd(&mr.data[i + j * mr.rows]);
v_mr = _mm_add_pd(v_mr, _mm_mul_pd(v_m1, v_m2));
_mm_storeu_pd(&mr.data[i + j * mr.rows], v_mr);
}
}
else
#endif
{
// Fallback for non-SIMD or unsupported types
for (; i < mr.rows; i++) {
mr.data[i + j * mr.rows] += m1.data[i + n * m1.rows] * val_m2;
}
}
}
}
}
}
*/

View File

@@ -0,0 +1,31 @@
#pragma once
#include <spider/runtime/common.hpp>
/*
namespace spider {
template<typename T>
struct Matrix {
T* data;
isize rows, cols;
};
void matrix_fill(f32 diag, Matrix<f32> mat);
void matrix_fill(f64 diag, Matrix<f64> mat);
Matrix<f32> matrix_mul(Matrix<f32> m1, Matrix<f32> m2);
Matrix<f64> matrix_mul(Matrix<f64> m1, Matrix<f64> m2);
Matrix<f32> matrix_inv(Matrix<f32> mat);
Matrix<f64> matrix_inv(Matrix<f64> mat);
f32 matrix_det(Matrix<f32> mat);
f64 matrix_det(Matrix<f64> mat);
}
*/

View File

@@ -0,0 +1,109 @@
#include <iostream>
/*
template<typename T, int Rows, int Cols>
struct Matrix {
T data[Rows][Cols];
void setZero() {
for (int i = 0; i < Rows; i++) {
for (int j = 0; j < Cols; j++) {
data[i][j] = T();
}
}
}
};
template<typename T, int M, int N, int P>
Matrix<T, M, P> mat_multiply(Matrix<T, M, N> A, Matrix<T, N, P> B) {
//Determination of resulting matrix size
// COMPILE-TIME calculation (using constexpr)
constexpr int RSize = (M > P) ? M : P;
// COMPILE-TIME square size calculation
constexpr int CSize = (RSize <= 4) ? 4 :
(RSize % 4 == 0) ? RSize :
4 * (RSize / 4 + 1);
// SIMD width selection
int simd_width;
if (RSize > 8) {
simd_width = 8;
}
else if (RSize > 4 && RSize < 8){
simd_width = 4;
}
else {
simd_width = RSize;
}
// Create result square matrix with size CSize(optimization)
Matrix<T, CSize, CSize> tempResult;
tempResult.setZero();
// Matrix multiplication with SIMD-style unrolling
for (int i = 0; i < M; i++) { // For each row in A
for (int k = 0; k < N; k++) { // For each inner dimension
T a_val = A.data[i][k];
// Process columns in chunks of simd_width
int j = 0;
while (j < P) {
int remaining = P - j;
if (remaining >= simd_width) {
// Full SIMD operation - unrolled loops
if (simd_width == 8) {
tempResult.data[i][j] += a_val * B.data[k][j];
tempResult.data[i][j+1] += a_val * B.data[k][j+1];
tempResult.data[i][j+2] += a_val * B.data[k][j+2];
tempResult.data[i][j+3] += a_val * B.data[k][j+3];
tempResult.data[i][j+4] += a_val * B.data[k][j+4];
tempResult.data[i][j+5] += a_val * B.data[k][j+5];
tempResult.data[i][j+6] += a_val * B.data[k][j+6];
tempResult.data[i][j+7] += a_val * B.data[k][j+7];
}
else if (simd_width == 4) {
tempResult.data[i][j] += a_val * B.data[k][j];
tempResult.data[i][j+1] += a_val * B.data[k][j+1];
tempResult.data[i][j+2] += a_val * B.data[k][j+2];
tempResult.data[i][j+3] += a_val * B.data[k][j+3];
}
else if (simd_width == 3) {
tempResult.data[i][j] += a_val * B.data[k][j];
tempResult.data[i][j+1] += a_val * B.data[k][j+1];
tempResult.data[i][j+2] += a_val * B.data[k][j+2];
}
else if (simd_width == 2) {
tempResult.data[i][j] += a_val * B.data[k][j];
tempResult.data[i][j+1] += a_val * B.data[k][j+1];
}
else { // simd_width == 1
tempResult.data[i][j] += a_val * B.data[k][j];
}
j += simd_width;
}
else {
// Handle remaining columns that don't fit in SIMD width
for (int s = 0; s < remaining; s++) {
tempResult.data[i][j + s] += a_val * B.data[k][j + s];
}
j += remaining;
}
}
}
}
// Extract the actual result (M x P) from the temporary square matrix
Matrix<T, M, P> result;
for (int i = 0; i < M; i++) {
for (int j = 0; j < P; j++) {
result.data[i][j] = tempResult.data[i][j];
}
}
return result;
}
*/

View File

@@ -3,20 +3,57 @@
#include <iostream>
namespace spider {
/**
* Multiplies two quaternions together.
* General case, use it when no optimizations exist.
*/
template<typename T>
inline Quat<T> quat_mul_gnrl(Quat<T> A, Quat<T> B) {
return {
B.w * A.w - B.x * A.x - B.y * A.y - B.z * A.z,
B.w * A.x + B.x * A.w - B.y * A.z + B.z * A.y,
B.w * A.y + B.x * A.z + B.y * A.w - B.z * A.x,
B.w * A.z - B.x * A.y + B.y * A.x + B.z * A.w
};
}
/**
* Multiplies two quaternions together.
* Attempts to use SIMD instructions when available.
*/
template<typename T>
inline Quat<T> quat_mul_smart(Quat<T> A, Quat<T> B) {
}
Quat<f32> quat_mul(Quat<f32> q1, Quat<f32> q2) {
return quat_mul_gnrl<f32>(q1, q2);
}
//void quat_mat(Quat<f32> quat, f32* mat) {
// // TODO
//}
Quat<f64> quat_mul(Quat<f64> q1, Quat<f64> q2) {
return quat_mul_gnrl<f64>(q1, q2);
}
//void quat_mat(Quat<f64> q1, f64* mat) {
// // TODO
//}
/*
int quatMain() {
Quat<double> q1 = { 1.0f, 0.0f, 0.0f, 0.0f };
Quat<double> q2 = { 0.5f, 0.5f, 0.5f, 0.5f };
Quat<double> result = quat_multiply(q1, q2); // Returns the result!
std::cout << "Result: ("
<< result.w << ", "
<< result.x << ", "
<< result.y << ", "
<< result.z << ")" << std::endl;
return 0;
}
*/
}

View File

@@ -10,15 +10,47 @@ namespace spider {
};
/**
* Multiplies two quaternions together.
* Creates a quaternion from Euler Angles.
*/
template<typename T> inline Quat<T> quat_multiply(Quat<T> A, Quat<T> B) {
return {
B.w * A.w - B.x * A.x - B.y * A.y - B.z * A.z,
B.w * A.x + B.x * A.w - B.y * A.z + B.z * A.y,
B.w * A.y + B.x * A.z + B.y * A.w - B.z * A.x,
B.w * A.z - B.x * A.y + B.y * A.x + B.z * A.w
};
}
Quat<f32> quat_make_euler(f32 x, f32 y, f32 z);
/**
* Creates a quaternion from an axis and an angle.
*/
Quat<f32> quat_make_axis_angle(f32 angle, f32 x, f32 y, f32 z);
/**
* Creates a quaternion from Euler Angles.
*/
Quat<f64> quat_make_euler(f64 x, f64 y, f64 z);
/**
* Creates a quaternion from an axis and an angle.
*/
Quat<f64> quat_make_axis_angle(f64 angle, f64 x, f64 y, f64 z);
/**
* Multiples a quaternion with another quaternion.
* The result is output to the qr variable.
* This pointer can be the same as q1.
*/
Quat<f32> quat_mul(Quat<f32> q1, Quat<f32> q2);
/**
* Converts a quaternion to a matrix.
*/
void quat_mat(Quat<f32> quat, f32* mat);
/**
* Multiples a quaternion with another quaternion.
* The result is output to the qr variable.
* This pointer can be the same as q1.
*/
Quat<f64> quat_mul(Quat<f64> q1, Quat<f64> q2);
/**
* Converts a quaternion to a matrix.
*/
void quat_mat(Quat<f64> q1, f64* mat);
}

View File

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

View File

@@ -2,6 +2,8 @@
#include <spider/runtime/common.hpp>
#include <spider/runtime/cpu/Register.hpp>
namespace spider {
/**
@@ -43,6 +45,8 @@ namespace spider {
u8 at(u64 i) const;
void loadRegister(u64 i, u8 size_code, register_t* r);
public:
void resize(u64 new_size);

View File

@@ -118,8 +118,8 @@ namespace spider {
std::memcpy(bytes, &n, sizeof(T));
#endif
#if SPIDER_LITTLE_ENDIAN
T tmp = byteswap(n);
std::memcpy(bytes, &tmp, sizeof(T));
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) {
@@ -151,9 +151,8 @@ namespace spider {
std::memcpy(n, bytes, sizeof(T));
#endif
#if SPIDER_LITTLE_ENDIAN
T tmp;
std::memcpy(&tmp, bytes, sizeof(T));
*n = byteswap(tmp);
std::memcpy(&n, bytes, sizeof(T));
*n = byteswap(*n);
#endif
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
using U = std::make_unsigned_t<T>;
@@ -185,8 +184,8 @@ namespace spider {
inline void storeLE(T n, u8* bytes) {
static_assert(std::is_trivially_copyable<T>::value);
#if SPIDER_BIG_ENDIAN
T tmp = byteswap(n);
std::memcpy(bytes, &tmp, sizeof(T));
n = byteswap(n);
std::memcpy(bytes, &n, sizeof(T));
#endif
#if SPIDER_LITTLE_ENDIAN
std::memcpy(bytes, &n, sizeof(T));
@@ -218,9 +217,8 @@ namespace spider {
inline void loadLE(T* n, const u8* bytes) {
static_assert(std::is_trivially_copyable<T>::value);
#if SPIDER_BIG_ENDIAN
T tmp;
std::memcpy(&tmp, bytes, sizeof(T));
*n = byteswap(tmp);
std::memcpy(&n, bytes, sizeof(T));
*n = byteswap(n);
#endif
#if SPIDER_LITTLE_ENDIAN
std::memcpy(n, bytes, sizeof(T));
@@ -249,5 +247,80 @@ namespace spider {
*n = bit_cast<f64>(tmp);
}
// ADVANCED Load Little Endian //
/**
* Loads LE bytes into a type.
* Also considers that the array may end, actually.
*/
template<typename T>
inline void loadPartialLE(T* n, const u8* bytes, isize length) {
*n = 0;
length = std::min(sizeof(T), length);
#if SPIDER_BIG_ENDIAN
std::memcpy(n, bytes, length);
*n = byteswap(n);
#endif
#if SPIDER_LITTLE_ENDIAN
std::memcpy(n, bytes, length);
#endif
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
using U = std::make_unsigned_t<T>;
U result = 0;
for (size_t i = 0; i < length; ++i) {
result |= static_cast<U>(bytes[i]) << (i * 8);
}
*n = static_cast<T>(result);
#endif
}
template<>
inline void loadPartialLE<f32>(f32* n, const u8* bytes, isize length) {
u32 tmp;
loadPartialLE(&tmp, bytes, length);
*n = bit_cast<f32>(tmp);
}
template<>
inline void loadPartialLE<f64>(f64* n, const u8* bytes, isize length) {
u64 tmp;
loadPartialLE(&tmp, bytes, length);
*n = bit_cast<f64>(tmp);
}
inline void loadRegisterU8(register_t* r, const u8* bytes, isize length) {
loadPartialLE(&r->_u8, bytes, length);
}
inline void loadRegisterU16(register_t* r, const u8* bytes, isize length) {
loadPartialLE(&r->_u16, bytes, length);
}
inline void loadRegisterU32(register_t* r, const u8* bytes, isize length) {
loadPartialLE(&r->_u32, bytes, length);
}
inline void loadRegisterU64(register_t* r, const u8* bytes, isize length) {
loadPartialLE(&r->_u64, bytes, length);
}
using _regload = void (*)(register_t* r, const u8* bytes, isize length);
inline _regload loadRegister[] = {
&loadRegisterU8, &loadRegisterU16,
&loadRegisterU32, &loadRegisterU64
};
// MISCs
inline void loadPartialBytes(const u8* from, isize fromOffset, isize fromLength, u8* to, isize toLength) {
size_t safeOffset = std::min(fromOffset, fromLength);
from += safeOffset;
fromLength -= safeOffset;
size_t writable = std::min(fromLength, toLength);
std::copy(from, from + writable, to);
std::fill(to + writable, to + toLength, 0);
}
}

View File

@@ -1,8 +1,11 @@
#pragma once
#include <spider/SpiderRuntime.hpp>
#include <spider/runtime/memory/ByteArray.hpp>
#include <spider/runtime/cpu/Register.hpp>
namespace spider {
/**
@@ -55,6 +58,8 @@ namespace spider {
*/
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.
*/

View File

@@ -9,7 +9,7 @@ namespace spider {
growTo((length >> 8) + ((length & 255) != 0));
}
InstrReelDyn::InstrReelDyn(const u8* data, u64 length) {}
//InstrReelDyn::InstrReelDyn(const u8* data, u64 length) {}
InstrReelDyn::InstrReelDyn(const InstrReelDyn& copy)
: _blocks(copy._blocks), _size(copy._size) {
@@ -89,7 +89,7 @@ namespace spider {
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);
dat |= u16(b.data[s_index++ & 0xFF] << (i * 8));
}
return dat;
}
@@ -179,6 +179,12 @@ namespace spider {
}
}
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.
*/
@@ -190,17 +196,14 @@ namespace spider {
// 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) {}
//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) {}
//void InstrReelDyn::append(u16 bc) {}
}

View File

@@ -85,6 +85,8 @@ namespace spider {
*/
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.
*/

View File

@@ -47,49 +47,36 @@ namespace spider {
// Instruction abstraction //
u8 InstrReelFixed::readU8(u64 ip) {
// guard against access
if(ip + 1 > _size) return 0;
// send byte
return _mem[ip];
u8 dat;
spider::loadPartialLE(&dat, _mem + ip, _size);
return dat;
}
u16 InstrReelFixed::readU16(u64 ip) {
// guard against access
if(ip + 2 > _size) return 0;
// build a 16-bit big endian number
u16 dat;
spider::loadLE(&dat, _mem + ip);
spider::loadPartialLE(&dat, _mem + ip, _size);
return dat;
}
u32 InstrReelFixed::readU32(u64 ip) {
// guard against access
if(ip + 4 > _size) return 0;
// build a 32-bit big endian number
u32 dat;
spider::loadLE(&dat, _mem + ip);
spider::loadPartialLE(&dat, _mem + ip, _size);
return dat;
}
u64 InstrReelFixed::readU64(u64 ip) {
// guard against access
if(ip + 8 > _size) return 0;
// build a 64-bit big endian number
u64 dat;
spider::loadLE(&dat, _mem + ip);
spider::loadPartialLE(&dat, _mem + ip, _size);
return dat;
}
void InstrReelFixed::readRange(u64 ip, u8* out, u64 length) {
if(ip + length > _size) {
std::memset(out, 0, length);
return;
}
std::memcpy(out, _mem + ip, length);
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() {

View File

@@ -70,6 +70,8 @@ namespace spider {
*/
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.
*/

View File

@@ -11,8 +11,15 @@
#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 {
@@ -148,7 +155,7 @@ namespace spider {
// 4. Overlay the title if provided
if (!title.empty()) {
move(startRow, startCol + (width - title.size() - 2) / 2);
move(startRow, startCol + (width - i32(title.size()) - 2) / 2);
std::cout << " " << title << " ";
}
@@ -218,7 +225,8 @@ namespace spider {
struct termios oldt, newt;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
//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;
@@ -247,7 +255,8 @@ namespace spider {
}
} else if (ch == 10) result = Terminal::ENTER;
else if (ch == 127) result = Terminal::BACKSPACE;
else result = (u8)ch;
else result = static_cast<u8>(ch); //added this line
//else result = (u8)ch;
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return result;

View File

@@ -156,8 +156,8 @@ namespace spider {
if (s.length() >= isize(width)) {
std::cout << s;
} else {
i32 total_padding = width - s.length();
i32 left_padding = total_padding / 2;
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, ' ');