1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-04-30 13:52:33 +00:00

[TG68K] Barrel shifter in 68020 mode

This commit is contained in:
Till Harbaum
2016-01-29 19:58:19 +01:00
parent 926af02ee0
commit 0ab0768f59
8 changed files with 423 additions and 250 deletions

View File

@@ -29,11 +29,13 @@ 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,
DIV_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
BarrelShifter : integer := 0 --0=>no, 1=>yes, 2=>switchable with CPU(1)
);
port (
clk : in std_logic;
Reset : in std_logic;
cpu : in std_logic_vector(1 downto 0);
clkena_lw : in std_logic := '1';
execOPC : in bit;
exe_condition : in std_logic;
@@ -171,12 +173,15 @@ architecture logic of TG68K_ALU IS
signal index : std_logic_vector(4 downto 0);
signal bf_flag_z : std_logic;
signal bf_flag_n : std_logic;
signal set_V_Flag : BIT;
-- barrel shifter
signal bs_rox : std_logic_vector(32 downto 0);
signal bs_mask : std_logic_vector(31 downto 0);
signal bs_data : std_logic_vector(31 downto 0);
signal bs_msb : std_logic_vector(4 downto 0);
signal bs_V : std_logic;
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);
@@ -458,7 +463,7 @@ begin
-- 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)
datareg, bf_NFlag, result, reg_QB, sign, bf_d32, copy, bf_loffset, bf_width, bf_loff_dir, exe_opcode)
begin
if rising_edge(clk) then
if clkena_lw = '1' then
@@ -621,7 +626,7 @@ begin
-----------------------------------------------------------------------------
-- Rotation
-----------------------------------------------------------------------------
process (exe_opcode, OP1out, Flags, rot_bits, rot_msb, rot_lsb, rot_cnt, rot_out, rot_rot, bs_data, bs_msb, exec)
process (exe_opcode, OP1out, Flags, rot_bits, rot_msb, rot_lsb, rot_cnt, rot_out, rot_rot, bs_data, bs_mask, bs_msb, bs_rox, exec)
begin
case exe_opcode(7 downto 6) IS
when "00" => --Byte
@@ -676,49 +681,203 @@ begin
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
---------------------------------------------------------------------------
--------------------------- 68020 barrel shifter --------------------------
---------------------------------------------------------------------------
bs_mask <= (others => '-');
bs_rox <= (others => '-');
-- default: long word size
bs_data <= OP1out;
bs_msb <= "11111"; -- 31
bs_V <= '0'; -- overflow flag for asr/asl
-- the <ea> version doesn't use the barrel shifter as it can only shift 1 bit anyway
if (BarrelShifter = 1 or (cpu(1) = '1' and BarrelShifter = 2)) then
if exe_opcode(7 downto 6) /= "11" then
-- create a mask of rot_cnt left aligned 1 bits according to operation size
-- this is required for the arithmetic shifts to handle the V bit and the sign
bs_mask <= (others => '0');
for i in 0 TO 31 loop
if rot_cnt > bs_msb-i and i <= bs_msb then
bs_mask(i) <= '1';
end if;
end loop;
bs_data <= OP1out;
bs_msb <= "11111";
-- check if msb would change during shifts
-- in left shift either msb is 1 and remaining mask bits are not 11111...
if OP1out(to_integer(unsigned(bs_msb))) = '1' and exe_opcode(8) = '1' then
if (OP1out and ('0' & bs_mask(31 downto 1))) /= ('0' & bs_mask(31 downto 1)) then
bs_V <= '1';
end if;
-- word size
if exe_opcode(7 downto 6)="01" then
bs_msb <= "01111";
bs_data(31 downto 16) <= "0000000000000000";
-- when shifting left more than 31/15/7 times a '0' will sure appear in the msb
if(rot_cnt > bs_msb) then
bs_V <= '1';
end if;
end if;
-- ... or msb is 0 and remaining mask bits are not 00000...
if OP1out(to_integer(unsigned(bs_msb))) = '0' and exe_opcode(8) = '1' then
if (OP1out and ('0' & bs_mask(31 downto 1))) /= x"00000000" then
bs_V <= '1';
end if;
end if;
-- TODO: move to asr/asl only
-- word or byte size
if exe_opcode(7) = '0' then
bs_msb(4) <= '0'; -- 15
bs_data(31 downto 16) <= "0000000000000000";
-- byte size
if exe_opcode(6) = '0' then
bs_msb(3) <= '0'; -- 7
bs_data(15 downto 8) <= "00000000";
end if;
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)));
if rot_bits = "10" then
--====================== ROXL =====================
if exe_opcode(7 downto 6) = "00" then
-- roxl.b
bs_rox <= "------------------------" &
std_logic_vector(unsigned(Flags(4) & bs_data(7 downto 0)) rol
to_integer(unsigned(rot_cnt)));
rot_X <= bs_rox(8);
rot_C <= bs_rox(8);
elsif exe_opcode(7 downto 6) = "01" then
-- roxl.w
bs_rox <= "----------------" &
std_logic_vector(unsigned(Flags(4) & bs_data(15 downto 0)) rol
to_integer(unsigned(rot_cnt)));
rot_X <= bs_rox(16);
rot_C <= bs_rox(16);
else
-- roxl.l
bs_rox <= std_logic_vector(unsigned(Flags(4) & bs_data) rol
to_integer(unsigned(rot_cnt)));
rot_X <= bs_rox(32);
rot_C <= bs_rox(32);
end if;
rot_out <= bs_rox(31 downto 0);
elsif rot_bits = "11" then
--====================== ROL =====================
if exe_opcode(7 downto 6) = "00" then
-- rol.b
rot_out <= "------------------------" &
std_logic_vector(unsigned(bs_data(7 downto 0)) rol
to_integer(unsigned(rot_cnt(2 downto 0))));
rot_C <= OP1out(to_integer(unsigned("001" - rot_cnt(2 downto 0) + bs_msb(2 downto 0))));
elsif exe_opcode(7 downto 6) = "01" then
-- rol.w
rot_out <= "----------------" &
std_logic_vector(unsigned(bs_data(15 downto 0)) rol
to_integer(unsigned(rot_cnt(3 downto 0))));
rot_C <= OP1out(to_integer(unsigned("0001" - rot_cnt(3 downto 0) + bs_msb(3 downto 0))));
else
-- rol.l
rot_out <= std_logic_vector(unsigned(bs_data) rol
to_integer(unsigned(rot_cnt(4 downto 0))));
rot_C <= OP1out(to_integer(unsigned("00001" - rot_cnt(4 downto 0) + bs_msb)));
end if;
rot_X <= Flags(4); -- keep X flag
else
--====================== LSL/ASL =====================
-- shifting left is the same for arithmetic and logic
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)));
end if;
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")));
if rot_bits = "10" then
--====================== ROXR =====================
if exe_opcode(7 downto 6) = "00" then
-- roxr.b
bs_rox <= "------------------------" &
std_logic_vector(unsigned(bs_data(7 downto 0) & Flags(4)) ror
to_integer(unsigned(rot_cnt)));
elsif exe_opcode(7 downto 6) = "01" then
-- roxr.w
bs_rox <= "----------------" &
std_logic_vector(unsigned(bs_data(15 downto 0) & Flags(4)) ror
to_integer(unsigned(rot_cnt)));
else
-- roxr.l
bs_rox <= std_logic_vector(unsigned(bs_data & Flags(4)) ror
to_integer(unsigned(rot_cnt)));
end if;
rot_out <= bs_rox(32 downto 1);
rot_C <= bs_rox(0);
rot_X <= bs_rox(0);
elsif rot_bits = "11" then
--====================== ROR =====================
if exe_opcode(7 downto 6) = "00" then
-- ror.b
rot_out <= "------------------------" &
std_logic_vector(unsigned(bs_data(7 downto 0)) ror
to_integer(unsigned(rot_cnt(2 downto 0))));
rot_C <= OP1out(to_integer(unsigned(rot_cnt(2 downto 0) - "001")));
elsif exe_opcode(7 downto 6) = "01" then
-- ror.w
rot_out <= "----------------" &
std_logic_vector(unsigned(bs_data(15 downto 0)) ror
to_integer(unsigned(rot_cnt(3 downto 0))));
rot_C <= OP1out(to_integer(unsigned(rot_cnt(3 downto 0) - "0001")));
else
-- ror.l
rot_out <= std_logic_vector(unsigned(bs_data) ror
to_integer(unsigned(rot_cnt(4 downto 0))));
rot_C <= OP1out(to_integer(unsigned(rot_cnt(4 downto 0) - "00001")));
end if;
rot_X <= Flags(4); -- keep X flag
else
--====================== LSR/ASR =====================
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")));
-- arithmetic shift right with msb being 1? then make sure all
-- newly shifted in bits are set to 1
if rot_bits = "00" and OP1out(to_integer(unsigned(bs_msb))) = '1' then
rot_out <= bs_mask or std_logic_vector(unsigned(bs_data) srl
to_integer(unsigned(rot_cnt)));
end if;
end if;
end if;
-- not shifting at all or shifting more than the whole byte/word/long
if(rot_cnt = 0) then
-- rox returns X in C bit with rotate of zero. all other clear it
if rot_bits = "10" then
rot_C <= Flags(4);
else
rot_C <= '0';
end if;
rot_X <= Flags(4);
rot_C <= '0';
else
if(rot_cnt - 1 > bs_msb) then
-- asX/lsX shifting more than the total operand width
if rot_bits(1) = '0' and rot_cnt - 1 > bs_msb then
rot_X <= '0';
rot_C <= '0';
-- arithmetic shift right with msb set? Then the sign '1's will
-- be shifted out
if rot_bits = "00" and exe_opcode(8) = '0' and
OP1out(to_integer(unsigned(bs_msb))) = '1' then
rot_X <= '1';
rot_C <= '1';
end if;
end if;
end if;
end if;
end if;
end process;
@@ -838,6 +997,12 @@ process (clk, Reset, exe_opcode, exe_datatype, Flags, last_data_read, OP2out, fl
else
Flags(1) <= '0';
end if;
if BarrelShifter = 1 or (cpu(1) = '1' and BarrelShifter = 2) then
-- v flag from barrel shifter when doing asl/asr
if rot_bits = "00" and exe_opcode(7 downto 6) /= "11" then
Flags(1) <= bs_V;
end if;
end if;
elsif exec(opcBITS) = '1' then
Flags(2) <= not one_bit_in;
elsif exec(opcCHK) = '1' then

View File

@@ -199,11 +199,13 @@ package TG68K_Pack is
component TG68K_ALU
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,
DIV_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
BarrelShifter : integer := 0 --0=>no, 1=>yes, 2=>switchable with CPU(1)
);
port(
clk : in std_logic;
Reset : in std_logic;
cpu : in std_logic_vector(1 downto 0);
clkena_lw : in std_logic:='1';
execOPC : in bit;
exe_condition : in std_logic;

View File

@@ -36,10 +36,11 @@
-- CAS, CAS2
-- CHK2
-- CMP2
-- cpXXX Coprozessor stuff
-- cpXXX coprocessor stuff
-- TRAPcc
-- done 020:
-- barrel shifter
-- PACK, UNPK
-- Bitfields
-- address modes
@@ -61,7 +62,8 @@ entity TG68KdotC_Kernel is
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)
BitField : integer := 0; --0=>no, 1=>yes, 2=>switchable with CPU(1)
BarrelShifter : integer := 0 --0=>no, 1=>yes, 2=>switchable with CPU(1)
);
port (
clk : in std_logic;
@@ -227,9 +229,6 @@ architecture logic of TG68KdotC_Kernel is
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 IPL_nr : std_logic_vector(2 downto 0);
signal rIPL_nr : std_logic_vector(2 downto 0);
@@ -284,7 +283,6 @@ architecture logic of TG68KdotC_Kernel is
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 micro_state : micro_states;
signal next_micro_state : micro_states;
@@ -296,11 +294,13 @@ 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,
DIV_Mode => DIV_Mode, --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
BarrelShifter => BarrelShifter --0=>no, 1=>yes, 2=>switchable with CPU(1)
)
port map(
clk => clk, --: in std_logic;
Reset => Reset, --: in std_logic;
cpu => cpu, --: in std_logic_vector(1 downto 0);
clkena_lw => clkena_lw, --: in std_logic:='1';
execOPC => execOPC, --: in bit;
exe_condition => exe_condition, --: in std_logic;
@@ -577,7 +577,7 @@ begin
-----------------------------------------------------------------------------
-- set OP1out
-----------------------------------------------------------------------------
process (reg_QA, store_in_tmp, ea_data, long_start, addr, exec, memmaskmux)
process (reg_QA, store_in_tmp, ea_data, long_start, addr, exec, memmaskmux, data_write_tmp)
begin
OP1out <= reg_QA;
if exec(OP1out_zero) = '1' then
@@ -1295,7 +1295,7 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
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,
datatype, interrupt, c_out, trapmake, rot_cnt, brief, addr, last_data_in,
long_start, set_datatype, sndOPC, set_exec, exec, ea_build_now, reg_QA, reg_QB, make_berr, trap_berr)
begin
TG68_PC_brw <= '0';
@@ -1316,6 +1316,7 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
ea_build_now <= '0';
set_rot_bits <= "XX";
set_rot_cnt <= "000001";
set_alu_rot_cnt <= "XXXXXX";
dest_hbits <= '0';
source_lowbits <= '0';
source_2ndHbits <= '0';
@@ -1335,9 +1336,6 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
set_vectoraddr <= '0';
writeSR <= '0';
set_stop <= '0';
illegal_write_mode <= '0';
illegal_read_mode <= '0';
illegal_byteaddr <= '0';
set_Z_error <= '0';
next_micro_state <= idle;
@@ -2616,9 +2614,9 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
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
-- use barrel shifter
if BarrelShifter = 1 or (cpu(1) = '1' and BarrelShifter = 2) then
set_rot_cnt <= "000001";
end if;
@@ -3264,8 +3262,8 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
set(opcDIVU) <= '1';
when rota1 =>
-- load rot_cnt from register
if opcode(4 downto 3) = "01" then -- lsl/lsr uses barrel shifter
-- load rot_cnt from register, use barrel shifter
if BarrelShifter = 1 or (cpu(1) = '1' and BarrelShifter = 2) then
set_alu_rot_cnt <= OP2out(5 downto 0);
else
if OP2out(5 downto 0) /= "000000" then
@@ -3445,85 +3443,6 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
end if;
end process;
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

