|
|
|
@ -37,7 +37,7 @@ architecture behaviour of fpu is
|
|
|
|
|
|
|
|
|
|
type state_t is (IDLE,
|
|
|
|
|
DO_MCRFS, DO_MTFSB, DO_MTFSFI, DO_MFFS, DO_MTFSF,
|
|
|
|
|
DO_FMR, DO_FMRG,
|
|
|
|
|
DO_FMR, DO_FMRG, DO_FCMP,
|
|
|
|
|
DO_FCFID, DO_FCTI,
|
|
|
|
|
DO_FRSP, DO_FRI,
|
|
|
|
|
DO_FADD, DO_FMUL, DO_FDIV,
|
|
|
|
@ -45,6 +45,7 @@ architecture behaviour of fpu is
|
|
|
|
|
DO_FSEL,
|
|
|
|
|
FRI_1,
|
|
|
|
|
ADD_SHIFT, ADD_2, ADD_3,
|
|
|
|
|
CMP_1, CMP_2,
|
|
|
|
|
MULT_1,
|
|
|
|
|
LOOKUP,
|
|
|
|
|
DIV_2, DIV_3, DIV_4, DIV_5, DIV_6,
|
|
|
|
@ -603,7 +604,11 @@ begin
|
|
|
|
|
if e_in.valid = '1' then
|
|
|
|
|
case e_in.insn(5 downto 1) is
|
|
|
|
|
when "00000" =>
|
|
|
|
|
v.state := DO_MCRFS;
|
|
|
|
|
if e_in.insn(7) = '1' then
|
|
|
|
|
v.state := DO_MCRFS;
|
|
|
|
|
else
|
|
|
|
|
v.state := DO_FCMP;
|
|
|
|
|
end if;
|
|
|
|
|
when "00110" =>
|
|
|
|
|
if e_in.insn(10) = '0' then
|
|
|
|
|
if e_in.insn(8) = '0' then
|
|
|
|
@ -669,6 +674,62 @@ begin
|
|
|
|
|
v.instr_done := '1';
|
|
|
|
|
v.state := IDLE;
|
|
|
|
|
|
|
|
|
|
when DO_FCMP =>
|
|
|
|
|
-- fcmp[uo]
|
|
|
|
|
v.instr_done := '1';
|
|
|
|
|
v.state := IDLE;
|
|
|
|
|
update_fx := '1';
|
|
|
|
|
opsel_a <= AIN_B;
|
|
|
|
|
opsel_r <= RES_SUM;
|
|
|
|
|
v.result_exp := r.b.exponent;
|
|
|
|
|
if (r.a.class = NAN and r.a.mantissa(53) = '0') or
|
|
|
|
|
(r.b.class = NAN and r.b.mantissa(53) = '0') then
|
|
|
|
|
-- Signalling NAN
|
|
|
|
|
v.fpscr(FPSCR_VXSNAN) := '1';
|
|
|
|
|
if r.insn(6) = '1' and r.fpscr(FPSCR_VE) = '0' then
|
|
|
|
|
v.fpscr(FPSCR_VXVC) := '1';
|
|
|
|
|
end if;
|
|
|
|
|
invalid := '1';
|
|
|
|
|
v.cr_result := "0001"; -- unordered
|
|
|
|
|
elsif r.a.class = NAN or r.b.class = NAN then
|
|
|
|
|
if r.insn(6) = '1' then
|
|
|
|
|
-- fcmpo
|
|
|
|
|
v.fpscr(FPSCR_VXVC) := '1';
|
|
|
|
|
invalid := '1';
|
|
|
|
|
end if;
|
|
|
|
|
v.cr_result := "0001"; -- unordered
|
|
|
|
|
elsif r.a.class = ZERO and r.b.class = ZERO then
|
|
|
|
|
v.cr_result := "0010"; -- equal
|
|
|
|
|
elsif r.a.negative /= r.b.negative then
|
|
|
|
|
v.cr_result := r.a.negative & r.b.negative & "00";
|
|
|
|
|
elsif r.a.class = ZERO then
|
|
|
|
|
-- A and B are the same sign from here down
|
|
|
|
|
v.cr_result := not r.b.negative & r.b.negative & "00";
|
|
|
|
|
elsif r.a.class = INFINITY then
|
|
|
|
|
if r.b.class = INFINITY then
|
|
|
|
|
v.cr_result := "0010";
|
|
|
|
|
else
|
|
|
|
|
v.cr_result := r.a.negative & not r.a.negative & "00";
|
|
|
|
|
end if;
|
|
|
|
|
elsif r.b.class = ZERO then
|
|
|
|
|
-- A is finite from here down
|
|
|
|
|
v.cr_result := r.a.negative & not r.a.negative & "00";
|
|
|
|
|
elsif r.b.class = INFINITY then
|
|
|
|
|
v.cr_result := not r.b.negative & r.b.negative & "00";
|
|
|
|
|
elsif r.exp_cmp = '1' then
|
|
|
|
|
-- A and B are both finite from here down
|
|
|
|
|
v.cr_result := r.a.negative & not r.a.negative & "00";
|
|
|
|
|
elsif r.a.exponent /= r.b.exponent then
|
|
|
|
|
-- A exponent is smaller than B
|
|
|
|
|
v.cr_result := not r.a.negative & r.a.negative & "00";
|
|
|
|
|
else
|
|
|
|
|
-- Prepare to subtract mantissas, put B in R
|
|
|
|
|
v.cr_result := "0000";
|
|
|
|
|
v.instr_done := '0';
|
|
|
|
|
v.state := CMP_1;
|
|
|
|
|
end if;
|
|
|
|
|
v.fpscr(FPSCR_FL downto FPSCR_FU) := v.cr_result;
|
|
|
|
|
|
|
|
|
|
when DO_MTFSB =>
|
|
|
|
|
-- mtfsb{0,1}
|
|
|
|
|
j := to_integer(unsigned(insn_bt(r.insn)));
|
|
|
|
@ -1193,6 +1254,26 @@ begin
|
|
|
|
|
v.state := NORMALIZE;
|
|
|
|
|
end if;
|
|
|
|
|
|
|
|
|
|
when CMP_1 =>
|
|
|
|
|
opsel_a <= AIN_A;
|
|
|
|
|
opsel_b <= BIN_R;
|
|
|
|
|
opsel_binv <= '1';
|
|
|
|
|
carry_in <= '1';
|
|
|
|
|
v.state := CMP_2;
|
|
|
|
|
|
|
|
|
|
when CMP_2 =>
|
|
|
|
|
if r.r(63) = '1' then
|
|
|
|
|
-- A is smaller in magnitude
|
|
|
|
|
v.cr_result := not r.a.negative & r.a.negative & "00";
|
|
|
|
|
elsif (r_hi_nz or r_lo_nz) = '0' then
|
|
|
|
|
v.cr_result := "0010";
|
|
|
|
|
else
|
|
|
|
|
v.cr_result := r.a.negative & not r.a.negative & "00";
|
|
|
|
|
end if;
|
|
|
|
|
v.fpscr(FPSCR_FL downto FPSCR_FU) := v.cr_result;
|
|
|
|
|
v.instr_done := '1';
|
|
|
|
|
v.state := IDLE;
|
|
|
|
|
|
|
|
|
|
when MULT_1 =>
|
|
|
|
|
f_to_multiply.valid <= r.first;
|
|
|
|
|
opsel_r <= RES_MULT;
|
|
|
|
|