Пример #1
0
        /// <summary>
        /// Floating-Point Classigy, Double-Precision命令
        /// 浮動小数点レジスタrs1のクラスを示すマスクを整数レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FclassD(Register rd, FPRegister rs1, UInt32 insLength = 4U)
        {
            Binary64 binary1 = reg.GetValue(rs1);
            UInt32   result  = 0U;

            if (IsNegative(binary1) && IsInfinity(binary1))
            {
                // rs1が-∞の場合
                result |= 0b00_0000_0001;
            }
            else if (IsNegative(binary1) && IsNormalNum(binary1))
            {
                // rs1が負の正規数の場合
                result |= 0b00_0000_0010;
            }
            else if (IsNegative(binary1) && IsDenormalNum(binary1))
            {
                // rs1が負の非正規数の場合
                result |= 0b00_0000_0100;
            }
            else if (IsNegative(binary1) && IsZero(binary1))
            {
                // rs1が-0の場合
                result |= 0b00_0000_1000;
            }
            else if (IsPositive(binary1) && IsZero(binary1))
            {
                // rs1が+0の場合
                result |= 0b00_0001_0000;
            }
            else if (IsPositive(binary1) && IsDenormalNum(binary1))
            {
                // rs1が正の非正規数の場合
                result |= 0b00_0010_0000;
            }
            else if (IsPositive(binary1) && IsNormalNum(binary1))
            {
                // rs1が正の正規数の場合
                result |= 0b00_0100_0000;
            }
            else if (IsPositive(binary1) && IsInfinity(binary1))
            {
                // rs1が+∞の場合
                result |= 0b00_1000_0000;
            }
            else if (IsSigNaN(binary1))
            {
                // rs1がシグナル型非数の場合
                result |= 0b01_0000_0000;
            }
            else if (IsQuietNaN(binary1))
            {
                // rs1がクワイエット型非数の場合
                result |= 0b10_0000_0000;
            }

            reg.SetValue(rd, result);
            reg.IncrementPc(insLength);
            return(true);
        }
Пример #2
0
        /// <summary>
        /// Floating-Point Square Root, Double-Precision命令
        /// 浮動小数点レジスタrs1の平方根を浮動小数点レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <param name="rs2">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FsqrtD(FPRegister rd, FPRegister rs1, FloatRoundingMode frm, UInt32 insLength = 4U)
        {
            Binary64 binary1 = reg.GetValue(rs1);
            Binary64 result;
            FloatCSR fcsr = 0;

            result = ToBinary((Double)Math.Sqrt(ToDouble(binary1)));
            result = IsNaN(result) ? NaN : result;

            if (IsSigNaN(binary1))
            {
                // いずれかの数値がシグナリングNaNの場合
                fcsr.NV = true;
            }
            else if (IsNegative(binary1))
            {
                // 負数の平方根を求めようとした場合
                fcsr.NV = true;
            }
            else if (ToDouble(result) * ToDouble(result) != ToDouble(binary1))
            {
                // 結果が一致しない場合
                fcsr.NX = true;
            }
            else if (IsRounded(binary1, result))
            {
                // 桁丸めが発生している場合
                fcsr.NX = true;
            }

            reg.SetValue(rd, result);
            reg.SetFflagsCSR(fcsr);
            reg.IncrementPc(insLength);
            return(true);
        }
