Files
spider-runtime/src/spider/runtime/reel/InstrReelFixed.cpp

171 lines
4.1 KiB
C++

#include "InstrReelFixed.hpp"
#include <spider/runtime/memory/Types.hpp>
#include <cstring>
namespace spider {
// Constructors & Destructors //
InstrReelFixed::InstrReelFixed(u64 length)
: _mem(nullptr), _size(length) {
if (_size > 0) {
_mem = new u8[_size];
std::memset(_mem, 0, _size);
}
}
InstrReelFixed::InstrReelFixed(const u8* data, u64 length)
: _mem(nullptr), _size(length) {
if (_size > 0) {
_mem = new u8[_size];
std::copy(data, data + _size, _mem);
}
}
InstrReelFixed::InstrReelFixed(const InstrReelFixed& other) {
_size = other._size;
_mem = new u8[_size];
std::copy(other._mem, other._mem + _size, _mem);
}
InstrReelFixed::InstrReelFixed(InstrReelFixed&& other) noexcept {
_mem = other._mem;
_size = other._size;
other._mem = nullptr;
other._size = 0;
}
InstrReelFixed::~InstrReelFixed() {
delete[] _mem;
}
// General Case(s) //
// Instruction abstraction //
u8 InstrReelFixed::readU8(u64 ip) {
u8 dat;
spider::loadPartialLE(&dat, _mem + ip, _size);
return dat;
}
u16 InstrReelFixed::readU16(u64 ip) {
u16 dat;
spider::loadPartialLE(&dat, _mem + ip, _size);
return dat;
}
u32 InstrReelFixed::readU32(u64 ip) {
u32 dat;
spider::loadPartialLE(&dat, _mem + ip, _size);
return dat;
}
u64 InstrReelFixed::readU64(u64 ip) {
u64 dat;
spider::loadPartialLE(&dat, _mem + ip, _size);
return dat;
}
void InstrReelFixed::readRange(u64 ip, u8* out, u64 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() {
return _size;
}
// Assign Operators //
InstrReelFixed& InstrReelFixed::operator=(const InstrReelFixed& other) {
if (this == &other) return *this; // lock self
u8* new_mem = new u8[other._size];
std::copy(other._mem, other._mem + other._size, new_mem);
delete[] _mem;
_mem = new_mem;
_size = other._size;
return *this;
}
InstrReelFixed& InstrReelFixed::operator=(InstrReelFixed&& other) noexcept {
if (this == &other) return *this; // lock self
delete[] _mem;
_mem = other._mem; // steal
_size = other._size;
other._mem = nullptr; // leave as husk
other._size = 0;
return *this;
}
// Misc //
void InstrReelFixed::writeU8(u64 ip, u8 dat) {
if(ip + 1 > _size) return;
_mem[ip] = dat;
}
void InstrReelFixed::writeU16(u64 ip, u16 dat) {
if(ip + 2 > _size) return;
spider::storeLE(dat, _mem + ip);
}
void InstrReelFixed::writeU32(u64 ip, u32 dat) {
if(ip + 4 > _size) return;
spider::storeLE(dat, _mem + ip);
}
void InstrReelFixed::writeU64(u64 ip, u64 dat) {
if(ip + 8 > _size) return;
spider::storeLE(dat, _mem + ip);
}
void InstrReelFixed::resize(u64 new_size) {
// Special case 1
if (new_size == _size) return;
// Special case 2
if (new_size == 0) {
delete[] _mem;
_mem = nullptr;
_size = 0;
return;
}
// 1. Allocate the new block
u8* new_mem = new u8[new_size];
// 2. Zero-initialize
std::memset(new_mem, 0, new_size);
// 3. Preserve data
// If shrinking, copy 'new_size' bytes. If growing, copy 'old_size' bytes.
u64 bytes_to_copy = (new_size < _size) ? new_size : _size;
// 3.1 Previous size could be zero, where _mem would be null
if (_mem != nullptr) {
std::copy(_mem, _mem + bytes_to_copy, new_mem);
}
// 4. Swap and Clean up
delete[] _mem;
_mem = new_mem;
_size = new_size;
}
}