m68kmmu improvements (#4229)

* m68kmmu: PMMU improvements (nw)

- handle RW bit in ATC cache properly
- add page table walk that result in BUSERROR to ATC
- fix ptest instruction
- trap if PLOAD is called with MMU disabled on MC68851
- don't skip descriptor status update for page descriptors
- set address in ptest to last descriptor address
- add function code page table lookup
- fix ptest level report in MMU SR
- fix TT register matching (test RW bit, fix masking of bits)
- decode fc field for pload instruction
- fix decoding of pload instruction

* m68kmmu: remove unused variable (nw)

* m68kmmu: abort table search when WP is encountered

* m68kmmu: various improvements

* hp9k_3xx: call MMU buserror handler

* m68kmmu: set M bit if root descriptor is of page type

It seems like at least the 68030 sets the M bit in the MMU SR
if the root descriptor is of PAGE type, so do a logical and
between RW and the root type.

* m68kmmu: fix comment

* m68kmmu: rename descriptor types to more useful names

* m68kmmu: set type for 8 byte table descriptors

* m68kmmu: use iterative approach for table walking

* style (nw)

* fix ptest argument (nw)

* hp9k_3xx: ignore buserror if it's caused by a page table walk (nw)

* m68kmmu: initialize addr_out to 0 (nw)

Otherwise we might return an arbitrary value if ptest can't
find an entry. Shouldn't matter for the OS, but that
change makes at least the compiler happy.
This commit is contained in:
dxl 2018-11-02 15:16:49 +01:00 committed by R. Belmont
parent bc0a6560c4
commit 56fb140e00
4 changed files with 505 additions and 292 deletions

View File

@ -290,6 +290,7 @@ protected:
uint16_t m_mmu_tmp_buserror_rw; /* temporary hack: (first) bus error rw */
uint16_t m_mmu_tmp_buserror_sz; /* temporary hack: (first) bus error size` */
bool m_mmu_tablewalk; /* set when MMU walks page tables */
uint32_t m_ic_address[M68K_IC_SIZE]; /* instruction cache address data */
uint32_t m_ic_data[M68K_IC_SIZE]; /* instruction cache content data */
bool m_ic_valid[M68K_IC_SIZE]; /* instruction cache valid flags */

View File

@ -725,7 +725,7 @@ bool m68000_base_device::memory_translate(int space, int intention, offs_t &addr
}
else
{
address = pmmu_translate_addr_with_fc(address, mode, 1);
address = pmmu_translate_addr_with_fc<false, false>(address, mode, (intention & TRANSLATE_TYPE_MASK) == TRANSLATE_READ);
}
if ((m_mmu_tmp_sr & M68K_MMU_SR_INVALID) != 0) {
@ -1280,7 +1280,7 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
m_readimm16 = [this, ocache](offs_t address) -> u16 {
if (m_pmmu_enabled) {
address = pmmu_translate_addr(address);
address = pmmu_translate_addr(address, 1);
if (m_mmu_tmp_buserror_occurred)
return ~0;
}
@ -1290,7 +1290,7 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
m_read8 = [this](offs_t address) -> u8 {
if (m_pmmu_enabled) {
address = pmmu_translate_addr(address);
address = pmmu_translate_addr(address, 1);
if (m_mmu_tmp_buserror_occurred)
return ~0;
}
@ -1299,12 +1299,12 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
m_read16 = [this](offs_t address) -> u16 {
if (m_pmmu_enabled) {
u32 address0 = pmmu_translate_addr(address);
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);
u32 address1 = pmmu_translate_addr(address + 1);
u32 address1 = pmmu_translate_addr(address + 1, 1);
if (m_mmu_tmp_buserror_occurred)
return ~0;
u16 result = m_space->read_byte(address0) << 8;
@ -1319,7 +1319,7 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
m_read32 = [this](offs_t address) -> u32 {
if (m_pmmu_enabled) {
u32 address0 = pmmu_translate_addr(address);
u32 address0 = pmmu_translate_addr(address, 1);
if (m_mmu_tmp_buserror_occurred)
return ~0;
if ((address +3) & 0xfc)
@ -1328,15 +1328,15 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
else if (DWORD_ALIGNED(address)) // 0
return m_space->read_dword(address0);
else {
u32 address2 = pmmu_translate_addr(address+2);
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 address1 = pmmu_translate_addr(address+1);
u32 address3 = pmmu_translate_addr(address+3);
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;
@ -1357,7 +1357,7 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
m_write8 = [this](offs_t address, u8 data) {
if (m_pmmu_enabled) {
address = pmmu_translate_addr(address);
address = pmmu_translate_addr(address, 0);
if (m_mmu_tmp_buserror_occurred)
return;
}
@ -1366,14 +1366,14 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
m_write16 = [this](offs_t address, u16 data) {
if (m_pmmu_enabled) {
u32 address0 = pmmu_translate_addr(address);
u32 address0 = pmmu_translate_addr(address, 0);
if (m_mmu_tmp_buserror_occurred)
return;
if (WORD_ALIGNED(address)) {
m_space->write_word(address0, data);
return;
}
u32 address1 = pmmu_translate_addr(address + 1);
u32 address1 = pmmu_translate_addr(address + 1, 0);
if (m_mmu_tmp_buserror_occurred)
return;
m_space->write_byte(address0, data >> 8);
@ -1391,7 +1391,7 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
m_write32 = [this](offs_t address, u32 data) {
if (m_pmmu_enabled) {
u32 address0 = pmmu_translate_addr(address);
u32 address0 = pmmu_translate_addr(address, 0);
if (m_mmu_tmp_buserror_occurred)
return;
if ((address +3) & 0xfc) {
@ -1401,7 +1401,7 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
m_space->write_dword(address0, data);
return;
} else {
u32 address2 = pmmu_translate_addr(address+2);
u32 address2 = pmmu_translate_addr(address+2, 0);
if (m_mmu_tmp_buserror_occurred)
return;
if (WORD_ALIGNED(address)) { // 2
@ -1409,8 +1409,8 @@ void m68000_base_device::init32mmu(address_space &space, address_space &ospace)
m_space->write_word(address2, data);
return;
}
u32 address1 = pmmu_translate_addr(address+1);
u32 address3 = pmmu_translate_addr(address+3);
u32 address1 = pmmu_translate_addr(address+1, 0);
u32 address3 = pmmu_translate_addr(address+3, 0);
if (m_mmu_tmp_buserror_occurred)
return;
m_space->write_byte(address0, data >> 24);

File diff suppressed because it is too large Load Diff

View File

@ -285,6 +285,9 @@ void hp9k3xx_state::add_dio32_bus(machine_config &config)
void hp9k3xx_state::set_bus_error(uint32_t address, bool write, uint16_t mem_mask)
{
if (m_maincpu->m68851_buserror())
return;
if (m_bus_error)
return;