// See LICENSE for license details. #include #include #include #include #include "memif.h" void memif_t::read(addr_t addr, size_t len, void* bytes) { size_t align = cmemif->chunk_align(); if (len && (addr & (align-1))) { size_t this_len = std::min(len, align - size_t(addr & (align-1))); std::vector chunk(align); cmemif->read_chunk(addr & ~(align-1), align, &chunk[0]); memcpy(bytes, &chunk[addr & (align-1)], this_len); bytes = (char*)bytes + this_len; addr += this_len; len -= this_len; } if (len & (align-1)) { size_t this_len = len & (align-1); size_t start = len - this_len; std::vector chunk(align); cmemif->read_chunk(addr + start, align, &chunk[0]); memcpy((char*)bytes + start, &chunk[0], this_len); len -= this_len; } // now we're aligned for (size_t pos = 0; pos < len; pos += cmemif->chunk_max_size()) cmemif->read_chunk(addr + pos, std::min(cmemif->chunk_max_size(), len - pos), (char*)bytes + pos); } void memif_t::write(addr_t addr, size_t len, const void* bytes) { size_t align = cmemif->chunk_align(); if (len && (addr & (align-1))) { size_t this_len = std::min(len, align - size_t(addr & (align-1))); std::vector chunk(align); cmemif->read_chunk(addr & ~(align-1), align, &chunk[0]); memcpy(&chunk[addr & (align-1)], bytes, this_len); cmemif->write_chunk(addr & ~(align-1), align, &chunk[0]); bytes = (char*)bytes + this_len; addr += this_len; len -= this_len; } if (len & (align-1)) { size_t this_len = len & (align-1); size_t start = len - this_len; std::vector chunk(align); cmemif->read_chunk(addr + start, align, &chunk[0]); memcpy(&chunk[0], (char*)bytes + start, this_len); cmemif->write_chunk(addr + start, align, &chunk[0]); len -= this_len; } // now we're aligned bool all_zero = len != 0; for (size_t i = 0; i < len; i++) all_zero &= ((const char*)bytes)[i] == 0; if (all_zero) { cmemif->clear_chunk(addr, len); } else { size_t max_chunk = cmemif->chunk_max_size(); for (size_t pos = 0; pos < len; pos += max_chunk) cmemif->write_chunk(addr + pos, std::min(max_chunk, len - pos), (char*)bytes + pos); } } #define MEMIF_READ_FUNC \ if(addr & (sizeof(val)-1)) \ throw std::runtime_error("misaligned address"); \ this->read(addr, sizeof(val), &val); \ return val #define MEMIF_WRITE_FUNC \ if(addr & (sizeof(val)-1)) \ throw std::runtime_error("misaligned address"); \ this->write(addr, sizeof(val), &val) target_endian memif_t::read_uint8(addr_t addr) { target_endian val; MEMIF_READ_FUNC; } target_endian memif_t::read_int8(addr_t addr) { target_endian val; MEMIF_READ_FUNC; } void memif_t::write_uint8(addr_t addr, target_endian val) { MEMIF_WRITE_FUNC; } void memif_t::write_int8(addr_t addr, target_endian val) { MEMIF_WRITE_FUNC; } target_endian memif_t::read_uint16(addr_t addr) { target_endian val; MEMIF_READ_FUNC; } target_endian memif_t::read_int16(addr_t addr) { target_endian val; MEMIF_READ_FUNC; } void memif_t::write_uint16(addr_t addr, target_endian val) { MEMIF_WRITE_FUNC; } void memif_t::write_int16(addr_t addr, target_endian val) { MEMIF_WRITE_FUNC; } target_endian memif_t::read_uint32(addr_t addr) { target_endian val; MEMIF_READ_FUNC; } target_endian memif_t::read_int32(addr_t addr) { target_endian val; MEMIF_READ_FUNC; } void memif_t::write_uint32(addr_t addr, target_endian val) { MEMIF_WRITE_FUNC; } void memif_t::write_int32(addr_t addr, target_endian val) { MEMIF_WRITE_FUNC; } target_endian memif_t::read_uint64(addr_t addr) { target_endian val; MEMIF_READ_FUNC; } target_endian memif_t::read_int64(addr_t addr) { target_endian val; MEMIF_READ_FUNC; } void memif_t::write_uint64(addr_t addr, target_endian val) { MEMIF_WRITE_FUNC; } void memif_t::write_int64(addr_t addr, target_endian val) { MEMIF_WRITE_FUNC; }