// license:BSD-3-Clause
// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett
#ifndef MAME_CPU_I386_I386_H
#define MAME_CPU_I386_I386_H

#pragma once

// SoftFloat 2 lacks an include guard
#ifndef softfloat_h
#define softfloat_h 1
#include "../softfloat/milieu.h"
#include "../softfloat/softfloat.h"
#endif

#include "debug/debugger.h"
#include "../divtlb.h"

#include "./i386dasm.h"
//#include "./cache.h"

#define SIG_I386_A20	1
#define SIG_I386_SMI	2
enum
{
	INPUT_LINE_IRQ = 0,
	INPUT_LINE_NMI
};

typedef u8 uint8_t;
typedef u16 uint16_t;
typedef u32 uint32_t;
typedef u64 uint64_t;

// mingw has this defined for 32-bit compiles
#undef i386

#define X86_NUM_CPUS        4

#include "../address_spacenum.h"

class VM_TEMPLATE;
class EMU;
class DEBUGGER;
class i386_device : public DEVICE
{
protected:
	outputs_t outputs_reset;
	DEVICE* d_mem;
	DEVICE* d_io;
	DEVICE* d_dma;
	DEVICE* d_pic;
	DEVICE* d_bios;
	
	DEBUGGER* d_debugger;
	DEVICE* d_program_stored, d_io_stored;

	int m_wait;
public:
	// construction/destruction
	i386_device(VM_TEMPLATE* parent_vm, EMU* parent_emu);
	~i386_device();
	virtual bool process_state(FILEIO* state_fio, bool loading);
	virtual void initialize() override;
	virtual void reset() override;
	virtual int __FASTCALL run(int clocks);
	virtual uint32_t __FASTCALL read_signal(int ch);
	virtual void __FASTCALL write_signal(int ch, uint32_t data, uint32_t mask);
	virtual void set_intr_line(bool line, bool pending, uint32_t bit);
	virtual void set_extra_clock(int cycles);
	virtual int get_extra_clock();
	uint32_t get_pc();
	uint32_t get_next_pc();
	uint32_t __FASTCALL translate_address(int segment, uint32_t offset);
//#ifdef USE_DEBUGGER
	bool is_cpu()
	{
		return true;
	}
	bool is_debugger_available()
	{
		return true;
	}
	void *get_debugger()
	{
		return d_debugger;
	}
	uint32_t get_debug_prog_addr_mask()
	{
		return 0xffffffff;
	}
	uint32_t get_debug_data_addr_mask()
	{
		return 0xffffffff;
	}
	void __FASTCALL write_debug_data8(uint32_t addr, uint32_t data);
	uint32_t __FASTCALL read_debug_data8(uint32_t addr);
	void __FASTCALL write_debug_data16(uint32_t addr, uint32_t data);
	uint32_t __FASTCALL read_debug_data16(uint32_t addr);
	void __FASTCALL write_debug_data32(uint32_t addr, uint32_t data);
	uint32_t __FASTCALL read_debug_data32(uint32_t addr);
	void __FASTCALL write_debug_io8(uint32_t addr, uint32_t data);
	uint32_t __FASTCALL read_debug_io8(uint32_t addr);
	void __FASTCALL write_debug_io16(uint32_t addr, uint32_t data);
	uint32_t __FASTCALL read_debug_io32(uint32_t addr);
	void __FASTCALL write_debug_io32(uint32_t addr, uint32_t data);
	uint32_t __FASTCALL read_debug_io16(uint32_t addr);
	bool write_debug_reg(const _TCHAR *reg, uint32_t data);
	uint32_t __FASTCALL read_debug_reg(const _TCHAR *reg);
	bool get_debug_regs_info(_TCHAR *buffer, size_t buffer_len);
	int debug_dasm_with_userdata(uint32_t pc, _TCHAR *buffer, size_t buffer_len, uint32_t userdata = 0);
	
	
	void set_address_mask(uint32_t mask)
	{
		m_a20_mask = mask;
		d_vtlb->vtlb_flush_dynamic();
	}
	uint32_t get_address_mask()
	{
		return m_a20_mask;
	}
	void set_shutdown_flag(int shutdown)
	{
		m_shutdown = (shutdown != 0) ? true : false;
	}
	int set_shutdown_flag()
	{
		return (m_shutdown) ? 1 : 0;
	}
	
	void set_context_mem(DEVICE* device)
	{
		d_mem = device;
	}
	void set_context_io(DEVICE* device)
	{
		d_io = device;
	}
	void set_context_intr(DEVICE* device)
	{
		d_pic = device;
	}
	void set_context_bios(DEVICE* device)
	{
		d_bios = device;
	}
	void set_context_dma(DEVICE* device)
	{
		d_dma = device;
	}
	void set_context_debugger(DEBUGGER* device)
	{
		d_debugger = device;
	}
	void set_reset_line(DEVICE* dev, int id, uint32_t mask)
	{
		register_output_signal(&outputs_reset, dev, id, mask);
	}
#if 0
	void set_cachable_region(uint32_t start, uint32_t end, DEVICE* dev = NULL, int type = CACHE_LINE_READ_WRITE)
	{
		cache_line *p;
		if(dev == NULL) {
		p = new cache_line(start, end, d_device, type);
		} else {
			p = new cache_line(start, end, dev, type);
		}
		if(p != NULL) {
			cache_mem.push_back(p);
		}
	}
	void delete_cachable_region(uint32_t start, uint32_t end)
	{
		for(auto pp = cache_mem.begin(); pp != cache_mem.end(); ++pp) {
			cache_line* p = *pp;
			if(p != NULL) {
				if((p->get_start_address() == start) && (p->get_end_address() == end)) {
					delete p;
					pcache_mem.erace(pp);
				}
			}
		}
	}
	void change_cache_type(uint32_t start, uint32_t end, int new_mode)
	{
		for(auto pp = cache_mem.begin(); pp != cache_mem.end(); ++pp) {
			cache_line* p = *pp;
			if(p != NULL) {
				if((p->get_start_address() == start) && (p->get_end_address() == end)) {
					p->change_access_mode(new_mode);
				}
			}
		}
	}
#endif
	// configuration helpers
#if 0
	uint64_t debug_segbase(symbol_table &table, int params, const uint64_t *param);
	uint64_t debug_seglimit(symbol_table &table, int params, const uint64_t *param);
	uint64_t debug_segofftovirt(symbol_table &table, int params, const uint64_t *param);
	uint64_t debug_virttophys(symbol_table &table, int params, const uint64_t *param);
#endif
protected:
	device_vtlb_interface* d_vtlb;
	bool process_state_segment(int num, FILEIO* state_fio, bool loading);
	bool process_state_i386(FILEIO* state_fio, bool loading);
	bool process_state_i386_x87(FILEIO* state_fio, bool loading);
	bool process_state_i386_xmm(FILEIO* state_fio, bool loading);
	
	bool bios_int_x86(int num);
	bool bios_call_far_x86(uint32_t address);
	bool bios_trap_x86(uint32_t address, int &stat);

	// device-level overrides
	//virtual void device_debug_setup() override;

	// device_execute_interface overrides
	virtual uint32_t execute_min_cycles() const override { return 1; }
	virtual uint32_t execute_max_cycles() const override { return 40; }
	virtual uint32_t execute_input_lines() const override { return 32; }

	// device_memory_interface overrides
	virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;

	// device_state_interface overrides
	//virtual void state_import(const device_state_entry &entry) override;
	//virtual void state_export(const device_state_entry &entry) override;
	//virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;

	// device_disasm_interface overrides
	//virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
	virtual int get_mode() const override;

	// routines for opcodes whose operation can vary between cpu models
	// default implementations usually just log an error message
	virtual void opcode_cpuid();
	virtual __FASTCALL uint64_t opcode_rdmsr(bool &valid_msr);
	virtual __FASTCALL void opcode_wrmsr(uint64_t data, bool &valid_msr);
	virtual void opcode_invd() {}
	virtual void opcode_wbinvd() {}

	// routine to access memory
	// ToDo: Memory cache
#if 1
	virtual u8 __FASTCALL mem_pr8(offs_t address) { return d_mem->read_data8(address); }
	virtual u16 __FASTCALL mem_pr16(offs_t address) { return d_mem->read_data16(address); }
	virtual u32 __FASTCALL mem_pr32(offs_t address) { return d_mem->read_data32(address); }

	virtual u8 __FASTCALL mem_prd8(offs_t address) { return d_mem->read_data8(address); }
	virtual u16 __FASTCALL mem_prd16(offs_t address) { return d_mem->read_data16(address); }
	virtual u32 __FASTCALL mem_prd32(offs_t address) { return d_mem->read_data32(address); }
	virtual void __FASTCALL mem_pwd8(offs_t address, u8 data) { d_mem->write_data8(address, data); }
	virtual void __FASTCALL mem_pwd16(offs_t address, u16 data) { d_mem->write_data16(address, data); }
	virtual void __FASTCALL mem_pwd32(offs_t address, u32 data) { d_mem->write_data32(address, data); }
#else
	virtual u8 mem_pr8(offs_t address) {
		int n = cache_mem.size();
		for(int i = 0; i < n; i++) {
			cache_line* p = cache_mem[i];
			if(p != NULL) {
				if(p->region_check(address)) {
					return p->read_data8w(addr, &m_wait);
				}
			}
		}
		return d_device->read_data8w(address, &m_wait);
	}
	virtual u16 mem_pr16(offs_t address) {
		int n = cache_mem.size();
		for(int i = 0; i < n; i++) {
			cache_line* p = cache_mem[i];
			if(p != NULL) {
				if(p->region_check_range(address, 2)) {
					return p->read_data16w(addr, &m_wait);
				}
			}
		}
		return d_device->read_data16w(address, &m_wait);
	}
	virtual u32 mem_pr32(offs_t address) {
		int n = cache_mem.size();
		for(int i = 0; i < n; i++) {
			cache_line* p = cache_mem[i];
			if(p != NULL) {
				if(p->region_check_range(address, 4)) {
					return p->read_data32w(addr, &m_wait);
				}
			}
		}
		return d_device->read_data32w(address, &m_wait);
	}