Пример #3
0
        /// <summary>
        /// Floating-Point Multiply, Double-Precision命令
        /// 浮動小数点レジスタrs1とrs2の積を浮動小数点レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <param name="rs2">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FmulD(FPRegister rd, FPRegister rs1, FPRegister rs2, FloatRoundingMode frm, UInt32 insLength = 4U)
        {
            Binary64 binary1 = reg.GetValue(rs1);
            Binary64 binary2 = reg.GetValue(rs2);
            Binary64 result;
            FloatCSR fcsr = 0;

            result = ToBinary(ToDouble(binary1) * ToDouble(binary2));
            result = IsNaN(result) ? NaN : result;

            if (IsSigNaN(binary1) || IsSigNaN(binary2))
            {
                // いずれかの数値がシグナリングNaNの場合
                fcsr.NV = true;
            }
            else if (ToDouble(result) != ToDouble(binary1) * ToDouble(binary2))
            {
                // 結果が一致しない場合
                fcsr.NX = true;
            }
            else if (IsRounded(result, binary1) || IsRounded(result, binary2))
            {
                // 桁丸めが発生している場合
                fcsr.NX = true;
            }

            reg.SetValue(rd, result);
            reg.SetFflagsCSR(fcsr);
            reg.IncrementPc(insLength);
            return(true);
        }
Пример #4
0
        /// <summary>
        /// Floating-Point Convert to Single from Double命令
        /// 浮動小数点レジスタrs1の倍精度浮動小数を単精度浮動小数に変換して、浮動小数点レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FcvtSD(FPRegister rd, FPRegister rs1, FloatRoundingMode frm, UInt32 insLength = 4U)
        {
            Binary64 binary1 = reg.GetValue(rs1);
            Binary32 result;
            FloatCSR fcsr = 0;

            Binary32 sign = (Binary32)((binary1 & SignMask) >> 32);

            if (IsInfinity(binary1))
            {
                // +-∞の場合
                result = sign | RV32_SingleFpu.Infinity;
            }
            else if (IsZero(binary1))
            {
                // +-0の場合
                result = sign | RV32_SingleFpu.Zero;
            }
            else if (IsSigNaN(binary1))
            {
                // シグナリングNaNの場合
                fcsr.NV = true;
                result  = RV32_SingleFpu.NaN;
            }
            else if (IsQuietNaN(binary1))
            {
                result = RV32_SingleFpu.NaN;
            }
            else
            {
                result = RV32_SingleFpu.ToBinary((Single)ToDouble(binary1));


                if (RV32_SingleFpu.ToSingle(result) != ToDouble(binary1))
                {
                    // 結果が一致しない場合
                    fcsr.NX = true;
                    if (ToDouble(binary1) > 0)
                    {
                        fcsr.OF = true;
                    }
                    else
                    {
                        fcsr.UF = true;
                    }
                }
            }

            reg.SetValue(rd, result);
            reg.SetFflagsCSR(fcsr);
            reg.IncrementPc(insLength);
            return(true);
        }
Пример #5
0
        /// <summary>
        /// Floating-Point Sign Inject, Double-Precision命令
        /// 浮動小数点レジスタrs1の指数と仮数と、rs2の符号を組み立てて
        /// 浮動小数点レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <param name="rs2">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FsgnjD(FPRegister rd, FPRegister rs1, FPRegister rs2, UInt32 insLength = 4U)
        {
            Binary64 binary1 = reg.GetValue(rs1);
            Binary64 binary2 = reg.GetValue(rs2);
            Binary64 result;

            result = binary1 & 0x7fff_ffffU | binary2 & 0x8000_0000U;

            reg.SetValue(rd, result);
            reg.IncrementPc(insLength);
            return(true);
        }
Пример #6
0
        /// <summary>
        /// Floating-Point Sign Inject, Double-Precision命令
        /// 浮動小数点レジスタrs1の指数と仮数と、rs1の符号とrs2の符号の排他的論理和を組み立てて
        /// 浮動小数点レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <param name="rs2">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FsgnjxD(FPRegister rd, FPRegister rs1, FPRegister rs2, UInt32 insLength = 4U)
        {
            Binary64 binary1 = reg.GetValue(rs1);
            Binary64 binary2 = reg.GetValue(rs2);
            Binary64 result;
            FloatCSR fcsr = 0;

            result = binary1 & 0x7fff_ffffU | (binary1 ^ binary2) & 0x8000_0000U;

            reg.SetValue(rd, result);
            reg.SetFflagsCSR(fcsr);
            reg.IncrementPc(insLength);
            return(true);
        }
