OSDN Git Service

[VM] Fix i386.cpp , temporally.
authorK.Ohta <whatisthis.sowhat@gmail.com>
Fri, 3 Feb 2017 18:04:10 +0000 (03:04 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Fri, 3 Feb 2017 18:04:10 +0000 (03:04 +0900)
source/src/vm/i386.cpp
source/src/vm/i386.h
source/src/vm/i386_base.cpp [new file with mode: 0644]
source/src/vm/i386_base.h [new file with mode: 0644]

index 5cbf4b2..1dd3125 100644 (file)
@@ -1,22 +1,12 @@
-/*
-       Skelton for retropc emulator
 
-       Origin : MAME i386 core
-       Author : Takeda.Toshiya
-       Date  : 2009.06.08-
-
-       [ i386/i486/Pentium/MediaGX ]
-*/
 
+#include "vm.h"
+#include "../emu.h"
 #include "i386.h"
 #ifdef USE_DEBUGGER
 #include "debugger.h"
 #endif
 
-/* ----------------------------------------------------------------------------
-       MAME i386
----------------------------------------------------------------------------- */
-
 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
 #pragma warning( disable : 4018 )
 #pragma warning( disable : 4065 )
        #define CPU_MODEL pentium4
 #endif
 
-#ifndef __BIG_ENDIAN__
-#define LSB_FIRST
-#endif
-
 #ifndef INLINE
 #define INLINE inline
 #endif
@@ -181,41 +167,43 @@ typedef UINT32    offs_t;
 #define ARRAY_LENGTH(x)     (sizeof(x) / sizeof(x[0]))
 
 #ifdef I386_PSEUDO_BIOS
-#define BIOS_INT(num) if(cpustate->bios != NULL) { \
+#define BIOS_INT(num, __ret) if(cpustate->bios != NULL) { \
        uint16_t regs[8], sregs[4]; \
+       __ret = false; \
        regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
        regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
        sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
        sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
        int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
+       printf("INT %x \n", num); \
        if(cpustate->bios->bios_int_i86(num, regs, sregs, &ZeroFlag, &CarryFlag)) { \
                REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
                REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
                cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
-               return; \
+               __ret = true;                                                                                                   \
        } \
 }
-#define BIOS_CALL(address) if(cpustate->bios != NULL) { \
+#define BIOS_CALL(address,__ret) if(cpustate->bios != NULL) {  \
        uint16_t regs[8], sregs[4]; \
+       __ret = false; \
        regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
        regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
        sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
        sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
        int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
+       printf("CALL %08x %0x AX=%04x %02x %02x\n", cpustate, address, regs[0], REG8(AH), REG8(AL)); \
        if(cpustate->bios->bios_call_i86(address, regs, sregs, &ZeroFlag, &CarryFlag)) { \
                REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
                REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
                cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
-               return; \
+               __ret = true; \
        } \
 }
 #endif
 
-static CPU_TRANSLATE(i386);
-
-#include "mame/lib/softfloat/softfloat.c"
-#include "mame/emu/cpu/vtlb.c"
-#include "mame/emu/cpu/i386/i386.c"
+//static CPU_TRANSLATE(i386);
+#include "mame/emu/cpu/vtlb.h"
+#include "mame/emu/cpu/i386/i386_exec.c"
 #ifdef USE_DEBUGGER
 #include "mame/emu/cpu/i386/i386dasm.c"
 #endif
@@ -225,15 +213,15 @@ void I386::initialize()
        opaque = CPU_INIT_CALL(CPU_MODEL);
        
        i386_state *cpustate = (i386_state *)opaque;
+
+       //I386_BASE::initialize();
        cpustate->pic = d_pic;
        cpustate->program = d_mem;
        cpustate->io = d_io;
-#ifdef I386_PSEUDO_BIOS
        cpustate->bios = d_bios;
-#endif
-#ifdef SINGLE_MODE_DMA
        cpustate->dma = d_dma;
