/* * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "dosbox.h" #include "mem.h" #include "cpu.h" #include "lazyflags.h" #include "inout.h" #include "callback.h" #include "pic.h" #include "fpu.h" #if C_DEBUG #include "debug.h" #endif #define SegBase(c) SegPhys(c) #if (!C_CORE_INLINE) #define LoadMb(off) mem_readb(off) #define LoadMw(off) mem_readw(off) #define LoadMd(off) mem_readd(off) #define SaveMb(off,val) mem_writeb(off,val) #define SaveMw(off,val) mem_writew(off,val) #define SaveMd(off,val) mem_writed(off,val) #else #include "paging.h" #define LoadMb(off) mem_readb_inline(off) #define LoadMw(off) mem_readw_inline(off) #define LoadMd(off) mem_readd_inline(off) #define SaveMb(off,val) mem_writeb_inline(off,val) #define SaveMw(off,val) mem_writew_inline(off,val) #define SaveMd(off,val) mem_writed_inline(off,val) #endif #define LoadMbs(off) (Bit8s)(LoadMb(off)) #define LoadMws(off) (Bit16s)(LoadMw(off)) #define LoadMds(off) (Bit32s)(LoadMd(off)) #define LoadRb(reg) reg #define LoadRw(reg) reg #define LoadRd(reg) reg #define SaveRb(reg,val) reg=val #define SaveRw(reg,val) reg=val #define SaveRd(reg,val) reg=val extern Bitu cycle_count; #if C_FPU #define CPU_FPU 1 //Enable FPU escape instructions #endif #define CPU_PIC_CHECK 1 #define CPU_TRAP_CHECK 1 #define OPCODE_NONE 0x000 #define OPCODE_0F 0x100 #define OPCODE_SIZE 0x200 #define PREFIX_SEG 0x1 #define PREFIX_ADDR 0x2 #define PREFIX_SEG_ADDR (PREFIX_SEG|PREFIX_ADDR) #define PREFIX_REP 0x4 #define TEST_PREFIX_SEG (core.prefixes & PREFIX_SEG) #define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR) #define TEST_PREFIX_REP (core.prefixes & PREFIX_REP) #define DO_PREFIX_SEG(_SEG) \ core.prefixes|=PREFIX_SEG; \ core.seg_prefix_base=SegBase(_SEG); \ goto restart_prefix; #define DO_PREFIX_ADDR() \ core.prefixes^=PREFIX_ADDR; \ goto restart_prefix; #define DO_PREFIX_REP(_ZERO) \ core.prefixes|=PREFIX_REP; \ core.rep_zero=_ZERO; \ goto restart_prefix; typedef PhysPt (*GetEATable[256])(void); static struct { Bitu opcode_index; Bitu prefixes; Bitu index_default; Bitu prefix_default; PhysPt op_start; PhysPt ip_lookup; PhysPt seg_prefix_base; bool rep_zero; GetEATable * ea_table; struct { bool skip; } trap; } core; #include "instructions.h" #include "core_normal/support.h" #include "core_normal/string.h" static GetEATable * EAPrefixTable[8] = { &GetEA_NONE,&GetEA_SEG,&GetEA_ADDR,&GetEA_SEG_ADDR, &GetEA_NONE,&GetEA_SEG,&GetEA_ADDR,&GetEA_SEG_ADDR, }; #define CASE_W(_WHICH) \ case (OPCODE_NONE+_WHICH): #define CASE_D(_WHICH) \ case (OPCODE_SIZE+_WHICH): #define CASE_B(_WHICH) \ CASE_W(_WHICH) \ CASE_D(_WHICH) #define CASE_0F_W(_WHICH) \ case ((OPCODE_0F|OPCODE_NONE)+_WHICH): #define CASE_0F_D(_WHICH) \ case ((OPCODE_0F|OPCODE_SIZE)+_WHICH): #define CASE_0F_B(_WHICH) \ CASE_0F_W(_WHICH) \ CASE_0F_D(_WHICH) #define EALookupTable (*(core.ea_table)) Bits CPU_Core_Normal_Run(void) { decode_start: if (cpu.code.big) { core.index_default=0x200; core.prefix_default=PREFIX_ADDR; } else { core.index_default=0; core.prefix_default=0; } LOADIP; lflags.type=t_UNKNOWN; while (CPU_Cycles-->0) { core.op_start=core.ip_lookup; core.opcode_index=core.index_default; core.prefixes=core.prefix_default; #if C_DEBUG cycle_count++; #if C_HEAVY_DEBUG SAVEIP; if (DEBUG_HeavyIsBreakpoint()) { LEAVECORE; return debugCallback; }; #endif #endif restart_prefix: core.ea_table=EAPrefixTable[core.prefixes]; restart_opcode: switch (core.opcode_index+Fetchb()) { #include "core_normal/prefix_none.h" #include "core_normal/prefix_0f.h" #include "core_normal/prefix_66.h" #include "core_normal/prefix_66_0f.h" default: ADDIPFAST(-1); #if C_DEBUG LOG_MSG("Unhandled code %X",core.opcode_index+Fetchb()); #else E_Exit("Unhandled CPU opcode"); #endif } } decode_end: LEAVECORE; return CBRET_NONE; } Bits CPU_Core_Normal_Trap_Run(void) { Bits oldCycles = CPU_Cycles; CPU_Cycles = 1; core.trap.skip=false; Bits ret=CPU_Core_Normal_Run(); if (!core.trap.skip) CPU_SW_Interrupt(1,0); CPU_Cycles = oldCycles-1; cpudecoder = &CPU_Core_Normal_Run; return ret; } void CPU_Core_Normal_Init(void) { }