Example #1
0
        /// <summary>
        /// Floating-Point Classigy, Single-Precision命令
        /// 浮動小数点レジスタrs1のクラスを示すマスクを整数レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FclassS(Register rd, FPRegister rs1, UInt32 insLength = 4U)
        {
            Binary32 binary1 = (Binary32)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);
        }
Example #2
0
        /// <summary>
        /// Floating-Point Square Root, Single-Precision命令
        /// 浮動小数点レジスタrs1の平方根を浮動小数点レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <param name="rs2">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FsqrtS(FPRegister rd, FPRegister rs1, FloatRoundingMode frm, UInt32 insLength = 4U)
        {
            Binary32 binary1 = (Binary32)reg.GetValue(rs1);
            Binary32 result;
            FloatCSR fcsr = 0;

            result = ToBinary((Single)Math.Sqrt(ToSingle(binary1)));
            result = IsNaN(result) ? NaN : result;

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

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

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

            if (IsSigNaN(binary1) || IsSigNaN(binary2))
            {
                // いずれかの数値がシグナリングNaNの場合
                fcsr.NV = true;
            }
            else if (ToSingle(result) != ToSingle(binary1) * ToSingle(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);
        }
Example #4
0
        /// <summary>
        /// Floating-Point Move to Integer from Word命令
        /// 浮動小数点レジスタrs1を整数レジスタrd(符号付き)に書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FmvXW(Register rd, FPRegister rs1, UInt32 insLength = 4U)
        {
            Binary32 binary1 = (Binary32)reg.GetValue(rs1);
            UInt32   result;

            result = binary1;

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

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

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

            result = ToBinary((Double)RV32_SingleFpu.ToSingle(binary1));

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

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

            reg.SetValue(rd, result);
            reg.SetFflagsCSR(fcsr);
            reg.IncrementPc(insLength);
            return(true);
        }
Example #9
0
        /// <summary>
        /// Floating-Point Divide, Single-Precision命令
        /// 浮動小数点レジスタrs1とrs2の商を浮動小数点レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <param name="rs2">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FdivS(FPRegister rd, FPRegister rs1, FPRegister rs2, FloatRoundingMode frm, UInt32 insLength = 4U)
        {
            Binary32 binary1 = (Binary32)reg.GetValue(rs1);
            Binary32 binary2 = (Binary32)reg.GetValue(rs2);
            Binary32 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(ToSingle(binary1) / ToSingle(binary2));
                result = IsNaN(result) ? NaN : result;

                if (IsSigNaN(binary1) || IsSigNaN(binary2))
                {
                    // いずれかの数値がシグナリングNaNの場合
                    fcsr.NV = true;
                }
                else if (ToSingle(result) != ToSingle(binary1) / ToSingle(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);
        }
Example #10
0
        /// <summary>
        /// Floating-Point Less Then or Equal, Single-Precision命令
        /// 浮動小数点レジスタrs1がrs2以下であれば 1 を、そうでなければ 0 を
        /// 整数レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FleS(Register rd, FPRegister rs1, FPRegister rs2, UInt32 insLength = 4U)
        {
            Binary32 binary1 = (Binary32)reg.GetValue(rs1);
            Binary32 binary2 = (Binary32)reg.GetValue(rs2);
            UInt32   result;
            FloatCSR fcsr = 0;

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

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

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

            result = ToSingle(binary1) > ToSingle(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);
        }
Example #12
0
        /// <summary>
        /// Floating-Point Convert to Unsigned Word from Single命令
        /// 浮動小数点レジスタrs1の単精度浮動小数を整数(符号なし)に変換して、整数レジスタrdに書き込む
        /// </summary>
        /// <param name="rd">結果を格納するレジスタ番号</param>
        /// <param name="rs1">レジスタ番号</param>
        /// <returns>処理の成否</returns>
        public bool FcvtWUS(Register rd, FPRegister rs1, FloatRoundingMode frm, UInt32 insLength = 4U)
        {
            Binary32 binary1 = (Binary32)reg.GetValue(rs1);
            Single   value1  = ToSingle(binary1);
            Single   rvalue1 = ToSingle(RoundNum(binary1, 0, frm));
            UInt32   result;
            FloatCSR fcsr = 0;

            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);
        }
Example #13
0
        /// <summary>
        /// Floating-Point Fused Multiply-Subtract, Single-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 FmsubS(FPRegister rd, FPRegister rs1, FPRegister rs2, FPRegister rs3, FloatRoundingMode frm, UInt32 insLength = 4U)
        {
            Binary32 binary1 = (Binary32)reg.GetValue(rs1);
            Binary32 binary2 = (Binary32)reg.GetValue(rs2);
            Binary32 binary3 = (Binary32)reg.GetValue(rs3);
            Binary32 result;
            FloatCSR fcsr = 0;

            result = ToBinary((ToSingle(binary1) * ToSingle(binary2)) - ToSingle(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 (ToSingle(result) != (ToSingle(binary1) * ToSingle(binary2)) - ToSingle(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);
        }
Example #14
0
 internal static bool IsNaN(Binary32 binary) => (binary & ExpMask) == 0x7f80_0000U && (binary & MantMask) > 0U;
Example #15
0
 internal static bool IsNormalNum(Binary32 binary) => (binary & ExpMask) > 0U && (binary & ExpMask) < 0x7f80_0000U;
Example #16
0
 internal static bool IsDenormalNum(Binary32 binary) => (binary & ExpMask) == 0U && !IsZero(binary);
Example #17
0
 internal static bool IsZero(Binary32 binary) => (binary & (ExpMask | MantMask)) == Zero;