From fc2968f13279524cfc44581ebf4c308bd78611c9 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 29 Aug 2020 20:34:55 +1000 Subject: [PATCH] FPU: Implement remaining FPSCR-related instructions This implements mcrfs, mtfsfi, mtfsb0/1, mffscr, mffscrn, mffscrni and mffsl. Signed-off-by: Paul Mackerras --- decode1.vhdl | 4 +++ fpu.vhdl | 81 ++++++++++++++++++++++++++++++++++++++++++++--- insn_helpers.vhdl | 6 ++++ 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/decode1.vhdl b/decode1.vhdl index afd37ef..343c0c3 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -422,6 +422,10 @@ architecture behaviour of decode1 is constant decode_op_63l_array : op_63_subop_array_0_t := ( -- unit internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl -- op in out A out in out len ext pipe + 2#000000010# => (FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- 2/0=mcrfs + 2#011000001# => (FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 1/6=mtfsb1 + 2#011000010# => (FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 2/6=mtfsb0 + 2#011000100# => (FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 4/6=mtfsfi 2#011110010# => (FPU, OP_FPOP_I, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 18/7=mffs family 2#011110110# => (FPU, OP_FPOP_I, NONE, FRB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 22/7=mtfsf others => illegal_inst diff --git a/fpu.vhdl b/fpu.vhdl index b05ec9d..047bf2d 100644 --- a/fpu.vhdl +++ b/fpu.vhdl @@ -26,7 +26,7 @@ end entity fpu; architecture behaviour of fpu is type state_t is (IDLE, - DO_MFFS, DO_MTFSF); + DO_MCRFS, DO_MTFSB, DO_MTFSFI, DO_MFFS, DO_MTFSF); type reg_type is record state : state_t; @@ -42,6 +42,7 @@ architecture behaviour of fpu is single_prec : std_ulogic; fpscr : std_ulogic_vector(31 downto 0); b : std_ulogic_vector(63 downto 0); + r : std_ulogic_vector(63 downto 0); writing_back : std_ulogic; cr_result : std_ulogic_vector(3 downto 0); cr_mask : std_ulogic_vector(7 downto 0); @@ -77,13 +78,14 @@ begin w_out.write_enable <= r.writing_back; w_out.write_reg <= r.dest_fpr; w_out.write_data <= fp_result; - w_out.write_cr_enable <= r.instr_done and r.rc; + w_out.write_cr_enable <= r.instr_done and (r.rc or r.is_cmp); w_out.write_cr_mask <= r.cr_mask; w_out.write_cr_data <= r.cr_result & r.cr_result & r.cr_result & r.cr_result & r.cr_result & r.cr_result & r.cr_result & r.cr_result; fpu_1: process(all) variable v : reg_type; + variable fpscr_mask : std_ulogic_vector(31 downto 0); variable illegal : std_ulogic; variable j, k : integer; variable flm : std_ulogic_vector(7 downto 0); @@ -101,17 +103,30 @@ begin v.single_prec := e_in.single; v.rc := e_in.rc; v.is_cmp := e_in.out_cr; - v.cr_mask := num_to_fxm(1); + if e_in.out_cr = '0' then + v.cr_mask := num_to_fxm(1); + else + v.cr_mask := num_to_fxm(to_integer(unsigned(insn_bf(e_in.insn)))); + end if; v.b := e_in.frb; end if; v.writing_back := '0'; v.instr_done := '0'; + fpscr_mask := (others => '1'); case r.state is when IDLE => if e_in.valid = '1' then case e_in.insn(5 downto 1) is + when "00000" => + v.state := DO_MCRFS; + when "00110" => + if e_in.insn(8) = '0' then + v.state := DO_MTFSB; + else + v.state := DO_MTFSFI; + end if; when "00111" => if e_in.insn(8) = '0' then v.state := DO_MFFS; @@ -123,11 +138,67 @@ begin end case; end if; + when DO_MCRFS => + j := to_integer(unsigned(insn_bfa(r.insn))); + for i in 0 to 7 loop + if i = j then + k := (7 - i) * 4; + v.cr_result := r.fpscr(k + 3 downto k); + fpscr_mask(k + 3 downto k) := "0000"; + end if; + end loop; + v.fpscr := r.fpscr and (fpscr_mask or x"6007F8FF"); + v.instr_done := '1'; + v.state := IDLE; + + when DO_MTFSB => + -- mtfsb{0,1} + j := to_integer(unsigned(insn_bt(r.insn))); + for i in 0 to 31 loop + if i = j then + v.fpscr(31 - i) := r.insn(6); + end if; + end loop; + v.instr_done := '1'; + v.state := IDLE; + + when DO_MTFSFI => + -- mtfsfi + j := to_integer(unsigned(insn_bf(r.insn))); + if r.insn(16) = '0' then + for i in 0 to 7 loop + if i = j then + k := (7 - i) * 4; + v.fpscr(k + 3 downto k) := insn_u(r.insn); + end if; + end loop; + end if; + v.instr_done := '1'; + v.state := IDLE; + when DO_MFFS => v.writing_back := '1'; case r.insn(20 downto 16) is when "00000" => -- mffs + when "00001" => + -- mffsce + v.fpscr(FPSCR_VE downto FPSCR_XE) := "00000"; + when "10100" | "10101" => + -- mffscdrn[i] (but we don't implement DRN) + fpscr_mask := x"000000FF"; + when "10110" => + -- mffscrn + fpscr_mask := x"000000FF"; + v.fpscr(FPSCR_RN+1 downto FPSCR_RN) := + r.b(FPSCR_RN+1 downto FPSCR_RN); + when "10111" => + -- mffscrni + fpscr_mask := x"000000FF"; + v.fpscr(FPSCR_RN+1 downto FPSCR_RN) := r.insn(12 downto 11); + when "11000" => + -- mffsl + fpscr_mask := x"0007F0FF"; when others => illegal := '1'; end case; @@ -155,7 +226,9 @@ begin -- Data path. -- Just enough to read FPSCR for now. - fp_result <= x"00000000" & r.fpscr; + v.r := x"00000000" & (r.fpscr and fpscr_mask); + + fp_result <= r.r; v.fpscr(FPSCR_VX) := (or (v.fpscr(FPSCR_VXSNAN downto FPSCR_VXVC))) or (or (v.fpscr(FPSCR_VXSOFT downto FPSCR_VXCVI))); diff --git a/insn_helpers.vhdl b/insn_helpers.vhdl index be3892a..519aa76 100644 --- a/insn_helpers.vhdl +++ b/insn_helpers.vhdl @@ -41,6 +41,7 @@ package insn_helpers is function insn_fra (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_frb (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_frc (insn_in : std_ulogic_vector) return std_ulogic_vector; + function insn_u (insn_in : std_ulogic_vector) return std_ulogic_vector; end package insn_helpers; package body insn_helpers is @@ -238,4 +239,9 @@ package body insn_helpers is begin return insn_in(10 downto 6); end; + + function insn_u(insn_in : std_ulogic_vector) return std_ulogic_vector is + begin + return insn_in(15 downto 12); + end; end package body insn_helpers; -- 2.30.2