View File

@@ -846,7 +846,7 @@ wire [15:0] cache_data_out = data_cache_hit?data_cache_data_out:inst_cache_data_
wire [15:0] cpu_data_in = cacheRead?cache_data_out:system_data_out;
TG68KdotC_Kernel #(2,2,2,2,2,2) tg68k (
TG68KdotC_Kernel #(2,2,2,2,2,2,2) tg68k (
.clk (clk_32 ),
.nReset (~reset ),
.clkena_in (clkena ),

View File

@@ -29,11 +29,13 @@ 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,
DIV_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
BarrelShifter : integer := 0 --0=>no, 1=>yes, 2=>switchable with CPU(1)
);
port (
clk : in std_logic;
Reset : in std_logic;
cpu : in std_logic_vector(1 downto 0);
clkena_lw : in std_logic := '1';
execOPC : in bit;
exe_condition : in std_logic;
@@ -171,12 +173,15 @@ architecture logic of TG68K_ALU IS
signal index : std_logic_vector(4 downto 0);
signal bf_flag_z : std_logic;
signal bf_flag_n : std_logic;
signal set_V_Flag : BIT;
-- barrel shifter
signal bs_rox : std_logic_vector(32 downto 0);
signal bs_mask : std_logic_vector(31 downto 0);
signal bs_data : std_logic_vector(31 downto 0);
signal bs_msb : std_logic_vector(4 downto 0);
signal bs_V : std_logic;
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);
@@ -458,7 +463,7 @@ begin
-- 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)
datareg, bf_NFlag, result, reg_QB, sign, bf_d32, copy, bf_loffset, bf_width, bf_loff_dir, exe_opcode)
begin
if rising_edge(clk) then
if clkena_lw = '1' then
@@ -621,7 +626,7 @@ begin
-----------------------------------------------------------------------------
-- Rotation
-----------------------------------------------------------------------------
process (exe_opcode, OP1out, Flags, rot_bits, rot_msb, rot_lsb, rot_cnt, rot_out, rot_rot, bs_data, bs_msb, exec)
process (exe_opcode, OP1out, Flags, rot_bits, rot_msb, rot_lsb, rot_cnt, rot_out, rot_rot, bs_data, bs_mask, bs_msb, bs_rox, exec)
begin
case exe_opcode(7 downto 6) IS
when "00" => --Byte
@@ -676,49 +681,203 @@ begin
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
---------------------------------------------------------------------------
--------------------------- 68020 barrel shifter --------------------------
---------------------------------------------------------------------------
bs_mask <= (others => '-');
bs_rox <= (others => '-');
-- default: long word size
bs_data <= OP1out;
bs_msb <= "11111"; -- 31
bs_V <= '0'; -- overflow flag for asr/asl
-- the <ea> version doesn't use the barrel shifter as it can only shift 1 bit anyway
if (BarrelShifter = 1 or (cpu(1) = '1' and BarrelShifter = 2)) then
if exe_opcode(7 downto 6) /= "11" then
-- create a mask of rot_cnt left aligned 1 bits according to operation size
-- this is required for the arithmetic shifts to handle the V bit and the sign
bs_mask <= (others => '0');
for i in 0 TO 31 loop
if rot_cnt > bs_msb-i and i <= bs_msb then
bs_mask(i) <= '1';
end if;
end loop;
bs_data <= OP1out;
bs_msb <= "11111";
-- check if msb would change during shifts
-- in left shift either msb is 1 and remaining mask bits are not 11111...
if OP1out(to_integer(unsigned(bs_msb))) = '1' and exe_opcode(8) = '1' then
if (OP1out and ('0' & bs_mask(31 downto 1))) /= ('0' & bs_mask(31 downto 1)) then
bs_V <= '1';
end if;
-- word size
if exe_opcode(7 downto 6)="01" then
bs_msb <= "01111";
bs_data(31 downto 16) <= "0000000000000000";
-- when shifting left more than 31/15/7 times a '0' will sure appear in the msb
if(rot_cnt > bs_msb) then
bs_V <= '1';
end if;
end if;
-- ... or msb is 0 and remaining mask bits are not 00000...
if OP1out(to_integer(unsigned(bs_msb))) = '0' and exe_opcode(8) = '1' then
if (OP1out and ('0' & bs_mask(31 downto 1))) /= x"00000000" then
bs_V <= '1';
end if;
end if;
-- TODO: move to asr/asl only
-- word or byte size
if exe_opcode(7) = '0' then
bs_msb(4) <= '0'; -- 15
bs_data(31 downto 16) <= "0000000000000000";
-- byte size
if exe_opcode(6) = '0' then
bs_msb(3) <= '0'; -- 7
bs_data(15 downto 8) <= "00000000";
end if;
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)));
if rot_bits = "10" then
--====================== ROXL =====================
if exe_opcode(7 downto 6) = "00" then
-- roxl.b
bs_rox <= "------------------------" &
std_logic_vector(unsigned(Flags(4) & bs_data(7 downto 0)) rol
to_integer(unsigned(rot_cnt)));
rot_X <= bs_rox(8);
rot_C <= bs_rox(8);
elsif exe_opcode(7 downto 6) = "01" then
-- roxl.w
bs_rox <= "----------------" &
std_logic_vector(unsigned(Flags(4) & bs_data(15 downto 0)) rol
to_integer(unsigned(rot_cnt)));
rot_X <= bs_rox(16);
rot_C <= bs_rox(16);
else
-- roxl.l
bs_rox <= std_logic_vector(unsigned(Flags(4) & bs_data) rol
to_integer(unsigned(rot_cnt)));
rot_X <= bs_rox(32);
rot_C <= bs_rox(32);
end if;
rot_out <= bs_rox(31 downto 0);
elsif rot_bits = "11" then
--====================== ROL =====================
if exe_opcode(7 downto 6) = "00" then
-- rol.b
rot_out <= "------------------------" &
std_logic_vector(unsigned(bs_data(7 downto 0)) rol
to_integer(unsigned(rot_cnt(2 downto 0))));
rot_C <= OP1out(to_integer(unsigned("001" - rot_cnt(2 downto 0) + bs_msb(2 downto 0))));
elsif exe_opcode(7 downto 6) = "01" then
-- rol.w
rot_out <= "----------------" &
std_logic_vector(unsigned(bs_data(15 downto 0)) rol
to_integer(unsigned(rot_cnt(3 downto 0))));
rot_C <= OP1out(to_integer(unsigned("0001" - rot_cnt(3 downto 0) + bs_msb(3 downto 0))));
else
-- rol.l
rot_out <= std_logic_vector(unsigned(bs_data) rol
to_integer(unsigned(rot_cnt(4 downto 0))));
rot_C <= OP1out(to_integer(unsigned("00001" - rot_cnt(4 downto 0) + bs_msb)));
end if;
rot_X <= Flags(4); -- keep X flag
else
--====================== LSL/ASL =====================
-- shifting left is the same for arithmetic and logic
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)));
end if;
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")));
if rot_bits = "10" then
--====================== ROXR =====================
if exe_opcode(7 downto 6) = "00" then
-- roxr.b
bs_rox <= "------------------------" &
std_logic_vector(unsigned(bs_data(7 downto 0) & Flags(4)) ror
to_integer(unsigned(rot_cnt)));
elsif exe_opcode(7 downto 6) = "01" then
-- roxr.w
bs_rox <= "----------------" &
std_logic_vector(unsigned(bs_data(15 downto 0) & Flags(4)) ror
to_integer(unsigned(rot_cnt)));
else
-- roxr.l
bs_rox <= std_logic_vector(unsigned(bs_data & Flags(4)) ror
to_integer(unsigned(rot_cnt)));
end if;
rot_out <= bs_rox(32 downto 1);
rot_C <= bs_rox(0);
rot_X <= bs_rox(0);
elsif rot_bits = "11" then
--====================== ROR =====================
if exe_opcode(7 downto 6) = "00" then
-- ror.b
rot_out <= "------------------------" &
std_logic_vector(unsigned(bs_data(7 downto 0)) ror
to_integer(unsigned(rot_cnt(2 downto 0))));
rot_C <= OP1out(to_integer(unsigned(rot_cnt(2 downto 0) - "001")));
elsif exe_opcode(7 downto 6) = "01" then
-- ror.w
rot_out <= "----------------" &
std_logic_vector(unsigned(bs_data(15 downto 0)) ror
to_integer(unsigned(rot_cnt(3 downto 0))));
rot_C <= OP1out(to_integer(unsigned(rot_cnt(3 downto 0) - "0001")));
else
-- ror.l
rot_out <= std_logic_vector(unsigned(bs_data) ror
to_integer(unsigned(rot_cnt(4 downto 0))));
rot_C <= OP1out(to_integer(unsigned(rot_cnt(4 downto 0) - "00001")));
end if;
rot_X <= Flags(4); -- keep X flag
else
--====================== LSR/ASR =====================
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")));
-- arithmetic shift right with msb being 1? then make sure all
-- newly shifted in bits are set to 1
if rot_bits = "00" and OP1out(to_integer(unsigned(bs_msb))) = '1' then
rot_out <= bs_mask or std_logic_vector(unsigned(bs_data) srl
to_integer(unsigned(rot_cnt)));
end if;
end if;
end if;
-- not shifting at all or shifting more than the whole byte/word/long
if(rot_cnt = 0) then
-- rox returns X in C bit with rotate of zero. all other clear it
if rot_bits = "10" then
rot_C <= Flags(4);
else
rot_C <= '0';
end if;
rot_X <= Flags(4);
rot_C <= '0';
else
if(rot_cnt - 1 > bs_msb) then
-- asX/lsX shifting more than the total operand width
if rot_bits(1) = '0' and rot_cnt - 1 > bs_msb then
rot_X <= '0';
rot_C <= '0';
-- arithmetic shift right with msb set? Then the sign '1's will
-- be shifted out
if rot_bits = "00" and exe_opcode(8) = '0' and
OP1out(to_integer(unsigned(bs_msb))) = '1' then
rot_X <= '1';
rot_C <= '1';
end if;
end if;
end if;
end if;
end if;
end process;
@@ -838,6 +997,12 @@ process (clk, Reset, exe_opcode, exe_datatype, Flags, last_data_read, OP2out, fl
else
Flags(1) <= '0';
end if;
if BarrelShifter = 1 or (cpu(1) = '1' and BarrelShifter = 2) then
-- v flag from barrel shifter when doing asl/asr
if rot_bits = "00" and exe_opcode(7 downto 6) /= "11" then
Flags(1) <= bs_V;
end if;
end if;
elsif exec(opcBITS) = '1' then
Flags(2) <= not one_bit_in;
elsif exec(opcCHK) = '1' then

View File

@@ -199,11 +199,13 @@ package TG68K_Pack is
component TG68K_ALU
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,
DIV_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
BarrelShifter : integer := 0 --0=>no, 1=>yes, 2=>switchable with CPU(1)
);
port(
clk : in std_logic;
Reset : in std_logic;
cpu : in std_logic_vector(1 downto 0);
clkena_lw : in std_logic:='1';
execOPC : in bit;
exe_condition : in std_logic;

View File

@@ -36,10 +36,11 @@
-- CAS, CAS2
-- CHK2
-- CMP2
-- cpXXX Coprozessor stuff
-- cpXXX coprocessor stuff
-- TRAPcc
-- done 020:
-- barrel shifter
-- PACK, UNPK
-- Bitfields
-- address modes
@@ -61,7 +62,8 @@ entity TG68KdotC_Kernel is
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)
BitField : integer := 0; --0=>no, 1=>yes, 2=>switchable with CPU(1)
BarrelShifter : integer := 0 --0=>no, 1=>yes, 2=>switchable with CPU(1)
);
port (
clk : in std_logic;
@@ -227,9 +229,6 @@ architecture logic of TG68KdotC_Kernel is
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 IPL_nr : std_logic_vector(2 downto 0);
signal rIPL_nr : std_logic_vector(2 downto 0);
@@ -284,7 +283,6 @@ architecture logic of TG68KdotC_Kernel is
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 micro_state : micro_states;
signal next_micro_state : micro_states;
@@ -296,11 +294,13 @@ 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,
DIV_Mode => DIV_Mode, --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
BarrelShifter => BarrelShifter --0=>no, 1=>yes, 2=>switchable with CPU(1)
)
port map(
clk => clk, --: in std_logic;
Reset => Reset, --: in std_logic;
cpu => cpu, --: in std_logic_vector(1 downto 0);
clkena_lw => clkena_lw, --: in std_logic:='1';
execOPC => execOPC, --: in bit;
exe_condition => exe_condition, --: in std_logic;
@@ -577,7 +577,7 @@ begin
-----------------------------------------------------------------------------
-- set OP1out
-----------------------------------------------------------------------------
process (reg_QA, store_in_tmp, ea_data, long_start, addr, exec, memmaskmux)
process (reg_QA, store_in_tmp, ea_data, long_start, addr, exec, memmaskmux, data_write_tmp)
begin
OP1out <= reg_QA;
if exec(OP1out_zero) = '1' then
@@ -1295,7 +1295,7 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
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,
datatype, interrupt, c_out, trapmake, rot_cnt, brief, addr, last_data_in,
long_start, set_datatype, sndOPC, set_exec, exec, ea_build_now, reg_QA, reg_QB, make_berr, trap_berr)
begin
TG68_PC_brw <= '0';
@@ -1316,6 +1316,7 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
ea_build_now <= '0';
set_rot_bits <= "XX";
set_rot_cnt <= "000001";
set_alu_rot_cnt <= "XXXXXX";
dest_hbits <= '0';
source_lowbits <= '0';
source_2ndHbits <= '0';
@@ -1335,9 +1336,6 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
set_vectoraddr <= '0';
writeSR <= '0';
set_stop <= '0';
illegal_write_mode <= '0';
illegal_read_mode <= '0';
illegal_byteaddr <= '0';
set_Z_error <= '0';
next_micro_state <= idle;
@@ -2616,9 +2614,9 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
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
-- use barrel shifter
if BarrelShifter = 1 or (cpu(1) = '1' and BarrelShifter = 2) then
set_rot_cnt <= "000001";
end if;
@@ -3264,8 +3262,8 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
set(opcDIVU) <= '1';
when rota1 =>
-- load rot_cnt from register
if opcode(4 downto 3) = "01" then -- lsl/lsr uses barrel shifter
-- load rot_cnt from register, use barrel shifter
if BarrelShifter = 1 or (cpu(1) = '1' and BarrelShifter = 2) then
set_alu_rot_cnt <= OP2out(5 downto 0);
else
if OP2out(5 downto 0) /= "000000" then
@@ -3445,85 +3443,6 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
end if;
end process;
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

View File

@@ -22,7 +22,8 @@ generic(
extAddr_Mode : integer:= 2; --0=>no, 1=>yes, 2=>switchable with CPU(1)
MUL_Mode : integer := 2; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
DIV_Mode : integer := 2; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
BitField : integer := 2 --0=>no, 1=>yes, 2=>switchable with CPU(1)
BitField : integer := 2; --0=>no, 1=>yes, 2=>switchable with CPU(1)
BarrelShifter : integer := 2 --0=>no, 1=>yes, 2=>switchable with CPU(1)
);
port (clk : in std_logic;
nReset : in std_logic; --low active