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