diff --git a/src/spider/runtime/cpu/CPU.cpp b/src/spider/runtime/cpu/CPU.cpp index 3308b8f..4b984d8 100644 --- a/src/spider/runtime/cpu/CPU.cpp +++ b/src/spider/runtime/cpu/CPU.cpp @@ -111,21 +111,7 @@ namespace spider { * 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; - } - + _reel->loadRegister(RI, _size, _alu); _opers[0] = _alu; _post = &CPU::imp; RI += 1 << _size; @@ -134,51 +120,28 @@ namespace spider { /** * 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; + void CPU::abs() { + // Load the actual ptr into the ALU + u8 mm = u8(getFlag(CPU::FLAG_MEMORY_MODE)); + _reel->loadRegister(RI, mm, _alu); + RI += 1 << mm; - 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; + // read the memory from RAM + _store = _alu->_u64; + _ram->loadRegister(_store, _size, _alu); + _post = &CPU::psw; } /** * Register Addressing Mode */ - void CPU::reg() { - + void CPU::reg() { // NOT FINISHED + // Two consecutive registers can be declared + // Shift if the top part will become .reg too + u8 sh = (_addrm & 0b11000 == 0b11000) * 4; + + // store no-op + _post = &CPU::imp; } /** diff --git a/src/spider/runtime/memory/RAM.cpp b/src/spider/runtime/memory/RAM.cpp index 5c65303..374091f 100644 --- a/src/spider/runtime/memory/RAM.cpp +++ b/src/spider/runtime/memory/RAM.cpp @@ -1,5 +1,9 @@ #include "RAM.hpp" +#include + +#include + #include 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) { diff --git a/src/spider/runtime/memory/RAM.hpp b/src/spider/runtime/memory/RAM.hpp index c62cd46..c1fc641 100644 --- a/src/spider/runtime/memory/RAM.hpp +++ b/src/spider/runtime/memory/RAM.hpp @@ -43,6 +43,8 @@ namespace spider { u8 at(u64 i) const; + void loadRegister(u64 i, u8 size_code, register_t* r); + public: void resize(u64 new_size); diff --git a/src/spider/runtime/memory/Types.hpp b/src/spider/runtime/memory/Types.hpp index 635dc67..028ccff 100644 --- a/src/spider/runtime/memory/Types.hpp +++ b/src/spider/runtime/memory/Types.hpp @@ -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; @@ -185,8 +184,8 @@ namespace spider { inline void storeLE(T n, u8* bytes) { static_assert(std::is_trivially_copyable::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::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(tmp); } + // ADVANCED Load Little Endian // + + /** + * Loads LE bytes into a type. + * Also considers that the array may end, actually. + */ + template + 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; + U result = 0; + for (size_t i = 0; i < length; ++i) { + result |= static_cast(bytes[i]) << (i * 8); + } + *n = static_cast(result); +#endif + } + + template<> + inline void loadPartialLE(f32* n, const u8* bytes, isize length) { + u32 tmp; + loadLE(&tmp, bytes); + *n = bit_cast(tmp); + } + + template<> + inline void loadPartialLE(f64* n, const u8* bytes, isize length) { + u64 tmp; + loadLE(&tmp, bytes); + *n = bit_cast(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); + } + } diff --git a/src/spider/runtime/reel/InstrReel.hpp b/src/spider/runtime/reel/InstrReel.hpp index a60d9c3..470fa2b 100644 --- a/src/spider/runtime/reel/InstrReel.hpp +++ b/src/spider/runtime/reel/InstrReel.hpp @@ -55,6 +55,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. */ diff --git a/src/spider/runtime/reel/InstrReelDyn.cpp b/src/spider/runtime/reel/InstrReelDyn.cpp index 0aceeb2..701572f 100644 --- a/src/spider/runtime/reel/InstrReelDyn.cpp +++ b/src/spider/runtime/reel/InstrReelDyn.cpp @@ -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. */ diff --git a/src/spider/runtime/reel/InstrReelDyn.hpp b/src/spider/runtime/reel/InstrReelDyn.hpp index d5ed28c..ea932f1 100644 --- a/src/spider/runtime/reel/InstrReelDyn.hpp +++ b/src/spider/runtime/reel/InstrReelDyn.hpp @@ -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. */ diff --git a/src/spider/runtime/reel/InstrReelFixed.cpp b/src/spider/runtime/reel/InstrReelFixed.cpp index 15e62eb..48882b4 100644 --- a/src/spider/runtime/reel/InstrReelFixed.cpp +++ b/src/spider/runtime/reel/InstrReelFixed.cpp @@ -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() { diff --git a/src/spider/runtime/reel/InstrReelFixed.hpp b/src/spider/runtime/reel/InstrReelFixed.hpp index f9b09a8..39c272c 100644 --- a/src/spider/runtime/reel/InstrReelFixed.hpp +++ b/src/spider/runtime/reel/InstrReelFixed.hpp @@ -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. */