	virtual u8 mem_prd8(offs_t address) { return d_mem->read_data8(address); }
	virtual u16 mem_prd16(offs_t address) { return d_mem->read_data16(address); }
	virtual u32 mem_prd32(offs_t address) { return d_mem->read_data32(address); }
	virtual void mem_pwd8(offs_t address, u8 data) { d_mem->write_data8(address, data); }
	virtual void mem_pwd16(offs_t address, u16 data) { d_mem->write_data16(address, data); }
	virtual void mem_pwd32(offs_t address, u32 data) { d_mem->write_data32(address, data); }
#endif	
	//address_space_config m_mem_config;
	//address_space_config m_io_config;

	std::unique_ptr<uint8_t[]> cycle_table_rm[X86_NUM_CPUS];
	std::unique_ptr<uint8_t[]> cycle_table_pm[X86_NUM_CPUS];


	union I386_GPR {
		uint32_t d[8];
		uint16_t w[16];
		uint8_t b[32];
	};

	struct I386_SREG {
		uint16_t selector;
		uint16_t flags;
		uint32_t base;
		uint32_t limit;
		int d;      // Operand size
		bool valid;
	};

	struct I386_SYS_TABLE {
		uint32_t base;
		uint16_t limit;
	};

	struct I386_SEG_DESC {
		uint16_t segment;
		uint16_t flags;
		uint32_t base;
		uint32_t limit;
	};

	union XMM_REG {
		uint8_t  b[16];
		uint16_t w[8];
		uint32_t d[4];
		uint64_t q[2];
		int8_t   c[16];
		int16_t  s[8];
		int32_t  i[4];
		int64_t  l[2];
		float  f[4];
		double  f64[2];
	};

	union MMX_REG {
		uint32_t d[2];
		int32_t  i[2];
		uint16_t w[4];
		int16_t  s[4];
		uint8_t  b[8];
		int8_t   c[8];
		float  f[2];
		uint64_t q;
		int64_t  l;
	};

	struct I386_CALL_GATE
	{
		uint16_t segment;
		uint16_t selector;
		uint32_t offset;
		uint8_t ar;  // access rights
		uint8_t dpl;
		uint8_t dword_count;
		uint8_t present;
	};

	enum FEATURE_FLAGS : uint32_t {
		// returned in the EDX register
		FF_PBE = (u32)1 << 31, // Pend. Brk. EN.
		FF_TM = 1 << 29,       // Thermal Monitor
		FF_HTT = 1 << 28,      // Multi-threading
		FF_SS = 1 << 27,       // Self Snoop
		FF_SSE2 = 1 << 26,     // SSE2 Extensions
		FF_SSE = 1 << 25,      // SSE Extensions
		FF_FXSR = 1 << 24,     // FXSAVE/FXRSTOR
		FF_MMX = 1 << 23,      // MMX Technology
		FF_ACPI = 1 << 22,     // Thermal Monitor and Clock Ctrl
		FF_DS = 1 << 21,       // Debug Store
		FF_CLFSH = 1 << 19,    // CLFLUSH instruction
		FF_PSN = 1 << 18,      // Processor Serial Number
		FF_PSE36 = 1 << 17,    // 36 Bit Page Size Extension
		FF_PAT = 1 << 16,      // Page Attribute Table
		FF_CMOV = 1 << 15,     // Conditional Move/Compare Instruction
		FF_MCA = 1 << 14,      // Machine Check Architecture
		FF_PGE = 1 << 13,      // PTE Global Bit
		FF_MTRR = 1 << 12,     // Memory Type Range Registers
		FF_SEP = 1 << 11,      // SYSENTER and SYSEXIT
		FF_APIC = 1 << 9,      // APIC on Chip
		FF_CX8 = 1 << 8,       // CMPXCHG8B Inst.
		FF_MCE = 1 << 7,       // Machine Check Exception
		FF_PAE = 1 << 6,       // Physical Address Extensions
		FF_MSR = 1 << 5,       // RDMSR and WRMSR Support
		FF_TSC = 1 << 4,       // Time Stamp Counter
		FF_PSE = 1 << 3,       // Page Size Extensions
		FF_DE = 1 << 2,        // Debugging Extensions
		FF_VME = 1 << 1,       // Virtual-8086 Mode Enhancement
		FF_FPU = 1 << 0,       // x87 FPU on Chip
		// retuned in the ECX register
		FF_RDRAND = 1 << 30,
		FF_F16C = 1 << 29,
		FF_AVX = 1 << 28,
		FF_OSXSAVE = 1 << 27,
		FF_XSAVE = 1 << 26,
		FF_AES = 1 << 25,
		FF_TSCD = 1 << 24,     // Deadline
		FF_POPCNT = 1 << 23,
		FF_MOVBE = 1 << 22,
		FF_x2APIC = 1 << 21,
		FF_SSE4_2 = 1 << 20,   // SSE4.2
		FF_SSE4_1 = 1 << 19,   // SSE4.1
		FF_DCA = 1 << 18,      // Direct Cache Access
		FF_PCID = 1 << 17,     // Process-context Identifiers
		FF_PDCM = 1 << 15,     // Perf/Debug Capability MSR
		FF_xTPR = 1 << 14,     // Update Control
		FF_CMPXCHG16B = 1 << 13,
		FF_FMA = 1 << 12,      // Fused Multiply Add
		FF_SDBG = 1 << 11,
		FF_CNXT_ID = 1 << 10,  // L1 Context ID
		FF_SSSE3 = 1 << 9,     // SSSE3 Extensions
		FF_TM2 = 1 << 8,       // Thermal Monitor 2
		FF_EIST = 1 << 7,      // Enhanced Intel SpeedStep Technology
		FF_SMX = 1 << 6,       // Safer Mode Extensions
		FF_VMX = 1 << 5,       // Virtual Machine Extensions
		FF_DS_CPL = 1 << 4,    // CPL Qualified Debug Store
		FF_MONITOR = 1 << 3,   // MONITOR/MWAIT
		FF_DTES64 = 1 << 2,    // 64 Bit DS Area
		FF_PCLMULQDQ = 1 << 1, // Carryless Multiplication
		FF_SSE3 = 1 << 0,      // SSE3 Extensions
	};

	typedef void (i386_device::*i386_modrm_func)(uint8_t modrm);
	typedef void (i386_device::*i386_op_func)();
	struct X86_OPCODE {
		uint8_t opcode;
		uint32_t flags;
		i386_op_func handler16;
		i386_op_func handler32;
		bool lockable;
	};
	static const X86_OPCODE s_x86_opcode_table[];

	I386_GPR m_reg;
	I386_SREG m_sreg[6];
	uint32_t m_eip;
	uint32_t m_pc;
	uint32_t m_prev_eip;
	uint32_t m_eflags;
	uint32_t m_eflags_mask;
	uint8_t m_CF;
	uint8_t m_DF;
	uint8_t m_SF;
	uint8_t m_OF;
	uint8_t m_ZF;
	uint8_t m_PF;
	uint8_t m_AF;
	uint8_t m_IF;
	uint8_t m_TF;
	uint8_t m_IOP1;
	uint8_t m_IOP2;
	uint8_t m_NT;
	uint8_t m_RF;
	uint8_t m_VM;
	uint8_t m_AC;
	uint8_t m_VIF;
	uint8_t m_VIP;
	uint8_t m_ID;

	uint8_t m_CPL;  // current privilege level

	uint8_t m_performed_intersegment_jump;
	uint8_t m_delayed_interrupt_enable;

	uint32_t m_cr[5];       // Control registers
	uint32_t m_dr[8];       // Debug registers
	uint32_t m_tr[8];       // Test registers

	I386_SYS_TABLE m_gdtr;    // Global Descriptor Table Register
	I386_SYS_TABLE m_idtr;    // Interrupt Descriptor Table Register
	I386_SEG_DESC m_task;     // Task register
	I386_SEG_DESC m_ldtr;     // Local Descriptor Table Register

	uint8_t m_ext;  // external interrupt

	int m_halted;
	int m_busreq;

	int m_operand_size;
	int m_xmm_operand_size;
	int m_address_size;
	int m_operand_prefix;
	int m_address_prefix;

	int m_segment_prefix;
	int m_segment_override;

	int m_cycles;
	int m_base_cycles;
	int64_t total_cycles;
	int64_t prev_total_cycles;
	int extra_cycles;
	
	uint8_t m_opcode;

	uint8_t m_irq_state;
	uint32_t m_a20_mask;
	bool m_shutdown;
	// ToDo: Memory Cache.
	//memory_access_cache<1, 0, ENDIANNESS_LITTLE> *macache16;
	//memory_access_cache<2, 0, ENDIANNESS_LITTLE> *macache32;
//	std::vector<cache_line *>cache_data; 

	int m_cpuid_max_input_value_eax; // Highest CPUID standard function available
	uint32_t m_cpuid_id0, m_cpuid_id1, m_cpuid_id2;
	uint32_t m_cpu_version;
	uint32_t m_feature_flags;
	uint64_t m_tsc;
	uint64_t m_perfctr[2];