-#endif
+       cpustate->shutdown = 0;
+       
 #ifdef USE_DEBUGGER
        cpustate->emu = emu;
        cpustate->debugger = d_debugger;
@@ -246,13 +234,6 @@ void I386::initialize()
        cpustate->shutdown = 0;
 }
 
-void I386::release()
-{
-       i386_state *cpustate = (i386_state *)opaque;
-       vtlb_free(cpustate->vtlb);
-       free(opaque);
-}
-
 void I386::reset()
 {
        i386_state *cpustate = (i386_state *)opaque;
@@ -262,53 +243,200 @@ void I386::reset()
 int I386::run(int cycles)
 {
        i386_state *cpustate = (i386_state *)opaque;
-       return CPU_EXECUTE_CALL(i386);
+       return cpu_execute((void *)cpustate, cycles);
+       //return CPU_EXECUTE_CALL(i386);
 }
 
-void I386::write_signal(int id, uint32_t data, uint32_t mask)
+extern "C" {
+extern void I386OP(decode_opcode)(i386_state *cpustate);
+};     
+
+int I386::cpu_execute(void *p, int cycles)
 {
-       i386_state *cpustate = (i386_state *)opaque;
-       
-       if(id == SIG_CPU_NMI) {
-               i386_set_irq_line(cpustate, INPUT_LINE_NMI, (data & mask) ? HOLD_LINE : CLEAR_LINE);
-       } else if(id == SIG_CPU_IRQ) {
-               i386_set_irq_line(cpustate, INPUT_LINE_IRQ, (data & mask) ? HOLD_LINE : CLEAR_LINE);
-       } else if(id == SIG_CPU_BUSREQ) {
-               cpustate->busreq = (data & mask) ? 1 : 0;
-       } else if(id == SIG_I386_A20) {
-               i386_set_a20_line(cpustate, data & mask);
+       i386_state *cpustate = (i386_state *)p;
+       CHANGE_PC(cpustate,cpustate->eip);
+
+       if (cpustate->halted || cpustate->busreq)
+       {
+#ifdef SINGLE_MODE_DMA
+               if(cpustate->dma != NULL) {
+                       cpustate->dma->do_dma();
+               }
+#endif
+               if (cycles == -1) {
+                       int passed_cycles = max(1, cpustate->extra_cycles);
+                       // this is main cpu, cpustate->cycles is not used
+                       /*cpustate->cycles = */cpustate->extra_cycles = 0;
+                       cpustate->tsc += passed_cycles;
+                       return passed_cycles;
+               } else {
+                       cpustate->cycles += cycles;
+                       cpustate->base_cycles = cpustate->cycles;
+
+                       /* adjust for any interrupts that came in */
+                       cpustate->cycles -= cpustate->extra_cycles;
+                       cpustate->extra_cycles = 0;
+
+                       /* if busreq is raised, spin cpu while remained clock */
+                       if (cpustate->cycles > 0) {
+                               cpustate->cycles = 0;
+                       }
+                       int passed_cycles = cpustate->base_cycles - cpustate->cycles;
+                       cpustate->tsc += passed_cycles;
+                       return passed_cycles;
+               }
        }
-}
 
-void I386::set_intr_line(bool line, bool pending, uint32_t bit)
-{
-       i386_state *cpustate = (i386_state *)opaque;
-       i386_set_irq_line(cpustate, INPUT_LINE_IRQ, line ? HOLD_LINE : CLEAR_LINE);
-}
+       if (cycles == -1) {
+               cpustate->cycles = 1;
+       } else {
+               cpustate->cycles += cycles;
+       }
+       cpustate->base_cycles = cpustate->cycles;
 
-void I386::set_extra_clock(int cycles)
-{
-       i386_state *cpustate = (i386_state *)opaque;
-       cpustate->extra_cycles += cycles;
-}
+       /* adjust for any interrupts that came in */
+       cpustate->cycles -= cpustate->extra_cycles;
+       cpustate->extra_cycles = 0;
 
-int I386::get_extra_clock()
-{
-       i386_state *cpustate = (i386_state *)opaque;
-       return cpustate->extra_cycles;
-}
+       while( cpustate->cycles > 0 && !cpustate->busreq )
+       {
+#ifdef USE_DEBUGGER
+               bool now_debugging = cpustate->debugger->now_debugging;
+               if(now_debugging) {
+                       cpustate->debugger->check_break_points(cpustate->pc);
+                       if(cpustate->debugger->now_suspended) {
+                               cpustate->emu->mute_sound();
+                               while(cpustate->debugger->now_debugging && cpustate->debugger->now_suspended) {
+                                       cpustate->emu->sleep(10);
+                               }
+                       }
+                       if(cpustate->debugger->now_debugging) {
+                               cpustate->program = cpustate->io = cpustate->debugger;
+                       } else {
+                               now_debugging = false;
+                       }
+                       i386_check_irq_line(cpustate);
+                       cpustate->operand_size = cpustate->sreg[CS].d;
+                       cpustate->xmm_operand_size = 0;
+                       cpustate->address_size = cpustate->sreg[CS].d;
+                       cpustate->operand_prefix = 0;
+                       cpustate->address_prefix = 0;
+
+                       cpustate->ext = 1;
+                       int old_tf = cpustate->TF;
+
+                       cpustate->segment_prefix = 0;
+                       cpustate->prev_eip = cpustate->eip;
+                       cpustate->prev_pc = cpustate->pc;
+
+                       if(cpustate->delayed_interrupt_enable != 0)
+                       {
+                               cpustate->IF = 1;
+                               cpustate->delayed_interrupt_enable = 0;
+                       }
+#ifdef DEBUG_MISSING_OPCODE
+                       cpustate->opcode_bytes_length = 0;
+                       cpustate->opcode_pc = cpustate->pc;
+#endif
+                       try
+                       {
+                               I386OP(decode_opcode)(cpustate);
+                               printf("%04x\n", REG16(AX));
+                               if(cpustate->TF && old_tf)
+                               {
+                                       cpustate->prev_eip = cpustate->eip;
+                                       cpustate->ext = 1;
+                                       i386_trap(cpustate,1,0,0);
+                               }
+                               if(cpustate->lock && (cpustate->opcode != 0xf0))
+                                       cpustate->lock = false;
+                       }
+                       catch(UINT64 e)
+                       {
+                               cpustate->ext = 1;
+                               i386_trap_with_error(cpustate,e&0xffffffff,0,0,e>>32);
+                       }
+#ifdef SINGLE_MODE_DMA
+                       if(cpustate->dma != NULL) {
+                               cpustate->dma->do_dma();
+                       }
+#endif
+                       /* adjust for any interrupts that came in */
+                       cpustate->cycles -= cpustate->extra_cycles;
+                       cpustate->extra_cycles = 0;
+                       
+                       if(now_debugging) {
+                               if(!cpustate->debugger->now_going) {
+                                       cpustate->debugger->now_suspended = true;
+                               }
+                               cpustate->program = cpustate->program_stored;
+                               cpustate->io = cpustate->io_stored;
+                       }
+               } else {
+#endif
+                       i386_check_irq_line(cpustate);
+                       cpustate->operand_size = cpustate->sreg[CS].d;
+                       cpustate->xmm_operand_size = 0;
+                       cpustate->address_size = cpustate->sreg[CS].d;
+                       cpustate->operand_prefix = 0;
+                       cpustate->address_prefix = 0;
+
+                       cpustate->ext = 1;
+                       int old_tf = cpustate->TF;
+
+                       cpustate->segment_prefix = 0;
+                       cpustate->prev_eip = cpustate->eip;
+                       cpustate->prev_pc = cpustate->pc;
+
+                       if(cpustate->delayed_interrupt_enable != 0)
+                       {
+                               cpustate->IF = 1;
+                               cpustate->delayed_interrupt_enable = 0;
+                       }
+#ifdef DEBUG_MISSING_OPCODE
+                       cpustate->opcode_bytes_length = 0;
+                       cpustate->opcode_pc = cpustate->pc;
+#endif
+                       try
+                       {
+                               I386OP(decode_opcode)(cpustate);
+                               printf("%04x\n", REG16(AX));
+                               if(cpustate->TF && old_tf)
+                               {
+                                       cpustate->prev_eip = cpustate->eip;
+                                       cpustate->ext = 1;
+                                       i386_trap(cpustate,1,0,0);
+                               }
+                               if(cpustate->lock && (cpustate->opcode != 0xf0))
+                                       cpustate->lock = false;
+                       }
+                       catch(UINT64 e)
+                       {
+                               cpustate->ext = 1;
+                               i386_trap_with_error(cpustate,e&0xffffffff,0,0,e>>32);
+                       }
+#ifdef SINGLE_MODE_DMA
+                       if(cpustate->dma != NULL) {
+                               cpustate->dma->do_dma();
+                       }
+#endif
+                       /* adjust for any interrupts that came in */
+                       cpustate->cycles -= cpustate->extra_cycles;
+                       cpustate->extra_cycles = 0;
+#ifdef USE_DEBUGGER
+               }
+#endif
+       }
 
-uint32_t I386::get_pc()
-{
-       i386_state *cpustate = (i386_state *)opaque;
-       return cpustate->prev_pc;
+       /* if busreq is raised, spin cpu while remained clock */
+       if (cpustate->cycles > 0 && cpustate->busreq) {
+               cpustate->cycles = 0;
+       }
+       int passed_cycles = cpustate->base_cycles - cpustate->cycles;
+       cpustate->tsc += passed_cycles;
+       return passed_cycles;
 }
 
-uint32_t I386::get_next_pc()
-{
-       i386_state *cpustate = (i386_state *)opaque;
-       return cpustate->pc;
-}
 
 #ifdef USE_DEBUGGER
 void I386::write_debug_data8(uint32_t addr, uint32_t data)
@@ -454,61 +582,16 @@ int I386::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
 }
 #endif
 
-void I386::set_address_mask(uint32_t mask)
-{
-       i386_state *cpustate = (i386_state *)opaque;
-       cpustate->a20_mask = mask;
-}
-
-uint32_t I386::get_address_mask()
-{
-       i386_state *cpustate = (i386_state *)opaque;
-       return cpustate->a20_mask;
-}
-
-void I386::set_shutdown_flag(int shutdown)
-{
-       i386_state *cpustate = (i386_state *)opaque;
-       cpustate->shutdown = shutdown;
-}
-
-int I386::get_shutdown_flag()
-{
-       i386_state *cpustate = (i386_state *)opaque;
-       return cpustate->shutdown;
-}
-
-#define STATE_VERSION  1
-
 void I386::save_state(FILEIO* state_fio)
 {
-       state_fio->FputUint32(STATE_VERSION);
-       state_fio->FputInt32(this_device_id);
-       
-       state_fio->Fwrite(opaque, sizeof(i386_state), 1);
+       I386_BASE::save_state(state_fio);
 }
 
-bool I386::load_state(FILEIOstate_fio)
+bool I386::load_state(FILEIO *state_fio)
 {
-       if(state_fio->FgetUint32() != STATE_VERSION) {
-               return false;
-       }
-       if(state_fio->FgetInt32() != this_device_id) {
-               return false;
-       }
-       state_fio->Fread(opaque, sizeof(i386_state), 1);
+       if(!I386_BASE::load_state(state_fio)) return false;
        
-       // post process
        i386_state *cpustate = (i386_state *)opaque;
-       cpustate->pic = d_pic;
-       cpustate->program = d_mem;
-       cpustate->io = d_io;
-#ifdef I86_PSEUDO_BIOS
-       cpustate->bios = d_bios;
-#endif
-#ifdef SINGLE_MODE_DMA
-       cpustate->dma = d_dma;
-#endif
 #ifdef USE_DEBUGGER
        cpustate->emu = emu;
        cpustate->debugger = d_debugger;
@@ -517,4 +600,3 @@ bool I386::load_state(FILEIO* state_fio)
 #endif
        return true;
 }
-
index e1511c0..c4b7c26 100644 (file)
 
 #include "vm.h"
 #include "../emu.h"
-#include "device.h"
-
-#define SIG_I386_A20   1
+#include "i386_base.h"
 
 #ifdef USE_DEBUGGER
 class DEBUGGER;
 #endif
 
-class I386 : public DEVICE
+class I386 : public I386_BASE
 {
-private:
-       DEVICE *d_mem, *d_io, *d_pic;
-#ifdef I386_PSEUDO_BIOS
-       DEVICE *d_bios;
-#endif
-#ifdef SINGLE_MODE_DMA
-       DEVICE *d_dma;
-#endif
+protected:
 #ifdef USE_DEBUGGER
        DEBUGGER *d_debugger;
 #endif
-       void *opaque;
-       
 public:
-       I386(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+       I386(VM* parent_vm, EMU* parent_emu) : I386_BASE(parent_vm, parent_emu)
        {
-#ifdef I386_PSEUDO_BIOS
-               d_bios = NULL;
-#endif
-#ifdef SINGLE_MODE_DMA
-               d_dma = NULL;
-#endif
+               d_debugger = NULL;
 #if defined(HAS_I386)
                set_device_name(_T("i80386 CPU"));
 #elif defined(HAS_I486)
@@ -66,18 +50,11 @@ public:
 #endif
        }
        ~I386() {}
-       
        // common functions
        void initialize();
-       void release();
        void reset();
        int run(int cycles);
-       void write_signal(int id, uint32_t data, uint32_t mask);
-       void set_intr_line(bool line, bool pending, uint32_t bit);
-       void set_extra_clock(int cycles);
-       int get_extra_clock();
-       uint32_t get_pc();
-       uint32_t get_next_pc();
+       int cpu_execute(void *p, int cycles);   
 #ifdef USE_DEBUGGER
        void *get_debugger()
        {
@@ -107,44 +84,34 @@ public:
        void get_debug_regs_info(_TCHAR *buffer, size_t buffer_len);
        int debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len);
 #endif
+
        void save_state(FILEIO* state_fio);
        bool load_state(FILEIO* state_fio);
        
        // unique function
-       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;
-       }
-#ifdef I386_PSEUDO_BIOS
        void set_context_bios(DEVICE* device)
        {
+#ifdef I386_PSEUDO_BIOS
                d_bios = device;
-       }
+               printf("BIOS = %0x \n", device);
 #endif
-#ifdef SINGLE_MODE_DMA
+       }
+
        void set_context_dma(DEVICE* device)
        {
+#ifdef SINGLE_MODE_DMA
                d_dma = device;
-       }
+               printf("DMA = %0x \n", device);
 #endif
+       }
+
 #ifdef USE_DEBUGGER
        void set_context_debugger(DEBUGGER* device)
        {
                d_debugger = device;
        }
 #endif
