1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-01-28 12:38:43 +00:00

[TG68K] Major bitfield fixes, bfffo still broken ...

This commit is contained in:
Till Harbaum
2016-01-22 22:00:02 +01:00
parent 673b83f930
commit b3fbf37a5a
3 changed files with 105 additions and 72 deletions

View File

@@ -63,7 +63,7 @@ entity TG68K_ALU is
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);
bf_offset : in std_logic_vector(5 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);
@@ -160,12 +160,12 @@ architecture logic of TG68K_ALU IS
signal inmux1 : std_logic_vector(39 downto 0);
signal inmux2 : std_logic_vector(39 downto 0);
signal inmux3 : std_logic_vector(39 downto 0);
signal copymuxd32 : std_logic_vector(39 downto 0);
signal inmux4 : std_logic_vector(39 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(39 downto 0);
signal bf_set2 : std_logic_vector(31 downto 0);
signal bf_set2 : std_logic_vector(39 downto 0);
signal shift : std_logic_vector(39 downto 0);
signal copy : std_logic_vector(39 downto 0);
@@ -205,9 +205,9 @@ begin
if bf_fffo = '1' then
ALUout <= (others => '0');
if mux = "0000" then
ALUout(5 downto 0) <= bf_offset + bf_width + 1;
ALUout <= bf_offset + bf_width + 1;
else
ALUout(5 downto 0) <= bf_offset + bf_width - bf_firstbit;
ALUout <= bf_offset + bf_width - bf_firstbit;
end if;
end if;
end if;
@@ -453,7 +453,7 @@ begin
-- contents as with bfset, bfclr or bfchg
process (clk, mux, mask, bitnr, bf_ins, bf_bchg, bf_bset, bf_exts, bf_extu, bf_shift, inmux0, inmux1, inmux2, inmux3, bf_set2, OP1out, OP2out, result_tmp, bf_ext_in,
process (clk, mux, mask, bitnr, bf_ins, bf_bchg, bf_bset, bf_exts, bf_extu, bf_shift, inmux0, inmux1, inmux2, inmux3, inmux4, bf_set2, OP1out, OP2out, result_tmp, bf_ext_in,
shift, datareg, bf_NFlag, result, reg_QB, sign, bf_d32, copy, bf_loffset, copymux0, copymux1, copymux2, copymux3, bf_width)
begin
if rising_edge(clk) then
@@ -480,20 +480,15 @@ process (clk, mux, mask, bitnr, bf_ins, bf_bchg, bf_bset, bf_exts, bf_extu, bf_s
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;
-- source of bfins is always a register, thus we need to set
-- bits 39:32 to mirror 7:0
if bf_ins = '1' then
shift(39 downto 32) <= OP2out(7 downto 0);
end if;
-- Rotate right by bf_shift bits. Rotate through 32 bits when using
-- register (bf_d32 = 1), through 40 bits else.
-- Rotate right by bf_shift bits. Rotate through 32 bits when
-- operating on a register (bf_d32 = 1), through 40 bits else.
-- rotate 1 bit right if required
if bf_shift(0) = '1' then
@@ -542,67 +537,94 @@ process (clk, mux, mask, bitnr, bf_ins, bf_bchg, bf_bset, bf_exts, bf_extu, bf_s
-- rotate 16 bits right if required
if bf_shift(4) = '1' then
if bf_d32 = '1' then
bf_set2 <= inmux3(15 downto 0) & inmux3(31 downto 16);
inmux4(31 downto 0) <= inmux3(15 downto 0) & inmux3(31 downto 16);
else
bf_set2 <= inmux3(15 downto 0) & inmux3(39 downto 24);
inmux4 <= inmux3(15 downto 0) & inmux3(39 downto 16);
end if;
else
bf_set2 <= inmux3(31 downto 0);
inmux4 <= inmux3;
end if;
-- rotate 32 bits right if required
if bf_shift(5) = '1' then
if bf_d32 = '1' then
bf_set2(31 downto 0) <= inmux4(31 downto 0);
else
bf_set2 <= inmux4(31 downto 0) & inmux3(39 downto 32);
end if;
else
bf_set2 <= inmux4;
end if;
-- shift 16 bits left if required while expanding sign from 32 bits to 40 bits
--TH: Check if it's possible to shift 1 bits in from lsb instead of wrapping
if bf_loffset(4) = '1' then
copymux3 <= sign(23 downto 0) & "11111111" & sign(31 downto 24);
if bf_d32 = '1' then
-- _ABCD -> _CDAB
copymux3(31 downto 0) <= sign(15 downto 0) & sign(31 downto 16);
else
-- _ABCD -> BCD1A
copymux3 <= sign(23 downto 0) & "11111111" & sign(31 downto 24);
end if;
else
copymux3 <= "11111111" & sign;
copymux3 <= "11111111" & sign;
end if;
-- shift 8 bits left if required
if bf_loffset(3) = '1' then
copymux2 <= copymux3(31 downto 0) & copymux3(39 downto 32);
if bf_d32 = '1' then
-- _ABCD -> _BCDA
copymux2(31 downto 0) <= copymux3(23 downto 0) & copymux3(31 downto 24);
else
-- ABCDE -> BCDEA
copymux2 <= copymux3(31 downto 0) & copymux3(39 downto 32);
end if;
else
copymux2 <= copymux3;
end if;
-- shift 4 bits left if required
if bf_loffset(2) = '1' then
copymux1 <= copymux2(35 downto 0) & copymux2(39 downto 36);
if bf_d32 = '1' then
copymux1(31 downto 0) <= copymux2(27 downto 0) & copymux2(31 downto 28);
else
copymux1 <= copymux2(35 downto 0) & copymux2(39 downto 36);
end if;
else
copymux1 <= copymux2;
end if;
-- shift 2 bits left if required
if bf_loffset(1) = '1' then
copymux0 <= copymux1(37 downto 0) & copymux1(39 downto 38);
if bf_d32 = '1' then
copymux0(31 downto 0) <= copymux1(29 downto 0) & copymux1(31 downto 30);
else
copymux0 <= copymux1(37 downto 0) & copymux1(39 downto 38);
end if;
else
copymux0 <= copymux1;
end if;
-- shift 1 bit left if required
if bf_loffset(0) = '1' then
copymuxd32 <= copymux0(38 downto 0) & copymux0(39);
if bf_d32 = '1' then
copy(31 downto 0) <= copymux0(30 downto 0) & copymux0(31);
else
copy <= copymux0(38 downto 0) & copymux0(39);
end if;
else
copymuxd32 <= copymux0;
copy <= copymux0;
end if;
--TH demux properly for 32 bit registers (bf_d32)
if bf_d32='1' then
copy <= "11111111" & copymuxd32(31 downto 8) & (copymuxd32(7 downto 0) and copymuxd32(39 downto 32));
else
copy <= copymuxd32;
end if;
if bf_ins = '1' then
datareg <= reg_QB;
else
datareg <= bf_set2;
datareg <= bf_set2(31 downto 0);
end if;
-- do the bitfield operation itself
if bf_ins = '1' then
result(31 downto 0) <= bf_set2;
result(39 downto 32) <= bf_set2(7 downto 0);
result <= bf_set2;
elsif bf_bchg = '1' then
result(31 downto 0) <= not OP1out;
result(39 downto 32) <= not bf_ext_in;
@@ -621,14 +643,19 @@ process (clk, mux, mask, bitnr, bf_ins, bf_bchg, bf_bset, bf_exts, bf_extu, bf_s
end if;
end loop;
result_tmp <= bf_ext_in & OP1out;
-- 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';
--TH XYZ
if bf_d32 = '0' then
-- The test for this overflow shouldn't be needed. But GHDL complains
-- otherwise.
-- bf_flag_n_idx <= to_integer(unsigned('0' & bf_loffset)+unsigned(bf_width));
if(to_integer(unsigned('0' & bf_loffset)+unsigned(bf_width)) > 39) then
bf_flag_n <= result_tmp(39);
else
@@ -651,8 +678,7 @@ process (clk, mux, mask, bitnr, bf_ins, bf_bchg, bf_bset, bf_exts, bf_extu, bf_s
else
bf_datareg <= datareg;
end if;
-- bf_datareg <= copy(31 downto 0);
-- result(31 downto 0)<=datareg;
--BFFFO
mask <= datareg;
bf_firstbit <= '0' & bitnr;

View File

@@ -233,7 +233,7 @@ package TG68K_Pack is
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);
bf_offset : in std_logic_vector(5 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);

View File

@@ -265,7 +265,7 @@ architecture logic of TG68KdotC_Kernel is
signal last_data_read : std_logic_vector(31 downto 0);
signal last_data_in : std_logic_vector(31 downto 0);
signal alu_bf_offset : std_logic_vector(5 downto 0);
signal alu_bf_offset : 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_bhits : std_logic_vector(5 downto 0);
@@ -1174,12 +1174,14 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
------------------------------------------------------------------------------
process (clk, Reset, sndOPC, reg_QA, reg_QB, bf_width, bf_offset, bf_bhits, opcode, setstate, bf_shift)
begin
-- the ALU needs the full real offset to return the correct result for
-- bfffo
if sndOPC(11) = '1' then
alu_bf_offset <= '0'&reg_QA(4 downto 0);
alu_bf_offset <= reg_QA;
else
alu_bf_offset <= '0'&sndOPC(10 downto 6);
alu_bf_offset <= "000000000000000000000000000" & sndOPC(10 downto 6);
end if;
bf_offset <= alu_bf_offset;
bf_offset <= '0' & alu_bf_offset(4 downto 0);
bf_width(5) <= '0';
if sndOPC(5) = '1' then
@@ -1190,28 +1192,28 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
bf_bhits <= bf_width + bf_offset;
set_oddout <= not bf_bhits(3);
if opcode(10 downto 8) = "111" then --INS
bf_loffset <= 32 - bf_shift;
else
bf_loffset <= bf_shift;
end if;
bf_loffset(5) <= '0';
if opcode(4 downto 3) = "00" then
if opcode(4 downto 3) = "00" then -- register target
if opcode(10 downto 8) = "111" then --INS
bf_shift <= bf_bhits + 1;
bf_shift <= bf_bhits + 1; -- bf_shift = offset + width
else
bf_shift <= 31 - bf_bhits;
bf_shift <= 31 - bf_bhits; -- bf_shift = 32 - (offset + width);
end if;
bf_loffset <= 31 - bf_bhits;
bf_shift(5) <= '0';
else
if opcode(10 downto 8) = "111" then --INS
bf_shift <= "011" & ("001" + bf_bhits(2 downto 0));
-- memory target
if opcode(10 downto 8) = "111" then --INS
-- bf_shift = 40 - (7 - (bf_bhits & 7))
bf_shift <= 40 - ("000" & ("111" - bf_bhits(2 downto 0)));
else
bf_shift <= "000" & ("111" - bf_bhits(2 downto 0));
-- bf_shift = 7 - (bf_bhits & 7)
bf_shift <= "000" & ("111" - bf_bhits(2 downto 0));
end if;
-- bf_loffset = 7 - (bf_bhits & 7)
bf_loffset <= "000" & ("111" - bf_bhits(2 downto 0));
bf_offset(4 downto 3) <= "00";
end if;
bf_loffset(5) <= '0';
case bf_bhits(5 downto 3) is
when "000" =>
@@ -2534,26 +2536,31 @@ PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro
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';
set_exec(opcBFwb) <= '1'; --TH: really? for bfffo?
--TH: TODO: Make sure the following is still needed
-- it seems by now only bfffo needs it when the
if opcode(10 downto 8)/="111" and opcode(4 downto 3) /= "00" THEN
--not bfins and not on register -- TEMP FIX2
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';
if opcode(10 downto 8)/="111" and opcode(4 downto 3) /= "00" THEN
--not bfins and not on register -- TEMP FIX2
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';
-- 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
-- register destination
if opcode(4 downto 3) = "00" then
-- bftst doesn't write
if opcode(10 downto 8) /= "000" then