1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-01-25 03:25:52 +00:00
Gyorgy Szombathelyi 74804cb1b2 IremM72
2022-09-04 23:11:21 +02:00

3137 lines
196 KiB
VHDL

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;