⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 softfloat.c

📁 <Floating Point Unit Core> fpupack.vhd pre_norm_addsub.vhd addsub_28.vhd post_norm_addsub.
💻 C
📖 第 1 页 / 共 5 页
字号:
    int16 aExp, bExp, zExp;
    bits32 aSig, bSig, zSig;
    int16 expDiff;

    aSig = extractFloat32Frac( a );
    aExp = extractFloat32Exp( a );
    bSig = extractFloat32Frac( b );
    bExp = extractFloat32Exp( b );
    expDiff = aExp - bExp;
    aSig <<= 6;
    bSig <<= 6;
    if ( 0 < expDiff ) {
        if ( aExp == 0xFF ) {
            if ( aSig ) return propagateFloat32NaN( a, b );
            return a;
        }
        if ( bExp == 0 ) {
            --expDiff;
        }
        else {
            bSig |= 0x20000000;
        }
        shift32RightJamming( bSig, expDiff, &bSig );
        zExp = aExp;
    }
    else if ( expDiff < 0 ) {
        if ( bExp == 0xFF ) {
            if ( bSig ) return propagateFloat32NaN( a, b );
            return packFloat32( zSign, 0xFF, 0 );
        }
        if ( aExp == 0 ) {
            ++expDiff;
        }
        else {
            aSig |= 0x20000000;
        }
        shift32RightJamming( aSig, - expDiff, &aSig );
        zExp = bExp;
    }
    else {
        if ( aExp == 0xFF ) {
            if ( aSig | bSig ) return propagateFloat32NaN( a, b );
            return a;
        }
        if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
        zSig = 0x40000000 + aSig + bSig;
        zExp = aExp;
        goto roundAndPack;
    }
    aSig |= 0x20000000;
    zSig = ( aSig + bSig )<<1;
    --zExp;
    if ( (sbits32) zSig < 0 ) {
        zSig = aSig + bSig;
        ++zExp;
    }
 roundAndPack:
    return roundAndPackFloat32( zSign, zExp, zSig );

}

/*----------------------------------------------------------------------------
| Returns the result of subtracting the absolute values of the single-
| precision floating-point values `a' and `b'.  If `zSign' is 1, the
| difference is negated before being returned.  `zSign' is ignored if the
| result is a NaN.  The subtraction is performed according to the IEC/IEEE
| Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/

static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
{
    int16 aExp, bExp, zExp;
    bits32 aSig, bSig, zSig;
    int16 expDiff;

    aSig = extractFloat32Frac( a );
    aExp = extractFloat32Exp( a );
    bSig = extractFloat32Frac( b );
    bExp = extractFloat32Exp( b );
    expDiff = aExp - bExp;
    aSig <<= 7;
    bSig <<= 7;
    if ( 0 < expDiff ) goto aExpBigger;
    if ( expDiff < 0 ) goto bExpBigger;
    if ( aExp == 0xFF ) {
        if ( aSig | bSig ) return propagateFloat32NaN( a, b );
        float_raise( float_flag_invalid );
        return float32_default_nan;
    }
    if ( aExp == 0 ) {
        aExp = 1;
        bExp = 1;
    }
    if ( bSig < aSig ) goto aBigger;
    if ( aSig < bSig ) goto bBigger;
    return packFloat32( float_rounding_mode == float_round_down, 0, 0 );
 bExpBigger:
    if ( bExp == 0xFF ) {
        if ( bSig ) return propagateFloat32NaN( a, b );
        return packFloat32( zSign ^ 1, 0xFF, 0 );
    }
    if ( aExp == 0 ) {
        ++expDiff;
    }
    else {
        aSig |= 0x40000000;
    }
    shift32RightJamming( aSig, - expDiff, &aSig );
    bSig |= 0x40000000;
 bBigger:
    zSig = bSig - aSig;
    zExp = bExp;
    zSign ^= 1;
    goto normalizeRoundAndPack;
 aExpBigger:
    if ( aExp == 0xFF ) {
        if ( aSig ) return propagateFloat32NaN( a, b );
        return a;
    }
    if ( bExp == 0 ) {
        --expDiff;
    }
    else {
        bSig |= 0x40000000;
    }
    shift32RightJamming( bSig, expDiff, &bSig );
    aSig |= 0x40000000;
 aBigger:
    zSig = aSig - bSig;
    zExp = aExp;
 normalizeRoundAndPack:
    --zExp;
    return normalizeRoundAndPackFloat32( zSign, zExp, zSig );

}

/*----------------------------------------------------------------------------
| Returns the result of adding the single-precision floating-point values `a'
| and `b'.  The operation is performed according to the IEC/IEEE Standard for
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
/*
        -- fpu operations (fpu_op_i):		-- ========================		-- 000 = add, 		-- 001 = substract, 		-- 010 = multiply, 		-- 011 = divide,		-- 100 = square root		-- 101 = unused		-- 110 = unused		-- 111 = unused		        -- Rounding Mode:         -- ==============        -- 00 = round to nearest even(default),         -- 01 = round to zero,         -- 10 = round up,         -- 11 = round down

*/
void print_roundmode(void)
{
		if (float_rounding_mode==float_round_nearest_even) printf("00");	 else
		if (float_rounding_mode==float_round_to_zero) printf("01");	else
		if (float_rounding_mode==float_round_up) printf("10");	else
		if (float_rounding_mode==float_round_down) printf("11");	

}

				
float32 float32_add2( float32 a, float32 b )
{
    flag aSign, bSign;

    aSign = extractFloat32Sign( a );
    bSign = extractFloat32Sign( b );
    if ( aSign == bSign ) {
        return addFloat32Sigs( a, b, aSign );
    }
    else {
        return subFloat32Sigs( a, b, aSign );
    }

}

