mirror of
https://github.com/holub/mame
synced 2025-04-20 15:32:45 +03:00
i386: Improve splitting of unaligned accesses (excluding program fetches)
(nw) This entails a major code reorganization just to keep the scale of it all halfway sane.
This commit is contained in:
parent
e4f9fc8d82
commit
6fff18773b
@ -1087,6 +1087,8 @@ if (CPUS["I386"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/cpu/i386/i386.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/i386/i386.h",
|
||||
MAME_DIR .. "src/devices/cpu/i386/athlon.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/i386/athlon.h",
|
||||
MAME_DIR .. "src/devices/cpu/i386/cache.h",
|
||||
MAME_DIR .. "src/devices/cpu/i386/cycles.h",
|
||||
MAME_DIR .. "src/devices/cpu/i386/i386op16.hxx",
|
||||
@ -1094,6 +1096,7 @@ if (CPUS["I386"]~=null) then
|
||||
MAME_DIR .. "src/devices/cpu/i386/i386ops.h",
|
||||
MAME_DIR .. "src/devices/cpu/i386/i386ops.hxx",
|
||||
MAME_DIR .. "src/devices/cpu/i386/i386priv.h",
|
||||
MAME_DIR .. "src/devices/cpu/i386/i386segs.hxx",
|
||||
MAME_DIR .. "src/devices/cpu/i386/i486ops.hxx",
|
||||
MAME_DIR .. "src/devices/cpu/i386/pentops.hxx",
|
||||
MAME_DIR .. "src/devices/cpu/i386/x87ops.hxx",
|
||||
|
954
src/devices/cpu/i386/athlon.cpp
Normal file
954
src/devices/cpu/i386/athlon.cpp
Normal file
@ -0,0 +1,954 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett
|
||||
|
||||
#include "emu.h"
|
||||
#include "athlon.h"
|
||||
#include "i386priv.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(ATHLONXP, athlonxp_device, "athlonxp", "Amd Athlon XP")
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* AMD Athlon XP
|
||||
Model: Athlon XP 2400+
|
||||
Part number: AXDA2400DKV3C
|
||||
Stepping code: AIUCP
|
||||
Date code: 0240MPMW
|
||||
*/
|
||||
|
||||
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_smm_base));
|
||||
save_item(NAME(m_msr_smm_mask));
|
||||
save_item(NAME(m_msr_mtrrfix));
|
||||
save_item(NAME(m_memory_ranges_1m));
|
||||
}
|
||||
|
||||
void athlonxp_device::device_reset()
|
||||
{
|
||||
zero_state();
|
||||
|
||||
m_sreg[CS].selector = 0xf000;
|
||||
m_sreg[CS].base = 0xffff0000;
|
||||
m_sreg[CS].limit = 0xffff;
|
||||
m_sreg[CS].flags = 0x0093;
|
||||
|
||||
m_sreg[DS].base = m_sreg[ES].base = m_sreg[FS].base = m_sreg[GS].base = m_sreg[SS].base = 0x00000000;
|
||||
m_sreg[DS].limit = m_sreg[ES].limit = m_sreg[FS].limit = m_sreg[GS].limit = m_sreg[SS].limit = 0xffff;
|
||||
m_sreg[DS].flags = m_sreg[ES].flags = m_sreg[FS].flags = m_sreg[GS].flags = m_sreg[SS].flags = 0x0093;
|
||||
|
||||
m_idtr.base = 0;
|
||||
m_idtr.limit = 0x3ff;
|
||||
|
||||
m_a20_mask = ~0;
|
||||
|
||||
m_cr[0] = 0x60000010;
|
||||
m_eflags = 0x00200000;
|
||||
m_eflags_mask = 0x00277fd7; /* TODO: is this correct? */
|
||||
m_eip = 0xfff0;
|
||||
m_mxcsr = 0x1f80;
|
||||
m_smm = false;
|
||||
m_smi_latched = false;
|
||||
m_smbase = 0x30000;
|
||||
m_nmi_masked = false;
|
||||
m_nmi_latched = false;
|
||||
|
||||
x87_reset();
|
||||
|
||||
// [11:8] Family
|
||||
// [ 7:4] Model
|
||||
// [ 3:0] Stepping ID
|
||||
// Family 6, Model 8, Stepping 1
|
||||
REG32(EAX) = 0;
|
||||
REG32(EDX) = (6 << 8) | (8 << 4) | (1);
|
||||
|
||||
m_cpuid_id0 = ('h' << 24) | ('t' << 16) | ('u' << 8) | 'A'; // Auth
|
||||
m_cpuid_id1 = ('i' << 24) | ('t' << 16) | ('n' << 8) | 'e'; // enti
|
||||
m_cpuid_id2 = ('D' << 24) | ('M' << 16) | ('A' << 8) | 'c'; // cAMD
|
||||
memset(m_processor_name_string, 0, 48);
|
||||
strcpy((char *)m_processor_name_string, "AMD Athlon(tm) Processor");
|
||||
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;
|
||||
m_msr_top_mem = 1024 * 1024;
|
||||
m_msr_sys_cfg = 0;
|
||||
m_msr_smm_base = m_smbase;
|
||||
m_msr_smm_mask = 0;
|
||||
|
||||
m_cpuid_max_input_value_eax = 0x01;
|
||||
m_cpu_version = REG32(EDX);
|
||||
|
||||
// see FEATURE_FLAGS enum for bit names
|
||||
m_feature_flags = 0x0383fbff;
|
||||
|
||||
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::enter_smm()
|
||||
{
|
||||
u64 data;
|
||||
|
||||
if (m_msr_smm_mask & 1)
|
||||
data = 0x1818181818181818; // when smm is active
|
||||
else
|
||||
data = m_msr_mtrrfix[2];
|
||||
parse_mtrrfix(data, 0xa0000, 16);
|
||||
i386_device::enter_smm();
|
||||
}
|
||||
|
||||
void athlonxp_device::leave_smm()
|
||||
{
|
||||
u64 data;
|
||||
|
||||
i386_device::leave_smm();
|
||||
if (m_msr_smm_mask & 1)
|
||||
data = 0; // when smm is not active
|
||||
else
|
||||
data = m_msr_mtrrfix[2];
|
||||
parse_mtrrfix(data, 0xa0000, 16);
|
||||
}
|
||||
|
||||
void athlonxp_device::parse_mtrrfix(u64 mtrr, offs_t base, int kblock)
|
||||
{
|
||||
int nb = kblock / 4;
|
||||
int range = (int)(base >> 12); // base must never be higher than 1 megabyte
|
||||
|
||||
for (int n = 0; n < 8; n++)
|
||||
{
|
||||
uint8_t type = mtrr & 0xff;
|
||||
|
||||
for (int b = 0; b < nb; b++)
|
||||
{
|
||||
m_memory_ranges_1m[range] = type;
|
||||
range++;
|
||||
}
|
||||
mtrr = mtrr >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
int athlonxp_device::check_cacheable(offs_t address)
|
||||
{
|
||||
offs_t block;
|
||||
int disabled;
|
||||
|
||||
disabled = 0;
|
||||
if (m_cr[0] & (1 << 30))
|
||||
disabled = 128;
|
||||
if (address >= 0x100000)
|
||||
return disabled;
|
||||
block = address >> 12;
|
||||
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)
|
||||
nocache = true;
|
||||
if (mode & 1)
|
||||
nocache = true;
|
||||
if (nocache == false)
|
||||
{
|
||||
int offset = (address & 63) ^ xorle;
|
||||
data = cache.search<CacheRead>(address);
|
||||
if (data)
|
||||
return *(dt *)(data + offset);
|
||||
if (!(mode & 128))
|
||||
{
|
||||
bool dirty = cache.allocate<CacheRead>(address, &data);
|
||||
address = cache.base(address);
|
||||
if (dirty)
|
||||
{
|
||||
offs_t old_address = cache.old();
|
||||
|
||||
for (int w = 0; w < 64; w += 4)
|
||||
m->write_dword(old_address + w, *(u32 *)(data + w));
|
||||
}
|
||||
for (int r = 0; r < 64; r += 4)
|
||||
*(u32 *)(data + r) = m->read_dword(address + r);
|
||||
return *(dt *)(data + offset);
|
||||
}
|
||||
}
|
||||
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
|
||||
return m->read_dword(address);
|
||||
}
|
||||
|
||||
uint32_t athlonxp_device::program_read_cache(offs_t address, uint32_t mask)
|
||||
{
|
||||
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) & mask;
|
||||
if (!(mode & 128))
|
||||
{
|
||||
bool dirty = cache.allocate<CacheRead>(address, &data);
|
||||
address = cache.base(address);
|
||||
if (dirty)
|
||||
{
|
||||
offs_t old_address = cache.old();
|
||||
|
||||
for (int w = 0; w < 64; w += 4)
|
||||
m->write_dword(old_address + w, *(u32 *)(data + w));
|
||||
}
|
||||
for (int r = 0; r < 64; r += 4)
|
||||
*(u32 *)(data + r) = m->read_dword(address + r);
|
||||
return *(u32 *)(data + offset) & mask;
|
||||
}
|
||||
}
|
||||
if (address_mode<1>(address))
|
||||
m = m_data;
|
||||
return m->read_dword(address, mask) & mask;
|
||||
}
|
||||
|
||||
void athlonxp_device::program_write_cache(offs_t address, uint32_t data, uint32_t mask)
|
||||
{
|
||||
int mode = check_cacheable(address);
|
||||
bool nocache = false;
|
||||
address_space *m = m_program;
|
||||
u8 *dataw;
|
||||
|
||||
if ((mode & 7) == 0)
|
||||
nocache = true;
|
||||
if (mode & 1)
|
||||
nocache = true;
|
||||
if (nocache == false)
|
||||
{
|
||||
int offset = address & 63;
|
||||
dataw = cache.search<CacheWrite>(address);
|
||||
if (dataw)
|
||||
{
|
||||
*(u32 *)(dataw + offset) = (*(u32 *)(dataw + offset) & ~mask) | (data & mask);
|
||||
return;
|
||||
}
|
||||
if (!(mode & 128))
|
||||
{
|
||||
bool dirty = cache.allocate<CacheWrite>(address, &dataw);
|
||||
address = cache.base(address);
|
||||
if (dirty)
|
||||
{
|
||||
offs_t old_address = cache.old();
|
||||
|
||||
for (int w = 0; w < 64; w += 4)
|
||||
m->write_dword(old_address + w, *(u32 *)(dataw + w));
|
||||
}
|
||||
for (int r = 0; r < 64; r += 4)
|
||||
*(u32 *)(dataw + r) = m->read_dword(address + r);
|
||||
*(u32 *)(dataw + offset) = (*(u32 *)(dataw + offset) & ~mask) | (data & mask);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (address_mode<0>(address))
|
||||
m = m_data;
|
||||
m->write_dword(address, data, mask);
|
||||
}
|
||||
|
||||
void athlonxp_device::cache_writeback()
|
||||
{
|
||||
// dirty cachelines are written back to memory
|
||||
address_space *m = m_program;
|
||||
u32 base;
|
||||
u8 *data;
|
||||
|
||||
data = cache.first_dirty(base, false);
|
||||
while (data != nullptr)
|
||||
{
|
||||
for (int w = 0; w < 64; w += 4)
|
||||
m->write_dword(base + w, *(u32 *)(data + w));
|
||||
data = cache.next_dirty(base, false);
|
||||
}
|
||||
}
|
||||
|
||||
void athlonxp_device::cache_invalidate()
|
||||
{
|
||||
// dirty cachelines are not written back to memory
|
||||
cache.reset();
|
||||
}
|
||||
|
||||
void athlonxp_device::cache_clean()
|
||||
{
|
||||
// dirty cachelines are marked as clean but not written back to memory
|
||||
u32 base;
|
||||
u8 *data;
|
||||
|
||||
data = cache.first_dirty(base, true);
|
||||
while (data != nullptr)
|
||||
data = cache.next_dirty(base, true);
|
||||
}
|
||||
|
||||
uint8_t athlonxp_device::READ8PL(uint32_t ea, uint8_t privilege)
|
||||
{
|
||||
uint32_t address = ea, error;
|
||||
|
||||
if(!translate_address(privilege,TRANSLATE_READ,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
|
||||
uint8_t shift = 8 * (ea & 3);
|
||||
return program_read_cache(address - (ea & 3), uint32_t(0xff) << shift) >> shift;
|
||||
}
|
||||
|
||||
uint16_t athlonxp_device::READ16PL(uint32_t ea, uint8_t privilege)
|
||||
{
|
||||
uint16_t value;
|
||||
uint32_t address = ea, error;
|
||||
|
||||
switch (ea & 3)
|
||||
{
|
||||
case 0:
|
||||
if(!translate_address(privilege,TRANSLATE_READ,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
value = program_read_cache(address, 0x0000ffff) & 0xffff;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(!translate_address(privilege,TRANSLATE_READ,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
value = (program_read_cache(address - 1, 0x00ffff00) >> 8) & 0xffff;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if(!translate_address(privilege,TRANSLATE_READ,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
value = (program_read_cache(address - 2, 0xffff0000) >> 16) & 0xffff;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
value = READ8PL(ea, privilege);
|
||||
value |= READ8PL(ea + 1, privilege) << 8;
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t athlonxp_device::READ32PL(uint32_t ea, uint8_t privilege)
|
||||
{
|
||||
uint32_t value;
|
||||
uint32_t address = ea, error;
|
||||
|
||||
switch (ea & 3)
|
||||
{
|
||||
case 0:
|
||||
if(!translate_address(privilege,TRANSLATE_READ,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
value = program_read_cache(address, 0xffffffff);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(!translate_address(privilege,TRANSLATE_READ,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
value = program_read_cache(address - 1, 0xffffff00) >> 8;
|
||||
value |= READ8PL(ea + 3, privilege) << 24;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
value = READ16PL(ea, privilege);
|
||||
value |= READ16PL(ea + 2, privilege) << 16;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
value = READ8PL(ea, privilege);
|
||||
|
||||
address = ea + 1;
|
||||
if(!translate_address(privilege,TRANSLATE_READ,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
value |= program_read_cache(address, 0x00ffffff) << 8;
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint64_t athlonxp_device::READ64PL(uint32_t ea, uint8_t privilege)
|
||||
{
|
||||
uint64_t value;
|
||||
uint32_t address = ea, error;
|
||||
|
||||
switch (ea & 3)
|
||||
{
|
||||
case 0:
|
||||
value = READ32PL(ea, privilege);
|
||||
value |= uint64_t(READ32PL(ea + 2, privilege)) << 32;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(!translate_address(privilege,TRANSLATE_READ,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
value = program_read_cache(address - 1, 0xffffff00) >> 8;
|
||||
value |= uint64_t(READ32PL(ea + 3, privilege)) << 24;
|
||||
value |= uint64_t(READ8PL(ea + 7, privilege)) << 56;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
value = READ16PL(ea, privilege);
|
||||
value |= uint64_t(READ32PL(ea + 2, privilege)) << 16;
|
||||
value |= uint64_t(READ16PL(ea + 6, privilege)) << 48;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
value = READ8PL(ea, privilege);
|
||||
value |= uint64_t(READ32PL(ea + 1, privilege)) << 8;
|
||||
|
||||
address = ea + 5;
|
||||
if(!translate_address(privilege,TRANSLATE_READ,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
value |= uint64_t(program_read_cache(address, 0x00ffffff)) << 40;
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void athlonxp_device::WRITE8PL(uint32_t ea, uint8_t privilege, uint8_t value)
|
||||
{
|
||||
uint32_t address = ea, error;
|
||||
if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
|
||||
uint8_t shift = 8 * (ea & 3);
|
||||
program_write_cache(address - (ea & 3), value << shift, uint32_t(0xff) << shift);
|
||||
}
|
||||
|
||||
void athlonxp_device::WRITE16PL(uint32_t ea, uint8_t privilege, uint16_t value)
|
||||
{
|
||||
uint32_t address = ea, error;
|
||||
|
||||
switch(ea & 3)
|
||||
{
|
||||
case 0:
|
||||
if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
program_write_cache(address, value, 0x0000ffff);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
program_write_cache(address - 1, value << 8, 0x00ffff00);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
program_write_cache(address - 2, value << 16, 0xffff0000);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
WRITE8PL(ea, privilege, value & 0xff);
|
||||
WRITE8PL(ea + 1, privilege, (value >> 8) & 0xff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void athlonxp_device::WRITE32PL(uint32_t ea, uint8_t privilege, uint32_t value)
|
||||
{
|
||||
uint32_t address = ea, error;
|
||||
|
||||
switch(ea & 3)
|
||||
{
|
||||
case 0:
|
||||
if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
program_write_cache(address, value, 0xffffffff);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
program_write_cache(address - 1, (value << 8) & 0xffffff00, 0xffffff00);
|
||||
WRITE8PL(ea + 3, privilege, (value >> 24) & 0xff);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
WRITE16PL(ea, privilege, value & 0xffff);
|
||||
WRITE16PL(ea + 2, privilege, (value >> 16) & 0xffff);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
WRITE8PL(ea, privilege, value & 0xff);
|
||||
|
||||
address = ea + 1;
|
||||
if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
program_write_cache(address, value >> 8, 0x00ffffff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void athlonxp_device::WRITE64PL(uint32_t ea, uint8_t privilege, uint64_t value)
|
||||
{
|
||||
uint32_t address = ea, error;
|
||||
|
||||
switch(ea & 3)
|
||||
{
|
||||
case 0:
|
||||
WRITE32PL(ea, privilege, value & 0xffffffff);
|
||||
WRITE32PL(ea + 2, privilege, (value >> 32) & 0xffffffff);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
program_write_cache(address - 1, value << 8, 0xffffff00);
|
||||
WRITE32PL(ea + 3, privilege, (value >> 24) & 0xffffffff);
|
||||
WRITE8PL(ea + 7, privilege, (value >> 56) & 0xff );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
WRITE16PL(ea, privilege, value & 0xffff);
|
||||
WRITE32PL(ea + 2, privilege, (value >> 16) & 0xffffffff);
|
||||
WRITE16PL(ea + 6, privilege, (value >> 48) & 0xffff);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
WRITE8PL(ea, privilege, value & 0xff);
|
||||
WRITE32PL(ea + 1, privilege, (value >> 8) & 0xffffffff);
|
||||
|
||||
address = ea + 5;
|
||||
if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error))
|
||||
PF_THROW(error);
|
||||
|
||||
address &= m_a20_mask;
|
||||
program_write_cache(address, (value >> 40) & 0x00ffffff, 0x00ffffff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************************/
|
||||
|
||||
void athlonxp_device::opcode_cpuid()
|
||||
{
|
||||
switch (REG32(EAX))
|
||||
{
|
||||
case 0x80000000:
|
||||
{
|
||||
REG32(EAX) = 0x80000008;
|
||||
REG32(EBX) = m_cpuid_id0;
|
||||
REG32(ECX) = m_cpuid_id2;
|
||||
REG32(EDX) = m_cpuid_id1;
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80000001:
|
||||
{
|
||||
REG32(EAX) = m_cpu_version + 0x100; // family+1 as specified in AMD documentation
|
||||
REG32(EDX) = m_feature_flags;
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80000002:
|
||||
case 0x80000003:
|
||||
case 0x80000004:
|
||||
{
|
||||
int offset = (REG32(EAX) - 0x80000002) << 4;
|
||||
uint8_t *b = m_processor_name_string + offset;
|
||||
REG32(EAX) = b[ 0] + (b[ 1] << 8) + (b[ 2] << 16) + (b[ 3] << 24);
|
||||
REG32(EBX) = b[ 4] + (b[ 5] << 8) + (b[ 6] << 16) + (b[ 7] << 24);
|
||||
REG32(ECX) = b[ 8] + (b[ 9] << 8) + (b[10] << 16) + (b[11] << 24);
|
||||
REG32(EDX) = b[12] + (b[13] << 8) + (b[14] << 16) + (b[15] << 24);
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80000005:
|
||||
{
|
||||
REG32(EAX) = 0x0408FF08; // 2M/4M data tlb associativity 04 data tlb number of entries 08 instruction tlb associativity FF instruction tlb number of entries 08
|
||||
REG32(EBX) = 0xFF20FF10; // 4K data tlb associativity FF data tlb number of entries 20 instruction tlb associativity FF instruction tlb number of entries 10
|
||||
REG32(ECX) = 0x40020140; // L1 data cache size in K 40 associativity 02 lines per tag 01 line size in bytes 40
|
||||
REG32(EDX) = 0x40020140; // L1 instruction cache size in K 40 associativity 02 lines per tag 01 line size in bytes 40
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80000006:
|
||||
{
|
||||
REG32(EAX) = 0;
|
||||
REG32(EBX) = 0x41004100; // 4 100 4 100
|
||||
REG32(ECX) = 0x01008140; // L2 cache size in K 0100 associativity 8=16-way lines per tag 1 line size in bytes 40
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80000007:
|
||||
{
|
||||
REG32(EDX) = 1; // Advanced power management information, temperature sensor present
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80000008:
|
||||
{
|
||||
REG32(EAX) = 0x00002022;
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_device::opcode_cpuid();
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t athlonxp_device::opcode_rdmsr(bool &valid_msr)
|
||||
{
|
||||
uint64_t ret;
|
||||
uint32_t offset = REG32(ECX);
|
||||
|
||||
ret = 0;
|
||||
switch (offset)
|
||||
{
|
||||
case 0x10: // TSC
|
||||
break;
|
||||
case 0x1b: // APIC_BASE
|
||||
break;
|
||||
case 0xfe: // MTRRcap
|
||||
// 7-0 MTRRCapVCnt - Number of variable range MTRRs (8)
|
||||
// 8 MtrrCapFix - Fixed range MTRRs available (1)
|
||||
// 10 MtrrCapWc - Write combining memory type available (1)
|
||||
ret = 0x508;
|
||||
break;
|
||||
case 0x17b: // MCG_CTL
|
||||
break;
|
||||
case 0x200: // MTRRphysBase0-7
|
||||
case 0x202:
|
||||
case 0x204:
|
||||
case 0x206:
|
||||
case 0x208:
|
||||
case 0x20a:
|
||||
case 0x20c:
|
||||
case 0x20e:
|
||||
// 7-0 Type - Memory type for this memory range
|
||||
// 39-12 PhyBase27-0 - Base address for this memory range
|
||||
/* Format of type field:
|
||||
Bits 2-0 specify the memory type with the following encoding
|
||||
0 UC Uncacheable
|
||||
1 WC Write Combining
|
||||
4 WT Write Through
|
||||
5 WP Write Protect
|
||||
6 WB Write Back
|
||||
7 UC Uncacheable used only in PAT register
|
||||
Bit 3 WrMem 1 write to memory 0 write to mmio, present only in fixed range MTRRs
|
||||
Bit 4 RdMem 1 read from memory 0 read from mmio, present only in fixed range MTRRs
|
||||
Other bits are unused
|
||||
*/
|
||||
break;
|
||||
case 0x201: // MTRRphysMask0-7
|
||||
case 0x203:
|
||||
case 0x205:
|
||||
case 0x207:
|
||||
case 0x209:
|
||||
case 0x20b:
|
||||
case 0x20d:
|
||||
case 0x20f:
|
||||
// 11 Valid - Memory range active
|
||||
// 39-12 PhyMask27-0 - Address mask
|
||||
break;
|
||||
case 0x2ff: // MTRRdefType
|
||||
// 7-0 MtrrDefMemType - Default memory type
|
||||
// 10 MtrrDefTypeFixEn - Enable fixed range MTRRs
|
||||
// 11 MtrrDefTypeEn - Enable MTRRs
|
||||
break;
|
||||
case 0x250: // MTRRfix64K_00000
|
||||
// 8 bits for each 64k block starting at address 0
|
||||
ret = m_msr_mtrrfix[0];
|
||||
break;
|
||||
case 0x258: // MTRRfix16K_80000
|
||||
// 8 bits for each 16k block starting at address 0x80000
|
||||
ret = m_msr_mtrrfix[1];
|
||||
break;
|
||||
case 0x259: // MTRRfix16K_A0000
|
||||
// 8 bits for each 16k block starting at address 0xa0000
|
||||
ret = m_msr_mtrrfix[2];
|
||||
break;
|
||||
case 0x268: // MTRRfix4K_C0000
|
||||
case 0x269: // MTRRfix4K_C8000
|
||||
case 0x26a: // MTRRfix4K_D0000
|
||||
case 0x26b: // MTRRfix4K_D8000
|
||||
case 0x26c: // MTRRfix4K_E0000
|
||||
case 0x26d: // MTRRfix4K_E8000
|
||||
case 0x26e: // MTRRfix4K_F0000
|
||||
case 0x26f: // MTRRfix4K_F8000
|
||||
// 8 bits for each 4k block
|
||||
ret = m_msr_mtrrfix[3 + offset - 0x268];
|
||||
break;
|
||||
case 0x400: // MC0_CTL
|
||||
break;
|
||||
case 0x404: // MC1_CTL
|
||||
break;
|
||||
case 0x408: // MC2_CTL
|
||||
break;
|
||||
case 0x40c: // MC3_CTL
|
||||
break;
|
||||
case 0xC0010010: // SYS_CFG
|
||||
// 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;
|
||||
case 0xC0010016: // IORRBase0-1
|
||||
case 0xC0010018:
|
||||
// 39-12 Base27-0 - Base address for this memory range
|
||||
// 4 RdDram - Read from DRAM
|
||||
// 3 WrDram - Write to DRAM
|
||||
break;
|
||||
case 0xC0010017: // IORRMask0-1
|
||||
case 0xC0010019:
|
||||
// 39-12 Mask27-0 - Address mask
|
||||
// 11 V - Register enabled
|
||||
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;
|
||||
case 0xC0010111: // SMM_BASE
|
||||
// address of system management mode area
|
||||
ret = (uint64_t)m_msr_smm_base;
|
||||
break;
|
||||
case 0xC0010113: // SMM_MASK
|
||||
// 1 TValid - Enable TSeg SMRAM Range
|
||||
// 0 AValid - Enable ASeg SMRAM Range
|
||||
/* Access to the ASeg (a0000-bffff) depends on bit 0 of smm_mask
|
||||
if the bit is 0 use the associated fixed mtrr
|
||||
if the bit is 1
|
||||
if smm is active
|
||||
access goes to dram (wrmem 1 rdmem 1)
|
||||
if smm not active
|
||||
access goes to mmio (wrmem 0 rdmem 0) */
|
||||
ret = m_msr_smm_mask;
|
||||
break;
|
||||
}
|
||||
valid_msr = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void athlonxp_device::opcode_wrmsr(uint64_t data, bool &valid_msr)
|
||||
{
|
||||
uint32_t offset = REG32(ECX);
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0x1b: // APIC_BASE
|
||||
break;
|
||||
case 0x17b: // MCG_CTL
|
||||
break;
|
||||
case 0x200: // MTRRphysBase0-7
|
||||
case 0x201: // MTRRphysMask0-7
|
||||
case 0x202:
|
||||
case 0x203:
|
||||
case 0x204:
|
||||
case 0x205:
|
||||
case 0x206:
|
||||
case 0x207:
|
||||
case 0x208:
|
||||
case 0x209:
|
||||
case 0x20a:
|
||||
case 0x20b:
|
||||
case 0x20c:
|
||||
case 0x20d:
|
||||
case 0x20e:
|
||||
case 0x20f:
|
||||
break;
|
||||
case 0x2ff: // MTRRdefType
|
||||
break;
|
||||
case 0x250: // MTRRfix64K_00000
|
||||
m_msr_mtrrfix[0] = data;
|
||||
parse_mtrrfix(data, 0, 64);
|
||||
break;
|
||||
case 0x258: // MTRRfix16K_80000
|
||||
m_msr_mtrrfix[1] = data;
|
||||
parse_mtrrfix(data, 0x80000, 16);
|
||||
break;
|
||||
case 0x259: // MTRRfix16K_A0000
|
||||
m_msr_mtrrfix[2] = data;
|
||||
if (m_msr_smm_mask & 1)
|
||||
{
|
||||
if (m_smm)
|
||||
data = 0x1818181818181818; // when smm is active
|
||||
else
|
||||
data = 0; // when smm is not active
|
||||
}
|
||||
parse_mtrrfix(data, 0xa0000, 16);
|
||||
break;
|
||||
case 0x268: // MTRRfix4K_C0000-F8000
|
||||
case 0x269:
|
||||
case 0x26a:
|
||||
case 0x26b:
|
||||
case 0x26c:
|
||||
case 0x26d:
|
||||
case 0x26e:
|
||||
case 0x26f:
|
||||
m_msr_mtrrfix[3 + offset - 0x268] = data;
|
||||
parse_mtrrfix(data, 0xc0000 + (offset - 0x268) * 0x8000, 4);
|
||||
break;
|
||||
case 0x400: // MC0_CTL
|
||||
break;
|
||||
case 0x404: // MC1_CTL
|
||||
break;
|
||||
case 0x408: // MC2_CTL
|
||||
break;
|
||||
case 0x40c: // MC3_CTL
|
||||
break;
|
||||
case 0xC0010010: // SYS_CFG
|
||||
m_msr_sys_cfg = data;
|
||||
break;
|
||||
case 0xC0010015: // HWCR
|
||||
break;
|
||||
case 0xC0010016: // IORRBase
|
||||
case 0xC0010017: // IORRMask
|
||||
case 0xC0010018:
|
||||
case 0xC0010019:
|
||||
break;
|
||||
case 0xC001001A: // TOP_MEM
|
||||
m_msr_top_mem = (offs_t)data;
|
||||
break;
|
||||
case 0xC0010111: // SMM_BASE
|
||||
m_msr_smm_base = (offs_t)data;
|
||||
m_smbase = m_msr_smm_base;
|
||||
break;
|
||||
case 0xC0010113: // SMM_MASK
|
||||
m_msr_smm_mask = data;
|
||||
if (m_msr_smm_mask & 1)
|
||||
{
|
||||
if (m_smm)
|
||||
data = 0x1818181818181818; // when smm is active
|
||||
else
|
||||
data = 0; // when smm is not active
|
||||
}
|
||||
else
|
||||
data = m_msr_mtrrfix[2];
|
||||
parse_mtrrfix(data, 0xa0000, 16);
|
||||
break;
|
||||
}
|
||||
valid_msr = true;
|
||||
}
|
75
src/devices/cpu/i386/athlon.h
Normal file
75
src/devices/cpu/i386/athlon.h
Normal file
@ -0,0 +1,75 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett
|
||||
|
||||
#ifndef MAME_CPU_I386_ATHLON_H
|
||||
#define MAME_CPU_I386_ATHLON_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "i386.h"
|
||||
#include "cache.h"
|
||||
|
||||
class athlonxp_device : public pentium_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
athlonxp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
protected:
|
||||
virtual void opcode_cpuid() override;
|
||||
virtual uint64_t opcode_rdmsr(bool &valid_msr) override;
|
||||
virtual void opcode_wrmsr(uint64_t data, bool &valid_msr) override;
|
||||
virtual void cache_writeback() override;
|
||||
virtual void cache_invalidate() override;
|
||||
virtual void cache_clean() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void enter_smm() override;
|
||||
virtual void leave_smm() override;
|
||||
|
||||
virtual u8 mem_pr8(offs_t address) override { return opcode_read_cache<u8, NATIVE_ENDIAN_VALUE_LE_BE(0, 3)>(address); }
|
||||
virtual u16 mem_pr16(offs_t address) override { return opcode_read_cache<u16, NATIVE_ENDIAN_VALUE_LE_BE(0, 2)>(address); }
|
||||
virtual u32 mem_pr32(offs_t address) override { return opcode_read_cache<u32, 0>(address); }
|
||||
|
||||
virtual uint8_t READ8PL(uint32_t ea, uint8_t privilege) override;
|
||||
virtual uint16_t READ16PL(uint32_t ea, uint8_t privilege) override;
|
||||
virtual uint32_t READ32PL(uint32_t ea, uint8_t privilege) override;
|
||||
virtual uint64_t READ64PL(uint32_t ea, uint8_t privilege) override;
|
||||
virtual void WRITE8PL(uint32_t ea, uint8_t privilege, uint8_t value) override;
|
||||
virtual void WRITE16PL(uint32_t ea, uint8_t privilege, uint16_t value) override;
|
||||
virtual void WRITE32PL(uint32_t ea, uint8_t privilege, uint32_t value) override;
|
||||
virtual void WRITE64PL(uint32_t ea, uint8_t privilege, uint64_t value) override;
|
||||
|
||||
// device_memory_interface override
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
private:
|
||||
void parse_mtrrfix(u64 mtrr, offs_t base, int kblock);
|
||||
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);
|
||||
uint32_t program_read_cache(offs_t address, uint32_t mask);
|
||||
void program_write_cache(offs_t address, uint32_t data, uint32_t mask);
|
||||
|
||||
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;
|
||||
offs_t m_msr_smm_base;
|
||||
uint64_t m_msr_smm_mask;
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(ATHLONXP, athlonxp_device)
|
||||
|
||||
#endif // MAME_CPU_I386_ATHLON_H
|
@ -178,314 +178,3 @@ void pentium4_device::opcode_wrmsr(uint64_t data, bool &valid_msr)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void athlonxp_device::opcode_cpuid()
|
||||
{
|
||||
switch (REG32(EAX))
|
||||
{
|
||||
case 0x80000000:
|
||||
{
|
||||
REG32(EAX) = 0x80000008;
|
||||
REG32(EBX) = m_cpuid_id0;
|
||||
REG32(ECX) = m_cpuid_id2;
|
||||
REG32(EDX) = m_cpuid_id1;
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80000001:
|
||||
{
|
||||
REG32(EAX) = m_cpu_version + 0x100; // family+1 as specified in AMD documentation
|
||||
REG32(EDX) = m_feature_flags;
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80000002:
|
||||
case 0x80000003:
|
||||
case 0x80000004:
|
||||
{
|
||||
int offset = (REG32(EAX) - 0x80000002) << 4;
|
||||
uint8_t *b = m_processor_name_string + offset;
|
||||
REG32(EAX) = b[ 0] + (b[ 1] << 8) + (b[ 2] << 16) + (b[ 3] << 24);
|
||||
REG32(EBX) = b[ 4] + (b[ 5] << 8) + (b[ 6] << 16) + (b[ 7] << 24);
|
||||
REG32(ECX) = b[ 8] + (b[ 9] << 8) + (b[10] << 16) + (b[11] << 24);
|
||||
REG32(EDX) = b[12] + (b[13] << 8) + (b[14] << 16) + (b[15] << 24);
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80000005:
|
||||
{
|
||||
REG32(EAX) = 0x0408FF08; // 2M/4M data tlb associativity 04 data tlb number of entries 08 instruction tlb associativity FF instruction tlb number of entries 08
|
||||
REG32(EBX) = 0xFF20FF10; // 4K data tlb associativity FF data tlb number of entries 20 instruction tlb associativity FF instruction tlb number of entries 10
|
||||
REG32(ECX) = 0x40020140; // L1 data cache size in K 40 associativity 02 lines per tag 01 line size in bytes 40
|
||||
REG32(EDX) = 0x40020140; // L1 instruction cache size in K 40 associativity 02 lines per tag 01 line size in bytes 40
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80000006:
|
||||
{
|
||||
REG32(EAX) = 0;
|
||||
REG32(EBX) = 0x41004100; // 4 100 4 100
|
||||
REG32(ECX) = 0x01008140; // L2 cache size in K 0100 associativity 8=16-way lines per tag 1 line size in bytes 40
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80000007:
|
||||
{
|
||||
REG32(EDX) = 1; // Advanced power management information, temperature sensor present
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80000008:
|
||||
{
|
||||
REG32(EAX) = 0x00002022;
|
||||
CYCLES(CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_device::opcode_cpuid();
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t athlonxp_device::opcode_rdmsr(bool &valid_msr)
|
||||
{
|
||||
uint64_t ret;
|
||||
uint32_t offset = REG32(ECX);
|
||||
|
||||
ret = 0;
|
||||
switch (offset)
|
||||
{
|
||||
case 0x10: // TSC
|
||||
break;
|
||||
case 0x1b: // APIC_BASE
|
||||
break;
|
||||
case 0xfe: // MTRRcap
|
||||
// 7-0 MTRRCapVCnt - Number of variable range MTRRs (8)
|
||||
// 8 MtrrCapFix - Fixed range MTRRs available (1)
|
||||
// 10 MtrrCapWc - Write combining memory type available (1)
|
||||
ret = 0x508;
|
||||
break;
|
||||
case 0x17b: // MCG_CTL
|
||||
break;
|
||||
case 0x200: // MTRRphysBase0-7
|
||||
case 0x202:
|
||||
case 0x204:
|
||||
case 0x206:
|
||||
case 0x208:
|
||||
case 0x20a:
|
||||
case 0x20c:
|
||||
case 0x20e:
|
||||
// 7-0 Type - Memory type for this memory range
|
||||
// 39-12 PhyBase27-0 - Base address for this memory range
|
||||
/* Format of type field:
|
||||
Bits 2-0 specify the memory type with the following encoding
|
||||
0 UC Uncacheable
|
||||
1 WC Write Combining
|
||||
4 WT Write Through
|
||||
5 WP Write Protect
|
||||
6 WB Write Back
|
||||
7 UC Uncacheable used only in PAT register
|
||||
Bit 3 WrMem 1 write to memory 0 write to mmio, present only in fixed range MTRRs
|
||||
Bit 4 RdMem 1 read from memory 0 read from mmio, present only in fixed range MTRRs
|
||||
Other bits are unused
|
||||
*/
|
||||
break;
|
||||
case 0x201: // MTRRphysMask0-7
|
||||
case 0x203:
|
||||
case 0x205:
|
||||
case 0x207:
|
||||
case 0x209:
|
||||
case 0x20b:
|
||||
case 0x20d:
|
||||
case 0x20f:
|
||||
// 11 Valid - Memory range active
|
||||
// 39-12 PhyMask27-0 - Address mask
|
||||
break;
|
||||
case 0x2ff: // MTRRdefType
|
||||
// 7-0 MtrrDefMemType - Default memory type
|
||||
// 10 MtrrDefTypeFixEn - Enable fixed range MTRRs
|
||||
// 11 MtrrDefTypeEn - Enable MTRRs
|
||||
break;
|
||||
case 0x250: // MTRRfix64K_00000
|
||||
// 8 bits for each 64k block starting at address 0
|
||||
ret = m_msr_mtrrfix[0];
|
||||
break;
|
||||
case 0x258: // MTRRfix16K_80000
|
||||
// 8 bits for each 16k block starting at address 0x80000
|
||||
ret = m_msr_mtrrfix[1];
|
||||
break;
|
||||
case 0x259: // MTRRfix16K_A0000
|
||||
// 8 bits for each 16k block starting at address 0xa0000
|
||||
ret = m_msr_mtrrfix[2];
|
||||
break;
|
||||
case 0x268: // MTRRfix4K_C0000
|
||||
case 0x269: // MTRRfix4K_C8000
|
||||
case 0x26a: // MTRRfix4K_D0000
|
||||
case 0x26b: // MTRRfix4K_D8000
|
||||
case 0x26c: // MTRRfix4K_E0000
|
||||
case 0x26d: // MTRRfix4K_E8000
|
||||
case 0x26e: // MTRRfix4K_F0000
|
||||
case 0x26f: // MTRRfix4K_F8000
|
||||
// 8 bits for each 4k block
|
||||
ret = m_msr_mtrrfix[3 + offset - 0x268];
|
||||
break;
|
||||
case 0x400: // MC0_CTL
|
||||
break;
|
||||
case 0x404: // MC1_CTL
|
||||
break;
|
||||
case 0x408: // MC2_CTL
|
||||
break;
|
||||
case 0x40c: // MC3_CTL
|
||||
break;
|
||||
case 0xC0010010: // SYS_CFG
|
||||
// 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;
|
||||
case 0xC0010016: // IORRBase0-1
|
||||
case 0xC0010018:
|
||||
// 39-12 Base27-0 - Base address for this memory range
|
||||
// 4 RdDram - Read from DRAM
|
||||
// 3 WrDram - Write to DRAM
|
||||
break;
|
||||
case 0xC0010017: // IORRMask0-1
|
||||
case 0xC0010019:
|
||||
// 39-12 Mask27-0 - Address mask
|
||||
// 11 V - Register enabled
|
||||
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;
|
||||
case 0xC0010111: // SMM_BASE
|
||||
// address of system management mode area
|
||||
ret = (uint64_t)m_msr_smm_base;
|
||||
break;
|
||||
case 0xC0010113: // SMM_MASK
|
||||
// 1 TValid - Enable TSeg SMRAM Range
|
||||
// 0 AValid - Enable ASeg SMRAM Range
|
||||
/* Access to the ASeg (a0000-bffff) depends on bit 0 of smm_mask
|
||||
if the bit is 0 use the associated fixed mtrr
|
||||
if the bit is 1
|
||||
if smm is active
|
||||
access goes to dram (wrmem 1 rdmem 1)
|
||||
if smm not active
|
||||
access goes to mmio (wrmem 0 rdmem 0) */
|
||||
ret = m_msr_smm_mask;
|
||||
break;
|
||||
}
|
||||
valid_msr = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void athlonxp_device::opcode_wrmsr(uint64_t data, bool &valid_msr)
|
||||
{
|
||||
uint32_t offset = REG32(ECX);
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0x1b: // APIC_BASE
|
||||
break;
|
||||
case 0x17b: // MCG_CTL
|
||||
break;
|
||||
case 0x200: // MTRRphysBase0-7
|
||||
case 0x201: // MTRRphysMask0-7
|
||||
case 0x202:
|
||||
case 0x203:
|
||||
case 0x204:
|
||||
case 0x205:
|
||||
case 0x206:
|
||||
case 0x207:
|
||||
case 0x208:
|
||||
case 0x209:
|
||||
case 0x20a:
|
||||
case 0x20b:
|
||||
case 0x20c:
|
||||
case 0x20d:
|
||||
case 0x20e:
|
||||
case 0x20f:
|
||||
break;
|
||||
case 0x2ff: // MTRRdefType
|
||||
break;
|
||||
case 0x250: // MTRRfix64K_00000
|
||||
m_msr_mtrrfix[0] = data;
|
||||
parse_mtrrfix(data, 0, 64);
|
||||
break;
|
||||
case 0x258: // MTRRfix16K_80000
|
||||
m_msr_mtrrfix[1] = data;
|
||||
parse_mtrrfix(data, 0x80000, 16);
|
||||
break;
|
||||
case 0x259: // MTRRfix16K_A0000
|
||||
m_msr_mtrrfix[2] = data;
|
||||
if (m_msr_smm_mask & 1)
|
||||
{
|
||||
if (m_smm)
|
||||
data = 0x1818181818181818; // when smm is active
|
||||
else
|
||||
data = 0; // when smm is not active
|
||||
}
|
||||
parse_mtrrfix(data, 0xa0000, 16);
|
||||
break;
|
||||
case 0x268: // MTRRfix4K_C0000-F8000
|
||||
case 0x269:
|
||||
case 0x26a:
|
||||
case 0x26b:
|
||||
case 0x26c:
|
||||
case 0x26d:
|
||||
case 0x26e:
|
||||
case 0x26f:
|
||||
m_msr_mtrrfix[3 + offset - 0x268] = data;
|
||||
parse_mtrrfix(data, 0xc0000 + (offset - 0x268) * 0x8000, 4);
|
||||
break;
|
||||
case 0x400: // MC0_CTL
|
||||
break;
|
||||
case 0x404: // MC1_CTL
|
||||
break;
|
||||
case 0x408: // MC2_CTL
|
||||
break;
|
||||
case 0x40c: // MC3_CTL
|
||||
break;
|
||||
case 0xC0010010: // SYS_CFG
|
||||
m_msr_sys_cfg = data;
|
||||
break;
|
||||
case 0xC0010015: // HWCR
|
||||
break;
|
||||
case 0xC0010016: // IORRBase
|
||||
case 0xC0010017: // IORRMask
|
||||
case 0xC0010018:
|
||||
case 0xC0010019:
|
||||
break;
|
||||
case 0xC001001A: // TOP_MEM
|
||||
m_msr_top_mem = (offs_t)data;
|
||||
break;
|
||||
case 0xC0010111: // SMM_BASE
|
||||
m_msr_smm_base = (offs_t)data;
|
||||
m_smbase = m_msr_smm_base;
|
||||
break;
|
||||
case 0xC0010113: // SMM_MASK
|
||||
m_msr_smm_mask = data;
|
||||
if (m_msr_smm_mask & 1)
|
||||
{
|
||||
if (m_smm)
|
||||
data = 0x1818181818181818; // when smm is active
|
||||
else
|
||||
data = 0; // when smm is not active
|
||||
}
|
||||
else
|
||||
data = m_msr_mtrrfix[2];
|
||||
parse_mtrrfix(data, 0xa0000, 16);
|
||||
break;
|
||||
}
|
||||
valid_msr = true;
|
||||
}
|
||||
|
@ -6,339 +6,6 @@
|
||||
#ifndef __CYCLES_H__
|
||||
#define __CYCLES_H__
|
||||
|
||||
enum X86_CYCLES
|
||||
{
|
||||
CYCLES_MOV_REG_REG,
|
||||
CYCLES_MOV_REG_MEM,
|
||||
CYCLES_MOV_MEM_REG,
|
||||
CYCLES_MOV_IMM_REG,
|
||||
CYCLES_MOV_IMM_MEM,
|
||||
CYCLES_MOV_ACC_MEM,
|
||||
CYCLES_MOV_MEM_ACC,
|
||||
CYCLES_MOV_REG_SREG,
|
||||
CYCLES_MOV_MEM_SREG,
|
||||
CYCLES_MOV_SREG_REG,
|
||||
CYCLES_MOV_SREG_MEM,
|
||||
CYCLES_MOVSX_REG_REG,
|
||||
CYCLES_MOVSX_MEM_REG,
|
||||
CYCLES_MOVZX_REG_REG,
|
||||
CYCLES_MOVZX_MEM_REG,
|
||||
CYCLES_PUSH_RM,
|
||||
CYCLES_PUSH_REG_SHORT,
|
||||
CYCLES_PUSH_SREG,
|
||||
CYCLES_PUSH_IMM,
|
||||
CYCLES_PUSHA,
|
||||
CYCLES_POP_RM,
|
||||
CYCLES_POP_REG_SHORT,
|
||||
CYCLES_POP_SREG,
|
||||
CYCLES_POPA,
|
||||
CYCLES_XCHG_REG_REG,
|
||||
CYCLES_XCHG_REG_MEM,
|
||||
CYCLES_IN,
|
||||
CYCLES_IN_VAR,
|
||||
CYCLES_OUT,
|
||||
CYCLES_OUT_VAR,
|
||||
CYCLES_LEA,
|
||||
CYCLES_LDS,
|
||||
CYCLES_LES,
|
||||
CYCLES_LFS,
|
||||
CYCLES_LGS,
|
||||
CYCLES_LSS,
|
||||
CYCLES_CLC,
|
||||
CYCLES_CLD,
|
||||
CYCLES_CLI,
|
||||
CYCLES_CLTS,
|
||||
CYCLES_CMC,
|
||||
CYCLES_LAHF,
|
||||
CYCLES_POPF,
|
||||
CYCLES_PUSHF,
|
||||
CYCLES_SAHF,
|
||||
CYCLES_STC,
|
||||
CYCLES_STD,
|
||||
CYCLES_STI,
|
||||
CYCLES_ALU_REG_REG,
|
||||
CYCLES_ALU_REG_MEM,
|
||||
CYCLES_ALU_MEM_REG,
|
||||
CYCLES_ALU_IMM_REG,
|
||||
CYCLES_ALU_IMM_MEM,
|
||||
CYCLES_ALU_IMM_ACC,
|
||||
CYCLES_INC_REG,
|
||||
CYCLES_INC_MEM,
|
||||
CYCLES_DEC_REG,
|
||||
CYCLES_DEC_MEM,
|
||||
CYCLES_CMP_REG_REG,
|
||||
CYCLES_CMP_REG_MEM,
|
||||
CYCLES_CMP_MEM_REG,
|
||||
CYCLES_CMP_IMM_REG,
|
||||
CYCLES_CMP_IMM_MEM,
|
||||
CYCLES_CMP_IMM_ACC,
|
||||
CYCLES_TEST_REG_REG,
|
||||
CYCLES_TEST_REG_MEM,
|
||||
CYCLES_TEST_IMM_REG,
|
||||
CYCLES_TEST_IMM_MEM,
|
||||
CYCLES_TEST_IMM_ACC,
|
||||
CYCLES_NEG_REG,
|
||||
CYCLES_NEG_MEM,
|
||||
CYCLES_AAA,
|
||||
CYCLES_AAS,
|
||||
CYCLES_DAA,
|
||||
CYCLES_DAS,
|
||||
CYCLES_MUL8_ACC_REG,
|
||||
CYCLES_MUL8_ACC_MEM,
|
||||
CYCLES_MUL16_ACC_REG,
|
||||
CYCLES_MUL16_ACC_MEM,
|
||||
CYCLES_MUL32_ACC_REG,
|
||||
CYCLES_MUL32_ACC_MEM,
|
||||
CYCLES_IMUL8_ACC_REG,
|
||||
CYCLES_IMUL8_ACC_MEM,
|
||||
CYCLES_IMUL16_ACC_REG,
|
||||
CYCLES_IMUL16_ACC_MEM,
|
||||
CYCLES_IMUL32_ACC_REG,
|
||||
CYCLES_IMUL32_ACC_MEM,
|
||||
CYCLES_IMUL8_REG_REG,
|
||||
CYCLES_IMUL8_REG_MEM,
|
||||
CYCLES_IMUL16_REG_REG,
|
||||
CYCLES_IMUL16_REG_MEM,
|
||||
CYCLES_IMUL32_REG_REG,
|
||||
CYCLES_IMUL32_REG_MEM,
|
||||
CYCLES_IMUL16_REG_IMM_REG,
|
||||
CYCLES_IMUL16_MEM_IMM_REG,
|
||||
CYCLES_IMUL32_REG_IMM_REG,
|
||||
CYCLES_IMUL32_MEM_IMM_REG,
|
||||
CYCLES_DIV8_ACC_REG,
|
||||
CYCLES_DIV8_ACC_MEM,
|
||||
CYCLES_DIV16_ACC_REG,
|
||||
CYCLES_DIV16_ACC_MEM,
|
||||
CYCLES_DIV32_ACC_REG,
|
||||
CYCLES_DIV32_ACC_MEM,
|
||||
CYCLES_IDIV8_ACC_REG,
|
||||
CYCLES_IDIV8_ACC_MEM,
|
||||
CYCLES_IDIV16_ACC_REG,
|
||||
CYCLES_IDIV16_ACC_MEM,
|
||||
CYCLES_IDIV32_ACC_REG,
|
||||
CYCLES_IDIV32_ACC_MEM,
|
||||
CYCLES_AAD,
|
||||
CYCLES_AAM,
|
||||
CYCLES_CBW,
|
||||
CYCLES_CWD,
|
||||
CYCLES_ROTATE_REG,
|
||||
CYCLES_ROTATE_MEM,
|
||||
CYCLES_ROTATE_CARRY_REG,
|
||||
CYCLES_ROTATE_CARRY_MEM,
|
||||
CYCLES_SHLD_REG,
|
||||
CYCLES_SHLD_MEM,
|
||||
CYCLES_SHRD_REG,
|
||||
CYCLES_SHRD_MEM,
|
||||
CYCLES_NOT_REG,
|
||||
CYCLES_NOT_MEM,
|
||||
CYCLES_CMPS,
|
||||
CYCLES_INS,
|
||||
CYCLES_LODS,
|
||||
CYCLES_MOVS,
|
||||
CYCLES_OUTS,
|
||||
CYCLES_SCAS,
|
||||
CYCLES_STOS,
|
||||
CYCLES_XLAT,
|
||||
CYCLES_REP_CMPS_BASE,
|
||||
CYCLES_REP_INS_BASE,
|
||||
CYCLES_REP_LODS_BASE,
|
||||
CYCLES_REP_MOVS_BASE,
|
||||
CYCLES_REP_OUTS_BASE,
|
||||
CYCLES_REP_SCAS_BASE,
|
||||
CYCLES_REP_STOS_BASE,
|
||||
CYCLES_REP_CMPS,
|
||||
CYCLES_REP_INS,
|
||||
CYCLES_REP_LODS,
|
||||
CYCLES_REP_MOVS,
|
||||
CYCLES_REP_OUTS,
|
||||
CYCLES_REP_SCAS,
|
||||
CYCLES_REP_STOS,
|
||||
CYCLES_BSF_BASE,
|
||||
CYCLES_BSF,
|
||||
CYCLES_BSR_BASE,
|
||||
CYCLES_BSR,
|
||||
CYCLES_BT_IMM_REG,
|
||||
CYCLES_BT_IMM_MEM,
|
||||
CYCLES_BT_REG_REG,
|
||||
CYCLES_BT_REG_MEM,
|
||||
CYCLES_BTC_IMM_REG,
|
||||
CYCLES_BTC_IMM_MEM,
|
||||
CYCLES_BTC_REG_REG,
|
||||
CYCLES_BTC_REG_MEM,
|
||||
CYCLES_BTR_IMM_REG,
|
||||
CYCLES_BTR_IMM_MEM,
|
||||
CYCLES_BTR_REG_REG,
|
||||
CYCLES_BTR_REG_MEM,
|
||||
CYCLES_BTS_IMM_REG,
|
||||
CYCLES_BTS_IMM_MEM,
|
||||
CYCLES_BTS_REG_REG,
|
||||
CYCLES_BTS_REG_MEM,
|
||||
CYCLES_CALL, // E8
|
||||
CYCLES_CALL_REG, // FF /2
|
||||
CYCLES_CALL_MEM, // FF /2
|
||||
CYCLES_CALL_INTERSEG, // 9A
|
||||
CYCLES_CALL_REG_INTERSEG, // FF /3
|
||||
CYCLES_CALL_MEM_INTERSEG, // FF /3
|
||||
CYCLES_JMP_SHORT, // EB
|
||||
CYCLES_JMP, // E9
|
||||
CYCLES_JMP_REG, // FF /4
|
||||
CYCLES_JMP_MEM, // FF /4
|
||||
CYCLES_JMP_INTERSEG, // EA
|
||||
CYCLES_JMP_REG_INTERSEG, // FF /5
|
||||
CYCLES_JMP_MEM_INTERSEG, // FF /5
|
||||
CYCLES_RET, // C3
|
||||
CYCLES_RET_IMM, // C2
|
||||
CYCLES_RET_INTERSEG, // CB
|
||||
CYCLES_RET_IMM_INTERSEG, // CA
|
||||
CYCLES_JCC_DISP8,
|
||||
CYCLES_JCC_FULL_DISP,
|
||||
CYCLES_JCC_DISP8_NOBRANCH,
|
||||
CYCLES_JCC_FULL_DISP_NOBRANCH,
|
||||
CYCLES_JCXZ,
|
||||
CYCLES_JCXZ_NOBRANCH,
|
||||
CYCLES_LOOP,
|
||||
CYCLES_LOOPZ,
|
||||
CYCLES_LOOPNZ,
|
||||
CYCLES_SETCC_REG,
|
||||
CYCLES_SETCC_MEM,
|
||||
CYCLES_ENTER,
|
||||
CYCLES_LEAVE,
|
||||
CYCLES_INT,
|
||||
CYCLES_INT3,
|
||||
CYCLES_INTO_OF1,
|
||||
CYCLES_INTO_OF0,
|
||||
CYCLES_BOUND_IN_RANGE,
|
||||
CYCLES_BOUND_OUT_RANGE,
|
||||
CYCLES_IRET,
|
||||
CYCLES_HLT,
|
||||
CYCLES_MOV_REG_CR0,
|
||||
CYCLES_MOV_REG_CR2,
|
||||
CYCLES_MOV_REG_CR3,
|
||||
CYCLES_MOV_CR_REG,
|
||||
CYCLES_MOV_REG_DR0_3,
|
||||
CYCLES_MOV_REG_DR6_7,
|
||||
CYCLES_MOV_DR6_7_REG,
|
||||
CYCLES_MOV_DR0_3_REG,
|
||||
CYCLES_MOV_REG_TR6_7,
|
||||
CYCLES_MOV_TR6_7_REG,
|
||||
CYCLES_NOP,
|
||||
CYCLES_WAIT,
|
||||
CYCLES_ARPL_REG,
|
||||
CYCLES_ARPL_MEM,
|
||||
CYCLES_LAR_REG,
|
||||
CYCLES_LAR_MEM,
|
||||
CYCLES_LGDT,
|
||||
CYCLES_LIDT,
|
||||
CYCLES_LLDT_REG,
|
||||
CYCLES_LLDT_MEM,
|
||||
CYCLES_LMSW_REG,
|
||||
CYCLES_LMSW_MEM,
|
||||
CYCLES_LSL_REG,
|
||||
CYCLES_LSL_MEM,
|
||||
CYCLES_LTR_REG,
|
||||
CYCLES_LTR_MEM,
|
||||
CYCLES_SGDT,
|
||||
CYCLES_SIDT,
|
||||
CYCLES_SLDT_REG,
|
||||
CYCLES_SLDT_MEM,
|
||||
CYCLES_SMSW_REG,
|
||||
CYCLES_SMSW_MEM,
|
||||
CYCLES_STR_REG,
|
||||
CYCLES_STR_MEM,
|
||||
CYCLES_VERR_REG,
|
||||
CYCLES_VERR_MEM,
|
||||
CYCLES_VERW_REG,
|
||||
CYCLES_VERW_MEM,
|
||||
CYCLES_LOCK,
|
||||
|
||||
CYCLES_BSWAP,
|
||||
CYCLES_CMPXCHG8B,
|
||||
CYCLES_CMPXCHG,
|
||||
CYCLES_CPUID,
|
||||
CYCLES_CPUID_EAX1,
|
||||
CYCLES_INVD,
|
||||
CYCLES_XADD,
|
||||
CYCLES_RDTSC,
|
||||
CYCLES_RSM,
|
||||
CYCLES_RDMSR,
|
||||
|
||||
CYCLES_FABS,
|
||||
CYCLES_FADD,
|
||||
CYCLES_FBLD,
|
||||
CYCLES_FBSTP,
|
||||
CYCLES_FCHS,
|
||||
CYCLES_FCLEX,
|
||||
CYCLES_FCOM,
|
||||
CYCLES_FCOS,
|
||||
CYCLES_FDECSTP,
|
||||
CYCLES_FDISI,
|
||||
CYCLES_FDIV,
|
||||
CYCLES_FDIVR,
|
||||
CYCLES_FENI,
|
||||
CYCLES_FFREE,
|
||||
CYCLES_FIADD,
|
||||
CYCLES_FICOM,
|
||||
CYCLES_FIDIV,
|
||||
CYCLES_FILD,
|
||||
CYCLES_FIMUL,
|
||||
CYCLES_FINCSTP,
|
||||
CYCLES_FINIT,
|
||||
CYCLES_FIST,
|
||||
CYCLES_FISUB,
|
||||
CYCLES_FLD,
|
||||
CYCLES_FLDZ,
|
||||
CYCLES_FLD1,
|
||||
CYCLES_FLDL2E,
|
||||
CYCLES_FLDL2T,
|
||||
CYCLES_FLDLG2,
|
||||
CYCLES_FLDLN2,
|
||||
CYCLES_FLDPI,
|
||||
CYCLES_FLDCW,
|
||||
CYCLES_FLDENV,
|
||||
CYCLES_FMUL,
|
||||
CYCLES_FNOP,
|
||||
CYCLES_FPATAN,
|
||||
CYCLES_FPREM,
|
||||
CYCLES_FPREM1,
|
||||
CYCLES_FPTAN,
|
||||
CYCLES_FRNDINT,
|
||||
CYCLES_FRSTOR,
|
||||
CYCLES_FSAVE,
|
||||
CYCLES_FSCALE,
|
||||
CYCLES_FSETPM,
|
||||
CYCLES_FSIN,
|
||||
CYCLES_FSINCOS,
|
||||
CYCLES_FSQRT,
|
||||
CYCLES_FST,
|
||||
CYCLES_FSTCW,
|
||||
CYCLES_FSTENV,
|
||||
CYCLES_FSTSW,
|
||||
CYCLES_FSUB,
|
||||
CYCLES_FSUBR,
|
||||
CYCLES_FTST,
|
||||
CYCLES_FUCOM,
|
||||
CYCLES_FXAM,
|
||||
CYCLES_FXCH,
|
||||
CYCLES_FXTRACT,
|
||||
CYCLES_FYL2X,
|
||||
CYCLES_FYL2XPI,
|
||||
CYCLES_CMPXCHG_REG_REG_T,
|
||||
CYCLES_CMPXCHG_REG_REG_F,
|
||||
CYCLES_CMPXCHG_REG_MEM_T,
|
||||
CYCLES_CMPXCHG_REG_MEM_F,
|
||||
CYCLES_XADD_REG_REG,
|
||||
CYCLES_XADD_REG_MEM,
|
||||
|
||||
CYCLES_NUM_OPCODES
|
||||
};
|
||||
|
||||
|
||||
#define CPU_CYCLES_I386 0
|
||||
#define CPU_CYCLES_I486 1
|
||||
#define CPU_CYCLES_PENTIUM 2
|
||||
#define CPU_CYCLES_MEDIAGX 3
|
||||
|
||||
|
||||
struct X86_CYCLE_TABLE
|
||||
{
|
||||
X86_CYCLES op;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,6 @@
|
||||
#include "divtlb.h"
|
||||
|
||||
#include "i386dasm.h"
|
||||
#include "cache.h"
|
||||
|
||||
#define INPUT_LINE_A20 1
|
||||
#define INPUT_LINE_SMI 2
|
||||
@ -95,13 +94,6 @@ protected:
|
||||
virtual u16 mem_pr16(offs_t address) { return macache32->read_word(address); }
|
||||
virtual u32 mem_pr32(offs_t address) { return macache32->read_dword(address); }
|
||||
|
||||
virtual u8 mem_prd8(offs_t address) { return m_program->read_byte(address); }
|
||||
virtual u16 mem_prd16(offs_t address) { return m_program->read_word(address); }
|
||||
virtual u32 mem_prd32(offs_t address) { return m_program->read_dword(address); }
|
||||
virtual void mem_pwd8(offs_t address, u8 data) { m_program->write_byte(address, data); }
|
||||
virtual void mem_pwd16(offs_t address, u16 data) { m_program->write_word(address, data); }
|
||||
virtual void mem_pwd32(offs_t address, u32 data) { m_program->write_dword(address, data); }
|
||||
|
||||
address_space_config m_program_config;
|
||||
address_space_config m_io_config;
|
||||
|
||||
@ -391,27 +383,32 @@ protected:
|
||||
void register_state_i386();
|
||||
void register_state_i386_x87();
|
||||
void register_state_i386_x87_xmm();
|
||||
inline uint32_t i386_translate(int segment, uint32_t ip, int rwn);
|
||||
uint32_t i386_translate(int segment, uint32_t ip, int rwn);
|
||||
inline vtlb_entry get_permissions(uint32_t pte, int wp);
|
||||
bool i386_translate_address(int intention, offs_t *address, vtlb_entry *entry);
|
||||
inline bool translate_address(int pl, int type, uint32_t *address, uint32_t *error);
|
||||
inline void CHANGE_PC(uint32_t pc);
|
||||
bool translate_address(int pl, int type, uint32_t *address, uint32_t *error);
|
||||
void CHANGE_PC(uint32_t pc);
|
||||
inline void NEAR_BRANCH(int32_t offs);
|
||||
inline uint8_t FETCH();
|
||||
inline uint16_t FETCH16();
|
||||
inline uint32_t FETCH32();
|
||||
inline uint8_t READ8(uint32_t ea);
|
||||
inline uint16_t READ16(uint32_t ea);
|
||||
inline uint32_t READ32(uint32_t ea);
|
||||
inline uint64_t READ64(uint32_t ea);
|
||||
inline uint8_t READ8PL0(uint32_t ea);
|
||||
inline uint16_t READ16PL0(uint32_t ea);
|
||||
inline uint32_t READ32PL0(uint32_t ea);
|
||||
inline uint8_t READ8(uint32_t ea) { return READ8PL(ea, m_CPL); }
|
||||
inline uint16_t READ16(uint32_t ea) { return READ16PL(ea, m_CPL); }
|
||||
inline uint32_t READ32(uint32_t ea) { return READ32PL(ea, m_CPL); }
|
||||
inline uint64_t READ64(uint32_t ea) { return READ64PL(ea, m_CPL); }
|
||||
virtual uint8_t READ8PL(uint32_t ea, uint8_t privilege);
|
||||
virtual uint16_t READ16PL(uint32_t ea, uint8_t privilege);
|
||||
virtual uint32_t READ32PL(uint32_t ea, uint8_t privilege);
|
||||
virtual uint64_t READ64PL(uint32_t ea, uint8_t privilege);
|
||||
inline void WRITE_TEST(uint32_t ea);
|
||||
inline void WRITE8(uint32_t ea, uint8_t value);
|
||||
inline void WRITE16(uint32_t ea, uint16_t value);
|
||||
inline void WRITE32(uint32_t ea, uint32_t value);
|
||||
inline void WRITE64(uint32_t ea, uint64_t value);
|
||||
inline void WRITE8(uint32_t ea, uint8_t value) { WRITE8PL(ea, m_CPL, value); }
|
||||
inline void WRITE16(uint32_t ea, uint16_t value) { WRITE16PL(ea, m_CPL, value); }
|
||||
inline void WRITE32(uint32_t ea, uint32_t value) { WRITE32PL(ea, m_CPL, value); }
|
||||
inline void WRITE64(uint32_t ea, uint64_t value) { WRITE64PL(ea, m_CPL, value); }
|
||||
virtual void WRITE8PL(uint32_t ea, uint8_t privilege, uint8_t value);
|
||||
virtual void WRITE16PL(uint32_t ea, uint8_t privilege, uint16_t value);
|
||||
virtual void WRITE32PL(uint32_t ea, uint8_t privilege, uint32_t value);
|
||||
virtual void WRITE64PL(uint32_t ea, uint8_t privilege, uint64_t value);
|
||||
inline uint8_t OR8(uint8_t dst, uint8_t src);
|
||||
inline uint16_t OR16(uint16_t dst, uint16_t src);
|
||||
inline uint32_t OR32(uint32_t dst, uint32_t src);
|
||||
@ -445,10 +442,10 @@ protected:
|
||||
inline void check_ioperm(offs_t port, uint8_t mask);
|
||||
inline uint8_t READPORT8(offs_t port);
|
||||
inline void WRITEPORT8(offs_t port, uint8_t value);
|
||||
inline uint16_t READPORT16(offs_t port);
|
||||
inline void WRITEPORT16(offs_t port, uint16_t value);
|
||||
inline uint32_t READPORT32(offs_t port);
|
||||
inline void WRITEPORT32(offs_t port, uint32_t value);
|
||||
virtual uint16_t READPORT16(offs_t port);
|
||||
virtual void WRITEPORT16(offs_t port, uint16_t value);
|
||||
virtual uint32_t READPORT32(offs_t port);
|
||||
virtual void WRITEPORT32(offs_t port, uint32_t value);
|
||||
uint32_t i386_load_protected_mode_segment(I386_SREG *seg, uint64_t *desc );
|
||||
void i386_load_call_gate(I386_CALL_GATE *gate);
|
||||
void i386_set_descriptor_accessed(uint16_t selector);
|
||||
@ -490,7 +487,7 @@ protected:
|
||||
void i386_decode_four_byte38f3();
|
||||
uint8_t read8_debug(uint32_t ea, uint8_t *data);
|
||||
uint32_t i386_get_debug_desc(I386_SREG *seg);
|
||||
inline void CYCLES(int x);
|
||||
void CYCLES(int x);
|
||||
inline void CYCLES_RM(int modrm, int r, int m);
|
||||
uint8_t i386_shift_rotate8(uint8_t modrm, uint32_t value, uint8_t shift);
|
||||
void i386_adc_rm8_r8();
|
||||
@ -1524,6 +1521,17 @@ protected:
|
||||
virtual u8 mem_pr8(offs_t address) override { return macache16->read_byte(address); };
|
||||
virtual u16 mem_pr16(offs_t address) override { return macache16->read_word(address); };
|
||||
virtual u32 mem_pr32(offs_t address) override { return macache16->read_dword(address); };
|
||||
|
||||
virtual uint16_t READ16PL(uint32_t ea, uint8_t privilege) override;
|
||||
virtual uint32_t READ32PL(uint32_t ea, uint8_t privilege) override;
|
||||
virtual uint64_t READ64PL(uint32_t ea, uint8_t privilege) override;
|
||||
virtual void WRITE16PL(uint32_t ea, uint8_t privilege, uint16_t value) override;
|
||||
virtual void WRITE32PL(uint32_t ea, uint8_t privilege, uint32_t value) override;
|
||||
virtual void WRITE64PL(uint32_t ea, uint8_t privilege, uint64_t value) override;
|
||||
virtual uint16_t READPORT16(offs_t port) override;
|
||||
virtual void WRITEPORT16(offs_t port, uint16_t value) override;
|
||||
virtual uint32_t READPORT32(offs_t port) override;
|
||||
virtual void WRITEPORT32(offs_t port, uint32_t value) override;
|
||||
};
|
||||
|
||||
class i486_device : public i386_device
|
||||
@ -1632,64 +1640,6 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class athlonxp_device : public pentium_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
athlonxp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
protected:
|
||||
virtual void opcode_cpuid() override;
|
||||
virtual uint64_t opcode_rdmsr(bool &valid_msr) override;
|
||||
virtual void opcode_wrmsr(uint64_t data, bool &valid_msr) override;
|
||||
virtual void cache_writeback() override;
|
||||
virtual void cache_invalidate() override;
|
||||
virtual void cache_clean() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void enter_smm() override;
|
||||
virtual void leave_smm() override;
|
||||
|
||||
virtual u8 mem_pr8(offs_t address) override { return opcode_read_cache<u8, NATIVE_ENDIAN_VALUE_LE_BE(0, 3)>(address); }
|
||||
virtual u16 mem_pr16(offs_t address) override { return opcode_read_cache<u16, NATIVE_ENDIAN_VALUE_LE_BE(0, 2)>(address); }
|
||||
virtual u32 mem_pr32(offs_t address) override { return opcode_read_cache<u32, 0>(address); }
|
||||
virtual u8 mem_prd8(offs_t address) override { return program_read_cache<u8, NATIVE_ENDIAN_VALUE_LE_BE(0, 3)>(address); }
|
||||
virtual u16 mem_prd16(offs_t address) override { return program_read_cache<u16, NATIVE_ENDIAN_VALUE_LE_BE(0, 2)>(address); }
|
||||
virtual u32 mem_prd32(offs_t address) override { return program_read_cache<u32, 0>(address); }
|
||||
virtual void mem_pwd8(offs_t address, u8 data) override { program_write_cache<u8, NATIVE_ENDIAN_VALUE_LE_BE(0, 3)>(address, data); }
|
||||
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);
|
||||
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;
|
||||
offs_t m_msr_smm_base;
|
||||
uint64_t m_msr_smm_mask;
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
class pentium4_device : public pentium_device
|
||||
{
|
||||
public:
|
||||
@ -1714,7 +1664,6 @@ DECLARE_DEVICE_TYPE(MEDIAGX, mediagx_device)
|
||||
DECLARE_DEVICE_TYPE(PENTIUM_PRO, pentium_pro_device)
|
||||
DECLARE_DEVICE_TYPE(PENTIUM2, pentium2_device)
|
||||
DECLARE_DEVICE_TYPE(PENTIUM3, pentium3_device)
|
||||
DECLARE_DEVICE_TYPE(ATHLONXP, athlonxp_device)
|
||||
DECLARE_DEVICE_TYPE(PENTIUM4, pentium4_device)
|
||||
|
||||
#endif // MAME_CPU_I386_I386_H
|
||||
|
@ -1,26 +1,5 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett
|
||||
#define OP_I386 0x1
|
||||
#define OP_FPU 0x2
|
||||
#define OP_I486 0x4
|
||||
#define OP_PENTIUM 0x8
|
||||
#define OP_MMX 0x10
|
||||
#define OP_PPRO 0x20
|
||||
#define OP_SSE 0x40
|
||||
#define OP_SSE2 0x80
|
||||
#define OP_SSE3 0x100
|
||||
#define OP_CYRIX 0x8000
|
||||
#define OP_2BYTE 0x80000000
|
||||
#define OP_3BYTE66 0x40000000
|
||||
#define OP_3BYTEF2 0x20000000
|
||||
#define OP_3BYTEF3 0x10000000
|
||||
#define OP_3BYTE38 0x08000000
|
||||
#define OP_3BYTE3A 0x04000000
|
||||
#define OP_4BYTE3866 0x02000000
|
||||
#define OP_4BYTE3A66 0x01000000
|
||||
#define OP_4BYTE38F2 0x00800000
|
||||
#define OP_4BYTE3AF2 0x00400000
|
||||
#define OP_4BYTE38F3 0x00200000
|
||||
|
||||
const i386_device::X86_OPCODE i386_device::s_x86_opcode_table[] =
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
2464
src/devices/cpu/i386/i386segs.hxx
Normal file
2464
src/devices/cpu/i386/i386segs.hxx
Normal file
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/i386/i386.h"
|
||||
#include "cpu/i386/athlon.h"
|
||||
#include "machine/pci.h"
|
||||
#include "machine/pci-ide.h"
|
||||
#include "machine/intelfsh.h"
|
||||
|
Loading…
Reference in New Issue
Block a user