From 2731384a4be19877c40fedfaeb72565d279577df Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 1 Mar 2024 22:12:46 +1100 Subject: [PATCH] FPU: Reduce misc_sel to 3 bits Signed-off-by: Paul Mackerras --- fpu.vhdl | 101 +++++++++++++++++++++++++------------------------------ 1 file changed, 45 insertions(+), 56 deletions(-) diff --git a/fpu.vhdl b/fpu.vhdl index 1a584d5..a309705 100644 --- a/fpu.vhdl +++ b/fpu.vhdl @@ -200,7 +200,7 @@ architecture behaviour of fpu is signal r_lo_nz : std_ulogic; signal r_gt_1 : std_ulogic; signal s_nz : std_ulogic; - signal misc_sel : std_ulogic_vector(3 downto 0); + signal misc_sel : std_ulogic_vector(2 downto 0); signal f_to_multiply : MultiplyInputType; signal multiply_to_f : MultiplyOutputType; signal msel_1 : std_ulogic_vector(1 downto 0); @@ -1150,7 +1150,7 @@ begin opsel_r <= RES_SUM; opsel_s <= S_ZERO; carry_in <= '0'; - misc_sel <= "0000"; + misc_sel <= "000"; fpscr_mask := (others => '1'); update_fx := '0'; arith_done := '0'; @@ -1498,13 +1498,14 @@ begin when DO_FMRG => -- fmrgew, fmrgow opsel_r <= RES_MISC; - misc_sel <= "01" & r.insn(8) & '0'; + misc_sel <= "100"; v.writing_fpr := '1'; v.instr_done := '1'; when DO_MFFS => v.writing_fpr := '1'; opsel_r <= RES_MISC; + misc_sel <= "011"; case r.insn(20 downto 16) is when "00000" => -- mffs @@ -2153,7 +2154,7 @@ begin re_neg1 <= '1'; re_set_result <= '1'; opsel_r <= RES_MISC; - misc_sel <= "0111"; + misc_sel <= "101"; -- set shift to 1 rs_con2 <= RSCON2_1; v.state := NORMALIZE; @@ -2173,7 +2174,7 @@ begin when RSQRT_1 => opsel_r <= RES_MISC; - misc_sel <= "0111"; + misc_sel <= "101"; re_sel1 <= REXP1_BHALF; re_neg1 <= '1'; re_set_result <= '1'; @@ -2186,7 +2187,7 @@ begin -- also transfer B (in R) to A set_a := '1'; opsel_r <= RES_MISC; - misc_sel <= "0111"; + misc_sel <= "101"; msel_1 <= MUL1_B; msel_2 <= MUL2_LUT; f_to_multiply.valid <= '1'; @@ -2399,7 +2400,7 @@ begin else msb := r.r(63); end if; - misc_sel <= '1' & r.insn(9 downto 8) & r.result_sign; + misc_sel <= "110"; if (r.insn(8) = '0' and msb /= r.result_sign) or (r.insn(8) = '1' and msb /= '1') then opsel_r <= RES_MISC; @@ -2414,10 +2415,7 @@ begin when INT_OFLOW => opsel_r <= RES_MISC; - misc_sel <= '1' & r.insn(9 downto 8) & r.result_sign; - if r.b.class = NAN then - misc_sel(0) <= '1'; - end if; + misc_sel <= "110"; v.fpscr(FPSCR_VXCVI) := '1'; invalid := '1'; arith_done := '1'; @@ -2515,7 +2513,7 @@ begin re_con2 <= RECON2_MAX; re_set_result <= '1'; opsel_r <= RES_MISC; - misc_sel <= "001" & r.single_prec; + misc_sel <= "010"; arith_done := '1'; else -- enabled overflow exception @@ -2761,7 +2759,7 @@ begin -- less than 0.5, in which case we want to use 0.5, to avoid -- infinite loops in some cases. opsel_r <= RES_MISC; - misc_sel <= "0001"; + misc_sel <= "001"; if multiply_to_f.valid = '1' then v.first := '1'; if r.count = "11" then @@ -2774,7 +2772,7 @@ begin -- Get 0.5 into R; it turns out the generated -- QNaN mantissa is actually what we want opsel_r <= RES_MISC; - misc_sel <= "0001"; + misc_sel <= "001"; v.opsel_a := AIN_A; -- set shift to 64 rs_con2 <= RSCON2_64; @@ -3136,7 +3134,7 @@ begin v.instr_done := '1'; when IDIV_ZERO => opsel_r <= RES_MISC; - misc_sel <= "0101"; + misc_sel <= "000"; v.xerc_result := v.xerc; if r.oe = '1' then v.xerc_result.ov := r.int_ovf; @@ -3176,7 +3174,7 @@ begin invalid := '1'; v.result_class := NAN; rsign := '0'; - misc_sel <= "0001"; + misc_sel <= "001"; opsel_r <= RES_MISC; arith_done := '1'; end if; @@ -3342,50 +3340,41 @@ begin when others => misc := (others => '0'); case misc_sel is - when "0000" => - misc := x"00000000" & (r.fpscr and fpscr_mask); - when "0001" => - -- generated QNaN mantissa + when "000" => + -- zero result, used in idiv logic + when "001" => + -- generated QNaN mantissa; also used for 0.5 in idiv logic misc(QNAN_BIT) := '1'; - when "0010" => - -- mantissa of max representable DP number - misc(UNIT_BIT downto DP_LSB) := (others => '1'); - when "0011" => - -- mantissa of max representable SP number + when "010" => + -- mantissa of max representable number, DP or SP misc(UNIT_BIT downto SP_LSB) := (others => '1'); - when "0100" => - -- fmrgow result - misc := r.a.mantissa(31 downto 0) & r.b.mantissa(31 downto 0); - when "0110" => - -- fmrgew result - misc := r.a.mantissa(63 downto 32) & r.b.mantissa(63 downto 32); - when "0111" => + misc(SP_LSB-1 downto DP_LSB) := (others => not r.single_prec); + when "011" => + -- read FPSCR + misc := x"00000000" & (r.fpscr and fpscr_mask); + when "100" => + -- fmrgow/fmrgew result + if r.insn(8) = '0' then + misc := r.a.mantissa(31 downto 0) & r.b.mantissa(31 downto 0); + else + misc := r.a.mantissa(63 downto 32) & r.b.mantissa(63 downto 32); + end if; + when "101" => misc := std_ulogic_vector(shift_left(resize(unsigned(inverse_est), 64), UNIT_BIT - 19)); - when "1000" => - -- max positive result for fctiw[z] - misc := x"000000007fffffff"; - when "1001" => - -- max negative result for fctiw[z] - misc := x"ffffffff80000000"; - when "1010" => - -- max positive result for fctiwu[z] - misc := x"00000000ffffffff"; - when "1011" => - -- max negative result for fctiwu[z] - misc := x"0000000000000000"; - when "1100" => - -- max positive result for fctid[z] - misc := x"7fffffffffffffff"; - when "1101" => - -- max negative result for fctid[z] - misc := x"8000000000000000"; - when "1110" => - -- max positive result for fctidu[z] - misc := x"ffffffffffffffff"; - when "1111" => - -- max negative result for fctidu[z] - misc := x"0000000000000000"; + when "110" => + -- max positive or negative result for fcti* + if r.result_sign = '0' and r.b.class /= NAN then + misc := x"000000007fffffff"; + misc(31) := r.insn(8) or r.insn(9); -- unsigned or dword + misc(62 downto 32) := (others => r.insn(9)); -- dword + misc(63) := r.insn(8) and r.insn(8); + elsif r.insn(8) = '0' then + misc(63) := '1'; + if r.insn(9) = '0' then + misc(62 downto 31) := (others => '1'); + end if; + end if; when others => end case; result <= misc;