library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; package whatever is type cpu_export_type is record reg_ax : unsigned(15 downto 0); reg_cx : unsigned(15 downto 0); reg_dx : unsigned(15 downto 0); reg_bx : unsigned(15 downto 0); reg_sp : unsigned(15 downto 0); reg_bp : unsigned(15 downto 0); reg_si : unsigned(15 downto 0); reg_di : unsigned(15 downto 0); reg_es : unsigned(15 downto 0); reg_cs : unsigned(15 downto 0); reg_ss : unsigned(15 downto 0); reg_ds : unsigned(15 downto 0); reg_ip : unsigned(15 downto 0); reg_f : unsigned(15 downto 0); opcodebyte_last : std_logic_vector(7 downto 0); end record; end package; library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; -- use work.pexport.all; use work.pBus_savestates.all; use work.pReg_savestates.all; use work.whatever.all; entity cpu is port ( clk : in std_logic; ce : in std_logic; ce_4x : in std_logic; reset : in std_logic; turbo : in std_logic; SLOWTIMING : in std_logic; -- only used in simulation to sync up with prefetching cpu_idle : out std_logic; cpu_halt : out std_logic; cpu_irqrequest : out std_logic; cpu_prefix : out std_logic; dma_active : in std_logic; sdma_request : in std_logic; canSpeedup : out std_logic; bus_read : out std_logic := '0'; bus_write : out std_logic := '0'; bus_be : out std_logic_vector(1 downto 0) := "00"; bus_addr : out unsigned(19 downto 0) := (others => '0'); bus_datawrite : out std_logic_vector(15 downto 0) := (others => '0'); bus_dataread : in std_logic_vector(15 downto 0); irqrequest_in : in std_logic; irqvector_in : in unsigned(9 downto 0) := (others => '0'); irqrequest_ack : out std_logic := '0'; load_savestate : in std_logic; cpu_done : out std_logic := '0'; cpu_export_opcode : out std_logic_vector(7 downto 0); cpu_export_reg_cs : out unsigned(15 downto 0); cpu_export_reg_ip : out unsigned(15 downto 0); -- register RegBus_Din : out std_logic_vector(7 downto 0) := (others => '0'); RegBus_Adr : out std_logic_vector(7 downto 0) := (others => '0'); RegBus_wren : out std_logic := '0'; RegBus_rden : out std_logic := '0'; RegBus_Dout : in std_logic_vector(7 downto 0); -- savestates sleep_savestate : in std_logic; SSBUS_Din : in std_logic_vector(SSBUS_buswidth-1 downto 0); SSBUS_Adr : in std_logic_vector(SSBUS_busadr-1 downto 0); SSBUS_wren : in std_logic; SSBUS_rst : in std_logic; SSBUS_Dout : out std_logic_vector(SSBUS_buswidth-1 downto 0) ); end entity; architecture arch of cpu is -- push/pop constant REGPOS_ax : std_logic_vector(15 downto 0) := x"0001"; constant REGPOS_cx : std_logic_vector(15 downto 0) := x"0002"; constant REGPOS_dx : std_logic_vector(15 downto 0) := x"0004"; constant REGPOS_bx : std_logic_vector(15 downto 0) := x"0008"; constant REGPOS_sp : std_logic_vector(15 downto 0) := x"0010"; constant REGPOS_bp : std_logic_vector(15 downto 0) := x"0020"; constant REGPOS_si : std_logic_vector(15 downto 0) := x"0040"; constant REGPOS_di : std_logic_vector(15 downto 0) := x"0080"; constant REGPOS_es : std_logic_vector(15 downto 0) := x"0100"; constant REGPOS_f : std_logic_vector(15 downto 0) := x"0200"; constant REGPOS_cs : std_logic_vector(15 downto 0) := x"0400"; constant REGPOS_ss : std_logic_vector(15 downto 0) := x"0800"; constant REGPOS_ds : std_logic_vector(15 downto 0) := x"1000"; constant REGPOS_ip : std_logic_vector(15 downto 0) := x"2000"; constant REGPOS_mem : std_logic_vector(15 downto 0) := x"4000"; constant REGPOS_imm : std_logic_vector(15 downto 0) := x"8000"; type tPrefetchState is ( PREFETCH_IDLE, PREFETCH_READ, PREFETCH_WAIT, PREFETCH_RECEIVE ); signal prefetchState : tPrefetchState; type tCPUSTAGE is ( CPUSTAGE_IDLE, CPUSTAGE_DECODEOP, CPUSTAGE_MODRM, CPUSTAGE_CHECKDATAREADY, CPUSTAGE_FETCHDATA1_8, CPUSTAGE_FETCHDATA1_16, CPUSTAGE_FETCHDATA2_8, CPUSTAGE_FETCHDATA2_16, CPUSTAGE_FETCHMEM_REQ, CPUSTAGE_FETCHMEM_WAIT, CPUSTAGE_FETCHMEM_REC, CPUSTAGE_IRQVECTOR_REQ, CPUSTAGE_IRQVECTOR_WAIT, CPUSTAGE_IRQVECTOR_REC, CPUSTAGE_PUSH, CPUSTAGE_POP_REQ, CPUSTAGE_POP_WAIT, CPUSTAGE_POP_REC, CPUSTAGE_EXECUTE ); signal cpustage : tCPUSTAGE; type tCPU_Opcode is ( --modrm OP_MEMIMM1, OP_MEMIMM2, OP_MEMIMM3, OP_MEMIMM4, -- final OP_MOVMEM, OP_MOVREG, OP_EXCHANGE, OP_BOUND, OP_OPIN, OP_OPOUT, OP_BCDSTRING, OP_STRINGLOAD, OP_STRINGCOMPARE, OP_STRINGSTORE, OP_ENTER, OP_JUMPIF, OP_JUMP, OP_JUMPABS, OP_JUMPFAR, OP_RETURNFAR, OP_IRQ, OP_IRQREQUEST, OP_FLAGSFROMACC, OP_FLAGSTOACC, OP_DIV, OP_DIVI, OP_MULADJUST, OP_DIVADJUST, OP_NOP, OP_INVALID ); type tOPSOURCE is ( OPSOURCE_FETCHVALUE8, OPSOURCE_FETCHVALUE16, OPSOURCE_MEM, OPSOURCE_MODRM_REG, OPSOURCE_MODRM_ADDR, OPSOURCE_ACC, OPSOURCE_IMMIDIATE, OPSOURCE_POPVALUE, OPSOURCE_STRINGLOAD1, OPSOURCE_STRINGLOAD2, OPSOURCE_IRQVECTOR, OPSOURCE_REG_ax, OPSOURCE_REG_cx, OPSOURCE_REG_dx, OPSOURCE_REG_bx, OPSOURCE_REG_sp, OPSOURCE_REG_bp, OPSOURCE_REG_si, OPSOURCE_REG_di, OPSOURCE_INVALID ); type tOPTARGET is ( OPTARGET_DECODE, OPTARGET_MEM, OPTARGET_MODRM_REG, OPTARGET_NONE ); type tCPU_REG is ( CPU_REG_al, CPU_REG_ah, CPU_REG_ax, CPU_REG_bl, CPU_REG_bh, CPU_REG_bx, CPU_REG_cl, CPU_REG_ch, CPU_REG_cx, CPU_REG_dl, CPU_REG_dh, CPU_REG_dx, CPU_REG_sp, CPU_REG_bp, CPU_REG_si, CPU_REG_di, CPU_REG_es, CPU_REG_cs, CPU_REG_ss, CPU_REG_ds, CPU_REG_ip, CPU_REG_f, CPU_REG_NONE ); type tALU_OP is ( ALU_OP_AND, ALU_OP_OR, ALU_OP_XOR, ALU_OP_NOT, ALU_OP_NEG, ALU_OP_ADD, ALU_OP_ADC, ALU_OP_INC, ALU_OP_SUB, ALU_OP_SBB, ALU_OP_DEC, ALU_OP_CMP, ALU_OP_TST, ALU_OP_ROL, ALU_OP_ROR, ALU_OP_RCL, ALU_OP_RCR, ALU_OP_SHL, ALU_OP_SHR, ALU_OP_SAL, ALU_OP_SAR, ALU_OP_MUL, ALU_OP_MULI, ALU_OP_DIV, ALU_OP_DIVI, ALU_OP_SXT, ALU_OP_DECADJUST, ALU_OP_ASCIIADJUST, ALU_OP_SET1, ALU_OP_CLR1, ALU_OP_NOT1, ALU_OP_TEST1, ALU_OP_ROR4, ALU_OP_ROL4, ALU_OP_NOTHING ); type tBCD_OP is ( BCD_OP_ADD, BCD_OP_SUB, BCD_OP_CMP ); -- decodedInstruction signal opcode : tCPU_Opcode; signal opcodeNext : tCPU_Opcode; signal source1 : tOPSOURCE; signal source2 : tOPSOURCE; signal optarget : tOPTARGET; signal optarget2 : tOPTARGET; signal target_reg : tCPU_REG; signal target_reg2 : tCPU_REG; signal target_decode : tCPU_REG; signal Repeat : std_logic; signal RepeatNext : std_logic; signal PrefixIP : unsigned(3 downto 0); signal segmentaccess : std_logic; signal prefixSegmentES : std_logic; signal prefixSegmentCS : std_logic; signal prefixSegmentSS : std_logic; signal prefixSegmentDS : std_logic; signal aluop : tALU_OP; signal bcdOp : tBCD_OP; signal useAluResult : std_logic; signal memSegment : unsigned(15 downto 0); signal pushlist : std_logic_vector(15 downto 0); signal poplist : std_logic_vector(15 downto 0); signal reg_sp_push : unsigned(15 downto 0); signal fetchedSource1 : std_logic; signal fetchedSource2 : std_logic; signal opsign : std_logic; signal irqBlocked : std_logic; signal reqModRM : std_logic; signal repeatZero : std_logic; signal opsize : integer range 1 to 2; signal instantFetch : std_logic; signal fetch1Val : unsigned(15 downto 0); signal fetch2Val : unsigned(15 downto 0); signal memFetchValue1 : unsigned(15 downto 0); signal memFetchValue2 : unsigned(15 downto 0); signal MODRM_value_reg : unsigned(15 downto 0); signal memAddr : unsigned(15 downto 0); signal immidiate8 : unsigned( 7 downto 0); signal poptarget : integer range 0 to 14; signal popval : unsigned(15 downto 0); signal stringLoad : unsigned(15 downto 0); signal stringLoad2 : unsigned(15 downto 0); signal unaligned1 : std_logic; signal unaligned2 : std_logic; signal irqrequest : std_logic; signal irqExtern : std_logic; signal irqvector : unsigned(9 downto 0); signal irqIP : unsigned(15 downto 0); signal irqCS : unsigned(15 downto 0); signal adjustNegate : std_logic; signal enterCnt : unsigned(5 downto 0); signal bcdOffset : unsigned(6 downto 0); signal bcdAcc : unsigned(7 downto 0); type tMemAccessType is ( MEMACC_NONE, MEMACC_PREFETCH, MEMACC_MEMFETCH, MEMACC_MEMWRITE, MEMACC_POP, MEMACC_STRINGLOAD1, MEMACC_STRINGLOAD2, MEMACC_IRQFETCH1, MEMACC_IRQFETCH2 ); signal MemAccessType : tMemAccessType; type tRegister is record reg_ax : unsigned(15 downto 0); reg_cx : unsigned(15 downto 0); reg_dx : unsigned(15 downto 0); reg_bx : unsigned(15 downto 0); reg_sp : unsigned(15 downto 0); reg_bp : unsigned(15 downto 0); reg_si : unsigned(15 downto 0); reg_di : unsigned(15 downto 0); reg_es : unsigned(15 downto 0); reg_cs : unsigned(15 downto 0); reg_ss : unsigned(15 downto 0); reg_ds : unsigned(15 downto 0); reg_ip : unsigned(15 downto 0); FlagCar : std_logic; FlagPar : std_logic; FlagHaC : std_logic; FlagZer : std_logic; FlagSgn : std_logic; FlagBrk : std_logic; FlagIrq : std_logic; FlagDir : std_logic; FlagOvf : std_logic; FlagMod : std_logic; end record; signal regs : tRegister; signal Reg_f : unsigned(15 downto 0); -- prefetch signal prefetchCount : integer range 0 to 15; signal prefetchBuffer : std_logic_vector(127 downto 0); signal prefetchAddr : unsigned(19 downto 0); signal prefetchAddrOld : unsigned(19 downto 0); signal prefetch1byte : std_logic; signal clearPrefetch : std_logic; signal consumePrefetch : integer range 0 to 3; signal prefetchAllow : std_logic; signal prefetchDisturb : std_logic; -- control and decode signal delay : integer range 0 to 31; signal dbuf : integer range 0 to 7; signal opcodebyte : std_logic_vector(7 downto 0); signal exOpcodebyte : std_logic_vector(7 downto 0); signal halt : std_logic := '0'; signal memFirst : std_logic := '0'; signal lastaddr : unsigned(19 downto 0); signal cpu_finished : std_logic := '0'; signal opstep : integer range 0 to 7; signal waitexe : std_logic; signal pushFirst : std_logic; signal popFirst : std_logic; signal popUnalnByte : std_logic_vector(7 downto 0); signal flagCarry : std_logic; attribute keep : string; attribute keep of exOpcodebyte : signal is "true"; -- divider signal DIVstart : std_logic; signal DIVdividend : signed(32 downto 0); signal DIVdivisor : signed(32 downto 0); signal DIVquotient : signed(32 downto 0); signal DIVremainder : signed(32 downto 0); -- savestates signal SS_CPU1 : std_logic_vector(REG_SAVESTATE_CPU1.upper downto REG_SAVESTATE_CPU1.lower); signal SS_CPU2 : std_logic_vector(REG_SAVESTATE_CPU2.upper downto REG_SAVESTATE_CPU2.lower); signal SS_CPU3 : std_logic_vector(REG_SAVESTATE_CPU3.upper downto REG_SAVESTATE_CPU3.lower); signal SS_CPU4 : std_logic_vector(REG_SAVESTATE_CPU4.upper downto REG_SAVESTATE_CPU4.lower); signal SS_CPU_BACK1 : std_logic_vector(REG_SAVESTATE_CPU1.upper downto REG_SAVESTATE_CPU1.lower); signal SS_CPU_BACK2 : std_logic_vector(REG_SAVESTATE_CPU2.upper downto REG_SAVESTATE_CPU2.lower); signal SS_CPU_BACK3 : std_logic_vector(REG_SAVESTATE_CPU3.upper downto REG_SAVESTATE_CPU3.lower); signal SS_CPU_BACK4 : std_logic_vector(REG_SAVESTATE_CPU4.upper downto REG_SAVESTATE_CPU4.lower); type t_ss_wired_or is array(0 to 3) of std_logic_vector(63 downto 0); signal ss_wired_or : t_ss_wired_or; -- debug signal executeDone : std_logic := '0'; signal dma_active_1 : std_logic := '0'; signal testcmd : unsigned(31 downto 0); signal testpcsum : unsigned(63 downto 0); begin cpu_idle <= '1' when cpustage = CPUSTAGE_IDLE else '0'; cpu_halt <= halt; cpu_irqrequest <= irqrequest; cpu_prefix <= '1' when PrefixIP > 0 else '0'; canSpeedup <= '1'; Reg_f(0 ) <= regs.FlagCar; Reg_f(1 ) <= '1' ; Reg_f(2 ) <= regs.FlagPar; Reg_f(3 ) <= '0' ; Reg_f(4 ) <= regs.FlagHaC; Reg_f(5 ) <= '0' ; Reg_f(6 ) <= regs.FlagZer; Reg_f(7 ) <= regs.FlagSgn; Reg_f(8 ) <= regs.FlagBrk; Reg_f(9 ) <= regs.FlagIrq; Reg_f(10) <= regs.FlagDir; Reg_f(11) <= regs.FlagOvf; Reg_f(12) <= '1' ; Reg_f(13) <= '1' ; Reg_f(14) <= '1' ; Reg_f(15) <= regs.FlagMod; -- savestate iSS_CPU1 : entity work.eReg_SS generic map ( REG_SAVESTATE_CPU1 ) port map (clk, SSBUS_Din, SSBUS_Adr, SSBUS_wren, SSBUS_rst, ss_wired_or(0), SS_CPU_BACK1, SS_CPU1); iSS_CPU2 : entity work.eReg_SS generic map ( REG_SAVESTATE_CPU2 ) port map (clk, SSBUS_Din, SSBUS_Adr, SSBUS_wren, SSBUS_rst, ss_wired_or(1), SS_CPU_BACK2, SS_CPU2); iSS_CPU3 : entity work.eReg_SS generic map ( REG_SAVESTATE_CPU3 ) port map (clk, SSBUS_Din, SSBUS_Adr, SSBUS_wren, SSBUS_rst, ss_wired_or(2), SS_CPU_BACK3, SS_CPU3); iSS_CPU4 : entity work.eReg_SS generic map ( REG_SAVESTATE_CPU4 ) port map (clk, SSBUS_Din, SSBUS_Adr, SSBUS_wren, SSBUS_rst, ss_wired_or(3), SS_CPU_BACK4, SS_CPU4); process (ss_wired_or) variable wired_or : std_logic_vector(63 downto 0); begin wired_or := ss_wired_or(0); for i in 1 to (ss_wired_or'length - 1) loop wired_or := wired_or or ss_wired_or(i); end loop; SSBUS_Dout <= wired_or; end process; SS_CPU_BACK1(15 downto 0) <= std_logic_vector(regs.reg_ip); SS_CPU_BACK1(31 downto 16) <= std_logic_vector(regs.reg_ax); SS_CPU_BACK1(47 downto 32) <= std_logic_vector(regs.reg_cx); SS_CPU_BACK1(63 downto 48) <= std_logic_vector(regs.reg_dx); SS_CPU_BACK2(15 downto 0) <= std_logic_vector(regs.reg_bx); SS_CPU_BACK2(31 downto 16) <= std_logic_vector(regs.reg_sp); SS_CPU_BACK2(47 downto 32) <= std_logic_vector(regs.reg_bp); SS_CPU_BACK2(63 downto 48) <= std_logic_vector(regs.reg_si); SS_CPU_BACK3(15 downto 0) <= std_logic_vector(regs.reg_di); SS_CPU_BACK3(31 downto 16) <= std_logic_vector(regs.reg_es); SS_CPU_BACK3(47 downto 32) <= std_logic_vector(regs.reg_cs); SS_CPU_BACK3(63 downto 48) <= std_logic_vector(regs.reg_ss); SS_CPU_BACK4(15 downto 0) <= std_logic_vector(regs.reg_ds); SS_CPU_BACK4(31 downto 16) <= std_logic_vector(Reg_f); process (clk) variable varPrefetchCount : integer range 0 to 15; variable varprefetchBuffer : std_logic_vector(127 downto 0); variable isPrefix : std_logic; variable usePrefix : std_logic; variable source1Val : unsigned(15 downto 0); variable source2Val : unsigned(15 downto 0); variable op2value : unsigned(15 downto 0); variable resultval : unsigned(15 downto 0); variable target : tCPU_REG; variable result : unsigned(15 downto 0); variable result17 : unsigned(16 downto 0); variable result32 : unsigned(31 downto 0); variable result8 : unsigned(7 downto 0); variable result8h : unsigned(7 downto 0); variable newZero : std_logic; variable newParity : std_logic; variable newSign : std_logic; variable carryWork1 : std_logic; variable carryWork2 : std_logic; variable cond : std_logic; variable exeDone : std_logic; variable pushValue : std_logic_vector(15 downto 0); variable pushindex : integer range 0 to 15; variable popindex : integer range 0 to 15; variable popValue : std_logic_vector(15 downto 0); variable popDone : std_logic; variable MODRM_mem : unsigned(2 downto 0); variable MODRM_reg : unsigned(2 downto 0); variable MODRM_mod : unsigned(1 downto 0); variable varoptarget : tOPTARGET; variable varsource1 : tOPSOURCE; variable varsource2 : tOPSOURCE; variable varfetchedSource1 : std_logic; variable varfetchedSource2 : std_logic; variable vartarget_reg : tCPU_REG; variable varmemSegment : unsigned(15 downto 0); variable varmemaddr : unsigned(15 downto 0); variable varpushlist : std_logic_vector(15 downto 0); variable fetchedRMMODData : unsigned(15 downto 0); variable newDelay : integer range 0 to 31; variable newBuf : integer range 0 to 7; variable newModDelay : integer range 0 to 31; variable newExeDelay : integer range 0 to 31; variable endRepeat : std_logic; variable newRepeat : std_logic; variable jumpNow : std_logic; variable jumpAddr : unsigned(15 downto 0); variable bcdResult : unsigned(7 downto 0); begin if rising_edge(clk) then DIVstart <= '0'; cpu_done <= '0'; bus_read <= '0'; bus_write <= '0'; if (ce_4x = '1') then clearPrefetch <= '0'; consumePrefetch <= 0; end if; if (ce = '1') then prefetchAllow <= '1'; RegBus_wren <= '0'; RegBus_rden <= '0'; irqrequest_ack <= '0'; end if; --if (testpcsum(63) = '1' and testcmd(31) = '1') then -- DIVstart <= '1'; --end if; if (sleep_savestate = '1') then prefetchDisturb <= '1'; end if; if (reset = '1') then regs.reg_ip <= unsigned(SS_CPU1(15 downto 0)); -- x"0000"; regs.reg_ax <= unsigned(SS_CPU1(31 downto 16)); -- x"0000"; regs.reg_cx <= unsigned(SS_CPU1(47 downto 32)); -- x"0000"; regs.reg_dx <= unsigned(SS_CPU1(63 downto 48)); -- x"0000"; regs.reg_bx <= unsigned(SS_CPU2(15 downto 0)); -- x"0000"; regs.reg_sp <= unsigned(SS_CPU2(31 downto 16)); -- x"2000"; regs.reg_bp <= unsigned(SS_CPU2(47 downto 32)); -- x"0000"; regs.reg_si <= unsigned(SS_CPU2(63 downto 48)); -- x"0000"; regs.reg_di <= unsigned(SS_CPU3(15 downto 0)); -- x"0000"; regs.reg_es <= unsigned(SS_CPU3(31 downto 16)); -- x"0000"; regs.reg_cs <= unsigned(SS_CPU3(47 downto 32)); -- x"FFFF"; regs.reg_ss <= unsigned(SS_CPU3(63 downto 48)); -- x"0000"; regs.reg_ds <= unsigned(SS_CPU4(15 downto 0)); -- x"0000"; regs.FlagCar <= SS_CPU4(16); --'0'; regs.FlagPar <= SS_CPU4(18); --'0'; regs.FlagHaC <= SS_CPU4(20); --'0'; regs.FlagZer <= SS_CPU4(22); --'0'; regs.FlagSgn <= SS_CPU4(23); --'0'; regs.FlagBrk <= SS_CPU4(24); --'0'; regs.FlagIrq <= SS_CPU4(25); --'0'; regs.FlagDir <= SS_CPU4(26); --'0'; regs.FlagOvf <= SS_CPU4(27); --'0'; regs.FlagMod <= SS_CPU4(31); --'1'; halt <= '0'; cpustage <= CPUSTAGE_IDLE; opcodebyte <= (others => '0'); exOpcodebyte <= (others => '0'); clearPrefetch <= '1'; delay <= 8; -- fill prefetch buffer dbuf <= 0; repeat <= '0'; repeatNext <= '0'; irqrequest <= '0'; irqBlocked <= '0'; irqrequest_ack <= '0'; prefixSegmentES <= '0'; prefixSegmentCS <= '0'; prefixSegmentSS <= '0'; prefixSegmentDS <= '0'; prefixIP <= (others => '0'); testcmd <= (others => '0'); testpcsum <= (others => '0'); RegBus_wren <= '0'; RegBus_rden <= '0'; elsif (ce_4x = '1') then dma_active_1 <= dma_active; if (ce = '1' and irqrequest_in = '1' and irqBlocked = '0' and cpustage = CPUSTAGE_IDLE) then halt <= '0'; end if; if (cpu_finished = '1' and dma_active = '0' and dma_active_1 = '1') then cpu_finished <= '0'; cpu_done <= '1'; end if; if (dma_active = '1') then delay <= 0; end if; if (ce = '1' and delay > 0) then delay <= delay - 1; if (delay = 1 and cpu_finished = '1' and dma_active = '0') then cpu_finished <= '0'; cpu_done <= '1'; end if; else case (cpustage) is when CPUSTAGE_IDLE => if (ce = '1' and sdma_request = '0') then if (irqrequest = '1') then irqrequest <= '0'; repeat <= '0'; delay <= 22; cpustage <= CPUSTAGE_IRQVECTOR_REQ; pushlist <= REGPOS_f or REGPOS_cs or REGPOS_ip; poplist <= (others => '0'); pushFirst <= '1'; opcode <= OP_IRQ; aluop <= ALU_OP_NOTHING; source1 <= OPSOURCE_IRQVECTOR; source2 <= OPSOURCE_IRQVECTOR; fetchedSource1 <= '0'; fetchedSource2 <= '0'; memFirst <= '1'; if (irqExtern = '1') then irqvector <= irqvector_in; irqrequest_ack <= '1'; end if; elsif (irqrequest_in = '1' and irqBlocked = '0' and regs.FlagIrq = '1') then irqrequest <= '1'; irqExtern <= '1'; halt <= '0'; elsif (halt = '1') then null; elsif (prefetchCount > 3 + consumePrefetch) then testpcsum <= testpcsum + regs.reg_ip; testcmd <= testcmd + 1; if (repeat = '0') then exOpcodebyte <= x"00"; if (consumePrefetch = 1) then opcodebyte <= prefetchBuffer(15 downto 8); else opcodebyte <= prefetchBuffer(7 downto 0); end if; if (repeatNext = '0') then regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; PrefixIP <= (others => '0'); end if; end if; cpustage <= CPUSTAGE_DECODEOP; if (dBuf > 6) then dBuf <= 6; end if; end if; end if; when CPUSTAGE_DECODEOP => newRepeat := '0'; if (repeatNext = '1') then if (opcodebyte = x"26" or opcodebyte = x"2E" or opcodebyte = x"36" or opcodebyte = x"3E") then regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; else RepeatNext <= '0'; Repeat <= '1'; newRepeat := '1'; end if; end if; opcode <= OP_INVALID; opcodeNext <= OP_INVALID; source1 <= OPSOURCE_INVALID; source2 <= OPSOURCE_INVALID; optarget <= OPTARGET_NONE; optarget2 <= OPTARGET_NONE; target_reg <= CPU_REG_NONE; target_reg2 <= CPU_REG_NONE; segmentaccess <= '0'; aluop <= ALU_OP_NOTHING; useAluResult <= '0'; memSegment <= Regs.reg_ds; pushlist <= (others => '0'); poplist <= (others => '0'); reg_sp_push <= Regs.reg_sp; instantFetch <= '0'; fetchedSource1 <= '0'; fetchedSource2 <= '0'; opsign <= '0'; irqBlocked <= '0'; unaligned1 <= '0'; unaligned2 <= '0'; memFirst <= '1'; opstep <= 0; waitexe <= '0'; enterCnt <= (others => '0'); irqExtern <= '0'; pushFirst <= '1'; popFirst <= '1'; flagCarry <= regs.FlagCar; isPrefix := '0'; usePrefix := '0'; newDelay := 0; newBuf := dbuf; case (opcodebyte) is when x"00" => opcode <= OP_MOVMEM; aluop <= ALU_OP_ADD; useAluResult <= '1'; opsize <= 1; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"01" => opcode <= OP_MOVMEM; aluop <= ALU_OP_ADD; useAluResult <= '1'; opsize <= 2; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"02" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADD; useAluResult <= '1'; opsize <= 1; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"03" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADD; useAluResult <= '1'; opsize <= 2; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"04" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADD; useAluResult <= '1'; opsize <= 1; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; when x"05" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADD; useAluResult <= '1'; opsize <= 2; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; when x"06" => pushlist <= REGPOS_es; cpustage <= CPUSTAGE_CHECKDATAREADY; when x"07" => poplist <= REGPOS_es; cpustage <= CPUSTAGE_CHECKDATAREADY; newDelay := 1; when x"08" => opcode <= OP_MOVMEM; aluop <= ALU_OP_OR ; useAluResult <= '1'; opsize <= 1; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"09" => opcode <= OP_MOVMEM; aluop <= ALU_OP_OR ; useAluResult <= '1'; opsize <= 2; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"0A" => opcode <= OP_MOVREG; aluop <= ALU_OP_OR ; useAluResult <= '1'; opsize <= 1; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"0B" => opcode <= OP_MOVREG; aluop <= ALU_OP_OR ; useAluResult <= '1'; opsize <= 2; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"0C" => opcode <= OP_MOVREG; aluop <= ALU_OP_OR ; useAluResult <= '1'; opsize <= 1; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; when x"0D" => opcode <= OP_MOVREG; aluop <= ALU_OP_OR ; useAluResult <= '1'; opsize <= 2; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; when x"0E" => pushlist <= REGPOS_cs; cpustage <= CPUSTAGE_CHECKDATAREADY; when x"0F" => exOpcodebyte <= prefetchBuffer(15 downto 8); regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; case (prefetchBuffer(15 downto 8)) is -- TEST1 when x"10" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_NOP; aluop <= ALU_OP_TEST1; opsize <= 1; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; when x"11" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_NOP; aluop <= ALU_OP_TEST1; opsize <= 2; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; when x"18" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_NOP; aluop <= ALU_OP_TEST1; opsize <= 1; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; when x"19" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_NOP; aluop <= ALU_OP_TEST1; opsize <= 2; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; -- CLR1 when x"12" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_CLR1; opsize <= 1; useAluResult <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; when x"13" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_CLR1; opsize <= 2; useAluResult <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; when x"1a" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_CLR1; opsize <= 1; useAluResult <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; when x"1b" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_CLR1; opsize <= 2; useAluResult <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; -- SET1 when x"14" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_SET1; opsize <= 1; useAluResult <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; when x"15" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_SET1; opsize <= 2; useAluResult <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; when x"1c" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_SET1; opsize <= 1; useAluResult <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; when x"1d" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_SET1; opsize <= 2; useAluResult <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; -- NOT1 when x"16" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_NOT1; opsize <= 1; useAluResult <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; when x"17" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_NOT1; opsize <= 2; useAluResult <= '1'; source2 <= OPSOURCE_REG_cx; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; when x"1e" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_NOT1; opsize <= 1; useAluResult <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; when x"1f" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_NOT1; opsize <= 2; useAluResult <= '1'; source2 <= OPSOURCE_FETCHVALUE8; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; -- ADD4S when x"20" => cpustage <= CPUSTAGE_EXECUTE; opcode <= OP_BCDSTRING; bcdOp <= BCD_OP_ADD; bcdOffset <= (others => '0'); regs.FlagCar <= '0'; regs.FlagZer <= '1'; -- SUB4S when x"22" => cpustage <= CPUSTAGE_EXECUTE; opcode <= OP_BCDSTRING; bcdOp <= BCD_OP_SUB; bcdOffset <= (others => '0'); regs.FlagCar <= '0'; regs.FlagZer <= '1'; -- CMP4S when x"26" => cpustage <= CPUSTAGE_EXECUTE; opcode <= OP_BCDSTRING; bcdOp <= BCD_OP_CMP; bcdOffset <= (others => '0'); regs.FlagCar <= '0'; regs.FlagZer <= '1'; -- ROL4 when x"28" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_ROL4; opsize <= 1; useAluResult <= '1'; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; -- ROR4 when x"2a" => cpustage <= CPUSTAGE_MODRM; opcode <= OP_MOVMEM; aluop <= ALU_OP_ROR4; opsize <= 1; useAluResult <= '1'; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; -- INS when x"31" => cpustage <= CPUSTAGE_IDLE; cpu_done <= '1'; halt <= '1'; -- EXT when x"33" => cpustage <= CPUSTAGE_IDLE; cpu_done <= '1'; halt <= '1'; -- INS when x"39" => cpustage <= CPUSTAGE_IDLE; cpu_done <= '1'; halt <= '1'; -- BRKEM when x"ff" => cpustage <= CPUSTAGE_IDLE; cpu_done <= '1'; halt <= '1'; when others => cpustage <= CPUSTAGE_IDLE; cpu_done <= '1'; halt <= '1'; end case; when x"10" => opcode <= OP_MOVMEM; aluop <= ALU_OP_ADC; useAluResult <= '1'; opsize <= 1; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"11" => opcode <= OP_MOVMEM; aluop <= ALU_OP_ADC; useAluResult <= '1'; opsize <= 2; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"12" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADC; useAluResult <= '1'; opsize <= 1; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"13" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADC; useAluResult <= '1'; opsize <= 2; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"14" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADC; useAluResult <= '1'; opsize <= 1; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; when x"15" => opcode <= OP_MOVREG; aluop <= ALU_OP_ADC; useAluResult <= '1'; opsize <= 2; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; when x"16" => pushlist <= REGPOS_ss; cpustage <= CPUSTAGE_CHECKDATAREADY; when x"17" => poplist <= REGPOS_ss; cpustage <= CPUSTAGE_CHECKDATAREADY; newDelay := 1; irqBlocked <= '1'; when x"18" => opcode <= OP_MOVMEM; aluop <= ALU_OP_SBB; useAluResult <= '1'; opsize <= 1; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"19" => opcode <= OP_MOVMEM; aluop <= ALU_OP_SBB; useAluResult <= '1'; opsize <= 2; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"1A" => opcode <= OP_MOVREG; aluop <= ALU_OP_SBB; useAluResult <= '1'; opsize <= 1; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"1B" => opcode <= OP_MOVREG; aluop <= ALU_OP_SBB; useAluResult <= '1'; opsize <= 2; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"1C" => opcode <= OP_MOVREG; aluop <= ALU_OP_SBB; useAluResult <= '1'; opsize <= 1; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; when x"1D" => opcode <= OP_MOVREG; aluop <= ALU_OP_SBB; useAluResult <= '1'; opsize <= 2; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; when x"1E" => pushlist <= REGPOS_ds; cpustage <= CPUSTAGE_CHECKDATAREADY; when x"1F" => poplist <= REGPOS_ds; cpustage <= CPUSTAGE_CHECKDATAREADY; newDelay := 1; when x"20" => opcode <= OP_MOVMEM; aluop <= ALU_OP_AND; useAluResult <= '1'; opsize <= 1; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"21" => opcode <= OP_MOVMEM; aluop <= ALU_OP_AND; useAluResult <= '1'; opsize <= 2; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"22" => opcode <= OP_MOVREG; aluop <= ALU_OP_AND; useAluResult <= '1'; opsize <= 1; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"23" => opcode <= OP_MOVREG; aluop <= ALU_OP_AND; useAluResult <= '1'; opsize <= 2; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"24" => opcode <= OP_MOVREG; aluop <= ALU_OP_AND; useAluResult <= '1'; opsize <= 1; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; when x"25" => opcode <= OP_MOVREG; aluop <= ALU_OP_AND; useAluResult <= '1'; opsize <= 2; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; when x"26" => prefixSegmentES <= '1'; isPrefix := '1'; irqBlocked <= '1'; usePrefix := '1'; cpu_done <= '1'; newBuf := dbuf + 1; cpustage <= CPUSTAGE_IDLE; when x"27" => opcode <= OP_MOVREG; aluop <= ALU_OP_DECADJUST; useAluResult <= '1'; newDelay := 9; opsize <= 1; cpustage <= CPUSTAGE_EXECUTE; target_decode <= CPU_REG_al; optarget <= OPTARGET_DECODE; adjustNegate <= '0'; when x"28" => opcode <= OP_MOVMEM; aluop <= ALU_OP_SUB; useAluResult <= '1'; opsize <= 1; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"29" => opcode <= OP_MOVMEM; aluop <= ALU_OP_SUB; useAluResult <= '1'; opsize <= 2; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"2A" => opcode <= OP_MOVREG; aluop <= ALU_OP_SUB; useAluResult <= '1'; opsize <= 1; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"2B" => opcode <= OP_MOVREG; aluop <= ALU_OP_SUB; useAluResult <= '1'; opsize <= 2; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"2C" => opcode <= OP_MOVREG; aluop <= ALU_OP_SUB; useAluResult <= '1'; opsize <= 1; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; when x"2D" => opcode <= OP_MOVREG; aluop <= ALU_OP_SUB; useAluResult <= '1'; opsize <= 2; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; when x"2E" => prefixSegmentCS <= '1'; isPrefix := '1'; irqBlocked <= '1'; usePrefix := '1'; cpu_done <= '1'; newBuf := dbuf + 1; cpustage <= CPUSTAGE_IDLE; when x"2F" => opcode <= OP_MOVREG; aluop <= ALU_OP_DECADJUST; useAluResult <= '1'; newDelay := 10; opsize <= 1; cpustage <= CPUSTAGE_EXECUTE; target_decode <= CPU_REG_al; optarget <= OPTARGET_DECODE; adjustNegate <= '1'; when x"30" => opcode <= OP_MOVMEM; aluop <= ALU_OP_XOR; useAluResult <= '1'; opsize <= 1; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"31" => opcode <= OP_MOVMEM; aluop <= ALU_OP_XOR; useAluResult <= '1'; opsize <= 2; newDelay := 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MEM; when x"32" => opcode <= OP_MOVREG; aluop <= ALU_OP_XOR; useAluResult <= '1'; opsize <= 1; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"33" => opcode <= OP_MOVREG; aluop <= ALU_OP_XOR; useAluResult <= '1'; opsize <= 2; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"34" => opcode <= OP_MOVREG; aluop <= ALU_OP_XOR; useAluResult <= '1'; opsize <= 1; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; when x"35" => opcode <= OP_MOVREG; aluop <= ALU_OP_XOR; useAluResult <= '1'; opsize <= 2; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; when x"36" => prefixSegmentSS <= '1'; isPrefix := '1'; irqBlocked <= '1'; usePrefix := '1'; cpu_done <= '1'; newBuf := dbuf + 1; cpustage <= CPUSTAGE_IDLE; when x"37" => opcode <= OP_MOVREG; aluop <= ALU_OP_ASCIIADJUST; useAluResult <= '1'; newDelay := 8; opsize <= 2; cpustage <= CPUSTAGE_EXECUTE; target_decode <= CPU_REG_ax; optarget <= OPTARGET_DECODE; adjustNegate <= '0'; when x"38" => opcode <= OP_NOP; aluop <= ALU_OP_CMP; opsize <= 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; when x"39" => opcode <= OP_NOP; aluop <= ALU_OP_CMP; opsize <= 2; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; cpustage <= CPUSTAGE_MODRM; when x"3A" => opcode <= OP_NOP; aluop <= ALU_OP_CMP; opsize <= 1; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; when x"3B" => opcode <= OP_NOP; aluop <= ALU_OP_CMP; opsize <= 2; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; when x"3C" => opcode <= OP_NOP; aluop <= ALU_OP_CMP; opsize <= 1; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA2_8 ; when x"3D" => opcode <= OP_NOP; aluop <= ALU_OP_CMP; opsize <= 2; instantFetch <= '1'; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA2_16; when x"3E" => prefixSegmentDS <= '1'; isPrefix := '1'; irqBlocked <= '1'; usePrefix := '1'; cpu_done <= '1'; newBuf := dbuf + 1; cpustage <= CPUSTAGE_IDLE; when x"3F" => opcode <= OP_MOVREG; aluop <= ALU_OP_ASCIIADJUST; useAluResult <= '1'; newDelay := 8; opsize <= 2; cpustage <= CPUSTAGE_EXECUTE; target_decode <= CPU_REG_ax; optarget <= OPTARGET_DECODE; adjustNegate <= '1'; when x"40" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_ax; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_ax; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"41" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_cx; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_cx; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"42" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_dx; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_dx; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"43" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_bx; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_bx; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"44" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_sp; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_sp; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"45" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_bp; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_bp; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"46" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_si; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_si; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"47" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_INC; source1 <= OPSOURCE_REG_di; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_di; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"48" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_ax; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_ax; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"49" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_cx; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_cx; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"4A" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_dx; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_dx; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"4B" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_bx; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_bx; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"4C" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_sp; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_sp; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"4D" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_bp; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_bp; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"4E" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_si; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_si; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"4F" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_DEC; source1 <= OPSOURCE_REG_di; source2 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; target_decode <= CPU_REG_di; optarget <= OPTARGET_DECODE; opsize <= 2; useAluResult <= '1'; when x"50" => pushlist <= REGPOS_ax; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"51" => pushlist <= REGPOS_cx; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"52" => pushlist <= REGPOS_dx; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"53" => pushlist <= REGPOS_bx; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"54" => pushlist <= REGPOS_sp; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"55" => pushlist <= REGPOS_bp; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"56" => pushlist <= REGPOS_si; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"57" => pushlist <= REGPOS_di; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"58" => poplist <= REGPOS_ax; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"59" => poplist <= REGPOS_cx; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"5A" => poplist <= REGPOS_dx; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"5B" => poplist <= REGPOS_bx; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"5C" => poplist <= REGPOS_sp; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"5D" => poplist <= REGPOS_bp; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"5E" => poplist <= REGPOS_si; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"5F" => poplist <= REGPOS_di; cpustage <= CPUSTAGE_CHECKDATAREADY; newBuf := dbuf + 1; when x"60" => pushlist <= REGPOS_ax or REGPOS_cx or REGPOS_dx or REGPOS_bx or REGPOS_sp or REGPOS_bp or REGPOS_si or REGPOS_di; cpustage <= CPUSTAGE_CHECKDATAREADY; when x"61" => poplist <= REGPOS_ax or REGPOS_cx or REGPOS_dx or REGPOS_bx or REGPOS_bp or REGPOS_si or REGPOS_di; cpustage <= CPUSTAGE_CHECKDATAREADY; newDelay := 1; when x"62" => opcode <= OP_BOUND; newDelay := 4; opsize <= 2; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MEM; -- when x"63" => ? -- when x"64" => repnc -- when x"65" => repc -- when x"66" => fpo2 -- when x"67" => fpo2 when x"68" => pushlist <= REGPOS_imm; cpustage <= CPUSTAGE_PUSH; opsize <= 2; newBuf := dbuf + 1; fetch1Val <= unsigned(prefetchBuffer(23 downto 8)); regs.reg_ip <= regs.reg_ip + 2; consumePrefetch <= 2; when x"69" => opcode <= OP_MOVREG; aluop <= ALU_OP_MULI; newDelay := 3; useAluResult <= '1'; opsize <= 2; source1 <= OPSOURCE_FETCHVALUE16; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"6A" => pushlist <= REGPOS_imm; cpustage <= CPUSTAGE_PUSH; opsize <= 1; newBuf := dbuf + 1; fetch1Val <= x"00" & unsigned(prefetchBuffer(15 downto 8)); regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; when x"6B" => opcode <= OP_MOVREG; aluop <= ALU_OP_MULI; newDelay := 3; useAluResult <= '1'; opsize <= 2; source1 <= OPSOURCE_FETCHVALUE8; source2 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; optarget <= OPTARGET_MODRM_REG; when x"6C" => opcode <= OP_OPIN; newDelay := 5; opcodeNext <= OP_STRINGSTORE; opsize <= 1; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; source2 <= OPSOURCE_MEM; when x"6D" => opcode <= OP_OPIN; newDelay := 4; opcodeNext <= OP_STRINGSTORE; opsize <= 2; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; source2 <= OPSOURCE_MEM; when x"6E" => opcode <= OP_STRINGLOAD; newDelay := 5; opcodeNext <= OP_OPOUT; opsize <= 1; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_REG_dx; source2 <= OPSOURCE_STRINGLOAD1; when x"6F" => opcode <= OP_STRINGLOAD; newDelay := 1; opcodeNext <= OP_OPOUT; opsize <= 2; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_REG_dx; source2 <= OPSOURCE_STRINGLOAD1; when x"70" | x"71" | x"72" | x"73" | x"74" | x"75" | x"76" | x"77" | x"78" | x"79" | x"7a" | x"7b" | x"7c" | x"7d" | x"7e" | x"7f" => opcode <= OP_JUMPIF; source1 <= OPSOURCE_FETCHVALUE8; cpustage <= CPUSTAGE_FETCHDATA1_8; when x"80" => opcode <= OP_MEMIMM1; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_FETCHVALUE8; optarget <= OPTARGET_MEM; useAluResult <= '1'; opsize <= 1; opsign <= '0'; when x"81" => opcode <= OP_MEMIMM1; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_FETCHVALUE16; optarget <= OPTARGET_MEM; useAluResult <= '1'; opsize <= 2; opsign <= '0'; when x"82" => opcode <= OP_MEMIMM1; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_FETCHVALUE8; optarget <= OPTARGET_MEM; useAluResult <= '1'; opsize <= 1; opsign <= '1'; when x"83" => opcode <= OP_MEMIMM1; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_FETCHVALUE8; optarget <= OPTARGET_MEM; useAluResult <= '1'; opsize <= 2; opsign <= '1'; when x"84" => opcode <= OP_NOP; cpustage <= CPUSTAGE_MODRM; opsize <= 1; aluop <= ALU_OP_TST; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; when x"85" => opcode <= OP_NOP; cpustage <= CPUSTAGE_MODRM; opsize <= 2; aluop <= ALU_OP_TST; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MODRM_REG; when x"86" => opcode <= OP_MOVMEM; newDelay := 2; opcodeNext <= OP_MOVREG; opsize <= 1; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; optarget2 <= OPTARGET_MODRM_REG; when x"87" => opcode <= OP_MOVMEM; newDelay := 2; opcodeNext <= OP_MOVREG; opsize <= 2; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_MODRM_REG; source2 <= OPSOURCE_MEM; optarget <= OPTARGET_MEM; optarget2 <= OPTARGET_MODRM_REG; when x"88" => opcode <= OP_MOVMEM; cpustage <= CPUSTAGE_MODRM; opsize <= 1; source1 <= OPSOURCE_MODRM_REG; optarget <= OPTARGET_MEM; when x"89" => opcode <= OP_MOVMEM; cpustage <= CPUSTAGE_MODRM; opsize <= 2; source1 <= OPSOURCE_MODRM_REG; optarget <= OPTARGET_MEM; when x"8A" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_MODRM; opsize <= 1; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MODRM_REG; newBuf := dbuf + 1; when x"8B" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_MODRM; opsize <= 2; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MODRM_REG; newBuf := dbuf + 1; when x"8C" => opcode <= OP_MOVMEM; cpustage <= CPUSTAGE_MODRM; opsize <= 2; source1 <= OPSOURCE_MODRM_REG; segmentaccess <= '1'; optarget <= OPTARGET_MEM; irqBlocked <= '1'; when x"8D" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_MODRM; opsize <= 2; source1 <= OPSOURCE_MODRM_ADDR; optarget <= OPTARGET_MODRM_REG; when x"8E" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_MODRM; opsize <= 2; source1 <= OPSOURCE_MEM; optarget <= OPTARGET_MODRM_REG; segmentaccess <= '1'; newDelay := 1; when x"8F" => opcode <= OP_MOVMEM; poplist <= REGPOS_mem; cpustage <= CPUSTAGE_MODRM; source1 <= OPSOURCE_POPVALUE; optarget <= OPTARGET_MEM; opsize <= 2; newDelay := 1; -- when x"90" => NOP when x"91" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; when x"92" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; when x"93" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; when x"94" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; when x"95" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; when x"96" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; when x"97" => opcode <= OP_EXCHANGE; cpustage <= CPUSTAGE_EXECUTE; newDelay := 2; when x"98" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_SXT; source1 <= OPSOURCE_ACC; opsize <= 2; useAluResult <= '1'; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_ax; when x"99" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_EXECUTE; aluop <= ALU_OP_SXT; source1 <= OPSOURCE_ACC; opsize <= 2; useAluResult <= '1'; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_dx; when x"9A" => opcode <= OP_JUMPFAR; newDelay := 4; cpustage <= CPUSTAGE_FETCHDATA1_16; pushlist <= REGPOS_cs or REGPOS_ip; source1 <= OPSOURCE_FETCHVALUE16; source2 <= OPSOURCE_FETCHVALUE16; -- when x"9B" => wait when x"9C" => pushlist <= REGPOS_f; cpustage <= CPUSTAGE_CHECKDATAREADY; when x"9D" => poplist <= REGPOS_f; cpustage <= CPUSTAGE_CHECKDATAREADY; irqBlocked <= '1'; newDelay := 1; when x"9E" => opcode <= OP_FLAGSFROMACC; newDelay := 3; cpustage <= CPUSTAGE_EXECUTE; when x"9F" => opcode <= OP_FLAGSTOACC; newDelay := 1; cpustage <= CPUSTAGE_EXECUTE; when x"A0" => opcode <= OP_MOVREG; newBuf := dbuf + 1; memAddr <= unsigned(prefetchBuffer(23 downto 8)); regs.reg_ip <= regs.reg_ip + 2; consumePrefetch <= 2; cpustage <= CPUSTAGE_CHECKDATAREADY; opsize <= 1; source1 <= OPSOURCE_MEM; target_decode <= CPU_REG_al; optarget <= OPTARGET_DECODE; when x"A1" => opcode <= OP_MOVREG; newBuf := dbuf + 1; memAddr <= unsigned(prefetchBuffer(23 downto 8)); regs.reg_ip <= regs.reg_ip + 2; consumePrefetch <= 2; cpustage <= CPUSTAGE_CHECKDATAREADY; opsize <= 2; source1 <= OPSOURCE_MEM; target_decode <= CPU_REG_ax; optarget <= OPTARGET_DECODE; when x"A2" => opcode <= OP_MOVMEM; memAddr <= unsigned(prefetchBuffer(23 downto 8)); regs.reg_ip <= regs.reg_ip + 2; consumePrefetch <= 2; cpustage <= CPUSTAGE_CHECKDATAREADY; opsize <= 1; source1 <= OPSOURCE_ACC; optarget <= OPTARGET_MEM; when x"A3" => opcode <= OP_MOVMEM; memAddr <= unsigned(prefetchBuffer(23 downto 8)); regs.reg_ip <= regs.reg_ip + 2; consumePrefetch <= 2; cpustage <= CPUSTAGE_CHECKDATAREADY; opsize <= 2; source1 <= OPSOURCE_ACC; optarget <= OPTARGET_MEM; when x"A4" => opcode <= OP_STRINGLOAD; newDelay := 3; opcodeNext <= OP_STRINGSTORE; opsize <= 1; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_STRINGLOAD1; usePrefix := '1'; when x"A5" => opcode <= OP_STRINGLOAD; newDelay := 1; opcodeNext <= OP_STRINGSTORE; opsize <= 2; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_STRINGLOAD1; usePrefix := '1'; when x"A6" => opcode <= OP_STRINGLOAD; newDelay := 2; opcodeNext <= OP_STRINGCOMPARE; opsize <= 1; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_STRINGLOAD1; source2 <= OPSOURCE_STRINGLOAD2; usePrefix := '1'; when x"A7" => opcode <= OP_STRINGLOAD; opcodeNext <= OP_STRINGCOMPARE; opsize <= 2; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_STRINGLOAD1; source2 <= OPSOURCE_STRINGLOAD2; usePrefix := '1'; when x"A8" => opcode <= OP_NOP; opsize <= 1; cpustage <= CPUSTAGE_FETCHDATA1_8 ; aluop <= ALU_OP_TST; source1 <= OPSOURCE_FETCHVALUE8; source2 <= OPSOURCE_ACC; instantFetch <= '1'; when x"A9" => opcode <= OP_NOP; opsize <= 2; cpustage <= CPUSTAGE_FETCHDATA1_16; aluop <= ALU_OP_TST; source1 <= OPSOURCE_FETCHVALUE16; source2 <= OPSOURCE_ACC; instantFetch <= '1'; when x"AA" => opcode <= OP_STRINGSTORE; newDelay := 2; opsize <= 1; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_ACC; usePrefix := '1'; when x"AB" => opcode <= OP_STRINGSTORE; newDelay := 1; opsize <= 2; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_ACC; usePrefix := '1'; when x"AC" => opcode <= OP_STRINGLOAD; newDelay := 1; opcodeNext <= OP_MOVREG; opsize <= 1; source1 <= OPSOURCE_STRINGLOAD1; cpustage <= CPUSTAGE_EXECUTE; usePrefix := '1'; target_decode <= CPU_REG_al; optarget <= OPTARGET_DECODE; when x"AD" => opcode <= OP_STRINGLOAD; opcodeNext <= OP_MOVREG; opsize <= 2; source1 <= OPSOURCE_STRINGLOAD1; cpustage <= CPUSTAGE_EXECUTE; usePrefix := '1'; target_decode <= CPU_REG_ax; optarget <= OPTARGET_DECODE; when x"AE" => opcode <= OP_STRINGCOMPARE; newDelay := 1; opsize <= 1; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_STRINGLOAD2; usePrefix := '1'; when x"AF" => opcode <= OP_STRINGCOMPARE; opsize <= 2; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_ACC; source2 <= OPSOURCE_STRINGLOAD2; usePrefix := '1'; when x"B0" => opcode <= OP_MOVREG; target_decode <= CPU_REG_al; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= 1; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"B1" => opcode <= OP_MOVREG; target_decode <= CPU_REG_cl; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= 1; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"B2" => opcode <= OP_MOVREG; target_decode <= CPU_REG_dl; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= 1; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"B3" => opcode <= OP_MOVREG; target_decode <= CPU_REG_bl; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= 1; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"B4" => opcode <= OP_MOVREG; target_decode <= CPU_REG_ah; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= 1; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"B5" => opcode <= OP_MOVREG; target_decode <= CPU_REG_ch; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= 1; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"B6" => opcode <= OP_MOVREG; target_decode <= CPU_REG_dh; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= 1; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"B7" => opcode <= OP_MOVREG; target_decode <= CPU_REG_bh; cpustage <= CPUSTAGE_FETCHDATA1_8 ; source1 <= OPSOURCE_FETCHVALUE8; opsize <= 1; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"B8" => opcode <= OP_MOVREG; target_decode <= CPU_REG_ax; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= 2; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"B9" => opcode <= OP_MOVREG; target_decode <= CPU_REG_cx; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= 2; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"BA" => opcode <= OP_MOVREG; target_decode <= CPU_REG_dx; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= 2; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"BB" => opcode <= OP_MOVREG; target_decode <= CPU_REG_bx; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= 2; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"BC" => opcode <= OP_MOVREG; target_decode <= CPU_REG_sp; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= 2; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"BD" => opcode <= OP_MOVREG; target_decode <= CPU_REG_bp; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= 2; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"BE" => opcode <= OP_MOVREG; target_decode <= CPU_REG_si; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= 2; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"BF" => opcode <= OP_MOVREG; target_decode <= CPU_REG_di; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; opsize <= 2; optarget <= OPTARGET_DECODE; instantFetch <= '1'; when x"C0" => opcode <= OP_MEMIMM2; newDelay := 2; cpustage <= CPUSTAGE_MODRM; opsize <= 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_FETCHVALUE8; useAluResult <= '1'; optarget <= OPTARGET_MEM; when x"C1" => opcode <= OP_MEMIMM2; newDelay := 2; cpustage <= CPUSTAGE_MODRM; opsize <= 2; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_FETCHVALUE8; useAluResult <= '1'; optarget <= OPTARGET_MEM; when x"C2" => opcode <= OP_RETURNFAR; opsize <= 2; source1 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA1_16; newDelay := 1; poplist <= REGPOS_ip; when x"C3" => newDelay := 1; poplist <= REGPOS_ip; cpustage <= CPUSTAGE_CHECKDATAREADY; when x"C4" => opcode <= OP_MOVREG; newDelay := 3; cpustage <= CPUSTAGE_MODRM; opsize <= 2; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MEM; optarget <= OPTARGET_MODRM_REG; when x"C5" => opcode <= OP_MOVREG; newDelay := 3; cpustage <= CPUSTAGE_MODRM; opsize <= 2; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_MEM; optarget <= OPTARGET_MODRM_REG; when x"C6" => opcode <= OP_MOVMEM; cpustage <= CPUSTAGE_MODRM; opsize <= 1; source1 <= OPSOURCE_FETCHVALUE8; optarget <= OPTARGET_MEM; newBuf := dbuf + 1; when x"C7" => opcode <= OP_MOVMEM; cpustage <= CPUSTAGE_MODRM; opsize <= 2; source1 <= OPSOURCE_FETCHVALUE16; optarget <= OPTARGET_MEM; newBuf := dbuf + 1; when x"C8" => opcode <= OP_ENTER; cpustage <= CPUSTAGE_FETCHDATA1_16; newDelay := 6; pushlist <= REGPOS_bp; opsize <= 1; source1 <= OPSOURCE_FETCHVALUE16; source2 <= OPSOURCE_FETCHVALUE8; when x"C9" => opcode <= OP_MOVREG; regs.reg_sp <= regs.reg_bp; poplist <= REGPOS_MEM; cpustage <= CPUSTAGE_POP_REQ; source1 <= OPSOURCE_POPVALUE; target_decode <= CPU_REG_bp; optarget <= OPTARGET_DECODE; when x"CA" => opcode <= OP_RETURNFAR; opsize <= 2; source1 <= OPSOURCE_FETCHVALUE16; cpustage <= CPUSTAGE_FETCHDATA1_16; poplist <= REGPOS_cs or REGPOS_ip; when x"CB" => newDelay := 2; poplist <= REGPOS_cs or REGPOS_ip; cpustage <= CPUSTAGE_CHECKDATAREADY; when x"CC" => opcode <= OP_IRQREQUEST; newDelay := 9; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"03"; when x"CD" => opcode <= OP_IRQREQUEST; newDelay := 10; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; when x"CE" => opcode <= OP_IRQREQUEST; newDelay := 6; cpustage <= CPUSTAGE_EXECUTE; source1 <= OPSOURCE_IMMIDIATE; immidiate8 <= x"04"; when x"CF" => newDelay := 3; poplist <= REGPOS_cs or REGPOS_ip or REGPOS_f; cpustage <= CPUSTAGE_CHECKDATAREADY; irqBlocked <= '1'; when x"D0" => opcode <= OP_MEMIMM2; cpustage <= CPUSTAGE_MODRM; opsize <= 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_IMMIDIATE; useAluResult <= '1'; optarget <= OPTARGET_MEM; newDelay := 1; immidiate8 <= x"01"; when x"D1" => opcode <= OP_MEMIMM2; cpustage <= CPUSTAGE_MODRM; opsize <= 2; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_IMMIDIATE; useAluResult <= '1'; optarget <= OPTARGET_MEM; newDelay := 1; immidiate8 <= x"01"; when x"D2" => opcode <= OP_MEMIMM2; cpustage <= CPUSTAGE_MODRM; opsize <= 1; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_IMMIDIATE; useAluResult <= '1'; optarget <= OPTARGET_MEM; newDelay := 3; immidiate8 <= regs.reg_cx(7 downto 0); when x"D3" => opcode <= OP_MEMIMM2; cpustage <= CPUSTAGE_MODRM; opsize <= 2; source1 <= OPSOURCE_MEM; source2 <= OPSOURCE_IMMIDIATE; useAluResult <= '1'; optarget <= OPTARGET_MEM; newDelay := 3; immidiate8 <= regs.reg_cx(7 downto 0); when x"D4" => opcode <= OP_MULADJUST; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; newDelay := 2; opsize <= 2; when x"D5" => opcode <= OP_DIVADJUST; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; newDelay := 4; opsize <= 2; when x"D6" | x"D7" => opcode <= OP_MOVREG; cpustage <= CPUSTAGE_CHECKDATAREADY; source1 <= OPSOURCE_MEM; opsize <= 1; optarget <= OPTARGET_DECODE; target_decode <= CPU_REG_al; newDelay := 3; memSegment <= regs.reg_ds; if (prefixSegmentES = '1') then memSegment <= regs.reg_es; end if; if (prefixSegmentCS = '1') then memSegment <= regs.reg_cs; end if; if (prefixSegmentSS = '1') then memSegment <= regs.reg_ss; end if; if (prefixSegmentDS = '1') then memSegment <= regs.reg_ds; end if; memAddr <= regs.reg_bx + regs.reg_ax(7 downto 0); if (opcodebyte = x"D6") then newDelay := 6; else newDelay := 3; end if; -- when x"D8" => fpo1 -- when x"D9" => fpo1 -- when x"DA" => fpo1 -- when x"DB" => fpo1 -- when x"DC" => fpo1 -- when x"DD" => fpo1 -- when x"DE" => fpo1 -- when x"DF" => fpo1 when x"E0" => opcode <= OP_JUMPIF; newDelay := 2; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; when x"E1" => opcode <= OP_JUMPIF; newDelay := 2; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; when x"E2" => opcode <= OP_JUMPIF; newDelay := 1; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; when x"E3" => opcode <= OP_JUMPIF; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; when x"E4" => opcode <= OP_OPIN; newDelay := 5; cpustage <= CPUSTAGE_FETCHDATA1_8; opsize <= 1; source1 <= OPSOURCE_FETCHVALUE8; when x"E5" => opcode <= OP_OPIN; newDelay := 4; cpustage <= CPUSTAGE_FETCHDATA1_8; opsize <= 2; source1 <= OPSOURCE_FETCHVALUE8; when x"E6" => opcode <= OP_OPOUT; newDelay := 4; cpustage <= CPUSTAGE_FETCHDATA1_8; opsize <= 1; source1 <= OPSOURCE_FETCHVALUE8; source2 <= OPSOURCE_ACC; when x"E7" => opcode <= OP_OPOUT; newDelay := 3; cpustage <= CPUSTAGE_FETCHDATA1_8; opsize <= 2; source1 <= OPSOURCE_FETCHVALUE8; source2 <= OPSOURCE_ACC; when x"E8" => opcode <= OP_JUMP; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; pushlist <= REGPOS_ip; when x"E9" => opcode <= OP_JUMP; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; when x"EA" => opcode <= OP_JUMPFAR; newDelay := 3; opsize <= 2; cpustage <= CPUSTAGE_FETCHDATA1_16; source1 <= OPSOURCE_FETCHVALUE16; source2 <= OPSOURCE_FETCHVALUE16; when x"EB" => opcode <= OP_JUMPIF; cpustage <= CPUSTAGE_FETCHDATA1_8; source1 <= OPSOURCE_FETCHVALUE8; when x"EC" => opcode <= OP_OPIN; newDelay := 4; cpustage <= CPUSTAGE_EXECUTE; opsize <= 1; source1 <= OPSOURCE_REG_dx; when x"ED" => opcode <= OP_OPIN; newDelay := 4; cpustage <= CPUSTAGE_EXECUTE; opsize <= 2; source1 <= OPSOURCE_REG_dx; when x"EE" => opcode <= OP_OPOUT; newDelay := 3; cpustage <= CPUSTAGE_EXECUTE; opsize <= 1; source1 <= OPSOURCE_REG_dx; source2 <= OPSOURCE_ACC; when x"EF" => opcode <= OP_OPOUT; newDelay := 2; cpustage <= CPUSTAGE_EXECUTE; opsize <= 2; source1 <= OPSOURCE_REG_dx; source2 <= OPSOURCE_ACC; when x"F0" => isPrefix := '1'; irqBlocked <= '1'; usePrefix := '1'; -- lock --when x"F1" => ? when x"F2" => newDelay := 4; RepeatNext <= '1'; isPrefix := '1'; repeatZero <= '0'; irqBlocked <= '1'; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; when x"F3" => newDelay := 4; RepeatNext <= '1'; isPrefix := '1'; repeatZero <= '1'; irqBlocked <= '1'; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; when x"F4" => newDelay := 8; halt <= '1'; cpustage <= CPUSTAGE_IDLE; when x"F5" => opcode <= OP_NOP; newDelay := 3; regs.FlagCar <= not regs.FlagCar; cpustage <= CPUSTAGE_EXECUTE; when x"F6" => opcode <= OP_MEMIMM3; source1 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; opsize <= 1; when x"F7" => opcode <= OP_MEMIMM3; source1 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; opsize <= 2; when x"F8" => newDelay := 3; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; regs.FlagCar <= '0'; when x"F9" => newDelay := 3; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; regs.FlagCar <= '1'; when x"FA" => newDelay := 3; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; regs.FlagIrq <= '0'; when x"FB" => newDelay := 3; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; regs.FlagIrq <= '1'; irqBlocked <= '1'; when x"FC" => newDelay := 3; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; regs.FlagDir <= '0'; when x"FD" => newDelay := 3; cpustage <= CPUSTAGE_IDLE; cpu_finished <= '1'; regs.FlagDir <= '1'; when x"FE" => opcode <= OP_MEMIMM4; source1 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; opsize <= 1; when x"FF" => opcode <= OP_MEMIMM4; source1 <= OPSOURCE_MEM; cpustage <= CPUSTAGE_MODRM; opsize <= 2; when others => cpustage <= CPUSTAGE_IDLE; cpu_done <= '1'; end case; if (turbo = '1') then delay <= 0; dbuf <= 0; elsif (newBuf = 0) then delay <= newDelay; dbuf <= 0; elsif (newBuf > newDelay) then delay <= 0; dbuf <= newBuf - newDelay; else delay <= newDelay - newBuf; dbuf <= 0; end if; if (isPrefix = '1') then PrefixIP <= PrefixIP + 1; end if; if ((repeat = '1' or newRepeat = '1') and usePrefix = '0') then regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; Repeat <= '0'; PrefixIP <= (others => '0'); end if; -- #################################################################################### -- ############################## MODRM ########################################## -- #################################################################################### when CPUSTAGE_MODRM => if (consumePrefetch = 0) then regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; MODRM_mem := unsigned(prefetchBuffer(2 downto 0)); MODRM_reg := unsigned(prefetchBuffer(5 downto 3)); MODRM_mod := unsigned(prefetchBuffer(7 downto 6)); if (opcodebyte = x"8E" and MODRM_reg = 3) then irqBlocked <= '1'; end if; newModDelay := delay; if (MODRM_mod = 0 and MODRM_mem = 6) then if (SLOWTIMING = '1') then newModDelay := newModDelay + 1; end if; consumePrefetch <= 3; regs.reg_ip <= regs.reg_ip + 3; memAddr <= unsigned(prefetchBuffer(23 downto 8)); else varmemaddr := x"0000"; case (to_integer(MODRM_mem)) is when 0 => memSegment <= regs.reg_ds; varmemaddr := regs.reg_bx + regs.reg_si; when 1 => memSegment <= regs.reg_ds; varmemaddr := regs.reg_bx + regs.reg_di; when 2 => memSegment <= regs.reg_ss; varmemaddr := regs.reg_bp + regs.reg_si; when 3 => memSegment <= regs.reg_ss; varmemaddr := regs.reg_bp + regs.reg_di; when 4 => memSegment <= regs.reg_ds; varmemaddr := regs.reg_si; when 5 => memSegment <= regs.reg_ds; varmemaddr := regs.reg_di; when 6 => memSegment <= regs.reg_ss; varmemaddr := regs.reg_bp; when 7 => memSegment <= regs.reg_ds; varmemaddr := regs.reg_bx; when others => null; end case; if (MODRM_mod = 1) then if (SLOWTIMING = '1') then newModDelay := newModDelay + 1; end if; consumePrefetch <= 2; regs.reg_ip <= regs.reg_ip + 2; varmemaddr := to_unsigned(to_integer(varmemaddr) + to_integer(signed(prefetchBuffer(15 downto 8))), 16); elsif (MODRM_mod = 2) then if (SLOWTIMING = '1') then newModDelay := newModDelay + 1; end if; consumePrefetch <= 3; regs.reg_ip <= regs.reg_ip + 3; varmemaddr := varmemaddr + unsigned(prefetchBuffer(23 downto 8)); end if; memaddr <= varmemaddr; end if; -- set target reg varoptarget := optarget; varsource1 := source1; varsource2 := source2; vartarget_reg := CPU_REG_NONE; varpushlist := pushlist; if (segmentaccess = '1') then case (to_integer(MODRM_reg(1 downto 0))) is when 0 => vartarget_reg := CPU_REG_es; when 1 => vartarget_reg := CPU_REG_cs; when 2 => vartarget_reg := CPU_REG_ss; when 3 => vartarget_reg := CPU_REG_ds; when others => null; end case; else if (opsize = 1) then case (to_integer(MODRM_reg)) is when 0 => vartarget_reg := CPU_REG_al; when 1 => vartarget_reg := CPU_REG_cl; when 2 => vartarget_reg := CPU_REG_dl; when 3 => vartarget_reg := CPU_REG_bl; when 4 => vartarget_reg := CPU_REG_ah; when 5 => vartarget_reg := CPU_REG_ch; when 6 => vartarget_reg := CPU_REG_dh; when 7 => vartarget_reg := CPU_REG_bh; when others => null; end case; elsif (opsize = 2) then case (to_integer(MODRM_reg)) is when 0 => vartarget_reg := CPU_REG_ax; when 1 => vartarget_reg := CPU_REG_cx; when 2 => vartarget_reg := CPU_REG_dx; when 3 => vartarget_reg := CPU_REG_bx; when 4 => vartarget_reg := CPU_REG_sp; when 5 => vartarget_reg := CPU_REG_bp; when 6 => vartarget_reg := CPU_REG_si; when 7 => vartarget_reg := CPU_REG_di; when others => null; end case; end if; end if; target_reg <= vartarget_reg; -- get reg if (segmentaccess = '1') then case (to_integer(MODRM_reg(1 downto 0))) is when 0 => MODRM_value_reg <= regs.reg_es; when 1 => MODRM_value_reg <= regs.reg_cs; when 2 => MODRM_value_reg <= regs.reg_ss; when 3 => MODRM_value_reg <= regs.reg_ds; when others => null; end case; else if (opsize = 1) then case (to_integer(MODRM_reg)) is when 0 => MODRM_value_reg <= x"00" & regs.reg_ax( 7 downto 0); when 1 => MODRM_value_reg <= x"00" & regs.reg_cx( 7 downto 0); when 2 => MODRM_value_reg <= x"00" & regs.reg_dx( 7 downto 0); when 3 => MODRM_value_reg <= x"00" & regs.reg_bx( 7 downto 0); when 4 => MODRM_value_reg <= x"00" & regs.reg_ax(15 downto 8); when 5 => MODRM_value_reg <= x"00" & regs.reg_cx(15 downto 8); when 6 => MODRM_value_reg <= x"00" & regs.reg_dx(15 downto 8); when 7 => MODRM_value_reg <= x"00" & regs.reg_bx(15 downto 8); when others => null; end case; elsif (opsize = 2) then case (to_integer(MODRM_reg)) is when 0 => MODRM_value_reg <= regs.reg_ax; when 1 => MODRM_value_reg <= regs.reg_cx; when 2 => MODRM_value_reg <= regs.reg_dx; when 3 => MODRM_value_reg <= regs.reg_bx; when 4 => MODRM_value_reg <= regs.reg_sp; when 5 => MODRM_value_reg <= regs.reg_bp; when 6 => MODRM_value_reg <= regs.reg_si; when 7 => MODRM_value_reg <= regs.reg_di; when others => null; end case; end if; end if; -- second decode case (opcode) is when OP_MEMIMM1 => opcode <= OP_MOVMEM; case (to_integer(MODRM_reg)) is when 0 => aluop <= ALU_OP_ADD; when 1 => aluop <= ALU_OP_OR; when 2 => aluop <= ALU_OP_ADC; when 3 => aluop <= ALU_OP_SBB; when 4 => aluop <= ALU_OP_AND; when 5 => aluop <= ALU_OP_SUB; when 6 => aluop <= ALU_OP_XOR; when 7 => aluop <= ALU_OP_CMP; opcode <= OP_NOP; when others => null; end case; when OP_MEMIMM2 => opcode <= OP_MOVMEM; case (to_integer(MODRM_reg)) is when 0 => aluop <= ALU_OP_ROL; when 1 => aluop <= ALU_OP_ROR; when 2 => aluop <= ALU_OP_RCL; when 3 => aluop <= ALU_OP_RCR; when 4 => aluop <= ALU_OP_SHL; when 5 => aluop <= ALU_OP_SHR; when 6 => aluop <= ALU_OP_SAL; when 7 => aluop <= ALU_OP_SAR; when others => null; end case; when OP_MEMIMM3 => case (to_integer(MODRM_reg)) is when 0 | 1 => opcode <= OP_NOP; aluop <= ALU_OP_TST; if (opsize = 2) then varsource2 := OPSOURCE_FETCHVALUE16; else varsource2 := OPSOURCE_FETCHVALUE8; end if; dbuf <= dbuf + 1; when 2 => opcode <= OP_MOVMEM; varoptarget := OPTARGET_MEM; aluop <= ALU_OP_NOT; useAluResult <= '1'; if (MODRM_mod /= 3) then newModDelay := newModDelay + 1; end if; when 3 => opcode <= OP_MOVMEM; varoptarget := OPTARGET_MEM; aluop <= ALU_OP_NEG; useAluResult <= '1'; if (MODRM_mod /= 3) then newModDelay := newModDelay + 1; end if; when 4 => opcode <= OP_NOP; varsource1 := OPSOURCE_ACC; varsource2 := OPSOURCE_MEM; aluop <= ALU_OP_MUL; useAluResult <= '1'; newModDelay := newModDelay + 2; when 5 => opcode <= OP_NOP; varsource1 := OPSOURCE_ACC; varsource2 := OPSOURCE_MEM; aluop <= ALU_OP_MULI; useAluResult <= '1'; newModDelay := newModDelay + 2; when 6 => opcode <= OP_DIV; varsource1 := OPSOURCE_ACC; varsource2 := OPSOURCE_MEM; if (opsize = 1) then newModDelay := newModDelay + 2; else newModDelay := newModDelay + 11; end if; when 7 => opcode <= OP_DIVI; varsource1 := OPSOURCE_ACC; varsource2 := OPSOURCE_MEM; if (opsize = 1) then newModDelay := newModDelay + 4; else newModDelay := newModDelay + 12; end if; when others => null; end case; when OP_MEMIMM4 => case (to_integer(MODRM_reg)) is when 0 => opcode <= OP_MOVMEM; varoptarget := OPTARGET_MEM; aluop <= ALU_OP_INC; varsource2 := OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; useAluResult <= '1'; if (MODRM_mod /= 3) then newModDelay := newModDelay + 1; end if; when 1 => opcode <= OP_MOVMEM; varoptarget := OPTARGET_MEM; aluop <= ALU_OP_DEC; varsource2 := OPSOURCE_IMMIDIATE; immidiate8 <= x"01"; useAluResult <= '1'; if (MODRM_mod /= 3) then newModDelay := newModDelay + 1; end if; when 2 => opcode <= OP_JUMPABS; newModDelay := newModDelay + 1; varpushlist := REGPOS_ip; when 3 => opcode <= OP_JUMPFAR; varsource2 := OPSOURCE_MEM; varpushlist := REGPOS_cs or REGPOS_ip; newModDelay := newModDelay + 6; when 4 => opcode <= OP_JUMPABS; newModDelay := newModDelay + 1; when 5 => opcode <= OP_JUMPFAR; varsource2 := OPSOURCE_MEM; newModDelay := newModDelay + 6; when 6 | 7 => opcode <= OP_NOP; varpushlist := REGPOS_mem; dbuf <= dbuf + 1; when others => null; end case; when others => null; end case; varfetchedSource1 := fetchedSource1; varfetchedSource2 := fetchedSource2; --set target mem if (varoptarget = OPTARGET_MEM and MODRM_mod = 3) then target_reg2 <= vartarget_reg; varoptarget := OPTARGET_MODRM_REG; opcode <= OP_MOVREG; if (opcodebyte = x"8F") then --special case: PopMem opcode <= OP_NOP; end if; if (opcode = OP_MEMIMM1 and to_integer(MODRM_reg) = 7) then -- special case: CMP opcode <= OP_NOP; end if; if (opsize = 1) then case (to_integer(MODRM_mem)) is when 0 => target_reg <= CPU_REG_al; when 1 => target_reg <= CPU_REG_cl; when 2 => target_reg <= CPU_REG_dl; when 3 => target_reg <= CPU_REG_bl; when 4 => target_reg <= CPU_REG_ah; when 5 => target_reg <= CPU_REG_ch; when 6 => target_reg <= CPU_REG_dh; when 7 => target_reg <= CPU_REG_bh; when others => null; end case; elsif (opsize = 2) then case (to_integer(MODRM_mem)) is when 0 => target_reg <= CPU_REG_ax; when 1 => target_reg <= CPU_REG_cx; when 2 => target_reg <= CPU_REG_dx; when 3 => target_reg <= CPU_REG_bx; when 4 => target_reg <= CPU_REG_sp; when 5 => target_reg <= CPU_REG_bp; when 6 => target_reg <= CPU_REG_si; when 7 => target_reg <= CPU_REG_di; when others => null; end case; end if; if (opcode = OP_MEMIMM1) then varfetchedSource2 := '1'; if (source2 = OPSOURCE_FETCHVALUE8) then if (opsign = '1') then fetch2Val <= unsigned(resize(signed(prefetchBuffer(15 downto 8)), 16)); else fetch2Val <= x"00" & unsigned(prefetchBuffer(15 downto 8)); end if; consumePrefetch <= 2; regs.reg_ip <= regs.reg_ip + 2; else fetch2Val <= unsigned(prefetchBuffer(23 downto 8)); consumePrefetch <= 3; regs.reg_ip <= regs.reg_ip + 3; end if; end if; end if; optarget <= varoptarget; -- instant fetching if memory access degrades to register access fetchedRMMODData := x"0000"; if (opsize = 1) then case (to_integer(MODRM_mem)) is when 0 => fetchedRMMODData := x"00" & regs.reg_ax( 7 downto 0); when 1 => fetchedRMMODData := x"00" & regs.reg_cx( 7 downto 0); when 2 => fetchedRMMODData := x"00" & regs.reg_dx( 7 downto 0); when 3 => fetchedRMMODData := x"00" & regs.reg_bx( 7 downto 0); when 4 => fetchedRMMODData := x"00" & regs.reg_ax(15 downto 8); when 5 => fetchedRMMODData := x"00" & regs.reg_cx(15 downto 8); when 6 => fetchedRMMODData := x"00" & regs.reg_dx(15 downto 8); when 7 => fetchedRMMODData := x"00" & regs.reg_bx(15 downto 8); when others => null; end case; elsif (opsize = 2) then case (to_integer(MODRM_mem)) is when 0 => fetchedRMMODData := regs.reg_ax; when 1 => fetchedRMMODData := regs.reg_cx; when 2 => fetchedRMMODData := regs.reg_dx; when 3 => fetchedRMMODData := regs.reg_bx; when 4 => fetchedRMMODData := regs.reg_sp; when 5 => fetchedRMMODData := regs.reg_bp; when 6 => fetchedRMMODData := regs.reg_si; when 7 => fetchedRMMODData := regs.reg_di; when others => null; end case; end if; if (varsource1 = OPSOURCE_MEM and MODRM_mod = 3) then varfetchedSource1 := '1'; memFetchValue1 <= fetchedRMMODData; end if; if (varsource2 = OPSOURCE_MEM and MODRM_mod = 3) then varfetchedSource2 := '1'; memFetchValue2 <= fetchedRMMODData; end if; source1 <= varsource1; source2 <= varsource2; fetchedSource1 <= varfetchedSource1; fetchedSource2 <= varfetchedSource2; pushlist <= varpushlist; delay <= newModDelay; if (turbo = '1') then delay <= 0; end if; cpustage <= CPUSTAGE_CHECKDATAREADY; end if; -- consumePrefetch = 0 -- #################################################################################### -- ############################## Source 1 + 2 ######################################## -- #################################################################################### when CPUSTAGE_CHECKDATAREADY => if (ce = '1' or delay = 0) then if (fetchedSource1 = '0' and source1 <= OPSOURCE_FETCHVALUE8 ) then cpustage <= CPUSTAGE_FETCHDATA1_8; elsif (fetchedSource1 = '0' and source1 <= OPSOURCE_FETCHVALUE16) then cpustage <= CPUSTAGE_FETCHDATA1_16; elsif (fetchedSource1 = '0' and source1 <= OPSOURCE_MEM ) then cpustage <= CPUSTAGE_FETCHMEM_REQ; elsif (fetchedSource2 = '0' and source2 <= OPSOURCE_FETCHVALUE8 ) then cpustage <= CPUSTAGE_FETCHDATA2_8; elsif (fetchedSource2 = '0' and source2 <= OPSOURCE_FETCHVALUE16) then cpustage <= CPUSTAGE_FETCHDATA2_16; elsif (fetchedSource2 = '0' and source2 <= OPSOURCE_MEM ) then cpustage <= CPUSTAGE_FETCHMEM_REQ; elsif (pushlist /= x"0000") then cpustage <= CPUSTAGE_PUSH; elsif (poplist /= x"0000") then cpustage <= CPUSTAGE_POP_REQ; else cpustage <= CPUSTAGE_EXECUTE; end if; end if; when CPUSTAGE_FETCHDATA1_8 => if ((ce = '1' or instantFetch = '1') and (prefetchCount - consumePrefetch) > 0) then fetchedSource1 <= '1'; if (instantFetch = '1') then cpustage <= CPUSTAGE_EXECUTE; else cpustage <= CPUSTAGE_CHECKDATAREADY; end if; if (consumePrefetch = 1) then if (opsign = '1') then fetch1Val <= unsigned(resize(signed(prefetchBuffer(15 downto 8)), 16)); else fetch1Val <= x"00" & unsigned(prefetchBuffer(15 downto 8)); end if; else if (opsign = '1') then fetch1Val <= unsigned(resize(signed(prefetchBuffer(7 downto 0)), 16)); else fetch1Val <= x"00" & unsigned(prefetchBuffer(7 downto 0)); end if; end if; regs.reg_ip <= Regs.reg_ip + 1; consumePrefetch <= 1; end if; when CPUSTAGE_FETCHDATA1_16 => if ((ce = '1' or instantFetch = '1') and (prefetchCount - consumePrefetch) > 1) then fetchedSource1 <= '1'; if (instantFetch = '1') then cpustage <= CPUSTAGE_EXECUTE; else cpustage <= CPUSTAGE_CHECKDATAREADY; end if; if (consumePrefetch = 1) then fetch1Val <= unsigned(prefetchBuffer(23 downto 8)); else fetch1Val <= unsigned(prefetchBuffer(15 downto 0)); end if; regs.reg_ip <= regs.reg_ip + 2; consumePrefetch <= 2; if (SLOWTIMING = '1') then delay <= 1; end if; end if; when CPUSTAGE_FETCHDATA2_8 => if ((ce = '1' or instantFetch = '1') and (prefetchCount - consumePrefetch) > 0) then fetchedSource2 <= '1'; if (instantFetch = '1') then cpustage <= CPUSTAGE_EXECUTE; else cpustage <= CPUSTAGE_CHECKDATAREADY; end if; if (consumePrefetch = 1) then if (opsign = '1') then fetch2Val <= unsigned(resize(signed(prefetchBuffer(15 downto 8)), 16)); else fetch2Val <= x"00" & unsigned(prefetchBuffer(15 downto 8)); end if; else if (opsign = '1') then fetch2Val <= unsigned(resize(signed(prefetchBuffer(7 downto 0)), 16)); else fetch2Val <= x"00" & unsigned(prefetchBuffer(7 downto 0)); end if; end if; regs.reg_ip <= Regs.reg_ip + 1; consumePrefetch <= 1; end if; when CPUSTAGE_FETCHDATA2_16 => if ((ce = '1' or instantFetch = '1') and (prefetchCount - consumePrefetch) > 1) then fetchedSource2 <= '1'; if (instantFetch = '1') then cpustage <= CPUSTAGE_EXECUTE; else cpustage <= CPUSTAGE_CHECKDATAREADY; end if; if (consumePrefetch = 1) then fetch2Val <= unsigned(prefetchBuffer(23 downto 8)); else fetch2Val <= unsigned(prefetchBuffer(15 downto 0)); end if; regs.reg_ip <= regs.reg_ip + 2; consumePrefetch <= 2; if (SLOWTIMING = '1') then delay <= 1; end if; end if; -- #################################################################################### -- ############################## FETCH Mem ########################################## -- #################################################################################### when CPUSTAGE_FETCHMEM_REQ => if (ce = '1') then cpustage <= CPUSTAGE_FETCHMEM_WAIT; varmemSegment := memSegment; if (prefixSegmentES = '1') then varmemSegment := regs.reg_es; end if; if (prefixSegmentCS = '1') then varmemSegment := regs.reg_cs; end if; if (prefixSegmentSS = '1') then varmemSegment := regs.reg_ss; end if; if (prefixSegmentDS = '1') then varmemSegment := regs.reg_ds; end if; if (source1 = OPSOURCE_MEM and fetchedSource1 = '0') then if (unaligned1 = '1') then bus_addr <= resize(varmemSegment * 16 + memAddr + 1, 20); else bus_addr <= resize(varmemSegment * 16 + memAddr, 20); end if; bus_read <= '1'; prefetchAllow <= '0'; elsif (source2 = OPSOURCE_MEM and fetchedSource2 = '0') then if (unaligned2 = '1') then bus_addr <= resize(varmemSegment * 16 + memAddr + 1, 20); else bus_addr <= resize(varmemSegment * 16 + memAddr, 20); end if; bus_read <= '1'; prefetchAllow <= '0'; end if; end if; when CPUSTAGE_FETCHMEM_WAIT => cpustage <= CPUSTAGE_FETCHMEM_REC; when CPUSTAGE_FETCHMEM_REC => if (source1 = OPSOURCE_MEM and fetchedSource1 = '0') then if (opsize = 1) then memFetchValue1 <= x"00" & unsigned(bus_dataread(7 downto 0)); if (source2 = OPSOURCE_MEM) then memAddr <= memAddr + 1; end if; fetchedSource1 <= '1'; cpustage <= CPUSTAGE_CHECKDATAREADY; if (pushlist /= x"0000" or (fetchedSource2 = '0' and (source2 <= OPSOURCE_FETCHVALUE8 or source2 <= OPSOURCE_FETCHVALUE16 or source2 <= OPSOURCE_MEM))) then cpustage <= CPUSTAGE_CHECKDATAREADY; else cpustage <= CPUSTAGE_EXECUTE; end if; else if (unaligned1 = '1') then if (source2 = OPSOURCE_MEM) then memAddr <= memAddr + 2; end if; fetchedSource1 <= '1'; memFetchValue1(15 downto 8) <= unsigned(bus_dataread(7 downto 0)); if (pushlist /= x"0000" or (fetchedSource2 = '0' and (source2 <= OPSOURCE_FETCHVALUE8 or source2 <= OPSOURCE_FETCHVALUE16 or source2 <= OPSOURCE_MEM))) then cpustage <= CPUSTAGE_CHECKDATAREADY; else cpustage <= CPUSTAGE_EXECUTE; end if; else memFetchValue1 <= unsigned(bus_dataread); if (memAddr(0) = '1') then unaligned1 <= '1'; cpustage <= CPUSTAGE_FETCHMEM_REQ; else if (source2 = OPSOURCE_MEM) then memAddr <= memAddr + 2; end if; if (SLOWTIMING = '1') then delay <= 1; end if; fetchedSource1 <= '1'; if (pushlist /= x"0000" or (fetchedSource2 = '0' and (source2 <= OPSOURCE_FETCHVALUE8 or source2 <= OPSOURCE_FETCHVALUE16 or source2 <= OPSOURCE_MEM))) then cpustage <= CPUSTAGE_CHECKDATAREADY; else cpustage <= CPUSTAGE_EXECUTE; end if; end if; end if; end if; elsif (source2 = OPSOURCE_MEM and fetchedSource2 = '0') then if (opsize = 1) then memFetchValue2 <= x"00" & unsigned(bus_dataread(7 downto 0)); fetchedSource2 <= '1'; if (pushlist /= x"0000") then cpustage <= CPUSTAGE_CHECKDATAREADY; else cpustage <= CPUSTAGE_EXECUTE; end if; else if (unaligned2 = '1') then fetchedSource2 <= '1'; memFetchValue2(15 downto 8) <= unsigned(bus_dataread(7 downto 0)); if (pushlist /= x"0000") then cpustage <= CPUSTAGE_CHECKDATAREADY; else cpustage <= CPUSTAGE_EXECUTE; end if; else memFetchValue2 <= unsigned(bus_dataread); if (memAddr(0) = '1') then unaligned2 <= '1'; cpustage <= CPUSTAGE_FETCHMEM_REQ; else if (SLOWTIMING = '1') then delay <= 1; end if; fetchedSource2 <= '1'; if (pushlist /= x"0000") then cpustage <= CPUSTAGE_CHECKDATAREADY; else cpustage <= CPUSTAGE_EXECUTE; end if; end if; end if; end if; end if; -- #################################################################################### -- ############################## FETCH IRQ Vector #################################### -- #################################################################################### when CPUSTAGE_IRQVECTOR_REQ => if (ce = '1') then bus_addr <= resize(irqvector, 20); bus_read <= '1'; prefetchAllow <= '0'; irqvector <= irqvector + 2; cpustage <= CPUSTAGE_IRQVECTOR_WAIT; end if; when CPUSTAGE_IRQVECTOR_WAIT => cpustage <= CPUSTAGE_IRQVECTOR_REC; when CPUSTAGE_IRQVECTOR_REC => memFirst <= '0'; if (memFirst = '1') then irqIP <= unsigned(bus_dataread); cpustage <= CPUSTAGE_IRQVECTOR_REQ; else irqCS <= unsigned(bus_dataread); cpustage <= CPUSTAGE_CHECKDATAREADY; end if; -- #################################################################################### -- ############################## Push ########################################## -- #################################################################################### when CPUSTAGE_PUSH => if (ce = '1') then pushindex := 0; for i in 15 downto 0 loop if (pushlist(i) = '1') then pushindex := i; end if; end loop; pushValue := x"0000"; case (pushindex) is when 0 => pushValue := std_logic_vector(regs.reg_ax); when 1 => pushValue := std_logic_vector(regs.reg_cx); when 2 => pushValue := std_logic_vector(regs.reg_dx); when 3 => pushValue := std_logic_vector(regs.reg_bx); when 4 => pushValue := std_logic_vector(reg_sp_push); when 5 => pushValue := std_logic_vector(regs.reg_bp); when 6 => pushValue := std_logic_vector(regs.reg_si); when 7 => pushValue := std_logic_vector(regs.reg_di); when 8 => pushValue := std_logic_vector(regs.reg_es); when 9 => pushValue := std_logic_vector(reg_f); when 10 => pushValue := std_logic_vector(regs.reg_cs); when 11 => pushValue := std_logic_vector(regs.reg_ss); when 12 => pushValue := std_logic_vector(regs.reg_ds); when 13 => pushValue := std_logic_vector(regs.reg_ip - prefixIP); when 14 => pushValue := std_logic_vector(memFetchValue1); when 15 => if (opsize = 1) then pushValue := std_logic_vector(resize(signed(fetch1Val(7 downto 0)), 16)); else pushValue := std_logic_vector(fetch1Val); end if; when others => null; end case; if (pushFirst = '1') then if (regs.reg_sp(0) = '0') then -- aligned regs.reg_sp <= regs.reg_sp - 2; bus_read <= '0'; bus_write <= '1'; bus_be <= "11"; bus_addr <= resize(regs.reg_ss * 16 + regs.reg_sp - 2, 20); bus_datawrite <= pushValue; prefetchAllow <= '0'; cpustage <= CPUSTAGE_CHECKDATAREADY; pushlist(pushindex) <= '0'; else bus_read <= '0'; bus_write <= '1'; bus_be <= "01"; bus_addr <= resize(regs.reg_ss * 16 + regs.reg_sp - 2, 20); bus_datawrite <= pushValue; prefetchAllow <= '0'; pushFirst <= '0'; end if; else regs.reg_sp <= regs.reg_sp - 2; bus_read <= '0'; bus_write <= '1'; bus_be <= "01"; bus_addr <= resize(regs.reg_ss * 16 + regs.reg_sp - 1, 20); bus_datawrite <= x"00" & pushValue(15 downto 8); prefetchAllow <= '0'; cpustage <= CPUSTAGE_CHECKDATAREADY; pushFirst <= '1'; pushlist(pushindex) <= '0'; end if; end if; -- #################################################################################### -- ############################## Pop ########################################## -- #################################################################################### when CPUSTAGE_POP_REQ => if (ce = '1') then cpustage <= CPUSTAGE_POP_WAIT; popindex := 0; for i in 0 to 15 loop if (poplist(i) = '1') then popindex := i; end if; end loop; poptarget <= popindex; bus_read <= '1'; bus_write <= '0'; if (popFirst = '1') then bus_addr <= resize(regs.reg_ss * 16 + regs.reg_sp, 20); else bus_addr <= resize(regs.reg_ss * 16 + regs.reg_sp + 1, 20); end if; prefetchAllow <= '0'; end if; when CPUSTAGE_POP_WAIT => cpustage <= CPUSTAGE_POP_REC; if (popFirst = '0' or regs.reg_sp(0) = '0') then poplist(poptarget) <= '0'; end if; when CPUSTAGE_POP_REC => cpustage <= CPUSTAGE_POP_REQ; popValue := bus_dataread; popDone := '0'; if (popFirst = '1') then if (regs.reg_sp(0) = '0') then -- aligned popDone := '1'; else popFirst <= '0'; popUnalnByte <= bus_dataread(7 downto 0); end if; else popDone := '1'; popValue := bus_dataread(7 downto 0) & popUnalnByte; end if; if (popDone = '1') then popFirst <= '1'; if (opcodebyte = x"61" and popindex = 5) then regs.reg_sp <= regs.reg_sp + 4; else regs.reg_sp <= regs.reg_sp + 2; end if; case (poptarget) is when 0 => regs.reg_ax <= unsigned(popValue); when 1 => regs.reg_cx <= unsigned(popValue); when 2 => regs.reg_dx <= unsigned(popValue); when 3 => regs.reg_bx <= unsigned(popValue); when 4 => regs.reg_sp <= unsigned(popValue); when 5 => regs.reg_bp <= unsigned(popValue); when 6 => regs.reg_si <= unsigned(popValue); when 7 => regs.reg_di <= unsigned(popValue); when 8 => regs.reg_es <= unsigned(popValue); when 9 => regs.FlagCar <= popValue(0); regs.FlagPar <= popValue(2); regs.FlagHaC <= popValue(4); regs.FlagZer <= popValue(6); regs.FlagSgn <= popValue(7); regs.FlagBrk <= popValue(8); regs.FlagIrq <= popValue(9); regs.FlagDir <= popValue(10); regs.FlagOvf <= popValue(11); regs.FlagMod <= popValue(15); when 10 => regs.reg_cs <= unsigned(popValue); when 11 => regs.reg_ss <= unsigned(popValue); when 12 => regs.reg_ds <= unsigned(popValue); when 13 => regs.reg_ip <= unsigned(popValue); when 14 => popVal <= unsigned(popValue); when others => null; end case; if (poplist = x"0000") then cpustage <= CPUSTAGE_EXECUTE; if (SLOWTIMING = '1') then delay <= 1; end if; if (opcodebyte = x"C2" or opcodebyte = x"C3" or opcodebyte = x"CA" or opcodebyte = x"CB" or opcodebyte = x"CF") then clearPrefetch <= '1'; delay <= 3; end if; end if; end if; -- #################################################################################### -- ############################## EXECUTE ########################################## -- #################################################################################### when CPUSTAGE_EXECUTE => source1Val := x"0000"; case (source1) is when OPSOURCE_FETCHVALUE8 => source1Val := fetch1Val; when OPSOURCE_FETCHVALUE16 => source1Val := fetch1Val; when OPSOURCE_IRQVECTOR => source1Val := fetch1Val; when OPSOURCE_MEM => source1Val := memFetchValue1; when OPSOURCE_MODRM_REG => source1Val := MODRM_value_reg; when OPSOURCE_MODRM_ADDR => source1Val := memAddr; when OPSOURCE_ACC => if (opsize = 1) then source1Val := x"00" & regs.reg_ax(7 downto 0); else source1Val := regs.reg_ax; end if; when OPSOURCE_STRINGLOAD1 => source1Val := stringLoad; when OPSOURCE_STRINGLOAD2 => source1Val := stringLoad2; when OPSOURCE_IMMIDIATE => source1Val := x"00" & immidiate8; when OPSOURCE_POPVALUE => source1Val := popVal; when OPSOURCE_REG_ax => source1Val := regs.reg_ax; when OPSOURCE_REG_cx => source1Val := regs.reg_cx; when OPSOURCE_REG_dx => source1Val := regs.reg_dx; when OPSOURCE_REG_bx => source1Val := regs.reg_bx; when OPSOURCE_REG_sp => source1Val := regs.reg_sp; when OPSOURCE_REG_bp => source1Val := regs.reg_bp; when OPSOURCE_REG_si => source1Val := regs.reg_si; when OPSOURCE_REG_di => source1Val := regs.reg_di; when others => null; end case; source2Val := x"0000"; case (source2) is when OPSOURCE_FETCHVALUE8 => source2Val := fetch2Val; when OPSOURCE_FETCHVALUE16 => source2Val := fetch2Val; when OPSOURCE_IRQVECTOR => source2Val := fetch2Val; when OPSOURCE_MEM => source2Val := memFetchValue2; when OPSOURCE_MODRM_REG => source2Val := MODRM_value_reg; when OPSOURCE_ACC => if (opsize = 1) then source2Val := x"00" & regs.reg_ax(7 downto 0); else source2Val := regs.reg_ax; end if; when OPSOURCE_STRINGLOAD1 => source2Val := stringLoad; when OPSOURCE_STRINGLOAD2 => source2Val := stringLoad2; when OPSOURCE_IMMIDIATE => source2Val := x"00" & immidiate8; when OPSOURCE_REG_cx => source2Val := regs.reg_cx; when others => null; end case; target := CPU_REG_ip; case (optarget) is when OPTARGET_DECODE => target := target_decode; --when OPTARGET_MEM => target := target_mem; when OPTARGET_MODRM_REG => target := target_reg; when others => null; end case; -- #################################################################################### -- ############################## CALC ########################################## -- #################################################################################### result := x"0000"; newZero := '0'; newParity := '0'; newSign := '0'; if (aluop /= ALU_OP_NOTHING) then case (aluop) is when ALU_OP_SET1 => if (opsize = 1) then op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(2 downto 0))); else op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(3 downto 0))); end if; result := source1Val or op2value; when ALU_OP_CLR1 => if (opsize = 1) then op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(2 downto 0))); else op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(3 downto 0))); end if; result := source1Val and (not op2value); when ALU_OP_TEST1 => if (opsize = 1) then op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(2 downto 0))); else op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(3 downto 0))); end if; result := source1Val and op2value; regs.FlagCar <= '0'; regs.FlagOvf <= '0'; regs.FlagHaC <= '0'; newZero := '1'; newParity := '1'; newSign := '1'; when ALU_OP_NOT1 => if (opsize = 1) then op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(2 downto 0))); else op2value := shift_left(to_unsigned(1, 16), to_integer(source2Val(3 downto 0))); end if; result := source1Val xor op2value; when ALU_OP_ROR4 => result := x"00" & regs.reg_ax(3 downto 0) & source1Val(7 downto 4); regs.reg_ax(7 downto 0) <= regs.reg_ax(7 downto 4) & source1Val(3 downto 0); when ALU_OP_ROL4 => result := x"00" & source1Val(3 downto 0) & regs.reg_ax(3 downto 0); regs.reg_ax(7 downto 0) <= regs.reg_ax(7 downto 4) & source1Val(7 downto 4); when ALU_OP_AND | ALU_OP_TST => result := source1Val and source2Val; regs.FlagCar <= '0'; regs.FlagOvf <= '0'; regs.FlagHaC <= '0'; newZero := '1'; newParity := '1'; newSign := '1'; when ALU_OP_OR => result := source1Val or source2Val; regs.FlagCar <= '0'; regs.FlagOvf <= '0'; regs.FlagHaC <= '0'; newZero := '1'; newParity := '1'; newSign := '1'; when ALU_OP_XOR => result := source1Val xor source2Val; regs.FlagCar <= '0'; regs.FlagOvf <= '0'; regs.FlagHaC <= '0'; newZero := '1'; newParity := '1'; newSign := '1'; when ALU_OP_NOT => result := not source1Val; when ALU_OP_NEG => result := 0 - source1Val; if (source1Val > 0) then regs.FlagCar <= '1'; else regs.FlagCar <= '0'; end if; if (source1Val(3 downto 0) > 0) then regs.FlagHaC <= '1'; else regs.FlagHaC <= '0'; end if; regs.FlagOvf <= '0'; if (opsize = 1 and source1Val(7 downto 0) = x"80") then regs.FlagOvf <= '1'; end if; if (opsize = 2 and source1Val = x"8000") then regs.FlagOvf <= '1'; end if; newZero := '1'; newParity := '1'; newSign := '1'; when ALU_OP_ADD | ALU_OP_INC | ALU_OP_ADC => op2value := source2Val; if (aluop = ALU_OP_ADC and flagCarry = '1') then op2value := op2value + 1; end if; newZero := '1'; newParity := '1'; newSign := '1'; result := source1Val + op2value; if (aluop /= ALU_OP_INC) then regs.FlagCar <= '0'; if (opsize = 1 and to_integer(source1Val) + to_integer(op2value) > 16#FF#) then regs.FlagCar <= '1'; end if; if (opsize = 2 and to_integer(source1Val) + to_integer(op2value) > 16#FFFF#) then regs.FlagCar <= '1'; end if; end if; if (to_integer(source1Val(3 downto 0)) + to_integer(op2value(3 downto 0)) >= 16) then regs.FlagHaC <= '1'; else regs.FlagHaC <= '0'; end if; if (opsize = 1) then regs.FlagOvf <= (source1Val(7) xor result(7)) and (op2value(7) xor result(7)); else regs.FlagOvf <= (source1Val(15) xor result(15)) and (op2value(15) xor result(15)); end if; when ALU_OP_SUB | ALU_OP_CMP | ALU_OP_DEC | ALU_OP_SBB => op2value := source2Val; if (aluop = ALU_OP_SBB and flagCarry = '1') then op2value := op2value + 1; end if; newZero := '1'; newParity := '1'; newSign := '1'; result := source1Val - op2value; if (aluop /= ALU_OP_DEC) then if (op2value > source1Val) then regs.FlagCar <= '1'; else regs.FlagCar <= '0'; end if; end if; if (op2value(3 downto 0) > source1Val(3 downto 0)) then regs.FlagHaC <= '1'; else regs.FlagHaC <= '0'; end if; if (opsize = 1) then regs.FlagOvf <= (source1Val(7) xor op2value(7)) and (source1Val(7) xor result(7)); else regs.FlagOvf <= (source1Val(15) xor op2value(15)) and (source1Val(15) xor result(15)); end if; when ALU_OP_ROL => result17 := resize(source1Val, 17) sll to_integer(source2Val(4 downto 0)); if (opsize = 1) then result(7 downto 0) := source1Val(7 downto 0) rol to_integer(source2Val(4 downto 0)); regs.FlagCar <= result17(8); regs.FlagOvf <= source1Val(7) xor result(7); else result17 := resize(source1Val, 17) sll to_integer(source2Val(4 downto 0)); result := resize(source1Val, 16) rol to_integer(source2Val(4 downto 0)); regs.FlagCar <= result17(16); regs.FlagOvf <= source1Val(15) xor result(15); end if; when ALU_OP_ROR => result17 := (source1Val & '0') srl to_integer(source2Val(4 downto 0)); result := result17(16 downto 1); regs.FlagCar <= result17(0); if (opsize = 1) then result(7 downto 0) := source1Val(7 downto 0) ror to_integer(source2Val(4 downto 0)); regs.FlagOvf <= source1Val(7) xor result(7); else result := resize(source1Val, 16) ror to_integer(source2Val(4 downto 0)); regs.FlagOvf <= source1Val(15) xor result(15); end if; when ALU_OP_RCL => carryWork1 := flagCarry; result := source1Val; for i in 0 to 31 loop if (i < source2Val(4 downto 0)) then if (opsize = 1) then carryWork2 := result(7); else carryWork2 := result(15); end if; result := result(14 downto 0) & carryWork1; carryWork1 := carryWork2; end if; end loop; regs.FlagCar <= carryWork1; if (opsize = 1) then regs.FlagOvf <= (source1Val(7) xor result(7)); else regs.FlagOvf <= (source1Val(15) xor result(15)); end if; when ALU_OP_RCR => carryWork1 := flagCarry; result := source1Val; for i in 0 to 31 loop if (i < source2Val(4 downto 0)) then carryWork2 := result(0); result := '0' & result(15 downto 1); if (opsize = 1) then result(7) := carryWork1; else result(15) := carryWork1; end if; carryWork1 := carryWork2; end if; end loop; regs.FlagCar <= carryWork1; if (opsize = 1) then regs.FlagOvf <= (source1Val(7) xor result(7)); else regs.FlagOvf <= (source1Val(15) xor result(15)); end if; when ALU_OP_SHL | ALU_OP_SAL => result17 := resize(source1Val, 17) sll to_integer(source2Val(4 downto 0)); if (opsize = 1) then regs.FlagCar <= result17(8); end if; if (opsize = 2) then regs.FlagCar <= result17(16); end if; if (aluop = ALU_OP_SAL) then regs.FlagOvf <= '0'; else if (opsize = 1) then regs.FlagOvf <= source1Val(7) xor result17(7); else regs.FlagOvf <= source1Val(15) xor result17(15); end if; end if; result := result17(15 downto 0); newZero := '1'; newParity := '1'; newSign := '1'; when ALU_OP_SHR => result17 := (source1Val & '0') srl to_integer(source2Val(4 downto 0)); result := result17(16 downto 1); regs.FlagCar <= result17(0); if (opsize = 1) then regs.FlagOvf <= source1Val(7) xor result(7); else regs.FlagOvf <= source1Val(15) xor result(15); end if; newZero := '1'; newParity := '1'; newSign := '1'; when ALU_OP_SAR => if (source2Val(4) = '1') then if ((opsize = 1 and source1Val(7) = '1') or (opsize = 2 and source1Val(15) = '1')) then result := x"FFFF"; regs.FlagCar <= '1'; else result := x"0000"; regs.FlagCar <= '0'; end if; else result17 := (source1Val & '0') srl to_integer(source2Val(4 downto 0)); regs.FlagCar <= result17(0); if (opsize = 1) then result := x"00" & unsigned(shift_right(signed(source1Val(7 downto 0)),to_integer(source2Val(4 downto 0)))); else result := unsigned(shift_right(signed(source1Val),to_integer(source2Val(4 downto 0)))); end if; regs.FlagOvf <= '0'; newZero := '1'; newParity := '1'; newSign := '1'; end if; when ALU_OP_MUL => regs.FlagCar <= '0'; regs.FlagOvf <= '0'; if (opsize = 1) then result32 := resize(source1Val(7 downto 0) * memFetchValue2, 32); regs.reg_ax <= result32(15 downto 0); if (result32(31 downto 8) /= x"000000") then regs.FlagCar <= '1'; regs.FlagOvf <= '1'; end if; else result32 := source1Val * memFetchValue2; regs.reg_ax <= result32(15 downto 0); regs.reg_dx <= result32(31 downto 16); if (result32(31 downto 16) /= x"0000") then regs.FlagCar <= '1'; regs.FlagOvf <= '1'; end if; end if; when ALU_OP_MULI => regs.FlagCar <= '0'; regs.FlagOvf <= '0'; if (opsize = 1) then result32 := unsigned(to_signed(to_integer(signed(source1Val(7 downto 0))) * to_integer(signed(memFetchValue2(7 downto 0))), 32)); if (opcode = OP_NOP) then regs.reg_ax <= result32(15 downto 0); end if; if (result32(31 downto 8) /= x"000000") then regs.FlagCar <= '1'; regs.FlagOvf <= '1'; end if; else if (source1 = OPSOURCE_FETCHVALUE8) then result32 := unsigned(to_signed(to_integer(signed(source1Val(7 downto 0))) * to_integer(signed(memFetchValue2)), 32)); else result32 := unsigned(to_signed(to_integer(signed(source1Val)) * to_integer(signed(memFetchValue2)), 32)); end if; if (opcode = OP_NOP) then regs.reg_ax <= result32(15 downto 0); regs.reg_dx <= result32(31 downto 16); end if; if (result32(31 downto 16) /= x"0000") then regs.FlagCar <= '1'; regs.FlagOvf <= '1'; end if; end if; result := result32(15 downto 0); when ALU_OP_DECADJUST => result8 := regs.reg_ax(7 downto 0); if (regs.FlagHaC = '1' or regs.reg_ax(3 downto 0) > x"9") then if (adjustNegate = '1') then result8 := result8 - 6; else result8 := result8 + 6; end if; regs.FlagHaC <= '1'; end if; if (regs.FlagCar = '1' or regs.reg_ax(7 downto 0) > x"99") then if (adjustNegate = '1') then result8 := result8 - 16#60#; else result8 := result8 + 16#60#; end if; regs.FlagCar <= '1'; end if; result := x"00" & result8; newZero := '1'; newParity := '1'; newSign := '1'; when ALU_OP_ASCIIADJUST => result8 := regs.reg_ax(7 downto 0); result8h := regs.reg_ax(15 downto 8); if (regs.FlagHaC = '1' or regs.reg_ax(3 downto 0) > x"9") then if (adjustNegate = '1') then result8 := result8 - 6; result8h := result8h - 1; else result8 := result8 + 6; result8h := result8h + 1; end if; regs.FlagHaC <= '1'; regs.FlagCar <= '1'; else regs.FlagHaC <= '0'; regs.FlagCar <= '0'; end if; result8(7 downto 4) := x"0"; result := result8h & result8; when ALU_OP_SXT => if (opcodebyte = x"98") then if (regs.reg_ax(7) = '1') then result := x"FF" & regs.reg_ax(7 downto 0); else result := x"00" & regs.reg_ax(7 downto 0); end if; else if (regs.reg_ax(15) = '1') then result := x"FFFF"; else result := x"0000"; end if; end if; when others => null; end case; end if; -- flags if (opsize = 1) then result(15 downto 8) := x"00"; end if; if (newZero = '1') then if (result = 0) then regs.FlagZer <= '1'; else regs.FlagZer <= '0'; end if; end if; if (newSign = '1') then if (opsize = 1) then regs.FlagSgn <= result(7); else regs.FlagSgn <= result(15); end if; end if; if (newParity = '1') then regs.FlagPar <= not(result(7) xor result(6) xor result(5) xor result(4) xor result(3) xor result(2) xor result(1) xor result(0)); end if; -- mux result if (useAluResult = '1') then resultval := result; else resultval := source1Val; end if; -- #################################################################################### -- ############################## OPCodes ########################################## -- #################################################################################### exeDone := '0'; newExeDelay := delay; endRepeat := '0'; jumpNow := '0'; jumpAddr := (others => '0'); case (opcode) is when OP_MOVMEM => if (optarget /= OPTARGET_NONE) then prefetchAllow <= '0'; if (bus_read = '0' and bus_write = '0' and (waitexe = '0' or ce = '1')) then memFirst <= '0'; waitexe <= '1'; varmemSegment := memSegment; if (prefixSegmentES = '1') then varmemSegment := regs.reg_es; end if; if (prefixSegmentCS = '1') then varmemSegment := regs.reg_cs; end if; if (prefixSegmentSS = '1') then varmemSegment := regs.reg_ss; end if; if (prefixSegmentDS = '1') then varmemSegment := regs.reg_ds; end if; bus_read <= '0'; bus_write <= '1'; if (memFirst = '0') then bus_addr <= resize(varmemSegment * 16 + memAddr + 1, 20); bus_datawrite <= x"00" & std_logic_vector(resultval(15 downto 8)); bus_be <= "01"; elsif (opsize = 2 and memAddr(0) = '0') then bus_addr <= resize(varmemSegment * 16 + memAddr, 20); bus_datawrite <= std_logic_vector(resultval); bus_be <= "11"; else bus_addr <= resize(varmemSegment * 16 + memAddr, 20); bus_datawrite <= std_logic_vector(resultval); bus_be <= "01"; end if; if (opsize = 1 or memFirst = '0' or memAddr(0) = '0') then if (SLOWTIMING = '1') then newExeDelay := newExeDelay + 1; end if; if (opcodeNext /= OP_INVALID) then if (target_reg2 /= CPU_REG_NONE) then target_reg <= target_reg2; end if; optarget <= optarget2; source1 <= source2; memFetchValue1 <= memFetchValue2; opcode <= opcodeNext; opcodeNext <= OP_INVALID; else exeDone := '1'; end if; end if; elsif (waitexe = '1' and ce = '1') then waitexe <= '0'; end if; else exeDone := '1'; end if; when OP_MOVREG => if (optarget /= OPTARGET_NONE) then case (target) is when CPU_REG_al => regs.reg_ax(7 downto 0) <= resultval(7 downto 0); when CPU_REG_ah => regs.reg_ax(15 downto 8) <= resultval(7 downto 0); when CPU_REG_ax => regs.reg_ax <= resultval; when CPU_REG_bl => regs.reg_bx(7 downto 0) <= resultval(7 downto 0); when CPU_REG_bh => regs.reg_bx(15 downto 8) <= resultval(7 downto 0); when CPU_REG_bx => regs.reg_bx <= resultval; when CPU_REG_cl => regs.reg_cx(7 downto 0) <= resultval(7 downto 0); when CPU_REG_ch => regs.reg_cx(15 downto 8) <= resultval(7 downto 0); when CPU_REG_cx => regs.reg_cx <= resultval; when CPU_REG_dl => regs.reg_dx(7 downto 0) <= resultval(7 downto 0); when CPU_REG_dh => regs.reg_dx(15 downto 8) <= resultval(7 downto 0); when CPU_REG_dx => regs.reg_dx <= resultval; when CPU_REG_sp => regs.reg_sp <= resultval; when CPU_REG_bp => regs.reg_bp <= resultval; when CPU_REG_si => regs.reg_si <= resultval; when CPU_REG_di => regs.reg_di <= resultval; when CPU_REG_es => regs.reg_es <= resultval; when CPU_REG_cs => regs.reg_cs <= resultval; when CPU_REG_ss => regs.reg_ss <= resultval; when CPU_REG_ds => regs.reg_ds <= resultval; when others => null; end case; end if; if (opcodebyte = x"C4") then regs.reg_es <= memFetchValue2; end if; if (opcodebyte = x"C5") then regs.reg_ds <= memFetchValue2; end if; if (opcodeNext /= OP_INVALID) then if (ce = '1') then if (target_reg2 /= CPU_REG_NONE) then target_reg <= target_reg2; end if; optarget <= optarget2; source1 <= source2; memFetchValue1 <= memFetchValue2; opcode <= opcodeNext; opcodeNext <= OP_INVALID; end if; else exeDone := '1'; end if; when OP_EXCHANGE => case (opcodebyte) is when x"91" => regs.reg_ax <= regs.reg_cx; regs.reg_cx <= regs.reg_ax; when x"92" => regs.reg_ax <= regs.reg_dx; regs.reg_dx <= regs.reg_ax; when x"93" => regs.reg_ax <= regs.reg_bx; regs.reg_bx <= regs.reg_ax; when x"94" => regs.reg_ax <= regs.reg_sp; regs.reg_sp <= regs.reg_ax; when x"95" => regs.reg_ax <= regs.reg_bp; regs.reg_bp <= regs.reg_ax; when x"96" => regs.reg_ax <= regs.reg_si; regs.reg_si <= regs.reg_ax; when x"97" => regs.reg_ax <= regs.reg_di; regs.reg_di <= regs.reg_ax; when others => null; end case; exeDone := '1'; when OP_BOUND => if (MODRM_value_reg < memFetchValue1 or MODRM_value_reg > memFetchValue2) then irqrequest <= '1'; irqvector <= to_unsigned(20, 10); --5 * 4; end if; exeDone := '1'; when OP_OPIN => case (opstep) is when 0 => RegBus_Adr <= std_logic_vector(source1Val(7 downto 0)); RegBus_rden <= '1'; opstep <= 1; when 1 => opstep <= 2; memFetchValue1(7 downto 0) <= unsigned(RegBus_Dout); if (opcodeNext = OP_INVALID) then regs.reg_ax(7 downto 0) <= unsigned(RegBus_Dout); end if; if (opsize = 1) then if (opcodeNext /= OP_INVALID) then if (ce = '1') then source1 <= source2; opcode <= opcodeNext; opcodeNext <= OP_INVALID; opstep <= 0; end if; else exeDone := '1'; end if; else RegBus_Adr <= std_logic_vector(source1Val(7 downto 0) + 1); RegBus_rden <= '1'; end if; when 2 => memFetchValue1(15 downto 8) <= unsigned(RegBus_Dout); if (opcodeNext = OP_INVALID) then regs.reg_ax(15 downto 8) <= unsigned(RegBus_Dout); end if; if (opcodeNext /= OP_INVALID) then if (ce = '1') then source1 <= source2; opcode <= opcodeNext; opcodeNext <= OP_INVALID; opstep <= 0; end if; else exeDone := '1'; end if; when others => null; end case; when OP_OPOUT => memFirst <= '0'; if (opsize = 1 or memFirst = '1') then RegBus_Din <= std_logic_vector(source2Val(7 downto 0)); RegBus_Adr <= std_logic_vector(source1Val(7 downto 0)); RegBus_wren <= '1'; elsif (ce = '1') then RegBus_Din <= std_logic_vector(source2Val(15 downto 8)); RegBus_Adr <= std_logic_vector(source1Val(7 downto 0) + 1); RegBus_wren <= '1'; end if; if (opsize = 1 or (memFirst = '0' and ce = '1')) then exeDone := '1'; newExeDelay := newExeDelay + 1; end if; when OP_BCDSTRING => if ((bcdOffset & "0") >= regs.reg_cx(7 downto 0)) then exeDone := '1'; else case (opstep) is when 0 => if (ce = '1') then opstep <= 1; varmemSegment := regs.reg_ds; if (prefixSegmentES = '1') then varmemSegment := regs.reg_es; end if; if (prefixSegmentCS = '1') then varmemSegment := regs.reg_cs; end if; if (prefixSegmentSS = '1') then varmemSegment := regs.reg_ss; end if; if (prefixSegmentDS = '1') then varmemSegment := regs.reg_ds; end if; bus_read <= '1'; bus_write <= '0'; bus_addr <= resize(varmemSegment * 16 + regs.reg_si + bcdOffset, 20); prefetchAllow <= '0'; end if; when 1 => opstep <= 2; -- wait when 2 => opstep <= 3; if (regs.FlagCar = '0') then fetch1Val(7 downto 0) <= unsigned(bus_dataread(7 downto 0)); else fetch1Val(7 downto 0) <= unsigned(bus_dataread(7 downto 0)) + 1; end if; regs.FlagCar <= '0'; when 3 => if (ce = '1') then bus_read <= '1'; bus_write <= '0'; bus_addr <= resize(regs.reg_es * 16 + regs.reg_di + bcdOffset, 20); prefetchAllow <= '0'; opstep <= 4; end if; when 4 => opstep <= 5; -- wait when 5 => opstep <= 6; if (bcdOp = BCD_OP_ADD) then bcdAcc <= unsigned(bus_dataread(7 downto 0)) + fetch1Val(7 downto 0); else bcdAcc <= unsigned(bus_dataread(7 downto 0)) - fetch1Val(7 downto 0); end if; when 6 => opstep <= 7; bcdResult := bcdAcc; if (bcdResult(3 downto 0) > x"9") then if (bcdOp = BCD_OP_ADD) then bcdResult := bcdResult + 6; else bcdResult := bcdResult - 6; end if; end if; if (bcdResult(7 downto 0) > x"99") then if (bcdOp = BCD_OP_ADD) then bcdResult := bcdResult + 16#60#; else bcdResult := bcdResult - 16#60#; end if; regs.FlagCar <= '1'; end if; bcdAcc <= bcdResult; when 7 => if (bcdOp = BCD_OP_CMP) then if (bcdAcc /= x"00") then regs.FlagZer <= '0'; end if; bcdOffset <= bcdOffset + 1; opstep <= 0; else prefetchAllow <= '0'; if (bus_read = '0' and bus_write = '0' and (waitexe = '0' or ce = '1')) then waitexe <= '1'; bus_read <= '0'; bus_write <= '1'; bus_be <= "01"; bus_datawrite <= x"00" & std_logic_vector(bcdAcc); bus_addr <= resize(regs.reg_es * 16 + regs.reg_di + bcdOffset, 20); if (bcdAcc /= x"00") then regs.FlagZer <= '0'; end if; bcdOffset <= bcdOffset + 1; opstep <= 0; elsif (waitexe = '1' and ce = '1') then waitexe <= '0'; end if; end if; end case; end if; when OP_STRINGLOAD => if (repeat = '1' and regs.reg_cx = 0) then repeat <= '0'; endRepeat := '1'; prefixIP <= (others => '0'); regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; newExeDelay := newExeDelay + 1; exeDone := '1'; if (opcodeNext /= OP_INVALID) then newExeDelay := newExeDelay + 1 + opsize; end if; else case (opstep) is when 0 => if (ce = '1') then opstep <= 1; varmemSegment := regs.reg_ds; if (prefixSegmentES = '1') then varmemSegment := regs.reg_es; end if; if (prefixSegmentCS = '1') then varmemSegment := regs.reg_cs; end if; if (prefixSegmentSS = '1') then varmemSegment := regs.reg_ss; end if; if (prefixSegmentDS = '1') then varmemSegment := regs.reg_ds; end if; bus_read <= '1'; bus_write <= '0'; if (memFirst = '0') then bus_addr <= resize(varmemSegment * 16 + regs.reg_si + 1, 20); else bus_addr <= resize(varmemSegment * 16 + regs.reg_si, 20); end if; prefetchAllow <= '0'; end if; when 1 => opstep <= 2; when 2 => opstep <= 0; memFirst <= '0'; if (opsize = 1 or memFirst = '1') then stringLoad(7 downto 0) <= unsigned(bus_dataread(7 downto 0)); if (opsize = 1) then stringLoad(15 downto 8) <= x"00"; end if; else stringLoad(15 downto 8) <= unsigned(bus_dataread(7 downto 0)); end if; if (opsize = 1 or memFirst = '0') then if (regs.FlagDir) then regs.reg_si <= regs.reg_si - opsize; else regs.reg_si <= regs.reg_si + opsize; end if; if (opcodeNext /= OP_INVALID) then opcode <= opcodeNext; opcodeNext <= OP_INVALID; memFirst <= '1'; else exeDone := '1'; if (repeat = '1') then regs.reg_cx <= regs.reg_cx - 1; if (regs.reg_cx = 1) then repeat <= '0'; endRepeat := '1'; prefixIP <= (others => '0'); regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; end if; end if; end if; end if; when others => null; end case; end if; when OP_STRINGCOMPARE => if (repeat = '1' and regs.reg_cx = 0) then repeat <= '0'; endRepeat := '1'; prefixIP <= (others => '0'); regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; exeDone := '1'; else case (opstep) is when 0 => if (ce = '1') then opstep <= 1; bus_read <= '1'; bus_write <= '0'; if (memFirst = '0') then bus_addr <= resize(regs.reg_es * 16 + regs.reg_di + 1, 20); else bus_addr <= resize(regs.reg_es * 16 + regs.reg_di, 20); end if; prefetchAllow <= '0'; end if; when 1 => opstep <= 2; when 2 => memFirst <= '0'; if (opsize = 1 or memFirst = '1') then stringLoad2(7 downto 0) <= unsigned(bus_dataread(7 downto 0)); if (opsize = 1) then stringLoad2(15 downto 8) <= x"00"; end if; else stringLoad2(15 downto 8) <= unsigned(bus_dataread(7 downto 0)); end if; if (opsize = 1 or memFirst = '0') then opstep <= 3; aluop <= ALU_OP_CMP; else opstep <= 0; end if; when 3 => if (ce = '1') then exeDone := '1'; if (regs.FlagDir) then regs.reg_di <= regs.reg_di - opsize; else regs.reg_di <= regs.reg_di + opsize; end if; if (repeat = '1') then regs.reg_cx <= regs.reg_cx - 1; if (regs.reg_cx = 1 or (repeatZero = '0' and regs.FlagZer = '1') or (repeatZero = '1' and regs.FlagZer = '0')) then repeat <= '0'; endRepeat := '1'; prefixIP <= (others => '0'); regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; end if; end if; end if; when others => null; end case; end if; when OP_STRINGSTORE => if (repeat = '1' and regs.reg_cx = 0) then repeat <= '0'; endRepeat := '1'; prefixIP <= (others => '0'); regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; newExeDelay := newExeDelay + 1; exeDone := '1'; else prefetchAllow <= '0'; if (bus_read = '0' and bus_write = '0' and (waitexe = '0' or ce = '1')) then memFirst <= '0'; waitexe <= '1'; bus_read <= '0'; bus_write <= '1'; bus_be <= "01"; if (memFirst = '0') then bus_datawrite <= x"00" & std_logic_vector(resultval(15 downto 8)); bus_addr <= resize(regs.reg_es * 16 + regs.reg_di + 1, 20); else bus_datawrite <= x"00" & std_logic_vector(resultval(7 downto 0)); bus_addr <= resize(regs.reg_es * 16 + regs.reg_di, 20); end if; if (opsize = 1 or memFirst = '0') then exeDone := '1'; if (regs.FlagDir) then regs.reg_di <= regs.reg_di - opsize; else regs.reg_di <= regs.reg_di + opsize; end if; if (repeat = '1') then regs.reg_cx <= regs.reg_cx - 1; if (regs.reg_cx = 1) then repeat <= '0'; endRepeat := '1'; prefixIP <= (others => '0'); regs.reg_ip <= regs.reg_ip + 1; consumePrefetch <= 1; end if; end if; end if; elsif (waitexe = '1' and ce = '1') then waitexe <= '0'; end if; end if; when OP_ENTER => case (opstep) is when 0 => regs.reg_bp <= regs.reg_sp; regs.reg_sp <= regs.reg_sp - fetch1Val; opstep <= 1; if (fetch2Val(4 downto 0) = 0) then exeDone := '1'; end if; when 1 => if (ce = '1') then opstep <= 2; varmemSegment := regs.reg_ds; if (prefixSegmentES = '1') then varmemSegment := regs.reg_es; end if; if (prefixSegmentCS = '1') then varmemSegment := regs.reg_cs; end if; if (prefixSegmentSS = '1') then varmemSegment := regs.reg_ss; end if; if (prefixSegmentDS = '1') then varmemSegment := regs.reg_ds; end if; bus_read <= '1'; bus_write <= '0'; if (memFirst = '1') then bus_addr <= resize(varmemSegment * 16 + regs.reg_bp - (enterCnt * 2), 20); else bus_addr <= resize(varmemSegment * 16 + regs.reg_bp - (enterCnt * 2) + 1, 20); end if; prefetchAllow <= '0'; end if; when 2 => opstep <= 3; when 3 => memFirst <= '0'; if (memFirst = '1') then memFetchValue1(7 downto 0) <= unsigned(bus_dataread(7 downto 0)); else memFetchValue1(15 downto 8) <= unsigned(bus_dataread(7 downto 0)); end if; if (memFirst = '0') then enterCnt <= enterCnt + 1; if (enterCnt = fetch2Val(4 downto 0)) then pushlist <= REGPOS_bp; opcode <= OP_NOP; cpustage <= CPUSTAGE_PUSH; else pushlist <= REGPOS_mem; cpustage <= CPUSTAGE_PUSH; opstep <= 1; memFirst <= '1'; end if; end if; when others => null; end case; when OP_JUMPIF => cond := '0'; case (opcodebyte) is when x"70" => if (regs.FlagOvf = '1' ) then cond := '1'; end if; when x"71" => if (regs.FlagOvf = '0' ) then cond := '1'; end if; when x"72" => if (regs.FlagCar = '1' ) then cond := '1'; end if; when x"73" => if (regs.FlagCar = '0' ) then cond := '1'; end if; when x"74" => if (regs.FlagZer = '1' ) then cond := '1'; end if; when x"75" => if (regs.FlagZer = '0' ) then cond := '1'; end if; when x"76" => if (regs.FlagZer = '1' or regs.FlagCar = '1' ) then cond := '1'; end if; when x"77" => if (regs.FlagZer = '0' and regs.FlagCar = '0' ) then cond := '1'; end if; when x"78" => if (regs.FlagSgn = '1' ) then cond := '1'; end if; when x"79" => if (regs.FlagSgn = '0' ) then cond := '1'; end if; when x"7A" => if (regs.FlagPar = '1' ) then cond := '1'; end if; when x"7B" => if (regs.FlagPar = '0' ) then cond := '1'; end if; when x"7C" => if (regs.FlagSgn /= regs.FlagOvf and regs.FlagZer = '0') then cond := '1'; end if; when x"7D" => if (regs.FlagSgn = regs.FlagOvf or regs.FlagZer = '1') then cond := '1'; end if; when x"7E" => if (regs.FlagSgn /= regs.FlagOvf or regs.FlagZer = '1') then cond := '1'; end if; when x"7F" => if (regs.FlagSgn = regs.FlagOvf and regs.FlagZer = '0') then cond := '1'; end if; when x"E0" => if (regs.reg_cx /= 1 and regs.FlagZer = '0') then cond := '1'; end if; regs.reg_cx <= regs.reg_cx - 1; when x"E1" => if (regs.reg_cx /= 1 and regs.FlagZer = '1') then cond := '1'; end if; regs.reg_cx <= regs.reg_cx - 1; when x"E2" => if (regs.reg_cx /= 1) then cond := '1'; end if; regs.reg_cx <= regs.reg_cx - 1; when x"E3" => if (regs.reg_cx = 0) then cond := '1'; end if; when x"EB" => cond := '1'; when others => null; end case; if (cond = '1') then jumpNow := '1'; jumpAddr := to_unsigned(to_integer(regs.reg_ip) + to_integer(signed(source1Val(7 downto 0))), 16); end if; exeDone := '1'; when OP_JUMP => jumpNow := '1'; jumpAddr := regs.reg_ip + source1Val; clearPrefetch <= '1'; exeDone := '1'; when OP_JUMPABS => jumpNow := '1'; jumpAddr := source1Val; clearPrefetch <= '1'; exeDone := '1'; when OP_JUMPFAR => jumpNow := '1'; jumpAddr := source1Val; regs.reg_cs <= source2Val; clearPrefetch <= '1'; exeDone := '1'; when OP_RETURNFAR => regs.reg_sp <= regs.reg_sp + source1Val; clearPrefetch <= '1'; newExeDelay := newExeDelay + 3; exeDone := '1'; when OP_IRQ => regs.FlagBrk <= '0'; regs.FlagIrq <= '0'; regs.FlagMod <= '1'; jumpNow := '1'; jumpAddr := irqIP; regs.reg_cs <= irqCS; clearPrefetch <= '1'; exeDone := '1'; when OP_IRQREQUEST => irqrequest <= '1'; irqvector <= source1Val(7 downto 0) & "00"; cpustage <= CPUSTAGE_IDLE; when OP_FLAGSFROMACC => regs.FlagCar <= regs.reg_ax(8); regs.FlagPar <= regs.reg_ax(10); regs.FlagHaC <= regs.reg_ax(12); regs.FlagZer <= regs.reg_ax(14); regs.FlagSgn <= regs.reg_ax(15); exeDone := '1'; when OP_FLAGSTOACC => regs.reg_ax(15 downto 8) <= Reg_f(7 downto 0); exeDone := '1'; when OP_DIV => if (opstep = 0 and ce = '1') then delay <= 10; opstep <= 1; DIVstart <= '1'; DIVdivisor <= '0' & x"0000" & signed(memFetchValue2); if (opsize = 1) then DIVdividend <= '0' & x"0000" & signed(regs.reg_ax); else DIVdividend <= '0' & signed(regs.reg_dx) & signed(regs.reg_ax); end if; elsif (ce = '1') then exeDone := '1'; if (memFetchValue2 = 0) then irqrequest <= '1'; irqvector <= (others => '0'); else if (opsize = 1) then regs.reg_ax <= unsigned(DIVremainder(7 downto 0)) & unsigned(DIVquotient(7 downto 0)); else regs.reg_ax <= unsigned(DIVquotient(15 downto 0)); regs.reg_dx <= unsigned(DIVremainder(15 downto 0)); end if; end if; end if; when OP_DIVI => if (opstep = 0 and ce = '1') then delay <= 10; opstep <= 1; DIVstart <= '1'; if (opsize = 1) then DIVdividend <= resize(signed(regs.reg_ax), 33); DIVdivisor <= resize(signed(memFetchValue2(7 downto 0)), 33); else DIVdividend <= resize(signed(regs.reg_dx & regs.reg_ax), 33); DIVdivisor <= resize(signed(memFetchValue2), 33); end if; elsif (ce = '1') then exeDone := '1'; if (memFetchValue2 = 0) then irqrequest <= '1'; irqvector <= (others => '0'); else if (opsize = 1) then regs.reg_ax <= unsigned(DIVremainder(7 downto 0)) & unsigned(DIVquotient(7 downto 0)); else regs.reg_ax <= unsigned(DIVquotient(15 downto 0)); regs.reg_dx <= unsigned(DIVremainder(15 downto 0)); end if; end if; end if; when OP_MULADJUST => if (opstep = 0 and ce = '1') then delay <= 10; opstep <= 1; DIVstart <= '1'; DIVdividend <= '0' & x"000000" & signed(regs.reg_ax(7 downto 0)); DIVdivisor <= to_signed(10, 33); elsif (ce = '1') then exeDone := '1'; if (fetch1Val = 0) then irqrequest <= '1'; irqvector <= (others => '0'); else regs.reg_ax <= unsigned(DIVquotient(7 downto 0)) & unsigned(DIVremainder(7 downto 0)); if (DIVremainder(7 downto 0) = 0 and DIVquotient(7 downto 0) = 0) then regs.FlagZer <= '1'; else regs.FlagZer <= '0'; end if; regs.FlagSgn <= DIVremainder(7); regs.FlagPar <= not(DIVremainder(7) xor DIVremainder(6) xor DIVremainder(5) xor DIVremainder(4) xor DIVremainder(3) xor DIVremainder(2) xor DIVremainder(1) xor DIVremainder(0)); end if; end if; when OP_DIVADJUST => result8 := regs.reg_ax(7 downto 0) + resize(regs.reg_ax(15 downto 8) * 10, 8); regs.reg_ax( 7 downto 0) <= result8; regs.reg_ax(15 downto 8) <= x"00"; if (result8 = 0) then regs.FlagZer <= '1'; else regs.FlagZer <= '0'; end if; regs.FlagSgn <='0'; regs.FlagPar <= not(result8(7) xor result8(6) xor result8(5) xor result8(4) xor result8(3) xor result8(2) xor result8(1) xor result8(0)); exeDone := '1'; when others => exeDone := '1'; end case; if (jumpNow = '1') then regs.reg_ip <= jumpAddr; clearPrefetch <= '1'; if (jumpAddr(0) = '1') then newExeDelay := newExeDelay + 4; else newExeDelay := newExeDelay + 3; end if; end if; if (exeDone = '1') then delay <= newExeDelay; if (newExeDelay = 0) then cpu_done <= '1'; else cpu_finished <= '1'; end if; cpustage <= CPUSTAGE_IDLE; if (repeat = '0' or endRepeat = '1') then prefixSegmentES <= '0'; prefixSegmentCS <= '0'; prefixSegmentSS <= '0'; prefixSegmentDS <= '0'; end if; end if; when others => null; end case; end if; -- prefetch varPrefetchCount := prefetchCount; varprefetchBuffer := prefetchBuffer; case (prefetchState) is when PREFETCH_IDLE => if (ce = '1' and prefetchCount < 14 and dma_active = '0' and sdma_request = '0') then prefetchState <= PREFETCH_READ; prefetchDisturb <= '0'; end if; when PREFETCH_READ => if (prefetchAllow = '1') then prefetchAddrOld <= prefetchAddr; prefetchState <= PREFETCH_WAIT; bus_addr <= prefetchAddr; bus_read <= '1'; if (prefetchAddr(0) = '1') then prefetchAddr <= PrefetchAddr + 1; prefetch1byte <= '1'; else prefetchAddr <= PrefetchAddr + 2; prefetch1byte <= '0'; end if; else prefetchState <= PREFETCH_IDLE; end if; when PREFETCH_WAIT => prefetchState <= PREFETCH_RECEIVE; when PREFETCH_RECEIVE => prefetchState <= PREFETCH_IDLE; if (prefetchAllow = '1' and dma_active = '0' and prefetchDisturb = '0') then varprefetchBuffer((PrefetchCount * 8) + 7 downto (PrefetchCount * 8)) := bus_dataread(7 downto 0); if (prefetch1byte = '0') then varprefetchBuffer((PrefetchCount * 8) + 15 downto (PrefetchCount * 8) + 8) := bus_dataread(15 downto 8); varPrefetchCount := varPrefetchCount + 2; else varPrefetchCount := varPrefetchCount + 1; end if; else prefetchAddr <= prefetchAddrOld; end if; end case; if (consumePrefetch = 1) then varprefetchBuffer := x"00" & varprefetchBuffer(127 downto 8); varPrefetchCount := varPrefetchCount - 1; elsif (consumePrefetch = 2) then varprefetchBuffer := x"0000" & varprefetchBuffer(127 downto 16); varPrefetchCount := varPrefetchCount - 2; elsif (consumePrefetch = 3) then varprefetchBuffer := x"000000" & varprefetchBuffer(127 downto 24); varPrefetchCount := varPrefetchCount - 3; end if; prefetchCount <= varPrefetchCount; prefetchBuffer <= varprefetchBuffer; if (clearPrefetch = '1') then if (ce = '1') then prefetchState <= PREFETCH_READ; else prefetchState <= PREFETCH_IDLE; end if; prefetchCount <= 0; prefetchBuffer <= (others => '0'); prefetchAddr <= resize(regs.reg_cs * 16 + regs.reg_ip, 20); end if; end if; end if; end process; idivider : entity work.divider port map ( clk => clk, start => DIVstart, done => open, busy => open, dividend => DIVdividend, divisor => DIVdivisor, quotient => DIVquotient, remainder => DIVremainder ); cpu_export_reg_cs <= regs.reg_cs; cpu_export_reg_ip <= regs.reg_ip; cpu_export_opcode <= opcodebyte; end architecture;