better algorithm to load bytes
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
std::memcpy(out, _mem + ip, 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() {
|
u64 InstrReelFixed::size() {
|
||||||
|
|||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user