mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-02 19:58:07 +00:00
FPU: Implement remaining FPSCR-related instructions
This implements mcrfs, mtfsfi, mtfsb0/1, mffscr, mffscrn, mffscrni and mffsl. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
@@ -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
|
||||
|
||||
81
fpu.vhdl
81
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)));
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user