	// FPU
	floatx80 m_x87_reg[8];

	uint16_t m_x87_cw;
	uint16_t m_x87_sw;
	uint16_t m_x87_tw;
	uint64_t m_x87_data_ptr;
	uint64_t m_x87_inst_ptr;
	uint16_t m_x87_opcode;

	i386_modrm_func m_opcode_table_x87_d8[256];
	i386_modrm_func m_opcode_table_x87_d9[256];
	i386_modrm_func m_opcode_table_x87_da[256];
	i386_modrm_func m_opcode_table_x87_db[256];
	i386_modrm_func m_opcode_table_x87_dc[256];
	i386_modrm_func m_opcode_table_x87_dd[256];
	i386_modrm_func m_opcode_table_x87_de[256];
	i386_modrm_func m_opcode_table_x87_df[256];

	// SSE
	XMM_REG m_sse_reg[8];
	uint32_t m_mxcsr;

	i386_op_func m_opcode_table1_16[256];
	i386_op_func m_opcode_table1_32[256];
	i386_op_func m_opcode_table2_16[256];
	i386_op_func m_opcode_table2_32[256];
	i386_op_func m_opcode_table338_16[256];
	i386_op_func m_opcode_table338_32[256];
	i386_op_func m_opcode_table33a_16[256];
	i386_op_func m_opcode_table33a_32[256];
	i386_op_func m_opcode_table366_16[256];
	i386_op_func m_opcode_table366_32[256];
	i386_op_func m_opcode_table3f2_16[256];
	i386_op_func m_opcode_table3f2_32[256];
	i386_op_func m_opcode_table3f3_16[256];
	i386_op_func m_opcode_table3f3_32[256];
	i386_op_func m_opcode_table46638_16[256];
	i386_op_func m_opcode_table46638_32[256];
	i386_op_func m_opcode_table4f238_16[256];
	i386_op_func m_opcode_table4f238_32[256];
	i386_op_func m_opcode_table4f338_16[256];
	i386_op_func m_opcode_table4f338_32[256];
	i386_op_func m_opcode_table4663a_16[256];
	i386_op_func m_opcode_table4663a_32[256];
	i386_op_func m_opcode_table4f23a_16[256];
	i386_op_func m_opcode_table4f23a_32[256];

	bool m_lock_table[2][256];

	uint8_t *m_cycle_table_pm;
	uint8_t *m_cycle_table_rm;

	bool m_smm;
	bool m_smi;
	bool m_smi_latched;
	bool m_nmi_masked;
	bool m_nmi_latched;
	uint32_t m_smbase;
	DEVICE* m_smiact;
	DEVICE* m_ferr_handler;
	bool m_smiact_enabled;
	int  m_ferr_err_value;
	bool m_lock;

	// bytes in current opcode, debug only
	uint8_t m_opcode_bytes[16];
	uint32_t m_opcode_pc;
	int m_opcode_bytes_length;

	uint64_t m_debugger_temp;

