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
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;
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);
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);
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;
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;
-- 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)));