Пример #7
0
        /// <summary>
        /// Floating-Point Divide, Double-Precision命令
        /// 浮動小数点レジスタrs1とrs2の商を浮動小数点レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <param name="rs2">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FdivD(FPRegister rd, FPRegister rs1, FPRegister rs2, FloatRoundingMode frm, UInt32 insLength = 4U)
        {
            Binary64 binary1 = reg.GetValue(rs1);
            Binary64 binary2 = reg.GetValue(rs2);
            Binary64 result;
            FloatCSR fcsr = 0;

            if (binary1 == 0f && binary2 == 0f)
            {
                // 被除数、除数ともに0の場合
                result  = NaN;
                fcsr.DZ = true;
            }
            else if (IsZero(binary2))
            {
                // ゼロ除算の場合
                result  = Infinity | ((binary1 & SignMask) ^ (binary2 & SignMask));
                fcsr.DZ = true;
            }
            else
            {
                result = ToBinary(ToDouble(binary1) / ToDouble(binary2));
                result = IsNaN(result) ? NaN : result;

                if (IsSigNaN(binary1) || IsSigNaN(binary2))
                {
                    // いずれかの数値がシグナリングNaNの場合
                    fcsr.NV = true;
                }
                else if (ToDouble(result) != ToDouble(binary1) / ToDouble(binary2))
                {
                    // 結果が一致しない場合
                    fcsr.NX = true;
                }
                else if (IsRounded(result, binary1) || IsRounded(result, binary2))
                {
                    // 桁丸めが発生している場合
                    fcsr.NX = true;
                }
            }

            reg.SetValue(rd, result);
            reg.SetFflagsCSR(fcsr);
            reg.IncrementPc(insLength);
            return(true);
        }
Пример #8
0
        /// <summary>
        /// Floating-Point Less Then or Equal, Double-Precision命令
        /// 浮動小数点レジスタrs1がrs2以下であれば 1 を、そうでなければ 0 を
        /// 整数レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FleD(Register rd, FPRegister rs1, FPRegister rs2, UInt32 insLength = 4U)
        {
            Binary64 binary1 = reg.GetValue(rs1);
            Binary64 binary2 = reg.GetValue(rs2);
            UInt32   result;
            FloatCSR fcsr = 0;

            result = ToDouble(binary1) <= ToDouble(binary2) ? 1U : 0U;

            if (IsNaN(binary1) || IsNaN(binary2))
            {
                fcsr.NV = true;
            }

            reg.SetValue(rd, result);
            reg.SetFflagsCSR(fcsr);
            reg.IncrementPc(insLength);
            return(true);
        }
Пример #9
0
        /// <summary>
        /// Floating-Point Maximum, Double-Precision命令
        /// 浮動小数点レジスタrs1とrs2の大きい方を浮動小数点レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <param name="rs2">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FmaxD(FPRegister rd, FPRegister rs1, FPRegister rs2, UInt32 insLength = 4U)
        {
            Binary64 binary1 = reg.GetValue(rs1);
            Binary64 binary2 = reg.GetValue(rs2);
            Binary64 result;
            FloatCSR fcsr = 0;

            result = ToDouble(binary1) > ToDouble(binary2) ? binary1 : (IsPositive(binary1) && IsZero(binary1) ? binary1 : binary2);
            result = IsNaN(result) ? NaN : result;

            if (IsSigNaN(binary1) || IsSigNaN(binary2))
            {
                fcsr.NV = true;
            }

            reg.SetValue(rd, result);
            reg.SetFflagsCSR(fcsr);
            reg.IncrementPc(insLength);
            return(true);
        }