	void register_state_i386();
	void register_state_i386_x87();
	void register_state_i386_x87_xmm();
	inline uint32_t __FASTCALL i386_translate(int segment, uint32_t ip, int rwn);
	inline vtlb_entry __FASTCALL get_permissions(uint32_t pte, int wp);
	bool __FASTCALL i386_translate_address(int intention, offs_t *address, vtlb_entry *entry);
	inline bool __FASTCALL translate_address(int pl, int type, uint32_t *address, uint32_t *error);
	inline void __FASTCALL CHANGE_PC(uint32_t pc);
	inline void __FASTCALL NEAR_BRANCH(int32_t offs);
	inline uint8_t FETCH();
	inline uint16_t FETCH16();
	inline uint32_t FETCH32();
	inline uint8_t __FASTCALL READ8(uint32_t ea);
	inline uint16_t __FASTCALL READ16(uint32_t ea);
	inline uint32_t __FASTCALL READ32(uint32_t ea);
	inline uint64_t __FASTCALL READ64(uint32_t ea);
	inline uint8_t __FASTCALL READ8PL0(uint32_t ea);
	inline uint16_t __FASTCALL READ16PL0(uint32_t ea);
	inline uint32_t __FASTCALL READ32PL0(uint32_t ea);
	inline void __FASTCALL WRITE_TEST(uint32_t ea);
	inline void __FASTCALL WRITE8(uint32_t ea, uint8_t value);
	inline void __FASTCALL WRITE16(uint32_t ea, uint16_t value);
	inline void __FASTCALL WRITE32(uint32_t ea, uint32_t value);
	inline void __FASTCALL WRITE64(uint32_t ea, uint64_t value);
	inline uint8_t __FASTCALL OR8(uint8_t dst, uint8_t src);
	inline uint16_t __FASTCALL OR16(uint16_t dst, uint16_t src);
	inline uint32_t __FASTCALL OR32(uint32_t dst, uint32_t src);
	inline uint8_t __FASTCALL AND8(uint8_t dst, uint8_t src);
	inline uint16_t __FASTCALL AND16(uint16_t dst, uint16_t src);
	inline uint32_t __FASTCALL AND32(uint32_t dst, uint32_t src);
	inline uint8_t __FASTCALL XOR8(uint8_t dst, uint8_t src);
	inline uint16_t __FASTCALL XOR16(uint16_t dst, uint16_t src);
	inline uint32_t __FASTCALL XOR32(uint32_t dst, uint32_t src);
	inline uint8_t __FASTCALL SBB8(uint8_t dst, uint8_t src, uint8_t b);
	inline uint16_t __FASTCALL SBB16(uint16_t dst, uint16_t src, uint16_t b);
	inline uint32_t __FASTCALL SBB32(uint32_t dst, uint32_t src, uint32_t b);
	inline uint8_t __FASTCALL ADC8(uint8_t dst, uint8_t src, uint8_t c);
	inline uint16_t __FASTCALL ADC16(uint16_t dst, uint16_t src, uint8_t c);
	inline uint32_t __FASTCALL ADC32(uint32_t dst, uint32_t src, uint32_t c);
	inline uint8_t __FASTCALL INC8(uint8_t dst);
	inline uint16_t __FASTCALL INC16(uint16_t dst);
	inline uint32_t __FASTCALL INC32(uint32_t dst);
	inline uint8_t DEC8(uint8_t dst);
	inline uint16_t DEC16(uint16_t dst);
	inline uint32_t DEC32(uint32_t dst);
	inline void __FASTCALL PUSH16(uint16_t value);
	inline void __FASTCALL PUSH32(uint32_t value);
	inline void __FASTCALL PUSH32SEG(uint32_t value);
	inline void __FASTCALL PUSH8(uint8_t value);
	inline uint8_t POP8();
	inline uint16_t POP16();
	inline uint32_t POP32();
	inline void __FASTCALL BUMP_SI(int adjustment);
	inline void __FASTCALL BUMP_DI(int adjustment);
	inline void __FASTCALL check_ioperm(offs_t port, uint8_t mask);
	inline uint8_t __FASTCALL READPORT8(offs_t port);
	inline void __FASTCALL WRITEPORT8(offs_t port, uint8_t value);
	inline uint16_t __FASTCALL READPORT16(offs_t port);
	inline void __FASTCALL WRITEPORT16(offs_t port, uint16_t value);
	inline uint32_t __FASTCALL READPORT32(offs_t port);
	inline void WRITEPORT32(offs_t port, uint32_t value);
	uint32_t __FASTCALL i386_load_protected_mode_segment(I386_SREG *seg, uint64_t *desc );
	void __FASTCALL i386_load_call_gate(I386_CALL_GATE *gate);
	void __FASTCALL i386_set_descriptor_accessed(uint16_t selector);
	void __FASTCALL i386_load_segment_descriptor(int segment );
	uint32_t __FASTCALL i386_get_stack_segment(uint8_t privilege);
	uint32_t __FASTCALL i386_get_stack_ptr(uint8_t privilege);
	uint32_t get_flags() const;
	void __FASTCALL set_flags(uint32_t f );
	void __FASTCALL sib_byte(uint8_t mod, uint32_t* out_ea, uint8_t* out_segment);
	void __FASTCALL modrm_to_EA(uint8_t mod_rm, uint32_t* out_ea, uint8_t* out_segment);
	uint32_t __FASTCALL GetNonTranslatedEA(uint8_t modrm,uint8_t *seg);
	uint32_t __FASTCALL GetEA(uint8_t modrm, int rwn);
	void __FASTCALL i386_check_sreg_validity(int reg);
	int __FASTCALL i386_limit_check(int seg, uint32_t offset);
	void __FASTCALL i386_sreg_load(uint16_t selector, uint8_t reg, bool *fault);
	void i386_trap(int irq, int irq_gate, int trap_level);
	void i386_trap_with_error(int irq, int irq_gate, int trap_level, uint32_t error);
	void i286_task_switch(uint16_t selector, uint8_t nested);
	void i386_task_switch(uint16_t selector, uint8_t nested);
	void i386_check_irq_line();
	void i386_protected_mode_jump(uint16_t seg, uint32_t off, int indirect, int operand32);
	void i386_protected_mode_call(uint16_t seg, uint32_t off, int indirect, int operand32);
	void i386_protected_mode_retf(uint8_t count, uint8_t operand32);
	void i386_protected_mode_iret(int operand32);
	void build_cycle_table();
	void report_invalid_opcode();
	void __FASTCALL report_invalid_modrm(const char* opcode, uint8_t modrm);
	void i386_decode_opcode();
	void i386_decode_two_byte();
	void i386_decode_three_byte38();
	void i386_decode_three_byte3a();
	void i386_decode_three_byte66();
	void i386_decode_three_bytef2();
	void i386_decode_three_bytef3();
	void i386_decode_four_byte3866();
	void i386_decode_four_byte3a66();
	void i386_decode_four_byte38f2();
	void i386_decode_four_byte3af2();
	void i386_decode_four_byte38f3();
	uint8_t __FASTCALL read8_debug(uint32_t ea, uint8_t *data);
	//uint32_t i386_get_debug_desc(I386_SREG *seg);
	inline void __FASTCALL CYCLES(int x);
	inline void __FASTCALL CYCLES_RM(int modrm, int r, int m);
	uint8_t __FASTCALL i386_shift_rotate8(uint8_t modrm, uint32_t value, uint8_t shift);
	void i386_adc_rm8_r8();
	void i386_adc_r8_rm8();
	void i386_adc_al_i8();
	void i386_add_rm8_r8();
	void i386_add_r8_rm8();
	void i386_add_al_i8();
	void i386_and_rm8_r8();
	void i386_and_r8_rm8();
	void i386_and_al_i8();
	void i386_clc();
	void i386_cld();
	void i386_cli();
	void i386_cmc();
	void i386_cmp_rm8_r8();
	void i386_cmp_r8_rm8();
	void i386_cmp_al_i8();
	void i386_cmpsb();
	void i386_in_al_i8();
	void i386_in_al_dx();
	void i386_ja_rel8();
	void i386_jbe_rel8();
	void i386_jc_rel8();
	void i386_jg_rel8();
	void i386_jge_rel8();
	void i386_jl_rel8();
	void i386_jle_rel8();
	void i386_jnc_rel8();
	void i386_jno_rel8();
	void i386_jnp_rel8();
	void i386_jns_rel8();
	void i386_jnz_rel8();
	void i386_jo_rel8();
	void i386_jp_rel8();
	void i386_js_rel8();
	void i386_jz_rel8();
	void i386_jmp_rel8();
	void i386_lahf();
	void i386_lodsb();
	void i386_mov_rm8_r8();
	void i386_mov_r8_rm8();
	void i386_mov_rm8_i8();
	void i386_mov_r32_cr();
	void i386_mov_r32_dr();
	void i386_mov_cr_r32();
	void i386_mov_dr_r32();
	void i386_mov_al_m8();
	void i386_mov_m8_al();
	void i386_mov_rm16_sreg();
	void i386_mov_sreg_rm16();
	void i386_mov_al_i8();
	void i386_mov_cl_i8();
	void i386_mov_dl_i8();
	void i386_mov_bl_i8();
	void i386_mov_ah_i8();
	void i386_mov_ch_i8();
	void i386_mov_dh_i8();
	void i386_mov_bh_i8();
	void i386_movsb();
	void i386_or_rm8_r8();
	void i386_or_r8_rm8();
	void i386_or_al_i8();
	void i386_out_al_i8();
	void i386_out_al_dx();
	void i386_arpl();
	void i386_push_i8();
	void __FASTCALL i386_ins_generic(int size);
	void i386_insb();
	void i386_insw();
	void i386_insd();
	void __FASTCALL i386_outs_generic(int size);
	void i386_outsb();
	void i386_outsw();
	void i386_outsd();
	void __FASTCALL i386_repeat(int invert_flag);
	void i386_rep();
	void i386_repne();
	void i386_sahf();
	void i386_sbb_rm8_r8();
	void i386_sbb_r8_rm8();
	void i386_sbb_al_i8();
	void i386_scasb();
	void i386_setalc();
	void i386_seta_rm8();
	void i386_setbe_rm8();
	void i386_setc_rm8();
	void i386_setg_rm8();
	void i386_setge_rm8();
	void i386_setl_rm8();
	void i386_setle_rm8();
	void i386_setnc_rm8();
	void i386_setno_rm8();
	void i386_setnp_rm8();
	void i386_setns_rm8();
	void i386_setnz_rm8();
	void i386_seto_rm8();
	void i386_setp_rm8();
	void i386_sets_rm8();
	void i386_setz_rm8();
	void i386_stc();
	void i386_std();
	void i386_sti();
	void i386_stosb();
	void i386_sub_rm8_r8();
	void i386_sub_r8_rm8();
	void i386_sub_al_i8();
	void i386_test_al_i8();
	void i386_test_rm8_r8();
	void i386_xchg_r8_rm8();
	void i386_xor_rm8_r8();
	void i386_xor_r8_rm8();
	void i386_xor_al_i8();
	void i386_group80_8();
	void i386_groupC0_8();
	void i386_groupD0_8();
	void i386_groupD2_8();
	void i386_groupF6_8();
	void i386_groupFE_8();
	void i386_segment_CS();
	void i386_segment_DS();
	void i386_segment_ES();
	void i386_segment_FS();
	void i386_segment_GS();
	void i386_segment_SS();
	void i386_operand_size();
	void i386_address_size();
	void i386_nop();
	void i386_int3();
	void i386_int();
	void i386_into();
	void i386_escape();
	void i386_hlt();
	void __FASTCALL i386_decimal_adjust(int direction);
	void i386_daa();
	void i386_das();
	void i386_aaa();
	void i386_aas();
	void i386_aad();
	void i386_aam();
	void i386_clts();
	void i386_wait();
	void i386_lock();
	void i386_mov_r32_tr();
	void i386_mov_tr_r32();
	void i386_loadall();
	void i386_invalid();
	void i386_xlat();
	uint16_t __FASTCALL i386_shift_rotate16(uint8_t modrm, uint32_t value, uint8_t shift);
	void i386_adc_rm16_r16();
	void i386_adc_r16_rm16();
	void i386_adc_ax_i16();
	void i386_add_rm16_r16();
	void i386_add_r16_rm16();
	void i386_add_ax_i16();
	void i386_and_rm16_r16();
	void i386_and_r16_rm16();
	void i386_and_ax_i16();
	void i386_bsf_r16_rm16();
	void i386_bsr_r16_rm16();
	void i386_bt_rm16_r16();
	void i386_btc_rm16_r16();
	void i386_btr_rm16_r16();
	void i386_bts_rm16_r16();
	void i386_call_abs16();
	void i386_call_rel16();
	void i386_cbw();
	void i386_cmp_rm16_r16();
	void i386_cmp_r16_rm16();
	void i386_cmp_ax_i16();
	void i386_cmpsw();
	void i386_cwd();
	void i386_dec_ax();
	void i386_dec_cx();
	void i386_dec_dx();
	void i386_dec_bx();
	void i386_dec_sp();
	void i386_dec_bp();
	void i386_dec_si();
	void i386_dec_di();
	void i386_imul_r16_rm16();
	void i386_imul_r16_rm16_i16();
	void i386_imul_r16_rm16_i8();
	void i386_in_ax_i8();
	void i386_in_ax_dx();
	void i386_inc_ax();
	void i386_inc_cx();
	void i386_inc_dx();
	void i386_inc_bx();
	void i386_inc_sp();
	void i386_inc_bp();
	void i386_inc_si();
	void i386_inc_di();
	void i386_iret16();
	void i386_ja_rel16();
	void i386_jbe_rel16();
	void i386_jc_rel16();
	void i386_jg_rel16();
	void i386_jge_rel16();
	void i386_jl_rel16();
	void i386_jle_rel16();
	void i386_jnc_rel16();
	void i386_jno_rel16();
	void i386_jnp_rel16();
	void i386_jns_rel16();
	void i386_jnz_rel16();
	void i386_jo_rel16();
	void i386_jp_rel16();
	void i386_js_rel16();
	void i386_jz_rel16();
	void i386_jcxz16();
	void i386_jmp_rel16();
	void i386_jmp_abs16();
	void i386_lea16();
	void i386_enter16();
	void i386_leave16();
	void i386_lodsw();
	void i386_loop16();
	void i386_loopne16();
	void i386_loopz16();
	void i386_mov_rm16_r16();
	void i386_mov_r16_rm16();
	void i386_mov_rm16_i16();
	void i386_mov_ax_m16();
	void i386_mov_m16_ax();
	void i386_mov_ax_i16();
	void i386_mov_cx_i16();
	void i386_mov_dx_i16();
	void i386_mov_bx_i16();
	void i386_mov_sp_i16();
	void i386_mov_bp_i16();
	void i386_mov_si_i16();
	void i386_mov_di_i16();
	void i386_movsw();
	void i386_movsx_r16_rm8();
	void i386_movzx_r16_rm8();
	void i386_or_rm16_r16();
	void i386_or_r16_rm16();
	void i386_or_ax_i16();
	void i386_out_ax_i8();
	void i386_out_ax_dx();
	void i386_pop_ax();
	void i386_pop_cx();
	void i386_pop_dx();
	void i386_pop_bx();
	void i386_pop_sp();
	void i386_pop_bp();
	void i386_pop_si();
	void i386_pop_di();
	bool __FASTCALL i386_pop_seg16(int segment);
	void i386_pop_ds16();
	void i386_pop_es16();
	void i386_pop_fs16();
	void i386_pop_gs16();
	void i386_pop_ss16();
	void i386_pop_rm16();
	void i386_popa();
	void i386_popf();
	void i386_push_ax();
	void i386_push_cx();
	void i386_push_dx();
	void i386_push_bx();
	void i386_push_sp();
	void i386_push_bp();
	void i386_push_si();
	void i386_push_di();
	void i386_push_cs16();
	void i386_push_ds16();
	void i386_push_es16();
	void i386_push_fs16();
	void i386_push_gs16();
	void i386_push_ss16();
	void i386_push_i16();
	void i386_pusha();
	void i386_pushf();
	void i386_ret_near16_i16();
	void i386_ret_near16();
	void i386_sbb_rm16_r16();
	void i386_sbb_r16_rm16();
	void i386_sbb_ax_i16();
	void i386_scasw();
	void i386_shld16_i8();
	void i386_shld16_cl();
	void i386_shrd16_i8();
	void i386_shrd16_cl();
	void i386_stosw();
	void i386_sub_rm16_r16();
	void i386_sub_r16_rm16();
	void i386_sub_ax_i16();
	void i386_test_ax_i16();
	void i386_test_rm16_r16();
	void i386_xchg_ax_cx();
	void i386_xchg_ax_dx();
	void i386_xchg_ax_bx();
	void i386_xchg_ax_sp();
	void i386_xchg_ax_bp();
	void i386_xchg_ax_si();
	void i386_xchg_ax_di();
	void i386_xchg_r16_rm16();
	void i386_xor_rm16_r16();
	void i386_xor_r16_rm16();
	void i386_xor_ax_i16();
	void i386_group81_16();
	void i386_group83_16();
	void i386_groupC1_16();
	void i386_groupD1_16();
	void i386_groupD3_16();
	void i386_groupF7_16();
	void i386_groupFF_16();
	void i386_group0F00_16();
	void i386_group0F01_16();
	void i386_group0FBA_16();
	void i386_lar_r16_rm16();
	void i386_lsl_r16_rm16();
	void i386_bound_r16_m16_m16();
	void i386_retf16();
	void i386_retf_i16();
	bool __FASTCALL i386_load_far_pointer16(int s);
	void i386_lds16();
	void i386_lss16();
	void i386_les16();
	void i386_lfs16();
	void i386_lgs16();
	uint32_t __FASTCALL i386_shift_rotate32(uint8_t modrm, uint32_t value, uint8_t shift);
	void i386_adc_rm32_r32();
	void i386_adc_r32_rm32();
	void i386_adc_eax_i32();
	void i386_add_rm32_r32();
	void i386_add_r32_rm32();
	void i386_add_eax_i32();
	void i386_and_rm32_r32();
	void i386_and_r32_rm32();
	void i386_and_eax_i32();
	void i386_bsf_r32_rm32();
	void i386_bsr_r32_rm32();
	void i386_bt_rm32_r32();
	void i386_btc_rm32_r32();
	void i386_btr_rm32_r32();
	void i386_bts_rm32_r32();
	void i386_call_abs32();
	void i386_call_rel32();
	void i386_cdq();
	void i386_cmp_rm32_r32();
	void i386_cmp_r32_rm32();
	void i386_cmp_eax_i32();
	void i386_cmpsd();
	void i386_cwde();
	void i386_dec_eax();
	void i386_dec_ecx();
	void i386_dec_edx();
	void i386_dec_ebx();
	void i386_dec_esp();
	void i386_dec_ebp();
	void i386_dec_esi();
	void i386_dec_edi();
	void i386_imul_r32_rm32();
	void i386_imul_r32_rm32_i32();
	void i386_imul_r32_rm32_i8();
	void i386_in_eax_i8();
	void i386_in_eax_dx();
	void i386_inc_eax();
	void i386_inc_ecx();
	void i386_inc_edx();
	void i386_inc_ebx();
	void i386_inc_esp();
	void i386_inc_ebp();
	void i386_inc_esi();
	void i386_inc_edi();
	void i386_iret32();
	void i386_ja_rel32();
	void i386_jbe_rel32();
	void i386_jc_rel32();
	void i386_jg_rel32();
	void i386_jge_rel32();
	void i386_jl_rel32();
	void i386_jle_rel32();
	void i386_jnc_rel32();
	void i386_jno_rel32();
	void i386_jnp_rel32();
	void i386_jns_rel32();
	void i386_jnz_rel32();
	void i386_jo_rel32();
	void i386_jp_rel32();
	void i386_js_rel32();
	void i386_jz_rel32();
	void i386_jcxz32();
	void i386_jmp_rel32();
	void i386_jmp_abs32();
	void i386_lea32();
	void i386_enter32();
	void i386_leave32();
	void i386_lodsd();
	void i386_loop32();
	void i386_loopne32();
	void i386_loopz32();
	void i386_mov_rm32_r32();
	void i386_mov_r32_rm32();
	void i386_mov_rm32_i32();
	void i386_mov_eax_m32();
	void i386_mov_m32_eax();
	void i386_mov_eax_i32();
	void i386_mov_ecx_i32();
	void i386_mov_edx_i32();
	void i386_mov_ebx_i32();
	void i386_mov_esp_i32();
	void i386_mov_ebp_i32();
	void i386_mov_esi_i32();
	void i386_mov_edi_i32();
	void i386_movsd();
	void i386_movsx_r32_rm8();
	void i386_movsx_r32_rm16();
	void i386_movzx_r32_rm8();
	void i386_movzx_r32_rm16();
	void i386_or_rm32_r32();
	void i386_or_r32_rm32();
	void i386_or_eax_i32();
	void i386_out_eax_i8();
	void i386_out_eax_dx();
	void i386_pop_eax();
	void i386_pop_ecx();
	void i386_pop_edx();
	void i386_pop_ebx();
	void i386_pop_esp();
	void i386_pop_ebp();
	void i386_pop_esi();
	void i386_pop_edi();
	bool __FASTCALL i386_pop_seg32(int segment);
	void i386_pop_ds32();
	void i386_pop_es32();
	void i386_pop_fs32();
	void i386_pop_gs32();
	void i386_pop_ss32();
	void i386_pop_rm32();
	void i386_popad();
	void i386_popfd();
	void i386_push_eax();
	void i386_push_ecx();
	void i386_push_edx();
	void i386_push_ebx();
	void i386_push_esp();
	void i386_push_ebp();
	void i386_push_esi();
	void i386_push_edi();
	void i386_push_cs32();
	void i386_push_ds32();
	void i386_push_es32();
	void i386_push_fs32();
	void i386_push_gs32();
	void i386_push_ss32();
	void i386_push_i32();
	void i386_pushad();
	void i386_pushfd();
	void i386_ret_near32_i16();
	void i386_ret_near32();
	void i386_sbb_rm32_r32();
	void i386_sbb_r32_rm32();
	void i386_sbb_eax_i32();
	void i386_scasd();
	void i386_shld32_i8();
	void i386_shld32_cl();
	void i386_shrd32_i8();
	void i386_shrd32_cl();
	void i386_stosd();
	void i386_sub_rm32_r32();
	void i386_sub_r32_rm32();
	void i386_sub_eax_i32();
	void i386_test_eax_i32();
	void i386_test_rm32_r32();
	void i386_xchg_eax_ecx();
	void i386_xchg_eax_edx();
	void i386_xchg_eax_ebx();
	void i386_xchg_eax_esp();
	void i386_xchg_eax_ebp();
	void i386_xchg_eax_esi();
	void i386_xchg_eax_edi();
	void i386_xchg_r32_rm32();
	void i386_xor_rm32_r32();
	void i386_xor_r32_rm32();
	void i386_xor_eax_i32();
	void i386_group81_32();
	void i386_group83_32();
	void i386_groupC1_32();
	void i386_groupD1_32();
	void i386_groupD3_32();
	void i386_groupF7_32();
	void i386_groupFF_32();
	void i386_group0F00_32();
	void i386_group0F01_32();
	void i386_group0FBA_32();
	void i386_lar_r32_rm32();
	void i386_lsl_r32_rm32();
	void i386_bound_r32_m32_m32();
	void i386_retf32();
	void i386_retf_i32();
	void __FASTCALL i386_load_far_pointer32(int s);
	void i386_lds32();
	void i386_lss32();
	void i386_les32();
	void i386_lfs32();
	void i386_lgs32();
	void i486_cpuid();
	void i486_invd();
	void i486_wbinvd();
	void i486_cmpxchg_rm8_r8();
	void i486_cmpxchg_rm16_r16();
	void i486_cmpxchg_rm32_r32();
	void i486_xadd_rm8_r8();
	void i486_xadd_rm16_r16();
	void i486_xadd_rm32_r32();
	void i486_group0F01_16();
	void i486_group0F01_32();
	void i486_bswap_eax();
	void i486_bswap_ecx();
	void i486_bswap_edx();
	void i486_bswap_ebx();
	void i486_bswap_esp();
	void i486_bswap_ebp();
	void i486_bswap_esi();
	void i486_bswap_edi();
	void i486_mov_cr_r32();
	inline void MMXPROLOG();
	inline void __FASTCALL READMMX(uint32_t ea,MMX_REG &r);
	inline void __FASTCALL WRITEMMX(uint32_t ea,MMX_REG &r);
	inline void __FASTCALL READXMM(uint32_t ea,XMM_REG &r);
	inline void __FASTCALL WRITEXMM(uint32_t ea,XMM_REG &r);
	inline void __FASTCALL READXMM_LO64(uint32_t ea,XMM_REG &r);
	inline void __FASTCALL WRITEXMM_LO64(uint32_t ea,XMM_REG &r);
	inline void __FASTCALL READXMM_HI64(uint32_t ea,XMM_REG &r);
	inline void __FASTCALL WRITEXMM_HI64(uint32_t ea,XMM_REG &r);
	void pentium_rdmsr();
	void pentium_wrmsr();
	void pentium_rdtsc();
	void pentium_ud2();
	void pentium_rsm();
	void pentium_prefetch_m8();
	void pentium_cmovo_r16_rm16();
	void pentium_cmovo_r32_rm32();
	void pentium_cmovno_r16_rm16();
	void pentium_cmovno_r32_rm32();
	void pentium_cmovb_r16_rm16();
	void pentium_cmovb_r32_rm32();
	void pentium_cmovae_r16_rm16();
	void pentium_cmovae_r32_rm32();
	void pentium_cmove_r16_rm16();
	void pentium_cmove_r32_rm32();
	void pentium_cmovne_r16_rm16();
	void pentium_cmovne_r32_rm32();
	void pentium_cmovbe_r16_rm16();
	void pentium_cmovbe_r32_rm32();
	void pentium_cmova_r16_rm16();
	void pentium_cmova_r32_rm32();
	void pentium_cmovs_r16_rm16();
	void pentium_cmovs_r32_rm32();
	void pentium_cmovns_r16_rm16();
	void pentium_cmovns_r32_rm32();
	void pentium_cmovp_r16_rm16();
	void pentium_cmovp_r32_rm32();
	void pentium_cmovnp_r16_rm16();
	void pentium_cmovnp_r32_rm32();
	void pentium_cmovl_r16_rm16();
	void pentium_cmovl_r32_rm32();
	void pentium_cmovge_r16_rm16();
	void pentium_cmovge_r32_rm32();
	void pentium_cmovle_r16_rm16();
	void pentium_cmovle_r32_rm32();
	void pentium_cmovg_r16_rm16();
	void pentium_cmovg_r32_rm32();
	void pentium_movnti_m16_r16();
	void pentium_movnti_m32_r32();
	void i386_cyrix_special();
	void i386_cyrix_unknown();
	void pentium_cmpxchg8b_m64();
	void pentium_movntq_m64_r64();
	void pentium_maskmovq_r64_r64();
	void pentium_popcnt_r16_rm16();
	void pentium_popcnt_r32_rm32();
	void pentium_tzcnt_r16_rm16();
	void pentium_tzcnt_r32_rm32();
	void mmx_group_0f71();
	void mmx_group_0f72();
	void mmx_group_0f73();
	void mmx_psrlw_r64_rm64();
	void mmx_psrld_r64_rm64();
	void mmx_psrlq_r64_rm64();
	void mmx_paddq_r64_rm64();
	void mmx_pmullw_r64_rm64();
	void mmx_psubusb_r64_rm64();
	void mmx_psubusw_r64_rm64();
	void mmx_pand_r64_rm64();
	void mmx_paddusb_r64_rm64();
	void mmx_paddusw_r64_rm64();
	void mmx_pandn_r64_rm64();
	void mmx_psraw_r64_rm64();
	void mmx_psrad_r64_rm64();
	void mmx_pmulhw_r64_rm64();
	void mmx_psubsb_r64_rm64();
	void mmx_psubsw_r64_rm64();
	void mmx_por_r64_rm64();
	void mmx_paddsb_r64_rm64();
	void mmx_paddsw_r64_rm64();
	void mmx_pxor_r64_rm64();
	void mmx_psllw_r64_rm64();
	void mmx_pslld_r64_rm64();
	void mmx_psllq_r64_rm64();
	void mmx_pmaddwd_r64_rm64();
	void mmx_psubb_r64_rm64();
	void mmx_psubw_r64_rm64();
	void mmx_psubd_r64_rm64();
	void mmx_paddb_r64_rm64();
	void mmx_paddw_r64_rm64();
	void mmx_paddd_r64_rm64();
	void mmx_emms();
	void i386_cyrix_svdc();
	void i386_cyrix_rsdc();
	void i386_cyrix_svldt();
	void i386_cyrix_rsldt();
	void i386_cyrix_svts();
	void i386_cyrix_rsts();
	void mmx_movd_r64_rm32();
	void mmx_movq_r64_rm64();
	void mmx_movd_rm32_r64();
	void mmx_movq_rm64_r64();
	void mmx_pcmpeqb_r64_rm64();
	void mmx_pcmpeqw_r64_rm64();
	void mmx_pcmpeqd_r64_rm64();
	void mmx_pshufw_r64_rm64_i8();
	void mmx_punpcklbw_r64_r64m32();
	void mmx_punpcklwd_r64_r64m32();
	void mmx_punpckldq_r64_r64m32();
	void mmx_packsswb_r64_rm64();
	void mmx_pcmpgtb_r64_rm64();
	void mmx_pcmpgtw_r64_rm64();
	void mmx_pcmpgtd_r64_rm64();
	void mmx_packuswb_r64_rm64();
	void mmx_punpckhbw_r64_rm64();
	void mmx_punpckhwd_r64_rm64();
	void mmx_punpckhdq_r64_rm64();
	void mmx_packssdw_r64_rm64();
	void sse_group_0fae();
	void sse_group_660f71();
	void sse_group_660f72();
	void sse_group_660f73();
	void sse_cvttps2dq_r128_rm128();
	void sse_cvtss2sd_r128_r128m32();
	void sse_cvttss2si_r32_r128m32();
	void sse_cvtss2si_r32_r128m32();
	void sse_cvtsi2ss_r128_rm32();
	void sse_cvtpi2ps_r128_rm64();
	void sse_cvttps2pi_r64_r128m64();
	void sse_cvtps2pi_r64_r128m64();
	void sse_cvtps2pd_r128_r128m64();
	void sse_cvtdq2ps_r128_rm128();
	void sse_cvtdq2pd_r128_r128m64();
	void sse_movss_r128_rm128();
	void sse_movss_rm128_r128();
	void sse_movsldup_r128_rm128();
	void sse_movshdup_r128_rm128();
	void sse_movaps_r128_rm128();
	void sse_movaps_rm128_r128();
	void sse_movups_r128_rm128();
	void sse_movups_rm128_r128();
	void sse_movlps_r128_m64();
	void sse_movlps_m64_r128();
	void sse_movhps_r128_m64();
	void sse_movhps_m64_r128();
	void sse_movntps_m128_r128();
	void sse_movmskps_r16_r128();
	void sse_movmskps_r32_r128();
	void sse_movq2dq_r128_r64();
	void sse_movdqu_r128_rm128();
	void sse_movdqu_rm128_r128();
	void sse_movd_m128_rm32();
	void sse_movdqa_m128_rm128();
	void sse_movq_r128_r128m64();
	void sse_movd_rm32_r128();
	void sse_movdqa_rm128_r128();
	void sse_pmovmskb_r16_r64();
	void sse_pmovmskb_r32_r64();
	void sse_xorps();
	void sse_addps();
	void sse_sqrtps_r128_rm128();
	void sse_rsqrtps_r128_rm128();
	void sse_rcpps_r128_rm128();
	void sse_andps_r128_rm128();
	void sse_andnps_r128_rm128();
	void sse_orps_r128_rm128();
	void sse_mulps();
	void sse_subps();
	void sse_minps();
	void sse_divps();
	void sse_maxps();
	void sse_maxss_r128_r128m32();
	void sse_addss();
	void sse_subss();
	void sse_mulss();
	void sse_divss();
	void sse_rcpss_r128_r128m32();
	void sse_sqrtss_r128_r128m32();
	void sse_rsqrtss_r128_r128m32();
	void sse_minss_r128_r128m32();
	void sse_comiss_r128_r128m32();
	void sse_ucomiss_r128_r128m32();
	void sse_shufps();
	void sse_punpcklbw_r128_rm128();
	void sse_punpcklwd_r128_rm128();
	void sse_punpckldq_r128_rm128();
	void sse_punpcklqdq_r128_rm128();
	void sse_unpcklps_r128_rm128();
	void sse_unpckhps_r128_rm128();
	void sse_cmpps_r128_rm128_i8();
	void sse_cmpss_r128_r128m32_i8();
	void sse_pinsrw_r64_r16m16_i8();
	void sse_pinsrw_r64_r32m16_i8();
	void sse_pinsrw_r128_r32m16_i8();
	void sse_pextrw_r16_r64_i8();
	void sse_pextrw_r32_r64_i8();
	void sse_pextrw_reg_r128_i8();
	void sse_pminub_r64_rm64();
	void sse_pmaxub_r64_rm64();
	void sse_pavgb_r64_rm64();
	void sse_pavgw_r64_rm64();
	void sse_pmulhuw_r64_rm64();
	void sse_pminsw_r64_rm64();
	void sse_pmaxsw_r64_rm64();
	void sse_pmuludq_r64_rm64();
	void sse_psadbw_r64_rm64();
	void sse_psubq_r64_rm64();
	void sse_pshufhw_r128_rm128_i8();
	void sse_packsswb_r128_rm128();
	void sse_packssdw_r128_rm128();
	void sse_pcmpgtb_r128_rm128();
	void sse_pcmpgtw_r128_rm128();
	void sse_pcmpgtd_r128_rm128();
	void sse_packuswb_r128_rm128();
	void sse_punpckhbw_r128_rm128();
	void sse_punpckhwd_r128_rm128();
	void sse_unpckhdq_r128_rm128();
	void sse_punpckhqdq_r128_rm128();
	void sse_pcmpeqb_r128_rm128();
	void sse_pcmpeqw_r128_rm128();
	void sse_pcmpeqd_r128_rm128();
	void sse_paddq_r128_rm128();
	void sse_pmullw_r128_rm128();
	void sse_pmuludq_r128_rm128();
	void sse_psubq_r128_rm128();
	void sse_paddb_r128_rm128();
	void sse_paddw_r128_rm128();
	void sse_paddd_r128_rm128();
	void sse_psubusb_r128_rm128();
	void sse_psubusw_r128_rm128();
	void sse_pminub_r128_rm128();
	void sse_pand_r128_rm128();
	void sse_pandn_r128_rm128();
	void sse_paddusb_r128_rm128();
	void sse_paddusw_r128_rm128();
	void sse_pmaxub_r128_rm128();
	void sse_pmulhuw_r128_rm128();
	void sse_pmulhw_r128_rm128();
	void sse_psubsw_r128_rm128();
	void sse_psubsb_r128_rm128();
	void sse_pminsw_r128_rm128();
	void sse_pmaxsw_r128_rm128();
	void sse_paddsb_r128_rm128();
	void sse_paddsw_r128_rm128();
	void sse_por_r128_rm128();
	void sse_pxor_r128_rm128();
	void sse_pmaddwd_r128_rm128();
	void sse_psubb_r128_rm128();
	void sse_psubw_r128_rm128();
	void sse_psubd_r128_rm128();
	void sse_psadbw_r128_rm128();
	void sse_pavgb_r128_rm128();
	void sse_pavgw_r128_rm128();
	void sse_pmovmskb_r32_r128();
	void sse_maskmovdqu_r128_r128();
	void sse_andpd_r128_rm128();
	void sse_andnpd_r128_rm128();
	void sse_orpd_r128_rm128();
	void sse_xorpd_r128_rm128();
	void sse_unpcklpd_r128_rm128();
	void sse_unpckhpd_r128_rm128();
	void sse_shufpd_r128_rm128_i8();
	void sse_pshufd_r128_rm128_i8();
	void sse_pshuflw_r128_rm128_i8();
	void sse_movmskpd_r32_r128();
	void sse_ucomisd_r128_r128m64();
	void sse_comisd_r128_r128m64();
	void sse_psrlw_r128_rm128();
	void sse_psrld_r128_rm128();
	void sse_psrlq_r128_rm128();
	void sse_psllw_r128_rm128();
	void sse_pslld_r128_rm128();
	void sse_psllq_r128_rm128();
	void sse_psraw_r128_rm128();
	void sse_psrad_r128_rm128();
	void sse_movntdq_m128_r128();
	void sse_cvttpd2dq_r128_rm128();
	void sse_movq_r128m64_r128();
	void sse_addsubpd_r128_rm128();
	void sse_cmppd_r128_rm128_i8();
	void sse_haddpd_r128_rm128();
	void sse_hsubpd_r128_rm128();
	void sse_sqrtpd_r128_rm128();
	void sse_cvtpi2pd_r128_rm64();
	void sse_cvttpd2pi_r64_rm128();
	void sse_cvtpd2pi_r64_rm128();
	void sse_cvtpd2ps_r128_rm128();
	void sse_cvtps2dq_r128_rm128();
	void sse_addpd_r128_rm128();
	void sse_mulpd_r128_rm128();
	void sse_subpd_r128_rm128();
	void sse_minpd_r128_rm128();
	void sse_divpd_r128_rm128();
	void sse_maxpd_r128_rm128();
	void sse_movntpd_m128_r128();
	void sse_movapd_r128_rm128();
	void sse_movapd_rm128_r128();
	void sse_movhpd_r128_m64();
	void sse_movhpd_m64_r128();
	void sse_movupd_r128_rm128();
	void sse_movupd_rm128_r128();
	void sse_movlpd_r128_m64();
	void sse_movlpd_m64_r128();
	void sse_movsd_r128_r128m64();
	void sse_movsd_r128m64_r128();
	void sse_movddup_r128_r128m64();
	void sse_cvtsi2sd_r128_rm32();
	void sse_cvttsd2si_r32_r128m64();
	void sse_cvtsd2si_r32_r128m64();
	void sse_sqrtsd_r128_r128m64();
	void sse_addsd_r128_r128m64();
	void sse_mulsd_r128_r128m64();
	void sse_cvtsd2ss_r128_r128m64();
	void sse_subsd_r128_r128m64();
	void sse_minsd_r128_r128m64();
	void sse_divsd_r128_r128m64();
	void sse_maxsd_r128_r128m64();
	void sse_haddps_r128_rm128();
	void sse_hsubps_r128_rm128();
	void sse_cmpsd_r128_r128m64_i8();
	void sse_addsubps_r128_rm128();
	void sse_movdq2q_r64_r128();
	void sse_cvtpd2dq_r128_rm128();
	void sse_lddqu_r128_m128();
	inline void __FASTCALL sse_predicate_compare_single(uint8_t imm8, XMM_REG d, XMM_REG s);
	inline void __FASTCALL sse_predicate_compare_double(uint8_t imm8, XMM_REG d, XMM_REG s);
	inline void __FASTCALL sse_predicate_compare_single_scalar(uint8_t imm8, XMM_REG d, XMM_REG s);
	inline void __FASTCALL sse_predicate_compare_double_scalar(uint8_t imm8, XMM_REG d, XMM_REG s);
	inline floatx80 __FASTCALL READ80(uint32_t ea);
	inline void __FASTCALL WRITE80(uint32_t ea, floatx80 t);
	inline void __FASTCALL x87_set_stack_top(int top);
	inline void __FASTCALL x87_set_tag(int reg, int tag);
	void __FASTCALL x87_write_stack(int i, floatx80 value, bool update_tag);
	inline void x87_set_stack_underflow();
	inline void x87_set_stack_overflow();
	int x87_inc_stack();
	int x87_dec_stack();
	int x87_check_exceptions();
	inline __FASTCALL void x87_write_cw(uint16_t cw);
	void x87_reset();
	floatx80 __FASTCALL x87_add(floatx80 a, floatx80 b);
	floatx80 __FASTCALL x87_sub(floatx80 a, floatx80 b);
	floatx80 __FASTCALL x87_mul(floatx80 a, floatx80 b);
	floatx80 __FASTCALL x87_div(floatx80 a, floatx80 b);
	void __FASTCALL x87_fadd_m32real(uint8_t modrm);
	void x87_fadd_m64real(uint8_t modrm);
	void x87_fadd_st_sti(uint8_t modrm);
	void x87_fadd_sti_st(uint8_t modrm);
	void x87_faddp(uint8_t modrm);
	void x87_fiadd_m32int(uint8_t modrm);
	void x87_fiadd_m16int(uint8_t modrm);
	void x87_fsub_m32real(uint8_t modrm);
	void x87_fsub_m64real(uint8_t modrm);
	void x87_fsub_st_sti(uint8_t modrm);
	void x87_fsub_sti_st(uint8_t modrm);
	void x87_fsubp(uint8_t modrm);
	void x87_fisub_m32int(uint8_t modrm);
	void x87_fisub_m16int(uint8_t modrm);
	void x87_fsubr_m32real(uint8_t modrm);
	void x87_fsubr_m64real(uint8_t modrm);
	void x87_fsubr_st_sti(uint8_t modrm);
	void x87_fsubr_sti_st(uint8_t modrm);
	void x87_fsubrp(uint8_t modrm);
	void x87_fisubr_m32int(uint8_t modrm);
	void x87_fisubr_m16int(uint8_t modrm);
	void x87_fdiv_m32real(uint8_t modrm);
	void x87_fdiv_m64real(uint8_t modrm);
	void x87_fdiv_st_sti(uint8_t modrm);
	void x87_fdiv_sti_st(uint8_t modrm);
	void x87_fdivp(uint8_t modrm);
	void x87_fidiv_m32int(uint8_t modrm);
	void x87_fidiv_m16int(uint8_t modrm);
	void x87_fdivr_m32real(uint8_t modrm);
	void x87_fdivr_m64real(uint8_t modrm);
	void x87_fdivr_st_sti(uint8_t modrm);
	void x87_fdivr_sti_st(uint8_t modrm);
	void x87_fdivrp(uint8_t modrm);
	void x87_fidivr_m32int(uint8_t modrm);
	void x87_fidivr_m16int(uint8_t modrm);
	void x87_fmul_m32real(uint8_t modrm);
	void x87_fmul_m64real(uint8_t modrm);
	void x87_fmul_st_sti(uint8_t modrm);
	void x87_fmul_sti_st(uint8_t modrm);
	void x87_fmulp(uint8_t modrm);
	void x87_fimul_m32int(uint8_t modrm);
	void x87_fimul_m16int(uint8_t modrm);
	void x87_fprem(uint8_t modrm);
	void x87_fprem1(uint8_t modrm);
	void x87_fsqrt(uint8_t modrm);
	void x87_f2xm1(uint8_t modrm);
	void x87_fyl2x(uint8_t modrm);
	void x87_fyl2xp1(uint8_t modrm);
	void x87_fptan(uint8_t modrm);
	void x87_fpatan(uint8_t modrm);
	void x87_fsin(uint8_t modrm);
	void x87_fcos(uint8_t modrm);
	void x87_fsincos(uint8_t modrm);
	void x87_fld_m32real(uint8_t modrm);
	void x87_fld_m64real(uint8_t modrm);
	void x87_fld_m80real(uint8_t modrm);
	void x87_fld_sti(uint8_t modrm);
	void x87_fild_m16int(uint8_t modrm);
	void x87_fild_m32int(uint8_t modrm);
	void x87_fild_m64int(uint8_t modrm);
	void x87_fbld(uint8_t modrm);
	void x87_fst_m32real(uint8_t modrm);
	void x87_fst_m64real(uint8_t modrm);
	void x87_fst_sti(uint8_t modrm);
	void x87_fstp_m32real(uint8_t modrm);
	void x87_fstp_m64real(uint8_t modrm);
	void x87_fstp_m80real(uint8_t modrm);
	void x87_fstp_sti(uint8_t modrm);
	void x87_fist_m16int(uint8_t modrm);
	void x87_fist_m32int(uint8_t modrm);
	void x87_fistp_m16int(uint8_t modrm);
	void x87_fistp_m32int(uint8_t modrm);
	void x87_fistp_m64int(uint8_t modrm);
	void x87_fbstp(uint8_t modrm);
	void x87_fld1(uint8_t modrm);
	void x87_fldl2t(uint8_t modrm);
	void x87_fldl2e(uint8_t modrm);
	void x87_fldpi(uint8_t modrm);
	void x87_fldlg2(uint8_t modrm);
	void x87_fldln2(uint8_t modrm);
	void x87_fldz(uint8_t modrm);
	void x87_fnop(uint8_t modrm);
	void x87_fchs(uint8_t modrm);
	void x87_fabs(uint8_t modrm);
	void x87_fscale(uint8_t modrm);
	void x87_frndint(uint8_t modrm);
	void x87_fxtract(uint8_t modrm);
	void x87_ftst(uint8_t modrm);
	void x87_fxam(uint8_t modrm);
	void x87_fcmovb_sti(uint8_t modrm);
	void x87_fcmove_sti(uint8_t modrm);
	void x87_fcmovbe_sti(uint8_t modrm);
	void x87_fcmovu_sti(uint8_t modrm);
	void x87_fcmovnb_sti(uint8_t modrm);
	void x87_fcmovne_sti(uint8_t modrm);
	void x87_fcmovnbe_sti(uint8_t modrm);
	void x87_fcmovnu_sti(uint8_t modrm);
	void x87_ficom_m16int(uint8_t modrm);
	void x87_ficom_m32int(uint8_t modrm);
	void x87_ficomp_m16int(uint8_t modrm);
	void x87_ficomp_m32int(uint8_t modrm);
	void x87_fcom_m32real(uint8_t modrm);
	void x87_fcom_m64real(uint8_t modrm);
	void x87_fcom_sti(uint8_t modrm);
	void x87_fcomp_m32real(uint8_t modrm);
	void x87_fcomp_m64real(uint8_t modrm);
	void x87_fcomp_sti(uint8_t modrm);
	void x87_fcomi_sti(uint8_t modrm);
	void x87_fcomip_sti(uint8_t modrm);
	void x87_fucomi_sti(uint8_t modrm);
	void x87_fucomip_sti(uint8_t modrm);
	void x87_fcompp(uint8_t modrm);
	void x87_fucom_sti(uint8_t modrm);
	void x87_fucomp_sti(uint8_t modrm);
	void x87_fucompp(uint8_t modrm);
	void x87_fdecstp(uint8_t modrm);
	void x87_fincstp(uint8_t modrm);
	void x87_fclex(uint8_t modrm);
	void x87_ffree(uint8_t modrm);
	void x87_fdisi(uint8_t modrm);
	void x87_feni(uint8_t modrm);
	void x87_finit(uint8_t modrm);
	void x87_fldcw(uint8_t modrm);
	void x87_fstcw(uint8_t modrm);
	void x87_fldenv(uint8_t modrm);
	void x87_fstenv(uint8_t modrm);
	void x87_fsave(uint8_t modrm);
	void x87_frstor(uint8_t modrm);
	void x87_fxch(uint8_t modrm);
	void x87_fxch_sti(uint8_t modrm);
	void x87_fstsw_ax(uint8_t modrm);
	void x87_fstsw_m2byte(uint8_t modrm);
	void x87_invalid(uint8_t modrm);
	void i386_x87_group_d8();
	void i386_x87_group_d9();
	void i386_x87_group_da();
	void i386_x87_group_db();
	void i386_x87_group_dc();
	void i386_x87_group_dd();
	void i386_x87_group_de();
	void i386_x87_group_df();
	void build_x87_opcode_table_d8();
	void build_x87_opcode_table_d9();
	void build_x87_opcode_table_da();
	void build_x87_opcode_table_db();
	void build_x87_opcode_table_dc();
	void build_x87_opcode_table_dd();
	void build_x87_opcode_table_de();
	void build_x87_opcode_table_df();
	void build_x87_opcode_table();
	void i386_postload();
	void i386_common_init();
	void build_opcode_table(uint32_t features);
	void pentium_smi();
	void zero_state();
	void i386_set_a20_line(int state);

};


