#include "vm.h"
#include "../emu.h"
#include "./i386.h"
-#include "./libcpu_i386/i386opdef_real.h"
+#include "./libcpu_i386/i386_real.h"
#ifdef USE_DEBUGGER
#include "debugger.h"
#endif
#define CPU_MODEL pentium4
#endif
-
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;
- cpustate->bios = d_bios;
- cpustate->dma = d_dma;
- cpustate->shutdown = 0;
+ DEVICE::initialize();
+ cpucore = new I386_OPS;
+#if defined(HAS_I386)
+ cpucore->cpu_init_i386();
+#elif defined(HAS_I486)
+ cpucore->cpu_init_i486();
+#elif defined(HAS_PENTIUM)
+ cpucore->cpu_init_pentium();
+#elif defined(HAS_MEDIAGX)
+ cpucore->cpu_init_mediagx();
+#elif defined(HAS_PENTIUM_PRO)
+ cpucore->cpu_init_pentium_pro();
+#elif defined(HAS_PENTIUM_MMX)
+ cpucore->cpu_init_pentium_mmx();
+#elif defined(HAS_PENTIUM2)
+ cpucore->cpu_init_pentium2();
+#elif defined(HAS_PENTIUM3)
+ cpucore->cpu_init_pentium3();
+#elif defined(HAS_PENTIUM4)
+ cpucore->cpu_init_pentium4();
+#endif
+ cpucore->set_context_pic(d_pic);
+ cpucore->set_context_progmem(d_mem);
+ cpucore->set_context_io(d_io);
+#ifdef I386_PSEUDO_BIOS
+ cpucore->set_context_pseudo_bios(d_bios);
+#endif
+#ifdef SINGLE_MODE_DMA
+ cpucore->set_context_dma(d_dma);
+#endif
#ifdef USE_DEBUGGER
- cpustate->emu = emu;
- cpustate->debugger = d_debugger;
- cpustate->program_stored = d_mem;
- cpustate->io_stored = d_io;
+ cpucore->set_context_emu(emu);
+ cpucore->set_context_debugger(d_debugger);
+ cpucore->set_context_progmem_stored(d_mem);
+ cpucore->set_context_io_stored(d_io);
d_debugger->set_context_mem(d_mem);
d_debugger->set_context_io(d_io);
#endif
- cpustate->shutdown = 0;
+ cpucore->set_shutdown_flag(0);
}
void I386::reset()
{
- i386_state *cpustate = (i386_state *)opaque;
- CPU_RESET_CALL(CPU_MODEL);
+#if defined(HAS_I386)
+ cpucore->cpu_reset_i386();
+#elif defined(HAS_I486)
+ cpucore->cpu_reset_i486();
+#elif defined(HAS_PENTIUM)
+ cpucore->cpu_reset_pentium();
+#elif defined(HAS_MEDIAGX)
+ cpucore->cpu_reset_mediagx();
+#elif defined(HAS_PENTIUM_PRO)
+ cpucore->cpu_reset_pentium_pro();
+#elif defined(HAS_PENTIUM_MMX)
+ cpucore->cpu_reset_pentium_mmx();
+#elif defined(HAS_PENTIUM2)
+ cpucore->cpu_reset_pentium2();
+#elif defined(HAS_PENTIUM3)
+ cpucore->cpu_reset_pentium3();
+#elif defined(HAS_PENTIUM4)
+ cpucore->cpu_reset_pentium4();
+#endif
}
int I386::run(int cycles)
{
- i386_state *cpustate = (i386_state *)opaque;
- return cpu_execute((void *)cpustate, cycles);
- //return CPU_EXECUTE_CALL(i386);
-}
-
-extern "C" {
-extern void I386OP(decode_opcode)(i386_state *cpustate);
-};
-
-int I386::cpu_execute(void *p, int cycles)
-{
- 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;
- }
- }
-
- if (cycles == -1) {
- cpustate->cycles = 1;
- } 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;
-
- 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
- }
-
- /* 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;
+ return cpucore->cpu_execute_i386(cycles);
}
bool I386::write_debug_reg(const _TCHAR *reg, uint32_t data)
{
- i386_state *cpustate = (i386_state *)opaque;
- if(_tcsicmp(reg, _T("IP")) == 0) {
- cpustate->eip = data & 0xffff;
- CHANGE_PC(cpustate, cpustate->eip);
- } else if(_tcsicmp(reg, _T("AX")) == 0) {
- REG16(AX) = data;
- } else if(_tcsicmp(reg, _T("BX")) == 0) {
- REG16(BX) = data;
- } else if(_tcsicmp(reg, _T("CX")) == 0) {
- REG16(CX) = data;
- } else if(_tcsicmp(reg, _T("DX")) == 0) {
- REG16(DX) = data;
- } else if(_tcsicmp(reg, _T("SP")) == 0) {
- REG16(SP) = data;
- } else if(_tcsicmp(reg, _T("BP")) == 0) {
- REG16(BP) = data;
- } else if(_tcsicmp(reg, _T("SI")) == 0) {
- REG16(SI) = data;
- } else if(_tcsicmp(reg, _T("DI")) == 0) {
- REG16(DI) = data;
- } else if(_tcsicmp(reg, _T("AL")) == 0) {
- REG8(AL) = data;
- } else if(_tcsicmp(reg, _T("AH")) == 0) {
- REG8(AH) = data;
- } else if(_tcsicmp(reg, _T("BL")) == 0) {
- REG8(BL) = data;
- } else if(_tcsicmp(reg, _T("BH")) == 0) {
- REG8(BH) = data;
- } else if(_tcsicmp(reg, _T("CL")) == 0) {
- REG8(CL) = data;
- } else if(_tcsicmp(reg, _T("CH")) == 0) {
- REG8(CH) = data;
- } else if(_tcsicmp(reg, _T("DL")) == 0) {
- REG8(DL) = data;
- } else if(_tcsicmp(reg, _T("DH")) == 0) {
- REG8(DH) = data;
- } else {
- return false;
- }
- return false;
+ return cpucore->write_debug_reg(reg, data);
+}
+
+uint32_t I386::read_debug_reg(const _TCHAR *reg)
+{
+ return cpucore->read_debug_reg(reg);
}
void I386::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
{
- i386_state *cpustate = (i386_state *)opaque;
+ i386_state *cpustate = cpucore->get_cpu_state();
+//#if defined(USE_DEBUGGER)
my_stprintf_s(buffer, buffer_len,
- _T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\nDS=%04X ES=%04X SS=%04X CS=%04X IP=%04X FLAG=[%c%c%c%c%c%c%c%c%c]"),
- REG16(AX), REG16(BX), REG16(CX), REG16(DX), REG16(SP), REG16(BP), REG16(SI), REG16(DI),
- cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->eip,
- cpustate->OF ? _T('O') : _T('-'), cpustate->DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
- cpustate->SF ? _T('S') : _T('-'), cpustate->ZF ? _T('Z') : _T('-'), cpustate->AF ? _T('A') : _T('-'), cpustate->PF ? _T('P') : _T('-'), cpustate->CF ? _T('C') : _T('-'));
+ _T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\nDS=%04X ES=%04X SS=%04X CS=%04X IP=%04X FLAG=[%c%c%c%c%c%c%c%c%c]\nClocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
+ cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->eip,
+ cpustate->OF ? _T('O') : _T('-'), cpustate->DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
+ cpustate->SF ? _T('S') : _T('-'), cpustate->ZF ? _T('Z') : _T('-'), cpustate->AF ? _T('A') : _T('-'), cpustate->PF ? _T('P') : _T('-'),
+ cpustate->CF ? _T('C') : _T('-'),
+ cpustate->total_cycles, cpustate->total_cycles - cpustate->prev_total_cycles,
+ get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
+ cpustate->prev_total_cycles = cpustate->total_cycles;
+//#endif
}
int I386::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
{
- i386_state *cpustate = (i386_state *)opaque;
- UINT64 eip = cpustate->eip;
- UINT8 ops[16];
- for(int i = 0; i < 16; i++) {
- int wait;
- ops[i] = d_mem->read_data8w(pc + i, &wait);
- }
- UINT8 *oprom = ops;
-
- if(cpustate->operand_size) {
- return CPU_DISASSEMBLE_CALL(x86_32) & DASMFLAG_LENGTHMASK;
- } else {
- return CPU_DISASSEMBLE_CALL(x86_16) & DASMFLAG_LENGTHMASK;
+ return cpucore->debug_dasm(pc, buffer, buffer_len);
+}
+#endif
+
+void I386::set_context_bios(DEVICE* device)
+{
+#ifdef I386_PSEUDO_BIOS
+ d_bios = device;
+ if(cpucore != NULL) cpucore->set_context_pseudo_bios(d_bios);
+#endif
+}
+void I386::set_context_dma(DEVICE* device)
+{
+#ifdef SINGLE_MODE_DMA
+ d_dma = device;
+ if(cpucore != NULL) cpucore->set_context_dma(d_dma);
+#endif
+}
+
+#ifdef USE_DEBUGGER
+void I386::set_context_debugger(DEBUGGER* device)
+{
+ d_debugger = device;
+ if(cpucore != NULL) {
+ cpucore->set_context_emu(emu);
+ cpucore->set_context_debugger(d_debugger);
+ cpucore->set_context_progmem_stored(d_mem);
+ cpucore->set_context_io_stored(d_io);
}
}
#endif
+
void I386::save_state(FILEIO* state_fio)
{
I386_BASE::save_state(state_fio);
{
if(!I386_BASE::load_state(state_fio)) return false;
- i386_state *cpustate = (i386_state *)opaque;
+#ifdef I386_PSEUDO_BIOS
+ cpucore->set_context_pseudo_bios(d_bios);
+#endif
+#ifdef SINGLE_MODE_DMA
+ cpucore->set_context_dma(d_dma);
+#endif
+
#ifdef USE_DEBUGGER
- cpustate->emu = emu;
- cpustate->debugger = d_debugger;
- cpustate->program_stored = d_mem;
- cpustate->io_stored = d_io;
+ cpucore->set_context_emu(emu);
+ cpucore->set_context_debugger(d_debugger);
+ cpucore->set_context_progmem_stored(d_mem);
+ cpucore->set_context_io_stored(d_io);
+ //d_debugger->set_context_mem(d_mem);
+ //d_debugger->set_context_io(d_io);
#endif
+ cpucore->set_shutdown_flag(0);
+ return true;
+}
+
+void I386::cpu_table_call(void)
+{
+#if defined(HAS_I386)
+ cpucore->cpu_table_i386();
+#elif defined(HAS_I486)
+ cpucore->cpu_table_i486();
+#elif defined(HAS_PENTIUM)
+ cpucore->cpu_table_pentium();
+#elif defined(HAS_MEDIAGX)
+ cpucore->cpu_table_mediagx();
+#elif defined(HAS_PENTIUM_PRO)
+ cpucore->cpu_table_pentium_pro();
+#elif defined(HAS_PENTIUM_MMX)
+ cpucore->cpu_table_pentium_mmx();
+#elif defined(HAS_PENTIUM2)
+ cpucore->cpu_table_pentium2();
+#elif defined(HAS_PENTIUM3)
+ cpucore->cpu_table_pentium3();
+#elif defined(HAS_PENTIUM4)
+ cpucore->cpu_table_pentium4();
+#endif
+}
+
+
+bool I386::process_state(FILEIO* state_fio, bool loading)
+{
+ i386_state *cpustate = cpucore->get_cpu_state();
+ if(!(I386_BASE::process_state(state_fio, loading))) return false;
+// if(save != NULL && save_size > 0) {
+// state_fio->StateBuffer(save, save_size, 1);
+// }
+
+ // post process
+ if(loading) {
+#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;
+ cpustate->program_stored = d_mem;
+ cpustate->io_stored = d_io;
+ cpustate->prev_total_cycles = cpustate->total_cycles;
+#endif
+ cpu_table_call();
+
+ cpucore->set_context_pic(d_pic);
+ cpucore->set_context_progmem(d_mem);
+ cpucore->set_context_io(d_io);
+ }
return true;
}