Пример #10
0
        /// <summary>
        /// Floating-Point Convert to Unsigned Word from Double命令
        /// 浮動小数点レジスタrs1の倍精度浮動小数を整数(符号なし)に変換して、整数レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FcvtWUD(Register rd, FPRegister rs1, FloatRoundingMode frm, UInt32 insLength = 4U)
        {
            Binary64 binary1 = reg.GetValue(rs1);
            UInt32   result;
            FloatCSR fcsr = 0;

            Double value1  = ToDouble(binary1);
            Double rvalue1 = ToDouble(RoundNum(binary1, 0, frm));

            result = (UInt32)rvalue1;

            if ((IsPositive(binary1) && IsInfinity(binary1)) || IsNaN(binary1))
            {
                fcsr.NV = true;
                result  = UInt32.MaxValue;
            }
            else if (IsNegative(binary1) && IsInfinity(binary1))
            {
                fcsr.NV = true;
                result  = UInt32.MinValue;
            }
            else if (UInt32.MaxValue < rvalue1)
            {
                fcsr.NV = true;
                result  = UInt32.MaxValue;
            }
            else if (UInt32.MinValue > rvalue1)
            {
                fcsr.NV = true;
                result  = UInt32.MinValue;
            }
            else if (result != value1)
            {
                fcsr.NX = true;
            }

            reg.SetValue(rd, result);
            reg.SetFflagsCSR(fcsr);
            reg.IncrementPc(insLength);
            return(true);
        }
Пример #11
0
        /// <summary>
        /// Floating-Point Fused Multiply-Subtract, Double-Precision命令
        /// 浮動小数点レジスタrs1とrs2の積からrs3を引いた値を浮動小数点レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <param name="rs2">レジスタ番号</param>
        /// <param name="rs3">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FmsubD(FPRegister rd, FPRegister rs1, FPRegister rs2, FPRegister rs3, FloatRoundingMode frm, UInt32 insLength = 4U)
        {
            Binary64 binary1 = reg.GetValue(rs1);
            Binary64 binary2 = reg.GetValue(rs2);
            Binary64 binary3 = reg.GetValue(rs3);
            Binary64 result;
            FloatCSR fcsr = 0;

            result = ToBinary((ToDouble(binary1) * ToDouble(binary2)) - ToDouble(binary3));
            result = IsNaN(result) ? NaN : result;

            if ((IsInfinity(binary1) || IsInfinity(binary2)) && IsInfinity(binary3) &&
                ((IsNegative(binary1) ^ IsPositive(binary2)) ^ IsPositive(binary3)))
            {
                // ∞ + -∞ もしくは -∞ + ∞の場合
                result  = NaN;
                fcsr.NV = true;
            }
            else if (IsSigNaN(binary1) || IsSigNaN(binary2) || IsSigNaN(binary3))
            {
                // いずれかの数値がシグナリングNaNの場合
                fcsr.NV = true;
            }
            else if (ToDouble(result) != (ToDouble(binary1) * ToDouble(binary2)) - ToDouble(binary3))
            {
                // 結果が一致しない場合
                fcsr.NX = true;
            }
            else if (IsRounded(result, binary1) || IsRounded(result, binary2) || IsRounded(result, binary3))
            {
                // 桁丸めが発生している場合
                fcsr.NX = true;
            }

            reg.SetValue(rd, result);
            reg.SetFflagsCSR(fcsr);
            reg.IncrementPc(insLength);
            return(true);
        }
Пример #12
0
 internal static bool IsNaN(Binary64 binary) => (binary & ExpMask) == 0x7ff0_0000_0000_0000U && (binary & MantMask) > 0U;
Пример #13
0
 internal static bool IsNormalNum(Binary64 binary) => (binary & ExpMask) > 0U && (binary & ExpMask) < 0x7ff0_0000_0000_0000U;
Пример #14
0
 internal static bool IsDenormalNum(Binary64 binary) => (binary & ExpMask) == 0U && !IsZero(binary);
Пример #15
0
 internal static bool IsZero(Binary64 binary) => (binary & (ExpMask | MantMask)) == Zero;