class i386sx_device : public i386_device
{
public:
	// construction/destruction
	i386sx_device(VM_TEMPLATE* parent_vm, EMU* parent_emu);

protected:
#if 0
	virtual u8 mem_pr8(offs_t address) override { return macache16->read_data8(address); };
	virtual u16 mem_pr16(offs_t address) override { return macache16->read_data16(address); };
	virtual u32 mem_pr32(offs_t address) override { return macache16->read_data32(address); };
#else
	virtual u8 __FASTCALL mem_pr8(offs_t address) override { return d_mem->read_data8(address); };
	virtual u16 __FASTCALL mem_pr16(offs_t address) override { return d_mem->read_data16(address); };
	virtual u32 __FASTCALL mem_pr32(offs_t address) override { return d_mem->read_data32(address); };
#endif	
};

class i486_device : public i386_device
{
public:
	// construction/destruction
	i486_device(VM_TEMPLATE* parent_vm, EMU* parent_emu);
	virtual bool process_state(FILEIO* state_fio, bool loading);
	virtual void initialize() override;
	virtual void reset() override;

};

class i486dx4_device : public i486_device
{
public:
	// construction/destruction
	i486dx4_device(VM_TEMPLATE* parent_vm, EMU* parent_emu);
	virtual void reset() override;

};


