FPU: Implement fsel
authorPaul Mackerras <paulus@ozlabs.org>
Wed, 29 Jul 2020 10:26:39 +0000 (20:26 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Thu, 3 Sep 2020 07:45:18 +0000 (17:45 +1000)
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
decode1.vhdl
fpu.vhdl

index c0c346513eb1ce7f6170cf807d53138df5a1242e..09aaf9196a011edf2f6730369215408541f9f0b4 100644 (file)
@@ -474,6 +474,7 @@ architecture behaviour of decode1 is
         2#0010#  =>  (FPU,   OP_FPOP,       FRA,  FRB,  NONE, FRT,  '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- fdiv
         2#0100#  =>  (FPU,   OP_FPOP,       FRA,  FRB,  NONE, FRT,  '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- fsub
         2#0101#  =>  (FPU,   OP_FPOP,       FRA,  FRB,  NONE, FRT,  '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- fadd
+        2#0111#  =>  (FPU,   OP_FPOP,       FRA,  FRB,  FRC,  FRT,  '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- fsel
         2#1000#  =>  (FPU,   OP_FPOP,       NONE, FRB,  NONE, FRT,  '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- fre
         2#1001#  =>  (FPU,   OP_FPOP,       FRA,  NONE, FRC,  FRT,  '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- fmul
         others => illegal_inst
index fee1776c55014e549291da7a455cd8033379f348..59e6f5d829782ec61f13977a36a18ff85b9cc691 100644 (file)
--- a/fpu.vhdl
+++ b/fpu.vhdl
@@ -42,6 +42,7 @@ architecture behaviour of fpu is
                      DO_FRSP, DO_FRI,
                      DO_FADD, DO_FMUL, DO_FDIV,
                      DO_FRE,
+                     DO_FSEL,
                      FRI_1,
                      ADD_SHIFT, ADD_2, ADD_3,
                      MULT_1,
@@ -641,6 +642,8 @@ begin
                             v.state := DO_FDIV;
                         when "10100" | "10101" =>
                             v.state := DO_FADD;
+                        when "10111" =>
+                            v.state := DO_FSEL;
                         when "11000" =>
                             v.state := DO_FRE;
                         when "11001" =>
@@ -1045,6 +1048,24 @@ begin
                     arith_done := '1';
                 end if;
 
+            when DO_FSEL =>
+                opsel_a <= AIN_A;
+                v.fpscr(FPSCR_FR) := '0';
+                v.fpscr(FPSCR_FI) := '0';
+                if r.a.class = ZERO or (r.a.negative = '0' and r.a.class /= NAN) then
+                    v.result_sign := r.c.negative;
+                    v.result_exp := r.c.exponent;
+                    v.result_class := r.c.class;
+                    opsel_a <= AIN_C;
+                else
+                    v.result_sign := r.b.negative;
+                    v.result_exp := r.b.exponent;
+                    v.result_class := r.b.class;
+                    opsel_a <= AIN_B;
+                end if;
+                v.quieten_nan := '0';
+                arith_done := '1';
+
             when DO_FRE =>
                 opsel_a <= AIN_B;
                 v.result_class := r.b.class;