2 Commits

9 changed files with 135 additions and 89 deletions

View File

@@ -111,21 +111,7 @@ namespace spider {
* Immediate Addressing Mode * Immediate Addressing Mode
*/ */
void CPU::imm() { void CPU::imm() {
switch(_size) { _reel->loadRegister(RI, _size, _alu);
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; _opers[0] = _alu;
_post = &CPU::imp; _post = &CPU::imp;
RI += 1 << _size; RI += 1 << _size;
@@ -134,51 +120,28 @@ namespace spider {
/** /**
* Absolute Addressing Mode * Absolute Addressing Mode
*/ */
void CPU::abs() { // TODO cache ptr size void CPU::abs() {
u8 dat_size = 1 << _size; // Load the actual ptr into the ALU
u8 ptr_size = 1 << getFlag(CPU::FLAG_MEMORY_MODE); u8 mm = u8(getFlag(CPU::FLAG_MEMORY_MODE));
u64 ptr = 0; _reel->loadRegister(RI, mm, _alu);
RI += 1 << mm;
if(ptr_size + dat_size > _ram->size()) return; // TODO: avoid overflow // read the memory from RAM
_store = _alu->_u64;
switch(ptr_size) { _ram->loadRegister(_store, _size, _alu);
case 1: _post = &CPU::psw;
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 * 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;
} }
/** /**

View File

@@ -1,5 +1,9 @@
#include "RAM.hpp" #include "RAM.hpp"
#include <spider/runtime/cpu/Register.hpp>
#include <spider/runtime/memory/Types.hpp>
#include <cstring> #include <cstring>
namespace spider { namespace spider {
@@ -72,6 +76,11 @@ namespace spider {
return (i < _size) ? _mem[i] : _oob; 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 // // Misc //
void RAM::resize(u64 new_size) { void RAM::resize(u64 new_size) {

View File

@@ -43,6 +43,8 @@ namespace spider {
u8 at(u64 i) const; u8 at(u64 i) const;
void loadRegister(u64 i, u8 size_code, register_t* r);
public: public:
void resize(u64 new_size); void resize(u64 new_size);

View File

@@ -118,8 +118,8 @@ namespace spider {
std::memcpy(bytes, &n, sizeof(T)); std::memcpy(bytes, &n, sizeof(T));
#endif #endif
#if SPIDER_LITTLE_ENDIAN #if SPIDER_LITTLE_ENDIAN
T tmp = byteswap(n); n = byteswap(n);
std::memcpy(bytes, &tmp, sizeof(T)); std::memcpy(bytes, &n, sizeof(T));
#endif #endif
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN #if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
for (size_t i = 0; i < sizeof(T); ++i) { for (size_t i = 0; i < sizeof(T); ++i) {
@@ -151,9 +151,8 @@ namespace spider {
std::memcpy(n, bytes, sizeof(T)); std::memcpy(n, bytes, sizeof(T));
#endif #endif
#if SPIDER_LITTLE_ENDIAN #if SPIDER_LITTLE_ENDIAN
T tmp; std::memcpy(&n, bytes, sizeof(T));
std::memcpy(&tmp, bytes, sizeof(T)); *n = byteswap(n);
*n = byteswap(tmp);
#endif #endif
#if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN #if !SPIDER_BIG_ENDIAN && !SPIDER_LITTLE_ENDIAN
using U = std::make_unsigned_t<T>; using U = std::make_unsigned_t<T>;
@@ -185,8 +184,8 @@ namespace spider {
inline void storeLE(T n, u8* bytes) { inline void storeLE(T n, u8* bytes) {
static_assert(std::is_trivially_copyable<T>::value); static_assert(std::is_trivially_copyable<T>::value);
#if SPIDER_BIG_ENDIAN #if SPIDER_BIG_ENDIAN
T tmp = byteswap(n); n = byteswap(n);
std::memcpy(bytes, &tmp, sizeof(T)); std::memcpy(bytes, &n, sizeof(T));
#endif #endif
#if SPIDER_LITTLE_ENDIAN #if SPIDER_LITTLE_ENDIAN
std::memcpy(bytes, &n, sizeof(T)); std::memcpy(bytes, &n, sizeof(T));
@@ -218,9 +217,8 @@ namespace spider {
inline void loadLE(T* n, const u8* bytes) { inline void loadLE(T* n, const u8* bytes) {
static_assert(std::is_trivially_copyable<T>::value); static_assert(std::is_trivially_copyable<T>::value);
#if SPIDER_BIG_ENDIAN #if SPIDER_BIG_ENDIAN
T tmp; std::memcpy(&n, bytes, sizeof(T));
std::memcpy(&tmp, bytes, sizeof(T)); *n = byteswap(n);
*n = byteswap(tmp);
#endif #endif
#if SPIDER_LITTLE_ENDIAN #if SPIDER_LITTLE_ENDIAN
std::memcpy(n, bytes, sizeof(T)); std::memcpy(n, bytes, sizeof(T));
@@ -249,5 +247,80 @@ namespace spider {
*n = bit_cast<f64>(tmp); *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;
loadLE(&tmp, bytes);
*n = bit_cast<f32>(tmp);
}
template<>
inline void loadPartialLE<f64>(f64* n, const u8* bytes, isize length) {
u64 tmp;
loadLE(&tmp, bytes);
*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

@@ -55,6 +55,8 @@ namespace spider {
*/ */
virtual void readRange(u64 ip, u8* out, u64 length) = 0; 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. * Current size of the instructions.
*/ */

View File

@@ -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. * Current size of the instructions.
*/ */

View File

@@ -85,6 +85,8 @@ namespace spider {
*/ */
virtual void readRange(u64 ip, u8* out, u64 length) override; 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. * Current size of the instructions.
*/ */

View File

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

View File

@@ -70,6 +70,8 @@ namespace spider {
*/ */
virtual void readRange(u64 ip, u8* out, u64 length) override; 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. * Current size of the instructions.
*/ */