#include "InstrReelDyn.hpp" #include namespace spider { InstrReelDyn::InstrReelDyn(u64 length) : _size(length) { // Safe int ceil division growTo((length >> 8) + ((length & 255) != 0)); } InstrReelDyn::InstrReelDyn(const u8* data, u64 length) {} InstrReelDyn::InstrReelDyn(const InstrReelDyn& copy) : _blocks(copy._blocks), _size(copy._size) { } InstrReelDyn::InstrReelDyn(InstrReelDyn&& move) noexcept : _blocks(std::move(move._blocks)), _size(std::move(move._size)) { } InstrReelDyn::~InstrReelDyn() { // .. // } InstrReelDyn& InstrReelDyn::operator=(const InstrReelDyn& copy) { _blocks = copy._blocks; _size = copy._size; return *this; } InstrReelDyn& InstrReelDyn::operator=(InstrReelDyn&& move) noexcept { _blocks = std::move(move._blocks); _size = std::move(move._size); return *this; } void InstrReelDyn::growTo(u64 ip) { u64 b_index = (ip >> 8) + 1; while (_blocks.size() < b_index) { _blocks.emplace_back(); } if (ip >= _size) _size = ip + 1; } std::pair InstrReelDyn::indexOf(u64 ip) { return { ip >> 8, ip & 0xFF }; // { ip / 256, ip % 256 }; } bool InstrReelDyn::continous(u64 ip0, u64 ip1, u64* b_index, u16* s_index) { auto i = indexOf(ip0); *b_index = i.first; *s_index = i.second; return i.first == (ip1 >> 8); } // Particular Cases /** * Obtains a byte of data at * the specific location. * Reindexing may occur, continous access * may incurr in less penalties. */ u8 InstrReelDyn::readU8(u64 ip) { if (ip + 1 > _size) return 0; auto i = indexOf(ip); return _blocks[i.first].data[i.second]; } /** * Obtains a byte of data at * the specific location. * Reindexing may occur, continous access * may incurr in less penalties. */ u16 InstrReelDyn::readU16(u64 ip) { if (ip + 2 > _size) return 0; u16 dat; u64 b_index; u16 s_index; if (continous(ip, ip + 1, &b_index, &s_index)) { spider::loadLE(&dat, &_blocks[b_index].data[s_index]); return dat; } dat = 0; for (isize i = 0; i < sizeof(dat); i++) { auto& b = _blocks[(b_index + s_index) >> 8]; dat |= u16(b.data[s_index++ & 0xFF]) << (i * 8); } return dat; } /** * Obtains a byte of data at * the specific location. * Reindexing may occur, continous access * may incurr in less penalties. */ u32 InstrReelDyn::readU32(u64 ip) { if (ip + 4 > _size) return 0; u32 dat; u64 b_index; u16 s_index; if (continous(ip, ip + 3, &b_index, &s_index)) { spider::loadLE(&dat, &_blocks[b_index].data[s_index]); return dat; } dat = 0; for (isize i = 0; i < sizeof(dat); i++) { auto& b = _blocks[(b_index + s_index) >> 8]; dat |= u32(b.data[s_index++ & 0xFF]) << (i * 8); } return dat; } /** * Obtains a byte of data at * the specific location. * Reindexing may occur, continous access * may incurr in less penalties. */ u64 InstrReelDyn::readU64(u64 ip) { if (ip + 8 > _size) return 0; u64 dat; u64 b_index; u16 s_index; if (continous(ip, ip + 7, &b_index, &s_index)) { spider::loadLE(&dat, &_blocks[b_index].data[s_index]); return dat; } dat = 0; for (isize i = 0; i < sizeof(dat); i++) { auto& b = _blocks[(b_index + s_index) >> 8]; dat |= u64(b.data[s_index++ & 0xFF]) << (i * 8); } return dat; } /** * Reads a range of data, and * outputs it. */ void InstrReelDyn::readRange(u64 ip, u8* out, u64 length) { if (ip + length > _size) { std::memset(out, 0, length); return; } u64 b_index; u16 s_index; if (continous(ip, ip + length, &b_index, &s_index)) { std::memcpy(out, &_blocks[b_index].data[s_index], length); return; } u64 bytes_read = 0; while (bytes_read < length) { u64 remaining_in_block = 256 - s_index; u64 chunk_size = std::min(remaining_in_block, length - bytes_read); // Perform bulk copy for the current segment std::memcpy(out + bytes_read, &_blocks[b_index].data[s_index], chunk_size); // Advance pointers bytes_read += chunk_size; b_index++; s_index = 0; // reset } } 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. */ u64 InstrReelDyn::size() { return _size; } // Mutation // // TODO! void InstrReelDyn::writeU8(u64 ip, u8 dat) {} void InstrReelDyn::writeU16(u64 ip, u16 dat) {} void InstrReelDyn::writeU32(u64 ip, u32 dat) {} void InstrReelDyn::writeU64(u64 ip, u64 dat) {} /** * Appends instruction at the end. */ void InstrReelDyn::append(u16 bc) {} }