// for FPU testbench
float32 float32_add( float32 a, float32 b )
{
	float32 output = float32_add2( a, b );
		/*//This can be used for copy&paste test mode
		printf("\t\t\twait for CLK_PERIOD; start_i <= '1';\n");
		printf("\t\t\topa_i <= X\"%x\";\n",a);
		printf("\t\t\topb_i <= X\"%x\";\n",b);
		printf("\t\t\tfpu_op_i <= \"000\";\n");
		printf("\t\t\trmode_i <= \""); print_roundmode(); printf("\";\n");
		printf("\t\t\twait for CLK_PERIOD; start_i <= '0'; wait until ready_o='1';\n");
		printf("\t\t\tassert output_o=x\"%x\"\n" ,output);
		//for exceptions, but didn't work!!
		//printf("\t\t\tassert output_o=x\"%x\" and ine_o='%d' and overflow_o='%d' and underflow_o='%d' and div_zero_o='%d' and qnan_o='%d' \n" ,output,exceptions.ine ,exceptions.overflow, exceptions.underflow, exceptions.div_zero, exceptions.invalid);
		printf("\t\t\treport \"Error!!!\"\n");
		printf("\t\t\tseverity failure;\n\n");*/
		

		printf("%x       \n",a);
		printf("%x       \n",b);
		printf("000\n");
		print_roundmode(); printf("\n");
		printf("%x       \n\n", output);
		
	return output;
}

/*----------------------------------------------------------------------------
| Returns the result of subtracting the single-precision floating-point values
| `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
| for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/

float32 float32_sub2( float32 a, float32 b )
{
    flag aSign, bSign;

    aSign = extractFloat32Sign( a );
    bSign = extractFloat32Sign( b );
    if ( aSign == bSign ) {
        return subFloat32Sigs( a, b, aSign );
    }
    else {
        return addFloat32Sigs( a, b, aSign );
    }

}
// for FPU testbench
float32 float32_sub( float32 a, float32 b )
{
	float32 output = float32_sub2( a, b );
		/*printf("\t\t\twait for CLK_PERIOD; start_i <= '1';\n");
		printf("\t\t\topa_i <= X\"%x\";\n",a);
		printf("\t\t\topb_i <= X\"%x\";\n",b);
		printf("\t\t\tfpu_op_i <= \"001\";\n");
		printf("\t\t\trmode_i <= \""); print_roundmode(); printf("\";\n");
		printf("\t\t\twait for CLK_PERIOD; start_i <= '0'; wait until ready_o='1';\n");
		printf("\t\t\tassert output_o=x\"%x\"\n" ,output);
		printf("\t\t\treport \"Error!!!\"\n");
		printf("\t\t\tseverity failure;\n\n");*/
		
		printf("%x       \n",a);
		printf("%x       \n",b);
		printf("001\n");
		print_roundmode(); printf("\n");
		printf("%x       \n\n", output);
		
	return output;
}

