@ -44,7 +44,7 @@ architecture behaviour of fpu is
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     DO_FRE, DO_FRSQRTE,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     DO_FSEL,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     FRI_1,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     ADD_SHIFT, ADD_2, ADD_3,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     ADD_1, ADD_SHIFT, ADD_2, ADD_3,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     CMP_1, CMP_2,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     MULT_1,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     FMADD_1, FMADD_2, FMADD_3,
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -65,7 +65,8 @@ architecture behaviour of fpu is
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     DENORM,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     RENORM_A, RENORM_A2,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     RENORM_B, RENORM_B2,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     RENORM_C, RENORM_C2);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     RENORM_C, RENORM_C2,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     NAN_RESULT, EXC_RESULT);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    type reg_type is record
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        state        : state_t;
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -111,6 +112,12 @@ architecture behaviour of fpu is
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        first        : std_ulogic;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        count        : unsigned(1 downto 0);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        doing_ftdiv  : std_ulogic_vector(1 downto 0);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        opsel_a      : std_ulogic_vector(1 downto 0);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        use_a        : std_ulogic;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        use_b        : std_ulogic;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        use_c        : std_ulogic;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        invalid      : std_ulogic;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        negate       : std_ulogic;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    end record;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    type lookup_table is array(0 to 1023) of std_ulogic_vector(17 downto 0);
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -118,7 +125,6 @@ architecture behaviour of fpu is
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    signal r, rin : reg_type;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    signal fp_result     : std_ulogic_vector(63 downto 0);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    signal opsel_a       : std_ulogic_vector(1 downto 0);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    signal opsel_b       : std_ulogic_vector(1 downto 0);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    signal opsel_r       : std_ulogic_vector(1 downto 0);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    signal opsel_s       : std_ulogic_vector(1 downto 0);
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -724,7 +730,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        v.update_fprf := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        v.shift := to_signed(0, EXP_BITS);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        v.first := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        opsel_a <= AIN_R;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        v.opsel_a := AIN_R;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        opsel_ainv <= '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        opsel_amask <= '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        opsel_b <= BIN_ZERO;
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -758,6 +764,11 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        shiftin := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        case r.state is
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when IDLE =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_a := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_b := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_c := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.invalid := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.negate := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if e_in.valid = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    case e_in.insn(5 downto 1) is
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "00000" =>
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -770,6 +781,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            elsif e_in.insn(7) = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.state := DO_MCRFS;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.state := DO_FCMP;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "00110" =>
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -789,14 +801,17 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.state := DO_MTFSF;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "01000" =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            if e_in.insn(9 downto 8) /= "11" then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.state := DO_FMR;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.state := DO_FRI;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "01100" =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := DO_FRSP;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "01110" =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            if int_input = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                -- fcfid[u][s]
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.state := DO_FCFID;
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -805,25 +820,45 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "01111" =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.round_mode := "001";
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := DO_FCTI;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "10010" =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.opsel_a := AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            if v.b.mantissa(54) = '0' and v.a.mantissa(54) = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := DO_FDIV;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "10100" | "10101" =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.opsel_a := AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := DO_FADD;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "10110" =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.is_sqrt := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := DO_FSQRT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "10111" =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := DO_FSEL;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "11000" =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := DO_FRE;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "11001" =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.is_multiply := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.opsel_a := AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            if v.c.mantissa(54) = '0' and v.a.mantissa(54) = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.opsel_a := AIN_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := DO_FMUL;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "11010" =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.is_sqrt := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := DO_FRSQRTE;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when "11100" | "11101" | "11110" | "11111" =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            if v.a.mantissa(54) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.opsel_a := AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            elsif v.c.mantissa(54) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.opsel_a := AIN_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := DO_FMADD;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        when others =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            illegal := '1';
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -880,11 +915,10 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when DO_FCMP =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- fcmp[uo]
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                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
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -930,6 +964,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    -- Prepare to subtract mantissas, put B in R
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.cr_result := "0000";
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.instr_done := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.opsel_a := AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.state := CMP_1;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FL downto FPSCR_FU) := v.cr_result;
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -1017,7 +1052,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.state := IDLE;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when DO_FMR =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_class := r.b.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_exp := r.b.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.quieten_nan := '0';
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1037,7 +1072,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.state := IDLE;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when DO_FRI =>    -- fri[nzpm]
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_class := r.b.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := r.b.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_exp := r.b.exponent;
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1062,7 +1097,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when DO_FRSP =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_B, r.shift = 0
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_class := r.b.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := r.b.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_exp := r.b.exponent;
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -1092,7 +1127,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- instr bit 9: 1=dword 0=word
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- instr bit 8: 1=unsigned 0=signed
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- instr bit 1: 1=round to zero 0=use fpscr[RN]
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_class := r.b.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := r.b.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_exp := r.b.exponent;
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -1130,8 +1165,8 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end case;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when DO_FCFID =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if r.insn(8) = '0' and r.b.negative = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    -- fcfid[s] with negative operand, set R = -B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    opsel_ainv <= '1';
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1150,16 +1185,19 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when DO_FADD =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- fadd[s] and fsub[s]
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_A
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := r.a.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_class := r.a.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_exp := r.a.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FR) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FI) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_a := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_b := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                is_add := r.a.negative xor r.b.negative xor r.insn(1);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if r.a.class = FINITE and r.b.class = FINITE then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.is_subtract := not is_add;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.add_bsmall := r.exp_cmp;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.exp_cmp = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.shift := r.a.exponent - r.b.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.b.negative xnor r.insn(1);
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1169,77 +1207,55 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := ADD_SHIFT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.shift := r.b.exponent - r.a.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_exp := r.b.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := ADD_SHIFT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := ADD_1;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    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';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        invalid := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.a.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- nothing to do, result is A
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.b.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_class := NAN;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.b.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.a.class = NAN or r.b.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := NAN_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.a.class = INFINITY and r.b.class = INFINITY and is_add = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- invalid operation, construct QNaN
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.fpscr(FPSCR_VXISI) := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        qnan_result := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.a.class = ZERO and r.b.class = ZERO and is_add = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- return -0 for rounding to -infinity
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.round_mode(1) and r.round_mode(0);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.a.class = INFINITY or r.b.class = ZERO then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- nothing to do, result is A
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- result is A
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.opsel_a := AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := EXC_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- result is +/- B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.b.negative xnor r.insn(1);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_class := r.b.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_exp := r.b.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.negate := not r.insn(1);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := EXC_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when DO_FMUL =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- fmul[s]
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := r.a.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_A unless C is denorm and A isn't
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := r.a.negative xor r.c.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_class := r.a.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_exp := r.a.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FR) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FI) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_a := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_c := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if r.a.class = FINITE and r.c.class = FINITE then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.result_sign := r.a.negative xor r.c.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.result_exp := r.a.exponent + r.c.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    -- Renormalize denorm operands
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.a.mantissa(54) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := RENORM_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.c.mantissa(54) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := RENORM_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        f_to_multiply.valid <= '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := MULT_1;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if (r.a.class = NAN and r.a.mantissa(53) = '0') or
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        (r.c.class = NAN and r.c.mantissa(53) = '0') then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- Signalling NAN
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.fpscr(FPSCR_VXSNAN) := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        invalid := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.a.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    -- result is A
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.c.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_class := NAN;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.c.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.a.class = NAN or r.c.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := NAN_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif (r.a.class = INFINITY and r.c.class = ZERO) or
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        (r.a.class = ZERO and r.c.class = INFINITY) then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- invalid operation, construct QNaN
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1247,22 +1263,22 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        qnan_result := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.a.class = ZERO or r.a.class = INFINITY then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- result is +/- A
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.a.negative xor r.c.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- r.c.class is ZERO or INFINITY
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_class := r.c.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.a.negative xor r.c.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.opsel_a := AIN_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.negate := r.a.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := EXC_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when DO_FDIV =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := r.a.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_A unless B is denorm and A isn't
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_class := r.a.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_exp := r.a.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FR) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FI) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_a := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_b := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := r.a.negative xor r.b.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_exp := r.a.exponent - r.b.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.count := "00";
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1271,26 +1287,14 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.a.mantissa(54) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := RENORM_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.b.mantissa(54) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := RENORM_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.first := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := DIV_2;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    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';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        invalid := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.a.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- result is A
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.a.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.b.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_class := NAN;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.b.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.a.class = NAN or r.b.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := NAN_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.b.class = INFINITY then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        if r.a.class = INFINITY then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.fpscr(FPSCR_VXIDI) := '1';
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1298,6 +1302,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.result_class := ZERO;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.b.class = ZERO then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        if r.a.class = ZERO then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.fpscr(FPSCR_VXZDZ) := '1';
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1308,46 +1313,36 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.result_class := INFINITY;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    -- else r.b.class = FINITE, result_class = r.a.class
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    else -- r.b.class = FINITE, result_class = r.a.class
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    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;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.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;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.quieten_nan := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.state := EXC_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when DO_FSQRT =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_class := r.b.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := r.b.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FR) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FI) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if r.b.class = NAN and r.b.mantissa(53) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.fpscr(FPSCR_VXSNAN) := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    invalid := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_b := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                case r.b.class is
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when FINITE =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_exp := r.b.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        if r.b.negative = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.fpscr(FPSCR_VXSQRT) := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            qnan_result := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        elsif r.b.mantissa(54) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := RENORM_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        elsif r.b.exponent(0) = '0' then
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1356,7 +1351,9 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.shift := to_signed(1, EXP_BITS);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := RENORM_B2;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when NAN | ZERO =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when NAN =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := NAN_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when ZERO =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- result is B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when INFINITY =>
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1369,15 +1366,12 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end case;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when DO_FRE =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_class := r.b.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := r.b.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FR) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FI) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if r.b.class = NAN and r.b.mantissa(53) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.fpscr(FPSCR_VXSNAN) := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    invalid := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_b := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                case r.b.class is
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when FINITE =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_exp := - r.b.exponent;
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1387,8 +1381,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := FRE_1;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when NAN =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- result is B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := NAN_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when INFINITY =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_class := ZERO;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        arith_done := '1';
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1399,15 +1392,12 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end case;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when DO_FRSQRTE =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_class := r.b.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := r.b.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FR) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FI) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if r.b.class = NAN and r.b.mantissa(53) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.fpscr(FPSCR_VXSNAN) := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    invalid := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_b := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.shift := to_signed(1, EXP_BITS);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                case r.b.class is
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when FINITE =>
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1415,7 +1405,6 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        if r.b.negative = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.fpscr(FPSCR_VXSQRT) := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            qnan_result := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        elsif r.b.mantissa(54) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := RENORM_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        elsif r.b.exponent(0) = '0' then
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1424,8 +1413,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := RENORM_B2;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when NAN =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- result is B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := NAN_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when INFINITY =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        if r.b.negative = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.fpscr(FPSCR_VXSQRT) := '1';
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1442,25 +1430,26 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when DO_FMADD =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- fmadd, fmsub, fnmadd, fnmsub
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_A if A is denorm, else AIN_C if C is denorm,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- else AIN_B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_sign := r.a.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_class := r.a.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_exp := r.a.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FR) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.fpscr(FPSCR_FI) := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_a := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_b := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.use_c := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                is_add := r.a.negative xor r.c.negative xor r.b.negative xor r.insn(1);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if r.a.class = FINITE and r.c.class = FINITE and
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    (r.b.class = FINITE or r.b.class = ZERO) then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.is_subtract := not is_add;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    mulexp := r.a.exponent + r.c.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.result_exp := mulexp;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    -- Make sure A and C are normalized
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.a.mantissa(54) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := RENORM_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.c.mantissa(54) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := RENORM_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.b.class = ZERO then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- no addend, degenerates to multiply
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1483,25 +1472,8 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := FMADD_2;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if (r.a.class = NAN and r.a.mantissa(53) = '0') or
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        (r.b.class = NAN and r.b.mantissa(53) = '0') or
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        (r.c.class = NAN and r.c.mantissa(53) = '0') then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- Signalling NAN
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.fpscr(FPSCR_VXSNAN) := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        invalid := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.a.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- nothing to do, result is A
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.b.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- result is B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_class := NAN;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.b.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif r.c.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- result is C
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_class := NAN;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.c.negative;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.a.class = NAN or r.b.class = NAN or r.c.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := NAN_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    elsif (r.a.class = ZERO and r.c.class = INFINITY) or
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        (r.a.class = INFINITY and r.c.class = ZERO) then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- invalid operation, construct QNaN
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1516,32 +1488,36 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            -- result is infinity
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.result_class := INFINITY;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.result_sign := r.a.negative xor r.c.negative xor r.insn(2);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- Here A is zero, C is zero, or B is infinity
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        -- Result is +/-B in all of those cases
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_class := r.b.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_exp := r.b.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        if v.result_class /= ZERO or is_add = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.result_sign := not (r.b.negative xor r.insn(1) xor r.insn(2));
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        if r.b.class /= ZERO or is_add = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.negate := not (r.insn(1) xor r.insn(2));
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            -- have to be careful about rule for 0 - 0 result sign
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.result_sign := (r.round_mode(1) and r.round_mode(0)) xor r.insn(2);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.negate := r.b.negative xor (r.round_mode(1) and r.round_mode(0)) xor r.insn(2);
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := EXC_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when RENORM_A =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                renormalize := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.state := RENORM_A2;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if r.insn(4) = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.opsel_a := AIN_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when RENORM_A2 =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_C for fmul/fmadd, AIN_B for fdiv
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                set_a := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_exp := new_exp;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if r.insn(4) = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    opsel_a <= AIN_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.c.mantissa(54) = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        if r.insn(3) = '0' or r.b.class = ZERO then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.first := '1';
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1551,18 +1527,18 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            if new_exp + 1 >= r.b.exponent then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                v.madd_cmp := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := DO_FMADD;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := RENORM_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        if r.b.mantissa(54) = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.first := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := DIV_2;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                            v.state := RENORM_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if r.b.mantissa(54) = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.first := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := DIV_2;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.state := RENORM_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1578,6 +1554,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.result_exp := new_exp;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.state := LOOKUP;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when RENORM_C =>
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1595,23 +1572,31 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    if new_exp + 1 >= r.b.exponent then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.madd_cmp := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.state := DO_FMADD;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when ADD_1 =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- transferring B to R
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.shift := r.b.exponent - r.a.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.result_exp := r.b.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.state := ADD_SHIFT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when ADD_SHIFT =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.shift = - exponent difference
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_r <= RES_SHIFT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.x := s_nz;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                set_x := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                longmask := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.state := ADD_2;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when ADD_2 =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if r.add_bsmall = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    opsel_a <= AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.opsel_a := AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.state := ADD_2;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when ADD_2 =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_A if r.add_bsmall = 1 else AIN_B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_b <= BIN_R;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_binv <= r.is_subtract;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                carry_in <= r.is_subtract and not r.x;
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -1655,7 +1640,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when CMP_1 =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_A
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_b <= BIN_R;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_binv <= '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                carry_in <= '1';
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -1696,7 +1681,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when FMADD_2 =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- Product is potentially bigger here
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.shift = addend exp - product exp + 64
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.shift = addend exp - product exp + 64, r.r = r.b.mantissa
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                set_s := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_s <= S_SHIFT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.shift := r.shift - to_signed(64, EXP_BITS);
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -1757,7 +1742,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when LOOKUP =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_a <= AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_B
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- wait one cycle for inverse_table[B] lookup
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.first := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if r.insn(4) = '0' then
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -2260,6 +2245,41 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                opsel_r <= RES_SHIFT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when NAN_RESULT =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if (r.use_a = '1' and r.a.class = NAN and r.a.mantissa(53) = '0') or
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    (r.use_b = '1' and r.b.class = NAN and r.b.mantissa(53) = '0') or
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    (r.use_c = '1' and r.c.class = NAN and r.c.mantissa(53) = '0') then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    -- Signalling NAN
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.fpscr(FPSCR_VXSNAN) := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    invalid := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                if r.use_a = '1' and r.a.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.opsel_a := AIN_A;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                elsif r.use_b = '1' and r.b.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.opsel_a := AIN_B;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                elsif r.use_c = '1' and r.c.class = NAN then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    v.opsel_a := AIN_C;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.state := EXC_RESULT;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when EXC_RESULT =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                -- r.opsel_a = AIN_A, AIN_B or AIN_C according to which input is the result
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                case r.opsel_a is
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when AIN_B =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.b.negative xor r.negate;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_exp := r.b.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_class := r.b.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when AIN_C =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.c.negative xor r.negate;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_exp := r.c.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_class := r.c.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    when others =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_sign := r.a.negative xor r.negate;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_exp := r.a.exponent;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        v.result_class := r.a.class;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                end case;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        end case;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        if zero_divide = '1' then
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -2271,11 +2291,15 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            v.result_sign := '0';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            misc_sel <= "0001";
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            opsel_r <= RES_MISC;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            arith_done := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        if invalid = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            v.invalid := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        if arith_done = '1' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            -- Enabled invalid exception doesn't write result or FPRF
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            -- Neither does enabled zero-divide exception
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            if (invalid and r.fpscr(FPSCR_VE)) = '0' and
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            if (v.invalid and r.fpscr(FPSCR_VE)) = '0' and
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                (zero_divide and r.fpscr(FPSCR_ZE)) = '0' then
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.writing_back := '1';
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                v.update_fprf := '1';
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -2355,7 +2379,7 @@ begin
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        else
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            mask := right_mask(unsigned(mshift(5 downto 0)));
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        end if;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        case opsel_a is
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        case r.opsel_a is
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when AIN_R =>
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                in_a0 := r.r;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            when AIN_A =>