aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Tests/Cpu/Tester
diff options
context:
space:
mode:
authorLDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>2018-04-30 01:39:58 +0200
committergdkchan <gab.dark.100@gmail.com>2018-04-29 20:39:58 -0300
commit7cda630aba8b99b65379c0ef0e92483491e4fbb3 (patch)
tree916bd69e1d296c8ff034df238eab3ca6de7d7ac6 /Ryujinx.Tests/Cpu/Tester
parent071754aaeb1c9113c5818421b7cca1f3c717052a (diff)
Add Sqxtn_S, Sqxtn_V, Uqxtn_S, Uqxtn_V instructions and Tests (6). (#110)
* Update ILGeneratorEx.cs * Update AOpCodeTable.cs * Update AInstEmitSimdArithmetic.cs * Update CpuTestSimd.cs * Update CpuTestSimdReg.cs * Update CpuTest.cs * Update Pseudocode.cs * Update Instructions.cs * Update AInstEmitSimdArithmetic.cs * Update AInstEmitSimdArithmetic.cs * Update AInstEmitSimdArithmetic.cs
Diffstat (limited to 'Ryujinx.Tests/Cpu/Tester')
-rw-r--r--Ryujinx.Tests/Cpu/Tester/Instructions.cs232
-rw-r--r--Ryujinx.Tests/Cpu/Tester/Pseudocode.cs67
2 files changed, 299 insertions, 0 deletions
diff --git a/Ryujinx.Tests/Cpu/Tester/Instructions.cs b/Ryujinx.Tests/Cpu/Tester/Instructions.cs
index 7439aa83..efea80bb 100644
--- a/Ryujinx.Tests/Cpu/Tester/Instructions.cs
+++ b/Ryujinx.Tests/Cpu/Tester/Instructions.cs
@@ -21,6 +21,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -37,6 +38,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -53,6 +55,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -75,6 +78,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
int container_size = 16;
@@ -113,6 +117,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
int container_size = 32;
@@ -187,6 +192,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
Bits imm;
@@ -225,6 +231,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
Bits imm;
@@ -259,6 +266,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
Bits imm;
@@ -288,6 +296,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
Bits imm;
@@ -312,6 +321,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
Bits imm;
@@ -341,6 +351,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
Bits imm;
@@ -370,6 +381,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
Bits imm;
@@ -409,6 +421,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
Bits imm;
@@ -447,6 +460,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -466,6 +480,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -488,6 +503,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if shift == '11' then ReservedValue(); */
@@ -513,6 +529,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if shift == '11' then ReservedValue(); */
@@ -541,6 +558,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if sf == '0' && imm6<5> == '1' then ReservedValue(); */
@@ -564,6 +582,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if sf == '0' && imm6<5> == '1' then ReservedValue(); */
@@ -591,6 +610,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
ShiftType shift_type = DecodeShift(op2);
@@ -610,6 +630,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if sf == '0' && imm6<5> == '1' then ReservedValue(); */
@@ -635,6 +656,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if sf == '0' && imm6<5> == '1' then ReservedValue(); */
@@ -716,6 +738,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if sf == '0' && imm6<5> == '1' then ReservedValue(); */
@@ -741,6 +764,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if sf == '0' && imm6<5> == '1' then ReservedValue(); */
@@ -764,6 +788,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if N != sf then UnallocatedEncoding(); */
@@ -790,6 +815,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
ShiftType shift_type = DecodeShift(op2);
@@ -811,6 +837,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
ShiftType shift_type = DecodeShift(op2);
@@ -830,6 +857,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if sf == '0' && imm6<5> == '1' then ReservedValue(); */
@@ -855,6 +883,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if sf == '0' && imm6<5> == '1' then ReservedValue(); */
@@ -880,6 +909,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
ShiftType shift_type = DecodeShift(op2);
@@ -899,6 +929,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -920,6 +951,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -944,6 +976,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -970,6 +1003,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if shift == '11' then ReservedValue(); */
@@ -997,6 +1031,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* if shift == '11' then ReservedValue(); */
@@ -1027,6 +1062,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -1055,6 +1091,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
ExtendType extend_type = DecodeRegExtend(option);
@@ -1086,6 +1123,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
ExtendType extend_type = DecodeRegExtend(option);
@@ -1113,6 +1151,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
ExtendType extend_type = DecodeRegExtend(option);
@@ -1146,6 +1185,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
ExtendType extend_type = DecodeRegExtend(option);
@@ -1176,6 +1216,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
int R;
@@ -1205,6 +1246,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
int R;
@@ -1238,6 +1280,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
int R;
@@ -1267,6 +1310,7 @@ namespace Ryujinx.Tests.Cpu.Tester
{
/* Decode */
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
Bits flags = nzcv;
@@ -1288,6 +1332,7 @@ namespace Ryujinx.Tests.Cpu.Tester
{
/* Decode */
int n = (int)UInt(Rn);
+
int datasize = (sf ? 64 : 32);
Bits flags = nzcv;
@@ -1314,6 +1359,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
Bits flags = nzcv;
@@ -1336,6 +1382,7 @@ namespace Ryujinx.Tests.Cpu.Tester
/* Decode */
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
Bits flags = nzcv;
@@ -1362,6 +1409,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -1388,6 +1436,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -1414,6 +1463,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -1440,6 +1490,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int d = (int)UInt(Rd);
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -1467,6 +1518,7 @@ namespace Ryujinx.Tests.Cpu.Tester
{
/* Decode */
int d = (int)UInt(Rd);
+
int datasize = (sf ? 64 : 32);
/* if sf == '0' && hw<1> == '1' then UnallocatedEncoding(); */
@@ -1486,6 +1538,7 @@ namespace Ryujinx.Tests.Cpu.Tester
{
/* Decode */
int d = (int)UInt(Rd);
+
int datasize = (sf ? 64 : 32);
/* if sf == '0' && hw<1> == '1' then UnallocatedEncoding(); */
@@ -1506,6 +1559,7 @@ namespace Ryujinx.Tests.Cpu.Tester
{
/* Decode */
int d = (int)UInt(Rd);
+
int datasize = (sf ? 64 : 32);
/* if sf == '0' && hw<1> == '1' then UnallocatedEncoding(); */
@@ -1530,6 +1584,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
int a = (int)UInt(Ra);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -1550,6 +1605,7 @@ namespace Ryujinx.Tests.Cpu.Tester
int n = (int)UInt(Rn);
int m = (int)UInt(Rm);
int a = (int)UInt(Ra);
+
int datasize = (sf ? 64 : 32);
/* Operation */
@@ -1983,6 +2039,182 @@ namespace Ryujinx.Tests.Cpu.Tester
V(d, result);
}
+
+ // https://meriac.github.io/archex/A64_v83A_ISA/sqxtn_advsimd.xml#SQXTN_asisdmisc_N
+ public static void Sqxtn_S(Bits size, Bits Rn, Bits Rd)
+ {
+ bool U = false;
+
+ /* Decode Scalar */
+ int d = (int)UInt(Rd);
+ int n = (int)UInt(Rn);
+
+ /* if size == '11' then ReservedValue(); */
+
+ int esize = 8 << (int)UInt(size);
+ int datasize = esize;
+ int part = 0;
+ int elements = 1;
+
+ bool unsigned = (U == true);
+
+ /* Operation */
+ /* CheckFPAdvSIMDEnabled64(); */
+
+ Bits result = new Bits(datasize);
+ Bits operand = V(2 * datasize, n);
+ Bits element;
+ bool sat;
+
+ for (int e = 0; e <= elements - 1; e++)
+ {
+ element = Elem(operand, e, 2 * esize);
+
+ (Bits _result, bool _sat) = SatQ(Int(element, unsigned), esize, unsigned);
+ Elem(result, e, esize, _result);
+ sat = _sat;
+
+ if (sat)
+ {
+ /* FPSR.QC = '1'; */
+ FPSR[27] = true; // FIXME: Temporary solution.
+ }
+ }
+
+ Vpart(d, part, result);
+ }
+
+ // https://meriac.github.io/archex/A64_v83A_ISA/sqxtn_advsimd.xml#SQXTN_asimdmisc_N
+ public static void Sqxtn_V(bool Q, Bits size, Bits Rn, Bits Rd)
+ {
+ bool U = false;
+
+ /* Decode Vector */
+ int d = (int)UInt(Rd);
+ int n = (int)UInt(Rn);
+
+ /* if size == '11' then ReservedValue(); */
+
+ int esize = 8 << (int)UInt(size);
+ int datasize = 64;
+ int part = (int)UInt(Q);
+ int elements = datasize / esize;
+
+ bool unsigned = (U == true);
+
+ /* Operation */
+ /* CheckFPAdvSIMDEnabled64(); */
+
+ Bits result = new Bits(datasize);
+ Bits operand = V(2 * datasize, n);
+ Bits element;
+ bool sat;
+
+ for (int e = 0; e <= elements - 1; e++)
+ {
+ element = Elem(operand, e, 2 * esize);
+
+ (Bits _result, bool _sat) = SatQ(Int(element, unsigned), esize, unsigned);
+ Elem(result, e, esize, _result);
+ sat = _sat;
+
+ if (sat)
+ {
+ /* FPSR.QC = '1'; */
+ FPSR[27] = true; // FIXME: Temporary solution.
+ }
+ }
+
+ Vpart(d, part, result);
+ }
+
+ // https://meriac.github.io/archex/A64_v83A_ISA/uqxtn_advsimd.xml#UQXTN_asisdmisc_N
+ public static void Uqxtn_S(Bits size, Bits Rn, Bits Rd)
+ {
+ bool U = true;
+
+ /* Decode Scalar */
+ int d = (int)UInt(Rd);
+ int n = (int)UInt(Rn);
+
+ /* if size == '11' then ReservedValue(); */
+
+ int esize = 8 << (int)UInt(size);
+ int datasize = esize;
+ int part = 0;
+ int elements = 1;
+
+ bool unsigned = (U == true);
+
+ /* Operation */
+ /* CheckFPAdvSIMDEnabled64(); */
+
+ Bits result = new Bits(datasize);
+ Bits operand = V(2 * datasize, n);
+ Bits element;
+ bool sat;
+
+ for (int e = 0; e <= elements - 1; e++)
+ {
+ element = Elem(operand, e, 2 * esize);
+
+ (Bits _result, bool _sat) = SatQ(Int(element, unsigned), esize, unsigned);
+ Elem(result, e, esize, _result);
+ sat = _sat;
+
+ if (sat)
+ {
+ /* FPSR.QC = '1'; */
+ FPSR[27] = true; // FIXME: Temporary solution.
+ }
+ }
+
+ Vpart(d, part, result);
+ }
+
+ // https://meriac.github.io/archex/A64_v83A_ISA/uqxtn_advsimd.xml#UQXTN_asimdmisc_N
+ public static void Uqxtn_V(bool Q, Bits size, Bits Rn, Bits Rd)
+ {
+ bool U = true;
+
+ /* Decode Vector */
+ int d = (int)UInt(Rd);
+ int n = (int)UInt(Rn);
+
+ /* if size == '11' then ReservedValue(); */
+
+ int esize = 8 << (int)UInt(size);
+ int datasize = 64;
+ int part = (int)UInt(Q);
+ int elements = datasize / esize;
+
+ bool unsigned = (U == true);
+
+ /* Operation */
+ /* CheckFPAdvSIMDEnabled64(); */
+
+ Bits result = new Bits(datasize);
+ Bits operand = V(2 * datasize, n);
+ Bits element;
+ bool sat;
+
+ for (int e = 0; e <= elements - 1; e++)
+ {
+ element = Elem(operand, e, 2 * esize);
+
+ (Bits _result, bool _sat) = SatQ(Int(element, unsigned), esize, unsigned);
+ Elem(result, e, esize, _result);
+ sat = _sat;
+
+ if (sat)
+ {
+ /* FPSR.QC = '1'; */
+ FPSR[27] = true; // FIXME: Temporary solution.
+ }
+ }
+
+ Vpart(d, part, result);
+ }
#endregion
#region "SimdReg"
diff --git a/Ryujinx.Tests/Cpu/Tester/Pseudocode.cs b/Ryujinx.Tests/Cpu/Tester/Pseudocode.cs
index 72e0bd78..18a1f441 100644
--- a/Ryujinx.Tests/Cpu/Tester/Pseudocode.cs
+++ b/Ryujinx.Tests/Cpu/Tester/Pseudocode.cs
@@ -104,6 +104,8 @@ namespace Ryujinx.Tests.Cpu.Tester
SP_EL0.SetAll(false);
/* SP_EL1 = bits(64) UNKNOWN; */
SP_EL1.SetAll(false);
+
+ FPSR.SetAll(false); // FIXME: Temporary solution.
}
// #impl-aarch64.SP.write.0
@@ -518,6 +520,8 @@ namespace Ryujinx.Tests.Cpu.Tester
SP_EL0 = new Bits(64, false);
SP_EL1 = new Bits(64, false);
+ FPSR = new Bits(32, false); // FIXME: Temporary solution.
+
PSTATE.N = false;
PSTATE.Z = false;
PSTATE.C = false;
@@ -1016,6 +1020,8 @@ namespace Ryujinx.Tests.Cpu.Tester
public static Bits SP_EL0;
public static Bits SP_EL1;
+
+ public static Bits FPSR; // FIXME: Temporary solution.
#endregion
#region "functions/system/"
@@ -1081,6 +1087,7 @@ namespace Ryujinx.Tests.Cpu.Tester
return true; // EL1 and EL0 must exist
}
+ /* return boolean IMPLEMENTATION_DEFINED; */
return false;
}
@@ -1113,5 +1120,65 @@ namespace Ryujinx.Tests.Cpu.Tester
public bool SP; // Stack pointer select: 0=SP0, 1=SPx [AArch64 only]
}
#endregion
+
+#region "functions/vector/"
+ // #impl-shared.SatQ.3
+ public static (Bits, bool) SatQ(BigInteger i, int N, bool unsigned)
+ {
+ (Bits result, bool sat) = (unsigned ? UnsignedSatQ(i, N) : SignedSatQ(i, N));
+
+ return (result, sat);
+ }
+
+ // #impl-shared.SignedSatQ.2
+ public static (Bits, bool) SignedSatQ(BigInteger i, int N)
+ {
+ BigInteger result;
+ bool saturated;
+
+ if (i > BigInteger.Pow(2, N - 1) - 1)
+ {
+ result = BigInteger.Pow(2, N - 1) - 1;
+ saturated = true;
+ }
+ else if (i < -(BigInteger.Pow(2, N - 1)))
+ {
+ result = -(BigInteger.Pow(2, N - 1));
+ saturated = true;
+ }
+ else
+ {
+ result = i;
+ saturated = false;
+ }
+
+ return (result.SubBigInteger(N - 1, 0), saturated);
+ }
+
+ // #impl-shared.UnsignedSatQ.2
+ public static (Bits, bool) UnsignedSatQ(BigInteger i, int N)
+ {
+ BigInteger result;
+ bool saturated;
+
+ if (i > BigInteger.Pow(2, N) - 1)
+ {
+ result = BigInteger.Pow(2, N) - 1;
+ saturated = true;
+ }
+ else if (i < 0)
+ {
+ result = 0;
+ saturated = true;
+ }
+ else
+ {
+ result = i;
+ saturated = false;
+ }
+
+ return (result.SubBigInteger(N - 1, 0), saturated);
+ }
+#endregion
}
}