mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
emumem: Another slight speedup, implemented on the 680x0 for now [O. Galibert]
memory_access_specific is declared and used exactly like memory_access_cache, but does not cache. It does, however, shortcut the virtual call into address_space, so that's one layer of call less. Gives another nice speedup for accesses with bad locality (e.g. anything that's not opcodes), at the expense of having a specifically typed object in the class. Should do well for cpus in general, drivers can keep using the address_space access calls for easier logistics.
This commit is contained in:
parent
beb60b8721
commit
ecef74a610
@ -1306,14 +1306,15 @@ void m68000_base_device::init8(address_space &space, address_space &ospace)
|
||||
m_space = &space;
|
||||
m_ospace = &ospace;
|
||||
auto ocache = ospace.cache<0, 0, ENDIANNESS_BIG>();
|
||||
auto pspec = space.specific<0, 0, ENDIANNESS_BIG>();
|
||||
|
||||
m_readimm16 = [ocache](offs_t address) -> u16 { return ocache->read_word(address); };
|
||||
m_read8 = [this](offs_t address) -> u8 { return m_space->read_byte(address); };
|
||||
m_read16 = [this](offs_t address) -> u16 { return m_space->read_word(address); };
|
||||
m_read32 = [this](offs_t address) -> u32 { return m_space->read_dword(address); };
|
||||
m_write8 = [this](offs_t address, u8 data) { m_space->write_byte(address, data); };
|
||||
m_write16 = [this](offs_t address, u16 data) { m_space->write_word(address, data); };
|
||||
m_write32 = [this](offs_t address, u32 data) { m_space->write_dword(address, data); };
|
||||
m_read8 = [pspec](offs_t address) -> u8 { return pspec->read_byte(address); };
|
||||
m_read16 = [pspec](offs_t address) -> u16 { return pspec->read_word(address); };
|
||||
m_read32 = [pspec](offs_t address) -> u32 { return pspec->read_dword(address); };
|
||||
m_write8 = [pspec](offs_t address, u8 data) { pspec->write_byte(address, data); };
|
||||
m_write16 = [pspec](offs_t address, u16 data) { pspec->write_word(address, data); };
|
||||
m_write32 = [pspec](offs_t address, u32 data) { pspec->write_dword(address, data); };
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1325,14 +1326,15 @@ void m68000_base_device::init16(address_space &space, address_space &ospace)
|
||||
m_space = &space;
|
||||
m_ospace = &ospace;
|
||||
auto ocache = ospace.cache<1, 0, ENDIANNESS_BIG>();
|
||||
auto pspec = space.specific<1, 0, ENDIANNESS_BIG>();
|
||||
|
||||
m_readimm16 = [ocache](offs_t address) -> u16 { return ocache->read_word(address); };
|
||||
m_read8 = [this](offs_t address) -> u8 { return m_space->read_byte(address); };
|
||||
m_read16 = [this](offs_t address) -> u16 { return m_space->read_word(address); };
|
||||
m_read32 = [this](offs_t address) -> u32 { return m_space->read_dword(address); };
|
||||
m_write8 = [this](offs_t address, u8 data) { m_space->write_word(address & ~1, data | (data << 8), address & 1 ? 0x00ff : 0xff00); };
|
||||
m_write16 = [this](offs_t address, u16 data) { m_space->write_word(address, data); };
|
||||
m_write32 = [this](offs_t address, u32 data) { m_space->write_dword(address, data); };
|
||||
m_read8 = [pspec](offs_t address) -> u8 { return pspec->read_byte(address); };
|
||||
m_read16 = [pspec](offs_t address) -> u16 { return pspec->read_word(address); };
|
||||
m_read32 = [pspec](offs_t address) -> u32 { return pspec->read_dword(address); };
|
||||
m_write8 = [pspec](offs_t address, u8 data) { pspec->write_word(address & ~1, data | (data << 8), address & 1 ? 0x00ff : 0xff00); };
|
||||
m_write16 = [pspec](offs_t address, u16 data) { pspec->write_word(address, data); };
|
||||
m_write32 = [pspec](offs_t address, u32 data) { pspec->write_dword(address, data); };
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1349,53 +1351,54 @@ void m68000_base_device::init32(address_space &space, address_space &ospace)
|
||||
m_space = &space;
|
||||
m_ospace = &ospace;
|
||||
auto ocache = ospace.cache<2, 0, ENDIANNESS_BIG>();
|
||||
auto pspec = space.specific<2, 0, ENDIANNESS_BIG>();
|
||||
|
||||
m_readimm16 = [ocache](offs_t address) -> u16 { return ocache->read_word(address); };
|
||||
m_read8 = [this](offs_t address) -> u8 { return m_space->read_byte(address); };
|
||||
m_read16 = [this](offs_t address) -> u16 { return m_space->read_word_unaligned(address); };
|
||||
m_read32 = [this](offs_t address) -> u32 { return m_space->read_dword_unaligned(address); };
|
||||
m_write8 = [this](offs_t address, u8 data) {
|
||||
m_space->write_dword(address & 0xfffffffcU, dword_from_byte(data), 0xff000000U >> 8 * (address & 3));
|
||||
m_read8 = [pspec](offs_t address) -> u8 { return pspec->read_byte(address); };
|
||||
m_read16 = [pspec](offs_t address) -> u16 { return pspec->read_word_unaligned(address); };
|
||||
m_read32 = [pspec](offs_t address) -> u32 { return pspec->read_dword_unaligned(address); };
|
||||
m_write8 = [pspec](offs_t address, u8 data) {
|
||||
pspec->write_dword(address & 0xfffffffcU, dword_from_byte(data), 0xff000000U >> 8 * (address & 3));
|
||||
};
|
||||
m_write16 = [this](offs_t address, u16 data) {
|
||||
m_write16 = [pspec](offs_t address, u16 data) {
|
||||
switch (address & 3) {
|
||||
case 0:
|
||||
m_space->write_dword(address, dword_from_word(data), 0xffff0000U);
|
||||
pspec->write_dword(address, dword_from_word(data), 0xffff0000U);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_space->write_dword(address - 1, dword_from_unaligned_word(data), 0x00ffff00);
|
||||
pspec->write_dword(address - 1, dword_from_unaligned_word(data), 0x00ffff00);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_space->write_dword(address - 2, dword_from_word(data), 0x0000ffff);
|
||||
pspec->write_dword(address - 2, dword_from_word(data), 0x0000ffff);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_space->write_dword(address - 3, dword_from_unaligned_word(data), 0x000000ff);
|
||||
m_space->write_dword(address + 1, dword_from_byte(data & 0x00ff), 0xff000000U);
|
||||
pspec->write_dword(address - 3, dword_from_unaligned_word(data), 0x000000ff);
|
||||
pspec->write_dword(address + 1, dword_from_byte(data & 0x00ff), 0xff000000U);
|
||||
break;
|
||||
}
|
||||
};
|
||||
m_write32 = [this](offs_t address, u32 data) {
|
||||
m_write32 = [pspec](offs_t address, u32 data) {
|
||||
switch (address & 3) {
|
||||
case 0:
|
||||
m_space->write_dword(address, data, 0xffffffffU);
|
||||
pspec->write_dword(address, data, 0xffffffffU);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_space->write_dword(address - 1, (data & 0xff000000U) | (data & 0xffffff00U) >> 8, 0x00ffffff);
|
||||
m_space->write_dword(address + 3, dword_from_byte(data & 0x000000ff), 0xff000000U);
|
||||
pspec->write_dword(address - 1, (data & 0xff000000U) | (data & 0xffffff00U) >> 8, 0x00ffffff);
|
||||
pspec->write_dword(address + 3, dword_from_byte(data & 0x000000ff), 0xff000000U);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_space->write_dword(address - 2, dword_from_word((data & 0xffff0000U) >> 16), 0x0000ffff);
|
||||
m_space->write_dword(address + 2, dword_from_word(data & 0x0000ffff), 0xffff0000U);
|
||||
pspec->write_dword(address - 2, dword_from_word((data & 0xffff0000U) >> 16), 0x0000ffff);
|
||||
pspec->write_dword(address + 2, dword_from_word(data & 0x0000ffff), 0xffff0000U);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_space->write_dword(address - 3, dword_from_unaligned_word((data & 0xffff0000U) >> 16), 0x000000ff);
|
||||
m_space->write_dword(address + 1, (data & 0x00ffffff) << 8 | (data & 0xff000000U) >> 24, 0xffffff00U);
|
||||
pspec->write_dword(address - 3, dword_from_unaligned_word((data & 0xffff0000U) >> 16), 0x000000ff);
|
||||
pspec->write_dword(address + 1, (data & 0x00ffffff) << 8 | (data & 0xff000000U) >> 24, 0xffffff00U);
|
||||
break;
|
||||
}
|
||||
};
|
||||
@ -1407,6 +1410,7 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
|
||||
m_space = &space;
|
||||
m_ospace = &ospace;
|
||||
auto ocache = ospace.cache<2, 0, ENDIANNESS_BIG>();
|
||||
auto pspec = space.specific<2, 0, ENDIANNESS_BIG>();
|
||||
|
||||
m_readimm16 = [this, ocache](offs_t address) -> u16 {
|
||||
if (m_pmmu_enabled) {
|
||||
@ -1418,32 +1422,32 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
|
||||
return ocache->read_word(address);
|
||||
};
|
||||
|
||||
m_read8 = [this](offs_t address) -> u8 {
|
||||
m_read8 = [this, pspec](offs_t address) -> u8 {
|
||||
if (m_pmmu_enabled) {
|
||||
address = pmmu_translate_addr(address, 1);
|
||||
if (m_mmu_tmp_buserror_occurred)
|
||||
return ~0;
|
||||
}
|
||||
return m_space->read_byte(address);
|
||||
return pspec->read_byte(address);
|
||||
};
|
||||
|
||||
m_read16 = [this](offs_t address) -> u16 {
|
||||
m_read16 = [this, pspec](offs_t address) -> u16 {
|
||||
if (m_pmmu_enabled) {
|
||||
u32 address0 = pmmu_translate_addr(address, 1);
|
||||
if (m_mmu_tmp_buserror_occurred)
|
||||
return ~0;
|
||||
if (WORD_ALIGNED(address))
|
||||
return m_space->read_word(address0);
|
||||
return pspec->read_word(address0);
|
||||
u32 address1 = pmmu_translate_addr(address + 1, 1);
|
||||
if (m_mmu_tmp_buserror_occurred)
|
||||
return ~0;
|
||||
u16 result = m_space->read_byte(address0) << 8;
|
||||
return result | m_space->read_byte(address1);
|
||||
u16 result = pspec->read_byte(address0) << 8;
|
||||
return result | pspec->read_byte(address1);
|
||||
}
|
||||
return m_space->read_word_unaligned(address);
|
||||
return pspec->read_word_unaligned(address);
|
||||
};
|
||||
|
||||
m_read32 = [this](offs_t address) -> u32 {
|
||||
m_read32 = [this, pspec](offs_t address) -> u32 {
|
||||
if (m_pmmu_enabled) {
|
||||
u32 address0 = pmmu_translate_addr(address, 1);
|
||||
if (m_mmu_tmp_buserror_occurred)
|
||||
@ -1452,37 +1456,37 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
|
||||
// not at page boundary; use default code
|
||||
address = address0;
|
||||
else if (DWORD_ALIGNED(address)) // 0
|
||||
return m_space->read_dword(address0);
|
||||
return pspec->read_dword(address0);
|
||||
else {
|
||||
u32 address2 = pmmu_translate_addr(address+2, 1);
|
||||
if (m_mmu_tmp_buserror_occurred)
|
||||
return ~0;
|
||||
if (WORD_ALIGNED(address)) { // 2
|
||||
u32 result = m_space->read_word(address0) << 16;
|
||||
return result | m_space->read_word(address2);
|
||||
u32 result = pspec->read_word(address0) << 16;
|
||||
return result | pspec->read_word(address2);
|
||||
}
|
||||
u32 address1 = pmmu_translate_addr(address+1, 1);
|
||||
u32 address3 = pmmu_translate_addr(address+3, 1);
|
||||
if (m_mmu_tmp_buserror_occurred)
|
||||
return ~0;
|
||||
u32 result = m_space->read_byte(address0) << 24;
|
||||
result |= m_space->read_word(address1) << 8;
|
||||
return result | m_space->read_byte(address3);
|
||||
u32 result = pspec->read_byte(address0) << 24;
|
||||
result |= pspec->read_word(address1) << 8;
|
||||
return result | pspec->read_byte(address3);
|
||||
}
|
||||
}
|
||||
return m_space->read_dword_unaligned(address);
|
||||
return pspec->read_dword_unaligned(address);
|
||||
};
|
||||
|
||||
m_write8 = [this](offs_t address, u8 data) {
|
||||
m_write8 = [this, pspec](offs_t address, u8 data) {
|
||||
if (m_pmmu_enabled) {
|
||||
address = pmmu_translate_addr(address, 0);
|
||||
if (m_mmu_tmp_buserror_occurred)
|
||||
return;
|
||||
}
|
||||
m_space->write_dword(address & 0xfffffffcU, dword_from_byte(data), 0xff000000U >> 8 * (address & 3));
|
||||
pspec->write_dword(address & 0xfffffffcU, dword_from_byte(data), 0xff000000U >> 8 * (address & 3));
|
||||
};
|
||||
|
||||
m_write16 = [this](offs_t address, u16 data) {
|
||||
m_write16 = [this, pspec](offs_t address, u16 data) {
|
||||
u32 address0 = address;
|
||||
if (m_pmmu_enabled) {
|
||||
address0 = pmmu_translate_addr(address0, 0);
|
||||
@ -1491,15 +1495,15 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
|
||||
}
|
||||
switch (address & 3) {
|
||||
case 0:
|
||||
m_space->write_dword(address0, dword_from_word(data), 0xffff0000U);
|
||||
pspec->write_dword(address0, dword_from_word(data), 0xffff0000U);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_space->write_dword(address0 - 1, dword_from_unaligned_word(data), 0x00ffff00);
|
||||
pspec->write_dword(address0 - 1, dword_from_unaligned_word(data), 0x00ffff00);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_space->write_dword(address0 - 2, dword_from_word(data), 0x0000ffff);
|
||||
pspec->write_dword(address0 - 2, dword_from_word(data), 0x0000ffff);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
@ -1510,14 +1514,14 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
|
||||
if (m_mmu_tmp_buserror_occurred)
|
||||
return;
|
||||
}
|
||||
m_space->write_dword(address0 - 3, dword_from_unaligned_word(data), 0x000000ff);
|
||||
m_space->write_dword(address1, dword_from_byte(data & 0x00ff), 0xff000000U);
|
||||
pspec->write_dword(address0 - 3, dword_from_unaligned_word(data), 0x000000ff);
|
||||
pspec->write_dword(address1, dword_from_byte(data & 0x00ff), 0xff000000U);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
m_write32 = [this](offs_t address, u32 data) {
|
||||
m_write32 = [this, pspec](offs_t address, u32 data) {
|
||||
u32 address0 = address;
|
||||
if (m_pmmu_enabled) {
|
||||
address0 = pmmu_translate_addr(address0, 0);
|
||||
@ -1526,7 +1530,7 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
|
||||
}
|
||||
switch (address & 3) {
|
||||
case 0:
|
||||
m_space->write_dword(address0, data, 0xffffffffU);
|
||||
pspec->write_dword(address0, data, 0xffffffffU);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
@ -1537,8 +1541,8 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
|
||||
if (m_mmu_tmp_buserror_occurred)
|
||||
return;
|
||||
}
|
||||
m_space->write_dword(address0 - 1, (data & 0xff000000U) | (data & 0xffffff00U) >> 8, 0x00ffffff);
|
||||
m_space->write_dword(address3, dword_from_byte(data & 0x000000ff), 0xff000000U);
|
||||
pspec->write_dword(address0 - 1, (data & 0xff000000U) | (data & 0xffffff00U) >> 8, 0x00ffffff);
|
||||
pspec->write_dword(address3, dword_from_byte(data & 0x000000ff), 0xff000000U);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1550,8 +1554,8 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
|
||||
if (m_mmu_tmp_buserror_occurred)
|
||||
return;
|
||||
}
|
||||
m_space->write_dword(address0 - 2, dword_from_word((data & 0xffff0000U) >> 16), 0x0000ffff);
|
||||
m_space->write_dword(address2, dword_from_word(data & 0x0000ffff), 0xffff0000U);
|
||||
pspec->write_dword(address0 - 2, dword_from_word((data & 0xffff0000U) >> 16), 0x0000ffff);
|
||||
pspec->write_dword(address2, dword_from_word(data & 0x0000ffff), 0xffff0000U);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1563,8 +1567,8 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
|
||||
if (m_mmu_tmp_buserror_occurred)
|
||||
return;
|
||||
}
|
||||
m_space->write_dword(address0 - 3, dword_from_unaligned_word((data & 0xffff0000U) >> 16), 0x000000ff);
|
||||
m_space->write_dword(address1, (data & 0x00ffffff) << 8 | (data & 0xff000000U) >> 24, 0xffffff00U);
|
||||
pspec->write_dword(address0 - 3, dword_from_unaligned_word((data & 0xffff0000U) >> 16), 0x000000ff);
|
||||
pspec->write_dword(address1, (data & 0x00ffffff) << 8 | (data & 0xff000000U) >> 24, 0xffffff00U);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1576,6 +1580,7 @@ void m68000_base_device::init32hmmu(address_space &space, address_space &ospace)
|
||||
m_space = &space;
|
||||
m_ospace = &ospace;
|
||||
auto ocache = ospace.cache<2, 0, ENDIANNESS_BIG>();
|
||||
auto pspec = space.specific<2, 0, ENDIANNESS_BIG>();
|
||||
|
||||
m_readimm16 = [this, ocache](offs_t address) -> u16 {
|
||||
if (m_hmmu_enabled)
|
||||
@ -1583,69 +1588,69 @@ void m68000_base_device::init32hmmu(address_space &space, address_space &ospace)
|
||||
return ocache->read_word(address);
|
||||
};
|
||||
|
||||
m_read8 = [this](offs_t address) -> u8 {
|
||||
m_read8 = [this, pspec](offs_t address) -> u8 {
|
||||
if (m_hmmu_enabled)
|
||||
address = hmmu_translate_addr(address);
|
||||
return m_space->read_byte(address);
|
||||
return pspec->read_byte(address);
|
||||
};
|
||||
|
||||
m_read16 = [this](offs_t address) -> u16 {
|
||||
m_read16 = [this, pspec](offs_t address) -> u16 {
|
||||
if (m_hmmu_enabled)
|
||||
address = hmmu_translate_addr(address);
|
||||
if (WORD_ALIGNED(address))
|
||||
return m_space->read_word(address);
|
||||
u16 result = m_space->read_byte(address) << 8;
|
||||
return result | m_space->read_byte(address + 1);
|
||||
return pspec->read_word(address);
|
||||
u16 result = pspec->read_byte(address) << 8;
|
||||
return result | pspec->read_byte(address + 1);
|
||||
};
|
||||
|
||||
m_read32 = [this](offs_t address) -> u32 {
|
||||
m_read32 = [this, pspec](offs_t address) -> u32 {
|
||||
if (m_hmmu_enabled)
|
||||
address = hmmu_translate_addr(address);
|
||||
|
||||
if (DWORD_ALIGNED(address))
|
||||
return m_space->read_dword(address);
|
||||
return pspec->read_dword(address);
|
||||
if (WORD_ALIGNED(address)) {
|
||||
u32 result = m_space->read_word(address) << 16;
|
||||
return result | m_space->read_word(address + 2);
|
||||
u32 result = pspec->read_word(address) << 16;
|
||||
return result | pspec->read_word(address + 2);
|
||||
}
|
||||
u32 result = m_space->read_byte(address) << 24;
|
||||
result |= m_space->read_word(address + 1) << 8;
|
||||
return result | m_space->read_byte(address + 3);
|
||||
u32 result = pspec->read_byte(address) << 24;
|
||||
result |= pspec->read_word(address + 1) << 8;
|
||||
return result | pspec->read_byte(address + 3);
|
||||
};
|
||||
|
||||
m_write8 = [this](offs_t address, u8 data) {
|
||||
m_write8 = [this, pspec](offs_t address, u8 data) {
|
||||
if (m_hmmu_enabled)
|
||||
address = hmmu_translate_addr(address);
|
||||
m_space->write_byte(address, data);
|
||||
pspec->write_byte(address, data);
|
||||
};
|
||||
|
||||
m_write16 = [this](offs_t address, u16 data) {
|
||||
m_write16 = [this, pspec](offs_t address, u16 data) {
|
||||
if (m_hmmu_enabled)
|
||||
address = hmmu_translate_addr(address);
|
||||
if (WORD_ALIGNED(address)) {
|
||||
m_space->write_word(address, data);
|
||||
pspec->write_word(address, data);
|
||||
return;
|
||||
}
|
||||
m_space->write_byte(address, data >> 8);
|
||||
m_space->write_byte(address + 1, data);
|
||||
pspec->write_byte(address, data >> 8);
|
||||
pspec->write_byte(address + 1, data);
|
||||
};
|
||||
|
||||
m_write32 = [this](offs_t address, u32 data) {
|
||||
m_write32 = [this, pspec](offs_t address, u32 data) {
|
||||
if (m_hmmu_enabled)
|
||||
address = hmmu_translate_addr(address);
|
||||
|
||||
if (DWORD_ALIGNED(address)) {
|
||||
m_space->write_dword(address, data);
|
||||
pspec->write_dword(address, data);
|
||||
return;
|
||||
}
|
||||
if (WORD_ALIGNED(address)) {
|
||||
m_space->write_word(address, data >> 16);
|
||||
m_space->write_word(address + 2, data);
|
||||
pspec->write_word(address, data >> 16);
|
||||
pspec->write_word(address + 2, data);
|
||||
return;
|
||||
}
|
||||
m_space->write_byte(address, data >> 24);
|
||||
m_space->write_word(address + 1, data >> 8);
|
||||
m_space->write_byte(address + 3, data);
|
||||
pspec->write_byte(address, data >> 24);
|
||||
pspec->write_word(address + 1, data >> 8);
|
||||
pspec->write_byte(address + 3, data);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -529,6 +529,10 @@ public:
|
||||
return new memory_access_cache<Width, AddrShift, Endian>(*this, m_root_read, m_root_write);
|
||||
}
|
||||
|
||||
void *create_specific() override {
|
||||
return new memory_access_specific<Width, AddrShift, Endian>(*this, m_dispatch_read, m_mask_read, m_shift_read, m_dispatch_write, m_mask_write, m_shift_write);
|
||||
}
|
||||
|
||||
void delayed_ref(handler_entry *e) {
|
||||
e->ref();
|
||||
m_delayed_unrefs.insert(e);
|
||||
@ -593,43 +597,25 @@ public:
|
||||
// native read
|
||||
NativeType read_native(offs_t offset, NativeType mask)
|
||||
{
|
||||
g_profiler.start(PROFILER_MEMREAD);
|
||||
|
||||
uX result = dispatch_read<Width, AddrShift, Endian>(m_mask_read, m_shift_read, offset, mask, m_dispatch_read);;
|
||||
|
||||
g_profiler.stop();
|
||||
return result;
|
||||
return dispatch_read<Width, AddrShift, Endian>(m_mask_read, m_shift_read, offset, mask, m_dispatch_read);;
|
||||
}
|
||||
|
||||
// mask-less native read
|
||||
NativeType read_native(offs_t offset)
|
||||
{
|
||||
g_profiler.start(PROFILER_MEMREAD);
|
||||
|
||||
uX result = dispatch_read<Width, AddrShift, Endian>(m_mask_read, m_shift_read, offset, uX(0xffffffffffffffffU), m_dispatch_read);;
|
||||
|
||||
g_profiler.stop();
|
||||
return result;
|
||||
return dispatch_read<Width, AddrShift, Endian>(m_mask_read, m_shift_read, offset, uX(0xffffffffffffffffU), m_dispatch_read);;
|
||||
}
|
||||
|
||||
// native write
|
||||
void write_native(offs_t offset, NativeType data, NativeType mask)
|
||||
{
|
||||
g_profiler.start(PROFILER_MEMWRITE);
|
||||
|
||||
dispatch_write<Width, AddrShift, Endian>(m_mask_write, m_shift_write, offset, data, mask, m_dispatch_write);;
|
||||
|
||||
g_profiler.stop();
|
||||
}
|
||||
|
||||
// mask-less native write
|
||||
void write_native(offs_t offset, NativeType data)
|
||||
{
|
||||
g_profiler.start(PROFILER_MEMWRITE);
|
||||
|
||||
dispatch_write<Width, AddrShift, Endian>(m_mask_write, m_shift_write, offset, data, uX(0xffffffffffffffffU), m_dispatch_write);;
|
||||
|
||||
g_profiler.stop();
|
||||
}
|
||||
|
||||
// virtual access to these functions
|
||||
|
101
src/emu/emumem.h
101
src/emu/emumem.h
@ -976,6 +976,78 @@ template<int Width, int AddrShift, int Endian> void dispatch_write(offs_t mask,
|
||||
}
|
||||
|
||||
|
||||
// ======================> memory_access_specific
|
||||
|
||||
// memory_access_specific does uncached but faster accesses by shortcutting the address_space virtual call
|
||||
|
||||
template<int Width, int AddrShift, int Endian> class memory_access_specific
|
||||
{
|
||||
using NativeType = typename emu::detail::handler_entry_size<Width>::uX;
|
||||
static constexpr u32 NATIVE_BYTES = 1 << Width;
|
||||
static constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? (1 << (Width + AddrShift)) - 1 : 0;
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
memory_access_specific(address_space &space,
|
||||
handler_entry_read <Width, AddrShift, Endian> *const *dispatch_read,
|
||||
offs_t mask_read, u8 shift_read,
|
||||
handler_entry_write<Width, AddrShift, Endian> *const *dispatch_write,
|
||||
offs_t mask_write, u8 shift_write);
|
||||
|
||||
|
||||
// getters
|
||||
address_space &space() const { return m_space; }
|
||||
|
||||
u8 read_byte(offs_t address) { address &= m_addrmask; return Width == 0 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 0, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xff); }
|
||||
u16 read_word(offs_t address) { address &= m_addrmask; return Width == 1 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffff); }
|
||||
u16 read_word(offs_t address, u16 mask) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
|
||||
u16 read_word_unaligned(offs_t address) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffff); }
|
||||
u16 read_word_unaligned(offs_t address, u16 mask) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
|
||||
u32 read_dword(offs_t address) { address &= m_addrmask; return Width == 2 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffff); }
|
||||
u32 read_dword(offs_t address, u32 mask) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
|
||||
u32 read_dword_unaligned(offs_t address) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffff); }
|
||||
u32 read_dword_unaligned(offs_t address, u32 mask) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
|
||||
u64 read_qword(offs_t address) { address &= m_addrmask; return Width == 3 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffffffffffffU); }
|
||||
u64 read_qword(offs_t address, u64 mask) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
|
||||
u64 read_qword_unaligned(offs_t address) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffffffffffffU); }
|
||||
u64 read_qword_unaligned(offs_t address, u64 mask) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
|
||||
|
||||
void write_byte(offs_t address, u8 data) { address &= m_addrmask; if (Width == 0) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 0, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xff); }
|
||||
void write_word(offs_t address, u16 data) { address &= m_addrmask; if (Width == 1) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffff); }
|
||||
void write_word(offs_t address, u16 data, u16 mask) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
|
||||
void write_word_unaligned(offs_t address, u16 data) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffff); }
|
||||
void write_word_unaligned(offs_t address, u16 data, u16 mask) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
|
||||
void write_dword(offs_t address, u32 data) { address &= m_addrmask; if (Width == 2) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffff); }
|
||||
void write_dword(offs_t address, u32 data, u32 mask) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
|
||||
void write_dword_unaligned(offs_t address, u32 data) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffff); }
|
||||
void write_dword_unaligned(offs_t address, u32 data, u32 mask) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
|
||||
void write_qword(offs_t address, u64 data) { address &= m_addrmask; if (Width == 3) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffffffffffffU); }
|
||||
void write_qword(offs_t address, u64 data, u64 mask) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
|
||||
void write_qword_unaligned(offs_t address, u64 data) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffffffffffffU); }
|
||||
void write_qword_unaligned(offs_t address, u64 data, u64 mask) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
|
||||
|
||||
private:
|
||||
address_space & m_space;
|
||||
|
||||
offs_t m_addrmask; // address mask
|
||||
|
||||
handler_entry_read<Width, AddrShift, Endian> *const *m_dispatch_read;
|
||||
handler_entry_write<Width, AddrShift, Endian> *const *m_dispatch_write;
|
||||
offs_t m_mask_read;
|
||||
offs_t m_mask_write;
|
||||
u8 m_shift_read;
|
||||
u8 m_shift_write;
|
||||
|
||||
NativeType read_native(offs_t address, NativeType mask = ~NativeType(0)) {
|
||||
return dispatch_read<Width, AddrShift, Endian>(m_mask_read, m_shift_read, address, mask, m_dispatch_read);;
|
||||
}
|
||||
|
||||
void write_native(offs_t address, NativeType data, NativeType mask = ~NativeType(0)) {
|
||||
dispatch_write<Width, AddrShift, Endian>(m_mask_write, m_shift_write, address, data, mask, m_dispatch_write);;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ======================> memory_access_cache
|
||||
|
||||
@ -1155,6 +1227,18 @@ public:
|
||||
return static_cast<memory_access_cache<Width, AddrShift, Endian> *>(create_cache());
|
||||
}
|
||||
|
||||
template<int Width, int AddrShift, int Endian> memory_access_specific<Width, AddrShift, Endian> *specific() {
|
||||
if(AddrShift != m_config.addr_shift())
|
||||
fatalerror("Requesting cache() with address shift %d while the config says %d\n", AddrShift, m_config.addr_shift());
|
||||
if(8 << Width != m_config.data_width())
|
||||
fatalerror("Requesting cache() with data width %d while the config says %d\n", 8 << Width, m_config.data_width());
|
||||
if(Endian != m_config.endianness())
|
||||
fatalerror("Requesting cache() with endianness %s while the config says %s\n",
|
||||
endianness_names[Endian], endianness_names[m_config.endianness()]);
|
||||
|
||||
return static_cast<memory_access_specific<Width, AddrShift, Endian> *>(create_specific());
|
||||
}
|
||||
|
||||
int add_change_notifier(std::function<void (read_or_write)> n);
|
||||
void remove_change_notifier(int id);
|
||||
|
||||
@ -1476,6 +1560,7 @@ public:
|
||||
protected:
|
||||
// internal helpers
|
||||
virtual void *create_cache() = 0;
|
||||
virtual void *create_specific() = 0;
|
||||
|
||||
void populate_map_entry(const address_map_entry &entry, read_or_write readorwrite);
|
||||
virtual void unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, bool quiet) = 0;
|
||||
@ -1848,4 +1933,20 @@ void memory_passthrough_handler::remove()
|
||||
m_space.remove_passthrough(m_handlers);
|
||||
}
|
||||
|
||||
template<int Width, int AddrShift, int Endian> memory_access_specific<Width, AddrShift, Endian>::memory_access_specific(address_space &space,
|
||||
handler_entry_read <Width, AddrShift, Endian> *const *dispatch_read,
|
||||
offs_t mask_read, u8 shift_read,
|
||||
handler_entry_write<Width, AddrShift, Endian> *const *dispatch_write,
|
||||
offs_t mask_write, u8 shift_write)
|
||||
: m_space(space),
|
||||
m_addrmask(space.addrmask()),
|
||||
m_dispatch_read(dispatch_read),
|
||||
m_dispatch_write(dispatch_write),
|
||||
m_mask_read(mask_read),
|
||||
m_mask_write(mask_write),
|
||||
m_shift_read(shift_read),
|
||||
m_shift_write(shift_write)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* MAME_EMU_EMUMEM_H */
|
||||
|
Loading…
Reference in New Issue
Block a user