/*----------------------------------------------------------------------------
| Returns the result of multiplying the single-precision floating-point values
| `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
| for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/

float32 float32_mul2( float32 a, float32 b )
{
    flag aSign, bSign, zSign;
    int16 aExp, bExp, zExp;
    bits32 aSig, bSig, zSig0, zSig1;

    aSig = extractFloat32Frac( a );
    aExp = extractFloat32Exp( a );
    aSign = extractFloat32Sign( a );
    bSig = extractFloat32Frac( b );
    bExp = extractFloat32Exp( b );
    bSign = extractFloat32Sign( b );
    zSign = aSign ^ bSign;
    if ( aExp == 0xFF ) {
        if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
            return propagateFloat32NaN( a, b );
        }
        if ( ( bExp | bSig ) == 0 ) {
            float_raise( float_flag_invalid );
            return float32_default_nan;
        }
        return packFloat32( zSign, 0xFF, 0 );
    }
    if ( bExp == 0xFF ) {
        if ( bSig ) return propagateFloat32NaN( a, b );
        if ( ( aExp | aSig ) == 0 ) {
            float_raise( float_flag_invalid );
            return float32_default_nan;
        }
        return packFloat32( zSign, 0xFF, 0 );
    }
    if ( aExp == 0 ) {
        if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
        normalizeFloat32Subnormal( aSig, &aExp, &aSig );
    }
    if ( bExp == 0 ) {
        if ( bSig == 0 ) return packFloat32( zSign, 0, 0 );
        normalizeFloat32Subnormal( bSig, &bExp, &bSig );
    }
    zExp = aExp + bExp - 0x7F;
    aSig = ( aSig | 0x00800000 )<<7;
    bSig = ( bSig | 0x00800000 )<<8;
    mul32To64( aSig, bSig, &zSig0, &zSig1 );
    zSig0 |= ( zSig1 != 0 );
    if ( 0 <= (sbits32) ( zSig0<<1 ) ) {
        zSig0 <<= 1;
        --zExp;
    }
    return roundAndPackFloat32( zSign, zExp, zSig0 );
}
// for FPU testbench
float32 float32_mul( float32 a, float32 b )
{
	float32 output = float32_mul2( a, b );
		/*printf("\t\t\twait for CLK_PERIOD; start_i <= '1';\n");
		printf("\t\t\topa_i <= X\"%x\";\n",a);
		printf("\t\t\topb_i <= X\"%x\";\n",b);
		printf("\t\t\tfpu_op_i <= \"010\";\n");
		printf("\t\t\trmode_i <= \""); print_roundmode(); printf("\";\n");
		printf("\t\t\twait for CLK_PERIOD; start_i <= '0'; wait until ready_o='1';\n");
		printf("\t\t\tassert output_o=x\"%x\"\n" ,output);
		printf("\t\t\treport \"Error!!!\"\n");
		printf("\t\t\tseverity failure;\n\n");*/
		
		printf("%x       \n",a);
		printf("%x       \n",b);
		printf("010\n");
		print_roundmode(); printf("\n");
		printf("%x       \n\n", output);
	return output;
}

/*----------------------------------------------------------------------------
| Returns the result of dividing the single-precision floating-point value `a'
| by the corresponding value `b'.  The operation is performed according to the
| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/


float32 float32_div2( float32 a, float32 b )
{
    flag aSign, bSign, zSign;
    int16 aExp, bExp, zExp;
    bits32 aSig, bSig, zSig, rem0, rem1, term0, term1;

    aSig = extractFloat32Frac( a );
    aExp = extractFloat32Exp( a );
    aSign = extractFloat32Sign( a );
    bSig = extractFloat32Frac( b );
    bExp = extractFloat32Exp( b );
    bSign = extractFloat32Sign( b );
    zSign = aSign ^ bSign;
    if ( aExp == 0xFF ) {
        if ( aSig ) return propagateFloat32NaN( a, b );
        if ( bExp == 0xFF ) {
            if ( bSig ) return propagateFloat32NaN( a, b );
            float_raise( float_flag_invalid );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -