mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-15 15:50:24 +00:00
FPU: Implement fcmpu and fcmpo
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
@@ -436,6 +436,8 @@ 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#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#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
|
||||
|
||||
85
fpu.vhdl
85
fpu.vhdl
@@ -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_FMR, DO_FMRG, DO_FCMP,
|
||||
DO_FCFID, DO_FCTI,
|
||||
DO_FRSP, DO_FRI,
|
||||
DO_FADD, DO_FMUL, DO_FDIV,
|
||||
@@ -45,6 +45,7 @@ architecture behaviour of fpu is
|
||||
DO_FSEL,
|
||||
FRI_1,
|
||||
ADD_SHIFT, ADD_2, ADD_3,
|
||||
CMP_1, CMP_2,
|
||||
MULT_1,
|
||||
LOOKUP,
|
||||
DIV_2, DIV_3, DIV_4, DIV_5, DIV_6,
|
||||
@@ -603,7 +604,11 @@ begin
|
||||
if e_in.valid = '1' then
|
||||
case e_in.insn(5 downto 1) is
|
||||
when "00000" =>
|
||||
v.state := DO_MCRFS;
|
||||
if e_in.insn(7) = '1' then
|
||||
v.state := DO_MCRFS;
|
||||
else
|
||||
v.state := DO_FCMP;
|
||||
end if;
|
||||
when "00110" =>
|
||||
if e_in.insn(10) = '0' then
|
||||
if e_in.insn(8) = '0' then
|
||||
@@ -669,6 +674,62 @@ begin
|
||||
v.instr_done := '1';
|
||||
v.state := IDLE;
|
||||
|
||||
when DO_FCMP =>
|
||||
-- fcmp[uo]
|
||||
v.instr_done := '1';
|
||||
v.state := IDLE;
|
||||
update_fx := '1';
|
||||
opsel_a <= AIN_B;
|
||||
opsel_r <= RES_SUM;
|
||||
v.result_exp := r.b.exponent;
|
||||
if (r.a.class = NAN and r.a.mantissa(53) = '0') or
|
||||
(r.b.class = NAN and r.b.mantissa(53) = '0') then
|
||||
-- Signalling NAN
|
||||
v.fpscr(FPSCR_VXSNAN) := '1';
|
||||
if r.insn(6) = '1' and r.fpscr(FPSCR_VE) = '0' then
|
||||
v.fpscr(FPSCR_VXVC) := '1';
|
||||
end if;
|
||||
invalid := '1';
|
||||
v.cr_result := "0001"; -- unordered
|
||||
elsif r.a.class = NAN or r.b.class = NAN then
|
||||
if r.insn(6) = '1' then
|
||||
-- fcmpo
|
||||
v.fpscr(FPSCR_VXVC) := '1';
|
||||
invalid := '1';
|
||||
end if;
|
||||
v.cr_result := "0001"; -- unordered
|
||||
elsif r.a.class = ZERO and r.b.class = ZERO then
|
||||
v.cr_result := "0010"; -- equal
|
||||
elsif r.a.negative /= r.b.negative then
|
||||
v.cr_result := r.a.negative & r.b.negative & "00";
|
||||
elsif r.a.class = ZERO then
|
||||
-- A and B are the same sign from here down
|
||||
v.cr_result := not r.b.negative & r.b.negative & "00";
|
||||
elsif r.a.class = INFINITY then
|
||||
if r.b.class = INFINITY then
|
||||
v.cr_result := "0010";
|
||||
else
|
||||
v.cr_result := r.a.negative & not r.a.negative & "00";
|
||||
end if;
|
||||
elsif r.b.class = ZERO then
|
||||
-- A is finite from here down
|
||||
v.cr_result := r.a.negative & not r.a.negative & "00";
|
||||
elsif r.b.class = INFINITY then
|
||||
v.cr_result := not r.b.negative & r.b.negative & "00";
|
||||
elsif r.exp_cmp = '1' then
|
||||
-- A and B are both finite from here down
|
||||
v.cr_result := r.a.negative & not r.a.negative & "00";
|
||||
elsif r.a.exponent /= r.b.exponent then
|
||||
-- A exponent is smaller than B
|
||||
v.cr_result := not r.a.negative & r.a.negative & "00";
|
||||
else
|
||||
-- Prepare to subtract mantissas, put B in R
|
||||
v.cr_result := "0000";
|
||||
v.instr_done := '0';
|
||||
v.state := CMP_1;
|
||||
end if;
|
||||
v.fpscr(FPSCR_FL downto FPSCR_FU) := v.cr_result;
|
||||
|
||||
when DO_MTFSB =>
|
||||
-- mtfsb{0,1}
|
||||
j := to_integer(unsigned(insn_bt(r.insn)));
|
||||
@@ -1193,6 +1254,26 @@ begin
|
||||
v.state := NORMALIZE;
|
||||
end if;
|
||||
|
||||
when CMP_1 =>
|
||||
opsel_a <= AIN_A;
|
||||
opsel_b <= BIN_R;
|
||||
opsel_binv <= '1';
|
||||
carry_in <= '1';
|
||||
v.state := CMP_2;
|
||||
|
||||
when CMP_2 =>
|
||||
if r.r(63) = '1' then
|
||||
-- A is smaller in magnitude
|
||||
v.cr_result := not r.a.negative & r.a.negative & "00";
|
||||
elsif (r_hi_nz or r_lo_nz) = '0' then
|
||||
v.cr_result := "0010";
|
||||
else
|
||||
v.cr_result := r.a.negative & not r.a.negative & "00";
|
||||
end if;
|
||||
v.fpscr(FPSCR_FL downto FPSCR_FU) := v.cr_result;
|
||||
v.instr_done := '1';
|
||||
v.state := IDLE;
|
||||
|
||||
when MULT_1 =>
|
||||
f_to_multiply.valid <= r.first;
|
||||
opsel_r <= RES_MULT;
|
||||
|
||||
Reference in New Issue
Block a user