FPU: Implement ftdiv and ftsqrt

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/245/head
Paul Mackerras 4 years ago
parent c350bc1f25
commit c083b9507d

@ -441,6 +441,8 @@ architecture behaviour of decode1 is
2#000000000# => (FPU, OP_FPOP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- 0/0=fcmpu
2#000000001# => (FPU, OP_FPOP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- 1/0=fcmpo
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#000000100# => (FPU, OP_FPOP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- 4/0=ftdiv
2#000000101# => (FPU, OP_FPOP, NONE, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- 5/0=ftsqrt
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

@ -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_FCMP,
DO_FMR, DO_FMRG, DO_FCMP, DO_FTDIV, DO_FTSQRT,
DO_FCFID, DO_FCTI,
DO_FRSP, DO_FRI,
DO_FADD, DO_FMUL, DO_FDIV, DO_FSQRT,
@ -51,6 +51,7 @@ architecture behaviour of fpu is
DIV_2, DIV_3, DIV_4, DIV_5, DIV_6,
FRE_1,
RSQRT_1,
FTDIV_1,
SQRT_1, SQRT_2, SQRT_3, SQRT_4,
SQRT_5, SQRT_6, SQRT_7, SQRT_8,
SQRT_9, SQRT_10, SQRT_11, SQRT_12,
@ -105,6 +106,7 @@ architecture behaviour of fpu is
is_sqrt : std_ulogic;
first : std_ulogic;
count : unsigned(1 downto 0);
doing_ftdiv : std_ulogic_vector(1 downto 0);
end record;

type lookup_table is array(0 to 1023) of std_ulogic_vector(17 downto 0);
@ -642,6 +644,8 @@ begin
v.is_multiply := '0';
v.is_sqrt := '0';
v.add_bsmall := '0';
v.doing_ftdiv := "00";

adec := decode_dp(e_in.fra, int_input);
bdec := decode_dp(e_in.frb, int_input);
cdec := decode_dp(e_in.frc, int_input);
@ -659,8 +663,16 @@ begin
r_lo_nz <= or (r.r(30 downto 2));

if r.single_prec = '0' then
max_exp := to_signed(1023, EXP_BITS);
min_exp := to_signed(-1022, EXP_BITS);
if r.doing_ftdiv(1) = '0' then
max_exp := to_signed(1023, EXP_BITS);
else
max_exp := to_signed(1020, EXP_BITS);
end if;
if r.doing_ftdiv(0) = '0' then
min_exp := to_signed(-1022, EXP_BITS);
else
min_exp := to_signed(-1021, EXP_BITS);
end if;
bias_exp := to_signed(1536, EXP_BITS);
else
max_exp := to_signed(127, EXP_BITS);
@ -728,7 +740,13 @@ begin
if e_in.valid = '1' then
case e_in.insn(5 downto 1) is
when "00000" =>
if e_in.insn(7) = '1' then
if e_in.insn(8) = '1' then
if e_in.insn(6) = '0' then
v.state := DO_FTDIV;
else
v.state := DO_FTSQRT;
end if;
elsif e_in.insn(7) = '1' then
v.state := DO_MCRFS;
else
v.state := DO_FCMP;
@ -804,6 +822,38 @@ begin
v.instr_done := '1';
v.state := IDLE;

when DO_FTDIV =>
v.instr_done := '1';
v.state := IDLE;
v.cr_result := "0000";
if r.a.class = INFINITY or r.b.class = ZERO or r.b.class = INFINITY or
(r.b.class = FINITE and r.b.mantissa(53) = '0') then
v.cr_result(2) := '1';
end if;
if r.a.class = NAN or r.a.class = INFINITY or
r.b.class = NAN or r.b.class = ZERO or r.b.class = INFINITY or
(r.a.class = FINITE and r.a.exponent <= to_signed(-970, EXP_BITS)) then
v.cr_result(1) := '1';
else
v.doing_ftdiv := "11";
v.first := '1';
v.state := FTDIV_1;
v.instr_done := '0';
end if;

when DO_FTSQRT =>
v.instr_done := '1';
v.state := IDLE;
v.cr_result := "0000";
if r.b.class = ZERO or r.b.class = INFINITY or
(r.b.class = FINITE and r.b.mantissa(53) = '0') then
v.cr_result(2) := '1';
end if;
if r.b.class = NAN or r.b.class = INFINITY or r.b.class = ZERO
or r.b.negative = '1' or r.b.exponent <= to_signed(-970, EXP_BITS) then
v.cr_result(1) := '0';
end if;

when DO_FCMP =>
-- fcmp[uo]
v.instr_done := '1';
@ -1587,6 +1637,16 @@ begin
v.shift := to_signed(1, EXP_BITS);
v.state := NORMALIZE;

when FTDIV_1 =>
v.cr_result(1) := exp_tiny or exp_huge;
if exp_tiny = '1' or exp_huge = '1' or r.a.class = ZERO or r.first = '0' then
v.instr_done := '1';
v.state := IDLE;
else
v.shift := r.a.exponent;
v.doing_ftdiv := "10";
end if;

when RSQRT_1 =>
opsel_r <= RES_MISC;
misc_sel <= "0111";

Loading…
Cancel
Save