// license:BSD-3-Clause // copyright-holders:Olivier Galibert #include "emu.h" #include "emumem_hea.h" #include "emumem_mud.h" #include "emumem_heu.h" template handler_entry_read_units::handler_entry_read_units(const memory_units_descriptor &descriptor, u8 ukey, address_space *space) : handler_entry_read(space, inh::F_UNITS), m_subunits(0) { const auto &entries = descriptor.get_entries_for_key(ukey); fill(descriptor, entries); std::sort(m_subunit_infos, m_subunit_infos + m_subunits, [](const subunit_info &a, const subunit_info &b) { return a.m_offset < b.m_offset; }); } template handler_entry_read_units::handler_entry_read_units(const memory_units_descriptor &descriptor, u8 ukey, const handler_entry_read_units *src) : handler_entry_read(src->m_space, inh::F_UNITS), m_subunits(0) { uX fullmask = 0; const auto &entries = descriptor.get_entries_for_key(ukey); for(const auto &e : entries) fullmask |= e.m_dmask; for(u32 i=0; i != src->m_subunits; i++) if(!(src->m_subunit_infos[i].m_dmask & fullmask)) { m_subunit_infos[m_subunits] = src->m_subunit_infos[i]; m_subunit_infos[m_subunits].m_handler->ref(); m_subunits++; } fill(descriptor, entries); std::sort(m_subunit_infos, m_subunit_infos + m_subunits, [](const subunit_info &a, const subunit_info &b) { return a.m_offset < b.m_offset; }); } template handler_entry_read_units::~handler_entry_read_units() { for(u32 i=0; i != m_subunits; i++) m_subunit_infos[i].m_handler->unref(); } template void handler_entry_read_units::enumerate_references(handler_entry::reflist &refs) const { for(u32 i=0; i != m_subunits; i++) refs.add(m_subunit_infos[i].m_handler); } template void handler_entry_read_units::fill(const memory_units_descriptor &descriptor, const std::vector::entry> &entries) { handler_entry *handler = descriptor.get_subunit_handler(); handler->ref(entries.size()); for(const auto &e : entries) m_subunit_infos[m_subunits++] = subunit_info{ handler, e.m_amask, e.m_dmask, e.m_ashift, e.m_offset, e.m_dshift, descriptor.get_subunit_width(), descriptor.get_subunit_endian() }; m_unmap = inh::m_space->unmap(); for(int i = 0; i < m_subunits; i++) m_unmap &= ~m_subunit_infos[i].m_dmask; } template typename emu::detail::handler_entry_size::uX handler_entry_read_units::read(offs_t offset, uX mem_mask) { this->ref(); uX result = m_unmap; for (int index = 0; index < m_subunits; index++) { const subunit_info &si = m_subunit_infos[index]; if (mem_mask & si.m_amask) { offs_t aoffset = (si.m_ashift >= 0 ? offset >> si.m_ashift : offset << si.m_ashift) + si.m_offset; switch(si.m_width) { case 0: if(si.m_endian == ENDIANNESS_LITTLE) result |= uX(static_cast *>(si.m_handler)->read(aoffset, mem_mask >> si.m_dshift)) << si.m_dshift; else result |= uX(static_cast *>(si.m_handler)->read(aoffset, mem_mask >> si.m_dshift)) << si.m_dshift; break; case 1: if(si.m_endian == ENDIANNESS_LITTLE) result |= uX(static_cast *>(si.m_handler)->read(aoffset, mem_mask >> si.m_dshift)) << si.m_dshift; else result |= uX(static_cast *>(si.m_handler)->read(aoffset, mem_mask >> si.m_dshift)) << si.m_dshift; break; case 2: if(si.m_endian == ENDIANNESS_LITTLE) result |= uX(static_cast *>(si.m_handler)->read(aoffset, mem_mask >> si.m_dshift)) << si.m_dshift; else result |= uX(static_cast *>(si.m_handler)->read(aoffset, mem_mask >> si.m_dshift)) << si.m_dshift; break; default: abort(); } } } this->unref(); return result; } template std::string handler_entry_read_units::m2r(typename emu::detail::handler_entry_size::uX mask) { constexpr u32 mbits = 8*sizeof(uX); u32 start, end; for(start = 0; start < mbits && !(mask & (uX(1)<= mbits || end >= mbits) return "???"; return util::string_format("%d-%d", end, start); } template std::string handler_entry_read_units::name() const { std::string result; for (int index = 0; index < m_subunits; index++) { const subunit_info &si = m_subunit_infos[index]; if(!result.empty()) result += ' '; result += util::string_format("%s:%s:%d:%d:%d:%s", m2r(si.m_amask), m2r(si.m_dmask), si.m_ashift, si.m_offset, si.m_dshift, si.m_handler->name()); } return result; } template handler_entry_write_units::handler_entry_write_units(const memory_units_descriptor &descriptor, u8 ukey, address_space *space) : handler_entry_write(space, inh::F_UNITS), m_subunits(0) { const auto &entries = descriptor.get_entries_for_key(ukey); fill(descriptor, entries); std::sort(m_subunit_infos, m_subunit_infos + m_subunits, [](const subunit_info &a, const subunit_info &b) { return a.m_offset < b.m_offset; }); } template handler_entry_write_units::handler_entry_write_units(const memory_units_descriptor &descriptor, u8 ukey, const handler_entry_write_units *src) : handler_entry_write(src->m_space, inh::F_UNITS), m_subunits(0) { uX fullmask = 0; const auto &entries = descriptor.get_entries_for_key(ukey); for(const auto &e : entries) fullmask |= e.m_dmask; for(u32 i=0; i != src->m_subunits; i++) if(!(src->m_subunit_infos[i].m_dmask & fullmask)) { m_subunit_infos[m_subunits] = src->m_subunit_infos[i]; m_subunit_infos[m_subunits].m_handler->ref(); m_subunits++; } fill(descriptor, entries); std::sort(m_subunit_infos, m_subunit_infos + m_subunits, [](const subunit_info &a, const subunit_info &b) { return a.m_offset < b.m_offset; }); } template handler_entry_write_units::~handler_entry_write_units() { for(u32 i=0; i != m_subunits; i++) m_subunit_infos[i].m_handler->unref(); } template void handler_entry_write_units::enumerate_references(handler_entry::reflist &refs) const { for(u32 i=0; i != m_subunits; i++) refs.add(m_subunit_infos[i].m_handler); } template void handler_entry_write_units::fill(const memory_units_descriptor &descriptor, const std::vector::entry> &entries) { handler_entry *handler = descriptor.get_subunit_handler(); handler->ref(entries.size()); for(const auto &e : entries) m_subunit_infos[m_subunits++] = subunit_info{ handler, e.m_amask, e.m_dmask, e.m_ashift, e.m_offset, e.m_dshift, descriptor.get_subunit_width(), descriptor.get_subunit_endian() }; } template void handler_entry_write_units::write(offs_t offset, uX data, uX mem_mask) { this->ref(); for (int index = 0; index < m_subunits; index++) { const subunit_info &si = m_subunit_infos[index]; if (mem_mask & si.m_amask) { offs_t aoffset = (si.m_ashift >= 0 ? offset >> si.m_ashift : offset << si.m_ashift) + si.m_offset; switch(si.m_width) { case 0: if(si.m_endian == ENDIANNESS_LITTLE) static_cast *>(si.m_handler)->write(aoffset, data >> si.m_dshift, mem_mask >> si.m_dshift); else static_cast *>(si.m_handler)->write(aoffset, data >> si.m_dshift, mem_mask >> si.m_dshift); break; case 1: if(si.m_endian == ENDIANNESS_LITTLE) static_cast *>(si.m_handler)->write(aoffset, data >> si.m_dshift, mem_mask >> si.m_dshift); else static_cast *>(si.m_handler)->write(aoffset, data >> si.m_dshift, mem_mask >> si.m_dshift); break; case 2: if(si.m_endian == ENDIANNESS_LITTLE) static_cast *>(si.m_handler)->write(aoffset, data >> si.m_dshift, mem_mask >> si.m_dshift); else static_cast *>(si.m_handler)->write(aoffset, data >> si.m_dshift, mem_mask >> si.m_dshift); break; default: abort(); } } } this->unref(); } template std::string handler_entry_write_units::m2r(typename emu::detail::handler_entry_size::uX mask) { constexpr u32 mbits = 8*sizeof(uX); u32 start, end; for(start = 0; start < mbits && !(mask & (uX(1)<= mbits || end >= mbits) return "???"; return util::string_format("%d-%d", end, start); } template std::string handler_entry_write_units::name() const { std::string result; for (int index = 0; index < m_subunits; index++) { const subunit_info &si = m_subunit_infos[index]; if(!result.empty()) result += ' '; result += util::string_format("%s:%s:%d:%d:%d:%s", m2r(si.m_amask), m2r(si.m_dmask), si.m_ashift, si.m_offset, si.m_dshift, si.m_handler->name()); } return result; } template class handler_entry_read_units<0, 1, ENDIANNESS_LITTLE>; template class handler_entry_read_units<0, 1, ENDIANNESS_BIG>; template class handler_entry_read_units<0, 0, ENDIANNESS_LITTLE>; template class handler_entry_read_units<0, 0, ENDIANNESS_BIG>; template class handler_entry_read_units<1, 3, ENDIANNESS_LITTLE>; template class handler_entry_read_units<1, 3, ENDIANNESS_BIG>; template class handler_entry_read_units<1, 0, ENDIANNESS_LITTLE>; template class handler_entry_read_units<1, 0, ENDIANNESS_BIG>; template class handler_entry_read_units<1, -1, ENDIANNESS_LITTLE>; template class handler_entry_read_units<1, -1, ENDIANNESS_BIG>; template class handler_entry_read_units<2, 0, ENDIANNESS_LITTLE>; template class handler_entry_read_units<2, 0, ENDIANNESS_BIG>; template class handler_entry_read_units<2, -1, ENDIANNESS_LITTLE>; template class handler_entry_read_units<2, -1, ENDIANNESS_BIG>; template class handler_entry_read_units<2, -2, ENDIANNESS_LITTLE>; template class handler_entry_read_units<2, -2, ENDIANNESS_BIG>; template class handler_entry_read_units<3, 0, ENDIANNESS_LITTLE>; template class handler_entry_read_units<3, 0, ENDIANNESS_BIG>; template class handler_entry_read_units<3, -1, ENDIANNESS_LITTLE>; template class handler_entry_read_units<3, -1, ENDIANNESS_BIG>; template class handler_entry_read_units<3, -2, ENDIANNESS_LITTLE>; template class handler_entry_read_units<3, -2, ENDIANNESS_BIG>; template class handler_entry_read_units<3, -3, ENDIANNESS_LITTLE>; template class handler_entry_read_units<3, -3, ENDIANNESS_BIG>; template class handler_entry_write_units<0, 1, ENDIANNESS_LITTLE>; template class handler_entry_write_units<0, 1, ENDIANNESS_BIG>; template class handler_entry_write_units<0, 0, ENDIANNESS_LITTLE>; template class handler_entry_write_units<0, 0, ENDIANNESS_BIG>; template class handler_entry_write_units<1, 3, ENDIANNESS_LITTLE>; template class handler_entry_write_units<1, 3, ENDIANNESS_BIG>; template class handler_entry_write_units<1, 0, ENDIANNESS_LITTLE>; template class handler_entry_write_units<1, 0, ENDIANNESS_BIG>; template class handler_entry_write_units<1, -1, ENDIANNESS_LITTLE>; template class handler_entry_write_units<1, -1, ENDIANNESS_BIG>; template class handler_entry_write_units<2, 0, ENDIANNESS_LITTLE>; template class handler_entry_write_units<2, 0, ENDIANNESS_BIG>; template class handler_entry_write_units<2, -1, ENDIANNESS_LITTLE>; template class handler_entry_write_units<2, -1, ENDIANNESS_BIG>; template class handler_entry_write_units<2, -2, ENDIANNESS_LITTLE>; template class handler_entry_write_units<2, -2, ENDIANNESS_BIG>; template class handler_entry_write_units<3, 0, ENDIANNESS_LITTLE>; template class handler_entry_write_units<3, 0, ENDIANNESS_BIG>; template class handler_entry_write_units<3, -1, ENDIANNESS_LITTLE>; template class handler_entry_write_units<3, -1, ENDIANNESS_BIG>; template class handler_entry_write_units<3, -2, ENDIANNESS_LITTLE>; template class handler_entry_write_units<3, -2, ENDIANNESS_BIG>; template class handler_entry_write_units<3, -3, ENDIANNESS_LITTLE>; template class handler_entry_write_units<3, -3, ENDIANNESS_BIG>;