-       void set_address_mask(uint32_t mask);
-       uint32_t get_address_mask();
-       void set_shutdown_flag(int shutdown);
-       int get_shutdown_flag();
+
 };
 
 #endif
diff --git a/source/src/vm/i386_base.cpp b/source/src/vm/i386_base.cpp
new file mode 100644 (file)
index 0000000..3424c20
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+       Skelton for retropc emulator
+
+       Origin : MAME i386 core
+       Author : Takeda.Toshiya
+       Date  : 2009.06.08-
+
+       [ i386/i486/Pentium/MediaGX ]
+*/
+
+#include "i386_base.h"
+
+/* ----------------------------------------------------------------------------
+       MAME i386
+---------------------------------------------------------------------------- */
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#pragma warning( disable : 4018 )
+#pragma warning( disable : 4065 )
+#pragma warning( disable : 4146 )
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4996 )
+#endif
+
+#ifndef __BIG_ENDIAN__
+#define LSB_FIRST
+#endif
+
+extern "C" {
+#ifndef INLINE
+#define INLINE inline
+#endif
+
+#define U64(v) UINT64(v)
+
+#define fatalerror(...) exit(1)
+#define logerror(...)
+#define popmessage(...)
+
+/*****************************************************************************/
+/* src/emu/devcpu.h */
+
+/*****************************************************************************/
+/* src/emu/didisasm.h */
+
+// Disassembler constants
+const UINT32 DASMFLAG_SUPPORTED     = 0x80000000;   // are disassembly flags supported?
+const UINT32 DASMFLAG_STEP_OUT      = 0x40000000;   // this instruction should be the end of a step out sequence
+const UINT32 DASMFLAG_STEP_OVER     = 0x20000000;   // this instruction should be stepped over by setting a breakpoint afterwards
+const UINT32 DASMFLAG_OVERINSTMASK  = 0x18000000;   // number of extra instructions to skip when stepping over
+const UINT32 DASMFLAG_OVERINSTSHIFT = 27;           // bits to shift after masking to get the value
+const UINT32 DASMFLAG_LENGTHMASK    = 0x0000ffff;   // the low 16-bits contain the actual length
+
+/*****************************************************************************/
+/* src/emu/diexec.h */
+
+// I/O line states
+enum line_state
+{
+       CLEAR_LINE = 0,                         // clear (a fired or held) line
+       ASSERT_LINE,                            // assert an interrupt immediately
+       HOLD_LINE,                              // hold interrupt line until acknowledged
+       PULSE_LINE                              // pulse interrupt line instantaneously (only for NMI, RESET)
+};
+
+enum
+{
+       INPUT_LINE_IRQ = 0,
+       INPUT_LINE_NMI
+};
+
+/*****************************************************************************/
+/* src/emu/dimemory.h */
+
+// Translation intentions
+const int TRANSLATE_TYPE_MASK       = 0x03;     // read write or fetch
+const int TRANSLATE_USER_MASK       = 0x04;     // user mode or fully privileged
+const int TRANSLATE_DEBUG_MASK      = 0x08;     // debug mode (no side effects)
+
+const int TRANSLATE_READ            = 0;        // translate for read
+const int TRANSLATE_WRITE           = 1;        // translate for write
+const int TRANSLATE_FETCH           = 2;        // translate for instruction fetch
+const int TRANSLATE_READ_USER       = (TRANSLATE_READ | TRANSLATE_USER_MASK);
+const int TRANSLATE_WRITE_USER      = (TRANSLATE_WRITE | TRANSLATE_USER_MASK);
+const int TRANSLATE_FETCH_USER      = (TRANSLATE_FETCH | TRANSLATE_USER_MASK);
+const int TRANSLATE_READ_DEBUG      = (TRANSLATE_READ | TRANSLATE_DEBUG_MASK);
+const int TRANSLATE_WRITE_DEBUG     = (TRANSLATE_WRITE | TRANSLATE_DEBUG_MASK);
+const int TRANSLATE_FETCH_DEBUG     = (TRANSLATE_FETCH | TRANSLATE_DEBUG_MASK);
+
+/*****************************************************************************/
+/* src/emu/emucore.h */
+
+// constants for expression endianness
+enum endianness_t
+{
+       ENDIANNESS_LITTLE,
+       ENDIANNESS_BIG
+};
+
+// declare native endianness to be one or the other
+#ifdef LSB_FIRST
+const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_LITTLE;
+#else
+const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_BIG;
+#endif
+// endian-based value: first value is if 'endian' is little-endian, second is if 'endian' is big-endian
+#define ENDIAN_VALUE_LE_BE(endian,leval,beval) (((endian) == ENDIANNESS_LITTLE) ? (leval) : (beval))
+// endian-based value: first value is if native endianness is little-endian, second is if native is big-endian
+#define NATIVE_ENDIAN_VALUE_LE_BE(leval,beval) ENDIAN_VALUE_LE_BE(ENDIANNESS_NATIVE, leval, beval)
+// endian-based value: first value is if 'endian' matches native, second is if 'endian' doesn't match native
+#define ENDIAN_VALUE_NE_NNE(endian,leval,beval)        (((endian) == ENDIANNESS_NATIVE) ? (neval) : (nneval))
+
+/*****************************************************************************/
+/* src/emu/memory.h */
+
+// address spaces
+enum address_spacenum
+{
+       AS_0,                           // first address space
+       AS_1,                           // second address space
+       AS_2,                           // third address space
+       AS_3,                           // fourth address space
+       ADDRESS_SPACES,                 // maximum number of address spaces
+
+       // alternate address space names for common use
+       AS_PROGRAM = AS_0,              // program address space
+       AS_DATA = AS_1,                 // data address space
+       AS_IO = AS_2                    // I/O address space
+};
+
+// offsets and addresses are 32-bit (for now...)
+typedef UINT32 offs_t;
+
+/*****************************************************************************/
+/* src/osd/osdcomm.h */
+
+/* Highly useful macro for compile-time knowledge of an array size */
+#define ARRAY_LENGTH(x)     (sizeof(x) / sizeof(x[0]))
+
+static CPU_TRANSLATE(i386);
+}
+#include "mame/lib/softfloat/softfloat.c"
+#include "mame/emu/cpu/vtlb.c"
+#include "mame/emu/cpu/i386/i386.c"
+
+
+void I386_BASE::initialize()
+{
+//     i386_state *cpustate = (i386_state *)opaque;
+//     cpustate->pic = d_pic;
+//     cpustate->program = d_mem;
+//     cpustate->io = d_io;
+//     cpustate->bios = d_bios;
+//     cpustate->dma = d_dma;
+//     cpustate->shutdown = 0;
+}
+
+void I386_BASE::release()
+{
+       i386_state *cpustate = (i386_state *)opaque;
+       vtlb_free(cpustate->vtlb);
+       free(opaque);
+}
+
+void I386_BASE::reset()
+{
+       //i386_state *cpustate = (i386_state *)opaque;
+       //CPU_RESET_CALL(CPU_MODEL);
+}
+
+int I386_BASE::run(int cycles)
+{
+       //i386_state *cpustate = (i386_state *)opaque;
+       return 0;
+       //return CPU_EXECUTE_CALL(i386);
+}
+
+void I386_BASE::write_signal(int id, uint32_t data, uint32_t mask)
+{
+       i386_state *cpustate = (i386_state *)opaque;
+       
+       if(id == SIG_CPU_NMI) {
+               i386_set_irq_line(cpustate, INPUT_LINE_NMI, (data & mask) ? HOLD_LINE : CLEAR_LINE);
+       } else if(id == SIG_CPU_IRQ) {
+               i386_set_irq_line(cpustate, INPUT_LINE_IRQ, (data & mask) ? HOLD_LINE : CLEAR_LINE);
+       } else if(id == SIG_CPU_BUSREQ) {
+               cpustate->busreq = (data & mask) ? 1 : 0;
+       } else if(id == SIG_I386_A20) {
+               i386_set_a20_line(cpustate, data & mask);
+       }
+}
+
+void I386_BASE::set_intr_line(bool line, bool pending, uint32_t bit)
+{
+       i386_state *cpustate = (i386_state *)opaque;
+       i386_set_irq_line(cpustate, INPUT_LINE_IRQ, line ? HOLD_LINE : CLEAR_LINE);
+}
+
+void I386_BASE::set_extra_clock(int cycles)
+{
+       i386_state *cpustate = (i386_state *)opaque;
+       cpustate->extra_cycles += cycles;
+}
+
+int I386_BASE::get_extra_clock()
+{
+       i386_state *cpustate = (i386_state *)opaque;
+       return cpustate->extra_cycles;
+}
+
+uint32_t I386_BASE::get_pc()
+{
+       i386_state *cpustate = (i386_state *)opaque;
+       return cpustate->prev_pc;
+}
+
+uint32_t I386_BASE::get_next_pc()
+{
+       i386_state *cpustate = (i386_state *)opaque;
+       return cpustate->pc;
+}
+
+void I386_BASE::set_address_mask(uint32_t mask)
+{
+       i386_state *cpustate = (i386_state *)opaque;
+       cpustate->a20_mask = mask;
+}
+
+uint32_t I386_BASE::get_address_mask()
+{
+       i386_state *cpustate = (i386_state *)opaque;
+       return cpustate->a20_mask;
+}
+
+void I386_BASE::set_shutdown_flag(int shutdown)
+{
+       i386_state *cpustate = (i386_state *)opaque;
+       cpustate->shutdown = shutdown;
+}
+
+int I386_BASE::get_shutdown_flag()
+{
+       i386_state *cpustate = (i386_state *)opaque;
+       return cpustate->shutdown;
+}
+
+#define STATE_VERSION  1
+
+void I386_BASE::save_state(FILEIO* state_fio)
+{
+       state_fio->FputUint32(STATE_VERSION);
+       state_fio->FputInt32(this_device_id);
+       
+       state_fio->Fwrite(opaque, sizeof(i386_state), 1);
+}
+
+bool I386_BASE::load_state(FILEIO* state_fio)
+{
+       if(state_fio->FgetUint32() != STATE_VERSION) {
+               return false;
+       }
+       if(state_fio->FgetInt32() != this_device_id) {
+               return false;
+       }
+       state_fio->Fread(opaque, sizeof(i386_state), 1);
+       
+       // post process
+       i386_state *cpustate = (i386_state *)opaque;
+       cpustate->pic = d_pic;
+       cpustate->program = d_mem;
+       cpustate->io = d_io;
+
+       cpustate->bios = d_bios;
+       cpustate->dma = d_dma;
+
+       return true;
+}
+
diff --git a/source/src/vm/i386_base.h b/source/src/vm/i386_base.h
new file mode 100644 (file)
index 0000000..c3888d1
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+       Skelton for retropc emulator
+
+       Origin : MAME i386 core
+       Author : Takeda.Toshiya
+       Date  : 2009.06.08-
+
+       [ i386/i486/Pentium/MediaGX ]
+*/
+
+#ifndef _I386_BASE_H_ 
+#define _I386_BASE_H_
+
+//#include "vm.h"
+//#include "../emu.h"
+#include <assert.h>
+#include "device.h"
+
+#define SIG_I386_A20   1
+
+class VM;
+class EMU;
+class DEBUGGER;
+class I386_BASE : public DEVICE
+{
+protected:
+       DEVICE *d_mem, *d_io, *d_pic;
+
+       DEVICE *d_bios;
+       DEVICE *d_dma;
+       void *opaque;
+       
+public:
+       I386_BASE(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+       {
+               d_bios = NULL;
+               d_dma = NULL;
+               set_device_name(_T("i80x86 CPU BASE"));
+       }
+       ~I386_BASE() {}
+       
+       // common functions
+       virtual void initialize();
+       void release();
+       virtual void reset();
+       virtual int run(int cycles);
+       void write_signal(int id, uint32_t data, uint32_t mask);
+       void set_intr_line(bool line, bool pending, uint32_t bit);
+       void set_extra_clock(int cycles);
+       int get_extra_clock();
+       uint32_t get_pc();
+       uint32_t get_next_pc();
+       
+       virtual void save_state(FILEIO* state_fio);
+       virtual bool load_state(FILEIO* state_fio);
+       
+       // unique function
+       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;
+       }
+       virtual void set_context_bios(DEVICE* device) {}
+       virtual void set_context_dma(DEVICE* device) {}
+       void set_address_mask(uint32_t mask);
+       uint32_t get_address_mask();
+       void set_shutdown_flag(int shutdown);
+       int get_shutdown_flag();
+};
+
+#endif