Compare commits
2 Commits
a077c084a2
...
41dd2b87b4
| Author | SHA1 | Date | |
|---|---|---|---|
| 41dd2b87b4 | |||
| 3d80b690c4 |
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
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 loadRegister(u64 ip, u8 size_code, register_t* r) = 0;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user