From 926af02ee0780a794b49e1df8d92c59adfb224d5 Mon Sep 17 00:00:00 2001 From: Till Harbaum Date: Wed, 27 Jan 2016 11:22:35 +0100 Subject: [PATCH] [TG68K] Tests with lsr/lsl barrel shifter --- cores/mist/TG68K_ALU.vhd | 1925 ++++----- cores/mist/TG68K_Pack.vhd | 237 +- cores/mist/TG68KdotC_Kernel.vhd | 6588 +++++++++++++++--------------- cores/mist/mist_top.v | 4 +- tests/tg68k/TG68K_ALU.vhd | 52 +- tests/tg68k/TG68K_Pack.vhd | 1 + tests/tg68k/TG68KdotC_Kernel.vhd | 42 +- 7 files changed, 4578 insertions(+), 4271 deletions(-) diff --git a/cores/mist/TG68K_ALU.vhd b/cores/mist/TG68K_ALU.vhd index d0e859d..26a18d7 100644 --- a/cores/mist/TG68K_ALU.vhd +++ b/cores/mist/TG68K_ALU.vhd @@ -1,932 +1,1031 @@ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ --- -- --- Copyright (c) 2009-2011 Tobias Gubener -- --- Subdesign fAMpIGA by TobiFlex -- --- -- +-- -- +-- Copyright (c) 2009-2011 Tobias Gubener -- +-- Subdesign fAMpIGA by TobiFlex -- +-- -- -- This source file is free software: you can redistribute it and/or modify -- --- it under the terms of the GNU General Public License as published -- --- by the Free Software Foundation, either version 3 of the License, or -- --- (at your option) any later version. -- --- -- --- This source file is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of -- --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- --- GNU General Public License for more details. -- --- -- --- You should have received a copy of the GNU General Public License -- +-- it under the terms of the GNU General Public License as published -- +-- by the Free Software Foundation, either version 3 of the License, or -- +-- (at your option) any later version. -- +-- -- +-- This source file is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of -- +-- MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE. See the -- +-- GNU General Public License for more details. -- +-- -- +-- You should have received a copy of the GNU General Public License -- -- along with this program. If not, see . -- --- -- +-- -- ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ library ieee; -use ieee.std_logic_1164.all; -use ieee.std_logic_unsigned.all; -use IEEE.numeric_std.all; -use work.TG68K_Pack.all; +use ieee.std_logic_1164.ALL; +use ieee.std_logic_unsigned.ALL; +use IEEE.numeric_std.ALL; +use work.TG68K_Pack.ALL; entity TG68K_ALU is -generic( - MUL_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL, - DIV_Mode : integer := 0 --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV, - ); - port(clk : in std_logic; - Reset : in std_logic; - clkena_lw : in std_logic:='1'; - execOPC : in bit; - exe_condition : in std_logic; - exec_tas : in std_logic; - long_start : in bit; - movem_presub : in bit; - set_stop : in bit; - Z_error : in bit; - rot_bits : in std_logic_vector(1 downto 0); - exec : in bit_vector(lastOpcBit downto 0); - OP1out : in std_logic_vector(31 downto 0); - OP2out : in std_logic_vector(31 downto 0); - reg_QA : in std_logic_vector(31 downto 0); - reg_QB : in std_logic_vector(31 downto 0); - opcode : in std_logic_vector(15 downto 0); - datatype : in std_logic_vector(1 downto 0); - exe_opcode : in std_logic_vector(15 downto 0); - exe_datatype : in std_logic_vector(1 downto 0); - sndOPC : in std_logic_vector(15 downto 0); - last_data_read : in std_logic_vector(15 downto 0); - data_read : in std_logic_vector(15 downto 0); - FlagsSR : in std_logic_vector(7 downto 0); - micro_state : in micro_states; - bf_ext_in : in std_logic_vector(7 downto 0); - bf_ext_out : out std_logic_vector(7 downto 0); - bf_shift : in std_logic_vector(5 downto 0); - bf_width : in std_logic_vector(5 downto 0); - bf_loffset : in std_logic_vector(4 downto 0); - - set_V_Flag : buffer bit; - Flags : buffer std_logic_vector(7 downto 0); - c_out : buffer std_logic_vector(2 downto 0); - addsub_q : buffer std_logic_vector(31 downto 0); - ALUout : out std_logic_vector(31 downto 0) - ); + generic ( + MUL_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL, + DIV_Mode : integer := 0 --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV, + ); + port ( + clk : in std_logic; + Reset : in std_logic; + clkena_lw : in std_logic := '1'; + execOPC : in bit; + exe_condition : in std_logic; + exec_tas : in std_logic; + long_start : in bit; + non_aligned : in std_logic; + movem_presub : in bit; + set_stop : in bit; + Z_error : in bit; + rot_bits : in std_logic_vector(1 downto 0); + rot_cnt : in std_logic_vector(5 downto 0); + exec : in bit_vector(lastOpcBit downto 0); + OP1out : in std_logic_vector(31 downto 0); + OP2out : in std_logic_vector(31 downto 0); + reg_QA : in std_logic_vector(31 downto 0); + reg_QB : in std_logic_vector(31 downto 0); + opcode : in std_logic_vector(15 downto 0); + datatype : in std_logic_vector(1 downto 0); + exe_opcode : in std_logic_vector(15 downto 0); + exe_datatype : in std_logic_vector(1 downto 0); + sndOPC : in std_logic_vector(15 downto 0); + last_data_read : in std_logic_vector(15 downto 0); + data_read : in std_logic_vector(15 downto 0); + FlagsSR : in std_logic_vector(7 downto 0); + micro_state : in micro_states; + bf_ext_in : in std_logic_vector(7 downto 0); + bf_ext_out : out std_logic_vector(7 downto 0); + bf_width : in std_logic_vector(4 downto 0); + bf_loffset : in std_logic_vector(4 downto 0); + bf_offset : in std_logic_vector(31 downto 0); + set_V_Flag_out : out bit; + Flags_out : out std_logic_vector(7 downto 0); + c_out_out : out std_logic_vector(2 downto 0); + addsub_q_out : out std_logic_vector(31 downto 0); + ALUout : out std_logic_vector(31 downto 0) + ); end TG68K_ALU; -architecture logic of TG68K_ALU is ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ --- ALU and more ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ - signal OP1in : std_logic_vector(31 downto 0); - signal addsub_a : std_logic_vector(31 downto 0); - signal addsub_b : std_logic_vector(31 downto 0); - signal notaddsub_b : std_logic_vector(33 downto 0); - signal add_result : std_logic_vector(33 downto 0); - signal addsub_ofl : std_logic_vector(2 downto 0); - signal opaddsub : bit; - signal c_in : std_logic_vector(3 downto 0); - signal flag_z : std_logic_vector(2 downto 0); - signal set_Flags : std_logic_vector(3 downto 0); --NZVC - signal CCRin : std_logic_vector(7 downto 0); - - signal niba_l : std_logic_vector(5 downto 0); - signal niba_h : std_logic_vector(5 downto 0); - signal niba_lc : std_logic; - signal niba_hc : std_logic; - signal bcda_lc : std_logic; - signal bcda_hc : std_logic; - signal nibs_l : std_logic_vector(5 downto 0); - signal nibs_h : std_logic_vector(5 downto 0); - signal nibs_lc : std_logic; - signal nibs_hc : std_logic; - - signal bcd_a : std_logic_vector(8 downto 0); - signal bcd_s : std_logic_vector(8 downto 0); - signal pack_out : std_logic_vector(15 downto 0); - signal pack_a : std_logic_vector(15 downto 0); - signal result_mulu : std_logic_vector(63 downto 0); - signal result_div : std_logic_vector(63 downto 0); - signal set_mV_Flag : std_logic; - signal V_Flag : bit; - - signal rot_rot : std_logic; - signal rot_lsb : std_logic; - signal rot_msb : std_logic; - signal rot_X : std_logic; - signal rot_C : std_logic; - signal rot_out : std_logic_vector(31 downto 0); - signal asl_VFlag : std_logic; - signal bit_bits : std_logic_vector(1 downto 0); - signal bit_number : std_logic_vector(4 downto 0); - signal bits_out : std_logic_vector(31 downto 0); - signal one_bit_in : std_logic; - signal bchg : std_logic; - signal bset : std_logic; - - signal mulu_sign : std_logic; - signal mulu_signext : std_logic_vector(16 downto 0); - signal muls_msb : std_logic; - signal mulu_reg : std_logic_vector(63 downto 0); - signal FAsign : std_logic; - signal faktorA : std_logic_vector(31 downto 0); - signal faktorB : std_logic_vector(31 downto 0); - - signal div_reg : std_logic_vector(63 downto 0); - signal div_quot : std_logic_vector(63 downto 0); - signal div_ovl : std_logic; - signal div_neg : std_logic; - signal div_bit : std_logic; - signal div_sub : std_logic_vector(32 downto 0); - signal div_over : std_logic_vector(32 downto 0); - signal nozero : std_logic; - signal div_qsign : std_logic; - signal divisor : std_logic_vector(63 downto 0); - signal divs : std_logic; - signal signedOP : std_logic; - signal OP1_sign : std_logic; - signal OP2_sign : std_logic; - signal OP2outext : std_logic_vector(15 downto 0); - - signal in_offset : std_logic_vector(5 downto 0); --- signal in_width : std_logic_vector(5 downto 0); - signal datareg : std_logic_vector(31 downto 0); - signal insert : std_logic_vector(31 downto 0); --- signal bf_result : std_logic_vector(31 downto 0); --- signal bf_offset : std_logic_vector(5 downto 0); --- signal bf_width : std_logic_vector(5 downto 0); --- signal bf_firstbit : std_logic_vector(5 downto 0); - signal bf_datareg : std_logic_vector(31 downto 0); --- signal bf_out : std_logic_vector(31 downto 0); - signal result : std_logic_vector(39 downto 0); - signal result_tmp : std_logic_vector(39 downto 0); - signal sign : std_logic_vector(31 downto 0); - signal bf_set1 : std_logic_vector(39 downto 0); - signal inmux0 : std_logic_vector(39 downto 0); - signal inmux1 : std_logic_vector(39 downto 0); - signal inmux2 : std_logic_vector(39 downto 0); - signal inmux3 : std_logic_vector(31 downto 0); - signal copymux0 : std_logic_vector(39 downto 0); - signal copymux1 : std_logic_vector(39 downto 0); - signal copymux2 : std_logic_vector(39 downto 0); - signal copymux3 : std_logic_vector(31 downto 0); - signal bf_set2 : std_logic_vector(31 downto 0); --- signal bf_set3 : std_logic_vector(31 downto 0); - signal shift : std_logic_vector(39 downto 0); - signal copy : std_logic_vector(39 downto 0); --- signal offset : std_logic_vector(5 downto 0); --- signal width : std_logic_vector(5 downto 0); - signal bf_firstbit : std_logic_vector(5 downto 0); - signal mux : std_logic_vector(3 downto 0); - signal bitnr : std_logic_vector(4 downto 0); - signal mask : std_logic_vector(31 downto 0); - signal bf_bset : std_logic; - signal bf_NFlag : std_logic; - signal bf_bchg : std_logic; - signal bf_ins : std_logic; - signal bf_exts : std_logic; - signal bf_fffo : std_logic; - signal bf_d32 : std_logic; - signal bf_s32 : std_logic; - signal index : std_logic_vector(4 downto 0); --- signal i : integer range 0 to 31; --- signal i : integer range 0 to 31; --- signal i : std_logic_vector(5 downto 0); -BEGIN ------------------------------------------------------------------------------ --- set OP1in ------------------------------------------------------------------------------ -PROCESS (OP2out, reg_QB, opcode, OP1out, OP1in, exe_datatype, addsub_q, execOPC, exec, - pack_out, bcd_a, bcd_s, result_mulu, result_div, exe_condition, bf_shift, - Flags, FlagsSR, bits_out, exec_tas, rot_out, exe_opcode, result, bf_fffo, bf_firstbit, bf_datareg) - BEGIN - ALUout <= OP1in; - ALUout(7) <= OP1in(7) OR exec_tas; - IF exec(opcBFwb)='1' THEN - ALUout <= result(31 downto 0); - IF bf_fffo='1' THEN - ALUout <= (OTHERS =>'0'); - ALUout(5 downto 0) <= bf_firstbit + bf_shift; - END IF; - END IF; - - OP1in <= addsub_q; - IF exec(opcABCD)='1' THEN - OP1in(7 downto 0) <= bcd_a(7 downto 0); - ELSIF exec(opcSBCD)='1' THEN - OP1in(7 downto 0) <= bcd_s(7 downto 0); - ELSIF exec(opcMULU)='1' AND MUL_Mode/=3 THEN - IF exec(write_lowlong)='1' AND (MUL_Mode=1 OR MUL_Mode=2) THEN - OP1in <= result_mulu(31 downto 0); - ELSE - OP1in <= result_mulu(63 downto 32); - END IF; - ELSIF exec(opcDIVU)='1' AND DIV_Mode/=3 THEN - IF exe_opcode(15)='1' OR DIV_Mode=0 THEN --- IF exe_opcode(15)='1' THEN - OP1in <= result_div(47 downto 32)&result_div(15 downto 0); - ELSE --64bit - IF exec(write_reminder)='1' THEN - OP1in <= result_div(63 downto 32); - ELSE - OP1in <= result_div(31 downto 0); - END IF; - END IF; - ELSIF exec(opcOR)='1' THEN - OP1in <= OP2out OR OP1out; - ELSIF exec(opcAND)='1' THEN - OP1in <= OP2out AND OP1out; - ELSIF exec(opcScc)='1' THEN - OP1in(7 downto 0) <= (others=>exe_condition); - ELSIF exec(opcEOR)='1' THEN - OP1in <= OP2out XOR OP1out; - ELSIF exec(opcMOVE)='1' OR exec(exg)='1' THEN --- OP1in <= OP2out(31 downto 8)&(OP2out(7)OR exec_tas)&OP2out(6 downto 0); - OP1in <= OP2out; - ELSIF exec(opcROT)='1' THEN - OP1in <= rot_out; - ELSIF exec(opcSWAP)='1' THEN - OP1in <= OP1out(15 downto 0)& OP1out(31 downto 16); - ELSIF exec(opcBITS)='1' THEN - OP1in <= bits_out; - ELSIF exec(opcBF)='1' THEN - OP1in <= bf_datareg; - ELSIF exec(opcMOVESR)='1' THEN - OP1in(7 downto 0) <= Flags; - IF exe_datatype="00" THEN - OP1in(15 downto 8) <= "00000000"; - ELSE - OP1in(15 downto 8) <= FlagsSR; - END IF; - ELSIF exec(opcPACK)='1' THEN - OP1in(15 downto 0) <= pack_out; - END IF; - END PROCESS; - ------------------------------------------------------------------------------ --- addsub ------------------------------------------------------------------------------ -PROCESS (OP1out, OP2out, execOPC, datatype, Flags, long_start, movem_presub, exe_datatype, exec, addsub_a, addsub_b, opaddsub, - notaddsub_b, add_result, c_in, sndOPC) - BEGIN - addsub_a <= OP1out; - IF exec(get_bfoffset)='1' THEN - IF sndOPC(11)='1' THEN - addsub_a <= OP1out(31)&OP1out(31)&OP1out(31)&OP1out(31 downto 3); - ELSE - addsub_a <= "000000000000000000000000000000"&sndOPC(10 downto 9); - END IF; - END IF; - - IF exec(subidx)='1' THEN - opaddsub <= '1'; - ELSE - opaddsub <= '0'; - END IF; - - c_in(0) <='0'; - addsub_b <= OP2out; - IF execOPC='0' AND exec(OP2out_one)='0' AND exec(get_bfoffset)='0'THEN - IF long_start='0' AND datatype="00" AND exec(use_SP)='0' THEN - addsub_b <= "00000000000000000000000000000001"; - ELSIF long_start='0' AND exe_datatype="10" AND (exec(presub) OR exec(postadd) OR movem_presub)='1' THEN - IF exec(movem_action)='1' THEN - addsub_b <= "00000000000000000000000000000110"; - ELSE - addsub_b <= "00000000000000000000000000000100"; - END IF; - ELSE - addsub_b <= "00000000000000000000000000000010"; - END IF; - ELSE - IF (exec(use_XZFlag)='1' AND Flags(4)='1') OR exec(opcCHK)='1' THEN - c_in(0) <= '1'; - END IF; - opaddsub <= exec(addsub); - END IF; +architecture logic of TG68K_ALU IS + ----------------------------------------------------------------------------- + ----------------------------------------------------------------------------- + -- ALU and more + ----------------------------------------------------------------------------- + ----------------------------------------------------------------------------- + signal OP1in : std_logic_vector(31 downto 0); + signal addsub_a : std_logic_vector(31 downto 0); + signal addsub_b : std_logic_vector(31 downto 0); + signal notaddsub_b : std_logic_vector(33 downto 0); + signal add_result : std_logic_vector(33 downto 0); + signal addsub_ofl : std_logic_vector(2 downto 0); + signal opaddsub : BIT; + signal c_in : std_logic_vector(3 downto 0); + signal flag_z : std_logic_vector(2 downto 0); + signal set_Flags : std_logic_vector(3 downto 0); --NZVC + signal CCRin : std_logic_vector(7 downto 0); - IF opaddsub='0' OR long_start='1' THEN --ADD - notaddsub_b <= '0'&addsub_b&c_in(0); - ELSE --SUB - notaddsub_b <= NOT ('0'&addsub_b&c_in(0)); - END IF; - add_result <= (('0'&addsub_a¬addsub_b(0))+notaddsub_b); - c_in(1) <= add_result(9) XOR addsub_a(8) XOR addsub_b(8); - c_in(2) <= add_result(17) XOR addsub_a(16) XOR addsub_b(16); - c_in(3) <= add_result(33); - addsub_q <= add_result(32 downto 1); - addsub_ofl(0) <= (c_in(1) XOR add_result(8) XOR addsub_a(7) XOR addsub_b(7)); --V Byte - addsub_ofl(1) <= (c_in(2) XOR add_result(16) XOR addsub_a(15) XOR addsub_b(15)); --V Word - addsub_ofl(2) <= (c_in(3) XOR add_result(32) XOR addsub_a(31) XOR addsub_b(31)); --V Long - c_out <= c_in(3 downto 1); - END PROCESS; - ------------------------------------------------------------------------------- ---ALU ------------------------------------------------------------------------------- -PROCESS (OP1out, OP2out, pack_a, niba_hc, niba_h, niba_l, niba_lc, nibs_hc, nibs_h, nibs_l, nibs_lc, Flags) - BEGIN - IF exe_opcode(7 downto 6) = "01" THEN - -- PACK - pack_a <= std_logic_vector(unsigned(OP1out(15 downto 0))+unsigned(OP2out(15 downto 0))); - pack_out <= "00000000" & pack_a(11 downto 8) & pack_a(3 downto 0); - ELSE - -- UNPK - pack_a <= "0000" & OP2out(7 downto 4) & "0000" & OP2out(3 downto 0); - pack_out <= std_logic_vector(unsigned(OP1out(15 downto 0))+unsigned(pack_a)); - END IF; - ---BCD_ARITH------------------------------------------------------------------- + signal niba_l : std_logic_vector(5 downto 0); + signal niba_h : std_logic_vector(5 downto 0); + signal niba_lc : std_logic; + signal niba_hc : std_logic; + signal bcda_lc : std_logic; + signal bcda_hc : std_logic; + signal nibs_l : std_logic_vector(5 downto 0); + signal nibs_h : std_logic_vector(5 downto 0); + signal nibs_lc : std_logic; + signal nibs_hc : std_logic; + + signal bcd_a : std_logic_vector(8 downto 0); + signal bcd_s : std_logic_vector(8 downto 0); + signal pack_out : std_logic_vector(15 downto 0); + signal pack_a : std_logic_vector(15 downto 0); + signal result_mulu : std_logic_vector(63 downto 0); + signal result_div : std_logic_vector(63 downto 0); + signal set_mV_Flag : std_logic; + signal V_Flag : BIT; + + signal rot_rot : std_logic; + signal rot_lsb : std_logic; + signal rot_msb : std_logic; + signal rot_X : std_logic; + signal rot_C : std_logic; + signal rot_out : std_logic_vector(31 downto 0); + signal asl_VFlag : std_logic; + signal bit_bits : std_logic_vector(1 downto 0); + signal bit_number : std_logic_vector(4 downto 0); + signal bits_out : std_logic_vector(31 downto 0); + signal one_bit_in : std_logic; + signal bchg : std_logic; + signal bset : std_logic; + + signal mulu_sign : std_logic; + signal mulu_signext : std_logic_vector(16 downto 0); + signal muls_msb : std_logic; + signal mulu_reg : std_logic_vector(63 downto 0); + signal FAsign : std_logic; + signal faktorA : std_logic_vector(31 downto 0); + signal faktorB : std_logic_vector(31 downto 0); + + signal div_reg : std_logic_vector(63 downto 0); + signal div_quot : std_logic_vector(63 downto 0); + signal div_ovl : std_logic; + signal div_neg : std_logic; + signal div_bit : std_logic; + signal div_sub : std_logic_vector(32 downto 0); + signal div_over : std_logic_vector(32 downto 0); + signal nozero : std_logic; + signal div_qsign : std_logic; + signal divisor : std_logic_vector(63 downto 0); + signal divs : std_logic; + signal signedOP : std_logic; + signal OP1_sign : std_logic; + signal OP2_sign : std_logic; + signal OP2outext : std_logic_vector(15 downto 0); + + signal in_offset : std_logic_vector(5 downto 0); + signal datareg : std_logic_vector(31 downto 0); + signal insert : std_logic_vector(31 downto 0); + signal bf_datareg : std_logic_vector(31 downto 0); + signal result : std_logic_vector(39 downto 0); + signal result_tmp : std_logic_vector(39 downto 0); + signal sign : std_logic_vector(31 downto 0); + signal bf_loff_dir : std_logic_vector(4 downto 0); + signal bf_set2 : std_logic_vector(39 downto 0); + signal copy : std_logic_vector(39 downto 0); + + signal bf_firstbit : std_logic_vector(5 downto 0); + signal bf_bset : std_logic; + signal bf_NFlag : std_logic; + signal bf_bchg : std_logic; + signal bf_ins : std_logic; + signal bf_exts : std_logic; + signal bf_extu : std_logic; + signal bf_fffo : std_logic; + signal bf_d32 : std_logic; + signal index : std_logic_vector(4 downto 0); + signal bf_flag_z : std_logic; + signal bf_flag_n : std_logic; + + -- barrel shifter + signal bs_data : std_logic_vector(31 downto 0); + signal bs_msb : std_logic_vector(4 downto 0); + + signal set_V_Flag : BIT; + signal Flags : std_logic_vector(7 downto 0); + signal c_out : std_logic_vector(2 downto 0); + signal addsub_q : std_logic_vector(31 downto 0); + +begin + ----------------------------------------------------------------------------- + -- set OP1in + ----------------------------------------------------------------------------- + process (OP2out, reg_QB, opcode, OP1out, OP1in, exe_datatype, addsub_q, execOPC, exec, + pack_out, bcd_a, bcd_s, result_mulu, result_div, exe_condition, bf_offset, bf_width, + Flags, FlagsSR, bits_out, exec_tas, rot_out, exe_opcode, result, bf_fffo, bf_firstbit, bf_datareg) + begin + ALUout <= OP1in; + ALUout(7) <= OP1in(7) OR exec_tas; + if exec(opcBFwb) = '1' then + ALUout <= result(31 downto 0); + if bf_fffo = '1' then + ALUout <= bf_offset + bf_width + 1 - bf_firstbit; + end if; + end if; + + OP1in <= addsub_q; + if exec(opcABCD) = '1' then + OP1in(7 downto 0) <= bcd_a(7 downto 0); + elsif exec(opcSBCD) = '1' then + OP1in(7 downto 0) <= bcd_s(7 downto 0); + elsif exec(opcMULU) = '1' and MUL_Mode /= 3 then + if exec(write_lowlong) = '1' and (MUL_Mode = 1 OR MUL_Mode = 2) then + OP1in <= result_mulu(31 downto 0); + else + OP1in <= result_mulu(63 downto 32); + end if; + elsif exec(opcDIVU) = '1' and DIV_Mode /= 3 then + if exe_opcode(15) = '1' OR DIV_Mode = 0 then + -- if exe_opcode(15)='1' then + OP1in <= result_div(47 downto 32) & result_div(15 downto 0); + else --64bit + if exec(write_reminder) = '1' then + OP1in <= result_div(63 downto 32); + else + OP1in <= result_div(31 downto 0); + end if; + end if; + elsif exec(opcOR) = '1' then + OP1in <= OP2out OR OP1out; + elsif exec(opcand) = '1' then + OP1in <= OP2out and OP1out; + elsif exec(opcScc) = '1' then + OP1in(7 downto 0) <= (others => exe_condition); + elsif exec(opcEOR) = '1' then + OP1in <= OP2out xor OP1out; + elsif exec(opcMOVE) = '1' OR exec(exg) = '1' then + -- OP1in <= OP2out(31 downto 8)&(OP2out(7)OR exec_tas)&OP2out(6 downto 0); + OP1in <= OP2out; + elsif exec(opcROT) = '1' then + OP1in <= rot_out; + elsif exec(opcSWAP) = '1' then + OP1in <= OP1out(15 downto 0) & OP1out(31 downto 16); + elsif exec(opcBITS) = '1' then + OP1in <= bits_out; + elsif exec(opcBF) = '1' then + OP1in <= bf_datareg; + elsif exec(opcMOVECCR) = '1' then + OP1in(15 downto 8) <= "00000000"; + OP1in( 7 downto 0) <= Flags; + elsif exec(opcMOVESR) = '1' then + OP1in(15 downto 8) <= FlagsSR; + OP1in( 7 downto 0) <= Flags; + elsif exec(opcPACK) = '1' then + OP1in(15 downto 0) <= pack_out; + end if; + end process; + + ----------------------------------------------------------------------------- + -- addsub + ----------------------------------------------------------------------------- + process (OP1out, OP2out, execOPC, datatype, Flags, long_start, non_aligned, movem_presub, exe_datatype, exec, addsub_a, addsub_b, opaddsub, + notaddsub_b, add_result, c_in, sndOPC) + begin + addsub_a <= OP1out; + if exec(get_bfoffset) = '1' then + if sndOPC(11) = '1' then + addsub_a <= OP1out(31) & OP1out(31) & OP1out(31) & OP1out(31 downto 3); + else + addsub_a <= "000000000000000000000000000000" & sndOPC(10 downto 9); + end if; + end if; + + if exec(subidx) = '1' then + opaddsub <= '1'; + else + opaddsub <= '0'; + end if; + + c_in(0) <= '0'; + addsub_b <= OP2out; + if execOPC = '0' and exec(OP2out_one) = '0' and exec(get_bfoffset) = '0' then + if long_start = '0' and datatype = "00" and exec(use_SP) = '0' then + addsub_b <= "00000000000000000000000000000001"; + elsif long_start = '0' and exe_datatype = "10" and (exec(presub) OR exec(postadd) OR movem_presub) = '1' then + if exec(movem_action) = '1' then -- used for initial offset / aligned case + addsub_b <= "00000000000000000000000000000110"; + else + addsub_b <= "00000000000000000000000000000100"; + end if; + else + addsub_b <= "00000000000000000000000000000010"; + end if; + else + if (exec(use_XZFlag) = '1' and Flags(4) = '1') OR exec(opcCHK) = '1' then + c_in(0) <= '1'; + end if; + opaddsub <= exec(addsub); + end if; + + -- patch for un-aligned movem + if (exec(movem_action) = '1') then + if (movem_presub = '0') then -- up + if (non_aligned = '1') and (long_start = '0') then -- hold + addsub_b <= (others => '0'); + end if; + else + if (non_aligned = '1') and (long_start = '0') then + if (exe_datatype = "10") then + addsub_b <= "00000000000000000000000000001000"; + else + addsub_b <= "00000000000000000000000000000100"; + end if; + end if; + end if; + end if; + + if opaddsub = '0' OR long_start = '1' then --ADD + notaddsub_b <= '0' & addsub_b & c_in(0); + else --SUB + notaddsub_b <= not ('0' & addsub_b & c_in(0)); + end if; + add_result <= (('0' & addsub_a & notaddsub_b(0)) + notaddsub_b); + + c_in(1) <= add_result(9) xor addsub_a(8) xor addsub_b(8); + c_in(2) <= add_result(17) xor addsub_a(16) xor addsub_b(16); + c_in(3) <= add_result(33); + + addsub_q <= add_result(32 downto 1); + addsub_ofl(0) <= (c_in(1) xor add_result(8) xor addsub_a(7) xor addsub_b(7)); --V Byte + addsub_ofl(1) <= (c_in(2) xor add_result(16) xor addsub_a(15) xor addsub_b(15)); --V Word + addsub_ofl(2) <= (c_in(3) xor add_result(32) xor addsub_a(31) xor addsub_b(31)); --V Long + c_out <= c_in(3 downto 1); + end process; + + ------------------------------------------------------------------------------ + --ALU + ------------------------------------------------------------------------------ + process (OP1out, OP2out, pack_a, niba_hc, niba_h, niba_l, niba_lc, nibs_hc, nibs_h, nibs_l, nibs_lc, Flags) + begin + if exe_opcode(7 downto 6) = "01" then + -- PACK + pack_a <= std_logic_vector(unsigned(OP1out(15 downto 0)) + unsigned(OP2out(15 downto 0))); + pack_out <= "00000000" & pack_a(11 downto 8) & pack_a(3 downto 0); + else + -- UNPK + pack_a <= "0000" & OP2out(7 downto 4) & "0000" & OP2out(3 downto 0); + pack_out <= std_logic_vector(unsigned(OP1out(15 downto 0)) + unsigned(pack_a)); + end if; + --BCD_ARITH------------------------------------------------------------------- --ADC - bcd_a <= niba_hc&(niba_h(4 downto 1)+('0',niba_hc,niba_hc,'0'))&(niba_l(4 downto 1)+('0',niba_lc,niba_lc,'0')); - niba_l <= ('0'&OP1out(3 downto 0)&'1') + ('0'&OP2out(3 downto 0)&Flags(4)); - niba_lc <= niba_l(5) OR (niba_l(4) AND niba_l(3)) OR (niba_l(4) AND niba_l(2)); + bcd_a <= niba_hc & (niba_h(4 downto 1) + ('0', niba_hc, niba_hc, '0')) & (niba_l(4 downto 1) + ('0', niba_lc, niba_lc, '0')); + niba_l <= ('0' & OP1out(3 downto 0) & '1') + ('0' & OP2out(3 downto 0) & Flags(4)); + niba_lc <= niba_l(5) OR (niba_l(4) and niba_l(3)) OR (niba_l(4) and niba_l(2)); - niba_h <= ('0'&OP1out(7 downto 4)&'1') + ('0'&OP2out(7 downto 4)&niba_lc); - niba_hc <= niba_h(5) OR (niba_h(4) AND niba_h(3)) OR (niba_h(4) AND niba_h(2)); - --SBC - bcd_s <= nibs_hc&(nibs_h(4 downto 1)-('0',nibs_hc,nibs_hc,'0'))&(nibs_l(4 downto 1)-('0',nibs_lc,nibs_lc,'0')); - nibs_l <= ('0'&OP1out(3 downto 0)&'0') - ('0'&OP2out(3 downto 0)&Flags(4)); - nibs_lc <= nibs_l(5); + niba_h <= ('0' & OP1out(7 downto 4) & '1') + ('0' & OP2out(7 downto 4) & niba_lc); + niba_hc <= niba_h(5) OR (niba_h(4) and niba_h(3)) OR (niba_h(4) and niba_h(2)); + --SBC + bcd_s <= nibs_hc & (nibs_h(4 downto 1) - ('0', nibs_hc, nibs_hc, '0')) & (nibs_l(4 downto 1) - ('0', nibs_lc, nibs_lc, '0')); + nibs_l <= ('0' & OP1out(3 downto 0) & '0') - ('0' & OP2out(3 downto 0) & Flags(4)); + nibs_lc <= nibs_l(5); - nibs_h <= ('0'&OP1out(7 downto 4)&'0') - ('0'&OP2out(7 downto 4)&nibs_lc); - nibs_hc <= nibs_h(5); - END PROCESS; - ------------------------------------------------------------------------------ --- Bits ------------------------------------------------------------------------------ -PROCESS (clk, exe_opcode, OP1out, OP2out, one_bit_in, bchg, bset, bit_Number, sndOPC, reg_QB) - BEGIN - IF rising_edge(clk) THEN - IF clkena_lw = '1' THEN - bchg <= '0'; - bset <= '0'; - CASE opcode(7 downto 6) IS - WHEN "01" => --bchg - bchg <= '1'; - WHEN "11" => --bset - bset <= '1'; - WHEN OTHERS => NULL; - END CASE; - END IF; - END IF; - - IF exe_opcode(8)='0' THEN - IF exe_opcode(5 downto 4)="00" THEN - bit_number <= sndOPC(4 downto 0); - ELSE - bit_number <= "00"&sndOPC(2 downto 0); - END IF; - ELSE - IF exe_opcode(5 downto 4)="00" THEN - bit_number <= reg_QB(4 downto 0); - ELSE - bit_number <= "00"®_QB(2 downto 0); - END IF; - END IF; - - one_bit_in <= OP1out(to_integer(unsigned(bit_Number))); - bits_out <= OP1out; - bits_out(to_integer(unsigned(bit_Number))) <= (bchg AND NOT one_bit_in) OR bset ; - END PROCESS; + nibs_h <= ('0' & OP1out(7 downto 4) & '0') - ('0' & OP2out(7 downto 4) & nibs_lc); + nibs_hc <= nibs_h(5); + end process; ------------------------------------------------------------------------------ --- Bit Field ------------------------------------------------------------------------------ -PROCESS (clk, mux, mask, bitnr, bf_ins, bf_bchg, bf_bset, bf_exts, bf_shift, inmux0, inmux1, inmux2, inmux3, bf_set2, OP1out, OP2out, result_tmp, bf_ext_in, - shift, datareg, bf_NFlag, result, reg_QB, sign, bf_d32, bf_s32, copy, bf_loffset, copymux0, copymux1, copymux2, copymux3, bf_width) - BEGIN - IF rising_edge(clk) THEN - IF clkena_lw = '1' THEN - bf_bset <= '0'; - bf_bchg <= '0'; - bf_ins <= '0'; - bf_exts <= '0'; - bf_fffo <= '0'; - bf_d32 <= '0'; - bf_s32 <= '0'; - CASE opcode(10 downto 8) IS - WHEN "010" => bf_bchg <= '1'; --BFCHG - WHEN "011" => bf_exts <= '1'; --BFEXTS --- WHEN "100" => insert <= (OTHERS =>'0'); --BFCLR - WHEN "101" => bf_fffo <= '1'; --BFFFO - WHEN "110" => bf_bset <= '1'; --BFSET - WHEN "111" => bf_ins <= '1'; --BFINS - bf_s32 <= '1'; - WHEN OTHERS => NULL; - END CASE; - IF opcode(4 downto 3)="00" THEN - bf_d32 <= '1'; - END IF; - bf_ext_out <= result(39 downto 32); - END IF; - END IF; - shift <= bf_ext_in&OP2out; - IF bf_s32='1' THEN - shift(39 downto 32) <= OP2out(7 downto 0); - END IF; - - IF bf_shift(0)='1' THEN - inmux0 <= shift(0)&shift(39 downto 1); - ELSE - inmux0 <= shift; - END IF; - IF bf_shift(1)='1' THEN - inmux1 <= inmux0(1 downto 0)&inmux0(39 downto 2); - ELSE - inmux1 <= inmux0; - END IF; - IF bf_shift(2)='1' THEN - inmux2 <= inmux1(3 downto 0)&inmux1(39 downto 4); - ELSE - inmux2 <= inmux1; - END IF; - IF bf_shift(3)='1' THEN - inmux3 <= inmux2(7 downto 0)&inmux2(31 downto 8); - ELSE - inmux3 <= inmux2(31 downto 0); - END IF; - IF bf_shift(4)='1' THEN - bf_set2(31 downto 0) <= inmux3(15 downto 0)&inmux3(31 downto 16); - ELSE - bf_set2(31 downto 0) <= inmux3; - END IF; - - IF bf_loffset(4)='1' THEN - copymux3 <= sign(15 downto 0)&sign(31 downto 16); - ELSE - copymux3 <= sign; - END IF; - IF bf_loffset(3)='1' THEN - copymux2(31 downto 0) <= copymux3(23 downto 0)©mux3(31 downto 24); - ELSE - copymux2(31 downto 0) <= copymux3; - END IF; - IF bf_d32='1' THEN - copymux2(39 downto 32) <= copymux3(7 downto 0); - ELSE - copymux2(39 downto 32) <= "11111111"; - END IF; - IF bf_loffset(2)='1' THEN - copymux1 <= copymux2(35 downto 0)©mux2(39 downto 36); - ELSE - copymux1 <= copymux2; - END IF; - IF bf_loffset(1)='1' THEN - copymux0 <= copymux1(37 downto 0)©mux1(39 downto 38); - ELSE - copymux0 <= copymux1; - END IF; - IF bf_loffset(0)='1' THEN - copy <= copymux0(38 downto 0)©mux0(39); - ELSE - copy <= copymux0; - END IF; - - result_tmp <= bf_ext_in&OP1out; - IF bf_ins='1' THEN - datareg <= reg_QB; - ELSE - datareg <= bf_set2; - END IF; - IF bf_ins='1' THEN - result(31 downto 0) <= bf_set2; - result(39 downto 32) <= bf_set2(7 downto 0); - ELSIF bf_bchg='1' THEN - result(31 downto 0) <= NOT OP1out; - result(39 downto 32) <= NOT bf_ext_in; - ELSE - result <= (OTHERS => '0'); - END IF; - IF bf_bset='1' THEN - result <= (OTHERS => '1'); - END IF; - - sign <= (OTHERS => '0'); - bf_NFlag <= datareg(to_integer(unsigned(bf_width))); - FOR i in 0 to 31 LOOP - IF i>bf_width(4 downto 0) THEN - datareg(i) <= '0'; - sign(i) <= '1'; - END IF; - END LOOP; - - FOR i in 0 to 39 LOOP - IF copy(i)='1' THEN - result(i) <= result_tmp(i); - END IF; - END LOOP; - - IF bf_exts='1' AND bf_NFlag='1' THEN - bf_datareg <= datareg OR sign; - ELSE - bf_datareg <= datareg; - END IF; --- bf_datareg <= copy(31 downto 0); --- result(31 downto 0)<=datareg; ---BFFFO - mask <= datareg; - bf_firstbit <= '0'&bitnr; - bitnr <= "11111"; - IF mask(31 downto 28)="0000" THEN - IF mask(27 downto 24)="0000" THEN - IF mask(23 downto 20)="0000" THEN - IF mask(19 downto 16)="0000" THEN - bitnr(4) <= '0'; - IF mask(15 downto 12)="0000" THEN - IF mask(11 downto 8)="0000" THEN - bitnr(3) <= '0'; - IF mask(7 downto 4)="0000" THEN - bitnr(2) <= '0'; - mux <= mask(3 downto 0); - ELSE - mux <= mask(7 downto 4); - END IF; - ELSE - mux <= mask(11 downto 8); - bitnr(2) <= '0'; - END IF; - ELSE - mux <= mask(15 downto 12); - END IF; - ELSE - mux <= mask(19 downto 16); - bitnr(3) <= '0'; - bitnr(2) <= '0'; - END IF; - ELSE - mux <= mask(23 downto 20); - bitnr(3) <= '0'; - END IF; - ELSE - mux <= mask(27 downto 24); - bitnr(2) <= '0'; - END IF; - ELSE - mux <= mask(31 downto 28); - END IF; - - IF mux(3 downto 2)="00" THEN - bitnr(1) <= '0'; - IF mux(1)='0' THEN - bitnr(0) <= '0'; - END IF; - ELSE - IF mux(3)='0' THEN - bitnr(0) <= '0'; - END IF; - END IF; - END PROCESS; + ----------------------------------------------------------------------------- + -- Bits + ----------------------------------------------------------------------------- + process (clk, exe_opcode, OP1out, OP2out, one_bit_in, bchg, bset, bit_Number, sndOPC, reg_QB) + begin + if rising_edge(clk) then + if clkena_lw = '1' then + bchg <= '0'; + bset <= '0'; + case opcode(7 downto 6) IS + when "01" => --bchg + bchg <= '1'; + when "11" => --bset + bset <= '1'; + when others => NULL; + end case; + end if; + end if; ------------------------------------------------------------------------------ --- Rotation ------------------------------------------------------------------------------ -PROCESS (exe_opcode, OP1out, Flags, rot_bits, rot_msb, rot_lsb, rot_rot, exec) - BEGIN - CASE exe_opcode(7 downto 6) IS - WHEN "00" => --Byte - rot_rot <= OP1out(7); - WHEN "01"|"11" => --Word - rot_rot <= OP1out(15); - WHEN "10" => --Long - rot_rot <= OP1out(31); - WHEN OTHERS => NULL; - END CASE; - - CASE rot_bits IS - WHEN "00" => --ASL, ASR - rot_lsb <= '0'; - rot_msb <= rot_rot; - WHEN "01" => --LSL, LSR - rot_lsb <= '0'; - rot_msb <= '0'; - WHEN "10" => --ROXL, ROXR - rot_lsb <= Flags(4); - rot_msb <= Flags(4); - WHEN "11" => --ROL, ROR - rot_lsb <= rot_rot; - rot_msb <= OP1out(0); - WHEN OTHERS => NULL; - END CASE; - - IF exec(rot_nop)='1' THEN - rot_out <= OP1out; - rot_X <= Flags(4); - IF rot_bits="10" THEN --ROXL, ROXR - rot_C <= Flags(4); - ELSE - rot_C <= '0'; - END IF; - ELSE - IF exe_opcode(8)='1' THEN --left - rot_out <= OP1out(30 downto 0)&rot_lsb; - rot_X <= rot_rot; - rot_C <= rot_rot; - ELSE --right - rot_X <= OP1out(0); - rot_C <= OP1out(0); - rot_out <= rot_msb&OP1out(31 downto 1); - CASE exe_opcode(7 downto 6) IS - WHEN "00" => --Byte - rot_out(7) <= rot_msb; - WHEN "01"|"11" => --Word - rot_out(15) <= rot_msb; - WHEN OTHERS => NULL; - END CASE; - END IF; - END IF; - END PROCESS; - ------------------------------------------------------------------------------- ---CCR op ------------------------------------------------------------------------------- -PROCESS (clk, Reset, exe_opcode, exe_datatype, Flags, last_data_read, OP2out, flag_z, OP1IN, c_out, addsub_ofl, - bcd_s, bcd_a, exec) - BEGIN - IF exec(andiSR)='1' THEN - CCRin <= Flags AND last_data_read(7 downto 0); - ELSIF exec(eoriSR)='1' THEN - CCRin <= Flags XOR last_data_read(7 downto 0); - ELSIF exec(oriSR)='1' THEN - CCRin <= Flags OR last_data_read(7 downto 0); - ELSE - CCRin <= OP2out(7 downto 0); - END IF; - ------------------------------------------------------------------------------- ---Flags ------------------------------------------------------------------------------- - flag_z <= "000"; - IF exec(use_XZFlag)='1' AND flags(2)='0' THEN - flag_z <= "000"; - ELSIF OP1in(7 downto 0)="00000000" THEN - flag_z(0) <= '1'; - IF OP1in(15 downto 8)="00000000" THEN - flag_z(1) <= '1'; - IF OP1in(31 downto 16)="0000000000000000" THEN - flag_z(2) <= '1'; - END IF; - END IF; - END IF; - --- --Flags NZVC - IF exe_datatype="00" THEN --Byte - set_flags <= OP1IN(7)&flag_z(0)&addsub_ofl(0)&c_out(0); - IF exec(opcABCD)='1' THEN - set_flags(0) <= bcd_a(8); - ELSIF exec(opcSBCD)='1' THEN - set_flags(0) <= bcd_s(8); - END IF; - ELSIF exe_datatype="10" OR exec(opcCPMAW)='1' THEN --Long - set_flags <= OP1IN(31)&flag_z(2)&addsub_ofl(2)&c_out(2); - ELSE --Word - set_flags <= OP1IN(15)&flag_z(1)&addsub_ofl(1)&c_out(1); - END IF; - - IF rising_edge(clk) THEN - IF clkena_lw = '1' THEN - IF exec(directSR)='1' OR set_stop='1' THEN - Flags(7 downto 0) <= data_read(7 downto 0); - END IF; - IF exec(directCCR)='1' THEN - Flags(7 downto 0) <= data_read(7 downto 0); - END IF; - - IF exec(opcROT)='1' THEN - asl_VFlag <= ((set_flags(3) XOR rot_rot) OR asl_VFlag); - ELSE - asl_VFlag <= '0'; - END IF; - IF exec(to_CCR)='1' THEN - Flags(7 downto 0) <= CCRin(7 downto 0); --CCR - ELSIF Z_error='1' THEN - IF exe_opcode(8)='0' THEN - Flags(3 downto 0) <= reg_QA(31)&"000"; - ELSE - Flags(3 downto 0) <= "0100"; - END IF; - ELSIF exec(no_Flags)='0' THEN - IF exec(opcADD)='1' THEN - Flags(4) <= set_flags(0); - ELSIF exec(opcROT)='1' AND rot_bits/="11" AND exec(rot_nop)='0' THEN - Flags(4) <= rot_X; - END IF; - - IF (exec(opcADD) OR exec(opcCMP))='1' THEN - Flags(3 downto 0) <= set_flags; - ELSIF exec(opcDIVU)='1' AND DIV_Mode/=3 THEN - IF V_Flag='1' THEN - Flags(3 downto 0) <= "1010"; - ELSE - Flags(3 downto 0) <= OP1IN(15)&flag_z(1)&"00"; - END IF; - ELSIF exec(write_reminder)='1' AND MUL_Mode/=3 THEN -- z-flag MULU.l - Flags(3) <= set_flags(3); - Flags(2) <= set_flags(2) AND Flags(2); - Flags(1) <= '0'; - Flags(0) <= '0'; - ELSIF exec(write_lowlong)='1' AND (MUL_Mode=1 OR MUL_Mode=2) THEN -- flag MULU.l - Flags(3) <= set_flags(3); - Flags(2) <= set_flags(2); - Flags(1) <= set_mV_Flag; --V - Flags(0) <= '0'; - ELSIF exec(opcOR)='1' OR exec(opcAND)='1' OR exec(opcEOR)='1' OR exec(opcMOVE)='1' OR exec(opcMOVEQ)='1' OR exec(opcSWAP)='1' OR exec(opcBF)='1' OR (exec(opcMULU)='1' AND MUL_Mode/=3) THEN - Flags(1 downto 0) <= "00"; - Flags(3 downto 2) <= set_flags(3 downto 2); - IF exec(opcBF)='1' THEN - Flags(3) <= bf_NFlag; - END IF; - ELSIF exec(opcROT)='1' THEN - Flags(3 downto 2) <= set_flags(3 downto 2); - Flags(0) <= rot_C; - IF rot_bits="00" AND ((set_flags(3) XOR rot_rot) OR asl_VFlag)='1' THEN --ASL/ASR - Flags(1) <= '1'; - ELSE - Flags(1) <= '0'; - END IF; - ELSIF exec(opcBITS)='1' THEN - Flags(2) <= NOT one_bit_in; - ELSIF exec(opcCHK)='1' THEN - IF exe_datatype="01" THEN --Word - Flags(3) <= OP1out(15); - ELSE - Flags(3) <= OP1out(31); - END IF; - IF OP1out(15 downto 0)=X"0000" AND (exe_datatype="01" OR OP1out(31 downto 16)=X"0000") THEN - Flags(2) <='1'; - ELSE - Flags(2) <='0'; - END IF; - Flags(1 downto 0) <= "00"; - END IF; - END IF; - END IF; - Flags(7 downto 5) <= "000"; - END IF; - END PROCESS; - -------------------------------------------------------------------------------- ----- MULU/MULS -------------------------------------------------------------------------------- -PROCESS (exe_opcode, OP2out, muls_msb, mulu_reg, FAsign, mulu_sign, reg_QA, faktorB, result_mulu, signedOP) - BEGIN - IF (signedOP='1' AND faktorB(31)='1') OR FAsign='1' THEN - muls_msb <= mulu_reg(63); - ELSE - muls_msb <= '0'; - END IF; - - IF signedOP='1' AND faktorB(31)='1' THEN - mulu_sign <= '1'; - ELSE - mulu_sign <= '0'; - END IF; - - IF MUL_Mode=0 THEN -- 16 Bit - result_mulu(63 downto 32) <= muls_msb&mulu_reg(63 downto 33); - result_mulu(15 downto 0) <= 'X'&mulu_reg(15 downto 1); - IF mulu_reg(0)='1' THEN - IF FAsign='1' THEN - result_mulu(63 downto 47) <= (muls_msb&mulu_reg(63 downto 48)-(mulu_sign&faktorB(31 downto 16))); - ELSE - result_mulu(63 downto 47) <= (muls_msb&mulu_reg(63 downto 48)+(mulu_sign&faktorB(31 downto 16))); - END IF; - END IF; - ELSE -- 32 Bit - result_mulu <= muls_msb&mulu_reg(63 downto 1); - IF mulu_reg(0)='1' THEN - IF FAsign='1' THEN - result_mulu(63 downto 31) <= (muls_msb&mulu_reg(63 downto 32)-(mulu_sign&faktorB)); - ELSE - result_mulu(63 downto 31) <= (muls_msb&mulu_reg(63 downto 32)+(mulu_sign&faktorB)); - END IF; - END IF; - END IF; - IF exe_opcode(15)='1' OR MUL_Mode=0 THEN - faktorB(31 downto 16) <= OP2out(15 downto 0); - faktorB(15 downto 0) <= (OTHERS=>'0'); - ELSE - faktorB <= OP2out; - END IF; - IF (result_mulu(63 downto 32)=X"00000000" AND (signedOP='0' OR result_mulu(31)='0')) OR - (result_mulu(63 downto 32)=X"FFFFFFFF" AND signedOP='1' AND result_mulu(31)='1') THEN - set_mV_Flag <= '0'; - ELSE - set_mV_Flag <= '1'; - END IF; - END PROCESS; - -PROCESS (clk) - BEGIN - IF rising_edge(clk) THEN - IF clkena_lw='1' THEN - IF micro_state=mul1 THEN - mulu_reg(63 downto 32) <= (OTHERS=>'0'); - IF divs='1' AND ((exe_opcode(15)='1' AND reg_QA(15)='1') OR (exe_opcode(15)='0' AND reg_QA(31)='1')) THEN --MULS Neg faktor - FAsign <= '1'; - mulu_reg(31 downto 0) <= 0-reg_QA; - ELSE - FAsign <= '0'; - mulu_reg(31 downto 0) <= reg_QA; - END IF; - ELSIF exec(opcMULU)='0' THEN - mulu_reg <= result_mulu; - END IF; - END IF; - END IF; - END PROCESS; - -------------------------------------------------------------------------------- ----- DIVU/DIVS -------------------------------------------------------------------------------- - -PROCESS (execOPC, OP1out, OP2out, div_reg, div_neg, div_bit, div_sub, div_quot, OP1_sign, div_over, result_div, reg_QA, opcode, sndOPC, divs, exe_opcode, reg_QB, - signedOP, nozero, div_qsign, OP2outext) - BEGIN - divs <= (opcode(15) AND opcode(8)) OR (NOT opcode(15) AND sndOPC(11)); - divisor(15 downto 0) <= (OTHERS=> '0'); - divisor(63 downto 32) <= (OTHERS=> divs AND reg_QA(31)); - IF exe_opcode(15)='1' OR DIV_Mode=0 THEN - divisor(47 downto 16) <= reg_QA; - ELSE - divisor(31 downto 0) <= reg_QA; - IF exe_opcode(14)='1' AND sndOPC(10)='1' THEN - divisor(63 downto 32) <= reg_QB; - END IF; - END IF; - IF signedOP='1' OR opcode(15)='0' THEN - OP2outext <= OP2out(31 downto 16); - ELSE - OP2outext <= (OTHERS=> '0'); - END IF; - IF signedOP='1' AND OP2out(31) ='1' THEN - div_sub <= (div_reg(63 downto 31))+('1'&OP2out(31 downto 0)); - ELSE - div_sub <= (div_reg(63 downto 31))-('0'&OP2outext(15 downto 0)&OP2out(15 downto 0)); - END IF; - IF DIV_Mode=0 THEN - div_bit <= div_sub(16); - ELSE - div_bit <= div_sub(32); - END IF; - IF div_bit='1' THEN - div_quot(63 downto 32) <= div_reg(62 downto 31); - ELSE - div_quot(63 downto 32) <= div_sub(31 downto 0); - END IF; - div_quot(31 downto 0) <= div_reg(30 downto 0)&NOT div_bit; - + if exe_opcode(8) = '0' then + if exe_opcode(5 downto 4) = "00" then + bit_number <= sndOPC(4 downto 0); + else + bit_number <= "00" & sndOPC(2 downto 0); + end if; + else + if exe_opcode(5 downto 4) = "00" then + bit_number <= reg_QB(4 downto 0); + else + bit_number <= "00" & reg_QB(2 downto 0); + end if; + end if; - IF ((nozero='1' AND signedOP='1' AND (OP2out(31) XOR OP1_sign XOR div_neg XOR div_qsign)='1' ) --Overflow DIVS - OR (signedOP='0' AND div_over(32)='0')) AND DIV_Mode/=3 THEN --Overflow DIVU - set_V_Flag <= '1'; - ELSE - set_V_Flag <= '0'; - END IF; - END PROCESS; - -PROCESS (clk) - BEGIN - IF rising_edge(clk) THEN - IF clkena_lw='1' THEN - V_Flag <= set_V_Flag; - signedOP <= divs; - IF micro_state=div1 THEN - nozero <= '0'; - IF divs='1' AND divisor(63)='1' THEN -- Neg divisor - OP1_sign <= '1'; - div_reg <= 0-divisor; - ELSE - OP1_sign <= '0'; - div_reg <= divisor; - END IF; - ELSE - div_reg <= div_quot; - nozero <= NOT div_bit OR nozero; - END IF; - IF micro_state=div2 THEN - div_qsign <= NOT div_bit; - div_neg <= signedOP AND (OP2out(31) XOR OP1_sign); - IF DIV_Mode=0 THEN - div_over(32 downto 16) <= ('0'&div_reg(47 downto 32))-('0'&OP2out(15 downto 0)); - ELSE - div_over <= ('0'&div_reg(63 downto 32))-('0'&OP2out); - END IF; - END IF; - IF exec(write_reminder)='0' THEN --- IF exec_DIVU='0' THEN - IF div_neg='1' THEN - result_div(31 downto 0) <= 0-div_quot(31 downto 0); - ELSE - result_div(31 downto 0) <= div_quot(31 downto 0); - END IF; - - IF OP1_sign='1' THEN - result_div(63 downto 32) <= 0-div_quot(63 downto 32); - ELSE - result_div(63 downto 32) <= div_quot(63 downto 32); - END IF; - END IF; - END IF; - END IF; - END PROCESS; -END; + one_bit_in <= OP1out(to_integer(unsigned(bit_Number))); + bits_out <= OP1out; + bits_out(to_integer(unsigned(bit_Number))) <= (bchg and not one_bit_in) OR bset; + end process; + + ----------------------------------------------------------------------------- + -- Bit Field + ----------------------------------------------------------------------------- + + -- Bitfields can have up to four (register) operands, e.g. bfins d0,d1{d2,d3} + -- the width an offset operands are evaluated while the second opcode word is + -- evaluated. These values are latched, so the two other registers can be read + -- in the next cycle while the ALU is working since the tg68k can only read + -- from two registers at once. + -- + -- All bitfield operations can operate on registers or memory. There are + -- two fundamental differences which make the shifters quite complex: + -- 1. Memory content is delivered byte aligned to the ALU. Thus all shifting + -- is 7 bits far at most. Registers are 32 bit in size and may require + -- shifting of up to 31 bit positions + -- 2. Memory operations can affect 5 bytes. Thus all shifting is 40 bit in that + -- case. Registers are 32 bit in size and bitfield operations wrap. Shifts + -- are actually rotations for that reason + -- + -- The destination operand is transfered via op1out and bf_ext into the ALU. + -- + -- bftst, bfset, bfclr and bfchg + -------------------------------- + -- bftst, bfset, bfclr and bfchg work very similar. A "sign" vector is generated + -- having "width" right aligned 0-bits and the rest ones. + -- A "copy" vector is generated from this by shifting through copymux so + -- this contains a 1 for all bits in bf_ext_in & op1out that will not be + -- affected by the operation. + -- The result vector is either all 1's (bfset), all 0's(bfclr) or the inverse + -- of bf_ext_in & op1out. Those bits in result that have a 1 in the copy + -- vector are overwritten with the original value from bf_ext_in & op1out + -- The result is returned through bf_ext_out and ALUout + -- + -- These instructions only calculate the Z and N flags. Both are derived + -- directly from bf_ext_in & op1out with the help of the copy vector and + -- the offset/width fields. Thus Z and N are set from the previous contents + -- of the bitfield. + -- + -- bfins + -------- + -- bfins reuses most of the functionality of bfset, bfclr and bfchg. But it + -- has another 32 bit parameter that's being used for the source. This is passed + -- to the ALU via op2out. This is moved to the shift register and shifted + -- bf_shift bits to the right. + -- The input valus is also store in datareg and the lowest "width" bits + -- are masked. This is then forwarded to op1in which in turn uses the normal + -- mechanisms to generate the flags. A special bf_NFlag is also generated + -- from this. Z and N are set from these and not from the previous bitfield + -- contents as with bfset, bfclr or bfchg + -- + -- bfextu/bfexts + ---------------- + -- bfexts and bfextu use the same shifter that is used by bfins to shift the + -- data to be inserted. It's using that same shifter to shift data in the + -- opposite direction. Flags are set from the extraced data + -- + -- bfffo + -------- + -- bfffo uses the same data path as bfext. But instead of directly returning + -- the extracted data it determines the highest bit setin the result + + process (clk, bf_ins, bf_bchg, bf_bset, bf_exts, bf_extu, bf_set2, OP1out, OP2out, result_tmp, bf_ext_in, + datareg, bf_NFlag, result, reg_QB, sign, bf_d32, copy, bf_loffset, bf_width) + begin + if rising_edge(clk) then + if clkena_lw = '1' then + bf_bset <= '0'; + bf_bchg <= '0'; + bf_ins <= '0'; + bf_exts <= '0'; + bf_extu <= '0'; + bf_fffo <= '0'; + bf_d32 <= '0'; + case opcode(10 downto 8) IS + when "010" => bf_bchg <= '1'; --BFCHG + when "011" => bf_exts <= '1'; --BFEXTS + when "001" => bf_extu <= '1'; --BFEXTU + -- when "100" => insert <= (others =>'0'); --BFCLR + when "101" => bf_fffo <= '1'; --BFFFO + when "110" => bf_bset <= '1'; --BFSET + when "111" => bf_ins <= '1'; --BFinS + when others => NULL; + end case; + + -- ea is a register + if opcode(4 downto 3) = "00" then + bf_d32 <= '1'; + end if; + + bf_ext_out <= result(39 downto 32); + end if; + end if; + + ------------- BF_SET2 -------------- + if bf_ins = '1' then + bf_loff_dir <= 32 - bf_loffset; + else + bf_loff_dir <= bf_loffset; + end if; + + if bf_d32 = '1' then + -- 32bit: rotate 0..31 bits left or right, don't care for upper 8 bits + bf_set2 <= "--------" & std_logic_vector(unsigned(OP2out) ror to_integer(unsigned(bf_loff_dir))); + else + if bf_ins = '1' then + -- 40 bit: shift 0..7 bits left + bf_set2 <= std_logic_vector(unsigned(bf_ext_in & OP2out) sll to_integer(unsigned(bf_loffset(2 downto 0)))); + else + -- 40 bit: shift 0..7 bits right + bf_set2 <= std_logic_vector(unsigned(bf_ext_in & OP2out) srl to_integer(unsigned(bf_loffset(2 downto 0)))); + end if; + end if; + + ------------- COPY -------------- + if bf_d32 = '1' then + -- 32bit: rotate 32 bits 0..31 bits left, don't care for upper 8 bits + copy <= "--------" & std_logic_vector(unsigned(sign) rol to_integer(unsigned(bf_loffset))); + else + -- 40 bit: shift 40 bits 0..7 bits left, fill with '1's (hence the two not's) + copy <= not std_logic_vector(unsigned(x"00" & (not sign)) sll to_integer(unsigned(bf_loffset(2 downto 0)))); + end if; + + if bf_ins = '1' then + datareg <= reg_QB; + else + datareg <= bf_set2(31 downto 0); + end if; + + -- do the bitfield operation itself + if bf_ins = '1' then + result <= bf_set2; + elsif bf_bchg = '1' then + result <= not (bf_ext_in & OP1out); + elsif bf_bset = '1' then + result <= (others => '1'); + else + result <= (others => '0'); + end if; + + sign <= (others => '0'); + bf_NFlag <= datareg(to_integer(unsigned(bf_width))); + for i in 0 TO 31 loop + if i > bf_width then + datareg(i) <= '0'; + sign(i) <= '1'; + end if; + end loop; + + -- Set bits 32..39 to 0 if operating on register to make sure + -- zero flag calculation over all 40 bits works correctly + result_tmp(31 downto 0) <= OP1out; + if bf_d32 = '1' then + result_tmp(39 downto 32) <= "00000000"; + else + result_tmp(39 downto 32) <= bf_ext_in; + end if; + + bf_flag_z <= '1'; + if bf_d32 = '0' then + -- The test for this overflow shouldn't be needed. But GHDL complains + -- otherwise. + if(to_integer(unsigned('0' & bf_loffset)+unsigned(bf_width)) > 39) then + bf_flag_n <= result_tmp(39); + else + bf_flag_n <= result_tmp(to_integer(unsigned('0' & bf_loffset)+unsigned(bf_width))); + end if; + else + --TH: TODO: check if this really does what it's supposed to + bf_flag_n <= result_tmp(to_integer(unsigned(bf_loffset)+unsigned(bf_width))); + end if; + for i in 0 TO 39 loop + if copy(i) = '1' then + result(i) <= result_tmp(i); + elsif result_tmp(i) = '1' then + bf_flag_z <= '0'; + end if; + end loop; + + if bf_exts = '1' and bf_NFlag = '1' then + bf_datareg <= datareg OR sign; + else + bf_datareg <= datareg; + end if; + + --BFFFO + if datareg(31) = '1' then bf_firstbit <= "100000"; + elsif datareg(30) = '1' then bf_firstbit <= "011111"; + elsif datareg(29) = '1' then bf_firstbit <= "011110"; + elsif datareg(28) = '1' then bf_firstbit <= "011101"; + elsif datareg(27) = '1' then bf_firstbit <= "011100"; + elsif datareg(26) = '1' then bf_firstbit <= "011011"; + elsif datareg(25) = '1' then bf_firstbit <= "011010"; + elsif datareg(24) = '1' then bf_firstbit <= "011001"; + elsif datareg(23) = '1' then bf_firstbit <= "011000"; + elsif datareg(22) = '1' then bf_firstbit <= "010111"; + elsif datareg(21) = '1' then bf_firstbit <= "010110"; + elsif datareg(20) = '1' then bf_firstbit <= "010101"; + elsif datareg(19) = '1' then bf_firstbit <= "010100"; + elsif datareg(18) = '1' then bf_firstbit <= "010011"; + elsif datareg(17) = '1' then bf_firstbit <= "010010"; + elsif datareg(16) = '1' then bf_firstbit <= "010001"; + elsif datareg(15) = '1' then bf_firstbit <= "010000"; + elsif datareg(14) = '1' then bf_firstbit <= "001111"; + elsif datareg(13) = '1' then bf_firstbit <= "001110"; + elsif datareg(12) = '1' then bf_firstbit <= "001101"; + elsif datareg(11) = '1' then bf_firstbit <= "001100"; + elsif datareg(10) = '1' then bf_firstbit <= "001011"; + elsif datareg(9) = '1' then bf_firstbit <= "001010"; + elsif datareg(8) = '1' then bf_firstbit <= "001001"; + elsif datareg(7) = '1' then bf_firstbit <= "001000"; + elsif datareg(6) = '1' then bf_firstbit <= "000111"; + elsif datareg(5) = '1' then bf_firstbit <= "000110"; + elsif datareg(4) = '1' then bf_firstbit <= "000101"; + elsif datareg(3) = '1' then bf_firstbit <= "000100"; + elsif datareg(2) = '1' then bf_firstbit <= "000011"; + elsif datareg(1) = '1' then bf_firstbit <= "000010"; + elsif datareg(0) = '1' then bf_firstbit <= "000001"; + else bf_firstbit <= "000000"; + end if; + + end process; + + ----------------------------------------------------------------------------- + -- Rotation + ----------------------------------------------------------------------------- + process (exe_opcode, OP1out, Flags, rot_bits, rot_msb, rot_lsb, rot_cnt, rot_out, rot_rot, bs_data, bs_msb, exec) + begin + case exe_opcode(7 downto 6) IS + when "00" => --Byte + rot_rot <= OP1out(7); + when "01" | "11" => --Word + rot_rot <= OP1out(15); + when "10" => --Long + rot_rot <= OP1out(31); + when others => NULL; + end case; + + case rot_bits IS + when "00" => --ASL, ASR + rot_lsb <= '0'; + rot_msb <= rot_rot; + when "01" => --LSL, LSR + rot_lsb <= '0'; + rot_msb <= '0'; + when "10" => --ROXL, ROXR + rot_lsb <= Flags(4); + rot_msb <= Flags(4); + when "11" => --ROL, ROR + rot_lsb <= rot_rot; + rot_msb <= OP1out(0); + when others => NULL; + end case; + + if exec(rot_nop) = '1' then + rot_out <= OP1out; + rot_X <= Flags(4); + if rot_bits = "10" then --ROXL, ROXR + rot_C <= Flags(4); + else + rot_C <= '0'; + end if; + else + if exe_opcode(8) = '1' then --left + rot_out <= OP1out(30 downto 0) & rot_lsb; + rot_X <= rot_rot; + rot_C <= rot_rot; + else --right + rot_X <= OP1out(0); + rot_C <= OP1out(0); + rot_out <= rot_msb & OP1out(31 downto 1); + case exe_opcode(7 downto 6) IS + when "00" => --Byte + rot_out(7) <= rot_msb; + when "01" | "11" => --Word + rot_out(15) <= rot_msb; + when others => NULL; + end case; + end if; + end if; + + -- -------- barrel shifter ------------ + if rot_bits = "01" and exe_opcode(7 downto 6) /= "11" then + -- currently only and LSL/LSR use the barrel shifter + + bs_data <= OP1out; + bs_msb <= "11111"; + + -- word size + if exe_opcode(7 downto 6)="01" then + bs_msb <= "01111"; + bs_data(31 downto 16) <= "0000000000000000"; + end if; + + -- byte size + if exe_opcode(7 downto 6)="00" then + bs_msb <= "00111"; + bs_data(31 downto 8) <= "000000000000000000000000"; + end if; + + if exe_opcode(8) = '1' then + -- left + rot_out <= std_logic_vector(unsigned(bs_data) sll to_integer(unsigned(rot_cnt))); + rot_X <= OP1out(to_integer(unsigned("00001" - rot_cnt(4 downto 0) + bs_msb))); + rot_C <= OP1out(to_integer(unsigned("00001" - rot_cnt(4 downto 0) + bs_msb))); + else + -- right + rot_out <= std_logic_vector(unsigned(bs_data) srl to_integer(unsigned(rot_cnt))); + rot_X <= OP1out(to_integer(unsigned(rot_cnt(4 downto 0) - "00001"))); + rot_C <= OP1out(to_integer(unsigned(rot_cnt(4 downto 0) - "00001"))); + end if; + + -- not shifting at all or shifting more than the whole byte/word/long + if(rot_cnt = 0) then + rot_X <= Flags(4); + rot_C <= '0'; + else + if(rot_cnt - 1 > bs_msb) then + rot_X <= '0'; + rot_C <= '0'; + end if; + end if; + + end if; + + end process; + + ------------------------------------------------------------------------------ + --CCR op + ------------------------------------------------------------------------------ +process (clk, Reset, exe_opcode, exe_datatype, Flags, last_data_read, OP2out, flag_z, OP1in, c_out, addsub_ofl, + bcd_s, bcd_a, exec) + begin + if exec(andiSR) = '1' then + CCRin <= Flags and last_data_read(7 downto 0); + elsif exec(eoriSR) = '1' then + CCRin <= Flags xor last_data_read(7 downto 0); + elsif exec(oriSR) = '1' then + CCRin <= Flags OR last_data_read(7 downto 0); + else + CCRin <= OP2out(7 downto 0); + end if; + + ------------------------------------------------------------------------------ + --Flags + ------------------------------------------------------------------------------ + flag_z <= "000"; + if exec(use_XZFlag) = '1' and flags(2) = '0' then + flag_z <= "000"; + elsif OP1in(7 downto 0) = "00000000" then + flag_z(0) <= '1'; + if OP1in(15 downto 8) = "00000000" then + flag_z(1) <= '1'; + if OP1in(31 downto 16) = "0000000000000000" then + flag_z(2) <= '1'; + end if; + end if; + end if; + + -- --Flags NZVC + if exe_datatype = "00" then --Byte + set_flags <= OP1in(7) & flag_z(0) & addsub_ofl(0) & c_out(0); + if exec(opcABCD) = '1' then + set_flags(0) <= bcd_a(8); + elsif exec(opcSBCD) = '1' then + set_flags(0) <= bcd_s(8); + end if; + elsif exe_datatype = "10" OR exec(opcCPMAW) = '1' then --Long + set_flags <= OP1in(31) & flag_z(2) & addsub_ofl(2) & c_out(2); + else --Word + set_flags <= OP1in(15) & flag_z(1) & addsub_ofl(1) & c_out(1); + end if; + + if rising_edge(clk) then + if clkena_lw = '1' then + if exec(directSR) = '1' OR set_stop = '1' then + Flags(7 downto 0) <= data_read(7 downto 0); + end if; + if exec(directCCR) = '1' then + Flags(7 downto 0) <= data_read(7 downto 0); + end if; + + if exec(opcROT) = '1' then + asl_VFlag <= ((set_flags(3) xor rot_rot) OR asl_VFlag); + else + asl_VFlag <= '0'; + end if; + if exec(to_CCR) = '1' then + Flags(7 downto 0) <= CCRin(7 downto 0); --CCR + elsif Z_error = '1' then + if exe_opcode(8) = '0' then + Flags(3 downto 0) <= reg_QA(31) & "000"; + else + Flags(3 downto 0) <= "0100"; + end if; + elsif exec(no_Flags) = '0' then + if exec(opcADD) = '1' then + Flags(4) <= set_flags(0); + elsif exec(opcROT) = '1' and rot_bits /= "11" and exec(rot_nop) = '0' then + Flags(4) <= rot_X; + end if; + + if (exec(opcADD) OR exec(opcCMP)) = '1' then + Flags(3 downto 0) <= set_flags; + elsif exec(opcDIVU) = '1' and DIV_Mode /= 3 then + if V_Flag = '1' then + Flags(3 downto 0) <= "1010"; + else + Flags(3 downto 0) <= OP1in(15) & flag_z(1) & "00"; + end if; + elsif exec(write_reminder) = '1' and MUL_Mode /= 3 then -- z-flag MULU.l + Flags(3) <= set_flags(3); + Flags(2) <= set_flags(2) and Flags(2); + Flags(1) <= '0'; + Flags(0) <= '0'; + elsif exec(write_lowlong) = '1' and (MUL_Mode = 1 OR MUL_Mode = 2) then -- flag MULU.l + Flags(3) <= set_flags(3); + Flags(2) <= set_flags(2); + Flags(1) <= set_mV_Flag; --V + Flags(0) <= '0'; + elsif exec(opcOR) = '1' OR exec(opcand) = '1' OR exec(opcEOR) = '1' OR exec(opcMOVE) = '1' OR exec(opcMOVEQ) = '1' OR exec(opcSWAP) = '1' OR exec(opcBF) = '1' OR (exec(opcMULU) = '1' and MUL_Mode /= 3) then + Flags(1 downto 0) <= "00"; + Flags(3 downto 2) <= set_flags(3 downto 2); + if exec(opcBF) = '1' then + -- flags(2) has correctly been set from set_flags + Flags(3) <= bf_NFlag; + + --TH TODO: check flag handling of fffo + + -- "normal" flags are taken from op2in + if bf_fffo = '0' and bf_extu='0' and bf_exts='0' and bf_ins='0' then + Flags(2) <= bf_flag_z; + Flags(3) <= bf_flag_n; + end if; + end if; + elsif exec(opcROT) = '1' then + Flags(3 downto 2) <= set_flags(3 downto 2); + Flags(0) <= rot_C; + if rot_bits = "00" and ((set_flags(3) xor rot_rot) OR asl_VFlag) = '1' then --ASL/ASR + Flags(1) <= '1'; + else + Flags(1) <= '0'; + end if; + elsif exec(opcBITS) = '1' then + Flags(2) <= not one_bit_in; + elsif exec(opcCHK) = '1' then + if exe_datatype = "01" then --Word + Flags(3) <= OP1out(15); + else + Flags(3) <= OP1out(31); + end if; + if OP1out(15 downto 0) = X"0000" and (exe_datatype = "01" OR OP1out(31 downto 16) = X"0000") then + Flags(2) <= '1'; + else + Flags(2) <= '0'; + end if; + Flags(1 downto 0) <= "00"; + end if; + end if; + end if; + Flags(7 downto 5) <= "000"; + end if; + end process; + + ------------------------------------------------------------------------------- + ---- MULU/MULS + ------------------------------------------------------------------------------- + process (exe_opcode, OP2out, muls_msb, mulu_reg, FAsign, mulu_sign, reg_QA, faktorB, result_mulu, signedOP) + begin + if (signedOP = '1' and faktorB(31) = '1') OR FAsign = '1' then + muls_msb <= mulu_reg(63); + else + muls_msb <= '0'; + end if; + + if signedOP = '1' and faktorB(31) = '1' then + mulu_sign <= '1'; + else + mulu_sign <= '0'; + end if; + + if MUL_Mode = 0 then -- 16 Bit + result_mulu(63 downto 32) <= muls_msb & mulu_reg(63 downto 33); + result_mulu(15 downto 0) <= 'X' & mulu_reg(15 downto 1); + if mulu_reg(0) = '1' then + if FAsign = '1' then + result_mulu(63 downto 47) <= (muls_msb & mulu_reg(63 downto 48) - (mulu_sign & faktorB(31 downto 16))); + else + result_mulu(63 downto 47) <= (muls_msb & mulu_reg(63 downto 48) + (mulu_sign & faktorB(31 downto 16))); + end if; + end if; + else -- 32 Bit + result_mulu <= muls_msb & mulu_reg(63 downto 1); + if mulu_reg(0) = '1' then + if FAsign = '1' then + result_mulu(63 downto 31) <= (muls_msb & mulu_reg(63 downto 32) - (mulu_sign & faktorB)); + else + result_mulu(63 downto 31) <= (muls_msb & mulu_reg(63 downto 32) + (mulu_sign & faktorB)); + end if; + end if; + end if; + if exe_opcode(15) = '1' OR MUL_Mode = 0 then + faktorB(31 downto 16) <= OP2out(15 downto 0); + faktorB(15 downto 0) <= (others => '0'); + else + faktorB <= OP2out; + end if; + if (result_mulu(63 downto 32) = X"00000000" and (signedOP = '0' OR result_mulu(31) = '0')) OR + (result_mulu(63 downto 32) = X"FFFFFFFF" and signedOP = '1' and result_mulu(31) = '1') then + set_mV_Flag <= '0'; + else + set_mV_Flag <= '1'; + end if; + end process; + + process (clk) + begin + if rising_edge(clk) then + if clkena_lw = '1' then + if micro_state = mul1 then + mulu_reg(63 downto 32) <= (others => '0'); + if divs = '1' and ((exe_opcode(15) = '1' and reg_QA(15) = '1') OR (exe_opcode(15) = '0' and reg_QA(31) = '1')) then --MULS Neg faktor + FAsign <= '1'; + mulu_reg(31 downto 0) <= 0 - reg_QA; + else + FAsign <= '0'; + mulu_reg(31 downto 0) <= reg_QA; + end if; + elsif exec(opcMULU) = '0' then + mulu_reg <= result_mulu; + end if; + end if; + end if; + end process; + + ------------------------------------------------------------------------------- + ---- DIVU/DIVS + ------------------------------------------------------------------------------- + +process (execOPC, OP1out, OP2out, div_reg, div_neg, div_bit, div_sub, div_quot, OP1_sign, div_over, result_div, reg_QA, opcode, sndOPC, divs, exe_opcode, reg_QB, + signedOP, nozero, div_qsign, OP2outext) + begin + divs <= (opcode(15) and opcode(8)) OR (not opcode(15) and sndOPC(11)); + divisor(15 downto 0) <= (others => '0'); + divisor(63 downto 32) <= (others => divs and reg_QA(31)); + if exe_opcode(15) = '1' OR DIV_Mode = 0 then + divisor(47 downto 16) <= reg_QA; + else + divisor(31 downto 0) <= reg_QA; + if exe_opcode(14) = '1' and sndOPC(10) = '1' then + divisor(63 downto 32) <= reg_QB; + end if; + end if; + if signedOP = '1' OR opcode(15) = '0' then + OP2outext <= OP2out(31 downto 16); + else + OP2outext <= (others => '0'); + end if; + if signedOP = '1' and OP2out(31) = '1' then + div_sub <= (div_reg(63 downto 31)) + ('1' & OP2out(31 downto 0)); + else + div_sub <= (div_reg(63 downto 31)) - ('0' & OP2outext(15 downto 0) & OP2out(15 downto 0)); + end if; + if DIV_Mode = 0 then + div_bit <= div_sub(16); + else + div_bit <= div_sub(32); + end if; + if div_bit = '1' then + div_quot(63 downto 32) <= div_reg(62 downto 31); + else + div_quot(63 downto 32) <= div_sub(31 downto 0); + end if; + div_quot(31 downto 0) <= div_reg(30 downto 0) & not div_bit; + if ((nozero = '1' and signedOP = '1' and (OP2out(31) xor OP1_sign xor div_neg xor div_qsign) = '1' ) --Overflow DIVS + OR (signedOP = '0' and div_over(32) = '0')) and DIV_Mode /= 3 then --Overflow DIVU + set_V_Flag <= '1'; + else + set_V_Flag <= '0'; + end if; + end process; + + process (clk) + begin + if rising_edge(clk) then + if clkena_lw = '1' then + V_Flag <= set_V_Flag; + signedOP <= divs; + if micro_state = div1 then + nozero <= '0'; + if divs = '1' and divisor(63) = '1' then -- Neg divisor + OP1_sign <= '1'; + div_reg <= 0 - divisor; + else + OP1_sign <= '0'; + div_reg <= divisor; + end if; + else + div_reg <= div_quot; + nozero <= not div_bit OR nozero; + end if; + if micro_state = div2 then + div_qsign <= not div_bit; + div_neg <= signedOP and (OP2out(31) xor OP1_sign); + if DIV_Mode = 0 then + div_over(32 downto 16) <= ('0' & div_reg(47 downto 32)) - ('0' & OP2out(15 downto 0)); + else + div_over <= ('0' & div_reg(63 downto 32)) - ('0' & OP2out); + end if; + end if; + if exec(write_reminder) = '0' then + -- if exec_DIVU='0' then + if div_neg = '1' then + result_div(31 downto 0) <= 0 - div_quot(31 downto 0); + else + result_div(31 downto 0) <= div_quot(31 downto 0); + end if; + + if OP1_sign = '1' then + result_div(63 downto 32) <= 0 - div_quot(63 downto 32); + else + result_div(63 downto 32) <= div_quot(63 downto 32); + end if; + end if; + end if; + end if; + end process; + + set_V_Flag_out <= set_V_Flag; + Flags_out <= Flags; + c_out_out <= c_out; + addsub_q_out <= addsub_q; + +end; diff --git a/cores/mist/TG68K_Pack.vhd b/cores/mist/TG68K_Pack.vhd index fd3c8f4..3e69a3a 100644 --- a/cores/mist/TG68K_Pack.vhd +++ b/cores/mist/TG68K_Pack.vhd @@ -27,104 +27,98 @@ package TG68K_Pack is type micro_states is (idle, nop, ld_nn, st_nn, ld_dAn1, ld_AnXn1, ld_AnXn2, st_dAn1, ld_AnXnbd1, ld_AnXnbd2, ld_AnXnbd3, ld_229_1, ld_229_2, ld_229_3, ld_229_4, st_229_1, st_229_2, st_229_3, st_229_4, st_AnXn1, st_AnXn2, bra1, bsr1, bsr2, nopnop, dbcc1, movem1, movem2, movem3, - andi, op_AxAy, cmpm, link1, link2, unlink1, unlink2, int1, int2, int3, int4, rte1, rte2, rte3, trap0, trap1, trap2, trap3, + andi, op_AxAy, cmpm, link1, link2, unlink1, unlink2, int1, int2, int3, int4, rte1, + rte2, rte3, rte4, rte5, trap00, trap0, trap1, trap2, trap3, trap4, trap5, trap6, movec1, movep1, movep2, movep3, movep4, movep5, rota1, bf1, mul1, mul2, mul_end1, mul_end2, div1, div2, div3, div4, div_end1, div_end2, pack1, pack2, pack3); constant opcMOVE : integer := 0; -- constant opcMOVEQ : integer := 1; -- constant opcMOVESR : integer := 2; -- - constant opcADD : integer := 3; -- - constant opcADDQ : integer := 4; -- - constant opcOR : integer := 5; -- - constant opcAND : integer := 6; -- - constant opcEOR : integer := 7; -- - constant opcCMP : integer := 8; -- - constant opcROT : integer := 9; -- - constant opcCPMAW : integer := 10; - constant opcEXT : integer := 11; -- - constant opcABCD : integer := 12; -- - constant opcSBCD : integer := 13; -- - constant opcBITS : integer := 14; -- - constant opcSWAP : integer := 15; -- - constant opcScc : integer := 16; -- - constant andiSR : integer := 17; -- - constant eoriSR : integer := 18; -- - constant oriSR : integer := 19; -- - constant opcMULU : integer := 20; -- - constant opcDIVU : integer := 21; -- - constant dispouter : integer := 22; -- - constant rot_nop : integer := 23; -- - constant ld_rot_cnt : integer := 24; -- - constant writePC_add : integer := 25; -- - constant ea_data_OP1 : integer := 26; -- - constant ea_data_OP2 : integer := 27; -- - constant use_XZFlag : integer := 28; -- - constant get_bfoffset : integer := 29; -- - constant save_memaddr : integer := 30; -- - constant opcCHK : integer := 31; -- - constant movec_rd : integer := 32; -- - constant movec_wr : integer := 33; -- - constant Regwrena : integer := 34; -- - constant update_FC : integer := 35; -- - constant linksp : integer := 36; -- - constant movepl : integer := 37; -- - constant update_ld : integer := 38; -- - constant OP1addr : integer := 39; -- - constant write_reg : integer := 40; -- - constant changeMode : integer := 41; -- - constant ea_build : integer := 42; -- - constant trap_chk : integer := 43; -- - constant store_ea_data : integer := 44; -- - constant addrlong : integer := 45; -- - constant postadd : integer := 46; -- - constant presub : integer := 47; -- - constant subidx : integer := 48; -- - constant no_Flags : integer := 49; -- - constant use_SP : integer := 50; -- - constant to_CCR : integer := 51; -- - constant to_SR : integer := 52; -- - constant OP2out_one : integer := 53; -- - constant OP1out_zero : integer := 54; -- - constant mem_addsub : integer := 55; -- - constant addsub : integer := 56; -- - constant directPC : integer := 57; -- - constant direct_delta : integer := 58; -- - constant directSR : integer := 59; -- - constant directCCR : integer := 60; -- - constant exg : integer := 61; -- - constant get_ea_now : integer := 62; -- - constant ea_to_pc : integer := 63; -- - constant hold_dwr : integer := 64; -- - constant to_USP : integer := 65; -- - constant from_USP : integer := 66; -- - constant write_lowlong : integer := 67; -- - constant write_reminder : integer := 68; -- - constant movem_action : integer := 69; -- - constant briefext : integer := 70; -- - constant get_2ndOPC : integer := 71; -- - constant mem_byte : integer := 72; -- - constant longaktion : integer := 73; -- - constant opcRESET : integer := 74; -- - constant opcBF : integer := 75; -- - constant opcBFwb : integer := 76; -- - constant s2nd_hbits : integer := 77; -- - constant opcPACK : integer := 77; -- --- constant s2nd_hbits : integer := 77; -- + constant opcMOVECCR : integer := 3; -- + constant opcADD : integer := 4; -- + constant opcADDQ : integer := 5; -- + constant opcOR : integer := 6; -- + constant opcAND : integer := 7; -- + constant opcEOR : integer := 8; -- + constant opcCMP : integer := 9; -- + constant opcROT : integer := 10; -- + constant opcCPMAW : integer := 11; + constant opcEXT : integer := 12; -- + constant opcABCD : integer := 13; -- + constant opcSBCD : integer := 14; -- + constant opcBITS : integer := 15; -- + constant opcSWAP : integer := 16; -- + constant opcScc : integer := 17; -- + constant andiSR : integer := 18; -- + constant eoriSR : integer := 19; -- + constant oriSR : integer := 20; -- + constant opcMULU : integer := 21; -- + constant opcDIVU : integer := 22; -- + constant dispouter : integer := 23; -- + constant rot_nop : integer := 24; -- + constant ld_rot_cnt : integer := 25; -- + constant writePC_add : integer := 26; -- + constant ea_data_OP1 : integer := 27; -- + constant ea_data_OP2 : integer := 28; -- + constant use_XZFlag : integer := 29; -- + constant get_bfoffset : integer := 30; -- + constant save_memaddr : integer := 31; -- + constant opcCHK : integer := 32; -- + constant movec_rd : integer := 33; -- + constant movec_wr : integer := 34; -- + constant Regwrena : integer := 35; -- + constant update_FC : integer := 36; -- + constant linksp : integer := 37; -- + constant movepl : integer := 38; -- + constant update_ld : integer := 39; -- + constant OP1addr : integer := 40; -- + constant write_reg : integer := 41; -- + constant changeMode : integer := 42; -- + constant ea_build : integer := 43; -- + constant trap_chk : integer := 44; -- + constant store_ea_data : integer := 45; -- + constant addrlong : integer := 46; -- + constant postadd : integer := 47; -- + constant presub : integer := 48; -- + constant subidx : integer := 49; -- + constant no_Flags : integer := 50; -- + constant use_SP : integer := 51; -- + constant to_CCR : integer := 52; -- + constant to_SR : integer := 53; -- + constant OP2out_one : integer := 54; -- + constant OP1out_zero : integer := 55; -- + constant mem_addsub : integer := 56; -- + constant addsub : integer := 57; -- + constant directPC : integer := 58; -- + constant direct_delta : integer := 59; -- + constant directSR : integer := 60; -- + constant directCCR : integer := 61; -- + constant exg : integer := 62; -- + constant get_ea_now : integer := 63; -- + constant ea_to_pc : integer := 64; -- + constant hold_dwr : integer := 65; -- + constant to_USP : integer := 66; -- + constant from_USP : integer := 67; -- + constant write_lowlong : integer := 68; -- + constant write_reminder : integer := 69; -- + constant movem_action : integer := 70; -- + constant briefext : integer := 71; -- + constant get_2ndOPC : integer := 72; -- + constant mem_byte : integer := 73; -- + constant longaktion : integer := 74; -- + constant opcRESET : integer := 75; -- + constant opcBF : integer := 76; -- + constant opcBFwb : integer := 77; -- + constant opcPACK : integer := 78; -- - --- constant : integer := 75; -- --- constant : integer := 76; -- --- constant : integer := 7; -- --- constant : integer := 7; -- --- constant : integer := 7; -- - - constant lastOpcBit : integer := 77; + constant lastOpcBit : integer := 78; type rTG68K_opc is record opcMOVE : bit; opcMOVEQ : bit; opcMOVESR : bit; + opcMOVECCR : bit; opcADD : bit; opcADDQ : bit; opcOR : bit; @@ -199,7 +193,7 @@ package TG68K_Pack is opcRESET : bit; opcBF : bit; opcBFwb : bit; - s2nd_hbits : bit; + opcPACK : bit; end record; component TG68K_ALU @@ -208,41 +202,42 @@ package TG68K_Pack is DIV_Mode : integer := 0 --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV, ); port( - clk : in std_logic; - Reset : in std_logic; - clkena_lw : in std_logic:='1'; - execOPC : in bit; - exe_condition : in std_logic; - exec_tas : in std_logic; - long_start : in bit; - movem_presub : in bit; - set_stop : in bit; - Z_error : in bit; - rot_bits : in std_logic_vector(1 downto 0); - exec : in bit_vector(lastOpcBit downto 0); - OP1out : in std_logic_vector(31 downto 0); - OP2out : in std_logic_vector(31 downto 0); - reg_QA : in std_logic_vector(31 downto 0); - reg_QB : in std_logic_vector(31 downto 0); - opcode : in std_logic_vector(15 downto 0); - datatype : in std_logic_vector(1 downto 0); - exe_opcode : in std_logic_vector(15 downto 0); - exe_datatype : in std_logic_vector(1 downto 0); - sndOPC : in std_logic_vector(15 downto 0); - last_data_read : in std_logic_vector(15 downto 0); - data_read : in std_logic_vector(15 downto 0); - FlagsSR : in std_logic_vector(7 downto 0); - micro_state : in micro_states; - bf_ext_in : in std_logic_vector(7 downto 0); + clk : in std_logic; + Reset : in std_logic; + clkena_lw : in std_logic:='1'; + execOPC : in bit; + exe_condition : in std_logic; + exec_tas : in std_logic; + long_start : in bit; + non_aligned : in std_logic; + movem_presub : in bit; + set_stop : in bit; + Z_error : in bit; + rot_bits : in std_logic_vector(1 downto 0); + rot_cnt : in std_logic_vector(5 downto 0); + exec : in bit_vector(lastOpcBit downto 0); + OP1out : in std_logic_vector(31 downto 0); + OP2out : in std_logic_vector(31 downto 0); + reg_QA : in std_logic_vector(31 downto 0); + reg_QB : in std_logic_vector(31 downto 0); + opcode : in std_logic_vector(15 downto 0); + datatype : in std_logic_vector(1 downto 0); + exe_opcode : in std_logic_vector(15 downto 0); + exe_datatype : in std_logic_vector(1 downto 0); + sndOPC : in std_logic_vector(15 downto 0); + last_data_read : in std_logic_vector(15 downto 0); + data_read : in std_logic_vector(15 downto 0); + FlagsSR : in std_logic_vector(7 downto 0); + micro_state : in micro_states; + bf_ext_in : in std_logic_vector(7 downto 0); bf_ext_out : out std_logic_vector(7 downto 0); - bf_shift : in std_logic_vector(5 downto 0); - bf_width : in std_logic_vector(5 downto 0); - bf_loffset : in std_logic_vector(4 downto 0); - - set_V_Flag : buffer bit; - Flags : buffer std_logic_vector(7 downto 0); - c_out : buffer std_logic_vector(2 downto 0); - addsub_q : buffer std_logic_vector(31 downto 0); + bf_width : in std_logic_vector(4 downto 0); + bf_loffset : in std_logic_vector(4 downto 0); + bf_offset : in std_logic_vector(31 downto 0); + set_V_Flag_out : out bit; + Flags_out : out std_logic_vector(7 downto 0); + c_out_out : out std_logic_vector(2 downto 0); + addsub_q_out : out std_logic_vector(31 downto 0); ALUout : out std_logic_vector(31 downto 0) ); end component; diff --git a/cores/mist/TG68KdotC_Kernel.vhd b/cores/mist/TG68KdotC_Kernel.vhd index 75f80b1..c46a746 100644 --- a/cores/mist/TG68KdotC_Kernel.vhd +++ b/cores/mist/TG68KdotC_Kernel.vhd @@ -1,23 +1,23 @@ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ --- -- --- Copyright (c) 2009-2013 Tobias Gubener -- +-- -- +-- Copyright (c) 2009-2013 Tobias Gubener -- -- Patches by MikeJ, Till Harbaum, Rok Krajnk, ... -- --- Subdesign fAMpIGA by TobiFlex -- --- -- +-- Subdesign fAMpIGA by TobiFlex -- +-- -- -- This source file is free software: you can redistribute it and/or modify -- --- it under the terms of the GNU General Public License as published -- --- by the Free Software Foundation, either version 3 of the License, or -- --- (at your option) any later version. -- --- -- --- This source file is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of -- --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- --- GNU General Public License for more details. -- --- -- --- You should have received a copy of the GNU General Public License -- +-- it under the terms of the GNU General Public License as published -- +-- by the Free Software Foundation, either version 3 of the License, or -- +-- (at your option) any later version. -- +-- -- +-- This source file is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of -- +-- MERCHANTABILITY or FITNESS For A PARTICULAR PURPOSE. See the -- +-- GNU General Public License for more details. -- +-- -- +-- You should have received a copy of the GNU General Public License -- -- along with this program. If not, see . -- --- -- +-- -- ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ @@ -50,3354 +50,3488 @@ -- extb.l library ieee; -use ieee.std_logic_1164.all; -use ieee.std_logic_unsigned.all; -use work.TG68K_Pack.all; +use ieee.std_logic_1164.ALL; +use ieee.std_logic_unsigned.ALL; +use work.TG68K_Pack.ALL; entity TG68KdotC_Kernel is - generic( - SR_Read : integer := 0; --0=>user, 1=>privileged, 2=>switchable with CPU(0) - VBR_Stackframe : integer := 0; --0=>no, 1=>yes/extended, 2=>switchable with CPU(0) - extAddr_Mode : integer := 0; --0=>no, 1=>yes, 2=>switchable with CPU(1) - MUL_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL, - DIV_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV, - BitField : integer := 0 --0=>no, 1=>yes, 2=>switchable with CPU(1) - ); - port(clk : in std_logic; - nReset : in std_logic; --low active - clkena_in : in std_logic:='1'; - data_in : in std_logic_vector(15 downto 0); - IPL : in std_logic_vector(2 downto 0):="111"; - IPL_autovector : in std_logic:='0'; - berr : in std_logic:='0'; -- only 68000 Stackpointer dummy - CPU : in std_logic_vector(1 downto 0):="00"; -- 00->68000 01->68010 11->68020(only some parts - yet) - addr : buffer std_logic_vector(31 downto 0); - data_write : buffer std_logic_vector(15 downto 0); - nWr : out std_logic; - nUDS : out std_logic; - nLDS : out std_logic; - busstate : out std_logic_vector(1 downto 0); -- 00-> fetch code 10->read data 11->write data 01->no memaccess - nResetOut : out std_logic; - FC : out std_logic_vector(2 downto 0); - clr_berr : out std_logic; --- for debug - skipFetch : out std_logic; - regin : buffer std_logic_vector(31 downto 0); - CACR_out : buffer std_logic_vector(3 downto 0); - VBR_out : buffer std_logic_vector(31 downto 0) - ); + generic ( + SR_Read : integer := 0; --0=>user, 1=>privileged, 2=>switchable with CPU(0) + VBR_Stackframe : integer := 0; --0=>no, 1=>yes/extended, 2=>switchable with CPU(0) + extAddr_Mode : integer := 0; --0=>no, 1=>yes, 2=>switchable with CPU(1) + MUL_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL, + DIV_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV, + BitField : integer := 0 --0=>no, 1=>yes, 2=>switchable with CPU(1) + ); + port ( + clk : in std_logic; + nReset : in std_logic; --low active + clkena_in : in std_logic := '1'; + data_in : in std_logic_vector(15 downto 0); + IPL : in std_logic_vector( 2 downto 0) := "111"; + IPL_autovector : in std_logic := '1'; -- ACTIVE LOW + berr : in std_logic :='0'; -- only 68000 Stackpointer dummy + CPU : in std_logic_vector( 1 downto 0) := "00"; -- 00->68000 01->68010 11->68020(only some parts - yet) + addr_out : out std_logic_vector(31 downto 0); + data_write : out std_logic_vector(15 downto 0); + nWr : out std_logic; + nUDS : out std_logic; + nLDS : out std_logic; + busstate : out std_logic_vector(1 downto 0); -- 00-> fetch code 10->read data 11->write data 01->no memaccess + nResetOut : out std_logic; + FC : out std_logic_vector(2 downto 0); + clr_berr : out std_logic; + -- for debug + skipFetch : out std_logic; + regin_out : out std_logic_vector(31 downto 0); + CACR_out : out std_logic_vector( 3 downto 0); + VBR_out : out std_logic_vector(31 downto 0) + ); end TG68KdotC_Kernel; --nBS : std_logic_vector(3 downto 0); -- nBS0 is 31..24 3 is 7..0, active LOW --SIZ : std_logic_vector(1 downto 0); --ACK for 16/32 bit transfer? architecture logic of TG68KdotC_Kernel is + signal syncReset : std_logic_vector(3 downto 0); + signal Reset : std_logic; + signal clkena_lw : std_logic; + signal TG68_PC : std_logic_vector(31 downto 0); + signal tmp_TG68_PC : std_logic_vector(31 downto 0); + signal TG68_PC_add : std_logic_vector(31 downto 0); + signal PC_dataa : std_logic_vector(31 downto 0); + signal PC_datab : std_logic_vector(31 downto 0); + signal memaddr : std_logic_vector(31 downto 0); + signal state : std_logic_vector(1 downto 0); + signal datatype : std_logic_vector(1 downto 0); + signal set_datatype : std_logic_vector(1 downto 0); + signal exe_datatype : std_logic_vector(1 downto 0); + signal setstate : std_logic_vector(1 downto 0); + signal opcode : std_logic_vector(15 downto 0); + signal exe_opcode : std_logic_vector(15 downto 0); + signal exe_pc : std_logic_vector(31 downto 0); + signal last_opc_pc : std_logic_vector(31 downto 0); + signal sndOPC : std_logic_vector(15 downto 0); + signal last_opc_read : std_logic_vector(15 downto 0); + signal reg_QA : std_logic_vector(31 downto 0); + signal reg_QB : std_logic_vector(31 downto 0); + signal Wwrena : bit; + signal Lwrena : bit; + signal Bwrena : bit; + signal Regwrena_now : bit; + signal rf_dest_addr : std_logic_vector(3 downto 0); + signal rf_source_addr : std_logic_vector(3 downto 0); + signal rf_source_addrd : std_logic_vector(3 downto 0); - signal syncReset : std_logic_vector(3 downto 0); - signal Reset : std_logic; - signal clkena_lw : std_logic; - signal TG68_PC : std_logic_vector(31 downto 0); - signal tmp_TG68_PC : std_logic_vector(31 downto 0); - signal TG68_PC_add : std_logic_vector(31 downto 0); - signal PC_dataa : std_logic_vector(31 downto 0); - signal PC_datab : std_logic_vector(31 downto 0); - signal memaddr : std_logic_vector(31 downto 0); - signal state : std_logic_vector(1 downto 0); - signal datatype : std_logic_vector(1 downto 0); - signal set_datatype : std_logic_vector(1 downto 0); - signal exe_datatype : std_logic_vector(1 downto 0); - signal setstate : std_logic_vector(1 downto 0); + type regfile_t is ARRAY(0 TO 15) OF std_logic_vector(31 downto 0); + signal regfile : regfile_t := (OTHERS => (OTHERS => '0')); -- mikej stops sim X issues; + signal RDindex_A : integer range 0 TO 15; + signal RDindex_B : integer range 0 TO 15; - signal opcode : std_logic_vector(15 downto 0); - signal exe_opcode : std_logic_vector(15 downto 0); - signal sndOPC : std_logic_vector(15 downto 0); + signal WR_AReg : std_logic; + signal addr : std_logic_vector(31 downto 0); + signal memaddr_reg : std_logic_vector(31 downto 0); + signal memaddr_delta : std_logic_vector(31 downto 0); + signal use_base : bit; + signal ea_data : std_logic_vector(31 downto 0); + signal OP1out : std_logic_vector(31 downto 0); + signal OP2out : std_logic_vector(31 downto 0); + signal OP1outbrief : std_logic_vector(15 downto 0); + signal OP1in : std_logic_vector(31 downto 0); + signal ALUout : std_logic_vector(31 downto 0); + signal data_write_tmp : std_logic_vector(31 downto 0); + signal data_write_muxin : std_logic_vector(31 downto 0); + signal data_write_mux : std_logic_vector(47 downto 0); + signal nextpass : bit; + signal setnextpass : bit; + signal setdispbyte : bit; + signal setdisp : bit; + signal regdirectsource : bit; -- checken !!! + signal addsub_q : std_logic_vector(31 downto 0); + signal briefdata : std_logic_vector(31 downto 0); - signal last_opc_read : std_logic_vector(15 downto 0); - signal registerin : std_logic_vector(31 downto 0); - signal reg_QA : std_logic_vector(31 downto 0); - signal reg_QB : std_logic_vector(31 downto 0); - signal Wwrena,Lwrena : bit; - signal Bwrena : bit; - signal Regwrena_now : bit; - signal rf_dest_addr : std_logic_vector(3 downto 0); - signal rf_source_addr : std_logic_vector(3 downto 0); - signal rf_source_addrd : std_logic_vector(3 downto 0); + signal c_out : std_logic_vector(2 downto 0); + signal mem_address : std_logic_vector(31 downto 0); + signal memaddr_a : std_logic_vector(31 downto 0); + signal TG68_PC_brw : bit; + signal TG68_PC_word : bit; + signal getbrief : bit; + signal brief : std_logic_vector(15 downto 0); + signal dest_areg : std_logic; + signal source_areg : std_logic; + signal data_is_source : bit; + signal store_in_tmp : bit; + signal write_back : bit; + signal exec_write_back : bit; + signal setstackaddr : bit; + signal writePC : bit; + signal writePCbig : bit; + signal set_writePCbig : bit; + signal setopcode : bit; + signal decodeOPC : bit; + signal execOPC : bit; + signal setexecOPC : bit; + signal endOPC : bit; + signal setendOPC : bit; + signal Flags : std_logic_vector(7 downto 0); -- ...XNZVC + signal FlagsSR : std_logic_vector(7 downto 0) := (others => '0'); -- T.S..III + signal SRin : std_logic_vector(7 downto 0); + signal exec_DIRECT : bit; + signal exec_tas : std_logic; + signal set_exec_tas : std_logic; + signal exe_condition : std_logic; + signal ea_only : bit; + signal source_lowbits : bit; + signal source_2ndHbits : bit; + signal source_2ndLbits : bit; + signal dest_2ndHbits : bit; + signal dest_hbits : bit; + signal rot_bits : std_logic_vector(1 downto 0); + signal set_rot_bits : std_logic_vector(1 downto 0); + signal alu_rot_cnt : std_logic_vector(5 downto 0); + signal set_alu_rot_cnt : std_logic_vector(5 downto 0); + signal rot_cnt : std_logic_vector(5 downto 0); + signal set_rot_cnt : std_logic_vector(5 downto 0); + signal movem_actiond : bit; + signal movem_regaddr : std_logic_vector(3 downto 0); + signal movem_mux : std_logic_vector(3 downto 0); + signal movem_presub : bit; + signal movem_run : bit; + signal ea_calc_b : std_logic_vector(31 downto 0); + signal set_direct_data : bit; + signal use_direct_data : bit; + signal direct_data : bit; - type regfile_t is array(0 to 15) of std_logic_vector(31 downto 0); - signal regfile : regfile_t := (others => (others =>'0')); -- mikej stops sim X issues; - signal RDindex_A : integer range 0 to 15; - signal RDindex_B : integer range 0 to 15; - signal WR_AReg : std_logic; + signal set_V_Flag : bit; + signal set_vectoraddr : bit; + signal writeSR : bit; + signal trap_berr : bit; + signal trap_illegal : bit; + signal trap_addr_error : bit; + signal trap_priv : bit; + signal trap_trace : bit; + signal trap_1010 : bit; + signal trap_1111 : bit; + signal trap_trap : bit; + signal trap_trapv : bit; + signal trap_interrupt : bit; + signal trapmake : bit; + signal trapd : bit; + signal trap_SR : std_logic_vector(7 downto 0); + signal make_trace : std_logic; + signal make_berr : std_logic; + signal set_stop : bit; + signal stop : bit; + signal trap_vector : std_logic_vector(31 downto 0); + signal trap_vector_vbr : std_logic_vector(31 downto 0); + signal USP : std_logic_vector(31 downto 0); + signal illegal_write_mode : bit; + signal illegal_read_mode : bit; + signal illegal_byteaddr : bit; - signal memaddr_reg : std_logic_vector(31 downto 0); - signal memaddr_delta : std_logic_vector(31 downto 0); - signal use_base : bit; + signal IPL_nr : std_logic_vector(2 downto 0); + signal rIPL_nr : std_logic_vector(2 downto 0); + signal IPL_vec : std_logic_vector(7 downto 0); + signal interrupt : bit; + signal setinterrupt : bit; + signal SVmode : std_logic; + signal preSVmode : std_logic; + signal Suppress_Base : bit; + signal set_Suppress_Base : bit; + signal set_Z_error : bit; + signal Z_error : bit; + signal ea_build_now : bit; + signal build_logical : bit; + signal build_bcd : bit; - signal ea_data : std_logic_vector(31 downto 0); - signal OP1out : std_logic_vector(31 downto 0); - signal OP2out : std_logic_vector(31 downto 0); - signal OP1outbrief : std_logic_vector(15 downto 0); - signal OP1in : std_logic_vector(31 downto 0); - signal ALUout : std_logic_vector(31 downto 0); - signal data_write_tmp : std_logic_vector(31 downto 0); - signal data_write_muxin : std_logic_vector(31 downto 0); - signal data_write_mux : std_logic_vector(47 downto 0); - signal nextpass : bit; - signal setnextpass : bit; - signal setdispbyte : bit; - signal setdisp : bit; - signal regdirectsource : bit; -- checken !!! - signal addsub_q : std_logic_vector(31 downto 0); - signal briefdata : std_logic_vector(31 downto 0); --- signal c_in : std_logic_vector(3 downto 0); - signal c_out : std_logic_vector(2 downto 0); + signal data_read : std_logic_vector(31 downto 0); + signal bf_ext_in : std_logic_vector(7 downto 0); + signal bf_ext_out : std_logic_vector(7 downto 0); + signal byte : bit; + signal long_start : bit; + signal long_start_alu : bit; + signal non_aligned : std_logic; + signal long_done : bit; + signal memmask : std_logic_vector(5 downto 0); + signal set_memmask : std_logic_vector(5 downto 0); + signal memread : std_logic_vector(3 downto 0); + signal wbmemmask : std_logic_vector(5 downto 0); + signal memmaskmux : std_logic_vector(5 downto 0); + signal oddout : std_logic; + signal set_oddout : std_logic; + signal PCbase : std_logic; + signal set_PCbase : std_logic; - signal mem_address : std_logic_vector(31 downto 0); - signal memaddr_a : std_logic_vector(31 downto 0); + signal last_data_read : std_logic_vector(31 downto 0); + signal last_data_in : std_logic_vector(31 downto 0); - signal TG68_PC_brw : bit; - signal TG68_PC_word : bit; - signal getbrief : bit; - signal brief : std_logic_vector(15 downto 0); - signal dest_areg : std_logic; - signal source_areg : std_logic; - signal data_is_source : bit; - signal store_in_tmp : bit; - signal write_back : bit; - signal exec_write_back : bit; - signal setstackaddr : bit; - signal writePC : bit; - signal writePCbig : bit; - signal set_writePCbig : bit; - signal setopcode : bit; - signal decodeOPC : bit; - signal execOPC : bit; - signal setexecOPC : bit; - signal endOPC : bit; - signal setendOPC : bit; - signal Flags : std_logic_vector(7 downto 0); -- ...XNZVC - signal FlagsSR : std_logic_vector(7 downto 0); -- T.S..III - signal SRin : std_logic_vector(7 downto 0); - signal exec_DIRECT : bit; - signal exec_tas : std_logic; - signal set_exec_tas : std_logic; + signal bf_offset : std_logic_vector(31 downto 0); + signal bf_offset_l : std_logic_vector(4 downto 0); + signal bf_loffset : std_logic_vector(4 downto 0); + signal bf_width : std_logic_vector(4 downto 0); + signal bf_bhits : std_logic_vector(5 downto 0); + signal alu_bf_width : std_logic_vector(4 downto 0); + signal alu_bf_offset : std_logic_vector(31 downto 0); + signal alu_bf_loffset : std_logic_vector(4 downto 0); - signal exe_condition : std_logic; - signal ea_only : bit; - signal source_lowbits : bit; - signal source_2ndHbits : bit; - signal source_2ndLbits : bit; - signal dest_2ndHbits : bit; - signal dest_hbits : bit; - signal rot_bits : std_logic_vector(1 downto 0); - signal set_rot_bits : std_logic_vector(1 downto 0); - signal rot_cnt : std_logic_vector(5 downto 0); - signal set_rot_cnt : std_logic_vector(5 downto 0); - signal movem_actiond : bit; - signal movem_regaddr : std_logic_vector(3 downto 0); - signal movem_mux : std_logic_vector(3 downto 0); - signal movem_presub : bit; - signal movem_run : bit; - signal ea_calc_b : std_logic_vector(31 downto 0); - signal set_direct_data : bit; - signal use_direct_data : bit; - signal direct_data : bit; + signal movec_data : std_logic_vector(31 downto 0); + signal VBR : std_logic_vector(31 downto 0); + signal CACR : std_logic_vector(3 downto 0); + signal DFC : std_logic_vector(2 downto 0); + signal SFC : std_logic_vector(2 downto 0); + signal set : bit_vector(lastOpcBit downto 0); + signal set_exec : bit_vector(lastOpcBit downto 0); + signal exec : bit_vector(lastOpcBit downto 0); + signal exec_d : rTG68K_opc; - signal set_V_Flag : bit; - signal set_vectoraddr : bit; - signal writeSR : bit; - signal trap_berr : bit; - signal trap_illegal : bit; - signal trap_addr_error : bit; - signal trap_priv : bit; - signal trap_trace : bit; - signal trap_1010 : bit; - signal trap_1111 : bit; - signal trap_trap : bit; - signal trap_trapv : bit; - signal trap_interrupt : bit; - signal trapmake : bit; - signal trapd : bit; - signal trap_SR : std_logic_vector(7 downto 0); - signal make_trace : std_logic; - signal make_berr : std_logic; + signal micro_state : micro_states; + signal next_micro_state : micro_states; - signal set_stop : bit; - signal stop : bit; - signal trap_vector : std_logic_vector(31 downto 0); - signal trap_vector_vbr : std_logic_vector(31 downto 0); - signal USP : std_logic_vector(31 downto 0); - signal illegal_write_mode : bit; - signal illegal_read_mode : bit; - signal illegal_byteaddr : bit; + signal regin : std_logic_vector(31 downto 0); - signal IPL_nr : std_logic_vector(2 downto 0); - signal rIPL_nr : std_logic_vector(2 downto 0); - signal IPL_vec : std_logic_vector(7 downto 0); - signal interrupt : bit; - signal setinterrupt : bit; - signal SVmode : std_logic; - signal preSVmode : std_logic; - signal Suppress_Base : bit; - signal set_Suppress_Base : bit; - signal set_Z_error : bit; - signal Z_error : bit; - signal ea_build_now : bit; - signal build_logical : bit; - signal build_bcd : bit; +begin - signal data_read : std_logic_vector(31 downto 0); - signal bf_ext_in : std_logic_vector(7 downto 0); - signal bf_ext_out : std_logic_vector(7 downto 0); - signal byte : bit; - signal long_start : bit; - signal long_start_alu : bit; - signal long_done : bit; - signal memmask : std_logic_vector(5 downto 0); - signal set_memmask : std_logic_vector(5 downto 0); - signal memread : std_logic_vector(3 downto 0); - signal wbmemmask : std_logic_vector(5 downto 0); - signal memmaskmux : std_logic_vector(5 downto 0); - signal oddout : std_logic; - signal set_oddout : std_logic; - signal PCbase : std_logic; - signal set_PCbase : std_logic; + ALU : TG68K_ALU + generic map( + MUL_Mode => MUL_Mode, --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL, + DIV_Mode => DIV_Mode --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV, + ) + port map( + clk => clk, --: in std_logic; + Reset => Reset, --: in std_logic; + clkena_lw => clkena_lw, --: in std_logic:='1'; + execOPC => execOPC, --: in bit; + exe_condition => exe_condition, --: in std_logic; + exec_tas => exec_tas, --: in std_logic; + long_start => long_start_alu, --: in bit; + non_aligned => non_aligned, + movem_presub => movem_presub, --: in bit; + set_stop => set_stop, --: in bit; + Z_error => Z_error, --: in bit; + rot_bits => rot_bits, --: in std_logic_vector(1 downto 0); + rot_cnt => alu_rot_cnt, --: in std_logic_vector(5 downto 0); + exec => exec, --: in bit_vector(lastOpcBit downto 0); + OP1out => OP1out, --: in std_logic_vector(31 downto 0); + OP2out => OP2out, --: in std_logic_vector(31 downto 0); + reg_QA => reg_QA, --: in std_logic_vector(31 downto 0); + reg_QB => reg_QB, --: in std_logic_vector(31 downto 0); + opcode => opcode, --: in std_logic_vector(15 downto 0); + datatype => datatype, --: in std_logic_vector(1 downto 0); + exe_opcode => exe_opcode, --: in std_logic_vector(15 downto 0); + exe_datatype => exe_datatype, --: in std_logic_vector(1 downto 0); + sndOPC => sndOPC, --: in std_logic_vector(15 downto 0); + last_data_read => last_data_read(15 downto 0), --: in std_logic_vector(31 downto 0); + data_read => data_read(15 downto 0), --: in std_logic_vector(31 downto 0); + FlagsSR => FlagsSR, --: in std_logic_vector(7 downto 0); + micro_state => micro_state, --: in micro_states; + bf_ext_in => bf_ext_in, + bf_ext_out => bf_ext_out, + bf_width => alu_bf_width, + bf_offset => alu_bf_offset, + bf_loffset => alu_bf_loffset, + set_V_Flag_out => set_V_Flag, --: buffer bit; + Flags_out => Flags, --: buffer std_logic_vector(8 downto 0); + c_out_out => c_out, --: buffer std_logic_vector(2 downto 0); + addsub_q_out => addsub_q, --: buffer std_logic_vector(31 downto 0); + ALUout => ALUout --: buffer std_logic_vector(31 downto 0) + ); - signal last_data_read : std_logic_vector(31 downto 0); - signal last_data_in : std_logic_vector(31 downto 0); + long_start_alu <= to_bit(not memmaskmux(3)); - signal bf_offset : std_logic_vector(5 downto 0); - signal bf_width : std_logic_vector(5 downto 0); - signal bf_bhits : std_logic_vector(5 downto 0); - signal bf_shift : std_logic_vector(5 downto 0); - signal alu_width : std_logic_vector(5 downto 0); - signal alu_bf_shift : std_logic_vector(5 downto 0); - signal bf_loffset : std_logic_vector(5 downto 0); - signal alu_bf_loffset : std_logic_vector(5 downto 0); + process (memmaskmux) + begin + non_aligned <= '0'; + if (memmaskmux(5 downto 4) = "01") or (memmaskmux(5 downto 4) = "10") then + non_aligned <= '1'; + end if; + end process; + ----------------------------------------------------------------------------- + -- Bus control + ----------------------------------------------------------------------------- + nWr <= '0' when state = "11" else '1'; + busstate <= state; + nResetOut <= '0' when exec(opcRESET) = '1' else '1'; - signal movec_data : std_logic_vector(31 downto 0); - signal VBR : std_logic_vector(31 downto 0); - signal CACR : std_logic_vector(3 downto 0); - signal DFC : std_logic_vector(2 downto 0); - signal SFC : std_logic_vector(2 downto 0); + -- does shift for byte access. note active low me + -- should produce address error on 68000 + memmaskmux <= memmask when addr(0) = '1' else memmask(4 downto 0) & '1'; + nUDS <= memmaskmux(5); + nLDS <= memmaskmux(4); + clkena_lw <= '1' when clkena_in = '1' and memmaskmux(3) = '1' else '0'; -- step + clr_berr <= '1' WHEN setopcode='1' AND trap_berr='1' ELSE '0'; - signal set : bit_vector(lastOpcBit downto 0); - signal set_exec : bit_vector(lastOpcBit downto 0); - signal exec : bit_vector(lastOpcBit downto 0); - signal exec_d : rTG68K_opc; + process (clk, nReset) + begin + if nReset = '0' then + syncReset <= "0000"; + Reset <= '1'; + elsif rising_edge(clk) then + if clkena_in = '1' then + syncReset <= syncReset(2 downto 0) & '1'; + Reset <= not syncReset(3); + end if; + end if; + end process; - signal micro_state : micro_states; - signal next_micro_state : micro_states; + process (clk, long_done, last_data_in, data_in, byte, addr, long_start, memmaskmux, memread, memmask, data_read) + begin + if memmaskmux(4) = '0' then + data_read <= last_data_in(15 downto 0) & data_in; + else + data_read <= last_data_in(23 downto 0) & data_in(15 downto 8); + end if; + if memread(0) = '1' or (memread(1 downto 0) = "10" and memmaskmux(4) = '1') then + data_read(31 downto 16) <= (others => data_read(15)); + end if; -BEGIN -ALU: TG68K_ALU - generic map( - MUL_Mode => MUL_Mode, --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL, - DIV_Mode => DIV_Mode --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV, - ) - port map( - clk => clk, --: in std_logic; - Reset => Reset, --: in std_logic; - clkena_lw => clkena_lw, --: in std_logic:='1'; - execOPC => execOPC, --: in bit; - exe_condition => exe_condition, --: in std_logic; - exec_tas => exec_tas, --: in std_logic; - long_start => long_start_alu, --: in bit; - movem_presub => movem_presub, --: in bit; - set_stop => set_stop, --: in bit; - Z_error => Z_error, --: in bit; - rot_bits => rot_bits, --: in std_logic_vector(1 downto 0); - exec => exec, --: in bit_vector(lastOpcBit downto 0); - OP1out => OP1out, --: in std_logic_vector(31 downto 0); - OP2out => OP2out, --: in std_logic_vector(31 downto 0); - reg_QA => reg_QA, --: in std_logic_vector(31 downto 0); - reg_QB => reg_QB, --: in std_logic_vector(31 downto 0); - opcode => opcode, --: in std_logic_vector(15 downto 0); - datatype => datatype, --: in std_logic_vector(1 downto 0); - exe_opcode => exe_opcode, --: in std_logic_vector(15 downto 0); - exe_datatype => exe_datatype, --: in std_logic_vector(1 downto 0); - sndOPC => sndOPC, --: in std_logic_vector(15 downto 0); - last_data_read => last_data_read(15 downto 0), --: in std_logic_vector(31 downto 0); - data_read => data_read(15 downto 0), --: in std_logic_vector(31 downto 0); - FlagsSR => FlagsSR, --: in std_logic_vector(7 downto 0); - micro_state => micro_state, --: in micro_states; - bf_ext_in => bf_ext_in, - bf_ext_out => bf_ext_out, - bf_shift => alu_bf_shift, - bf_width => alu_width, - bf_loffset => alu_bf_loffset(4 downto 0), - set_V_Flag => set_V_Flag, --: buffer bit; - Flags => Flags, --: buffer std_logic_vector(8 downto 0); - c_out => c_out, --: buffer std_logic_vector(2 downto 0); - addsub_q => addsub_q, --: buffer std_logic_vector(31 downto 0); - ALUout => ALUout --: buffer std_logic_vector(31 downto 0) - ); + if rising_edge(clk) then + if clkena_lw = '1' and state = "10" then + if memmaskmux(4) = '0' then + bf_ext_in <= last_data_in(23 downto 16); + else + bf_ext_in <= last_data_in(31 downto 24); + end if; + end if; - long_start_alu <= to_bit(NOT memmaskmux(3)); ------------------------------------------------------------------------------ --- Bus control ------------------------------------------------------------------------------ - nWr <= '0' WHEN state="11" ELSE '1'; - busstate <= state; - nResetOut <= '0' WHEN exec(opcRESET)='1' ELSE '1'; + if Reset = '1' then + last_data_read <= (others => '0'); + elsif clkena_in = '1' then + if state = "00" or exec(update_ld) = '1' then + last_data_read <= data_read; + if state(1) = '0' and memmask(1) = '0' then + last_data_read(31 downto 16) <= last_opc_read; + elsif state(1) = '0' or memread(1) = '1' then + last_data_read(31 downto 16) <= (others => data_in(15)); + end if; + end if; + last_data_in <= last_data_in(15 downto 0) & data_in(15 downto 0); - -- does shift for byte access. Note active low me - -- should produce address error on 68000 - memmaskmux <= memmask WHEN addr(0)='1' ELSE memmask(4 downto 0)&'1'; + end if; + end if; + long_start <= to_bit(not memmask(1)); + long_done <= to_bit(not memread(1)); + end process; - nUDS <= memmaskmux(5); - nLDS <= memmaskmux(4); - clkena_lw <= '1' WHEN clkena_in='1' AND memmaskmux(3)='1' ELSE '0'; -- step - clr_berr <= '1' WHEN setopcode='1' AND trap_berr='1' ELSE '0'; + process (byte, long_start, reg_QB, data_write_tmp, exec, data_read, data_write_mux, memmaskmux, bf_ext_out, + data_write_muxin, memmask, oddout, addr) + begin + if exec(write_reg) = '1' then + data_write_muxin <= reg_QB; -- 32 bits + else + data_write_muxin <= data_write_tmp; + end if; - PROCESS (clk, nReset) - BEGIN - IF nReset='0' THEN - syncReset <= "0000"; - Reset <= '1'; - ELSIF rising_edge(clk) THEN - IF clkena_in='1' THEN - syncReset <= syncReset(2 downto 0)&'1'; - Reset <= NOT syncReset(3); - END IF; - END IF; - END PROCESS; + if BitField = 0 then + if oddout = addr(0) then + data_write_mux <= "XXXXXXXX" & "XXXXXXXX" & data_write_muxin; + else + data_write_mux <= "XXXXXXXX" & data_write_muxin & "XXXXXXXX"; + end if; + else + if oddout = addr(0) then + data_write_mux <= "XXXXXXXX" & bf_ext_out & data_write_muxin; + else + data_write_mux <= bf_ext_out & data_write_muxin & "XXXXXXXX"; + end if; + end if; -PROCESS (clk, long_done, last_data_in, data_in, byte, addr, long_start, memmaskmux, memread, memmask, data_read) - BEGIN - IF memmaskmux(4)='0' THEN - data_read <= last_data_in(15 downto 0)&data_in; - ELSE - data_read <= last_data_in(23 downto 0)&data_in(15 downto 8); - END IF; - IF memread(0)='1' OR (memread(1 downto 0)="10" AND memmaskmux(4)='1')THEN - data_read(31 downto 16) <= (OTHERS=>data_read(15)); - END IF; + if memmaskmux(1) = '0' then + data_write <= data_write_mux(47 downto 32); + elsif memmaskmux(3) = '0' then + data_write <= data_write_mux(31 downto 16); + else + data_write <= data_write_mux(15 downto 0); + end if; - IF rising_edge(clk) THEN - IF clkena_lw='1' AND state="10" THEN - IF memmaskmux(4)='0' THEN - bf_ext_in <= last_data_in(23 downto 16); - ELSE - bf_ext_in <= last_data_in(31 downto 24); - END IF; - END IF; - IF Reset='1' THEN - last_data_read <= (OTHERS => '0'); - ELSIF clkena_in='1' THEN - IF state="00" OR exec(update_ld)='1' THEN - last_data_read <= data_read; - IF state(1)='0' AND memmask(1)='0' THEN - last_data_read(31 downto 16) <= last_opc_read; - ELSIF state(1)='0' OR memread(1)='1' THEN - last_data_read(31 downto 16) <= (OTHERS=>data_in(15)); - END IF; - END IF; - last_data_in <= last_data_in(15 downto 0)&data_in(15 downto 0); + if exec(mem_byte) = '1' then --movep + data_write(7 downto 0) <= data_write_tmp(15 downto 8); + end if; + end process; - END IF; - END IF; - long_start <= to_bit(NOT memmask(1)); - long_done <= to_bit(NOT memread(1)); - END PROCESS; + ----------------------------------------------------------------------------- + -- Registerfile + ----------------------------------------------------------------------------- + process (clk, regfile, RDindex_A, RDindex_B, exec) + begin + reg_QA <= regfile(RDindex_A); + reg_QB <= regfile(RDindex_B); + if rising_edge(clk) then + if clkena_lw = '1' then + rf_source_addrd <= rf_source_addr; + WR_AReg <= rf_dest_addr(3); + RDindex_A <= conv_integer(rf_dest_addr(3 downto 0)); + RDindex_B <= conv_integer(rf_source_addr(3 downto 0)); -PROCESS (byte, long_start, reg_QB, data_write_tmp, exec, data_read, data_write_mux, memmaskmux, bf_ext_out, - data_write_muxin, memmask, oddout, addr) - BEGIN - IF exec(write_reg)='1' THEN - data_write_muxin <= reg_QB; - ELSE - data_write_muxin <= data_write_tmp; - END IF; + if Wwrena = '1' then + regfile(RDindex_A) <= regin; + end if; - IF BitField=0 THEN - IF oddout=addr(0) THEN - data_write_mux <= "XXXXXXXX"&"XXXXXXXX"&data_write_muxin; - ELSE - data_write_mux <= "XXXXXXXX"&data_write_muxin&"XXXXXXXX"; - END IF; - ELSE - IF oddout=addr(0) THEN - data_write_mux <= "XXXXXXXX"&bf_ext_out&data_write_muxin; - ELSE - data_write_mux <= bf_ext_out&data_write_muxin&"XXXXXXXX"; - END IF; - END IF; + if exec(to_USP) = '1' then + USP <= reg_QA; + end if; + end if; + end if; + end process; - IF memmaskmux(1)='0' THEN - data_write <= data_write_mux(47 downto 32); - ELSIF memmaskmux(3)='0' THEN - data_write <= data_write_mux(31 downto 16); - ELSE - data_write <= data_write_mux(15 downto 0); - END IF; - IF exec(mem_byte)='1' THEN --movep - data_write(7 downto 0) <= data_write_tmp(15 downto 8); - END IF; - END PROCESS; + ----------------------------------------------------------------------------- + -- Write Reg + ----------------------------------------------------------------------------- + process (OP1in, reg_QA, Regwrena_now, Bwrena, Lwrena, exe_datatype, WR_AReg, movem_actiond, exec, ALUout, memaddr, memaddr_a, ea_only, USP, movec_data) + begin + regin <= ALUout; + if exec(save_memaddr) = '1' then -- only used for movem + regin <= memaddr; + elsif exec(get_ea_now) = '1' and ea_only = '1' then + regin <= memaddr_a; + elsif exec(from_USP) = '1' then + regin <= USP; + elsif exec(movec_rd) = '1' then + regin <= movec_data; + end if; ------------------------------------------------------------------------------ --- Registerfile ------------------------------------------------------------------------------ -PROCESS (clk, regfile, RDindex_A, RDindex_B, exec) - BEGIN - reg_QA <= regfile(RDindex_A); - reg_QB <= regfile(RDindex_B); - IF rising_edge(clk) THEN - IF clkena_lw='1' THEN - rf_source_addrd <= rf_source_addr; - WR_AReg <= rf_dest_addr(3); - RDindex_A <= conv_integer(rf_dest_addr(3 downto 0)); - RDindex_B <= conv_integer(rf_source_addr(3 downto 0)); - IF Wwrena='1' THEN - regfile(RDindex_A) <= regin; - END IF; + if Bwrena = '1' then + regin(15 downto 8) <= reg_QA(15 downto 8); + end if; + if Lwrena = '0' then + regin(31 downto 16) <= reg_QA(31 downto 16); + end if; - IF exec(to_USP)='1' THEN - USP <= reg_QA; - END IF; - END IF; - END IF; - END PROCESS; - ------------------------------------------------------------------------------ --- Write Reg ------------------------------------------------------------------------------ -PROCESS (OP1in, reg_QA, Regwrena_now, Bwrena, Lwrena, exe_datatype, WR_AReg, movem_actiond, exec, ALUout, memaddr, memaddr_a, ea_only, USP, movec_data) - BEGIN - regin <= ALUout; - IF exec(save_memaddr)='1' THEN - regin <= memaddr; - ELSIF exec(get_ea_now)='1' AND ea_only='1' THEN - regin <= memaddr_a; - ELSIF exec(from_USP)='1' THEN - regin <= USP; - ELSIF exec(movec_rd)='1' THEN - regin <= movec_data; - END IF; - - IF Bwrena='1' THEN - regin(15 downto 8) <= reg_QA(15 downto 8); - END IF; - IF Lwrena='0' THEN - regin(31 downto 16) <= reg_QA(31 downto 16); - END IF; - - Bwrena <= '0'; - Wwrena <= '0'; - Lwrena <= '0'; - IF exec(presub)='1' OR exec(postadd)='1' OR exec(changeMode)='1' THEN -- -(An)+ - Wwrena <= '1'; + Bwrena <= '0'; + Wwrena <= '0'; + Lwrena <= '0'; + if exec(presub) = '1' or exec(postadd) = '1' or exec(changeMode) = '1' then -- -(An)+ + Wwrena <= '1'; + Lwrena <= '1'; + elsif Regwrena_now = '1' then --dbcc + Wwrena <= '1'; + elsif exec(Regwrena) = '1' then --read (mem) + Wwrena <= '1'; + case exe_datatype is + when "00" => --BYTE + Bwrena <= '1'; + when "01" => --WorD + if WR_AReg = '1' or movem_actiond = '1' then Lwrena <= '1'; - ELSIF Regwrena_now='1' THEN --dbcc - Wwrena <= '1'; - ELSIF exec(Regwrena)='1' THEN --read (mem) - Wwrena <= '1'; - CASE exe_datatype IS - WHEN "00" => --BYTE - Bwrena <= '1'; - WHEN "01" => --WORD - IF WR_AReg='1' OR movem_actiond='1' THEN - Lwrena <='1'; - END IF; - WHEN OTHERS => --LONG - Lwrena <= '1'; - END CASE; - END IF; - END PROCESS; + end if; + when others => --LONG + Lwrena <= '1'; + end case; + end if; + end process; ------------------------------------------------------------------------------ --- set dest regaddr ------------------------------------------------------------------------------ -PROCESS (opcode, rf_source_addrd, brief, setstackaddr, dest_hbits, dest_areg, data_is_source, sndOPC, exec, set, dest_2ndHbits) - BEGIN - IF exec(movem_action) ='1' THEN - rf_dest_addr <= rf_source_addrd; - ELSIF set(briefext)='1' THEN - rf_dest_addr <= brief(15 downto 12); - ELSIF set(get_bfoffset)='1' THEN - rf_dest_addr <= sndOPC(9 downto 6); - ELSIF dest_2ndHbits='1' THEN - rf_dest_addr <= sndOPC(15 downto 12); - ELSIF set(write_reminder)='1' THEN - rf_dest_addr <= sndOPC(3 downto 0); - ELSIF setstackaddr='1' THEN - rf_dest_addr <= "1111"; - ELSIF dest_hbits='1' THEN - rf_dest_addr <= dest_areg&opcode(11 downto 9); - ELSE - IF opcode(5 downto 3)="000" OR data_is_source='1' THEN - rf_dest_addr <= dest_areg&opcode(2 downto 0); - ELSE - rf_dest_addr <= '1'&opcode(2 downto 0); - END IF; - END IF; - END PROCESS; + ----------------------------------------------------------------------------- + -- set dest regaddr + ----------------------------------------------------------------------------- + process (opcode, rf_source_addrd, brief, setstackaddr, dest_hbits, dest_areg, data_is_source, sndOPC, exec, set, dest_2ndHbits) + begin + if exec(movem_action) = '1' then + rf_dest_addr <= rf_source_addrd; + elsif set(briefext) = '1' then + rf_dest_addr <= brief(15 downto 12); + elsif set(get_bfoffset) = '1' then + rf_dest_addr <= sndOPC(9 downto 6); + elsif dest_2ndHbits = '1' then + rf_dest_addr <= sndOPC(15 downto 12); + elsif set(write_reminder) = '1' then + rf_dest_addr <= sndOPC(3 downto 0); + elsif setstackaddr = '1' then + rf_dest_addr <= "1111"; + elsif dest_hbits = '1' then + rf_dest_addr <= dest_areg & opcode(11 downto 9); + else + if opcode(5 downto 3) = "000" or data_is_source = '1' then + rf_dest_addr <= dest_areg & opcode(2 downto 0); + else + rf_dest_addr <= '1' & opcode(2 downto 0); + end if; + end if; + end process; ------------------------------------------------------------------------------ --- set source regaddr ------------------------------------------------------------------------------ -PROCESS (opcode, movem_presub, movem_regaddr, source_lowbits, source_areg, sndOPC, exec, set, source_2ndLbits, source_2ndHbits) - BEGIN - IF exec(movem_action)='1' OR set(movem_action) ='1' THEN - IF movem_presub='1' THEN - rf_source_addr <= movem_regaddr XOR "1111"; - ELSE - rf_source_addr <= movem_regaddr; - END IF; - ELSIF source_2ndLbits='1' THEN - rf_source_addr <= sndOPC(3 downto 0); - ELSIF source_2ndHbits='1' THEN - rf_source_addr <= sndOPC(15 downto 12); - ELSIF source_lowbits='1' THEN - rf_source_addr <= source_areg&opcode(2 downto 0); - ELSIF exec(linksp)='1' THEN - rf_source_addr <= "1111"; - ELSE - rf_source_addr <= source_areg&opcode(11 downto 9); - END IF; - END PROCESS; + ----------------------------------------------------------------------------- + -- set source regaddr + ----------------------------------------------------------------------------- + process (opcode, movem_presub, movem_regaddr, source_lowbits, source_areg, sndOPC, exec, set, source_2ndLbits, source_2ndHbits) + begin + if exec(movem_action) = '1' or set(movem_action) = '1' then + if movem_presub = '1' then + rf_source_addr <= movem_regaddr Xor "1111"; + else + rf_source_addr <= movem_regaddr; + end if; + elsif source_2ndLbits = '1' then + rf_source_addr <= sndOPC(3 downto 0); + elsif source_2ndHbits = '1' then + rf_source_addr <= sndOPC(15 downto 12); + elsif source_lowbits = '1' then + rf_source_addr <= source_areg & opcode(2 downto 0); + elsif exec(linksp) = '1' then + rf_source_addr <= "1111"; + else + rf_source_addr <= source_areg & opcode(11 downto 9); + end if; + end process; ------------------------------------------------------------------------------ --- set OP1out ------------------------------------------------------------------------------ -PROCESS (reg_QA, store_in_tmp, ea_data, long_start, addr, exec, memmaskmux) - BEGIN - OP1out <= reg_QA; - IF exec(OP1out_zero)='1' THEN - OP1out <= (OTHERS => '0'); - ELSIF exec(ea_data_OP1)='1' AND store_in_tmp='1' THEN - OP1out <= ea_data; - ELSIF exec(opcPACK)='1' THEN - OP1out <= data_write_tmp; - ELSIF exec(movem_action)='1' OR memmaskmux(3)='0' OR exec(OP1addr)='1' THEN - OP1out <= addr; - END IF; - END PROCESS; + ----------------------------------------------------------------------------- + -- set OP1out + ----------------------------------------------------------------------------- + process (reg_QA, store_in_tmp, ea_data, long_start, addr, exec, memmaskmux) + begin + OP1out <= reg_QA; + if exec(OP1out_zero) = '1' then + OP1out <= (others => '0'); + elsif exec(ea_data_OP1) = '1' and store_in_tmp = '1' then + OP1out <= ea_data; + elsif exec(opcPACK) = '1' then + OP1out <= data_write_tmp; + elsif exec(movem_action) = '1' or memmaskmux(3) = '0' or exec(OP1addr) = '1' then + OP1out <= addr; + end if; + end process; ------------------------------------------------------------------------------ --- set OP2out ------------------------------------------------------------------------------ -PROCESS (OP2out, reg_QB, exe_opcode, exe_datatype, execOPC, exec, use_direct_data, - store_in_tmp, data_write_tmp, ea_data) - BEGIN - OP2out(15 downto 0) <= reg_QB(15 downto 0); - OP2out(31 downto 16) <= (OTHERS => OP2out(15)); - IF exec(OP2out_one)='1' THEN - OP2out(15 downto 0) <= "1111111111111111"; - ELSIF exec(opcEXT)='1' THEN - IF exe_opcode(6)='0' OR exe_opcode(8)='1' THEN --ext.w - OP2out(15 downto 8) <= (OTHERS => OP2out(7)); - END IF; - ELSIF (use_direct_data='1' AND exec(opcPACK)='0') OR (exec(exg)='1' AND execOPC='1') OR exec(get_bfoffset)='1' THEN - OP2out <= data_write_tmp; - ELSIF (exec(ea_data_OP1)='0' AND store_in_tmp='1') OR exec(ea_data_OP2)='1' THEN - OP2out <= ea_data; - ELSIF exec(opcMOVEQ)='1' THEN - OP2out(7 downto 0) <= exe_opcode(7 downto 0); - OP2out(15 downto 8) <= (OTHERS => exe_opcode(7)); - ELSIF exec(opcADDQ)='1' THEN - OP2out(2 downto 0) <= exe_opcode(11 downto 9); - IF exe_opcode(11 downto 9)="000" THEN - OP2out(3) <='1'; - ELSE - OP2out(3) <='0'; - END IF; - OP2out(15 downto 4) <= (OTHERS => '0'); - ELSIF exe_datatype="10" THEN - OP2out(31 downto 16) <= reg_QB(31 downto 16); - END IF; - END PROCESS; + ----------------------------------------------------------------------------- + -- set OP2out + ----------------------------------------------------------------------------- + process ( OP2out, reg_QB, exe_opcode, exe_datatype, execOPC, exec, use_direct_data, store_in_tmp, data_write_tmp, ea_data) + begin + OP2out(15 downto 0) <= reg_QB(15 downto 0); + OP2out(31 downto 16) <= (others => OP2out(15)); + if exec(OP2out_one) = '1' then + OP2out(15 downto 0) <= "1111111111111111"; + elsif exec(opcEXT) = '1' then + if exe_opcode(6) = '0' or exe_opcode(8) = '1' then --ext.w + OP2out(15 downto 8) <= (others => OP2out(7)); + end if; ------------------------------------------------------------------------------ --- handle EA_data, data_write ------------------------------------------------------------------------------ -PROCESS (clk) - BEGIN - IF rising_edge(clk) THEN - IF Reset = '1' THEN - store_in_tmp <='0'; - exec_write_back <= '0'; - direct_data <= '0'; - use_direct_data <= '0'; - Z_error <= '0'; - ELSIF clkena_lw='1' THEN - direct_data <= '0'; - IF state="11" THEN - exec_write_back <= '0'; - ELSIF setstate="10" AND write_back='1' THEN - exec_write_back <= '1'; - END IF; + elsif (use_direct_data = '1' and exec(opcPACK) = '0') or (exec(exg) = '1' and execOPC = '1') or exec(get_bfoffset) = '1' then + OP2out <= data_write_tmp; + elsif (exec(ea_data_OP1) = '0' and store_in_tmp = '1') or exec(ea_data_OP2) = '1' then + OP2out <= ea_data; - IF set_direct_data='1' THEN - direct_data <= '1'; - IF set_exec(opcPACK)='1' THEN - use_direct_data <= '0'; - ELSE - use_direct_data <= '1'; - END IF; - ELSIF endOPC='1' THEN - use_direct_data <= '0'; - END IF; - exec_DIRECT <= set_exec(opcMOVE); + elsif exec(opcMOVEQ) = '1' then + OP2out(7 downto 0) <= exe_opcode(7 downto 0); + OP2out(15 downto 8) <= (others => exe_opcode(7)); - IF endOPC='1' THEN - store_in_tmp <='0'; - Z_error <= '0'; - ELSE - IF set_Z_error='1' THEN - Z_error <= '1'; - END IF; - IF set_exec(opcMOVE)='1' AND state="11" THEN - use_direct_data <= '1'; - END IF; + elsif exec(opcADDQ) = '1' then + OP2out(2 downto 0) <= exe_opcode(11 downto 9); + if exe_opcode(11 downto 9) = "000" then + OP2out(3) <= '1'; + else + OP2out(3) <= '0'; + end if; + OP2out(15 downto 4) <= (others => '0'); - IF state="10" THEN - store_in_tmp <= '1'; - END IF; - IF direct_data='1' AND state="00" THEN - store_in_tmp <= '1'; - END IF; - END IF; - IF state="10" THEN - ea_data <= data_read; - ELSIF exec(get_2ndOPC)='1' OR set_PCbase='1' THEN --TH cmpi (d16,PC) fix - ea_data <= addr; - ELSIF exec(store_ea_data)='1' OR (direct_data='1' AND state="00") THEN - ea_data <= last_data_read; - END IF; + elsif exe_datatype = "10" then + OP2out(31 downto 16) <= reg_QB(31 downto 16); + end if; + end process; - IF writePC='1' THEN - data_write_tmp <= TG68_PC; - ELSIF exec(writePC_add)='1' THEN - data_write_tmp <= TG68_PC_add; - ELSIF micro_state=trap0 THEN - data_write_tmp(15 downto 0) <= trap_vector(15 downto 0); - ELSIF exec(hold_dwr)='1' THEN - data_write_tmp <= data_write_tmp; - ELSIF exec(exg)='1' THEN - data_write_tmp <= OP1out; - ELSIF exec(get_ea_now)='1' AND ea_only='1' THEN -- ist for pea - data_write_tmp <= addr; - ELSIF execOPC='1' or micro_state=pack2 THEN - data_write_tmp <= ALUout; - ELSIF (exec_DIRECT='1' AND state="10") THEN - data_write_tmp <= data_read; - IF exec(movepl)='1' THEN - data_write_tmp(31 downto 8) <= data_write_tmp(23 downto 0); - END IF; - ELSIF exec(movepl)='1' THEN - data_write_tmp(15 downto 0) <= reg_QB(31 downto 16); - ELSIF direct_data='1' THEN - data_write_tmp <= last_data_read; - ELSIF writeSR='1'THEN - data_write_tmp(15 downto 0) <= trap_SR(7 downto 0)& Flags(7 downto 0); - ELSE - data_write_tmp <= OP2out; - END IF; - END IF; - END IF; - END PROCESS; + ----------------------------------------------------------------------------- + -- handle EA_data, data_write + ----------------------------------------------------------------------------- + process (clk) + begin + if rising_edge(clk) then + if Reset = '1' then + store_in_tmp <= '0'; + exec_write_back <= '0'; + direct_data <= '0'; + use_direct_data <= '0'; + Z_error <= '0'; + elsif clkena_lw = '1' then + direct_data <= '0'; ------------------------------------------------------------------------------ --- brief ------------------------------------------------------------------------------ -PROCESS (brief, OP1out, OP1outbrief, cpu) - BEGIN - IF brief(11)='1' THEN - OP1outbrief <= OP1out(31 downto 16); - ELSE - OP1outbrief <= (OTHERS=>OP1out(15)); - END IF; - briefdata <= OP1outbrief&OP1out(15 downto 0); - IF extAddr_Mode=1 OR (cpu(1)='1' AND extAddr_Mode=2) THEN - CASE brief(10 downto 9) IS -- mikej SCALE factor - WHEN "00" => briefdata <= OP1outbrief&OP1out(15 downto 0); - WHEN "01" => briefdata <= OP1outbrief(14 downto 0)&OP1out(15 downto 0)&'0'; - WHEN "10" => briefdata <= OP1outbrief(13 downto 0)&OP1out(15 downto 0)&"00"; - WHEN "11" => briefdata <= OP1outbrief(12 downto 0)&OP1out(15 downto 0)&"000"; - WHEN OTHERS => NULL; - END CASE; - END IF; - END PROCESS; + if state = "11" then + exec_write_back <= '0'; + elsif setstate = "10" and write_back = '1' then + exec_write_back <= '1'; + end if; ------------------------------------------------------------------------------ --- MEM_IO ------------------------------------------------------------------------------ -PROCESS (clk, setdisp, memaddr_a, briefdata, memaddr_delta, setdispbyte, datatype, interrupt, rIPL_nr, IPL_vec, - memaddr_reg, reg_QA, use_base, VBR, last_data_read, trap_vector, exec, set, cpu) - BEGIN + if set_direct_data = '1' then + direct_data <= '1'; + if set_exec(opcPACK) = '1' then + use_direct_data <= '0'; + else + use_direct_data <= '1'; + end if; + elsif endOPC = '1' then + use_direct_data <= '0'; + end if; + exec_DIRECT <= set_exec(opcMOVE); - IF rising_edge(clk) THEN - IF clkena_lw='1' THEN - trap_vector(31 downto 8) <= (others => '0'); - IF trap_berr='1' THEN - trap_vector(7 downto 0) <= X"08"; - END IF; - IF trap_addr_error='1' THEN - trap_vector(7 downto 0) <= X"0C"; - END IF; - IF trap_illegal='1' THEN - trap_vector(7 downto 0) <= X"10"; - END IF; - IF z_error='1' THEN - trap_vector(7 downto 0) <= X"14"; - END IF; - IF exec(trap_chk)='1' THEN - trap_vector(7 downto 0) <= X"18"; - END IF; - IF trap_trapv='1' THEN - trap_vector(7 downto 0) <= X"1C"; - END IF; - IF trap_priv='1' THEN - trap_vector(7 downto 0) <= X"20"; - END IF; - IF trap_trace='1' THEN - trap_vector(7 downto 0) <= X"24"; - END IF; - IF trap_1010='1' THEN - trap_vector(7 downto 0) <= X"28"; - END IF; - IF trap_1111='1' THEN - trap_vector(7 downto 0) <= X"2C"; - END IF; - IF trap_trap='1' THEN - trap_vector(7 downto 0) <= "10"&opcode(3 downto 0)&"00"; - END IF; - IF trap_interrupt='1' THEN - trap_vector(9 downto 0) <= IPL_vec & "00"; --TH - END IF; - -- TH TODO: non-autovector IRQs - END IF; - END IF; - IF VBR_Stackframe=0 OR (cpu(0)='0' AND VBR_Stackframe=2) THEN - trap_vector_vbr <= trap_vector; - ELSE - trap_vector_vbr <= trap_vector+VBR; - END IF; + if endOPC = '1' then + store_in_tmp <= '0'; + Z_error <= '0'; + else + if set_Z_error = '1' then + Z_error <= '1'; + end if; + if set_exec(opcMOVE) = '1' and state = "11" then + use_direct_data <= '1'; + end if; - memaddr_a(4 downto 0) <= "00000"; - memaddr_a(7 downto 5) <= (OTHERS=>memaddr_a(4)); - memaddr_a(15 downto 8) <= (OTHERS=>memaddr_a(7)); - memaddr_a(31 downto 16) <= (OTHERS=>memaddr_a(15)); - IF setdisp='1' THEN - IF exec(briefext)='1' THEN - memaddr_a <= briefdata+memaddr_delta; - ELSIF setdispbyte='1' THEN - memaddr_a(7 downto 0) <= last_data_read(7 downto 0); - ELSE - memaddr_a <= last_data_read; - END IF; - ELSIF set(presub)='1' THEN - IF set(longaktion)='1' THEN - memaddr_a(4 downto 0) <= "11100"; - ELSIF datatype="00" AND set(use_SP)='0' THEN - memaddr_a(4 downto 0) <= "11111"; - ELSE - memaddr_a(4 downto 0) <= "11110"; - END IF; - ELSIF interrupt='1' THEN - memaddr_a(4 downto 0) <= '1'&rIPL_nr&'0'; - END IF; + if state = "10" then + store_in_tmp <= '1'; + end if; + if direct_data = '1' and state = "00" then + store_in_tmp <= '1'; + end if; + end if; - IF rising_edge(clk) THEN - IF clkena_in='1' THEN - IF exec(get_2ndOPC)='1' OR (state="10" AND memread(0)='1') THEN - tmp_TG68_PC <= addr; - END IF; - use_base <= '0'; + if state = "10" then + ea_data <= data_read; + elsif exec(get_2ndOPC)='1' or set_PCbase='1' THEN --TH cmpi (d16,PC) fix + ea_data <= addr; + elsif exec(store_ea_data) = '1' or (direct_data = '1' and state = "00") then + ea_data <= last_data_read; + end if; - IF memmaskmux(3)='0' THEN - memaddr_delta <= addsub_q; - ELSIF exec(mem_addsub)='1' THEN - -- note, this should give an exception for 68000 - if exec(movem_action) = '1' and memmaskmux(3) = '1' and (memmaskmux(5 downto 4) = "10" or memmaskmux(5 downto 4) = "01") and (movem_presub = '0') then - memaddr_delta <= addr; -- hold for non-aligned case, only when incrementing - else - memaddr_delta <= addsub_q; - end if; - ELSIF state="01" AND exec_write_back='1' THEN - memaddr_delta <= tmp_TG68_PC; - ELSIF exec(direct_delta)='1' THEN - memaddr_delta <= data_read; - ELSIF exec(ea_to_pc)='1' AND setstate="00" THEN - memaddr_delta <= addr; - ELSIF set(addrlong)='1' THEN - memaddr_delta <= last_data_read; - ELSIF setstate="00" THEN - memaddr_delta <= TG68_PC_add; - ELSIF exec(dispouter)='1' THEN - memaddr_delta <= ea_data+memaddr_a; - ELSIF set_vectoraddr='1' THEN - memaddr_delta <= trap_vector_vbr; - ELSE - memaddr_delta <= memaddr_a; - IF interrupt='0' AND Suppress_Base='0' THEN --- IF interrupt='0' AND Suppress_Base='0' AND setstate(1)='1' THEN - use_base <= '1'; - END IF; - END IF; + if writePC = '1' then + data_write_tmp <= TG68_PC; + elsif exec(writePC_add) = '1' then + data_write_tmp <= TG68_PC_add; + elsif micro_state=trap00 THEN + data_write_tmp <= exe_pc; --TH + elsif micro_state = trap0 then + -- this is only active for 010+ since in 000 writePC is + -- true in state trap0 + if trap_trace='1' then + -- stack frame format #2 + data_write_tmp(15 downto 0) <= "0010" & trap_vector(11 downto 0); --TH + else + data_write_tmp(15 downto 0) <= "0000" & trap_vector(11 downto 0); + end if; + elsif exec(hold_dwr) = '1' then + data_write_tmp <= data_write_tmp; + elsif exec(exg) = '1' then + data_write_tmp <= OP1out; + elsif exec(get_ea_now) = '1' and ea_only = '1' then -- ist for pea + data_write_tmp <= addr; + elsif execOPC = '1' or micro_state = pack2 then + data_write_tmp <= ALUout; + elsif (exec_DIRECT = '1' and state = "10") then + data_write_tmp <= data_read; + if exec(movepl) = '1' then + data_write_tmp(31 downto 8) <= data_write_tmp(23 downto 0); + end if; + elsif exec(movepl) = '1' then + data_write_tmp(15 downto 0) <= reg_QB(31 downto 16); + elsif direct_data = '1' then + data_write_tmp <= last_data_read; + elsif writeSR = '1' then + data_write_tmp(15 downto 0) <= trap_SR(7 downto 0) & Flags(7 downto 0); + else + data_write_tmp <= OP2out; + end if; - IF (long_done='0' AND state(1)='1') OR movem_presub='0' THEN - memaddr <= addr; - END IF; - END IF; - END IF; - -- if access done, and not aligned, don't increment - addr <= memaddr_reg+memaddr_delta; - IF use_base='0' THEN - memaddr_reg <= (others=>'0'); - ELSE - memaddr_reg <= reg_QA; - END IF; - END PROCESS; + end if; + end if; + end process; ------------------------------------------------------------------------------ --- PC Calc + fetch opcode ------------------------------------------------------------------------------ -PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro_state, stop, make_trace, make_berr, IPL_nr, FlagsSR, set_rot_cnt, opcode, writePCbig, set_exec, exec, + ----------------------------------------------------------------------------- + -- brief + ----------------------------------------------------------------------------- + process (brief, OP1out, OP1outbrief, cpu) + begin + if brief(11) = '1' then + OP1outbrief <= OP1out(31 downto 16); + else + OP1outbrief <= (others => OP1out(15)); + end if; + briefdata <= OP1outbrief & OP1out(15 downto 0); + if extAddr_Mode = 1 or (cpu(1) = '1' and extAddr_Mode = 2) then + case brief(10 downto 9) is -- mikej SCALE factor + when "00" => briefdata <= OP1outbrief & OP1out(15 downto 0); + when "01" => briefdata <= OP1outbrief(14 downto 0) & OP1out(15 downto 0) & '0'; + when "10" => briefdata <= OP1outbrief(13 downto 0) & OP1out(15 downto 0) & "00"; + when "11" => briefdata <= OP1outbrief(12 downto 0) & OP1out(15 downto 0) & "000"; + when others => NULL; + end case; + end if; + end process; + + ----------------------------------------------------------------------------- + -- MEM_IO + ----------------------------------------------------------------------------- + process (clk, setdisp, memaddr_a, briefdata, memaddr_delta, setdispbyte, datatype, interrupt, rIPL_nr, IPL_vec, + memaddr_reg, reg_QA, use_base, VBR, last_data_read, trap_vector, exec, set, cpu) + begin + if rising_edge(clk) then + if clkena_lw = '1' then + trap_vector(31 downto 12) <= (others => '0'); + + if trap_berr='1' then + trap_vector(11 downto 0) <= X"008"; + end IF; + + if trap_addr_error = '1' then + trap_vector(11 downto 0) <= X"00C"; + end if; + + if trap_illegal = '1' then + trap_vector(11 downto 0) <= X"010"; + end if; + + if z_error = '1' then + trap_vector(11 downto 0) <= X"014"; + end if; + + if exec(trap_chk) = '1' then + trap_vector(11 downto 0) <= X"018"; + end if; + + if trap_trapv = '1' then + trap_vector(11 downto 0) <= X"01C"; + end if; + + if trap_priv = '1' then + trap_vector(11 downto 0) <= X"020"; + end if; + + if trap_trace = '1' then + trap_vector(11 downto 0) <= X"024"; + end if; + + if trap_1010 = '1' then + trap_vector(11 downto 0) <= X"028"; + end if; + + if trap_1111 = '1' then + trap_vector(11 downto 0) <= X"02C"; + end if; + + if trap_trap = '1' then + trap_vector(11 downto 0) <= x"0" & "10" & opcode(3 downto 0) & "00"; + end if; + + if trap_interrupt = '1' then + trap_vector(11 downto 0) <= "00" & IPL_vec & "00"; --TH + end if; + -- TH TODO: non-autovector IRQs + end if; + end if; + -- + if VBR_Stackframe = 0 or (cpu(0) = '0' and VBR_Stackframe = 2) then + trap_vector_vbr <= trap_vector; + else + trap_vector_vbr <= trap_vector + VBR; + end if; + + memaddr_a(4 downto 0) <= "00000"; + memaddr_a(7 downto 5) <= (others => memaddr_a(4)); + memaddr_a(15 downto 8) <= (others => memaddr_a(7)); + memaddr_a(31 downto 16) <= (others => memaddr_a(15)); + if setdisp = '1' then + if exec(briefext) = '1' then + memaddr_a <= briefdata + memaddr_delta; + elsif setdispbyte = '1' then + memaddr_a(7 downto 0) <= last_data_read(7 downto 0); + else + memaddr_a <= last_data_read; + end if; + elsif set(presub) = '1' then + if set(longaktion) = '1' then + memaddr_a(4 downto 0) <= "11100"; + elsif datatype = "00" and set(use_SP) = '0' then + memaddr_a(4 downto 0) <= "11111"; + else + memaddr_a(4 downto 0) <= "11110"; + end if; + elsif interrupt = '1' then + memaddr_a(4 downto 0) <= '1' & rIPL_nr & '0'; + end if; + + if rising_edge(clk) then + if clkena_in = '1' then + if exec(get_2ndOPC) = '1' or (state = "10" and memread(0) = '1') then + tmp_TG68_PC <= addr; + end if; + use_base <= '0'; + + if memmaskmux(3) = '0' then + memaddr_delta <= addsub_q; + elsif exec(mem_addsub) = '1' then + memaddr_delta <= addsub_q; + elsif state = "01" and exec_write_back = '1' then + memaddr_delta <= tmp_TG68_PC; + elsif exec(direct_delta) = '1' then + memaddr_delta <= data_read; + elsif exec(ea_to_pc) = '1' and setstate = "00" then + memaddr_delta <= addr; + elsif set(addrlong) = '1' then + memaddr_delta <= last_data_read; + elsif setstate = "00" then + memaddr_delta <= TG68_PC_add; + elsif exec(dispouter) = '1' then + memaddr_delta <= ea_data + memaddr_a; + elsif set_vectoraddr = '1' then + memaddr_delta <= trap_vector_vbr; + else + memaddr_delta <= memaddr_a; + if interrupt = '0' and Suppress_Base = '0' then + -- if interrupt='0' and Suppress_Base='0' and setstate(1)='1' then + use_base <= '1'; + end if; + end if; + + -- only used for movem address update + --if (long_done = '0' and state(1) = '1') or movem_presub = '0' then + if ((memread(0) = '1') and state(1) = '1') or movem_presub = '0' then -- fix for unaligned movem mikej + memaddr <= addr; + end if; + end if; + end if; + -- if access done, and not aligned, don't increment + addr <= memaddr_reg + memaddr_delta; + addr_out <= memaddr_reg + memaddr_delta; + + if use_base = '0' then + memaddr_reg <= (others => '0'); + else + memaddr_reg <= reg_QA; + end if; + end process; + + ----------------------------------------------------------------------------- + -- PC Calc + fetch opcode + ----------------------------------------------------------------------------- +PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro_state, stop, make_trace, make_berr, IPL_nr, FlagsSR, set_rot_cnt, set_alu_rot_cnt, opcode, writePCbig, set_exec, exec, PC_dataa, PC_datab, setnextpass, last_data_read, TG68_PC_brw, TG68_PC_word, Z_error, trap_trap, trap_trapv, interrupt, tmp_TG68_PC, TG68_PC) - BEGIN + begin + PC_dataa <= TG68_PC; + if TG68_PC_brw = '1' then + PC_dataa <= tmp_TG68_PC; + end if; - PC_dataa <= TG68_PC; - IF TG68_PC_brw = '1' THEN - PC_dataa <= tmp_TG68_PC; - END IF; + PC_datab(2 downto 0) <= (others => '0'); + PC_datab(3) <= PC_datab(2); + PC_datab( 7 downto 4) <= (others => PC_datab(3)); + PC_datab(15 downto 8) <= (others => PC_datab(7)); + PC_datab(31 downto 16) <= (others => PC_datab(15)); - PC_datab(2 downto 0) <= (others => '0'); - PC_datab(3) <= PC_datab(2); - PC_datab(7 downto 4) <= (others => PC_datab(3)); - PC_datab(15 downto 8) <= (others => PC_datab(7)); - PC_datab(31 downto 16) <= (others => PC_datab(15)); - IF interrupt='1' THEN - PC_datab(2 downto 1) <= "11"; - END IF; - IF exec(writePC_add) ='1' THEN - IF writePCbig='1' THEN - PC_datab(3) <= '1'; - PC_datab(1) <= '1'; - ELSE - PC_datab(2) <= '1'; - END IF; - IF trap_trap='1' OR trap_trapv='1' OR exec(trap_chk)='1' OR Z_error='1' THEN - PC_datab(1) <= '1'; - END IF; - ELSIF state="00" THEN - PC_datab(1) <= '1'; - END IF; - IF TG68_PC_brw = '1' THEN - IF TG68_PC_word='1' THEN - PC_datab <= last_data_read; - ELSE - PC_datab(7 downto 0) <= opcode(7 downto 0); - END IF; - END IF; + if interrupt = '1' then + PC_datab(2 downto 1) <= "11"; + end if; + if exec(writePC_add) = '1' then + if writePCbig = '1' then + PC_datab(3) <= '1'; + PC_datab(1) <= '1'; + else + PC_datab(2) <= '1'; + end if; + if trap_trap = '1' or trap_trapv = '1' or exec(trap_chk) = '1' or Z_error = '1' then + PC_datab(1) <= '1'; + end if; + elsif state = "00" then + PC_datab(1) <= '1'; + end if; - TG68_PC_add <= PC_dataa+PC_datab; + if TG68_PC_brw = '1' then + if TG68_PC_word = '1' then + PC_datab <= last_data_read; + else + PC_datab(7 downto 0) <= opcode(7 downto 0); + end if; + end if; - setopcode <= '0'; - setendOPC <= '0'; - setinterrupt <= '0'; - IF setstate="00" AND next_micro_state=idle AND setnextpass='0' AND (exec_write_back='0' OR state="11") AND set_rot_cnt="000001" AND set_exec(opcCHK)='0'THEN - setendOPC <= '1'; - IF FlagsSR(2 downto 0) - set_memmask <= "101111"; - WHEN "001" => - set_memmask <= "100111"; - WHEN "010" => - set_memmask <= "100011"; - WHEN "011" => - set_memmask <= "100001"; - WHEN OTHERS => - set_memmask <= "100000"; - END CASE; - IF setstate="00" THEN - set_memmask <= "100111"; - END IF; - END PROCESS; + ------------------------------------------------------------------------------ + --prepare Bitfield Parameters + ------------------------------------------------------------------------------ + process (clk, Reset, sndOPC, reg_QA, reg_QB, bf_width, bf_offset, bf_offset_l, bf_bhits, opcode, setstate) + begin + -- the ALU needs the full real offset to return the correct result for + -- bfffo + if sndOPC(11) = '1' then + bf_offset <= reg_QA; + else + bf_offset <= (others => '0'); + bf_offset(4 downto 0) <= sndOPC(10 downto 6); + end if; + -- offset within long word + bf_offset_l <= bf_offset(4 downto 0); ------------------------------------------------------------------------------- ---SR op ------------------------------------------------------------------------------- -PROCESS (clk, Reset, FlagsSR, last_data_read, OP2out, exec) - BEGIN - IF exec(andiSR)='1' THEN - SRin <= FlagsSR AND last_data_read(15 downto 8); - ELSIF exec(eoriSR)='1' THEN - SRin <= FlagsSR XOR last_data_read(15 downto 8); - ELSIF exec(oriSR)='1' THEN - SRin <= FlagsSR OR last_data_read(15 downto 8); - ELSE - SRin <= OP2out(15 downto 8); - END IF; + if sndOPC(5) = '1' then + bf_width <= reg_QB(4 downto 0) - 1; + else + bf_width <= sndOPC(4 downto 0) - 1; + end if; + + bf_bhits <= ('0' & bf_width) + ('0' & bf_offset_l); + set_oddout <= not bf_bhits(3); - IF rising_edge(clk) THEN - IF Reset='1' THEN - FlagsSR(5) <= '1'; - FC(2) <= '1'; - SVmode <= '1'; - preSVmode <= '1'; - FlagsSR(2 downto 0) <= "111"; - make_trace <= '0'; - ELSIF clkena_lw = '1' THEN - IF setopcode='1' THEN - make_trace <= FlagsSR(7); - IF set(changeMode)='1' THEN - SVmode <= NOT SVmode; - ELSE - SVmode <= preSVmode; - END IF; - END IF; - IF set(changeMode)='1' THEN - preSVmode <= NOT preSVmode; - FlagsSR(5) <= NOT preSVmode; - FC(2) <= NOT preSVmode; - END IF; - IF micro_state=trap3 THEN - FlagsSR(7) <= '0'; - END IF; - IF trap_trace='1' AND state="10" THEN - make_trace <= '0'; - END IF; - IF exec(directSR)='1' OR set_stop='1' THEN - FlagsSR <= data_read(15 downto 8); - END IF; - IF interrupt='1' AND trap_interrupt='1' THEN - FlagsSR(2 downto 0) <=rIPL_nr; - END IF; --- IF exec(to_CCR)='1' AND exec(to_SR)='1' THEN - IF exec(to_SR)='1' THEN - FlagsSR(7 downto 0) <= SRin; --SR - FC(2) <= SRin(5); --- END IF; - ELSIF exec(update_FC)='1' THEN - FC(2) <= FlagsSR(5); - END IF; - IF interrupt='1' THEN - FC(2) <= '1'; - END IF; - END IF; - END IF; - END PROCESS; + bf_loffset <= 31 - bf_bhits(4 downto 0); + if opcode(4 downto 3) /= "00" then + -- memory is being read with byte precision, thus offset + -- bit 2:0 are only used in the alu + bf_loffset(4 downto 3) <= "00"; + bf_offset_l(4 downto 3) <= "00"; + end if; + + case bf_bhits(5 downto 3) is + when "000" => + set_memmask <= "101111"; + when "001" => + set_memmask <= "100111"; + when "010" => + set_memmask <= "100011"; + when "011" => + set_memmask <= "100001"; + when others => + set_memmask <= "100000"; + end case; + if setstate = "00" then + set_memmask <= "100111"; + end if; ------------------------------------------------------------------------------ --- decode opcode ------------------------------------------------------------------------------ -PROCESS (clk, cpu, OP1out, OP2out, opcode, exe_condition, nextpass, micro_state, decodeOPC, state, setexecOPC, Flags, FlagsSR, direct_data, build_logical, - build_bcd, set_Z_error, trapd, movem_run, last_data_read, set, set_V_Flag, z_error, trap_trace, trap_interrupt, - SVmode, preSVmode, stop, long_done, ea_only, setstate, execOPC, exec_write_back, exe_datatype, - datatype, interrupt, c_out, trapmake, rot_cnt, brief, addr, - long_start, set_datatype, sndOPC, set_exec, exec, ea_build_now, reg_QA, reg_QB, make_berr, trap_berr) - BEGIN - TG68_PC_brw <= '0'; - setstate <= "00"; - Regwrena_now <= '0'; - movem_presub <= '0'; - setnextpass <= '0'; - regdirectsource <= '0'; - setdisp <= '0'; - setdispbyte <= '0'; - getbrief <= '0'; - dest_areg <= '0'; - source_areg <= '0'; - data_is_source <= '0'; - write_back <= '0'; - setstackaddr <= '0'; - writePC <= '0'; - ea_build_now <= '0'; - set_rot_bits <= "XX"; - set_rot_cnt <= "000001"; - dest_hbits <= '0'; - source_lowbits <= '0'; - source_2ndHbits <= '0'; - source_2ndLbits <= '0'; - dest_2ndHbits <= '0'; - ea_only <= '0'; - set_direct_data <= '0'; - set_exec_tas <= '0'; - trap_illegal <='0'; - trap_addr_error <= '0'; - trap_priv <='0'; - trap_1010 <='0'; - trap_1111 <='0'; - trap_trap <='0'; - trap_trapv <= '0'; - trapmake <='0'; - set_vectoraddr <='0'; - writeSR <= '0'; - set_stop <= '0'; - illegal_write_mode <= '0'; - illegal_read_mode <= '0'; - illegal_byteaddr <= '0'; - set_Z_error <= '0'; + end process; - next_micro_state <= idle; - build_logical <= '0'; - build_bcd <= '0'; - skipFetch <= make_berr; - set_writePCbig <= '0'; --- set_recall_last <= '0'; - set_Suppress_Base <= '0'; - set_PCbase <= '0'; + ------------------------------------------------------------------------------ + --SR op + ------------------------------------------------------------------------------ + process (clk, Reset, FlagsSR, last_data_read, OP2out, exec) + begin + if exec(andisR) = '1' then + SRin <= FlagsSR and last_data_read(15 downto 8); + elsif exec(eorisR) = '1' then + SRin <= FlagsSR Xor last_data_read(15 downto 8); + elsif exec(orisR) = '1' then + SRin <= FlagsSR or last_data_read(15 downto 8); + else + SRin <= OP2out(15 downto 8); + end if; - IF rot_cnt/="000001" THEN - set_rot_cnt <= rot_cnt-1; - END IF; - set_datatype <= datatype; + if rising_edge(clk) then + if Reset = '1' then + FlagsSR(5) <= '1'; + FlagsSR(2 downto 0) <= "111"; + FC(2) <= '1'; + SVmode <= '1'; + preSVmode <= '1'; + make_trace <= '0'; + elsif clkena_lw = '1' then + if setopcode = '1' then + make_trace <= FlagsSR(7); + if set(changeMode) = '1' then + SVmode <= not SVmode; + else + SVmode <= preSVmode; + end if; + end if; + if set(changeMode) = '1' then + preSVmode <= not preSVmode; + FlagsSR(5) <= not preSVmode; + FC(2) <= not preSVmode; + end if; + if micro_state = trap3 then + FlagsSR(7) <= '0'; + end if; + if trap_trace = '1' and state = "10" then + make_trace <= '0'; + end if; + if exec(directSR) = '1' or set_stop = '1' then + FlagsSR <= data_read(15 downto 8); + end if; + if interrupt = '1' and trap_interrupt = '1' then + FlagsSR(2 downto 0) <= rIPL_nr; + end if; + -- if exec(to_CCR)='1' and exec(to_SR)='1' then + if exec(to_SR) = '1' then + FlagsSR(7 downto 0) <= SRin; --SR + FC(2) <= SRin(5); + -- end if; + elsif exec(update_FC) = '1' then + FC(2) <= FlagsSR(5); + end if; + if interrupt = '1' then + FC(2) <= '1'; + end if; + end if; + end if; + end process; - set <= (OTHERS=>'0'); - set_exec <= (OTHERS=>'0'); - set(update_ld) <= '0'; --- odd_start <= '0'; ------------------------------------------------------------------------------- ---Sourcepass ------------------------------------------------------------------------------- - CASE opcode(7 downto 6) IS - WHEN "00" => datatype <= "00"; --Byte - WHEN "01" => datatype <= "01"; --Word - WHEN OTHERS => datatype <= "10"; --Long - END CASE; + ----------------------------------------------------------------------------- + -- decode opcode + ----------------------------------------------------------------------------- + process(clk, cpu, OP1out, OP2out, opcode, exe_condition, nextpass, micro_state, decodeOPC, state, setexecOPC, Flags, FlagsSR, direct_data, build_logical, + build_bcd, set_Z_error, trapd, movem_run, last_data_read, set, set_V_Flag, z_error, trap_trace, trap_interrupt, + SVmode, preSVmode, stop, long_done, ea_only, setstate, execOPC, exec_write_back, exe_datatype, + datatype, interrupt, c_out, trapmake, rot_cnt, brief, addr, + long_start, set_datatype, sndOPC, set_exec, exec, ea_build_now, reg_QA, reg_QB, make_berr, trap_berr) + begin + TG68_PC_brw <= '0'; + setstate <= "00"; + Regwrena_now <= '0'; + movem_presub <= '0'; + setnextpass <= '0'; + regdirectsource <= '0'; + setdisp <= '0'; + setdispbyte <= '0'; + getbrief <= '0'; + dest_areg <= '0'; + source_areg <= '0'; + data_is_source <= '0'; + write_back <= '0'; + setstackaddr <= '0'; + writePC <= '0'; + ea_build_now <= '0'; + set_rot_bits <= "XX"; + set_rot_cnt <= "000001"; + dest_hbits <= '0'; + source_lowbits <= '0'; + source_2ndHbits <= '0'; + source_2ndLbits <= '0'; + dest_2ndHbits <= '0'; + ea_only <= '0'; + set_direct_data <= '0'; + set_exec_tas <= '0'; + trap_illegal <= '0'; + trap_addr_error <= '0'; + trap_priv <= '0'; + trap_1010 <= '0'; + trap_1111 <= '0'; + trap_trap <= '0'; + trap_trapv <= '0'; + trapmake <= '0'; + set_vectoraddr <= '0'; + writeSR <= '0'; + set_stop <= '0'; + illegal_write_mode <= '0'; + illegal_read_mode <= '0'; + illegal_byteaddr <= '0'; + set_Z_error <= '0'; - IF trapmake='1' AND trapd='0' THEN - next_micro_state <= trap0; - IF VBR_Stackframe=0 OR (cpu(0)='0' AND VBR_Stackframe=2) THEN - set(writePC_add) <= '1'; --- set_datatype <= "10"; - END IF; - IF preSVmode='0' THEN - set(changeMode) <= '1'; - END IF; - setstate <= "01"; - END IF; - IF interrupt='1' AND trap_berr='1' THEN - next_micro_state <= trap0; - IF preSVmode='0' THEN - set(changeMode) <= '1'; - END IF; - setstate <= "01"; - END IF; - IF micro_state=int1 OR (interrupt='1' AND trap_trace='1') THEN - next_micro_state <= trap0; --- IF cpu(0)='0' THEN --- set_datatype <= "10"; --- END IF; - IF preSVmode='0' THEN - set(changeMode) <= '1'; - END IF; - setstate <= "01"; - END IF; + next_micro_state <= idle; + build_logical <= '0'; + build_bcd <= '0'; + skipFetch <= make_berr; + set_writePCbig <= '0'; + -- set_recall_last <= '0'; + set_Suppress_Base <= '0'; + set_PCbase <= '0'; - IF setexecOPC='1' AND FlagsSR(5)/=preSVmode THEN - set(changeMode) <= '1'; --- setstate <= "01"; --- next_micro_state <= nop; - END IF; + -- decrement xyz + if rot_cnt /= "000001" then + set_rot_cnt <= rot_cnt - 1; + end if; + set_datatype <= datatype; - IF interrupt='1' AND trap_interrupt='1'THEN --- skipFetch <= '1'; - next_micro_state <= int1; - set(update_ld) <= '1'; - setstate <= "10"; - END IF; + set <= (others => '0'); + set_exec <= (others => '0'); + set(update_ld) <= '0'; + -- odd_start <= '0'; + ------------------------------------------------------------------------------ + --Sourcepass + ------------------------------------------------------------------------------ + case opcode(7 downto 6) is + when "00" => datatype <= "00"; --Byte + when "01" => datatype <= "01"; --Word + when others => datatype <= "10"; --Long + end case; - IF set(changeMode)='1' THEN - set(to_USP) <= '1'; - set(from_USP) <= '1'; - setstackaddr <='1'; - END IF; + if trapmake = '1' and trapd = '0' then + next_micro_state <= trap0; + if VBR_Stackframe = 0 or (cpu(0) = '0' and VBR_Stackframe = 2) then + set(writePC_add) <= '1'; + -- set_datatype <= "10"; + end if; + if preSVmode = '0' then + set(changeMode) <= '1'; + end if; + setstate <= "01"; + end if; - IF ea_only='0' AND set(get_ea_now)='1' THEN - setstate <= "10"; --- set_recall_last <= '1'; --- set(update_ld) <= '0'; - END IF; + if interrupt='1' and trap_berr='1' THEN + next_micro_state <= trap0; + if preSVmode='0' THEN + set(changeMode) <= '1'; + end if; + setstate <= "01"; + end if; - IF setstate(1)='1' AND set_datatype(1)='1' THEN - set(longaktion) <= '1'; - END IF; + if micro_state = int1 or (interrupt = '1' and trap_trace = '1') then + if trap_trace='1' AND (VBR_Stackframe=1 or (cpu(0)='1' AND VBR_Stackframe=2)) then + next_micro_state <= trap00; --TH + else + next_micro_state <= trap0; + end if; + -- if cpu(0)='0' then + -- set_datatype <= "10"; + -- end if; + if preSVmode = '0' then + set(changeMode) <= '1'; + end if; + setstate <= "01"; + end if; - IF (ea_build_now='1' AND decodeOPC='1') OR exec(ea_build)='1' THEN - CASE opcode(5 downto 3) IS --source - WHEN "010"|"011"|"100" => -- -(An)+ - set(get_ea_now) <='1'; - setnextpass <= '1'; - IF opcode(3)='1' THEN --(An)+ - set(postadd) <= '1'; - IF opcode(2 downto 0)="111" THEN - set(use_SP) <= '1'; - END IF; - END IF; - IF opcode(5)='1' THEN -- -(An) - set(presub) <= '1'; - IF opcode(2 downto 0)="111" THEN - set(use_SP) <= '1'; - END IF; - END IF; - WHEN "101" => --(d16,An) - next_micro_state <= ld_dAn1; - WHEN "110" => --(d8,An,Xn) - next_micro_state <= ld_AnXn1; - getbrief <='1'; - WHEN "111" => - CASE opcode(2 downto 0) IS - WHEN "000" => --(xxxx).w - next_micro_state <= ld_nn; - WHEN "001" => --(xxxx).l - set(longaktion) <= '1'; - next_micro_state <= ld_nn; - WHEN "010" => --(d16,PC) - next_micro_state <= ld_dAn1; - set(dispouter) <= '1'; - set_Suppress_Base <= '1'; - set_PCbase <= '1'; - WHEN "011" => --(d8,PC,Xn) - next_micro_state <= ld_AnXn1; - getbrief <= '1'; - set(dispouter) <= '1'; - set_Suppress_Base <= '1'; - set_PCbase <= '1'; - WHEN "100" => --#data - setnextpass <= '1'; - set_direct_data <= '1'; - IF datatype="10" THEN - set(longaktion) <= '1'; - END IF; - WHEN OTHERS => NULL; - END CASE; - WHEN OTHERS => NULL; - END CASE; - END IF; ------------------------------------------------------------------------------- ---prepere opcode ------------------------------------------------------------------------------- - CASE opcode(15 downto 12) IS --- 0000 ---------------------------------------------------------------------------- - WHEN "0000" => - IF opcode(8)='1' AND opcode(5 downto 3)="001" THEN --movep - datatype <= "00"; --Byte - set(use_SP) <= '1'; --addr+2 - set(no_Flags) <='1'; - IF opcode(7)='0' THEN --to register - set_exec(Regwrena) <= '1'; - set_exec(opcMOVE) <= '1'; - set(movepl) <= '1'; - END IF; - IF decodeOPC='1' THEN - IF opcode(6)='1' THEN - set(movepl) <= '1'; - END IF; - IF opcode(7)='0' THEN - set_direct_data <= '1'; -- to register - END IF; - next_micro_state <= movep1; - END IF; - IF setexecOPC='1' THEN - dest_hbits <='1'; - END IF; - ELSE - IF opcode(8)='1' OR opcode(11 downto 9)="100" THEN --Bits - set_exec(opcBITS) <= '1'; - set_exec(ea_data_OP1) <= '1'; - IF opcode(7 downto 6)/="00" THEN - IF opcode(5 downto 4)="00" THEN - set_exec(Regwrena) <= '1'; - END IF; - write_back <= '1'; - END IF; - IF opcode(5 downto 4)="00" THEN - datatype <= "10"; --Long - ELSE - datatype <= "00"; --Byte - END IF; - IF opcode(8)='0' THEN - IF decodeOPC='1' THEN - next_micro_state <= nop; - set(get_2ndOPC) <= '1'; - set(ea_build) <= '1'; - END IF; - ELSE - ea_build_now <= '1'; - END IF; - ELSIF opcode(11 downto 9)="111" THEN --MOVES not in 68000 - trap_illegal <= '1'; --- trap_addr_error <= '1'; - trapmake <= '1'; - ELSE --andi, ...xxxi - IF opcode(11 downto 9)="000" THEN --ORI - set_exec(opcOR) <= '1'; - END IF; - IF opcode(11 downto 9)="001" THEN --ANDI - set_exec(opcAND) <= '1'; - END IF; - IF opcode(11 downto 9)="010" OR opcode(11 downto 9)="011" THEN --SUBI, ADDI - set_exec(opcADD) <= '1'; - END IF; - IF opcode(11 downto 9)="101" THEN --EORI - set_exec(opcEOR) <= '1'; - END IF; - IF opcode(11 downto 9)="110" THEN --CMPI - set_exec(opcCMP) <= '1'; - END IF; - IF opcode(7)='0' AND opcode(5 downto 0)="111100" AND (set_exec(opcAND) OR set_exec(opcOR) OR set_exec(opcEOR))='1' THEN --SR - IF decodeOPC='1' AND SVmode='0' AND opcode(6)='1' THEN --SR - trap_priv <= '1'; - trapmake <= '1'; - ELSE - set(no_Flags) <= '1'; - IF decodeOPC='1' THEN - IF opcode(6)='1' THEN - set(to_SR) <= '1'; - END IF; - set(to_CCR) <= '1'; - set(andiSR) <= set_exec(opcAND); - set(eoriSR) <= set_exec(opcEOR); - set(oriSR) <= set_exec(opcOR); - setstate <= "01"; - next_micro_state <= nopnop; - END IF; - END IF; - ELSE - IF decodeOPC='1' THEN - next_micro_state <= andi; - set(ea_build) <= '1'; - set_direct_data <= '1'; - IF datatype="10" THEN - set(longaktion) <= '1'; - END IF; - END IF; - IF opcode(5 downto 4)/="00" THEN - set_exec(ea_data_OP1) <= '1'; - END IF; - IF opcode(11 downto 9)/="110" THEN --CMPI - IF opcode(5 downto 4)="00" THEN - set_exec(Regwrena) <= '1'; - END IF; - write_back <= '1'; - END IF; - IF opcode(10 downto 9)="10" THEN --CMPI, SUBI - set(addsub) <= '1'; - END IF; - END IF; - END IF; - END IF; + if setexecOPC = '1' and FlagsSR(5) /= preSVmode then + set(changeMode) <= '1'; + -- setstate <= "01"; + -- next_micro_state <= nop; + end if; --- 0001, 0010, 0011 ----------------------------------------------------------------- - WHEN "0001"|"0010"|"0011" => --move.b, move.l, move.w - set_exec(opcMOVE) <= '1'; - ea_build_now <= '1'; - IF opcode(8 downto 6)="001" THEN - set(no_Flags) <= '1'; - END IF; - IF opcode(5 downto 4)="00" THEN --Dn, An - IF opcode(8 downto 7)="00" THEN - set_exec(Regwrena) <= '1'; - END IF; - END IF; - CASE opcode(13 downto 12) IS - WHEN "01" => datatype <= "00"; --Byte - WHEN "10" => datatype <= "10"; --Long - WHEN OTHERS => datatype <= "01"; --Word - END CASE; - source_lowbits <= '1'; -- Dn=> An=> - IF opcode(3)='1' THEN - source_areg <= '1'; - END IF; + if interrupt = '1' and trap_interrupt = '1' then + -- skipFetch <= '1'; + next_micro_state <= int1; + set(update_ld) <= '1'; + setstate <= "10"; + end if; - IF nextpass='1' OR opcode(5 downto 4)="00" THEN - dest_hbits <= '1'; - IF opcode(8 downto 6)/="000" THEN - dest_areg <= '1'; - END IF; - END IF; --- IF setstate="10" THEN --- set(update_ld) <= '0'; --- END IF; --- - IF micro_state=idle AND (nextpass='1' OR (opcode(5 downto 4)="00" AND decodeOPC='1')) THEN - CASE opcode(8 downto 6) IS --destination - WHEN "000"|"001" => --Dn,An - set_exec(Regwrena) <= '1'; - WHEN "010"|"011"|"100" => --destination -(an)+ - IF opcode(6)='1' THEN --(An)+ - set(postadd) <= '1'; - IF opcode(11 downto 9)="111" THEN - set(use_SP) <= '1'; - END IF; - END IF; - IF opcode(8)='1' THEN -- -(An) - set(presub) <= '1'; - IF opcode(11 downto 9)="111" THEN - set(use_SP) <= '1'; - END IF; - END IF; - setstate <= "11"; - next_micro_state <= nop; - IF nextpass='0' THEN - set(write_reg) <= '1'; - END IF; - WHEN "101" => --(d16,An) - next_micro_state <= st_dAn1; --- getbrief <= '1'; - WHEN "110" => --(d8,An,Xn) - next_micro_state <= st_AnXn1; - getbrief <= '1'; - WHEN "111" => - CASE opcode(11 downto 9) IS - WHEN "000" => --(xxxx).w - next_micro_state <= st_nn; - WHEN "001" => --(xxxx).l - set(longaktion) <= '1'; - next_micro_state <= st_nn; - WHEN OTHERS => NULL; - END CASE; - WHEN OTHERS => NULL; - END CASE; - END IF; ----- 0100 ---------------------------------------------------------------------------- - WHEN "0100" => --rts_group - IF opcode(8)='1' THEN --lea - IF opcode(6)='1' THEN --lea - IF opcode(7)='1' THEN - source_lowbits <= '1'; --- IF opcode(5 downto 3)="000" AND opcode(10)='0' THEN --ext - IF opcode(5 downto 4)="00" THEN --extb.l - set_exec(opcEXT) <= '1'; - set_exec(opcMOVE) <= '1'; - set_exec(Regwrena) <= '1'; --- IF opcode(6)='0' THEN --- datatype <= "01"; --WORD --- END IF; - ELSE - source_areg <= '1'; - ea_only <= '1'; - set_exec(Regwrena) <= '1'; - set_exec(opcMOVE) <='1'; - set(no_Flags) <='1'; - IF opcode(5 downto 3)="010" THEN --lea (Am),An - dest_areg <= '1'; - dest_hbits <= '1'; - ELSE - ea_build_now <= '1'; - END IF; - IF set(get_ea_now)='1' THEN - setstate <= "01"; - set_direct_data <= '1'; - END IF; - IF setexecOPC='1' THEN - dest_areg <= '1'; - dest_hbits <= '1'; - END IF; - END IF; - ELSE - trap_illegal <= '1'; - trapmake <= '1'; - END IF; - ELSE --chk - IF opcode(7)='1' AND opcode(5 downto 0) /= "111111" THEN - datatype <= "01"; --Word - set(trap_chk) <= '1'; - IF (c_out(1)='0' OR OP1out(15)='1' OR OP2out(15)='1') AND exec(opcCHK)='1' THEN - trapmake <= '1'; - END IF; - ELSIF cpu(1)='1' THEN --chk long for 68020 - datatype <= "10"; --Long - set(trap_chk) <= '1'; - IF (c_out(2)='1' OR OP1out(31)='1' OR OP2out(31)='1') AND exec(opcCHK)='1' THEN - trapmake <= '1'; - END IF; - ELSE - trap_illegal <= '1'; -- chk long for 68020 - trapmake <= '1'; - END IF; - IF opcode(7)='1' OR cpu(1)='1' THEN - IF (nextpass='1' OR opcode(5 downto 4)="00") AND exec(opcCHK)='0' AND micro_state=idle THEN - set_exec(opcCHK) <= '1'; - END IF; - ea_build_now <= '1'; - set(addsub) <= '1'; - IF setexecOPC='1' THEN - dest_hbits <= '1'; - source_lowbits <='1'; - END IF; - END IF; - END IF; - ELSE - CASE opcode(11 downto 9) IS - WHEN "000"=> - IF opcode(7 downto 6)="11" THEN --move from SR - IF SR_Read=0 OR (cpu(0)='0' AND SR_Read=2) OR SVmode='1' THEN --- IF SVmode='1' THEN - ea_build_now <= '1'; - set_exec(opcMOVESR) <= '1'; - datatype <= "01"; - write_back <='1'; -- im 68000 wird auch erst gelesen - IF cpu(0)='1' AND state="10" THEN - skipFetch <= '1'; - END IF; - IF opcode(5 downto 4)="00" THEN - set_exec(Regwrena) <= '1'; - END IF; - ELSE - trap_priv <= '1'; - trapmake <= '1'; - END IF; - ELSE --negx - ea_build_now <= '1'; - set_exec(use_XZFlag) <= '1'; - write_back <='1'; - set_exec(opcADD) <= '1'; - set(addsub) <= '1'; - source_lowbits <= '1'; - IF opcode(5 downto 4)="00" THEN - set_exec(Regwrena) <= '1'; - END IF; - IF setexecOPC='1' THEN - set(OP1out_zero) <= '1'; - END IF; - END IF; - WHEN "001"=> - IF opcode(7 downto 6)="11" THEN --move from CCR 68010 - IF SR_Read=1 OR (cpu(0)='1' AND SR_Read=2) THEN - ea_build_now <= '1'; - set_exec(opcMOVESR) <= '1'; - datatype <= "00"; - write_back <='1'; -- im 68000 wird auch erst gelesen - IF opcode(5 downto 4)="00" THEN - set_exec(Regwrena) <= '1'; - END IF; - ELSE - trap_illegal <= '1'; - trapmake <= '1'; - END IF; - ELSE --clr - ea_build_now <= '1'; - write_back <='1'; - set_exec(opcAND) <= '1'; - IF cpu(0)='1' AND state="10" THEN - skipFetch <= '1'; - END IF; - IF setexecOPC='1' THEN - set(OP1out_zero) <= '1'; - END IF; - IF opcode(5 downto 4)="00" THEN - set_exec(Regwrena) <= '1'; - END IF; - END IF; - WHEN "010"=> - ea_build_now <= '1'; - IF opcode(7 downto 6)="11" THEN --move to CCR - datatype <= "01"; - source_lowbits <= '1'; - IF (decodeOPC='1' AND opcode(5 downto 4)="00") OR state="10" OR direct_data='1' THEN - set(to_CCR) <= '1'; - END IF; - ELSE --neg - write_back <='1'; - set_exec(opcADD) <= '1'; - set(addsub) <= '1'; - source_lowbits <= '1'; - IF opcode(5 downto 4)="00" THEN - set_exec(Regwrena) <= '1'; - END IF; - IF setexecOPC='1' THEN - set(OP1out_zero) <= '1'; - END IF; - END IF; - WHEN "011"=> --not, move toSR - IF opcode(7 downto 6)="11" THEN --move to SR - IF SVmode='1' THEN - ea_build_now <= '1'; - datatype <= "01"; - source_lowbits <= '1'; - IF (decodeOPC='1' AND opcode(5 downto 4)="00") OR state="10" OR direct_data='1' THEN - set(to_SR) <= '1'; - set(to_CCR) <= '1'; - END IF; - IF exec(to_SR)='1' OR (decodeOPC='1' AND opcode(5 downto 4)="00") OR state="10" OR direct_data='1' THEN - setstate <="01"; - END IF; - ELSE - trap_priv <= '1'; - trapmake <= '1'; - END IF; - ELSE --not - ea_build_now <= '1'; - write_back <='1'; - set_exec(opcEOR) <= '1'; - set_exec(ea_data_OP1) <= '1'; - IF opcode(5 downto 3)="000" THEN - set_exec(Regwrena) <= '1'; - END IF; - IF setexecOPC='1' THEN - set(OP2out_one) <= '1'; - END IF; - END IF; - WHEN "100"|"110"=> - IF opcode(7)='1' THEN --movem, ext - IF opcode(5 downto 3)="000" AND opcode(10)='0' THEN --ext - source_lowbits <= '1'; - set_exec(opcEXT) <= '1'; - set_exec(opcMOVE) <= '1'; - set_exec(Regwrena) <= '1'; - IF opcode(6)='0' THEN - datatype <= "01"; --WORD - END IF; - ELSE --movem --- IF opcode(11 downto 7)="10001" OR opcode(11 downto 7)="11001" THEN --MOVEM - ea_only <= '1'; - set(no_Flags) <= '1'; - IF opcode(6)='0' THEN - datatype <= "01"; --Word transfer - END IF; - IF (opcode(5 downto 3)="100" OR opcode(5 downto 3)="011") AND state="01" THEN -- -(An), (An)+ - set_exec(save_memaddr) <= '1'; - set_exec(Regwrena) <= '1'; - END IF; - IF opcode(5 downto 3)="100" THEN -- -(An) - movem_presub <= '1'; - set(subidx) <= '1'; - END IF; - IF state="10" THEN - set(Regwrena) <= '1'; - set(opcMOVE) <= '1'; - END IF; - IF decodeOPC='1' THEN - set(get_2ndOPC) <='1'; - IF opcode(5 downto 3)="010" OR opcode(5 downto 3)="011" OR opcode(5 downto 3)="100" THEN - next_micro_state <= movem1; - ELSE - next_micro_state <= nop; - set(ea_build) <= '1'; - END IF; - END IF; - IF set(get_ea_now)='1' THEN - IF movem_run='1' THEN - set(movem_action) <= '1'; - IF opcode(10)='0' THEN - setstate <="11"; - set(write_reg) <= '1'; - ELSE - setstate <="10"; - END IF; - next_micro_state <= movem2; - set(mem_addsub) <= '1'; - ELSE - setstate <="01"; - END IF; - END IF; - END IF; - ELSE - IF opcode(10)='1' THEN --MUL.L, DIV.L 68020 --- IF cpu(1)='1' THEN - IF (opcode(6)='1' AND (DIV_Mode=1 OR (cpu(1)='1' AND DIV_Mode=2))) OR - (opcode(6)='0' AND (MUL_Mode=1 OR (cpu(1)='1' AND MUL_Mode=2))) THEN - IF decodeOPC='1' THEN - next_micro_state <= nop; - set(get_2ndOPC) <= '1'; - set(ea_build) <= '1'; - END IF; - IF (micro_state=idle AND nextpass='1') OR (opcode(5 downto 4)="00" AND exec(ea_build)='1')THEN - setstate <="01"; - dest_2ndHbits <= '1'; - source_2ndLbits <= '1'; - IF opcode(6)='1' THEN - next_micro_state <= div1; - ELSE - next_micro_state <= mul1; - set(ld_rot_cnt) <= '1'; - END IF; - END IF; - IF z_error='0' AND set_V_Flag='0' AND set(opcDIVU)='1' THEN - set(Regwrena) <= '1'; - END IF; - source_lowbits <='1'; - IF nextpass='1' OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN - dest_hbits <= '1'; - END IF; - datatype <= "10"; - ELSE - trap_illegal <= '1'; - trapmake <= '1'; - END IF; + if set(changeMode) = '1' then + set(to_USP) <= '1'; + set(from_USP) <= '1'; + setstackaddr <= '1'; + end if; - ELSE --pea, swap - IF opcode(6)='1' THEN - datatype <= "10"; - IF opcode(5 downto 3)="000" THEN --swap - set_exec(opcSWAP) <= '1'; - set_exec(Regwrena) <= '1'; - ELSIF opcode(5 downto 3)="001" THEN --bkpt + if ea_only = '0' and set(get_ea_now) = '1' then + setstate <= "10"; + -- set_recall_last <= '1'; + -- set(update_ld) <= '0'; + end if; - ELSE --pea - ea_only <= '1'; - ea_build_now <= '1'; - IF nextpass='1' AND micro_state=idle THEN - set(presub) <= '1'; - setstackaddr <='1'; - setstate <="11"; - next_micro_state <= nop; - END IF; - IF set(get_ea_now)='1' THEN - setstate <="01"; - END IF; - END IF; - ELSE - IF opcode(5 downto 3)="001" THEN --link.l - datatype <= "10"; - set_exec(opcADD) <= '1'; --for displacement - set_exec(Regwrena) <= '1'; - set(no_Flags) <= '1'; - IF decodeOPC='1' THEN - set(linksp) <= '1'; - set(longaktion) <= '1'; - next_micro_state <= link1; - set(presub) <= '1'; - setstackaddr <='1'; - set(mem_addsub) <= '1'; - source_lowbits <= '1'; - source_areg <= '1'; - set(store_ea_data) <= '1'; - END IF; - ELSE --nbcd - ea_build_now <= '1'; - set_exec(use_XZFlag) <= '1'; - write_back <='1'; - set_exec(opcADD) <= '1'; - set_exec(opcSBCD) <= '1'; - source_lowbits <= '1'; - IF opcode(5 downto 4)="00" THEN - set_exec(Regwrena) <= '1'; - END IF; - IF setexecOPC='1' THEN - set(OP1out_zero) <= '1'; - END IF; - END IF; - END IF; - END IF; - END IF; --- - WHEN "101"=> --tst, tas 4aFC - illegal - IF opcode(7 downto 2)="111111" THEN --illegal - trap_illegal <= '1'; - trapmake <= '1'; - ELSE - ea_build_now <= '1'; - IF setexecOPC='1' THEN - source_lowbits <= '1'; - IF opcode(3)='1' THEN --MC68020... - source_areg <= '1'; - END IF; - END IF; - set_exec(opcMOVE) <= '1'; - IF opcode(7 downto 6)="11" THEN --tas - set_exec_tas <= '1'; - write_back <= '1'; - datatype <= "00"; --Byte - IF opcode(5 downto 4)="00" THEN - set_exec(Regwrena) <= '1'; - END IF; - END IF; - END IF; ----- WHEN "110"=> - WHEN "111"=> --4EXX --- --- ea_only <= '1'; --- ea_build_now <= '1'; --- IF nextpass='1' AND micro_state=idle THEN --- set(presub) <= '1'; --- setstackaddr <='1'; --- set(mem_addsub) <= '1'; --- setstate <="11"; --- next_micro_state <= nop; --- END IF; --- IF set(get_ea_now)='1' THEN --- setstate <="01"; --- END IF; --- + if setstate(1) = '1' and set_datatype(1) = '1' then + set(longaktion) <= '1'; + end if; + if (ea_build_now = '1' and decodeOPC = '1') or exec(ea_build) = '1' then + case opcode(5 downto 3) is --source + when "010" | "011" | "100" => -- -(An)+ + set(get_ea_now) <= '1'; + setnextpass <= '1'; + if opcode(3) = '1' then --(An)+ + set(postadd) <= '1'; + if opcode(2 downto 0) = "111" then + set(use_SP) <= '1'; + end if; + end if; + if opcode(5) = '1' then -- -(An) + set(presub) <= '1'; + if opcode(2 downto 0) = "111" then + set(use_SP) <= '1'; + end if; + end if; + when "101" => --(d16,An) + next_micro_state <= ld_dAn1; + when "110" => --(d8,An,Xn) + next_micro_state <= ld_AnXn1; + getbrief <= '1'; + when "111" => + case opcode(2 downto 0) is + when "000" => --(xxxx).w + next_micro_state <= ld_nn; + when "001" => --(xxxx).l + set(longaktion) <= '1'; + next_micro_state <= ld_nn; + when "010" => --(d16,PC) + next_micro_state <= ld_dAn1; + set(dispouter) <= '1'; + set_Suppress_Base <= '1'; + set_PCbase <= '1'; + when "011" => --(d8,PC,Xn) + next_micro_state <= ld_AnXn1; + getbrief <= '1'; + set(dispouter) <= '1'; + set_Suppress_Base <= '1'; + set_PCbase <= '1'; + when "100" => --#data + setnextpass <= '1'; + set_direct_data <= '1'; + if datatype = "10" then + set(longaktion) <= '1'; + end if; + when others => NULL; + end case; + when others => NULL; + end case; + end if; - - IF opcode(7)='1' THEN --jsr, jmp - datatype <= "10"; - ea_only <= '1'; - ea_build_now <= '1'; - IF exec(ea_to_pc)='1' THEN - next_micro_state <= nop; - END IF; - IF nextpass='1' AND micro_state=idle AND opcode(6)='0' THEN - set(presub) <= '1'; - setstackaddr <='1'; - setstate <="11"; - next_micro_state <= nopnop; - END IF; --- achtung buggefahr - IF micro_state=ld_AnXn1 AND brief(8)='0'THEN --JMP/JSR n(Ax,Dn) - skipFetch <= '1'; - END IF; - IF state="00" THEN - writePC <= '1'; - END IF; - set(hold_dwr) <= '1'; - IF set(get_ea_now)='1' THEN --jsr - IF exec(longaktion)='0' OR long_done='1' THEN - skipFetch <= '1'; - END IF; - setstate <="01"; - set(ea_to_pc) <= '1'; - END IF; - ELSE -- - CASE opcode(6 downto 0) IS - WHEN "1000000"|"1000001"|"1000010"|"1000011"|"1000100"|"1000101"|"1000110"|"1000111"| --trap - "1001000"|"1001001"|"1001010"|"1001011"|"1001100"|"1001101"|"1001110"|"1001111" => --trap - trap_trap <='1'; - trapmake <= '1'; - WHEN "1010000"|"1010001"|"1010010"|"1010011"|"1010100"|"1010101"|"1010110"|"1010111"=> --link - datatype <= "10"; - set_exec(opcADD) <= '1'; --for displacement - set_exec(Regwrena) <= '1'; - set(no_Flags) <= '1'; - IF decodeOPC='1' THEN - next_micro_state <= link1; - set(presub) <= '1'; - setstackaddr <='1'; - set(mem_addsub) <= '1'; - source_lowbits <= '1'; - source_areg <= '1'; - set(store_ea_data) <= '1'; - END IF; - - WHEN "1011000"|"1011001"|"1011010"|"1011011"|"1011100"|"1011101"|"1011110"|"1011111" => --unlink - datatype <= "10"; - set_exec(Regwrena) <= '1'; - set_exec(opcMOVE) <= '1'; - set(no_Flags) <= '1'; - IF decodeOPC='1' THEN - setstate <= "01"; - next_micro_state <= unlink1; - set(opcMOVE) <= '1'; - set(Regwrena) <= '1'; - setstackaddr <='1'; - source_lowbits <= '1'; - source_areg <= '1'; - END IF; - - WHEN "1100000"|"1100001"|"1100010"|"1100011"|"1100100"|"1100101"|"1100110"|"1100111" => --move An,USP - IF SVmode='1' THEN --- set(no_Flags) <= '1'; - set(to_USP) <= '1'; - source_lowbits <= '1'; - source_areg <= '1'; - datatype <= "10"; - ELSE - trap_priv <= '1'; - trapmake <= '1'; - END IF; - WHEN "1101000"|"1101001"|"1101010"|"1101011"|"1101100"|"1101101"|"1101110"|"1101111" => --move USP,An - IF SVmode='1' THEN --- set(no_Flags) <= '1'; - set(from_USP) <= '1'; - datatype <= "10"; - set_exec(Regwrena) <= '1'; - ELSE - trap_priv <= '1'; - trapmake <= '1'; - END IF; - - WHEN "1110000" => --reset - IF SVmode='0' THEN - trap_priv <= '1'; - trapmake <= '1'; - ELSE - set(opcRESET) <= '1'; - IF decodeOPC='1' THEN - set(ld_rot_cnt) <= '1'; - set_rot_cnt <= "000000"; - END IF; - END IF; - - WHEN "1110001" => --nop - - WHEN "1110010" => --stop - IF SVmode='0' THEN - trap_priv <= '1'; - trapmake <= '1'; - ELSE - IF decodeOPC='1' THEN - setnextpass <= '1'; - set_stop <= '1'; - END IF; - IF stop='1' THEN - skipFetch <= '1'; - END IF; - - END IF; - - WHEN "1110011"|"1110111" => --rte/rtr - IF SVmode='1' OR opcode(2)='1' THEN - IF decodeOPC='1' THEN - setstate <= "10"; - set(postadd) <= '1'; - setstackaddr <= '1'; - IF opcode(2)='1' THEN - set(directCCR) <= '1'; - ELSE - set(directSR) <= '1'; - END IF; - next_micro_state <= rte1; - END IF; - ELSE - trap_priv <= '1'; - trapmake <= '1'; - END IF; - - WHEN "1110101" => --rts - datatype <= "10"; - IF decodeOPC='1' THEN - setstate <= "10"; - set(postadd) <= '1'; - setstackaddr <= '1'; - set(direct_delta) <= '1'; - set(directPC) <= '1'; - next_micro_state <= nopnop; - END IF; - - WHEN "1110110" => --trapv - IF decodeOPC='1' THEN - setstate <= "01"; - END IF; - IF Flags(1)='1' AND state="01" THEN - trap_trapv <= '1'; - trapmake <= '1'; - END IF; - - WHEN "1111010"|"1111011" => --movec - IF VBR_Stackframe=0 OR (cpu(0)='0' AND VBR_Stackframe=2) THEN - trap_illegal <= '1'; - trapmake <= '1'; - ELSIF SVmode='0' THEN - trap_priv <= '1'; - trapmake <= '1'; - ELSE - datatype <= "10"; --Long - IF last_data_read(11 downto 0)=X"800" THEN - set(from_USP) <= '1'; - IF opcode(0)='1' THEN - set(to_USP) <= '1'; - END IF; - END IF; - IF opcode(0)='0' THEN - set_exec(movec_rd) <= '1'; - ELSE - set_exec(movec_wr) <= '1'; - END IF; - IF decodeOPC='1' THEN - next_micro_state <= movec1; - getbrief <='1'; - END IF; - END IF; - - WHEN OTHERS => - trap_illegal <= '1'; - trapmake <= '1'; - END CASE; - END IF; - WHEN OTHERS => NULL; - END CASE; - END IF; --- ----- 0101 ---------------------------------------------------------------------------- - WHEN "0101" => --subq, addq - - IF opcode(7 downto 6)="11" THEN --dbcc - IF opcode(5 downto 3)="001" THEN --dbcc - IF decodeOPC='1' THEN - next_micro_state <= dbcc1; - set(OP2out_one) <= '1'; - data_is_source <= '1'; - END IF; - ELSE --Scc - datatype <= "00"; --Byte - ea_build_now <= '1'; - write_back <= '1'; - set_exec(opcScc) <= '1'; - IF cpu(0)='1' AND state="10" THEN - skipFetch <= '1'; - END IF; - IF opcode(5 downto 4)="00" THEN - set_exec(Regwrena) <= '1'; - END IF; - END IF; - ELSE --addq, subq - ea_build_now <= '1'; - IF opcode(5 downto 3)="001" THEN - set(no_Flags) <= '1'; - END IF; - IF opcode(8)='1' THEN - set(addsub) <= '1'; - END IF; - write_back <= '1'; - set_exec(opcADDQ) <= '1'; - set_exec(opcADD) <= '1'; - set_exec(ea_data_OP1) <= '1'; - IF opcode(5 downto 4)="00" THEN - set_exec(Regwrena) <= '1'; - END IF; - END IF; --- ----- 0110 ---------------------------------------------------------------------------- - WHEN "0110" => --bra,bsr,bcc - datatype <= "10"; - - IF micro_state=idle THEN - IF opcode(11 downto 8)="0001" THEN --bsr - set(presub) <= '1'; - setstackaddr <='1'; - IF opcode(7 downto 0)="11111111" THEN - next_micro_state <= bsr2; - set(longaktion) <= '1'; - ELSIF opcode(7 downto 0)="00000000" THEN - next_micro_state <= bsr2; - ELSE - next_micro_state <= bsr1; - setstate <= "11"; - writePC <= '1'; - END IF; - ELSE --bra - IF opcode(7 downto 0)="11111111" THEN - next_micro_state <= bra1; - set(longaktion) <= '1'; - ELSIF opcode(7 downto 0)="00000000" THEN - next_micro_state <= bra1; - ELSE - setstate <= "01"; - next_micro_state <= bra1; - END IF; - END IF; - END IF; - --- 0111 ---------------------------------------------------------------------------- - WHEN "0111" => --moveq --- IF opcode(8)='0' THEN -- Cloanto's Amiga Forver ROMs have mangled movq instructions with a 1 here... - IF trap_interrupt='0' AND trap_trace='0' THEN - datatype <= "10"; --Long - set_exec(Regwrena) <= '1'; - set_exec(opcMOVEQ) <= '1'; - set_exec(opcMOVE) <= '1'; - dest_hbits <= '1'; - END IF; --- ELSE --- trap_illegal <= '1'; --- trapmake <= '1'; --- END IF; - ----- 1000 ---------------------------------------------------------------------------- - WHEN "1000" => --or - IF opcode(7 downto 6)="11" THEN --divu, divs - IF DIV_Mode/=3 THEN - IF opcode(5 downto 4)="00" THEN --Dn, An - regdirectsource <= '1'; - END IF; - IF (micro_state=idle AND nextpass='1') OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN - setstate <="01"; - next_micro_state <= div1; - END IF; - ea_build_now <= '1'; - IF z_error='0' AND set_V_Flag='0' THEN - set_exec(Regwrena) <= '1'; - END IF; - source_lowbits <='1'; - IF nextpass='1' OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN - dest_hbits <= '1'; - END IF; - datatype <= "01"; - ELSE - trap_illegal <= '1'; - trapmake <= '1'; - END IF; - - ELSIF opcode(8)='1' AND opcode(5 downto 4)="00" THEN --sbcd, pack , unpack - IF opcode(7 downto 6)="00" THEN --sbcd - build_bcd <= '1'; - set_exec(opcADD) <= '1'; - set_exec(opcSBCD) <= '1'; - ELSIF cpu(1)='1' AND (opcode(7 downto 6)="01" OR opcode(7 downto 6)="10") THEN --pack, unpack - datatype <= "01"; --Word - set_exec(opcPACK) <= '1'; - set(no_Flags) <= '1'; -- this command modifies no flags - - -- immediate value is kept in op1 - -- source value is in op2 - - -- xyz - if opcode(3)='0' then -- R/M bit = 0 -> Dy->Dy, 1 -(Ax),-(Ay) - dest_hbits <='1'; -- dest register is encoded in bits 9-11 - source_lowbits <= '1'; -- source register is encoded in bits 0-2 - - set_exec(Regwrena) <= '1'; -- write result into register - set_exec(ea_data_OP1) <= '1'; -- immediate value goes into op2 - set(hold_dwr) <= '1'; - - -- pack writes a byte only - IF opcode(7 downto 6) = "01" THEN - datatype <= "00"; --Byte - ELSE - datatype <= "01"; --Word - END IF; - - IF decodeOPC='1' THEN - next_micro_state <= nop; - set_direct_data <= '1'; - END IF; - else - set_exec(ea_data_OP1) <= '1'; - source_lowbits <= '1'; -- source register is encoded in bits 0-2 - - IF decodeOPC='1' THEN - -- first step: read source value - IF opcode(7 downto 6) = "10" THEN -- UNPK reads a byte - datatype <= "00"; -- Byte - END IF; - set_direct_data <= '1'; - setstate <= "10"; - set(update_ld) <= '1'; - set(presub) <= '1'; - next_micro_state <= pack1; - dest_areg <= '1'; --??? - end IF; - end IF; - ELSE - trap_illegal <= '1'; - trapmake <= '1'; - END IF; - ELSE --or - set_exec(opcOR) <= '1'; - build_logical <= '1'; - END IF; - ----- 1001, 1101 ----------------------------------------------------------------------- - WHEN "1001"|"1101" => --sub, add - set_exec(opcADD) <= '1'; - ea_build_now <= '1'; - IF opcode(14)='0' THEN - set(addsub) <= '1'; - END IF; - IF opcode(7 downto 6)="11" THEN -- --adda, suba - IF opcode(8)='0' THEN --adda.w, suba.w - datatype <= "01"; --Word - END IF; - set_exec(Regwrena) <= '1'; - source_lowbits <='1'; - IF opcode(3)='1' THEN - source_areg <= '1'; - END IF; - set(no_Flags) <= '1'; - IF setexecOPC='1' THEN - dest_areg <='1'; - dest_hbits <= '1'; - END IF; - ELSE - IF opcode(8)='1' AND opcode(5 downto 4)="00" THEN --addx, subx - build_bcd <= '1'; - ELSE --sub, add - build_logical <= '1'; - END IF; - END IF; - --- ----- 1010 ---------------------------------------------------------------------------- - WHEN "1010" => --Trap 1010 - trap_1010 <= '1'; - trapmake <= '1'; ----- 1011 ---------------------------------------------------------------------------- - WHEN "1011" => --eor, cmp - ea_build_now <= '1'; - IF opcode(7 downto 6)="11" THEN --CMPA - IF opcode(8)='0' THEN --cmpa.w - datatype <= "01"; --Word - set_exec(opcCPMAW) <= '1'; - END IF; - set_exec(opcCMP) <= '1'; - IF setexecOPC='1' THEN - source_lowbits <='1'; - IF opcode(3)='1' THEN - source_areg <= '1'; - END IF; - dest_areg <='1'; - dest_hbits <= '1'; - END IF; - set(addsub) <= '1'; - ELSE - IF opcode(8)='1' THEN - IF opcode(5 downto 3)="001" THEN --cmpm - set_exec(opcCMP) <= '1'; - IF decodeOPC='1' THEN - setstate <= "10"; - set(update_ld) <= '1'; - set(postadd) <= '1'; - next_micro_state <= cmpm; - END IF; - set_exec(ea_data_OP1) <= '1'; - set(addsub) <= '1'; - ELSE --EOR - build_logical <= '1'; - set_exec(opcEOR) <= '1'; - END IF; - ELSE --CMP - build_logical <= '1'; - set_exec(opcCMP) <= '1'; - set(addsub) <= '1'; - END IF; - END IF; --- ----- 1100 ---------------------------------------------------------------------------- - WHEN "1100" => --and, exg - IF opcode(7 downto 6)="11" THEN --mulu, muls - IF MUL_Mode/=3 THEN - IF opcode(5 downto 4)="00" THEN --Dn, An - regdirectsource <= '1'; - END IF; - IF (micro_state=idle AND nextpass='1') OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN - setstate <="01"; - set(ld_rot_cnt) <= '1'; - next_micro_state <= mul1; - END IF; - ea_build_now <= '1'; - set_exec(Regwrena) <= '1'; - source_lowbits <='1'; - IF (nextpass='1') OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN - dest_hbits <= '1'; - END IF; - datatype <= "01"; - ELSE - trap_illegal <= '1'; - trapmake <= '1'; - END IF; - - ELSIF opcode(8)='1' AND opcode(5 downto 4)="00" THEN --exg, abcd - IF opcode(7 downto 6)="00" THEN --abcd - build_bcd <= '1'; - set_exec(opcADD) <= '1'; - set_exec(opcABCD) <= '1'; - ELSE --exg - datatype <= "10"; - set(Regwrena) <= '1'; - set(exg) <= '1'; - IF opcode(6)='1' AND opcode(3)='1' THEN - dest_areg <= '1'; - source_areg <= '1'; - END IF; - IF decodeOPC='1' THEN - setstate <= "01"; - ELSE - dest_hbits <= '1'; - END IF; - END IF; - ELSE --and - set_exec(opcAND) <= '1'; - build_logical <= '1'; - END IF; --- ----- 1110 ---------------------------------------------------------------------------- - WHEN "1110" => --rotation / bitfield - IF opcode(7 downto 6)="11" THEN - IF opcode(11)='0' THEN - set_exec(opcROT) <= '1'; - ea_build_now <= '1'; - datatype <= "01"; - set_rot_bits <= opcode(10 downto 9); - set_exec(ea_data_OP1) <= '1'; - write_back <= '1'; - ELSE --bitfield - IF BitField=0 OR (cpu(1)='0' AND BitField=2) THEN - trap_illegal <= '1'; - trapmake <= '1'; - ELSE - IF decodeOPC='1' THEN - next_micro_state <= nop; - set(get_2ndOPC) <= '1'; - set(ea_build) <= '1'; - END IF; - set_exec(opcBF) <= '1'; - IF opcode(10)='1' OR opcode(8)='0' THEN - set_exec(opcBFwb) <= '1'; - IF opcode(10 downto 8)/="111" THEN -- bfins - set_exec(ea_data_OP2) <= '1'; -- for the flags - END IF; - set_exec(ea_data_OP1) <= '1'; - END IF; - - -- BFCHG, BFCLR, BFSET, BFINS - IF opcode(10 downto 8)="010" OR opcode(10 downto 8)="100" OR opcode(10 downto 8)="110" OR opcode(10 downto 8)="111" THEN - write_back <= '1'; - END IF; - ea_only <= '1'; - -- BFEXTU, BFEXTS, BFFFO - IF opcode(10 downto 8)="001" OR opcode(10 downto 8)="011" OR opcode(10 downto 8)="101" THEN - set_exec(Regwrena) <= '1'; - END IF; - -- register destination - IF opcode(4 downto 3)="00" THEN - set_exec(Regwrena) <= '1'; - IF exec(ea_build)='1' THEN - dest_2ndHbits <= '1'; - source_2ndLbits <= '1'; - set(get_bfoffset) <='1'; - setstate <= "01"; - END IF; - END IF; - IF set(get_ea_now)='1' THEN - setstate <= "01"; - END IF; - IF exec(get_ea_now)='1' THEN - dest_2ndHbits <= '1'; - source_2ndLbits <= '1'; - set(get_bfoffset) <='1'; - setstate <= "01"; - set(mem_addsub) <='1'; - next_micro_state <= bf1; - END IF; - --- BFINS D1,D0 s2ndHbits < D0 --- BFEXT D0,D1 sLbits >>D0 -> D1 d2ndHbits --- BFINS D1,(A0) s2ndHbits < (A0) --- BFEXT (A0),D1 >>(A0) -> D1 d2ndHbits - IF setexecOPC='1' THEN - IF opcode(10 downto 8)="111" THEN --BFINS - source_2ndHbits <= '1'; - ELSIF opcode(10 downto 8)="001" or opcode(10 downto 8)="011" THEN --BFEXT - source_lowbits <= '1'; - dest_2ndHbits <= '1'; - END IF; - END IF; - END IF; - END IF; - ELSE - set_exec(opcROT) <= '1'; - set_rot_bits <= opcode(4 downto 3); - data_is_source <= '1'; - set_exec(Regwrena) <= '1'; - IF decodeOPC='1' THEN - IF opcode(5)='1' THEN - next_micro_state <= rota1; - set(ld_rot_cnt) <= '1'; - setstate <= "01"; - ELSE - set_rot_cnt(2 downto 0) <= opcode(11 downto 9); - IF opcode(11 downto 9)="000" THEN - set_rot_cnt(3) <='1'; - ELSE - set_rot_cnt(3) <='0'; - END IF; - END IF; - END IF; - END IF; --- ----- ---------------------------------------------------------------------------- - WHEN OTHERS => - trap_1111 <= '1'; - trapmake <= '1'; - - END CASE; - --- use for AND, OR, EOR, CMP - IF build_logical='1' THEN - ea_build_now <= '1'; - IF set_exec(opcCMP)='0' AND (opcode(8)='0' OR opcode(5 downto 4)="00" ) THEN - set_exec(Regwrena) <= '1'; - END IF; - IF opcode(8)='1' THEN - write_back <= '1'; - set_exec(ea_data_OP1) <= '1'; - ELSE - source_lowbits <='1'; - IF opcode(3)='1' THEN --use for cmp - source_areg <= '1'; - END IF; - IF setexecOPC='1' THEN - dest_hbits <= '1'; - END IF; - END IF; - END IF; - --- use for ABCD, SBCD - IF build_bcd='1' THEN - set_exec(use_XZFlag) <= '1'; + ------------------------------------------------------------------------------ + --prepere opcode + ------------------------------------------------------------------------------ + case opcode(15 downto 12) is + -- 0000 ---------------------------------------------------------------------------- + when "0000" => + if opcode(8) = '1' and opcode(5 downto 3) = "001" then --movep + datatype <= "00"; --Byte + set(use_SP) <= '1'; --addr+2 + set(no_Flags) <= '1'; + if opcode(7) = '0' then --to register + set_exec(Regwrena) <= '1'; + set_exec(opcMOVE) <= '1'; + set(movepl) <= '1'; + end if; + if decodeOPC = '1' then + if opcode(6) = '1' then + set(movepl) <= '1'; + end if; + if opcode(7) = '0' then + set_direct_data <= '1'; -- to register + end if; + next_micro_state <= movep1; + end if; + if setexecOPC = '1' then + dest_hbits <= '1'; + end if; + else + if opcode(8) = '1' or opcode(11 downto 9) = "100" then --Bits + set_exec(opcBITS) <= '1'; set_exec(ea_data_OP1) <= '1'; - write_back <= '1'; - source_lowbits <='1'; - IF opcode(3)='1' THEN - IF decodeOPC='1' THEN - setstate <= "10"; - set(update_ld) <= '1'; - set(presub) <= '1'; - next_micro_state <= op_AxAy; - dest_areg <= '1'; --??? - END IF; - ELSE - dest_hbits <= '1'; + if opcode(7 downto 6) /= "00" then + if opcode(5 downto 4) = "00" then set_exec(Regwrena) <= '1'; - END IF; - END IF; + end if; + write_back <= '1'; + end if; + if opcode(5 downto 4) = "00" then + datatype <= "10"; --Long + else + datatype <= "00"; --Byte + end if; + if opcode(8) = '0' then + if decodeOPC = '1' then + next_micro_state <= nop; + set(get_2ndOPC) <= '1'; + set(ea_build) <= '1'; + end if; + else + ea_build_now <= '1'; + end if; + elsif opcode(11 downto 9) = "111" then --MOVES not in 68000 + trap_illegal <= '1'; + -- trap_addr_error <= '1'; + trapmake <= '1'; + else --andi, ...xxxi + if opcode(11 downto 9) = "000" then --orI + set_exec(opcor) <= '1'; + end if; + if opcode(11 downto 9) = "001" then --andI + set_exec(opcand) <= '1'; + end if; + if opcode(11 downto 9) = "010" or opcode(11 downto 9) = "011" then --SUBI, ADDI + set_exec(opcADD) <= '1'; + end if; + if opcode(11 downto 9) = "101" then --EorI + set_exec(opcEor) <= '1'; + end if; + if opcode(11 downto 9) = "110" then --CMPI + set_exec(opcCMP) <= '1'; + end if; + if opcode(7) = '0' and opcode(5 downto 0) = "111100" and (set_exec(opcand) or set_exec(opcor) or set_exec(opcEor)) = '1' then --SR + if decodeOPC = '1' and SVmode = '0' and opcode(6) = '1' then --SR + trap_priv <= '1'; + trapmake <= '1'; + else + set(no_Flags) <= '1'; + if decodeOPC = '1' then + if opcode(6) = '1' then + set(to_SR) <= '1'; + end if; + set(to_CCR) <= '1'; + set(andisR) <= set_exec(opcand); + set(eorisR) <= set_exec(opcEor); + set(orisR) <= set_exec(opcor); + setstate <= "01"; + next_micro_state <= nopnop; + end if; + end if; + else + if decodeOPC = '1' then + next_micro_state <= andi; + set(ea_build) <= '1'; + set_direct_data <= '1'; + if datatype = "10" then + set(longaktion) <= '1'; + end if; + end if; + if opcode(5 downto 4) /= "00" then + set_exec(ea_data_OP1) <= '1'; + end if; + if opcode(11 downto 9) /= "110" then --CMPI + if opcode(5 downto 4) = "00" then + set_exec(Regwrena) <= '1'; + end if; + write_back <= '1'; + end if; + if opcode(10 downto 9) = "10" then --CMPI, SUBI + set(addsub) <= '1'; + end if; + end if; + end if; + end if; + -- 0001, 0010, 0011 ----------------------------------------------------------------- + when "0001" | "0010" | "0011" => --move.b, move.l, move.w + set_exec(opcMOVE) <= '1'; + ea_build_now <= '1'; + if opcode(8 downto 6) = "001" then + set(no_Flags) <= '1'; + end if; + if opcode(5 downto 4) = "00" then --Dn, An + if opcode(8 downto 7) = "00" then + set_exec(Regwrena) <= '1'; + end if; + end if; + case opcode(13 downto 12) is + when "01" => datatype <= "00"; --Byte + when "10" => datatype <= "10"; --Long + when others => datatype <= "01"; --Word + end case; + source_lowbits <= '1'; -- Dn=> An=> + if opcode(3) = '1' then + source_areg <= '1'; + end if; ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- - IF set_Z_error='1' THEN -- divu by zero - trapmake <= '1'; --wichtig for USP - IF trapd='0' THEN - writePC <= '1'; - END IF; - END IF; + if nextpass = '1' or opcode(5 downto 4) = "00" then + dest_hbits <= '1'; + if opcode(8 downto 6) /= "000" then + dest_areg <= '1'; + end if; + end if; + -- if setstate="10" then + -- set(update_ld) <= '0'; + -- end if; + -- + if micro_state = idle and (nextpass = '1' or (opcode(5 downto 4) = "00" and decodeOPC = '1')) then + case opcode(8 downto 6) is --destination + when "000" | "001" => --Dn,An + set_exec(Regwrena) <= '1'; + when "010" | "011" | "100" => --destination -(an)+ + if opcode(6) = '1' then --(An)+ + set(postadd) <= '1'; + if opcode(11 downto 9) = "111" then + set(use_SP) <= '1'; + end if; + end if; + if opcode(8) = '1' then -- -(An) + set(presub) <= '1'; + if opcode(11 downto 9) = "111" then + set(use_SP) <= '1'; + end if; + end if; + setstate <= "11"; + next_micro_state <= nop; + if nextpass = '0' then + set(write_reg) <= '1'; + end if; + when "101" => --(d16,An) + next_micro_state <= st_dAn1; + -- getbrief <= '1'; + when "110" => --(d8,An,Xn) + next_micro_state <= st_AnXn1; + getbrief <= '1'; + when "111" => + case opcode(11 downto 9) is + when "000" => --(xxxx).w + next_micro_state <= st_nn; + when "001" => --(xxxx).l + set(longaktion) <= '1'; + next_micro_state <= st_nn; + when others => NULL; + end case; + when others => NULL; + end case; + end if; + ---- 0100 ---------------------------------------------------------------------------- + when "0100" => --rts_group + if opcode(8) = '1' then --lea + if opcode(6) = '1' then --lea + if opcode(7) = '1' then + source_lowbits <= '1'; + -- if opcode(5 downto 3)="000" and opcode(10)='0' then --ext + if opcode(5 downto 4) = "00" then --extb.l + set_exec(opcEXT) <= '1'; + set_exec(opcMOVE) <= '1'; + set_exec(Regwrena) <= '1'; + -- if opcode(6)='0' then + -- datatype <= "01"; --WorD + -- end if; + else + source_areg <= '1'; + ea_only <= '1'; + set_exec(Regwrena) <= '1'; + set_exec(opcMOVE) <= '1'; + set(no_Flags) <= '1'; + if opcode(5 downto 3) = "010" then --lea (Am),An + dest_areg <= '1'; + dest_hbits <= '1'; + else + ea_build_now <= '1'; + end if; + if set(get_ea_now) = '1' then + setstate <= "01"; + set_direct_data <= '1'; + end if; + if setexecOPC = '1' then + dest_areg <= '1'; + dest_hbits <= '1'; + end if; + end if; + else + trap_illegal <= '1'; + trapmake <= '1'; + end if; + else --chk + IF opcode(7)='1' AND opcode(5 downto 0) /= "111111" THEN + datatype <= "01"; --Word + set(trap_chk) <= '1'; + if (c_out(1) = '0' or OP1out(15) = '1' or OP2out(15) = '1') and exec(opcCHK) = '1' then + trapmake <= '1'; + end if; + elsif cpu(1) = '1' then --chk long for 68020 + datatype <= "10"; --Long + set(trap_chk) <= '1'; + if (c_out(2) = '1' or OP1out(31) = '1' or OP2out(31) = '1') and exec(opcCHK) = '1' then + trapmake <= '1'; + end if; + else + trap_illegal <= '1'; -- chk long for 68020 + trapmake <= '1'; + end if; + if opcode(7) = '1' or cpu(1) = '1' then + if (nextpass = '1' or opcode(5 downto 4) = "00") and exec(opcCHK) = '0' and micro_state = idle then + set_exec(opcCHK) <= '1'; + end if; + ea_build_now <= '1'; + set(addsub) <= '1'; + if setexecOPC = '1' then + dest_hbits <= '1'; + source_lowbits <= '1'; + end if; + end if; + end if; + else + case opcode(11 downto 9) is + when "000" => + if opcode(7 downto 6) = "11" then --move from SR + if SR_Read = 0 or (cpu(0) = '0' and SR_Read = 2) or SVmode = '1' then + -- if SVmode='1' then + ea_build_now <= '1'; + set_exec(opcMOVESR) <= '1'; + datatype <= "01"; + write_back <= '1'; -- 68000 also reads first + if cpu(0) = '1' and state = "10" then + skipFetch <= '1'; + end if; + if opcode(5 downto 4) = "00" then + set_exec(Regwrena) <= '1'; + end if; + else + trap_priv <= '1'; + trapmake <= '1'; + end if; + else --negx + ea_build_now <= '1'; + set_exec(use_XZFlag) <= '1'; + write_back <= '1'; + set_exec(opcADD) <= '1'; + set(addsub) <= '1'; + source_lowbits <= '1'; + if opcode(5 downto 4) = "00" then + set_exec(Regwrena) <= '1'; + end if; + if setexecOPC = '1' then + set(OP1out_zero) <= '1'; + end if; + end if; + when "001" => + if opcode(7 downto 6) = "11" then --move from CCR 68010 + if SR_Read = 1 or (cpu(0) = '1' and SR_Read = 2) then + ea_build_now <= '1'; + set_exec(opcMOVECCR) <= '1'; + --datatype <= "00"; -- WRONG, should be WORD zero extended. + datatype <= "01"; -- WRONG, should be WORD zero extended. + write_back <= '1'; -- 68000 also reads first + if opcode(5 downto 4) = "00" then + set_exec(Regwrena) <= '1'; + end if; + else + trap_illegal <= '1'; + trapmake <= '1'; + end if; + else --clr + ea_build_now <= '1'; + write_back <= '1'; + set_exec(opcand) <= '1'; + if cpu(0) = '1' and state = "10" then + skipFetch <= '1'; + end if; + if setexecOPC = '1' then + set(OP1out_zero) <= '1'; + end if; + if opcode(5 downto 4) = "00" then + set_exec(Regwrena) <= '1'; + end if; + end if; + when "010" => + ea_build_now <= '1'; + if opcode(7 downto 6) = "11" then --move to CCR + datatype <= "01"; + source_lowbits <= '1'; + if (decodeOPC = '1' and opcode(5 downto 4) = "00") or state = "10" or direct_data = '1' then + set(to_CCR) <= '1'; + end if; + else --neg + write_back <= '1'; + set_exec(opcADD) <= '1'; + set(addsub) <= '1'; + source_lowbits <= '1'; + if opcode(5 downto 4) = "00" then + set_exec(Regwrena) <= '1'; + end if; + if setexecOPC = '1' then + set(OP1out_zero) <= '1'; + end if; + end if; + when "011" => --not, move toSR + if opcode(7 downto 6) = "11" then --move to SR + if SVmode = '1' then + ea_build_now <= '1'; + datatype <= "01"; + source_lowbits <= '1'; + if (decodeOPC = '1' and opcode(5 downto 4) = "00") or state = "10" or direct_data = '1' then + set(to_SR) <= '1'; + set(to_CCR) <= '1'; + end if; + if exec(to_SR) = '1' or (decodeOPC = '1' and opcode(5 downto 4) = "00") or state = "10" or direct_data = '1' then + setstate <= "01"; + end if; + else + trap_priv <= '1'; + trapmake <= '1'; + end if; + else --not + ea_build_now <= '1'; + write_back <= '1'; + set_exec(opcEor) <= '1'; + set_exec(ea_data_OP1) <= '1'; + if opcode(5 downto 3) = "000" then + set_exec(Regwrena) <= '1'; + end if; + if setexecOPC = '1' then + set(OP2out_one) <= '1'; + end if; + end if; + when "100" | "110" => + if opcode(7) = '1' then --movem, ext + if opcode(5 downto 3) = "000" and opcode(10) = '0' then --ext + source_lowbits <= '1'; + set_exec(opcEXT) <= '1'; + set_exec(opcMOVE) <= '1'; + set_exec(Regwrena) <= '1'; + if opcode(6) = '0' then + datatype <= "01"; --WorD + end if; + else --movem + -- if opcode(11 downto 7)="10001" or opcode(11 downto 7)="11001" then --MOVEM + ea_only <= '1'; + set(no_Flags) <= '1'; + if opcode(6) = '0' then + datatype <= "01"; --Word transfer + end if; + if (opcode(5 downto 3) = "100" or opcode(5 downto 3) = "011") and state = "01" then -- -(An), (An)+ + set_exec(save_memaddr) <= '1'; + set_exec(Regwrena) <= '1'; + end if; + if opcode(5 downto 3) = "100" then -- -(An) + movem_presub <= '1'; + set(subidx) <= '1'; + end if; + if state = "10" then + set(Regwrena) <= '1'; + set(opcMOVE) <= '1'; + end if; + if decodeOPC = '1' then + set(get_2ndOPC) <= '1'; + if opcode(5 downto 3) = "010" or opcode(5 downto 3) = "011" or opcode(5 downto 3) = "100" then + next_micro_state <= movem1; + else + next_micro_state <= nop; + set(ea_build) <= '1'; + end if; + end if; + if set(get_ea_now) = '1' then + if movem_run = '1' then + set(movem_action) <= '1'; + if opcode(10) = '0' then + setstate <= "11"; + set(write_reg) <= '1'; + else + setstate <= "10"; + end if; + next_micro_state <= movem2; + set(mem_addsub) <= '1'; + else + setstate <= "01"; + end if; + end if; + end if; + else + if opcode(10) = '1' then --MUL.L, DIV.L 68020 + -- if cpu(1)='1' then + if (opcode(6) = '1' and (DIV_Mode = 1 or (cpu(1) = '1' and DIV_Mode = 2))) or + (opcode(6) = '0' and (MUL_Mode = 1 or (cpu(1) = '1' and MUL_Mode = 2))) then + if decodeOPC = '1' then + next_micro_state <= nop; + set(get_2ndOPC) <= '1'; + set(ea_build) <= '1'; + end if; + if (micro_state = idle and nextpass = '1') or (opcode(5 downto 4) = "00" and exec(ea_build) = '1') then + setstate <= "01"; + dest_2ndHbits <= '1'; + source_2ndLbits <= '1'; + if opcode(6) = '1' then + next_micro_state <= div1; + else + next_micro_state <= mul1; + set(ld_rot_cnt) <= '1'; + end if; + end if; + if z_error = '0' and set_V_Flag = '0' and set(opcDIVU) = '1' then + set(Regwrena) <= '1'; + end if; + source_lowbits <= '1'; + if nextpass = '1' or (opcode(5 downto 4) = "00" and decodeOPC = '1') then + dest_hbits <= '1'; + end if; + datatype <= "10"; + else + trap_illegal <= '1'; + trapmake <= '1'; + end if; ------------------------------------------------------------------------------ --- execute microcode ------------------------------------------------------------------------------ - IF rising_edge(clk) THEN - IF Reset='1' THEN - micro_state <= ld_nn; - ELSIF clkena_lw='1' THEN - trapd <= trapmake; - micro_state <= next_micro_state; - END IF; - END IF; + else --pea, swap + if opcode(6) = '1' then + datatype <= "10"; + if opcode(5 downto 3) = "000" then --swap + set_exec(opcSWAP) <= '1'; + set_exec(Regwrena) <= '1'; + elsif opcode(5 downto 3) = "001" then --bkpt - CASE micro_state IS - WHEN ld_nn => -- (nnnn).w/l=> - set(get_ea_now) <='1'; - setnextpass <= '1'; - set(addrlong) <= '1'; - - WHEN st_nn => -- =>(nnnn).w/l - setstate <= "11"; - set(addrlong) <= '1'; - next_micro_state <= nop; - - WHEN ld_dAn1 => -- d(An)=>, --d(PC)=> - set(get_ea_now) <='1'; - setdisp <= '1'; --word - setnextpass <= '1'; - - WHEN ld_AnXn1 => -- d(An,Xn)=>, --d(PC,Xn)=> - IF brief(8)='0' OR extAddr_Mode=0 OR (cpu(1)='0' AND extAddr_Mode=2) THEN - -- mikej brief extension word only - setdisp <= '1'; --byte - setdispbyte <= '1'; - setstate <= "01"; - set(briefext) <= '1'; - next_micro_state <= ld_AnXn2; - ELSE - IF brief(7)='1'THEN --suppress Base - set_suppress_base <= '1'; - ELSIF exec(dispouter)='1' THEN - set(dispouter) <= '1'; - END IF; - IF brief(5)='0' THEN --NULL Base Displacement - setstate <= "01"; - ELSE --WORD Base Displacement - IF brief(4)='1' THEN - set(longaktion) <= '1'; --LONG Base Displacement - END IF; - END IF; - next_micro_state <= ld_229_1; - END IF; - - WHEN ld_AnXn2 => - set(get_ea_now) <='1'; - setdisp <= '1'; --brief - setnextpass <= '1'; - -------------------------------------------------------------------------------------- - - WHEN ld_229_1 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> - IF brief(5)='1' THEN --Base Displacement - setdisp <= '1'; --add last_data_read - END IF; - IF brief(6)='0' AND brief(2)='0' THEN --Preindex or Index - set(briefext) <= '1'; - setstate <= "01"; - IF brief(1 downto 0)="00" THEN - next_micro_state <= ld_AnXn2; - ELSE - next_micro_state <= ld_229_2; - END IF; - ELSE - IF brief(1 downto 0)="00" THEN - set(get_ea_now) <='1'; - setnextpass <= '1'; - ELSE - setstate <= "10"; - set(longaktion) <= '1'; - next_micro_state <= ld_229_3; - END IF; - END IF; - - WHEN ld_229_2 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> - setdisp <= '1'; -- add Index - setstate <= "10"; - set(longaktion) <= '1'; - next_micro_state <= ld_229_3; - - WHEN ld_229_3 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> - set_suppress_base <= '1'; - set(dispouter) <= '1'; - IF brief(1)='0' THEN --NULL Outer Displacement - setstate <= "01"; - ELSE --WORD Outer Displacement - IF brief(0)='1' THEN - set(longaktion) <= '1'; --LONG Outer Displacement - END IF; - END IF; - next_micro_state <= ld_229_4; - - WHEN ld_229_4 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> - IF brief(1)='1' THEN -- Outer Displacement - setdisp <= '1'; --add last_data_read - END IF; - IF brief(6)='0' AND brief(2)='1' THEN --Postindex - set(briefext) <= '1'; - setstate <= "01"; - next_micro_state <= ld_AnXn2; - ELSE - set(get_ea_now) <='1'; - setnextpass <= '1'; - END IF; - ----------------------------------------------------------------------------------------- - WHEN st_dAn1 => -- =>d(An) - setstate <= "11"; - setdisp <= '1'; --word - next_micro_state <= nop; - - WHEN st_AnXn1 => -- =>d(An,Xn) - IF brief(8)='0' OR extAddr_Mode=0 OR (cpu(1)='0' AND extAddr_Mode=2) THEN - setdisp <= '1'; --byte - setdispbyte <= '1'; - setstate <= "01"; - set(briefext) <= '1'; - next_micro_state <= st_AnXn2; - ELSE - IF brief(7)='1'THEN --suppress Base - set_suppress_base <= '1'; --- ELSIF exec(dispouter)='1' THEN --- set(dispouter) <= '1'; - END IF; - IF brief(5)='0' THEN --NULL Base Displacement - setstate <= "01"; - ELSE --WORD Base Displacement - IF brief(4)='1' THEN - set(longaktion) <= '1'; --LONG Base Displacement - END IF; - END IF; - next_micro_state <= st_229_1; - END IF; - - WHEN st_AnXn2 => - setstate <= "11"; - setdisp <= '1'; --brief - next_micro_state <= nop; - -------------------------------------------------------------------------------------- - - WHEN st_229_1 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> - IF brief(5)='1' THEN --Base Displacement - setdisp <= '1'; --add last_data_read - END IF; - IF brief(6)='0' AND brief(2)='0' THEN --Preindex or Index - set(briefext) <= '1'; - setstate <= "01"; - IF brief(1 downto 0)="00" THEN - next_micro_state <= st_AnXn2; - ELSE - next_micro_state <= st_229_2; - END IF; - ELSE - IF brief(1 downto 0)="00" THEN - setstate <= "11"; - next_micro_state <= nop; - ELSE - set(hold_dwr) <= '1'; - setstate <= "10"; - set(longaktion) <= '1'; - next_micro_state <= st_229_3; - END IF; - END IF; - - WHEN st_229_2 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> - setdisp <= '1'; -- add Index - set(hold_dwr) <= '1'; - setstate <= "10"; - set(longaktion) <= '1'; - next_micro_state <= st_229_3; - - WHEN st_229_3 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> - set(hold_dwr) <= '1'; - set_suppress_base <= '1'; - set(dispouter) <= '1'; - IF brief(1)='0' THEN --NULL Outer Displacement - setstate <= "01"; - ELSE --WORD Outer Displacement - IF brief(0)='1' THEN - set(longaktion) <= '1'; --LONG Outer Displacement - END IF; - END IF; - next_micro_state <= st_229_4; - - WHEN st_229_4 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> - set(hold_dwr) <= '1'; - IF brief(1)='1' THEN -- Outer Displacement - setdisp <= '1'; --add last_data_read - END IF; - IF brief(6)='0' AND brief(2)='1' THEN --Postindex - set(briefext) <= '1'; - setstate <= "01"; - next_micro_state <= st_AnXn2; - ELSE + else --pea + ea_only <= '1'; + ea_build_now <= '1'; + if nextpass = '1' and micro_state = idle then + set(presub) <= '1'; + setstackaddr <= '1'; setstate <= "11"; next_micro_state <= nop; - END IF; - ----------------------------------------------------------------------------------------- - WHEN bra1 => --bra - IF exe_condition='1' THEN - TG68_PC_brw <= '1'; --pc+0000 - next_micro_state <= nop; - skipFetch <= '1'; - END IF; - - WHEN bsr1 => --bsr short - TG68_PC_brw <= '1'; - next_micro_state <= nop; - - WHEN bsr2 => --bsr - IF long_start='0' THEN - TG68_PC_brw <= '1'; - END IF; - skipFetch <= '1'; - set(longaktion) <= '1'; - writePC <= '1'; - setstate <= "11"; - next_micro_state <= nopnop; - setstackaddr <='1'; - WHEN nopnop => --bsr - next_micro_state <= nop; - - WHEN dbcc1 => --dbcc - IF exe_condition='0' THEN - Regwrena_now <= '1'; - IF c_out(1)='1' THEN - skipFetch <= '1'; - next_micro_state <= nop; - TG68_PC_brw <= '1'; - END IF; - END IF; - - WHEN movem1 => --movem - IF last_data_read(15 downto 0)/=X"0000" THEN - setstate <="01"; - IF opcode(5 downto 3)="100" THEN - set(mem_addsub) <= '1'; - END IF; - next_micro_state <= movem2; - END IF; - WHEN movem2 => --movem - IF movem_run='0' THEN - setstate <="01"; - ELSE - set(movem_action) <= '1'; + end if; + if set(get_ea_now) = '1' then + setstate <= "01"; + end if; + end if; + else + if opcode(5 downto 3) = "001" then --link.l + datatype <= "10"; + set_exec(opcADD) <= '1'; --for displacement + set_exec(Regwrena) <= '1'; + set(no_Flags) <= '1'; + if decodeOPC = '1' then + set(linksp) <= '1'; + set(longaktion) <= '1'; + next_micro_state <= link1; + set(presub) <= '1'; + setstackaddr <= '1'; set(mem_addsub) <= '1'; - next_micro_state <= movem2; - IF opcode(10)='0' THEN - setstate <="11"; - set(write_reg) <= '1'; - ELSE - setstate <="10"; - END IF; - END IF; - - WHEN andi => --andi - IF opcode(5 downto 4)/="00" THEN - setnextpass <= '1'; - END IF; - - WHEN op_AxAy => -- op -(Ax),-(Ay) - set_direct_data <= '1'; - set(presub) <= '1'; - dest_hbits <= '1'; - dest_areg <= '1'; - setstate <= "10"; - - WHEN cmpm => -- cmpm (Ay)+,(Ax)+ - set_direct_data <= '1'; - set(postadd) <= '1'; - dest_hbits <= '1'; - dest_areg <= '1'; - setstate <= "10"; - - WHEN link1 => -- link - setstate <="11"; + source_lowbits <= '1'; + source_areg <= '1'; + set(store_ea_data) <= '1'; + end if; + else --nbcd + ea_build_now <= '1'; + set_exec(use_XZFlag) <= '1'; + write_back <= '1'; + set_exec(opcADD) <= '1'; + set_exec(opcSBCD) <= '1'; + source_lowbits <= '1'; + if opcode(5 downto 4) = "00" then + set_exec(Regwrena) <= '1'; + end if; + if setexecOPC = '1' then + set(OP1out_zero) <= '1'; + end if; + end if; + end if; + end if; + end if; + -- + when "101" => --tst, tas 4aFC - illegal + if opcode(7 downto 2) = "111111" then --illegal + trap_illegal <= '1'; + trapmake <= '1'; + else + ea_build_now <= '1'; + if setexecOPC = '1' then + source_lowbits <= '1'; + if opcode(3) = '1' then --MC68020... source_areg <= '1'; - set(opcMOVE) <= '1'; - set(Regwrena) <= '1'; - next_micro_state <= link2; - WHEN link2 => -- link - setstackaddr <='1'; - set(ea_data_OP2) <= '1'; + end if; + end if; + set_exec(opcMOVE) <= '1'; + if opcode(7 downto 6) = "11" then --tas + set_exec_tas <= '1'; + write_back <= '1'; + datatype <= "00"; --Byte + if opcode(5 downto 4) = "00" then + set_exec(Regwrena) <= '1'; + end if; + end if; + end if; + ---- when "110"=> + when "111" => --4EXX + -- + -- ea_only <= '1'; + -- ea_build_now <= '1'; + -- if nextpass='1' and micro_state=idle then + -- set(presub) <= '1'; + -- setstackaddr <='1'; + -- set(mem_addsub) <= '1'; + -- setstate <="11"; + -- next_micro_state <= nop; + -- end if; + -- if set(get_ea_now)='1' then + -- setstate <="01"; + -- end if; + -- - WHEN unlink1 => -- unlink - setstate <="10"; - setstackaddr <='1'; - set(postadd) <= '1'; - next_micro_state <= unlink2; - WHEN unlink2 => -- unlink - set(ea_data_OP2) <= '1'; + if opcode(7) = '1' then --jsr, jmp + datatype <= "10"; + ea_only <= '1'; + ea_build_now <= '1'; + if exec(ea_to_pc) = '1' then + next_micro_state <= nop; + end if; + if nextpass = '1' and micro_state = idle and opcode(6) = '0' then + set(presub) <= '1'; + setstackaddr <= '1'; + setstate <= "11"; + next_micro_state <= nopnop; + end if; + -- achtung buggefahr + if micro_state = ld_AnXn1 and brief(8) = '0' then --JMP/JSR n(Ax,Dn) + skipFetch <= '1'; + end if; + if state = "00" then + writePC <= '1'; + end if; + set(hold_dwr) <= '1'; + if set(get_ea_now) = '1' then --jsr + if exec(longaktion) = '0' or long_done = '1' then + skipFetch <= '1'; + end if; + setstate <= "01"; + set(ea_to_pc) <= '1'; + end if; + else -- + case opcode(6 downto 0) is + when "1000000" | "1000001" | "1000010" | "1000011" | "1000100" | "1000101" | "1000110" | "1000111" | --trap + "1001000" | "1001001" | "1001010" | "1001011" | "1001100" | "1001101" | "1001110" | "1001111" => --trap + trap_trap <= '1'; + trapmake <= '1'; + when "1010000" | "1010001" | "1010010" | "1010011" | "1010100" | "1010101" | "1010110" | "1010111" => --link + datatype <= "10"; + set_exec(opcADD) <= '1'; --for displacement + set_exec(Regwrena) <= '1'; + set(no_Flags) <= '1'; + if decodeOPC = '1' then + next_micro_state <= link1; + set(presub) <= '1'; + setstackaddr <= '1'; + set(mem_addsub) <= '1'; + source_lowbits <= '1'; + source_areg <= '1'; + set(store_ea_data) <= '1'; + end if; - WHEN trap0 => -- TRAP - set(presub) <= '1'; - setstackaddr <='1'; - setstate <= "11"; - IF VBR_Stackframe=1 OR (cpu(0)='1' AND VBR_Stackframe=2) THEN --68010 - set(writePC_add) <= '1'; - datatype <= "01"; --- set_datatype <= "10"; - next_micro_state <= trap1; - ELSE - IF trap_interrupt='1' OR trap_trace='1' OR trap_berr='1' THEN - writePC <= '1'; - END IF; - datatype <= "10"; - next_micro_state <= trap2; - END IF; - WHEN trap1 => -- TRAP - IF trap_interrupt='1' OR trap_trace='1' THEN - writePC <= '1'; - END IF; - set(presub) <= '1'; - setstackaddr <='1'; - setstate <= "11"; + when "1011000" | "1011001" | "1011010" | "1011011" | "1011100" | "1011101" | "1011110" | "1011111" => --unlink datatype <= "10"; - next_micro_state <= trap2; - WHEN trap2 => -- TRAP - set(presub) <= '1'; - setstackaddr <='1'; - setstate <= "11"; - datatype <= "01"; - writeSR <= '1'; - IF trap_berr='1' THEN - next_micro_state <= trap4; - ELSE - next_micro_state <= trap3; - END IF; - WHEN trap3 => -- TRAP - set_vectoraddr <= '1'; - datatype <= "10"; - set(direct_delta) <= '1'; - set(directPC) <= '1'; - setstate <= "10"; - next_micro_state <= nopnop; - WHEN trap4 => -- TRAP - set(presub) <= '1'; - setstackaddr <='1'; - setstate <= "11"; - datatype <= "01"; - writeSR <= '1'; - next_micro_state <= trap5; - WHEN trap5 => -- TRAP - set(presub) <= '1'; - setstackaddr <='1'; - setstate <= "11"; - datatype <= "10"; - writeSR <= '1'; - next_micro_state <= trap6; - WHEN trap6 => -- TRAP - set(presub) <= '1'; - setstackaddr <='1'; - setstate <= "11"; - datatype <= "01"; - writeSR <= '1'; - next_micro_state <= trap3; - WHEN rte1 => -- RTE - datatype <= "10"; - setstate <= "10"; - set(postadd) <= '1'; - setstackaddr <= '1'; - IF VBR_Stackframe=0 OR (cpu(0)='0' AND VBR_Stackframe=2) THEN - set(direct_delta) <= '1'; - END IF; - set(directPC) <= '1'; - next_micro_state <= rte2; - WHEN rte2 => -- RTE - datatype <= "01"; - set(update_FC) <= '1'; - IF VBR_Stackframe=1 OR (cpu(0)='1' AND VBR_Stackframe=2) THEN + set_exec(Regwrena) <= '1'; + set_exec(opcMOVE) <= '1'; + set(no_Flags) <= '1'; + if decodeOPC = '1' then + setstate <= "01"; + next_micro_state <= unlink1; + set(opcMOVE) <= '1'; + set(Regwrena) <= '1'; + setstackaddr <= '1'; + source_lowbits <= '1'; + source_areg <= '1'; + end if; + + when "1100000" | "1100001" | "1100010" | "1100011" | "1100100" | "1100101" | "1100110" | "1100111" => --move An,USP + if SVmode = '1' then + -- set(no_Flags) <= '1'; + set(to_USP) <= '1'; + source_lowbits <= '1'; + source_areg <= '1'; + datatype <= "10"; + else + trap_priv <= '1'; + trapmake <= '1'; + end if; + when "1101000" | "1101001" | "1101010" | "1101011" | "1101100" | "1101101" | "1101110" | "1101111" => --move USP,An + if SVmode = '1' then + -- set(no_Flags) <= '1'; + set(from_USP) <= '1'; + datatype <= "10"; + set_exec(Regwrena) <= '1'; + else + trap_priv <= '1'; + trapmake <= '1'; + end if; + + when "1110000" => --reset + if SVmode = '0' then + trap_priv <= '1'; + trapmake <= '1'; + else + set(opcRESET) <= '1'; + if decodeOPC = '1' then + set(ld_rot_cnt) <= '1'; + set_rot_cnt <= "000000"; + end if; + end if; + + when "1110001" => --nop + + when "1110010" => --stop + if SVmode = '0' then + trap_priv <= '1'; + trapmake <= '1'; + else + if decodeOPC = '1' then + setnextpass <= '1'; + set_stop <= '1'; + end if; + if stop = '1' then + skipFetch <= '1'; + end if; + + end if; + + when "1110011" | "1110111" => --rte/rtr + if SVmode = '1' or opcode(2) = '1' then + if decodeOPC = '1' then setstate <= "10"; set(postadd) <= '1'; setstackaddr <= '1'; - next_micro_state <= rte3; - ELSE - next_micro_state <= nop; - END IF; - WHEN rte3 => -- RTE + if opcode(2) = '1' then + set(directCCR) <= '1'; + else + set(directSR) <= '1'; + end if; + next_micro_state <= rte1; + end if; + else + trap_priv <= '1'; + trapmake <= '1'; + end if; + + when "1110101" => --rts + datatype <= "10"; + if decodeOPC = '1' then + setstate <= "10"; + set(postadd) <= '1'; + setstackaddr <= '1'; + set(direct_delta) <= '1'; + set(directPC) <= '1'; + next_micro_state <= nopnop; + end if; + + when "1110110" => --trapv + if decodeOPC = '1' then + setstate <= "01"; + end if; + if Flags(1) = '1' and state = "01" then + trap_trapv <= '1'; + trapmake <= '1'; + end if; + + when "1111010" | "1111011" => --movec + if VBR_Stackframe = 0 or (cpu(0) = '0' and VBR_Stackframe = 2) then + trap_illegal <= '1'; + trapmake <= '1'; + elsif SVmode = '0' then + trap_priv <= '1'; + trapmake <= '1'; + else + datatype <= "10"; --Long + if last_data_read(11 downto 0) = X"800" then + set(from_USP) <= '1'; + if opcode(0) = '1' then + set(to_USP) <= '1'; + end if; + end if; + if opcode(0) = '0' then + set_exec(movec_rd) <= '1'; + else + set_exec(movec_wr) <= '1'; + end if; + if decodeOPC = '1' then + next_micro_state <= movec1; + getbrief <= '1'; + end if; + end if; + + when others => + trap_illegal <= '1'; + trapmake <= '1'; + end case; + end if; + when others => NULL; + end case; + end if; + -- + ---- 0101 ---------------------------------------------------------------------------- + when "0101" => --subq, addq + + if opcode(7 downto 6) = "11" then --dbcc + if opcode(5 downto 3) = "001" then --dbcc + if decodeOPC = '1' then + next_micro_state <= dbcc1; + set(OP2out_one) <= '1'; + data_is_source <= '1'; + end if; + else --Scc + datatype <= "00"; --Byte + ea_build_now <= '1'; + write_back <= '1'; + set_exec(opcScc) <= '1'; + if cpu(0) = '1' and state = "10" then + skipFetch <= '1'; + end if; + if opcode(5 downto 4) = "00" then + set_exec(Regwrena) <= '1'; + end if; + end if; + else --addq, subq + ea_build_now <= '1'; + if opcode(5 downto 3) = "001" then + set(no_Flags) <= '1'; + end if; + if opcode(8) = '1' then + set(addsub) <= '1'; + end if; + write_back <= '1'; + set_exec(opcADDQ) <= '1'; + set_exec(opcADD) <= '1'; + set_exec(ea_data_OP1) <= '1'; + if opcode(5 downto 4) = "00" then + set_exec(Regwrena) <= '1'; + end if; + end if; + -- + ---- 0110 ---------------------------------------------------------------------------- + when "0110" => --bra,bsr,bcc + datatype <= "10"; + + if micro_state = idle then + if opcode(11 downto 8) = "0001" then --bsr + set(presub) <= '1'; + setstackaddr <= '1'; + if opcode(7 downto 0) = "11111111" then + next_micro_state <= bsr2; + set(longaktion) <= '1'; + elsif opcode(7 downto 0) = "00000000" then + next_micro_state <= bsr2; + else + next_micro_state <= bsr1; + setstate <= "11"; + writePC <= '1'; + end if; + else --bra + if opcode(7 downto 0) = "11111111" then + next_micro_state <= bra1; + set(longaktion) <= '1'; + elsif opcode(7 downto 0) = "00000000" then + next_micro_state <= bra1; + else + setstate <= "01"; + next_micro_state <= bra1; + end if; + end if; + end if; + + -- 0111 ---------------------------------------------------------------------------- + when "0111" => --moveq + -- if opcode(8)='0' then -- Cloanto's Amiga Forver ROMs have mangled movq instructions with a 1 here... + if trap_interrupt = '0' and trap_trace = '0' then + datatype <= "10"; --Long + set_exec(Regwrena) <= '1'; + set_exec(opcMOVEQ) <= '1'; + set_exec(opcMOVE) <= '1'; + dest_hbits <= '1'; + end if; + -- else + -- trap_illegal <= '1'; + -- trapmake <= '1'; + -- end if; + + ---- 1000 ---------------------------------------------------------------------------- + when "1000" => --or + if opcode(7 downto 6) = "11" then --divu, divs + if DIV_Mode /= 3 then + if opcode(5 downto 4) = "00" then --Dn, An + regdirectsource <= '1'; + end if; + if (micro_state = idle and nextpass = '1') or (opcode(5 downto 4) = "00" and decodeOPC = '1') then + setstate <= "01"; + next_micro_state <= div1; + end if; + ea_build_now <= '1'; + if z_error = '0' and set_V_Flag = '0' then + set_exec(Regwrena) <= '1'; + end if; + source_lowbits <= '1'; + if nextpass = '1' or (opcode(5 downto 4) = "00" and decodeOPC = '1') then + dest_hbits <= '1'; + end if; + datatype <= "01"; + else + trap_illegal <= '1'; + trapmake <= '1'; + end if; + + elsif opcode(8) = '1' and opcode(5 downto 4) = "00" then --sbcd, pack , unpack + if opcode(7 downto 6) = "00" then --sbcd + build_bcd <= '1'; + set_exec(opcADD) <= '1'; + set_exec(opcSBCD) <= '1'; + elsif cpu(1) = '1' and (opcode(7 downto 6) = "01" or opcode(7 downto 6) = "10") then --pack, unpack + datatype <= "01"; --Word + set_exec(opcPACK) <= '1'; + set(no_Flags) <= '1'; -- this command modifies no flags + -- immediate value is kept in op1 + -- source value is in op2 + + if opcode(3) = '0' then -- R/M bit = 0 -> Dy->Dy, 1 -(Ax),-(Ay) + dest_hbits <= '1'; -- dest register is encoded in bits 9-11 + source_lowbits <= '1'; -- source register is encoded in bits 0-2 + set_exec(Regwrena) <= '1'; -- write result into register + set_exec(ea_data_OP1) <= '1'; -- immediate value goes into op2 + set(hold_dwr) <= '1'; + -- pack writes a byte only + if opcode(7 downto 6) = "01" then + datatype <= "00"; --Byte + else + datatype <= "01"; --Word + end if; + if decodeOPC = '1' then + next_micro_state <= nop; + set_direct_data <= '1'; + end if; + else + set_exec(ea_data_OP1) <= '1'; + source_lowbits <= '1'; -- source register is encoded in bits 0-2 + if decodeOPC = '1' then + -- first step: read source value + if opcode(7 downto 6) = "10" then -- UNPK reads a byte + datatype <= "00"; -- Byte + end if; + set_direct_data <= '1'; + setstate <= "10"; + set(update_ld) <= '1'; + set(presub) <= '1'; + next_micro_state <= pack1; + dest_areg <= '1'; --??? + end if; + end if; + else + trap_illegal <= '1'; + trapmake <= '1'; + end if; + else --or + set_exec(opcor) <= '1'; + build_logical <= '1'; + end if; + + ---- 1001, 1101 ----------------------------------------------------------------------- + when "1001" | "1101" => --sub, add + set_exec(opcADD) <= '1'; + ea_build_now <= '1'; + if opcode(14) = '0' then + set(addsub) <= '1'; + end if; + if opcode(7 downto 6) = "11" then -- --adda, suba + if opcode(8) = '0' then --adda.w, suba.w + datatype <= "01"; --Word + end if; + set_exec(Regwrena) <= '1'; + source_lowbits <= '1'; + if opcode(3) = '1' then + source_areg <= '1'; + end if; + set(no_Flags) <= '1'; + if setexecOPC = '1' then + dest_areg <= '1'; + dest_hbits <= '1'; + end if; + else + if opcode(8) = '1' and opcode(5 downto 4) = "00" then --addx, subx + build_bcd <= '1'; + else --sub, add + build_logical <= '1'; + end if; + end if; + + -- + ---- 1010 ---------------------------------------------------------------------------- + when "1010" => --Trap 1010 + trap_1010 <= '1'; + trapmake <= '1'; + ---- 1011 ---------------------------------------------------------------------------- + when "1011" => --eor, cmp + ea_build_now <= '1'; + if opcode(7 downto 6) = "11" then --CMPA + if opcode(8) = '0' then --cmpa.w + datatype <= "01"; --Word + set_exec(opcCPMAW) <= '1'; + end if; + set_exec(opcCMP) <= '1'; + if setexecOPC = '1' then + source_lowbits <= '1'; + if opcode(3) = '1' then + source_areg <= '1'; + end if; + dest_areg <= '1'; + dest_hbits <= '1'; + end if; + set(addsub) <= '1'; + else + if opcode(8) = '1' then + if opcode(5 downto 3) = "001" then --cmpm + set_exec(opcCMP) <= '1'; + if decodeOPC = '1' then + setstate <= "10"; + set(update_ld) <= '1'; + set(postadd) <= '1'; + next_micro_state <= cmpm; + end if; + set_exec(ea_data_OP1) <= '1'; + set(addsub) <= '1'; + else --Eor + build_logical <= '1'; + set_exec(opcEor) <= '1'; + end if; + else --CMP + build_logical <= '1'; + set_exec(opcCMP) <= '1'; + set(addsub) <= '1'; + end if; + end if; + -- + ---- 1100 ---------------------------------------------------------------------------- + when "1100" => --and, exg + if opcode(7 downto 6) = "11" then --mulu, muls + if MUL_Mode /= 3 then + if opcode(5 downto 4) = "00" then --Dn, An + regdirectsource <= '1'; + end if; + if (micro_state = idle and nextpass = '1') or (opcode(5 downto 4) = "00" and decodeOPC = '1') then + setstate <= "01"; + set(ld_rot_cnt) <= '1'; + next_micro_state <= mul1; + end if; + ea_build_now <= '1'; + set_exec(Regwrena) <= '1'; + source_lowbits <= '1'; + if (nextpass = '1') or (opcode(5 downto 4) = "00" and decodeOPC = '1') then + dest_hbits <= '1'; + end if; + datatype <= "01"; + else + trap_illegal <= '1'; + trapmake <= '1'; + end if; + + elsif opcode(8) = '1' and opcode(5 downto 4) = "00" then --exg, abcd + if opcode(7 downto 6) = "00" then --abcd + build_bcd <= '1'; + set_exec(opcADD) <= '1'; + set_exec(opcABCD) <= '1'; + else --exg + datatype <= "10"; + set(Regwrena) <= '1'; + set(exg) <= '1'; + if opcode(6) = '1' and opcode(3) = '1' then + dest_areg <= '1'; + source_areg <= '1'; + end if; + if decodeOPC = '1' then + setstate <= "01"; + else + dest_hbits <= '1'; + end if; + end if; + else --and + set_exec(opcand) <= '1'; + build_logical <= '1'; + end if; + -- + ---- 1110 ---------------------------------------------------------------------------- + when "1110" => --rotation / bitfield + if opcode(7 downto 6) = "11" then + if opcode(11) = '0' then + set_exec(opcROT) <= '1'; + ea_build_now <= '1'; + datatype <= "01"; + set_rot_bits <= opcode(10 downto 9); + set_exec(ea_data_OP1) <= '1'; + write_back <= '1'; + else --bitfield + if BitField = 0 or (cpu(1) = '0' and BitField = 2) then + trap_illegal <= '1'; + trapmake <= '1'; + else + if decodeOPC = '1' then + next_micro_state <= nop; + set(get_2ndOPC) <= '1'; + set(ea_build) <= '1'; + end if; + set_exec(opcBF) <= '1'; + + -- BFCLR, BFSET, BFINS, BFCHG, BFFFO, BFTST + if opcode(10) = '1' or opcode(8) = '0' then + set_exec(opcBFwb) <= '1'; + -- BFFFO operating on memory + if opcode(10 downto 8) = "101" and opcode(4 downto 3) /= "00" then + set_exec(ea_data_OP2) <= '1'; + end if; + set_exec(ea_data_OP1) <= '1'; + end if; + + -- BFCHG, BFCLR, BFSET, BFINS + if opcode(10 downto 8) = "010" or opcode(10 downto 8) = "100" or + opcode(10 downto 8) = "110" or opcode(10 downto 8) = "111" then + write_back <= '1'; + end if; + + ea_only <= '1'; + -- BFEXTU, BFEXTS, BFFFO + if opcode(10 downto 8) = "001" or opcode(10 downto 8) = "011" or + opcode(10 downto 8) = "101" then + set_exec(Regwrena) <= '1'; + end if; + + -- register destination + if opcode(4 downto 3) = "00" then + -- bftst doesn't write + if opcode(10 downto 8) /= "000" then + set_exec(Regwrena) <= '1'; + end if; + + if exec(ea_build) = '1' then + dest_2ndHbits <= '1'; + source_2ndLbits <= '1'; + set(get_bfoffset) <= '1'; + setstate <= "01"; + end if; + end if; + if set(get_ea_now) = '1' then + setstate <= "01"; + end if; + if exec(get_ea_now) = '1' then + dest_2ndHbits <= '1'; + source_2ndLbits <= '1'; + set(get_bfoffset) <= '1'; + setstate <= "01"; + set(mem_addsub) <= '1'; + next_micro_state <= bf1; + end if; + + if setexecOPC = '1' then + if opcode(10 downto 8) = "111" then --BFINS + source_2ndHbits <= '1'; + elsif opcode(10 downto 8)="001" or opcode(10 downto 8)="011" or + opcode(10 downto 8)="101" THEN + --BFEXTU, BFEXTS, BFFFO + source_lowbits <= '1'; + dest_2ndHbits <= '1'; + end if; + end if; + end if; + end if; + else + -- register rotation/shift + set_exec(opcROT) <= '1'; + set_rot_bits <= opcode(4 downto 3); + data_is_source <= '1'; + set_exec(Regwrena) <= '1'; + if decodeOPC = '1' then + if opcode(5) = '1' then + -- load rotation count from register + next_micro_state <= rota1; + set(ld_rot_cnt) <= '1'; + setstate <= "01"; + else -- xyz + set_alu_rot_cnt <= (others => '0'); + set_alu_rot_cnt(2 downto 0) <= opcode(11 downto 9); + if opcode(11 downto 9) = "000" then set_alu_rot_cnt(3) <= '1'; + else set_alu_rot_cnt(3) <= '0'; + end if; + + -- take rotation count from opcode + set_rot_cnt(2 downto 0) <= opcode(11 downto 9); + if opcode(11 downto 9) = "000" then + set_rot_cnt(3) <= '1'; + else + set_rot_cnt(3) <= '0'; + end if; + + -- lsr or lsl use a barrel shifter and are done immediately + if opcode(4 downto 3) = "01" then + set_rot_cnt <= "000001"; + end if; + + end if; + end if; + end if; + -- + ---- ---------------------------------------------------------------------------- + when others => + trap_1111 <= '1'; + trapmake <= '1'; + + end case; + + -- use for and, or, Eor, CMP + if build_logical = '1' then + ea_build_now <= '1'; + if set_exec(opcCMP) = '0' and (opcode(8) = '0' or opcode(5 downto 4) = "00" ) then + set_exec(Regwrena) <= '1'; + end if; + if opcode(8) = '1' then + write_back <= '1'; + set_exec(ea_data_OP1) <= '1'; + else + source_lowbits <= '1'; + if opcode(3) = '1' then --use for cmp + source_areg <= '1'; + end if; + if setexecOPC = '1' then + dest_hbits <= '1'; + end if; + end if; + end if; + + -- use for ABCD, SBCD + if build_bcd = '1' then + set_exec(use_XZFlag) <= '1'; + set_exec(ea_data_OP1) <= '1'; + write_back <= '1'; + source_lowbits <= '1'; + if opcode(3) = '1' then + if decodeOPC = '1' then + setstate <= "10"; + set(update_ld) <= '1'; + set(presub) <= '1'; + next_micro_state <= op_AxAy; + dest_areg <= '1'; --??? + end if; + else + dest_hbits <= '1'; + set_exec(Regwrena) <= '1'; + end if; + end if; + ------------------------------------------------------------------------------ + ------------------------------------------------------------------------------ + if set_Z_error = '1' then -- divu by zero + trapmake <= '1'; --wichtig for USP + if trapd = '0' then + writePC <= '1'; + end if; + end if; + + ----------------------------------------------------------------------------- + -- execute microcode + ----------------------------------------------------------------------------- + if rising_edge(clk) THEN + if Reset='1' THEN + micro_state <= ld_nn; + elsif clkena_lw='1' THEN + trapd <= trapmake; + micro_state <= next_micro_state; + end if; + end if; + + case micro_state is + when ld_nn => -- (nnnn).w/l=> + set(get_ea_now) <= '1'; + setnextpass <= '1'; + set(addrlong) <= '1'; + + when st_nn => -- =>(nnnn).w/l + setstate <= "11"; + set(addrlong) <= '1'; + next_micro_state <= nop; + + when ld_dAn1 => -- d(An)=>, --d(PC)=> + set(get_ea_now) <= '1'; + setdisp <= '1'; --word + setnextpass <= '1'; + + when ld_AnXn1 => -- d(An,Xn)=>, --d(PC,Xn)=> + if brief(8) = '0' or extAddr_Mode = 0 or (cpu(1) = '0' and extAddr_Mode = 2) then + -- mikej brief extension word only + setdisp <= '1'; --byte + setdispbyte <= '1'; + setstate <= "01"; + set(briefext) <= '1'; + next_micro_state <= ld_AnXn2; + else + if brief(7) = '1' then --suppress Base + set_suppress_base <= '1'; + elsif exec(dispouter) = '1' then + set(dispouter) <= '1'; + end if; + if brief(5) = '0' then --NULL Base Displacement + setstate <= "01"; + else --WorD Base Displacement + if brief(4) = '1' then + set(longaktion) <= '1'; --LONG Base Displacement + end if; + end if; + next_micro_state <= ld_229_1; + end if; + + when ld_AnXn2 => + set(get_ea_now) <= '1'; + setdisp <= '1'; --brief + setnextpass <= '1'; + + ------------------------------------------------------------------------------------- + + when ld_229_1 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + if brief(5) = '1' then --Base Displacement + setdisp <= '1'; --add last_data_read + end if; + if brief(6) = '0' and brief(2) = '0' then --Preindex or Index + set(briefext) <= '1'; + setstate <= "01"; + if brief(1 downto 0) = "00" then + next_micro_state <= ld_AnXn2; + else + next_micro_state <= ld_229_2; + end if; + else + if brief(1 downto 0) = "00" then + set(get_ea_now) <= '1'; + setnextpass <= '1'; + else + setstate <= "10"; + set(longaktion) <= '1'; + next_micro_state <= ld_229_3; + end if; + end if; + + when ld_229_2 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + setdisp <= '1'; -- add Index + setstate <= "10"; + set(longaktion) <= '1'; + next_micro_state <= ld_229_3; + + when ld_229_3 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + set_suppress_base <= '1'; + set(dispouter) <= '1'; + if brief(1) = '0' then --NULL Outer Displacement + setstate <= "01"; + else --WORD Outer Displacement + if brief(0) = '1' then + set(longaktion) <= '1'; --LONG Outer Displacement + end if; + end if; + next_micro_state <= ld_229_4; + + when ld_229_4 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + if brief(1) = '1' then -- Outer Displacement + setdisp <= '1'; --add last_data_read + end if; + if brief(6) = '0' and brief(2) = '1' then --Postindex + set(briefext) <= '1'; + setstate <= "01"; + next_micro_state <= ld_AnXn2; + else + set(get_ea_now) <= '1'; + setnextpass <= '1'; + end if; + + ---------------------------------------------------------------------------------------- + when st_dAn1 => -- =>d(An) + setstate <= "11"; + setdisp <= '1'; --word + next_micro_state <= nop; + + when st_AnXn1 => -- =>d(An,Xn) + if brief(8) = '0' or extAddr_Mode = 0 or (cpu(1) = '0' and extAddr_Mode = 2) then + setdisp <= '1'; --byte + setdispbyte <= '1'; + setstate <= "01"; + set(briefext) <= '1'; + next_micro_state <= st_AnXn2; + else + if brief(7) = '1' then --suppress Base + set_suppress_base <= '1'; + -- elsif exec(dispouter)='1' then + -- set(dispouter) <= '1'; + end if; + if brief(5) = '0' then --NULL Base Displacement + setstate <= "01"; + else --WorD Base Displacement + if brief(4) = '1' then + set(longaktion) <= '1'; --LONG Base Displacement + end if; + end if; + next_micro_state <= st_229_1; + end if; + + when st_AnXn2 => + setstate <= "11"; + setdisp <= '1'; --brief + next_micro_state <= nop; + + ------------------------------------------------------------------------------------- + + when st_229_1 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + if brief(5) = '1' then --Base Displacement + setdisp <= '1'; --add last_data_read + end if; + if brief(6) = '0' and brief(2) = '0' then --Preindex or Index + set(briefext) <= '1'; + setstate <= "01"; + if brief(1 downto 0) = "00" then + next_micro_state <= st_AnXn2; + else + next_micro_state <= st_229_2; + end if; + else + if brief(1 downto 0) = "00" then + setstate <= "11"; + next_micro_state <= nop; + else + set(hold_dwr) <= '1'; + setstate <= "10"; + set(longaktion) <= '1'; + next_micro_state <= st_229_3; + end if; + end if; + + when st_229_2 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + setdisp <= '1'; -- add Index + set(hold_dwr) <= '1'; + setstate <= "10"; + set(longaktion) <= '1'; + next_micro_state <= st_229_3; + + when st_229_3 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + set(hold_dwr) <= '1'; + set_suppress_base <= '1'; + set(dispouter) <= '1'; + if brief(1) = '0' then --NULL Outer Displacement + setstate <= "01"; + else --WorD Outer Displacement + if brief(0) = '1' then + set(longaktion) <= '1'; --LONG Outer Displacement + end if; + end if; + next_micro_state <= st_229_4; + + when st_229_4 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + set(hold_dwr) <= '1'; + if brief(1) = '1' then -- Outer Displacement + setdisp <= '1'; --add last_data_read + end if; + if brief(6) = '0' and brief(2) = '1' then --Postindex + set(briefext) <= '1'; + setstate <= "01"; + next_micro_state <= st_AnXn2; + else + setstate <= "11"; + next_micro_state <= nop; + end if; + + ---------------------------------------------------------------------------------------- + when bra1 => --bra + if exe_condition = '1' then + TG68_PC_brw <= '1'; --pc+0000 + next_micro_state <= nop; + skipFetch <= '1'; + end if; + + when bsr1 => --bsr short + TG68_PC_brw <= '1'; + next_micro_state <= nop; + + when bsr2 => --bsr + if long_start = '0' then + TG68_PC_brw <= '1'; + end if; + skipFetch <= '1'; + set(longaktion) <= '1'; + writePC <= '1'; + setstate <= "11"; + next_micro_state <= nopnop; + setstackaddr <= '1'; + when nopnop => --bsr + next_micro_state <= nop; + + when dbcc1 => --dbcc + if exe_condition = '0' then + Regwrena_now <= '1'; + if c_out(1) = '1' then + skipFetch <= '1'; + next_micro_state <= nop; + TG68_PC_brw <= '1'; + end if; + end if; + + when movem1 => --movem + if last_data_read(15 downto 0) /= X"0000" then + setstate <= "01"; + if opcode(5 downto 3) = "100" then + set(mem_addsub) <= '1'; + end if; + next_micro_state <= movem2; + end if; + + when movem2 => --movem + if movem_run = '0' then + setstate <= "01"; + else + set(movem_action) <= '1'; + set(mem_addsub) <= '1'; + next_micro_state <= movem2; + if opcode(10) = '0' then + setstate <= "11"; + set(write_reg) <= '1'; + else + setstate <= "10"; + end if; + end if; + + when andi => --andi + if opcode(5 downto 4) /= "00" then + setnextpass <= '1'; + end if; + + when op_AxAy => -- op -(Ax),-(Ay) + set_direct_data <= '1'; + set(presub) <= '1'; + dest_hbits <= '1'; + dest_areg <= '1'; + setstate <= "10"; + + when cmpm => -- cmpm (Ay)+,(Ax)+ + set_direct_data <= '1'; + set(postadd) <= '1'; + dest_hbits <= '1'; + dest_areg <= '1'; + setstate <= "10"; + + when link1 => -- link + setstate <= "11"; + source_areg <= '1'; + set(opcMOVE) <= '1'; + set(Regwrena) <= '1'; + next_micro_state <= link2; + when link2 => -- link + setstackaddr <= '1'; + set(ea_data_OP2) <= '1'; + + when unlink1 => -- unlink + setstate <= "10"; + setstackaddr <= '1'; + set(postadd) <= '1'; + next_micro_state <= unlink2; + + when unlink2 => -- unlink + set(ea_data_OP2) <= '1'; + + when trap00 => -- TRAP format #2 + next_micro_state <= trap0; + set(presub) <= '1'; + setstackaddr <='1'; + setstate <= "11"; + datatype <= "10"; + + when trap0 => -- TRAP + set(presub) <= '1'; + setstackaddr <= '1'; + setstate <= "11"; + if VBR_Stackframe = 1 or (cpu(0) = '1' and VBR_Stackframe = 2) then --68010 + set(writePC_add) <= '1'; + datatype <= "01"; + -- set_datatype <= "10"; + next_micro_state <= trap1; + else + if trap_interrupt='1' or trap_trace='1' or trap_berr='1' THEN + writePC <= '1'; + end if; + datatype <= "10"; + next_micro_state <= trap2; + end if; + + when trap1 => -- TRAP + -- additional word for 68020 + if trap_interrupt = '1' or trap_trace = '1' then + writePC <= '1'; + end if; + set(presub) <= '1'; + setstackaddr <= '1'; + setstate <= "11"; + datatype <= "10"; + next_micro_state <= trap2; + + when trap2 => -- TRAP + set(presub) <= '1'; + setstackaddr <= '1'; + setstate <= "11"; + datatype <= "01"; + writeSR <= '1'; + if trap_berr='1' THEN + next_micro_state <= trap4; + else + next_micro_state <= trap3; + end if; + + when trap3 => -- TRAP + set_vectoraddr <= '1'; + datatype <= "10"; + set(direct_delta) <= '1'; + set(directPC) <= '1'; + setstate <= "10"; + next_micro_state <= nopnop; + + when trap4 => -- TRAP + set(presub) <= '1'; + setstackaddr <='1'; + setstate <= "11"; + datatype <= "01"; + writeSR <= '1'; + next_micro_state <= trap5; + + when trap5 => -- TRAP + set(presub) <= '1'; + setstackaddr <='1'; + setstate <= "11"; + datatype <= "10"; + writeSR <= '1'; + next_micro_state <= trap6; + + when trap6 => -- TRAP + set(presub) <= '1'; + setstackaddr <='1'; + setstate <= "11"; + datatype <= "01"; + writeSR <= '1'; + next_micro_state <= trap3; + + -- return from exception - RTE + -- fetch PC and status register from stack + -- 010+ fetches another word containing + -- the 12 bit vector offset and the + -- frame format. If the frame format is + -- 2 another two words have to be taken + -- from the stack + when rte1 => -- RTE + datatype <= "10"; + setstate <= "10"; + set(postadd) <= '1'; + setstackaddr <= '1'; + if VBR_Stackframe = 0 or (cpu(0) = '0' and VBR_Stackframe = 2) then + set(direct_delta) <= '1'; + end if; + set(directPC) <= '1'; + next_micro_state <= rte2; + + when rte2 => -- RTE + datatype <= "01"; + set(update_FC) <= '1'; + if VBR_Stackframe = 1 or (cpu(0) = '1' and VBR_Stackframe = 2) then + -- 010+ reads another word + setstate <= "10"; + set(postadd) <= '1'; + setstackaddr <= '1'; + next_micro_state <= rte3; + else + next_micro_state <= nop; + end if; + when rte3 => -- RTE + setstate <= "01"; -- idle state to wait + -- for input data to + -- arrive + next_micro_state <= rte4; + WHEN rte4 => -- RTE + -- check for stack frame format #2 + if last_data_in(15 downto 12)="0010" then + -- read another 32 bits in this case + setstate <= "10"; -- read + datatype <= "10"; -- long word + set(postadd) <= '1'; + setstackaddr <= '1'; + next_micro_state <= rte5; + else + datatype <= "01"; + next_micro_state <= nop; + end if; + WHEN rte5 => -- RTE next_micro_state <= nop; --- set(update_FC) <= '1'; + when movec1 => -- MOVEC + set(briefext) <= '1'; + set_writePCbig <= '1'; + if (brief(11 downto 0) = X"000" or brief(11 downto 0) = X"001" or brief(11 downto 0) = X"800" or brief(11 downto 0) = X"801") or + (cpu(1) = '1' and (brief(11 downto 0) = X"002" or brief(11 downto 0) = X"802" or brief(11 downto 0) = X"803" or brief(11 downto 0) = X"804")) then + if opcode(0) = '0' then + set(Regwrena) <= '1'; + end if; + -- elsif brief(11 downto 0)=X"800"or brief(11 downto 0)=X"001" or brief(11 downto 0)=X"000" then + -- trap_addr_error <= '1'; + -- trapmake <= '1'; + else + trap_illegal <= '1'; + trapmake <= '1'; + end if; - WHEN movec1 => -- MOVEC - set(briefext) <= '1'; - set_writePCbig <='1'; - IF (brief(11 downto 0)=X"000" OR brief(11 downto 0)=X"001" OR brief(11 downto 0)=X"800" OR brief(11 downto 0)=X"801") OR - (cpu(1)='1' AND (brief(11 downto 0)=X"002" OR brief(11 downto 0)=X"802" OR brief(11 downto 0)=X"803" OR brief(11 downto 0)=X"804")) THEN - IF opcode(0)='0' THEN - set(Regwrena) <= '1'; - END IF; --- ELSIF brief(11 downto 0)=X"800"OR brief(11 downto 0)=X"001" OR brief(11 downto 0)=X"000" THEN --- trap_addr_error <= '1'; --- trapmake <= '1'; - ELSE - trap_illegal <= '1'; - trapmake <= '1'; - END IF; + when movep1 => -- MOVEP d(An) + setdisp <= '1'; + set(mem_addsub) <= '1'; + set(mem_byte) <= '1'; + set(OP1addr) <= '1'; + if opcode(6) = '1' then + set(movepl) <= '1'; + end if; + if opcode(7) = '0' then + setstate <= "10"; + else + setstate <= "11"; + end if; + next_micro_state <= movep2; - WHEN movep1 => -- MOVEP d(An) - setdisp <= '1'; - set(mem_addsub) <= '1'; - set(mem_byte) <= '1'; - set(OP1addr) <= '1'; - IF opcode(6)='1' THEN - set(movepl) <= '1'; - END IF; - IF opcode(7)='0' THEN - setstate <= "10"; - ELSE - setstate <= "11"; - END IF; - next_micro_state <= movep2; - WHEN movep2 => - IF opcode(6)='1' THEN - set(mem_addsub) <= '1'; - set(OP1addr) <= '1'; - END IF; - IF opcode(7)='0' THEN - setstate <= "10"; - ELSE - setstate <= "11"; - END IF; - next_micro_state <= movep3; - WHEN movep3 => - IF opcode(6)='1' THEN - set(mem_addsub) <= '1'; - set(OP1addr) <= '1'; - set(mem_byte) <= '1'; - IF opcode(7)='0' THEN - setstate <= "10"; - ELSE - setstate <= "11"; - END IF; - next_micro_state <= movep4; - ELSE - datatype <= "01"; --Word - END IF; - WHEN movep4 => - IF opcode(7)='0' THEN - setstate <= "10"; - ELSE - setstate <= "11"; - END IF; - next_micro_state <= movep5; - WHEN movep5 => - datatype <= "10"; --Long + when movep2 => + if opcode(6) = '1' then + set(mem_addsub) <= '1'; + set(OP1addr) <= '1'; + end if; + if opcode(7) = '0' then + setstate <= "10"; + else + setstate <= "11"; + end if; + next_micro_state <= movep3; - WHEN mul1 => -- mulu - IF opcode(15)='1' OR MUL_Mode=0 THEN - set_rot_cnt <= "001110"; - ELSE - set_rot_cnt <= "011110"; - END IF; - setstate <="01"; - next_micro_state <= mul2; - WHEN mul2 => -- mulu - setstate <="01"; - IF rot_cnt="00001" THEN - next_micro_state <= mul_end1; - ELSE - next_micro_state <= mul2; - END IF; - WHEN mul_end1 => -- mulu - datatype <= "10"; - set(opcMULU) <= '1'; - IF opcode(15)='0' AND (MUL_Mode=1 OR MUL_Mode=2) THEN - dest_2ndHbits <= '1'; - source_2ndLbits <= '1';--??? - set(write_lowlong) <= '1'; - IF sndOPC(10)='1' THEN - setstate <="01"; - next_micro_state <= mul_end2; - END IF; - set(Regwrena) <= '1'; - END IF; - datatype <= "10"; - WHEN mul_end2 => -- divu - set(write_reminder) <= '1'; - set(Regwrena) <= '1'; - set(opcMULU) <= '1'; + when movep3 => + if opcode(6) = '1' then + set(mem_addsub) <= '1'; + set(OP1addr) <= '1'; + set(mem_byte) <= '1'; + if opcode(7) = '0' then + setstate <= "10"; + else + setstate <= "11"; + end if; + next_micro_state <= movep4; + else + datatype <= "01"; --Word + end if; - WHEN div1 => -- divu - setstate <="01"; - next_micro_state <= div2; - WHEN div2 => -- divu - IF (OP2out(31 downto 16)=x"0000" OR opcode(15)='1' OR DIV_Mode=0) AND OP2out(15 downto 0)=x"0000" THEN --div zero - set_Z_error <= '1'; - ELSE - next_micro_state <= div3; - END IF; - set(ld_rot_cnt) <= '1'; - setstate <="01"; - WHEN div3 => -- divu - IF opcode(15)='1' OR DIV_Mode=0 THEN - set_rot_cnt <= "001101"; - ELSE - set_rot_cnt <= "011101"; - END IF; - setstate <="01"; - next_micro_state <= div4; - WHEN div4 => -- divu - setstate <="01"; - IF rot_cnt="00001" THEN - next_micro_state <= div_end1; - ELSE - next_micro_state <= div4; - END IF; - WHEN div_end1 => -- divu - IF opcode(15)='0' AND (DIV_Mode=1 OR DIV_Mode=2) THEN - set(write_reminder) <= '1'; - next_micro_state <= div_end2; - setstate <="01"; - END IF; - set(opcDIVU) <= '1'; - datatype <= "10"; - WHEN div_end2 => -- divu - dest_2ndHbits <= '1'; - source_2ndLbits <= '1';--??? - set(opcDIVU) <= '1'; + when movep4 => + if opcode(7) = '0' then + setstate <= "10"; + else + setstate <= "11"; + end if; + next_micro_state <= movep5; + when movep5 => + datatype <= "10"; --Long - WHEN rota1 => - IF OP2out(5 downto 0)/="000000" THEN - set_rot_cnt <= OP2out(5 downto 0); - ELSE - set_exec(rot_nop) <= '1'; - END IF; + when mul1 => -- mulu + if opcode(15) = '1' or MUL_Mode = 0 then + set_rot_cnt <= "001110"; + else + set_rot_cnt <= "011110"; + end if; + setstate <= "01"; + next_micro_state <= mul2; - WHEN bf1 => - setstate <="10"; + when mul2 => -- mulu + setstate <= "01"; + if rot_cnt = "00001" then + next_micro_state <= mul_end1; + else + next_micro_state <= mul2; + end if; - when pack1 => - -- result computation - IF opcode(7 downto 6) = "10" THEN -- UNPK reads a byte - datatype <= "00"; -- Byte - END IF; - set(ea_data_OP2) <= '1'; - set(opcPACK) <= '1'; - next_micro_state <= pack2; + when mul_end1 => -- mulu + datatype <= "10"; + set(opcMULU) <= '1'; + if opcode(15) = '0' and (MUL_Mode = 1 or MUL_Mode = 2) then + dest_2ndHbits <= '1'; + source_2ndLbits <= '1';--??? + set(write_lowlong) <= '1'; + if sndOPC(10) = '1' then + setstate <= "01"; + next_micro_state <= mul_end2; + end if; + set(Regwrena) <= '1'; + end if; + datatype <= "10"; - when pack2 => - -- write result - IF opcode(7 downto 6) = "01" THEN -- PACK writes a byte - datatype <= "00"; - END IF; - set(presub) <= '1'; - setstate <= "11"; - dest_hbits <= '1'; - dest_areg <= '1'; - next_micro_state <= pack3; + when mul_end2 => -- divu + set(write_reminder) <= '1'; + set(Regwrena) <= '1'; + set(opcMULU) <= '1'; - when pack3 => - -- this is just to keep datatype == 00 - -- for byte writes - -- write result - IF opcode(7 downto 6) = "01" THEN -- PACK writes a byte - datatype <= "00"; - END IF; + when div1 => -- divu + setstate <= "01"; + next_micro_state <= div2; - WHEN OTHERS => NULL; - END CASE; - END PROCESS; + when div2 => -- divu + if (OP2out(31 downto 16) = x"0000" or opcode(15) = '1' or DIV_Mode = 0) and OP2out(15 downto 0) = x"0000" then --div zero + set_Z_error <= '1'; + else + next_micro_state <= div3; + end if; + set(ld_rot_cnt) <= '1'; + setstate <= "01"; ------------------------------------------------------------------------------ --- MOVEC ------------------------------------------------------------------------------ -PROCESS (clk, VBR, CACR, brief) - BEGIN - IF rising_edge(clk) THEN - IF Reset = '1' THEN - VBR <= (OTHERS => '0'); - CACR <= (OTHERS => '0'); - ELSIF clkena_lw='1' AND exec(movec_wr)='1' THEN - CASE brief(11 downto 0) IS - WHEN X"002" => CACR <= reg_QA(3 downto 0); - WHEN X"801" => VBR <= reg_QA; - WHEN OTHERS => NULL; - END CASE; - END IF; - END IF; - movec_data <= (OTHERS=>'0'); - CASE brief(11 downto 0) IS - WHEN X"002" => movec_data <= "0000000000000000000000000000" & (CACR AND "0011"); - WHEN X"801" => --IF VBR_Stackframe=1 OR (cpu(0)='1' AND VBR_Stackframe=2) THEN - movec_data <= VBR; - --END IF; - WHEN OTHERS => NULL; - END CASE; - END PROCESS; + when div3 => -- divu + if opcode(15) = '1' or DIV_Mode = 0 then + set_rot_cnt <= "001101"; + else + set_rot_cnt <= "011101"; + end if; + setstate <= "01"; + next_micro_state <= div4; + + when div4 => -- divu + setstate <= "01"; + if rot_cnt = "00001" then + next_micro_state <= div_end1; + else + next_micro_state <= div4; + end if; + + when div_end1 => -- divu + if opcode(15) = '0' and (DIV_Mode = 1 or DIV_Mode = 2) then + set(write_reminder) <= '1'; + next_micro_state <= div_end2; + setstate <= "01"; + end if; + set(opcDIVU) <= '1'; + datatype <= "10"; + + when div_end2 => -- divu + dest_2ndHbits <= '1'; + source_2ndLbits <= '1';--??? + set(opcDIVU) <= '1'; + + when rota1 => + -- load rot_cnt from register + if opcode(4 downto 3) = "01" then -- lsl/lsr uses barrel shifter + set_alu_rot_cnt <= OP2out(5 downto 0); + else + if OP2out(5 downto 0) /= "000000" then + set_rot_cnt <= OP2out(5 downto 0); + else + set_exec(rot_nop) <= '1'; + end if; + end if; + + when bf1 => + setstate <= "10"; + + when pack1 => + -- result computation + if opcode(7 downto 6) = "10" then -- UNPK reads a byte + datatype <= "00"; -- Byte + end if; + set(ea_data_OP2) <= '1'; + set(opcPACK) <= '1'; + next_micro_state <= pack2; + + when pack2 => + -- write result + if opcode(7 downto 6) = "01" then -- PACK writes a byte + datatype <= "00"; + end if; + set(presub) <= '1'; + setstate <= "11"; + dest_hbits <= '1'; + dest_areg <= '1'; + next_micro_state <= pack3; + + when pack3 => + -- this is just to keep datatype == 00 + -- for byte writes + -- write result + if opcode(7 downto 6) = "01" then -- PACK writes a byte + datatype <= "00"; + end if; + when others => NULL; + end case; + end process; + + ----------------------------------------------------------------------------- + -- MOVEC + ----------------------------------------------------------------------------- + process (clk, VBR, CACR, brief) + begin + -- all other hexa codes should give illegal isntruction exception + if rising_edge(clk) then + if Reset = '1' then + VBR <= (others => '0'); + CACR <= (others => '0'); + elsif clkena_lw = '1' and exec(movec_wr) = '1' then + case brief(11 downto 0) is + when X"000" => NULL; -- SFC -- 68010+ + when X"001" => NULL; -- DFC -- 68010+ + when X"002" => CACR <= reg_QA(3 downto 0); -- 68020+ + when X"800" => NULL; -- USP -- 68010+ + when X"801" => VBR <= reg_QA; -- 68010+ + when X"802" => NULL; -- CAAR -- 68020+ + when X"803" => NULL; -- MSP -- 68020+ + when X"804" => NULL; -- isP -- 68020+ + when others => NULL; + end case; + end if; + end if; + + movec_data <= (others => '0'); + case brief(11 downto 0) is + when X"002" => movec_data <= "0000000000000000000000000000" & (CACR AND "0011"); + + when X"801" => --if VBR_Stackframe=1 or (cpu(0)='1' and VBR_Stackframe=2) then + movec_data <= VBR; + --end if; + when others => NULL; + end case; + end process; CACR_out <= CACR; VBR_out <= VBR; ------------------------------------------------------------------------------ --- Conditions ------------------------------------------------------------------------------ -PROCESS (exe_opcode, Flags) - BEGIN - CASE exe_opcode(11 downto 8) IS - WHEN X"0" => exe_condition <= '1'; - WHEN X"1" => exe_condition <= '0'; - WHEN X"2" => exe_condition <= NOT Flags(0) AND NOT Flags(2); - WHEN X"3" => exe_condition <= Flags(0) OR Flags(2); - WHEN X"4" => exe_condition <= NOT Flags(0); - WHEN X"5" => exe_condition <= Flags(0); - WHEN X"6" => exe_condition <= NOT Flags(2); - WHEN X"7" => exe_condition <= Flags(2); - WHEN X"8" => exe_condition <= NOT Flags(1); - WHEN X"9" => exe_condition <= Flags(1); - WHEN X"a" => exe_condition <= NOT Flags(3); - WHEN X"b" => exe_condition <= Flags(3); - WHEN X"c" => exe_condition <= (Flags(3) AND Flags(1)) OR (NOT Flags(3) AND NOT Flags(1)); - WHEN X"d" => exe_condition <= (Flags(3) AND NOT Flags(1)) OR (NOT Flags(3) AND Flags(1)); - WHEN X"e" => exe_condition <= (Flags(3) AND Flags(1) AND NOT Flags(2)) OR (NOT Flags(3) AND NOT Flags(1) AND NOT Flags(2)); - WHEN X"f" => exe_condition <= (Flags(3) AND NOT Flags(1)) OR (NOT Flags(3) AND Flags(1)) OR Flags(2); - WHEN OTHERS => NULL; - END CASE; - END PROCESS; + ----------------------------------------------------------------------------- + -- Conditions + ----------------------------------------------------------------------------- + process (exe_opcode, Flags) + begin + case exe_opcode(11 downto 8) is + when X"0" => exe_condition <= '1'; + when X"1" => exe_condition <= '0'; + when X"2" => exe_condition <= not Flags(0) and not Flags(2); + when X"3" => exe_condition <= Flags(0) or Flags(2); + when X"4" => exe_condition <= not Flags(0); + when X"5" => exe_condition <= Flags(0); + when X"6" => exe_condition <= not Flags(2); + when X"7" => exe_condition <= Flags(2); + when X"8" => exe_condition <= not Flags(1); + when X"9" => exe_condition <= Flags(1); + when X"a" => exe_condition <= not Flags(3); + when X"b" => exe_condition <= Flags(3); + when X"c" => exe_condition <= (Flags(3) and Flags(1)) or (not Flags(3) and not Flags(1)); + when X"d" => exe_condition <= (Flags(3) and not Flags(1)) or (not Flags(3) and Flags(1)); + when X"e" => exe_condition <= (Flags(3) and Flags(1) and not Flags(2)) or (not Flags(3) and not Flags(1) and not Flags(2)); + when X"f" => exe_condition <= (Flags(3) and not Flags(1)) or (not Flags(3) and Flags(1)) or Flags(2); + when others => NULL; + end case; + end process; ------------------------------------------------------------------------------ --- Movem ------------------------------------------------------------------------------ -PROCESS (clk) - BEGIN - IF rising_edge(clk) THEN - IF clkena_lw='1' THEN - movem_actiond <= exec(movem_action); - IF decodeOPC='1' THEN - sndOPC <= data_read(15 downto 0); - ELSIF exec(movem_action)='1' OR set(movem_action) ='1' THEN - CASE movem_regaddr IS - WHEN "0000" => sndOPC(0) <= '0'; - WHEN "0001" => sndOPC(1) <= '0'; - WHEN "0010" => sndOPC(2) <= '0'; - WHEN "0011" => sndOPC(3) <= '0'; - WHEN "0100" => sndOPC(4) <= '0'; - WHEN "0101" => sndOPC(5) <= '0'; - WHEN "0110" => sndOPC(6) <= '0'; - WHEN "0111" => sndOPC(7) <= '0'; - WHEN "1000" => sndOPC(8) <= '0'; - WHEN "1001" => sndOPC(9) <= '0'; - WHEN "1010" => sndOPC(10) <= '0'; - WHEN "1011" => sndOPC(11) <= '0'; - WHEN "1100" => sndOPC(12) <= '0'; - WHEN "1101" => sndOPC(13) <= '0'; - WHEN "1110" => sndOPC(14) <= '0'; - WHEN "1111" => sndOPC(15) <= '0'; - WHEN OTHERS => NULL; - END CASE; - END IF; - END IF; - END IF; - END PROCESS; + ----------------------------------------------------------------------------- + -- Movem + ----------------------------------------------------------------------------- + process (clk) + begin + if rising_edge(clk) then + if clkena_lw = '1' then + movem_actiond <= exec(movem_action); + if decodeOPC = '1' then + sndOPC <= data_read(15 downto 0); + elsif exec(movem_action) = '1' or set(movem_action) = '1' then + case movem_regaddr is + when "0000" => sndOPC(0) <= '0'; + when "0001" => sndOPC(1) <= '0'; + when "0010" => sndOPC(2) <= '0'; + when "0011" => sndOPC(3) <= '0'; + when "0100" => sndOPC(4) <= '0'; + when "0101" => sndOPC(5) <= '0'; + when "0110" => sndOPC(6) <= '0'; + when "0111" => sndOPC(7) <= '0'; + when "1000" => sndOPC(8) <= '0'; + when "1001" => sndOPC(9) <= '0'; + when "1010" => sndOPC(10) <= '0'; + when "1011" => sndOPC(11) <= '0'; + when "1100" => sndOPC(12) <= '0'; + when "1101" => sndOPC(13) <= '0'; + when "1110" => sndOPC(14) <= '0'; + when "1111" => sndOPC(15) <= '0'; + when others => NULL; + end case; + end if; + end if; + end if; + end process; -PROCESS (sndOPC, movem_mux) - BEGIN - movem_regaddr <="0000"; - movem_run <= '1'; - IF sndOPC(3 downto 0)="0000" THEN - IF sndOPC(7 downto 4)="0000" THEN - movem_regaddr(3) <= '1'; - IF sndOPC(11 downto 8)="0000" THEN - IF sndOPC(15 downto 12)="0000" THEN - movem_run <= '0'; - END IF; - movem_regaddr(2) <= '1'; - movem_mux <= sndOPC(15 downto 12); - ELSE - movem_mux <= sndOPC(11 downto 8); - END IF; - ELSE - movem_mux <= sndOPC(7 downto 4); - movem_regaddr(2) <= '1'; - END IF; - ELSE - movem_mux <= sndOPC(3 downto 0); - END IF; - IF movem_mux(1 downto 0)="00" THEN - movem_regaddr(1) <= '1'; - IF movem_mux(2)='0' THEN - movem_regaddr(0) <= '1'; - END IF; - ELSE - IF movem_mux(0)='0' THEN - movem_regaddr(0) <= '1'; - END IF; - END IF; - END PROCESS; + process (sndOPC, movem_mux) + begin + movem_regaddr <= "0000"; + movem_run <= '1'; + if sndOPC(3 downto 0) = "0000" then + if sndOPC(7 downto 4) = "0000" then + movem_regaddr(3) <= '1'; + if sndOPC(11 downto 8) = "0000" then + if sndOPC(15 downto 12) = "0000" then + movem_run <= '0'; + end if; + movem_regaddr(2) <= '1'; + movem_mux <= sndOPC(15 downto 12); + else + movem_mux <= sndOPC(11 downto 8); + end if; + else + movem_mux <= sndOPC(7 downto 4); + movem_regaddr(2) <= '1'; + end if; + else + movem_mux <= sndOPC(3 downto 0); + end if; - exec_d.opcMOVE <= exec(opcMOVE); - exec_d.opcMOVEQ <= exec(opcMOVEQ); - exec_d.opcMOVESR <= exec(opcMOVESR); - exec_d.opcADD <= exec(opcADD); - exec_d.opcADDQ <= exec(opcADDQ); - exec_d.opcOR <= exec(opcOR); - exec_d.opcAND <= exec(opcAND); - exec_d.opcEOR <= exec(opcEOR); - exec_d.opcCMP <= exec(opcCMP); - exec_d.opcROT <= exec(opcROT); - exec_d.opcCPMAW <= exec(opcCPMAW); - exec_d.opcEXT <= exec(opcEXT); - exec_d.opcABCD <= exec(opcABCD); - exec_d.opcSBCD <= exec(opcSBCD); - exec_d.opcBITS <= exec(opcBITS); - exec_d.opcSWAP <= exec(opcSWAP); - exec_d.opcScc <= exec(opcScc); - exec_d.andiSR <= exec(andiSR); - exec_d.eoriSR <= exec(eoriSR); - exec_d.oriSR <= exec(oriSR); - exec_d.opcMULU <= exec(opcMULU); - exec_d.opcDIVU <= exec(opcDIVU); - exec_d.dispouter <= exec(dispouter); - exec_d.rot_nop <= exec(rot_nop); - exec_d.ld_rot_cnt <= exec(ld_rot_cnt); - exec_d.writePC_add <= exec(writePC_add); - exec_d.ea_data_OP1 <= exec(ea_data_OP1); - exec_d.ea_data_OP2 <= exec(ea_data_OP2); - exec_d.use_XZFlag <= exec(use_XZFlag); - exec_d.get_bfoffset <= exec(get_bfoffset); - exec_d.save_memaddr <= exec(save_memaddr); - exec_d.opcCHK <= exec(opcCHK); - exec_d.movec_rd <= exec(movec_rd); - exec_d.movec_wr <= exec(movec_wr); - exec_d.Regwrena <= exec(Regwrena); - exec_d.update_FC <= exec(update_FC); - exec_d.linksp <= exec(linksp); - exec_d.movepl <= exec(movepl); - exec_d.update_ld <= exec(update_ld); - exec_d.OP1addr <= exec(OP1addr); - exec_d.write_reg <= exec(write_reg); - exec_d.changeMode <= exec(changeMode); - exec_d.ea_build <= exec(ea_build); - exec_d.trap_chk <= exec(trap_chk); - exec_d.store_ea_data <= exec(store_ea_data); - exec_d.addrlong <= exec(addrlong); - exec_d.postadd <= exec(postadd); - exec_d.presub <= exec(presub); - exec_d.subidx <= exec(subidx); - exec_d.no_Flags <= exec(no_Flags); - exec_d.use_SP <= exec(use_SP); - exec_d.to_CCR <= exec(to_CCR); - exec_d.to_SR <= exec(to_SR); - exec_d.OP2out_one <= exec(OP2out_one); - exec_d.OP1out_zero <= exec(OP1out_zero); - exec_d.mem_addsub <= exec(mem_addsub); - exec_d.addsub <= exec(addsub); - exec_d.directPC <= exec(directPC); - exec_d.direct_delta <= exec(direct_delta); - exec_d.directSR <= exec(directSR); - exec_d.directCCR <= exec(directCCR); - exec_d.exg <= exec(exg); - exec_d.get_ea_now <= exec(get_ea_now); - exec_d.ea_to_pc <= exec(ea_to_pc); - exec_d.hold_dwr <= exec(hold_dwr); - exec_d.to_USP <= exec(to_USP); - exec_d.from_USP <= exec(from_USP); - exec_d.write_lowlong <= exec(write_lowlong); - exec_d.write_reminder <= exec(write_reminder); - exec_d.movem_action <= exec(movem_action); - exec_d.briefext <= exec(briefext); - exec_d.get_2ndOPC <= exec(get_2ndOPC); - exec_d.mem_byte <= exec(mem_byte); - exec_d.longaktion <= exec(longaktion); - exec_d.opcRESET <= exec(opcRESET); - exec_d.opcBF <= exec(opcBF); - exec_d.opcBFwb <= exec(opcBFwb); - exec_d.s2nd_hbits <= exec(s2nd_hbits); + if movem_mux(1 downto 0) = "00" then + movem_regaddr(1) <= '1'; + if movem_mux(2) = '0' then + movem_regaddr(0) <= '1'; + end if; + else + if movem_mux(0) = '0' then + movem_regaddr(0) <= '1'; + end if; + end if; + end process; ---When the instruction has completed, the decremented address ---register contains the address of the last operand stored. For ---the MC68020, MC68030, and MC68040, if the addressing ---register is also moved to memory, the value written is the ---initial register value decremented by the size of the oper- ---ation. The MC68000 writes the initial register value ---(not decremented). + exec_d.opcMOVE <= exec(opcMOVE); + exec_d.opcMOVEQ <= exec(opcMOVEQ); + exec_d.opcMOVESR <= exec(opcMOVESR); + exec_d.opcMOVECCR <= exec(opcMOVECCR); + exec_d.opcADD <= exec(opcADD); + exec_d.opcADDQ <= exec(opcADDQ); + exec_d.opcor <= exec(opcor); + exec_d.opcand <= exec(opcand); + exec_d.opcEor <= exec(opcEor); + exec_d.opcCMP <= exec(opcCMP); + exec_d.opcROT <= exec(opcROT); + exec_d.opcCPMAW <= exec(opcCPMAW); + exec_d.opcEXT <= exec(opcEXT); + exec_d.opcABCD <= exec(opcABCD); + exec_d.opcSBCD <= exec(opcSBCD); + exec_d.opcBITS <= exec(opcBITS); + exec_d.opcSWAP <= exec(opcSWAP); + exec_d.opcScc <= exec(opcScc); + exec_d.andisR <= exec(andisR); + exec_d.eorisR <= exec(eorisR); + exec_d.orisR <= exec(orisR); + exec_d.opcMULU <= exec(opcMULU); + exec_d.opcDIVU <= exec(opcDIVU); + exec_d.dispouter <= exec(dispouter); + exec_d.rot_nop <= exec(rot_nop); + exec_d.ld_rot_cnt <= exec(ld_rot_cnt); + exec_d.writePC_add <= exec(writePC_add); + exec_d.ea_data_OP1 <= exec(ea_data_OP1); + exec_d.ea_data_OP2 <= exec(ea_data_OP2); + exec_d.use_XZFlag <= exec(use_XZFlag); + exec_d.get_bfoffset <= exec(get_bfoffset); + exec_d.save_memaddr <= exec(save_memaddr); + exec_d.opcCHK <= exec(opcCHK); + exec_d.movec_rd <= exec(movec_rd); + exec_d.movec_wr <= exec(movec_wr); + exec_d.Regwrena <= exec(Regwrena); + exec_d.update_FC <= exec(update_FC); + exec_d.linksp <= exec(linksp); + exec_d.movepl <= exec(movepl); + exec_d.update_ld <= exec(update_ld); + exec_d.OP1addr <= exec(OP1addr); + exec_d.write_reg <= exec(write_reg); + exec_d.changeMode <= exec(changeMode); + exec_d.ea_build <= exec(ea_build); + exec_d.trap_chk <= exec(trap_chk); + exec_d.store_ea_data <= exec(store_ea_data); + exec_d.addrlong <= exec(addrlong); + exec_d.postadd <= exec(postadd); + exec_d.presub <= exec(presub); + exec_d.subidx <= exec(subidx); + exec_d.no_Flags <= exec(no_Flags); + exec_d.use_SP <= exec(use_SP); + exec_d.to_CCR <= exec(to_CCR); + exec_d.to_SR <= exec(to_SR); + exec_d.OP2out_one <= exec(OP2out_one); + exec_d.OP1out_zero <= exec(OP1out_zero); + exec_d.mem_addsub <= exec(mem_addsub); + exec_d.addsub <= exec(addsub); + exec_d.directPC <= exec(directPC); + exec_d.direct_delta <= exec(direct_delta); + exec_d.directSR <= exec(directSR); + exec_d.directCCR <= exec(directCCR); + exec_d.exg <= exec(exg); + exec_d.get_ea_now <= exec(get_ea_now); + exec_d.ea_to_pc <= exec(ea_to_pc); + exec_d.hold_dwr <= exec(hold_dwr); + exec_d.to_USP <= exec(to_USP); + exec_d.from_USP <= exec(from_USP); + exec_d.write_lowlong <= exec(write_lowlong); + exec_d.write_reminder <= exec(write_reminder); + exec_d.movem_action <= exec(movem_action); + exec_d.briefext <= exec(briefext); + exec_d.get_2ndOPC <= exec(get_2ndOPC); + exec_d.mem_byte <= exec(mem_byte); + exec_d.longaktion <= exec(longaktion); + exec_d.opcRESET <= exec(opcRESET); + exec_d.opcBF <= exec(opcBF); + exec_d.opcBFwb <= exec(opcBFwb); + exec_d.opcPACK <= exec(opcPACK); + --when the instruction has completed, the decremented address + --register contains the address of the last operand stored. For + --the MC68020, MC68030, and MC68040, if the addressing + --register is also moved to memory, the value written is the + --initial register value decremented by the size of the oper- + --ation. The MC68000 writes the initial register value + --(not decremented). + + regin_out <= regin; + end; -END; diff --git a/cores/mist/mist_top.v b/cores/mist/mist_top.v index 36bae0c..fbc3d71 100644 --- a/cores/mist/mist_top.v +++ b/cores/mist/mist_top.v @@ -1,7 +1,7 @@ /********************************************/ /* */ /********************************************/ - + module mist_top ( // clock inputs input wire [ 2-1:0] CLOCK_27, // 27 MHz @@ -856,7 +856,7 @@ TG68KdotC_Kernel #(2,2,2,2,2,2) tg68k ( .berr (tg68_berr ), .clr_berr (tg68_clr_berr ), .CPU (system_ctrl[5:4] ), // 00=68000 - .addr (tg68_adr_S ), + .addr_out (tg68_adr_S ), .data_write (tg68_dat_out_S), .nUDS (tg68_uds_S ), .nLDS (tg68_lds_S ), diff --git a/tests/tg68k/TG68K_ALU.vhd b/tests/tg68k/TG68K_ALU.vhd index 613ff87..26a18d7 100644 --- a/tests/tg68k/TG68K_ALU.vhd +++ b/tests/tg68k/TG68K_ALU.vhd @@ -44,6 +44,7 @@ entity TG68K_ALU is set_stop : in bit; Z_error : in bit; rot_bits : in std_logic_vector(1 downto 0); + rot_cnt : in std_logic_vector(5 downto 0); exec : in bit_vector(lastOpcBit downto 0); OP1out : in std_logic_vector(31 downto 0); OP2out : in std_logic_vector(31 downto 0); @@ -171,6 +172,10 @@ architecture logic of TG68K_ALU IS signal bf_flag_z : std_logic; signal bf_flag_n : std_logic; + -- barrel shifter + signal bs_data : std_logic_vector(31 downto 0); + signal bs_msb : std_logic_vector(4 downto 0); + signal set_V_Flag : BIT; signal Flags : std_logic_vector(7 downto 0); signal c_out : std_logic_vector(2 downto 0); @@ -616,7 +621,7 @@ begin ----------------------------------------------------------------------------- -- Rotation ----------------------------------------------------------------------------- - process (exe_opcode, OP1out, Flags, rot_bits, rot_msb, rot_lsb, rot_rot, exec) + process (exe_opcode, OP1out, Flags, rot_bits, rot_msb, rot_lsb, rot_cnt, rot_out, rot_rot, bs_data, bs_msb, exec) begin case exe_opcode(7 downto 6) IS when "00" => --Byte @@ -670,6 +675,51 @@ begin end case; end if; end if; + + -- -------- barrel shifter ------------ + if rot_bits = "01" and exe_opcode(7 downto 6) /= "11" then + -- currently only and LSL/LSR use the barrel shifter + + bs_data <= OP1out; + bs_msb <= "11111"; + + -- word size + if exe_opcode(7 downto 6)="01" then + bs_msb <= "01111"; + bs_data(31 downto 16) <= "0000000000000000"; + end if; + + -- byte size + if exe_opcode(7 downto 6)="00" then + bs_msb <= "00111"; + bs_data(31 downto 8) <= "000000000000000000000000"; + end if; + + if exe_opcode(8) = '1' then + -- left + rot_out <= std_logic_vector(unsigned(bs_data) sll to_integer(unsigned(rot_cnt))); + rot_X <= OP1out(to_integer(unsigned("00001" - rot_cnt(4 downto 0) + bs_msb))); + rot_C <= OP1out(to_integer(unsigned("00001" - rot_cnt(4 downto 0) + bs_msb))); + else + -- right + rot_out <= std_logic_vector(unsigned(bs_data) srl to_integer(unsigned(rot_cnt))); + rot_X <= OP1out(to_integer(unsigned(rot_cnt(4 downto 0) - "00001"))); + rot_C <= OP1out(to_integer(unsigned(rot_cnt(4 downto 0) - "00001"))); + end if; + + -- not shifting at all or shifting more than the whole byte/word/long + if(rot_cnt = 0) then + rot_X <= Flags(4); + rot_C <= '0'; + else + if(rot_cnt - 1 > bs_msb) then + rot_X <= '0'; + rot_C <= '0'; + end if; + end if; + + end if; + end process; ------------------------------------------------------------------------------ diff --git a/tests/tg68k/TG68K_Pack.vhd b/tests/tg68k/TG68K_Pack.vhd index 8a5cc40..3e69a3a 100644 --- a/tests/tg68k/TG68K_Pack.vhd +++ b/tests/tg68k/TG68K_Pack.vhd @@ -214,6 +214,7 @@ package TG68K_Pack is set_stop : in bit; Z_error : in bit; rot_bits : in std_logic_vector(1 downto 0); + rot_cnt : in std_logic_vector(5 downto 0); exec : in bit_vector(lastOpcBit downto 0); OP1out : in std_logic_vector(31 downto 0); OP2out : in std_logic_vector(31 downto 0); diff --git a/tests/tg68k/TG68KdotC_Kernel.vhd b/tests/tg68k/TG68KdotC_Kernel.vhd index 5e43693..c46a746 100644 --- a/tests/tg68k/TG68KdotC_Kernel.vhd +++ b/tests/tg68k/TG68KdotC_Kernel.vhd @@ -189,6 +189,8 @@ architecture logic of TG68KdotC_Kernel is signal dest_hbits : bit; signal rot_bits : std_logic_vector(1 downto 0); signal set_rot_bits : std_logic_vector(1 downto 0); + signal alu_rot_cnt : std_logic_vector(5 downto 0); + signal set_alu_rot_cnt : std_logic_vector(5 downto 0); signal rot_cnt : std_logic_vector(5 downto 0); signal set_rot_cnt : std_logic_vector(5 downto 0); signal movem_actiond : bit; @@ -309,6 +311,7 @@ begin set_stop => set_stop, --: in bit; Z_error => Z_error, --: in bit; rot_bits => rot_bits, --: in std_logic_vector(1 downto 0); + rot_cnt => alu_rot_cnt, --: in std_logic_vector(5 downto 0); exec => exec, --: in bit_vector(lastOpcBit downto 0); OP1out => OP1out, --: in std_logic_vector(31 downto 0); OP2out => OP2out, --: in std_logic_vector(31 downto 0); @@ -896,7 +899,7 @@ begin ----------------------------------------------------------------------------- -- PC Calc + fetch opcode ----------------------------------------------------------------------------- -PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro_state, stop, make_trace, make_berr, IPL_nr, FlagsSR, set_rot_cnt, opcode, writePCbig, set_exec, exec, +PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro_state, stop, make_trace, make_berr, IPL_nr, FlagsSR, set_rot_cnt, set_alu_rot_cnt, opcode, writePCbig, set_exec, exec, PC_dataa, PC_datab, setnextpass, last_data_read, TG68_PC_brw, TG68_PC_word, Z_error, trap_trap, trap_trapv, interrupt, tmp_TG68_PC, TG68_PC) begin PC_dataa <= TG68_PC; @@ -1099,7 +1102,11 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro if decodeOPC = '1' or exec(ld_rot_cnt) = '1' or rot_cnt /= "000001" then rot_cnt <= set_rot_cnt; end if; - if setstate(1) = '1' and set_datatype = "00" then + if decodeOPC = '1' or exec(ld_rot_cnt) = '1' then + alu_rot_cnt <= set_alu_rot_cnt; + end if; + + if setstate(1) = '1' and set_datatype = "00" then byte <= '1'; end if; @@ -1342,6 +1349,7 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro set_Suppress_Base <= '0'; set_PCbase <= '0'; + -- decrement xyz if rot_cnt /= "000001" then set_rot_cnt <= rot_cnt - 1; end if; @@ -2583,22 +2591,37 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro end if; end if; else + -- register rotation/shift set_exec(opcROT) <= '1'; set_rot_bits <= opcode(4 downto 3); data_is_source <= '1'; set_exec(Regwrena) <= '1'; if decodeOPC = '1' then if opcode(5) = '1' then + -- load rotation count from register next_micro_state <= rota1; set(ld_rot_cnt) <= '1'; setstate <= "01"; - else + else -- xyz + set_alu_rot_cnt <= (others => '0'); + set_alu_rot_cnt(2 downto 0) <= opcode(11 downto 9); + if opcode(11 downto 9) = "000" then set_alu_rot_cnt(3) <= '1'; + else set_alu_rot_cnt(3) <= '0'; + end if; + + -- take rotation count from opcode set_rot_cnt(2 downto 0) <= opcode(11 downto 9); if opcode(11 downto 9) = "000" then set_rot_cnt(3) <= '1'; else set_rot_cnt(3) <= '0'; end if; + + -- lsr or lsl use a barrel shifter and are done immediately + if opcode(4 downto 3) = "01" then + set_rot_cnt <= "000001"; + end if; + end if; end if; end if; @@ -3241,10 +3264,15 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro set(opcDIVU) <= '1'; when rota1 => - if OP2out(5 downto 0) /= "000000" then - set_rot_cnt <= OP2out(5 downto 0); - else - set_exec(rot_nop) <= '1'; + -- load rot_cnt from register + if opcode(4 downto 3) = "01" then -- lsl/lsr uses barrel shifter + set_alu_rot_cnt <= OP2out(5 downto 0); + else + if OP2out(5 downto 0) /= "000000" then + set_rot_cnt <= OP2out(5 downto 0); + else + set_exec(rot_nop) <= '1'; + end if; end if; when bf1 =>