mirror of
https://github.com/holub/mame
synced 2025-04-23 17:00:53 +03:00
i386.cpp: athlon xp updates to memory access (nw)
Now athlon xp supports WrMem and RdMem bits in fixed range MTRRs Accesses to the first megabyte can be directed to system memory (ram) or memory-mapped-io (mmio) (the pci bus) Above 1mb accesses below the top_mem MSR address ram the others mmio At reset everyting is directed to mmio Addresss spaces work in the following way AS_PROGRAM is used for ram AS_DATA is used for mmio AS_OPCODES is used by the debugger disassembler and in memory views to look at the memory contents from the point of view of the microprocessor, including the cache Also some class members have been added to the save state
This commit is contained in:
parent
702b45b1bc
commit
03e88d6696
@ -347,6 +347,7 @@ uint64_t athlonxp_device::opcode_rdmsr(bool &valid_msr)
|
||||
// 20 MtrrVarDramEn - Enable top of memory address and I/O range registers
|
||||
// 19 MtrrFixDramModEn - Enable modification of RdDram and WrDram bits in fixed MTRRs
|
||||
// 18 MtrrFixDramEn - Enable RdDram and WrDram attributes in fixed MTRRs
|
||||
ret = m_msr_sys_cfg;
|
||||
break;
|
||||
case 0xC0010015: // HWCR
|
||||
break;
|
||||
@ -363,6 +364,7 @@ uint64_t athlonxp_device::opcode_rdmsr(bool &valid_msr)
|
||||
break;
|
||||
case 0xC001001A: // TOP_MEM
|
||||
// 39-23 TOM16-0 - Top of Memory, accesses from this address onward are directed to mmio
|
||||
ret = (uint64_t)m_msr_top_mem;
|
||||
break;
|
||||
case 0xC001001D: // TOP_MEM2
|
||||
break;
|
||||
@ -434,6 +436,7 @@ void athlonxp_device::opcode_wrmsr(uint64_t data, bool &valid_msr)
|
||||
case 0x40c: // MC3_CTL
|
||||
break;
|
||||
case 0xC0010010: // SYS_CFG
|
||||
m_msr_sys_cfg = data;
|
||||
break;
|
||||
case 0xC0010015: // HWCR
|
||||
break;
|
||||
@ -443,6 +446,7 @@ void athlonxp_device::opcode_wrmsr(uint64_t data, bool &valid_msr)
|
||||
case 0xC0010019:
|
||||
break;
|
||||
case 0xC001001A: // TOP_MEM
|
||||
m_msr_top_mem = (offs_t)data;
|
||||
break;
|
||||
case 0xC0010113: // SMM_MASK
|
||||
break;
|
||||
|
@ -133,6 +133,8 @@ pentium3_device::pentium3_device(const machine_config &mconfig, const char *tag,
|
||||
|
||||
athlonxp_device::athlonxp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pentium_device(mconfig, ATHLONXP, tag, owner, clock)
|
||||
, m_data_config("mmio", ENDIANNESS_LITTLE, 32, 32, 0, 32, 12)
|
||||
, m_opcodes_config("debugger", ENDIANNESS_LITTLE, 32, 32, 0, 32, 12)
|
||||
{
|
||||
// TODO: put correct value
|
||||
set_vtlb_dynamic_entries(256);
|
||||
@ -4692,11 +4694,22 @@ void athlonxp_device::device_start()
|
||||
{
|
||||
i386_common_init();
|
||||
register_state_i386_x87_xmm();
|
||||
m_data = &space(AS_DATA);
|
||||
m_opcodes = &space(AS_OPCODES);
|
||||
mmacache32 = m_data->cache<2, 0, ENDIANNESS_LITTLE>();
|
||||
m_opcodes->install_read_handler(0, 0xffffffff, read32_delegate(FUNC(athlonxp_device::debug_read_memory), this));
|
||||
|
||||
build_x87_opcode_table();
|
||||
build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_PPRO | OP_MMX | OP_SSE);
|
||||
m_cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM].get(); // TODO: generate own cycle tables
|
||||
m_cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM].get(); // TODO: generate own cycle tables
|
||||
|
||||
// put savestate calls here
|
||||
save_item(NAME(m_processor_name_string));
|
||||
save_item(NAME(m_msr_top_mem));
|
||||
save_item(NAME(m_msr_sys_cfg));
|
||||
save_item(NAME(m_msr_mtrrfix));
|
||||
save_item(NAME(m_memory_ranges_1m));
|
||||
}
|
||||
|
||||
void athlonxp_device::device_reset()
|
||||
@ -4745,7 +4758,9 @@ void athlonxp_device::device_reset()
|
||||
for (int n = 0; n < 11; n++)
|
||||
m_msr_mtrrfix[n] = 0;
|
||||
for (int n = 0; n < (1024 / 4); n++)
|
||||
m_memory_ranges_1m[n] = 0; // change the 0 to 6 to test the cache just after reset
|
||||
m_memory_ranges_1m[n] = 0;
|
||||
m_msr_top_mem = 1024 * 1024;
|
||||
m_msr_sys_cfg = 0;
|
||||
|
||||
m_cpuid_max_input_value_eax = 0x01;
|
||||
m_cpu_version = REG32(EDX);
|
||||
@ -4756,6 +4771,16 @@ void athlonxp_device::device_reset()
|
||||
CHANGE_PC(m_eip);
|
||||
}
|
||||
|
||||
device_memory_interface::space_config_vector athlonxp_device::memory_space_config() const
|
||||
{
|
||||
return space_config_vector{
|
||||
std::make_pair(AS_PROGRAM, &m_program_config),
|
||||
std::make_pair(AS_IO, &m_io_config),
|
||||
std::make_pair(AS_DATA, &m_data_config),
|
||||
std::make_pair(AS_OPCODES, &m_opcodes_config)
|
||||
};
|
||||
}
|
||||
|
||||
void athlonxp_device::parse_mtrrfix(u64 mtrr, offs_t base, int kblock)
|
||||
{
|
||||
int nb = kblock / 4;
|
||||
@ -4788,11 +4813,48 @@ int athlonxp_device::check_cacheable(offs_t address)
|
||||
return m_memory_ranges_1m[block] | disabled;
|
||||
}
|
||||
|
||||
template <int wr>
|
||||
int athlonxp_device::address_mode(offs_t address)
|
||||
{
|
||||
if (address >= m_msr_top_mem)
|
||||
return 1;
|
||||
if (address >= 1 * 1024 * 1024)
|
||||
return 0;
|
||||
if ((m_memory_ranges_1m[address >> 12] & (1 << (3 + wr))) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
READ32_MEMBER(athlonxp_device::debug_read_memory)
|
||||
{
|
||||
offs_t address = offset << 2;
|
||||
int mode = check_cacheable(address);
|
||||
bool nocache = false;
|
||||
address_space *m = m_program;
|
||||
u8 *data;
|
||||
|
||||
if ((mode & 7) == 0)
|
||||
nocache = true;
|
||||
if (mode & 1)
|
||||
nocache = true;
|
||||
if (nocache == false)
|
||||
{
|
||||
int offset = (address & 63);
|
||||
data = cache.search<CacheRead>(address);
|
||||
if (data)
|
||||
return *(u32 *)(data + offset);
|
||||
}
|
||||
if (address_mode<1>(address))
|
||||
m = m_data;
|
||||
return m->read_dword(address);
|
||||
}
|
||||
|
||||
template <class dt, offs_t xorle>
|
||||
dt athlonxp_device::opcode_read_cache(offs_t address)
|
||||
{
|
||||
int mode = check_cacheable(address);
|
||||
bool nocache = false;
|
||||
memory_access_cache<2, 0, ENDIANNESS_LITTLE> *m = macache32;
|
||||
u8 *data;
|
||||
|
||||
if ((mode & 7) == 0)
|
||||
@ -4814,31 +4876,21 @@ dt athlonxp_device::opcode_read_cache(offs_t address)
|
||||
offs_t old_address = cache.old();
|
||||
|
||||
for (int w = 0; w < 64; w += 4)
|
||||
macache32->write_dword(old_address + w, *(u32 *)(data + w));
|
||||
m->write_dword(old_address + w, *(u32 *)(data + w));
|
||||
}
|
||||
for (int r = 0; r < 64; r += 4)
|
||||
*(u32 *)(data + r) = macache32->read_dword(address + r);
|
||||
*(u32 *)(data + r) = m->read_dword(address + r);
|
||||
return *(dt *)(data + offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sizeof(dt) == 1)
|
||||
return macache32->read_byte(address);
|
||||
else if (sizeof(dt) == 2)
|
||||
return macache32->read_word(address);
|
||||
else
|
||||
return macache32->read_dword(address);
|
||||
}
|
||||
}
|
||||
if (address_mode<1>(address))
|
||||
m = mmacache32;
|
||||
if (sizeof(dt) == 1)
|
||||
return m->read_byte(address);
|
||||
else if (sizeof(dt) == 2)
|
||||
return m->read_word(address);
|
||||
else
|
||||
{
|
||||
if (sizeof(dt) == 1)
|
||||
return macache32->read_byte(address);
|
||||
else if (sizeof(dt) == 2)
|
||||
return macache32->read_word(address);
|
||||
else
|
||||
return macache32->read_dword(address);
|
||||
}
|
||||
return m->read_dword(address);
|
||||
}
|
||||
|
||||
template <class dt, offs_t xorle>
|
||||
@ -4846,6 +4898,7 @@ dt athlonxp_device::program_read_cache(offs_t address)
|
||||
{
|
||||
int mode = check_cacheable(address);
|
||||
bool nocache = false;
|
||||
address_space *m = m_program;
|
||||
u8 *data;
|
||||
|
||||
if ((mode & 7) == 0)
|
||||
@ -4867,31 +4920,21 @@ dt athlonxp_device::program_read_cache(offs_t address)
|
||||
offs_t old_address = cache.old();
|
||||
|
||||
for (int w = 0; w < 64; w += 4)
|
||||
m_program->write_dword(old_address + w, *(u32 *)(data + w));
|
||||
m->write_dword(old_address + w, *(u32 *)(data + w));
|
||||
}
|
||||
for (int r = 0; r < 64; r += 4)
|
||||
*(u32 *)(data + r) = m_program->read_dword(address + r);
|
||||
*(u32 *)(data + r) = m->read_dword(address + r);
|
||||
return *(dt *)(data + offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sizeof(dt) == 1)
|
||||
return m_program->read_byte(address);
|
||||
else if (sizeof(dt) == 2)
|
||||
return m_program->read_word(address);
|
||||
else
|
||||
return m_program->read_dword(address);
|
||||
}
|
||||
}
|
||||
if (address_mode<1>(address))
|
||||
m = m_data;
|
||||
if (sizeof(dt) == 1)
|
||||
return m->read_byte(address);
|
||||
else if (sizeof(dt) == 2)
|
||||
return m->read_word(address);
|
||||
else
|
||||
{
|
||||
if (sizeof(dt) == 1)
|
||||
return m_program->read_byte(address);
|
||||
else if (sizeof(dt) == 2)
|
||||
return m_program->read_word(address);
|
||||
else
|
||||
return m_program->read_dword(address);
|
||||
}
|
||||
return m->read_dword(address);
|
||||
}
|
||||
|
||||
template <class dt, offs_t xorle>
|
||||
@ -4899,6 +4942,7 @@ void athlonxp_device::program_write_cache(offs_t address, dt data)
|
||||
{
|
||||
int mode = check_cacheable(address);
|
||||
bool nocache = false;
|
||||
address_space *m = m_program;
|
||||
u8 *dataw;
|
||||
|
||||
if ((mode & 7) == 0)
|
||||
@ -4923,36 +4967,28 @@ void athlonxp_device::program_write_cache(offs_t address, dt data)
|
||||
offs_t old_address = cache.old();
|
||||
|
||||
for (int w = 0; w < 64; w += 4)
|
||||
m_program->write_dword(old_address + w, *(u32 *)(dataw + w));
|
||||
m->write_dword(old_address + w, *(u32 *)(dataw + w));
|
||||
}
|
||||
for (int r = 0; r < 64; r += 4)
|
||||
*(u32 *)(dataw + r) = m_program->read_dword(address + r);
|
||||
*(u32 *)(dataw + r) = m->read_dword(address + r);
|
||||
*(dt *)(dataw + offset) = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sizeof(dt) == 1)
|
||||
m_program->write_byte(address, data);
|
||||
else if (sizeof(dt) == 2)
|
||||
m_program->write_word(address, data);
|
||||
else
|
||||
m_program->write_dword(address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (address_mode<0>(address))
|
||||
m = m_data;
|
||||
if (sizeof(dt) == 1)
|
||||
m->write_byte(address, data);
|
||||
else if (sizeof(dt) == 2)
|
||||
m->write_word(address, data);
|
||||
else
|
||||
{
|
||||
if (sizeof(dt) == 1)
|
||||
m_program->write_byte(address, data);
|
||||
else if (sizeof(dt) == 2)
|
||||
m_program->write_word(address, data);
|
||||
else
|
||||
m_program->write_dword(address, data);
|
||||
}
|
||||
m->write_dword(address, data);
|
||||
}
|
||||
|
||||
void athlonxp_device::cache_writeback()
|
||||
{
|
||||
// dirty cachelines are written back to memory
|
||||
address_space *m = m_program;
|
||||
u32 base;
|
||||
u8 *data;
|
||||
|
||||
@ -4960,7 +4996,7 @@ void athlonxp_device::cache_writeback()
|
||||
while (data != nullptr)
|
||||
{
|
||||
for (int w = 0; w < 64; w += 4)
|
||||
m_program->write_dword(base + w, *(u32 *)(data + w));
|
||||
m->write_dword(base + w, *(u32 *)(data + w));
|
||||
data = cache.next_dirty(base, false);
|
||||
}
|
||||
}
|
||||
|
@ -1655,15 +1655,28 @@ protected:
|
||||
virtual void mem_pwd16(offs_t address, u16 data) override { program_write_cache<u16, NATIVE_ENDIAN_VALUE_LE_BE(0, 2)>(address, data); }
|
||||
virtual void mem_pwd32(offs_t address, u32 data) override { program_write_cache<u32, 0>(address, data); }
|
||||
|
||||
// device_memory_interface override
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
private:
|
||||
void parse_mtrrfix(u64 mtrr, offs_t base, int kblock);
|
||||
int check_cacheable(offs_t address);
|
||||
inline int check_cacheable(offs_t address);
|
||||
template <int wr> int address_mode(offs_t address);
|
||||
|
||||
template <class dt, offs_t xorle> dt opcode_read_cache(offs_t address);
|
||||
template <class dt, offs_t xorle> dt program_read_cache(offs_t address);
|
||||
template <class dt, offs_t xorle> void program_write_cache(offs_t address, dt data);
|
||||
|
||||
DECLARE_READ32_MEMBER(debug_read_memory);
|
||||
|
||||
address_space_config m_data_config;
|
||||
address_space *m_data;
|
||||
address_space_config m_opcodes_config;
|
||||
address_space *m_opcodes;
|
||||
memory_access_cache<2, 0, ENDIANNESS_LITTLE> *mmacache32;
|
||||
uint8_t m_processor_name_string[48];
|
||||
offs_t m_msr_top_mem;
|
||||
uint64_t m_msr_sys_cfg;
|
||||
uint64_t m_msr_mtrrfix[11];
|
||||
uint8_t m_memory_ranges_1m[1024 / 4];
|
||||
cpucache<17, 9, Cache2Way, CacheLineBytes64> cache; // 512 sets, 2 ways (cachelines per set), 64 bytes per cacheline
|
||||
|
Loading…
Reference in New Issue
Block a user