class pentium_device : public i386_device
{
public:
	// construction/destruction
	pentium_device(VM_TEMPLATE* parent_vm, EMU* parent_emu);
	virtual bool process_state(FILEIO* state_fio, bool loading);
	virtual void initialize() override;
	virtual void reset() override;

protected:

	virtual bool __FASTCALL execute_input_edge_triggered(int inputnum) const override { return inputnum == SIG_CPU_NMI || inputnum == SIG_CPU_SMI; }
	virtual void __FASTCALL write_signal(int ch, uint32_t data, uint32_t mask) override;
	virtual __FASTCALL uint64_t opcode_rdmsr(bool &valid_msr) override;
	virtual __FASTCALL void opcode_wrmsr(uint64_t data, bool &valid_msr) override;
};


class pentium_mmx_device : public pentium_device
{
public:
	// construction/destruction
	pentium_mmx_device(VM_TEMPLATE* parent_vm, EMU* parent_emu);
	virtual bool process_state(FILEIO* state_fio, bool loading);
	virtual void initialize() override;
	virtual void reset() override;
};


class mediagx_device : public i386_device
{
public:
	// construction/destruction
	mediagx_device(VM_TEMPLATE* parent_vm, EMU* parent_emu);
	virtual bool process_state(FILEIO* state_fio, bool loading);
	virtual void initialize() override;
	virtual void reset() override;
};


