Compare commits
30 Commits
a077c084a2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| dd1cd03026 | |||
| 75f4b160bf | |||
|
|
0184ef6394 | ||
| 30e0203df4 | |||
| 7713be5293 | |||
| b61cc6b149 | |||
| 7155ad8d5a | |||
| 0449074ef6 | |||
|
|
d2ce5ea4bd | ||
|
|
6fb7a23e5d | ||
| 484c2a6afe | |||
| 6f8a9d80f2 | |||
|
|
429596af86 | ||
| 36889e160b | |||
| 4e1a601175 | |||
|
|
f82aa627c4 | ||
|
|
7d3781681d | ||
| 6ac82b47e7 | |||
| 48785b6a94 | |||
| c8bfdf44b6 | |||
| eba69f767e | |||
| 67ed4a7fc4 | |||
| 0015387d60 | |||
| 15bf03097f | |||
| 43f5d26b3d | |||
| f0148dbe45 | |||
| b397371a53 | |||
| aabcfc6f0c | |||
| 41dd2b87b4 | |||
| 3d80b690c4 |
Binary file not shown.
2
makefile
2
makefile
@@ -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 \
|
||||
|
||||
58
pygen.ipynb
58
pygen.ipynb
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace spider {
|
||||
/**
|
||||
* Non-owning reel setup.
|
||||
*/
|
||||
void hookReel(InstrReel* reel, bool own = false);
|
||||
void hookReel(InstrReel* newReel, bool own = false);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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> //
|
||||
|
||||
};
|
||||
|
||||
@@ -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.");
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)();
|
||||
}
|
||||
|
||||
}
|
||||
240
src/spider/runtime/instr/Instr_020-03F.cpp
Normal file
240
src/spider/runtime/instr/Instr_020-03F.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
401
src/spider/runtime/instr/Instr_040-05F.cpp
Normal file
401
src/spider/runtime/instr/Instr_040-05F.cpp
Normal 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)();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
181
src/spider/runtime/instr/Instr_060-07F.cpp
Normal file
181
src/spider/runtime/instr/Instr_060-07F.cpp
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
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 {
|
||||
|
||||
}
|
||||
55
src/spider/runtime/instr/Instr_0E0-0FF.cpp
Normal file
55
src/spider/runtime/instr/Instr_0E0-0FF.cpp
Normal 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]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
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 {
|
||||
|
||||
}
|
||||
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);
|
||||
|
||||
}
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <iostream>
|
||||
|
||||
|
||||
/*
|
||||
template<typename T, int Rows, int Cols>
|
||||
struct Matrix {
|
||||
T data[Rows][Cols];
|
||||
@@ -106,3 +106,4 @@ Matrix<T, M, P> mat_multiply(Matrix<T, M, N> A, Matrix<T, N, P> B) {
|
||||
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
@@ -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;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, ' ');
|
||||
|
||||
Reference in New Issue
Block a user