#pragma once #include #include #include #include #include #include #include #include #include #include "aisa/aisa.h" namespace aisa { template struct PagedMem { using page_t = std::array; static const addr_t PAGE_SIZE = 1 << PAGE_BITS; static const addr_t PAGE_MASK = PAGE_SIZE - 1; std::map pages; bool fetch_mem(byte_t *bytes, addr_t addr, addr_t size) { if (size == 0) return true; auto page_base = addr >> PAGE_BITS; auto page_offset = addr & PAGE_MASK; auto size_here = std::min(size, PAGE_SIZE - page_offset); if (auto page = pages.find(page_base); page != pages.end()) std::memcpy(bytes, page->second.data() + page_offset, size_here); else std::memset(bytes, 0, size_here); return fetch_mem(bytes + size_here, addr + size_here, size - size_here); } bool store_mem(addr_t addr, const byte_t *bytes, addr_t size) { if (size == 0) return true; auto page_base = addr >> PAGE_BITS; auto page_offset = addr & PAGE_MASK; auto size_here = std::min(size, PAGE_SIZE - page_offset); std::memcpy(pages[page_base].data() + page_offset, bytes, size_here); return store_mem(addr + size_here, bytes + size_here, size - size_here); } }; struct TaskStack { std::deque> tasks; bool pop_task() { if (tasks.empty()) return false; tasks.pop_back(); return true; } bool push_task(std::unique_ptr &&task) { tasks.emplace_back(std::move(task)); return true; } std::optional top_task() { if (tasks.empty()) return {}; return tasks.back().get(); } }; struct VectorRF { std::vector> rf; std::optional load_reg(regnum_t rn) const { if (rf.size() <= rn) return {}; return rf[rn]; } bool store_reg(regnum_t rn, regval_t rv) { if (rf.size() <= rn) rf.resize(rn + 1); rf[rn] = rv; return true; } }; }