class pentium_pro_device : public pentium_device
{
public:
	// construction/destruction
	pentium_pro_device(VM_TEMPLATE* parent_vm, EMU* parent_emu);
	virtual bool process_state(FILEIO* state_fio, bool loading);
	virtual void initialize() override;
	virtual void reset() override;

protected:
	virtual uint64_t __FASTCALL opcode_rdmsr(bool &valid_msr) override;
	virtual void __FASTCALL opcode_wrmsr(uint64_t data, bool &valid_msr) override;
};


class pentium2_device : public pentium_pro_device
{
public:
	// construction/destruction
	pentium2_device(VM_TEMPLATE* parent_vm, EMU* parent_emu);
	virtual bool process_state(FILEIO* state_fio, bool loading);
	virtual void initialize() override;
	virtual void reset() override;
};


class pentium3_device : public pentium_pro_device
{
public:
	// construction/destruction
	pentium3_device(VM_TEMPLATE* parent_vm, EMU* parent_emu);
	virtual bool process_state(FILEIO* state_fio, bool loading);
	virtual void initialize() override;
	virtual void reset() override;
};

#if 0
class athlonxp_device : public pentium_device
{
public:
	// construction/destruction
	athlonxp_device(VM_TEMPLATE* parent_vm, EMU* parent_emu);
	virtual bool process_state(FILEIO* state_fio, bool loading);
	virtual void initialize() override;
	virtual void reset() override;

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 opcode_invd() override;
	virtual void opcode_wbinvd() 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); }

private:
	void parse_mtrrfix(u64 mtrr, offs_t base, int kblock);
	int check_cacheable(offs_t address);
	void invalidate_cache(bool writeback);

	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);

	uint8_t m_processor_name_string[48];
	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
};
#endif

class pentium4_device : public pentium_device
{
public:
	// construction/destruction
	pentium4_device(VM_TEMPLATE* parent_vm, EMU* parent_emu);
	virtual bool process_state(FILEIO* state_fio, bool loading);
	virtual void initialize() override;
	virtual void reset() override;

protected:
	virtual uint64_t __FASTCALL opcode_rdmsr(bool &valid_msr) override;
	virtual void __FASTCALL opcode_wrmsr(uint64_t data, bool &valid_msr) override;
};

/*
DECLARE_DEVICE_TYPE(I386,        i386_device)
DECLARE_DEVICE_TYPE(I386SX,      i386sx_device)
DECLARE_DEVICE_TYPE(I486,        i486_device)
DECLARE_DEVICE_TYPE(I486DX4,     i486dx4_device)
DECLARE_DEVICE_TYPE(PENTIUM,     pentium_device)
DECLARE_DEVICE_TYPE(PENTIUM_MMX, pentium_mmx_device)
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
