|
@@ -0,0 +1,2028 @@
|
|
|
+-- ****
|
|
|
+-- T80(b) core. In an effort to merge and maintain bug fixes ....
|
|
|
+--
|
|
|
+--
|
|
|
+-- Ver 303 add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010
|
|
|
+-- Ver 302 fixed IO cycle timing, tested thanks to Alessandro.
|
|
|
+-- Ver 300 started tidyup
|
|
|
+-- MikeJ March 2005
|
|
|
+-- Latest version from www.fpgaarcade.com (original www.opencores.org)
|
|
|
+--
|
|
|
+-- ****
|
|
|
+--
|
|
|
+-- Z80 compatible microprocessor core
|
|
|
+--
|
|
|
+-- Version : 0242
|
|
|
+--
|
|
|
+-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
|
|
|
+--
|
|
|
+-- All rights reserved
|
|
|
+--
|
|
|
+-- Redistribution and use in source and synthezised forms, with or without
|
|
|
+-- modification, are permitted provided that the following conditions are met:
|
|
|
+--
|
|
|
+-- Redistributions of source code must retain the above copyright notice,
|
|
|
+-- this list of conditions and the following disclaimer.
|
|
|
+--
|
|
|
+-- Redistributions in synthesized form must reproduce the above copyright
|
|
|
+-- notice, this list of conditions and the following disclaimer in the
|
|
|
+-- documentation and/or other materials provided with the distribution.
|
|
|
+--
|
|
|
+-- Neither the name of the author nor the names of other contributors may
|
|
|
+-- be used to endorse or promote products derived from this software without
|
|
|
+-- specific prior written permission.
|
|
|
+--
|
|
|
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
|
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
|
|
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
+-- POSSIBILITY OF SUCH DAMAGE.
|
|
|
+--
|
|
|
+-- Please report bugs to the author, but before you do so, please
|
|
|
+-- make sure that this is not a derivative work and that
|
|
|
+-- you have the latest version of this file.
|
|
|
+--
|
|
|
+-- The latest version of this file can be found at:
|
|
|
+-- http://www.opencores.org/cvsweb.shtml/t80/
|
|
|
+--
|
|
|
+-- Limitations :
|
|
|
+--
|
|
|
+-- File history :
|
|
|
+--
|
|
|
+-- 0208 : First complete release
|
|
|
+--
|
|
|
+-- 0211 : Fixed IM 1
|
|
|
+--
|
|
|
+-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
|
|
|
+--
|
|
|
+-- 0235 : Added IM 2 fix by Mike Johnson
|
|
|
+--
|
|
|
+-- 0238 : Added NoRead signal
|
|
|
+--
|
|
|
+-- 0238b: Fixed instruction timing for POP and DJNZ
|
|
|
+--
|
|
|
+-- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes
|
|
|
+
|
|
|
+-- 0240mj1 fix for HL inc/dec for INI, IND, INIR, INDR, OUTI, OUTD, OTIR, OTDR
|
|
|
+--
|
|
|
+-- 0242 : Fixed I/O instruction timing, cleanup
|
|
|
+--
|
|
|
+
|
|
|
+library IEEE;
|
|
|
+use IEEE.std_logic_1164.all;
|
|
|
+use IEEE.numeric_std.all;
|
|
|
+use work.T80_Pack.all;
|
|
|
+
|
|
|
+entity T80_MCode is
|
|
|
+ generic(
|
|
|
+ Mode : integer := 0;
|
|
|
+ Flag_C : integer := 0;
|
|
|
+ Flag_N : integer := 1;
|
|
|
+ Flag_P : integer := 2;
|
|
|
+ Flag_X : integer := 3;
|
|
|
+ Flag_H : integer := 4;
|
|
|
+ Flag_Y : integer := 5;
|
|
|
+ Flag_Z : integer := 6;
|
|
|
+ Flag_S : integer := 7
|
|
|
+ );
|
|
|
+ port(
|
|
|
+ IR : in std_logic_vector(7 downto 0);
|
|
|
+ ISet : in std_logic_vector(1 downto 0);
|
|
|
+ MCycle : in std_logic_vector(2 downto 0);
|
|
|
+ F : in std_logic_vector(7 downto 0);
|
|
|
+ NMICycle : in std_logic;
|
|
|
+ IntCycle : in std_logic;
|
|
|
+ XY_State : in std_logic_vector(1 downto 0);
|
|
|
+ MCycles : out std_logic_vector(2 downto 0);
|
|
|
+ TStates : out std_logic_vector(2 downto 0);
|
|
|
+ Prefix : out std_logic_vector(1 downto 0); -- None,CB,ED,DD/FD
|
|
|
+ Inc_PC : out std_logic;
|
|
|
+ Inc_WZ : out std_logic;
|
|
|
+ IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc
|
|
|
+ Read_To_Reg : out std_logic;
|
|
|
+ Read_To_Acc : out std_logic;
|
|
|
+ Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
|
|
|
+ Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0
|
|
|
+ ALU_Op : out std_logic_vector(3 downto 0);
|
|
|
+ -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None
|
|
|
+ Save_ALU : out std_logic;
|
|
|
+ PreserveC : out std_logic;
|
|
|
+ Arith16 : out std_logic;
|
|
|
+ Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI
|
|
|
+ IORQ : out std_logic;
|
|
|
+ Jump : out std_logic;
|
|
|
+ JumpE : out std_logic;
|
|
|
+ JumpXY : out std_logic;
|
|
|
+ Call : out std_logic;
|
|
|
+ RstP : out std_logic;
|
|
|
+ LDZ : out std_logic;
|
|
|
+ LDW : out std_logic;
|
|
|
+ LDSPHL : out std_logic;
|
|
|
+ Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None
|
|
|
+ ExchangeDH : out std_logic;
|
|
|
+ ExchangeRp : out std_logic;
|
|
|
+ ExchangeAF : out std_logic;
|
|
|
+ ExchangeRS : out std_logic;
|
|
|
+ I_DJNZ : out std_logic;
|
|
|
+ I_CPL : out std_logic;
|
|
|
+ I_CCF : out std_logic;
|
|
|
+ I_SCF : out std_logic;
|
|
|
+ I_RETN : out std_logic;
|
|
|
+ I_BT : out std_logic;
|
|
|
+ I_BC : out std_logic;
|
|
|
+ I_BTR : out std_logic;
|
|
|
+ I_RLD : out std_logic;
|
|
|
+ I_RRD : out std_logic;
|
|
|
+ I_INRC : out std_logic;
|
|
|
+ SetDI : out std_logic;
|
|
|
+ SetEI : out std_logic;
|
|
|
+ IMode : out std_logic_vector(1 downto 0);
|
|
|
+ Halt : out std_logic;
|
|
|
+ NoRead : out std_logic;
|
|
|
+ Write : out std_logic;
|
|
|
+ XYbit_undoc : out std_logic
|
|
|
+ );
|
|
|
+end T80_MCode;
|
|
|
+
|
|
|
+architecture rtl of T80_MCode is
|
|
|
+
|
|
|
+ constant aNone : std_logic_vector(2 downto 0) := "111";
|
|
|
+ constant aBC : std_logic_vector(2 downto 0) := "000";
|
|
|
+ constant aDE : std_logic_vector(2 downto 0) := "001";
|
|
|
+ constant aXY : std_logic_vector(2 downto 0) := "010";
|
|
|
+ constant aIOA : std_logic_vector(2 downto 0) := "100";
|
|
|
+ constant aSP : std_logic_vector(2 downto 0) := "101";
|
|
|
+ constant aZI : std_logic_vector(2 downto 0) := "110";
|
|
|
+
|
|
|
+ function is_cc_true(
|
|
|
+ F : std_logic_vector(7 downto 0);
|
|
|
+ cc : bit_vector(2 downto 0)
|
|
|
+ ) return boolean is
|
|
|
+ begin
|
|
|
+ if Mode = 3 then
|
|
|
+ case cc is
|
|
|
+ when "000" => return F(7) = '0'; -- NZ
|
|
|
+ when "001" => return F(7) = '1'; -- Z
|
|
|
+ when "010" => return F(4) = '0'; -- NC
|
|
|
+ when "011" => return F(4) = '1'; -- C
|
|
|
+ when "100" => return false;
|
|
|
+ when "101" => return false;
|
|
|
+ when "110" => return false;
|
|
|
+ when "111" => return false;
|
|
|
+ end case;
|
|
|
+ else
|
|
|
+ case cc is
|
|
|
+ when "000" => return F(6) = '0'; -- NZ
|
|
|
+ when "001" => return F(6) = '1'; -- Z
|
|
|
+ when "010" => return F(0) = '0'; -- NC
|
|
|
+ when "011" => return F(0) = '1'; -- C
|
|
|
+ when "100" => return F(2) = '0'; -- PO
|
|
|
+ when "101" => return F(2) = '1'; -- PE
|
|
|
+ when "110" => return F(7) = '0'; -- P
|
|
|
+ when "111" => return F(7) = '1'; -- M
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ end;
|
|
|
+
|
|
|
+begin
|
|
|
+
|
|
|
+ process (IR, ISet, MCycle, F, NMICycle, IntCycle)
|
|
|
+ variable DDD : std_logic_vector(2 downto 0);
|
|
|
+ variable SSS : std_logic_vector(2 downto 0);
|
|
|
+ variable DPair : std_logic_vector(1 downto 0);
|
|
|
+ variable IRB : bit_vector(7 downto 0);
|
|
|
+ begin
|
|
|
+ DDD := IR(5 downto 3);
|
|
|
+ SSS := IR(2 downto 0);
|
|
|
+ DPair := IR(5 downto 4);
|
|
|
+ IRB := to_bitvector(IR);
|
|
|
+
|
|
|
+ MCycles <= "001";
|
|
|
+ if MCycle = "001" then
|
|
|
+ TStates <= "100";
|
|
|
+ else
|
|
|
+ TStates <= "011";
|
|
|
+ end if;
|
|
|
+ Prefix <= "00";
|
|
|
+ Inc_PC <= '0';
|
|
|
+ Inc_WZ <= '0';
|
|
|
+ IncDec_16 <= "0000";
|
|
|
+ Read_To_Acc <= '0';
|
|
|
+ Read_To_Reg <= '0';
|
|
|
+ Set_BusB_To <= "0000";
|
|
|
+ Set_BusA_To <= "0000";
|
|
|
+ ALU_Op <= "0" & IR(5 downto 3);
|
|
|
+ Save_ALU <= '0';
|
|
|
+ PreserveC <= '0';
|
|
|
+ Arith16 <= '0';
|
|
|
+ IORQ <= '0';
|
|
|
+ Set_Addr_To <= aNone;
|
|
|
+ Jump <= '0';
|
|
|
+ JumpE <= '0';
|
|
|
+ JumpXY <= '0';
|
|
|
+ Call <= '0';
|
|
|
+ RstP <= '0';
|
|
|
+ LDZ <= '0';
|
|
|
+ LDW <= '0';
|
|
|
+ LDSPHL <= '0';
|
|
|
+ Special_LD <= "000";
|
|
|
+ ExchangeDH <= '0';
|
|
|
+ ExchangeRp <= '0';
|
|
|
+ ExchangeAF <= '0';
|
|
|
+ ExchangeRS <= '0';
|
|
|
+ I_DJNZ <= '0';
|
|
|
+ I_CPL <= '0';
|
|
|
+ I_CCF <= '0';
|
|
|
+ I_SCF <= '0';
|
|
|
+ I_RETN <= '0';
|
|
|
+ I_BT <= '0';
|
|
|
+ I_BC <= '0';
|
|
|
+ I_BTR <= '0';
|
|
|
+ I_RLD <= '0';
|
|
|
+ I_RRD <= '0';
|
|
|
+ I_INRC <= '0';
|
|
|
+ SetDI <= '0';
|
|
|
+ SetEI <= '0';
|
|
|
+ IMode <= "11";
|
|
|
+ Halt <= '0';
|
|
|
+ NoRead <= '0';
|
|
|
+ Write <= '0';
|
|
|
+ XYbit_undoc <= '0';
|
|
|
+
|
|
|
+ case ISet is
|
|
|
+ when "00" =>
|
|
|
+
|
|
|
+------------------------------------------------------------------------------
|
|
|
+--
|
|
|
+-- Unprefixed instructions
|
|
|
+--
|
|
|
+------------------------------------------------------------------------------
|
|
|
+
|
|
|
+ case IRB is
|
|
|
+-- 8 BIT LOAD GROUP
|
|
|
+ when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111"
|
|
|
+ |"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111"
|
|
|
+ |"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111"
|
|
|
+ |"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111"
|
|
|
+ |"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111"
|
|
|
+ |"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111"
|
|
|
+ |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" =>
|
|
|
+ -- LD r,r'
|
|
|
+ Set_BusB_To(2 downto 0) <= SSS;
|
|
|
+ ExchangeRp <= '1';
|
|
|
+ Set_BusA_To(2 downto 0) <= DDD;
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ when "00000110"|"00001110"|"00010110"|"00011110"|"00100110"|"00101110"|"00111110" =>
|
|
|
+ -- LD r,n
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Set_BusA_To(2 downto 0) <= DDD;
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01111110" =>
|
|
|
+ -- LD r,(HL)
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ Set_BusA_To(2 downto 0) <= DDD;
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" =>
|
|
|
+ -- LD (HL),r
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ Set_BusB_To(2 downto 0) <= SSS;
|
|
|
+ Set_BusB_To(3) <= '0';
|
|
|
+ when 2 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "00110110" =>
|
|
|
+ -- LD (HL),n
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ Set_BusB_To(2 downto 0) <= SSS;
|
|
|
+ Set_BusB_To(3) <= '0';
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "00001010" =>
|
|
|
+ -- LD A,(BC)
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aBC;
|
|
|
+ when 2 =>
|
|
|
+ Read_To_Acc <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "00011010" =>
|
|
|
+ -- LD A,(DE)
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aDE;
|
|
|
+ when 2 =>
|
|
|
+ Read_To_Acc <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "00111010" =>
|
|
|
+ if Mode = 3 then
|
|
|
+ -- LDD A,(HL)
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ Read_To_Acc <= '1';
|
|
|
+ IncDec_16 <= "1110";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ else
|
|
|
+ -- LD A,(nn)
|
|
|
+ MCycles <= "100";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Inc_PC <= '1';
|
|
|
+ when 4 =>
|
|
|
+ Read_To_Acc <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "00000010" =>
|
|
|
+ -- LD (BC),A
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aBC;
|
|
|
+ Set_BusB_To <= "0111";
|
|
|
+ when 2 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "00010010" =>
|
|
|
+ -- LD (DE),A
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aDE;
|
|
|
+ Set_BusB_To <= "0111";
|
|
|
+ when 2 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "00110010" =>
|
|
|
+ if Mode = 3 then
|
|
|
+ -- LDD (HL),A
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ Set_BusB_To <= "0111";
|
|
|
+ when 2 =>
|
|
|
+ Write <= '1';
|
|
|
+ IncDec_16 <= "1110";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ else
|
|
|
+ -- LD (nn),A
|
|
|
+ MCycles <= "100";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Set_BusB_To <= "0111";
|
|
|
+ when 4 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+
|
|
|
+-- 16 BIT LOAD GROUP
|
|
|
+ when "00000001"|"00010001"|"00100001"|"00110001" =>
|
|
|
+ -- LD dd,nn
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ if DPAIR = "11" then
|
|
|
+ Set_BusA_To(3 downto 0) <= "1000";
|
|
|
+ else
|
|
|
+ Set_BusA_To(2 downto 1) <= DPAIR;
|
|
|
+ Set_BusA_To(0) <= '1';
|
|
|
+ end if;
|
|
|
+ when 3 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ if DPAIR = "11" then
|
|
|
+ Set_BusA_To(3 downto 0) <= "1001";
|
|
|
+ else
|
|
|
+ Set_BusA_To(2 downto 1) <= DPAIR;
|
|
|
+ Set_BusA_To(0) <= '0';
|
|
|
+ end if;
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "00101010" =>
|
|
|
+ if Mode = 3 then
|
|
|
+ -- LDI A,(HL)
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ Read_To_Acc <= '1';
|
|
|
+ IncDec_16 <= "0110";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ else
|
|
|
+ -- LD HL,(nn)
|
|
|
+ MCycles <= "101";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDW <= '1';
|
|
|
+ when 4 =>
|
|
|
+ Set_BusA_To(2 downto 0) <= "101"; -- L
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Inc_WZ <= '1';
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ when 5 =>
|
|
|
+ Set_BusA_To(2 downto 0) <= "100"; -- H
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "00100010" =>
|
|
|
+ if Mode = 3 then
|
|
|
+ -- LDI (HL),A
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ Set_BusB_To <= "0111";
|
|
|
+ when 2 =>
|
|
|
+ Write <= '1';
|
|
|
+ IncDec_16 <= "0110";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ else
|
|
|
+ -- LD (nn),HL
|
|
|
+ MCycles <= "101";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDW <= '1';
|
|
|
+ Set_BusB_To <= "0101"; -- L
|
|
|
+ when 4 =>
|
|
|
+ Inc_WZ <= '1';
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Write <= '1';
|
|
|
+ Set_BusB_To <= "0100"; -- H
|
|
|
+ when 5 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "11111001" =>
|
|
|
+ -- LD SP,HL
|
|
|
+ TStates <= "110";
|
|
|
+ LDSPHL <= '1';
|
|
|
+ when "11000101"|"11010101"|"11100101"|"11110101" =>
|
|
|
+ -- PUSH qq
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ TStates <= "101";
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ Set_Addr_TO <= aSP;
|
|
|
+ if DPAIR = "11" then
|
|
|
+ Set_BusB_To <= "0111";
|
|
|
+ else
|
|
|
+ Set_BusB_To(2 downto 1) <= DPAIR;
|
|
|
+ Set_BusB_To(0) <= '0';
|
|
|
+ Set_BusB_To(3) <= '0';
|
|
|
+ end if;
|
|
|
+ when 2 =>
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ if DPAIR = "11" then
|
|
|
+ Set_BusB_To <= "1011";
|
|
|
+ else
|
|
|
+ Set_BusB_To(2 downto 1) <= DPAIR;
|
|
|
+ Set_BusB_To(0) <= '1';
|
|
|
+ Set_BusB_To(3) <= '0';
|
|
|
+ end if;
|
|
|
+ Write <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "11000001"|"11010001"|"11100001"|"11110001" =>
|
|
|
+ -- POP qq
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ when 2 =>
|
|
|
+ IncDec_16 <= "0111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ if DPAIR = "11" then
|
|
|
+ Set_BusA_To(3 downto 0) <= "1011";
|
|
|
+ else
|
|
|
+ Set_BusA_To(2 downto 1) <= DPAIR;
|
|
|
+ Set_BusA_To(0) <= '1';
|
|
|
+ end if;
|
|
|
+ when 3 =>
|
|
|
+ IncDec_16 <= "0111";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ if DPAIR = "11" then
|
|
|
+ Set_BusA_To(3 downto 0) <= "0111";
|
|
|
+ else
|
|
|
+ Set_BusA_To(2 downto 1) <= DPAIR;
|
|
|
+ Set_BusA_To(0) <= '0';
|
|
|
+ end if;
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+
|
|
|
+-- EXCHANGE, BLOCK TRANSFER AND SEARCH GROUP
|
|
|
+ when "11101011" =>
|
|
|
+ if Mode /= 3 then
|
|
|
+ -- EX DE,HL
|
|
|
+ ExchangeDH <= '1';
|
|
|
+ end if;
|
|
|
+ when "00001000" =>
|
|
|
+ if Mode = 3 then
|
|
|
+ -- LD (nn),SP
|
|
|
+ MCycles <= "101";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDW <= '1';
|
|
|
+ Set_BusB_To <= "1000";
|
|
|
+ when 4 =>
|
|
|
+ Inc_WZ <= '1';
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Write <= '1';
|
|
|
+ Set_BusB_To <= "1001";
|
|
|
+ when 5 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ elsif Mode < 2 then
|
|
|
+ -- EX AF,AF'
|
|
|
+ ExchangeAF <= '1';
|
|
|
+ end if;
|
|
|
+ when "11011001" =>
|
|
|
+ if Mode = 3 then
|
|
|
+ -- RETI
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_TO <= aSP;
|
|
|
+ when 2 =>
|
|
|
+ IncDec_16 <= "0111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Jump <= '1';
|
|
|
+ IncDec_16 <= "0111";
|
|
|
+ I_RETN <= '1';
|
|
|
+ SetEI <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ elsif Mode < 2 then
|
|
|
+ -- EXX
|
|
|
+ ExchangeRS <= '1';
|
|
|
+ end if;
|
|
|
+ when "11100011" =>
|
|
|
+ if Mode /= 3 then
|
|
|
+ -- EX (SP),HL
|
|
|
+ MCycles <= "101";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ when 2 =>
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Set_BusA_To <= "0101";
|
|
|
+ Set_BusB_To <= "0101";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ when 3 =>
|
|
|
+ IncDec_16 <= "0111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ TStates <= "100";
|
|
|
+ Write <= '1';
|
|
|
+ when 4 =>
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Set_BusA_To <= "0100";
|
|
|
+ Set_BusB_To <= "0100";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ when 5 =>
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ TStates <= "101";
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+
|
|
|
+-- 8 BIT ARITHMETIC AND LOGICAL GROUP
|
|
|
+ when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111"
|
|
|
+ |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111"
|
|
|
+ |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111"
|
|
|
+ |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111"
|
|
|
+ |"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111"
|
|
|
+ |"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111"
|
|
|
+ |"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111"
|
|
|
+ |"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" =>
|
|
|
+ -- ADD A,r
|
|
|
+ -- ADC A,r
|
|
|
+ -- SUB A,r
|
|
|
+ -- SBC A,r
|
|
|
+ -- AND A,r
|
|
|
+ -- OR A,r
|
|
|
+ -- XOR A,r
|
|
|
+ -- CP A,r
|
|
|
+ Set_BusB_To(2 downto 0) <= SSS;
|
|
|
+ Set_BusA_To(2 downto 0) <= "111";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" =>
|
|
|
+ -- ADD A,(HL)
|
|
|
+ -- ADC A,(HL)
|
|
|
+ -- SUB A,(HL)
|
|
|
+ -- SBC A,(HL)
|
|
|
+ -- AND A,(HL)
|
|
|
+ -- OR A,(HL)
|
|
|
+ -- XOR A,(HL)
|
|
|
+ -- CP A,(HL)
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_BusB_To(2 downto 0) <= SSS;
|
|
|
+ Set_BusA_To(2 downto 0) <= "111";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" =>
|
|
|
+ -- ADD A,n
|
|
|
+ -- ADC A,n
|
|
|
+ -- SUB A,n
|
|
|
+ -- SBC A,n
|
|
|
+ -- AND A,n
|
|
|
+ -- OR A,n
|
|
|
+ -- XOR A,n
|
|
|
+ -- CP A,n
|
|
|
+ MCycles <= "010";
|
|
|
+ if MCycle = "010" then
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_BusB_To(2 downto 0) <= SSS;
|
|
|
+ Set_BusA_To(2 downto 0) <= "111";
|
|
|
+ end if;
|
|
|
+ when "00000100"|"00001100"|"00010100"|"00011100"|"00100100"|"00101100"|"00111100" =>
|
|
|
+ -- INC r
|
|
|
+ Set_BusB_To <= "1010";
|
|
|
+ Set_BusA_To(2 downto 0) <= DDD;
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ PreserveC <= '1';
|
|
|
+ ALU_Op <= "0000";
|
|
|
+ when "00110100" =>
|
|
|
+ -- INC (HL)
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ TStates <= "100";
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ PreserveC <= '1';
|
|
|
+ ALU_Op <= "0000";
|
|
|
+ Set_BusB_To <= "1010";
|
|
|
+ Set_BusA_To(2 downto 0) <= DDD;
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "00000101"|"00001101"|"00010101"|"00011101"|"00100101"|"00101101"|"00111101" =>
|
|
|
+ -- DEC r
|
|
|
+ Set_BusB_To <= "1010";
|
|
|
+ Set_BusA_To(2 downto 0) <= DDD;
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ PreserveC <= '1';
|
|
|
+ ALU_Op <= "0010";
|
|
|
+ when "00110101" =>
|
|
|
+ -- DEC (HL)
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ TStates <= "100";
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ ALU_Op <= "0010";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ PreserveC <= '1';
|
|
|
+ Set_BusB_To <= "1010";
|
|
|
+ Set_BusA_To(2 downto 0) <= DDD;
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+
|
|
|
+-- GENERAL PURPOSE ARITHMETIC AND CPU CONTROL GROUPS
|
|
|
+ when "00100111" =>
|
|
|
+ -- DAA
|
|
|
+ Set_BusA_To(2 downto 0) <= "111";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ ALU_Op <= "1100";
|
|
|
+ Save_ALU <= '1';
|
|
|
+ when "00101111" =>
|
|
|
+ -- CPL
|
|
|
+ I_CPL <= '1';
|
|
|
+ when "00111111" =>
|
|
|
+ -- CCF
|
|
|
+ I_CCF <= '1';
|
|
|
+ when "00110111" =>
|
|
|
+ -- SCF
|
|
|
+ I_SCF <= '1';
|
|
|
+ when "00000000" =>
|
|
|
+ if NMICycle = '1' then
|
|
|
+ -- NMI
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ TStates <= "101";
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ Set_BusB_To <= "1101";
|
|
|
+ when 2 =>
|
|
|
+ TStates <= "100";
|
|
|
+ Write <= '1';
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ Set_BusB_To <= "1100";
|
|
|
+ when 3 =>
|
|
|
+ TStates <= "100";
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ elsif IntCycle = '1' then
|
|
|
+ -- INT (IM 2)
|
|
|
+ MCycles <= "101";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ LDZ <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ Set_BusB_To <= "1101";
|
|
|
+ when 2 =>
|
|
|
+ TStates <= "100";
|
|
|
+ Write <= '1';
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ Set_BusB_To <= "1100";
|
|
|
+ when 3 =>
|
|
|
+ TStates <= "100";
|
|
|
+ Write <= '1';
|
|
|
+ when 4 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 5 =>
|
|
|
+ Jump <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ else
|
|
|
+ -- NOP
|
|
|
+ end if;
|
|
|
+ when "01110110" =>
|
|
|
+ -- HALT
|
|
|
+ Halt <= '1';
|
|
|
+ when "11110011" =>
|
|
|
+ -- DI
|
|
|
+ SetDI <= '1';
|
|
|
+ when "11111011" =>
|
|
|
+ -- EI
|
|
|
+ SetEI <= '1';
|
|
|
+
|
|
|
+-- 16 BIT ARITHMETIC GROUP
|
|
|
+ when "00001001"|"00011001"|"00101001"|"00111001" =>
|
|
|
+ -- ADD HL,ss
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ ALU_Op <= "0000";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_BusA_To(2 downto 0) <= "101";
|
|
|
+ case to_integer(unsigned(IR(5 downto 4))) is
|
|
|
+ when 0|1|2 =>
|
|
|
+ Set_BusB_To(2 downto 1) <= IR(5 downto 4);
|
|
|
+ Set_BusB_To(0) <= '1';
|
|
|
+ when others =>
|
|
|
+ Set_BusB_To <= "1000";
|
|
|
+ end case;
|
|
|
+ TStates <= "100";
|
|
|
+ Arith16 <= '1';
|
|
|
+ when 3 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ ALU_Op <= "0001";
|
|
|
+ Set_BusA_To(2 downto 0) <= "100";
|
|
|
+ case to_integer(unsigned(IR(5 downto 4))) is
|
|
|
+ when 0|1|2 =>
|
|
|
+ Set_BusB_To(2 downto 1) <= IR(5 downto 4);
|
|
|
+ when others =>
|
|
|
+ Set_BusB_To <= "1001";
|
|
|
+ end case;
|
|
|
+ Arith16 <= '1';
|
|
|
+ when others =>
|
|
|
+ end case;
|
|
|
+ when "00000011"|"00010011"|"00100011"|"00110011" =>
|
|
|
+ -- INC ss
|
|
|
+ TStates <= "110";
|
|
|
+ IncDec_16(3 downto 2) <= "01";
|
|
|
+ IncDec_16(1 downto 0) <= DPair;
|
|
|
+ when "00001011"|"00011011"|"00101011"|"00111011" =>
|
|
|
+ -- DEC ss
|
|
|
+ TStates <= "110";
|
|
|
+ IncDec_16(3 downto 2) <= "11";
|
|
|
+ IncDec_16(1 downto 0) <= DPair;
|
|
|
+
|
|
|
+-- ROTATE AND SHIFT GROUP
|
|
|
+ when "00000111"
|
|
|
+ -- RLCA
|
|
|
+ |"00010111"
|
|
|
+ -- RLA
|
|
|
+ |"00001111"
|
|
|
+ -- RRCA
|
|
|
+ |"00011111" =>
|
|
|
+ -- RRA
|
|
|
+ Set_BusA_To(2 downto 0) <= "111";
|
|
|
+ ALU_Op <= "1000";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+
|
|
|
+-- JUMP GROUP
|
|
|
+ when "11000011" =>
|
|
|
+ -- JP nn
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Jump <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" =>
|
|
|
+ if IR(5) = '1' and Mode = 3 then
|
|
|
+ case IRB(4 downto 3) is
|
|
|
+ when "00" =>
|
|
|
+ -- LD ($FF00+C),A
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aBC;
|
|
|
+ Set_BusB_To <= "0111";
|
|
|
+ when 2 =>
|
|
|
+ Write <= '1';
|
|
|
+ IORQ <= '1';
|
|
|
+ when others =>
|
|
|
+ end case;
|
|
|
+ when "01" =>
|
|
|
+ -- LD (nn),A
|
|
|
+ MCycles <= "100";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Set_BusB_To <= "0111";
|
|
|
+ when 4 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "10" =>
|
|
|
+ -- LD A,($FF00+C)
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aBC;
|
|
|
+ when 2 =>
|
|
|
+ Read_To_Acc <= '1';
|
|
|
+ IORQ <= '1';
|
|
|
+ when others =>
|
|
|
+ end case;
|
|
|
+ when "11" =>
|
|
|
+ -- LD A,(nn)
|
|
|
+ MCycles <= "100";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Inc_PC <= '1';
|
|
|
+ when 4 =>
|
|
|
+ Read_To_Acc <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end case;
|
|
|
+ else
|
|
|
+ -- JP cc,nn
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ if is_cc_true(F, to_bitvector(IR(5 downto 3))) then
|
|
|
+ Jump <= '1';
|
|
|
+ end if;
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "00011000" =>
|
|
|
+ if Mode /= 2 then
|
|
|
+ -- JR e
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ when 3 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ JumpE <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "00111000" =>
|
|
|
+ if Mode /= 2 then
|
|
|
+ -- JR C,e
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ if F(Flag_C) = '0' then
|
|
|
+ MCycles <= "010";
|
|
|
+ end if;
|
|
|
+ when 3 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ JumpE <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "00110000" =>
|
|
|
+ if Mode /= 2 then
|
|
|
+ -- JR NC,e
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ if F(Flag_C) = '1' then
|
|
|
+ MCycles <= "010";
|
|
|
+ end if;
|
|
|
+ when 3 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ JumpE <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "00101000" =>
|
|
|
+ if Mode /= 2 then
|
|
|
+ -- JR Z,e
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ if F(Flag_Z) = '0' then
|
|
|
+ MCycles <= "010";
|
|
|
+ end if;
|
|
|
+ when 3 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ JumpE <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "00100000" =>
|
|
|
+ if Mode /= 2 then
|
|
|
+ -- JR NZ,e
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ if F(Flag_Z) = '1' then
|
|
|
+ MCycles <= "010";
|
|
|
+ end if;
|
|
|
+ when 3 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ JumpE <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "11101001" =>
|
|
|
+ -- JP (HL)
|
|
|
+ JumpXY <= '1';
|
|
|
+ when "00010000" =>
|
|
|
+ if Mode = 3 then
|
|
|
+ I_DJNZ <= '1';
|
|
|
+ elsif Mode < 2 then
|
|
|
+ -- DJNZ,e
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ TStates <= "101";
|
|
|
+ I_DJNZ <= '1';
|
|
|
+ Set_BusB_To <= "1010";
|
|
|
+ Set_BusA_To(2 downto 0) <= "000";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ ALU_Op <= "0010";
|
|
|
+ when 2 =>
|
|
|
+ I_DJNZ <= '1';
|
|
|
+ Inc_PC <= '1';
|
|
|
+ when 3 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ JumpE <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+
|
|
|
+-- CALL AND RETURN GROUP
|
|
|
+ when "11001101" =>
|
|
|
+ -- CALL nn
|
|
|
+ MCycles <= "101";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ Inc_PC <= '1';
|
|
|
+ TStates <= "100";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ LDW <= '1';
|
|
|
+ Set_BusB_To <= "1101";
|
|
|
+ when 4 =>
|
|
|
+ Write <= '1';
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ Set_BusB_To <= "1100";
|
|
|
+ when 5 =>
|
|
|
+ Write <= '1';
|
|
|
+ Call <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "11000100"|"11001100"|"11010100"|"11011100"|"11100100"|"11101100"|"11110100"|"11111100" =>
|
|
|
+ if IR(5) = '0' or Mode /= 3 then
|
|
|
+ -- CALL cc,nn
|
|
|
+ MCycles <= "101";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDW <= '1';
|
|
|
+ if is_cc_true(F, to_bitvector(IR(5 downto 3))) then
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ Set_Addr_TO <= aSP;
|
|
|
+ TStates <= "100";
|
|
|
+ Set_BusB_To <= "1101";
|
|
|
+ else
|
|
|
+ MCycles <= "011";
|
|
|
+ end if;
|
|
|
+ when 4 =>
|
|
|
+ Write <= '1';
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ Set_BusB_To <= "1100";
|
|
|
+ when 5 =>
|
|
|
+ Write <= '1';
|
|
|
+ Call <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "11001001" =>
|
|
|
+ -- RET
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_TO <= aSP;
|
|
|
+ when 2 =>
|
|
|
+ IncDec_16 <= "0111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Jump <= '1';
|
|
|
+ IncDec_16 <= "0111";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "11000000"|"11001000"|"11010000"|"11011000"|"11100000"|"11101000"|"11110000"|"11111000" =>
|
|
|
+ if IR(5) = '1' and Mode = 3 then
|
|
|
+ case IRB(4 downto 3) is
|
|
|
+ when "00" =>
|
|
|
+ -- LD ($FF00+nn),A
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Set_Addr_To <= aIOA;
|
|
|
+ Set_BusB_To <= "0111";
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "01" =>
|
|
|
+ -- ADD SP,n
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ ALU_Op <= "0000";
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_BusA_To <= "1000";
|
|
|
+ Set_BusB_To <= "0110";
|
|
|
+ when 3 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ ALU_Op <= "0001";
|
|
|
+ Set_BusA_To <= "1001";
|
|
|
+ Set_BusB_To <= "1110"; -- Incorrect unsigned !!!!!!!!!!!!!!!!!!!!!
|
|
|
+ when others =>
|
|
|
+ end case;
|
|
|
+ when "10" =>
|
|
|
+ -- LD A,($FF00+nn)
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Set_Addr_To <= aIOA;
|
|
|
+ when 3 =>
|
|
|
+ Read_To_Acc <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "11" =>
|
|
|
+ -- LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!!
|
|
|
+ MCycles <= "101";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDW <= '1';
|
|
|
+ when 4 =>
|
|
|
+ Set_BusA_To(2 downto 0) <= "101"; -- L
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Inc_WZ <= '1';
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ when 5 =>
|
|
|
+ Set_BusA_To(2 downto 0) <= "100"; -- H
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end case;
|
|
|
+ else
|
|
|
+ -- RET cc
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ if is_cc_true(F, to_bitvector(IR(5 downto 3))) then
|
|
|
+ Set_Addr_TO <= aSP;
|
|
|
+ else
|
|
|
+ MCycles <= "001";
|
|
|
+ end if;
|
|
|
+ TStates <= "101";
|
|
|
+ when 2 =>
|
|
|
+ IncDec_16 <= "0111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Jump <= '1';
|
|
|
+ IncDec_16 <= "0111";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "11000111"|"11001111"|"11010111"|"11011111"|"11100111"|"11101111"|"11110111"|"11111111" =>
|
|
|
+ -- RST p
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ TStates <= "101";
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ Set_BusB_To <= "1101";
|
|
|
+ when 2 =>
|
|
|
+ Write <= '1';
|
|
|
+ IncDec_16 <= "1111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ Set_BusB_To <= "1100";
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ RstP <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+
|
|
|
+-- INPUT AND OUTPUT GROUP
|
|
|
+ when "11011011" =>
|
|
|
+ if Mode /= 3 then
|
|
|
+ -- IN A,(n)
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Set_Addr_To <= aIOA;
|
|
|
+ when 3 =>
|
|
|
+ Read_To_Acc <= '1';
|
|
|
+ IORQ <= '1';
|
|
|
+ TStates <= "100"; -- MIKEJ should be 4 for IO cycle
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "11010011" =>
|
|
|
+ if Mode /= 3 then
|
|
|
+ -- OUT (n),A
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ Set_Addr_To <= aIOA;
|
|
|
+ Set_BusB_To <= "0111";
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ IORQ <= '1';
|
|
|
+ TStates <= "100"; -- MIKEJ should be 4 for IO cycle
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+
|
|
|
+------------------------------------------------------------------------------
|
|
|
+------------------------------------------------------------------------------
|
|
|
+-- MULTIBYTE INSTRUCTIONS
|
|
|
+------------------------------------------------------------------------------
|
|
|
+------------------------------------------------------------------------------
|
|
|
+
|
|
|
+ when "11001011" =>
|
|
|
+ if Mode /= 2 then
|
|
|
+ Prefix <= "01";
|
|
|
+ end if;
|
|
|
+
|
|
|
+ when "11101101" =>
|
|
|
+ if Mode < 2 then
|
|
|
+ Prefix <= "10";
|
|
|
+ end if;
|
|
|
+
|
|
|
+ when "11011101"|"11111101" =>
|
|
|
+ if Mode < 2 then
|
|
|
+ Prefix <= "11";
|
|
|
+ end if;
|
|
|
+
|
|
|
+ end case;
|
|
|
+
|
|
|
+ when "01" =>
|
|
|
+
|
|
|
+------------------------------------------------------------------------------
|
|
|
+--
|
|
|
+-- CB prefixed instructions
|
|
|
+--
|
|
|
+------------------------------------------------------------------------------
|
|
|
+
|
|
|
+ Set_BusA_To(2 downto 0) <= IR(2 downto 0);
|
|
|
+ Set_BusB_To(2 downto 0) <= IR(2 downto 0);
|
|
|
+
|
|
|
+ case IRB is
|
|
|
+ when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000111"
|
|
|
+ |"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010111"
|
|
|
+ |"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001111"
|
|
|
+ |"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011111"
|
|
|
+ |"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100111"
|
|
|
+ |"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101111"
|
|
|
+ |"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110111"
|
|
|
+ |"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111111" =>
|
|
|
+ -- RLC r
|
|
|
+ -- RL r
|
|
|
+ -- RRC r
|
|
|
+ -- RR r
|
|
|
+ -- SLA r
|
|
|
+ -- SRA r
|
|
|
+ -- SRL r
|
|
|
+ -- SLL r (Undocumented) / SWAP r
|
|
|
+ if XY_State="00" then
|
|
|
+ if MCycle = "001" then
|
|
|
+ ALU_Op <= "1000";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ end if;
|
|
|
+ else
|
|
|
+ -- R/S (IX+d),Reg, undocumented
|
|
|
+ MCycles <= "011";
|
|
|
+ XYbit_undoc <= '1';
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 | 7=>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ ALU_Op <= "1000";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ TStates <= "100";
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+
|
|
|
+
|
|
|
+ when "00000110"|"00010110"|"00001110"|"00011110"|"00101110"|"00111110"|"00100110"|"00110110" =>
|
|
|
+ -- RLC (HL)
|
|
|
+ -- RL (HL)
|
|
|
+ -- RRC (HL)
|
|
|
+ -- RR (HL)
|
|
|
+ -- SRA (HL)
|
|
|
+ -- SRL (HL)
|
|
|
+ -- SLA (HL)
|
|
|
+ -- SLL (HL) (Undocumented) / SWAP (HL)
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 | 7 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ ALU_Op <= "1000";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ TStates <= "100";
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others =>
|
|
|
+ end case;
|
|
|
+ when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111"
|
|
|
+ |"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111"
|
|
|
+ |"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111"
|
|
|
+ |"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111"
|
|
|
+ |"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111"
|
|
|
+ |"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111"
|
|
|
+ |"01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111"
|
|
|
+ |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" =>
|
|
|
+ -- BIT b,r
|
|
|
+ if XY_State="00" then
|
|
|
+ if MCycle = "001" then
|
|
|
+ Set_BusB_To(2 downto 0) <= IR(2 downto 0);
|
|
|
+ ALU_Op <= "1001";
|
|
|
+ end if;
|
|
|
+ else
|
|
|
+ -- BIT b,(IX+d), undocumented
|
|
|
+ MCycles <= "010";
|
|
|
+ XYbit_undoc <= '1';
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 | 7=>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ ALU_Op <= "1001";
|
|
|
+ TStates <= "100";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01110110"|"01111110" =>
|
|
|
+ -- BIT b,(HL)
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 | 7=>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ ALU_Op <= "1001";
|
|
|
+ TStates <= "100";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000111"
|
|
|
+ |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001111"
|
|
|
+ |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010111"
|
|
|
+ |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011111"
|
|
|
+ |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100111"
|
|
|
+ |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101111"
|
|
|
+ |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110111"
|
|
|
+ |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111111" =>
|
|
|
+ -- SET b,r
|
|
|
+ if XY_State="00" then
|
|
|
+ if MCycle = "001" then
|
|
|
+ ALU_Op <= "1010";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ end if;
|
|
|
+ else
|
|
|
+ -- SET b,(IX+d),Reg, undocumented
|
|
|
+ MCycles <= "011";
|
|
|
+ XYbit_undoc <= '1';
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 | 7=>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ ALU_Op <= "1010";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ TStates <= "100";
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+ when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" =>
|
|
|
+ -- SET b,(HL)
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 | 7=>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ ALU_Op <= "1010";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ TStates <= "100";
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111"
|
|
|
+ |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111"
|
|
|
+ |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111"
|
|
|
+ |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111"
|
|
|
+ |"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111"
|
|
|
+ |"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111"
|
|
|
+ |"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111"
|
|
|
+ |"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" =>
|
|
|
+ -- RES b,r
|
|
|
+ if XY_State="00" then
|
|
|
+ if MCycle = "001" then
|
|
|
+ ALU_Op <= "1011";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ end if;
|
|
|
+ else
|
|
|
+ -- RES b,(IX+d),Reg, undocumented
|
|
|
+ MCycles <= "011";
|
|
|
+ XYbit_undoc <= '1';
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 | 7=>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ ALU_Op <= "1011";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ TStates <= "100";
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end if;
|
|
|
+
|
|
|
+ when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" =>
|
|
|
+ -- RES b,(HL)
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 | 7 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 2 =>
|
|
|
+ ALU_Op <= "1011";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ TStates <= "100";
|
|
|
+ when 3 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end case;
|
|
|
+
|
|
|
+ when others =>
|
|
|
+
|
|
|
+------------------------------------------------------------------------------
|
|
|
+--
|
|
|
+-- ED prefixed instructions
|
|
|
+--
|
|
|
+------------------------------------------------------------------------------
|
|
|
+
|
|
|
+ case IRB is
|
|
|
+ when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000110"|"00000111"
|
|
|
+ |"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001110"|"00001111"
|
|
|
+ |"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010110"|"00010111"
|
|
|
+ |"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011110"|"00011111"
|
|
|
+ |"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100110"|"00100111"
|
|
|
+ |"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101110"|"00101111"
|
|
|
+ |"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110110"|"00110111"
|
|
|
+ |"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111110"|"00111111"
|
|
|
+
|
|
|
+
|
|
|
+ |"10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000110"|"10000111"
|
|
|
+ |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001110"|"10001111"
|
|
|
+ |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010110"|"10010111"
|
|
|
+ |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011110"|"10011111"
|
|
|
+ | "10100100"|"10100101"|"10100110"|"10100111"
|
|
|
+ | "10101100"|"10101101"|"10101110"|"10101111"
|
|
|
+ | "10110100"|"10110101"|"10110110"|"10110111"
|
|
|
+ | "10111100"|"10111101"|"10111110"|"10111111"
|
|
|
+ |"11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000110"|"11000111"
|
|
|
+ |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111"
|
|
|
+ |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111"
|
|
|
+ |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111"
|
|
|
+ |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100110"|"11100111"
|
|
|
+ |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101110"|"11101111"
|
|
|
+ |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110110"|"11110111"
|
|
|
+ |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111110"|"11111111" =>
|
|
|
+ null; -- NOP, undocumented
|
|
|
+ when "01111110"|"01111111" =>
|
|
|
+ -- NOP, undocumented
|
|
|
+ null;
|
|
|
+-- 8 BIT LOAD GROUP
|
|
|
+ when "01010111" =>
|
|
|
+ -- LD A,I
|
|
|
+ Special_LD <= "100";
|
|
|
+ TStates <= "101";
|
|
|
+ when "01011111" =>
|
|
|
+ -- LD A,R
|
|
|
+ Special_LD <= "101";
|
|
|
+ TStates <= "101";
|
|
|
+ when "01000111" =>
|
|
|
+ -- LD I,A
|
|
|
+ Special_LD <= "110";
|
|
|
+ TStates <= "101";
|
|
|
+ when "01001111" =>
|
|
|
+ -- LD R,A
|
|
|
+ Special_LD <= "111";
|
|
|
+ TStates <= "101";
|
|
|
+-- 16 BIT LOAD GROUP
|
|
|
+ when "01001011"|"01011011"|"01101011"|"01111011" =>
|
|
|
+ -- LD dd,(nn)
|
|
|
+ MCycles <= "101";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDW <= '1';
|
|
|
+ when 4 =>
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ if IR(5 downto 4) = "11" then
|
|
|
+ Set_BusA_To <= "1000";
|
|
|
+ else
|
|
|
+ Set_BusA_To(2 downto 1) <= IR(5 downto 4);
|
|
|
+ Set_BusA_To(0) <= '1';
|
|
|
+ end if;
|
|
|
+ Inc_WZ <= '1';
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ when 5 =>
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ if IR(5 downto 4) = "11" then
|
|
|
+ Set_BusA_To <= "1001";
|
|
|
+ else
|
|
|
+ Set_BusA_To(2 downto 1) <= IR(5 downto 4);
|
|
|
+ Set_BusA_To(0) <= '0';
|
|
|
+ end if;
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "01000011"|"01010011"|"01100011"|"01110011" =>
|
|
|
+ -- LD (nn),dd
|
|
|
+ MCycles <= "101";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Inc_PC <= '1';
|
|
|
+ LDW <= '1';
|
|
|
+ if IR(5 downto 4) = "11" then
|
|
|
+ Set_BusB_To <= "1000";
|
|
|
+ else
|
|
|
+ Set_BusB_To(2 downto 1) <= IR(5 downto 4);
|
|
|
+ Set_BusB_To(0) <= '1';
|
|
|
+ Set_BusB_To(3) <= '0';
|
|
|
+ end if;
|
|
|
+ when 4 =>
|
|
|
+ Inc_WZ <= '1';
|
|
|
+ Set_Addr_To <= aZI;
|
|
|
+ Write <= '1';
|
|
|
+ if IR(5 downto 4) = "11" then
|
|
|
+ Set_BusB_To <= "1001";
|
|
|
+ else
|
|
|
+ Set_BusB_To(2 downto 1) <= IR(5 downto 4);
|
|
|
+ Set_BusB_To(0) <= '0';
|
|
|
+ Set_BusB_To(3) <= '0';
|
|
|
+ end if;
|
|
|
+ when 5 =>
|
|
|
+ Write <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "10100000" | "10101000" | "10110000" | "10111000" =>
|
|
|
+ -- LDI, LDD, LDIR, LDDR
|
|
|
+ MCycles <= "100";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ IncDec_16 <= "1100"; -- BC
|
|
|
+ when 2 =>
|
|
|
+ Set_BusB_To <= "0110";
|
|
|
+ Set_BusA_To(2 downto 0) <= "111";
|
|
|
+ ALU_Op <= "0000";
|
|
|
+ Set_Addr_To <= aDE;
|
|
|
+ if IR(3) = '0' then
|
|
|
+ IncDec_16 <= "0110"; -- IX
|
|
|
+ else
|
|
|
+ IncDec_16 <= "1110";
|
|
|
+ end if;
|
|
|
+ when 3 =>
|
|
|
+ I_BT <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ Write <= '1';
|
|
|
+ if IR(3) = '0' then
|
|
|
+ IncDec_16 <= "0101"; -- DE
|
|
|
+ else
|
|
|
+ IncDec_16 <= "1101";
|
|
|
+ end if;
|
|
|
+ when 4 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "10100001" | "10101001" | "10110001" | "10111001" =>
|
|
|
+ -- CPI, CPD, CPIR, CPDR
|
|
|
+ MCycles <= "100";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ IncDec_16 <= "1100"; -- BC
|
|
|
+ when 2 =>
|
|
|
+ Set_BusB_To <= "0110";
|
|
|
+ Set_BusA_To(2 downto 0) <= "111";
|
|
|
+ ALU_Op <= "0111";
|
|
|
+ Save_ALU <= '1';
|
|
|
+ PreserveC <= '1';
|
|
|
+ if IR(3) = '0' then
|
|
|
+ IncDec_16 <= "0110";
|
|
|
+ else
|
|
|
+ IncDec_16 <= "1110";
|
|
|
+ end if;
|
|
|
+ when 3 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ I_BC <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ when 4 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "01000100"|"01001100"|"01010100"|"01011100"|"01100100"|"01101100"|"01110100"|"01111100" =>
|
|
|
+ -- NEG
|
|
|
+ Alu_OP <= "0010";
|
|
|
+ Set_BusB_To <= "0111";
|
|
|
+ Set_BusA_To <= "1010";
|
|
|
+ Read_To_Acc <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ when "01000110"|"01001110"|"01100110"|"01101110" =>
|
|
|
+ -- IM 0
|
|
|
+ IMode <= "00";
|
|
|
+ when "01010110"|"01110110" =>
|
|
|
+ -- IM 1
|
|
|
+ IMode <= "01";
|
|
|
+ when "01011110"|"01110111" =>
|
|
|
+ -- IM 2
|
|
|
+ IMode <= "10";
|
|
|
+-- 16 bit arithmetic
|
|
|
+ when "01001010"|"01011010"|"01101010"|"01111010" =>
|
|
|
+ -- ADC HL,ss
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ ALU_Op <= "0001";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_BusA_To(2 downto 0) <= "101";
|
|
|
+ case to_integer(unsigned(IR(5 downto 4))) is
|
|
|
+ when 0|1|2 =>
|
|
|
+ Set_BusB_To(2 downto 1) <= IR(5 downto 4);
|
|
|
+ Set_BusB_To(0) <= '1';
|
|
|
+ when others =>
|
|
|
+ Set_BusB_To <= "1000";
|
|
|
+ end case;
|
|
|
+ TStates <= "100";
|
|
|
+ when 3 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ ALU_Op <= "0001";
|
|
|
+ Set_BusA_To(2 downto 0) <= "100";
|
|
|
+ case to_integer(unsigned(IR(5 downto 4))) is
|
|
|
+ when 0|1|2 =>
|
|
|
+ Set_BusB_To(2 downto 1) <= IR(5 downto 4);
|
|
|
+ Set_BusB_To(0) <= '0';
|
|
|
+ when others =>
|
|
|
+ Set_BusB_To <= "1001";
|
|
|
+ end case;
|
|
|
+ when others =>
|
|
|
+ end case;
|
|
|
+ when "01000010"|"01010010"|"01100010"|"01110010" =>
|
|
|
+ -- SBC HL,ss
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ ALU_Op <= "0011";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_BusA_To(2 downto 0) <= "101";
|
|
|
+ case to_integer(unsigned(IR(5 downto 4))) is
|
|
|
+ when 0|1|2 =>
|
|
|
+ Set_BusB_To(2 downto 1) <= IR(5 downto 4);
|
|
|
+ Set_BusB_To(0) <= '1';
|
|
|
+ when others =>
|
|
|
+ Set_BusB_To <= "1000";
|
|
|
+ end case;
|
|
|
+ TStates <= "100";
|
|
|
+ when 3 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ ALU_Op <= "0011";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ Set_BusA_To(2 downto 0) <= "100";
|
|
|
+ case to_integer(unsigned(IR(5 downto 4))) is
|
|
|
+ when 0|1|2 =>
|
|
|
+ Set_BusB_To(2 downto 1) <= IR(5 downto 4);
|
|
|
+ when others =>
|
|
|
+ Set_BusB_To <= "1001";
|
|
|
+ end case;
|
|
|
+ when others =>
|
|
|
+ end case;
|
|
|
+ when "01101111" =>
|
|
|
+ -- RLD
|
|
|
+ MCycles <= "100";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 3 =>
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Set_BusB_To(2 downto 0) <= "110";
|
|
|
+ Set_BusA_To(2 downto 0) <= "111";
|
|
|
+ ALU_Op <= "1101";
|
|
|
+ TStates <= "100";
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ Save_ALU <= '1';
|
|
|
+ when 4 =>
|
|
|
+ I_RLD <= '1';
|
|
|
+ Write <= '1';
|
|
|
+ when others =>
|
|
|
+ end case;
|
|
|
+ when "01100111" =>
|
|
|
+ -- RRD
|
|
|
+ MCycles <= "100";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 2 =>
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 3 =>
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Set_BusB_To(2 downto 0) <= "110";
|
|
|
+ Set_BusA_To(2 downto 0) <= "111";
|
|
|
+ ALU_Op <= "1110";
|
|
|
+ TStates <= "100";
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ Save_ALU <= '1';
|
|
|
+ when 4 =>
|
|
|
+ I_RRD <= '1';
|
|
|
+ Write <= '1';
|
|
|
+ when others =>
|
|
|
+ end case;
|
|
|
+ when "01000101"|"01001101"|"01010101"|"01011101"|"01100101"|"01101101"|"01110101"|"01111101" =>
|
|
|
+ -- RETI, RETN
|
|
|
+ MCycles <= "011";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_TO <= aSP;
|
|
|
+ when 2 =>
|
|
|
+ IncDec_16 <= "0111";
|
|
|
+ Set_Addr_To <= aSP;
|
|
|
+ LDZ <= '1';
|
|
|
+ when 3 =>
|
|
|
+ Jump <= '1';
|
|
|
+ IncDec_16 <= "0111";
|
|
|
+ I_RETN <= '1';
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "01000000"|"01001000"|"01010000"|"01011000"|"01100000"|"01101000"|"01110000"|"01111000" =>
|
|
|
+ -- IN r,(C)
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aBC;
|
|
|
+ when 2 =>
|
|
|
+ TStates <= "100"; -- MIKEJ should be 4 for IO cycle
|
|
|
+ IORQ <= '1';
|
|
|
+ if IR(5 downto 3) /= "110" then
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Set_BusA_To(2 downto 0) <= IR(5 downto 3);
|
|
|
+ end if;
|
|
|
+ I_INRC <= '1';
|
|
|
+ when others =>
|
|
|
+ end case;
|
|
|
+ when "01000001"|"01001001"|"01010001"|"01011001"|"01100001"|"01101001"|"01110001"|"01111001" =>
|
|
|
+ -- OUT (C),r
|
|
|
+ -- OUT (C),0
|
|
|
+ MCycles <= "010";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aBC;
|
|
|
+ Set_BusB_To(2 downto 0) <= IR(5 downto 3);
|
|
|
+ if IR(5 downto 3) = "110" then
|
|
|
+ Set_BusB_To(3) <= '1';
|
|
|
+ end if;
|
|
|
+ when 2 =>
|
|
|
+ TStates <= "100"; -- MIKEJ should be 4 for IO cycle
|
|
|
+ Write <= '1';
|
|
|
+ IORQ <= '1';
|
|
|
+ when others =>
|
|
|
+ end case;
|
|
|
+ when "10100010" | "10101010" | "10110010" | "10111010" =>
|
|
|
+ -- INI, IND, INIR, INDR
|
|
|
+ -- note B is decremented AFTER being put on the bus
|
|
|
+ MCycles <= "100";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ Set_Addr_To <= aBC;
|
|
|
+ Set_BusB_To <= "1010";
|
|
|
+ Set_BusA_To <= "0000";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ ALU_Op <= "0010";
|
|
|
+ when 2 =>
|
|
|
+ TStates <= "100"; -- MIKEJ should be 4 for IO cycle
|
|
|
+ IORQ <= '1';
|
|
|
+ Set_BusB_To <= "0110";
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ when 3 =>
|
|
|
+ if IR(3) = '0' then
|
|
|
+ --IncDec_16 <= "0010";
|
|
|
+ IncDec_16 <= "0110";
|
|
|
+ else
|
|
|
+ --IncDec_16 <= "1010";
|
|
|
+ IncDec_16 <= "1110";
|
|
|
+ end if;
|
|
|
+ TStates <= "100";
|
|
|
+ Write <= '1';
|
|
|
+ I_BTR <= '1';
|
|
|
+ when 4 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ when "10100011" | "10101011" | "10110011" | "10111011" =>
|
|
|
+ -- OUTI, OUTD, OTIR, OTDR
|
|
|
+ -- note B is decremented BEFORE being put on the bus.
|
|
|
+ -- mikej fix for hl inc
|
|
|
+ MCycles <= "100";
|
|
|
+ case to_integer(unsigned(MCycle)) is
|
|
|
+ when 1 =>
|
|
|
+ TStates <= "101";
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ Set_BusB_To <= "1010";
|
|
|
+ Set_BusA_To <= "0000";
|
|
|
+ Read_To_Reg <= '1';
|
|
|
+ Save_ALU <= '1';
|
|
|
+ ALU_Op <= "0010";
|
|
|
+ when 2 =>
|
|
|
+ Set_BusB_To <= "0110";
|
|
|
+ Set_Addr_To <= aBC;
|
|
|
+ when 3 =>
|
|
|
+ if IR(3) = '0' then
|
|
|
+ IncDec_16 <= "0110"; -- mikej
|
|
|
+ else
|
|
|
+ IncDec_16 <= "1110"; -- mikej
|
|
|
+ end if;
|
|
|
+ TStates <= "100"; -- MIKEJ should be 4 for IO cycle
|
|
|
+ IORQ <= '1';
|
|
|
+ Write <= '1';
|
|
|
+ I_BTR <= '1';
|
|
|
+ when 4 =>
|
|
|
+ NoRead <= '1';
|
|
|
+ TStates <= "101";
|
|
|
+ when others => null;
|
|
|
+ end case;
|
|
|
+ end case;
|
|
|
+
|
|
|
+ end case;
|
|
|
+
|
|
|
+ if Mode = 1 then
|
|
|
+ if MCycle = "001" then
|
|
|
+-- TStates <= "100";
|
|
|
+ else
|
|
|
+ TStates <= "011";
|
|
|
+ end if;
|
|
|
+ end if;
|
|
|
+
|
|
|
+ if Mode = 3 then
|
|
|
+ if MCycle = "001" then
|
|
|
+-- TStates <= "100";
|
|
|
+ else
|
|
|
+ TStates <= "100";
|
|
|
+ end if;
|
|
|
+ end if;
|
|
|
+
|
|
|
+ if Mode < 2 then
|
|
|
+ if MCycle = "110" then
|
|
|
+ Inc_PC <= '1';
|
|
|
+ if Mode = 1 then
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ TStates <= "100";
|
|
|
+ Set_BusB_To(2 downto 0) <= SSS;
|
|
|
+ Set_BusB_To(3) <= '0';
|
|
|
+ end if;
|
|
|
+ if IRB = "00110110" or IRB = "11001011" then
|
|
|
+ Set_Addr_To <= aNone;
|
|
|
+ end if;
|
|
|
+ end if;
|
|
|
+ if MCycle = "111" then
|
|
|
+ if Mode = 0 then
|
|
|
+ TStates <= "101";
|
|
|
+ end if;
|
|
|
+ if ISet /= "01" then
|
|
|
+ Set_Addr_To <= aXY;
|
|
|
+ end if;
|
|
|
+ Set_BusB_To(2 downto 0) <= SSS;
|
|
|
+ Set_BusB_To(3) <= '0';
|
|
|
+ if IRB = "00110110" or ISet = "01" then
|
|
|
+ -- LD (HL),n
|
|
|
+ Inc_PC <= '1';
|
|
|
+ else
|
|
|
+ NoRead <= '1';
|
|
|
+ end if;
|
|
|
+ end if;
|
|
|
+ end if;
|
|
|
+
|
|
|
+ end process;
|
|
|
+
|
|
|
+end;
|