From 5f34353dce716bca2e3fc1c7e82be6276b95d61a Mon Sep 17 00:00:00 2001 From: LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> Date: Sat, 4 Aug 2018 21:58:54 +0200 Subject: Add SQADD, UQADD, SQSUB, UQSUB, SUQADD, USQADD, SQABS, SQNEG (Scalar, Vector) instructions; add 24 Tests. Most saturation instructions now on ASoftFallback. (#314) * Update AOpCodeTable.cs * Update AInstEmitSimdHelper.cs * Update AInstEmitSimdArithmetic.cs * Update Pseudocode.cs * Update Instructions.cs * Update CpuTestSimd.cs * Update CpuTestSimdReg.cs * Update AInstEmitSimdHelper.cs * Update AInstEmitSimdHelper.cs * Update AInstEmitSimdHelper.cs * Update AInstEmitSimdHelper.cs * Update ASoftFallback.cs * Update AInstEmitSimdHelper.cs * Update ASoftFallback.cs * Update AInstEmitSimdHelper.cs * Update CpuTestSimd.cs * Update CpuTestSimdReg.cs * Update ASoftFallback.cs * Update AInstEmitSimdHelper.cs * Opt. (retest). --- Ryujinx.Tests/Cpu/Tester/Instructions.cs | 944 ++++++++++++++++++++++++++++--- Ryujinx.Tests/Cpu/Tester/Pseudocode.cs | 4 +- 2 files changed, 862 insertions(+), 86 deletions(-) (limited to 'Ryujinx.Tests/Cpu/Tester') diff --git a/Ryujinx.Tests/Cpu/Tester/Instructions.cs b/Ryujinx.Tests/Cpu/Tester/Instructions.cs index 2f52dcbf..8b1b010f 100644 --- a/Ryujinx.Tests/Cpu/Tester/Instructions.cs +++ b/Ryujinx.Tests/Cpu/Tester/Instructions.cs @@ -3060,6 +3060,210 @@ namespace Ryujinx.Tests.Cpu.Tester V(d, result); } + // sqabs_advsimd.html#SQABS_asisdmisc_R + public static void Sqabs_S(Bits size, Bits Rn, Bits Rd) + { + const bool U = false; + + /* Decode Scalar */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + + int esize = 8 << (int)UInt(size); + int datasize = esize; + int elements = 1; + + bool neg = (U == true); + + /* Operation */ + /* CheckFPAdvSIMDEnabled64(); */ + + Bits result = new Bits(datasize); + Bits operand = V(datasize, n); + BigInteger element; + bool sat; + + for (int e = 0; e <= elements - 1; e++) + { + element = SInt(Elem(operand, e, esize)); + + if (neg) + { + element = -element; + } + else + { + element = Abs(element); + } + + (Bits _result, bool _sat) = SignedSatQ(element, esize); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } + } + + V(d, result); + } + + // sqabs_advsimd.html#SQABS_asimdmisc_R + public static void Sqabs_V(bool Q, Bits size, Bits Rn, Bits Rd) + { + const bool U = false; + + /* Decode Vector */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + + /* if size:Q == '110' then ReservedValue(); */ + + int esize = 8 << (int)UInt(size); + int datasize = (Q ? 128 : 64); + int elements = datasize / esize; + + bool neg = (U == true); + + /* Operation */ + /* CheckFPAdvSIMDEnabled64(); */ + + Bits result = new Bits(datasize); + Bits operand = V(datasize, n); + BigInteger element; + bool sat; + + for (int e = 0; e <= elements - 1; e++) + { + element = SInt(Elem(operand, e, esize)); + + if (neg) + { + element = -element; + } + else + { + element = Abs(element); + } + + (Bits _result, bool _sat) = SignedSatQ(element, esize); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } + } + + V(d, result); + } + + // sqneg_advsimd.html#SQNEG_asisdmisc_R + public static void Sqneg_S(Bits size, Bits Rn, Bits Rd) + { + const bool U = true; + + /* Decode Scalar */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + + int esize = 8 << (int)UInt(size); + int datasize = esize; + int elements = 1; + + bool neg = (U == true); + + /* Operation */ + /* CheckFPAdvSIMDEnabled64(); */ + + Bits result = new Bits(datasize); + Bits operand = V(datasize, n); + BigInteger element; + bool sat; + + for (int e = 0; e <= elements - 1; e++) + { + element = SInt(Elem(operand, e, esize)); + + if (neg) + { + element = -element; + } + else + { + element = Abs(element); + } + + (Bits _result, bool _sat) = SignedSatQ(element, esize); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } + } + + V(d, result); + } + + // sqneg_advsimd.html#SQNEG_asimdmisc_R + public static void Sqneg_V(bool Q, Bits size, Bits Rn, Bits Rd) + { + const bool U = true; + + /* Decode Vector */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + + /* if size:Q == '110' then ReservedValue(); */ + + int esize = 8 << (int)UInt(size); + int datasize = (Q ? 128 : 64); + int elements = datasize / esize; + + bool neg = (U == true); + + /* Operation */ + /* CheckFPAdvSIMDEnabled64(); */ + + Bits result = new Bits(datasize); + Bits operand = V(datasize, n); + BigInteger element; + bool sat; + + for (int e = 0; e <= elements - 1; e++) + { + element = SInt(Elem(operand, e, esize)); + + if (neg) + { + element = -element; + } + else + { + element = Abs(element); + } + + (Bits _result, bool _sat) = SignedSatQ(element, esize); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } + } + + V(d, result); + } + // sqxtn_advsimd.html#SQXTN_asisdmisc_N public static void Sqxtn_S(Bits size, Bits Rn, Bits Rd) { @@ -3069,11 +3273,176 @@ namespace Ryujinx.Tests.Cpu.Tester int d = (int)UInt(Rd); int n = (int)UInt(Rn); - /* if size == '11' then ReservedValue(); */ - + /* 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; // TODO: Add named fields. + } + } + + Vpart(d, part, result); + } + + // sqxtn_advsimd.html#SQXTN_asimdmisc_N + public static void Sqxtn_V(bool Q, Bits size, Bits Rn, Bits Rd) + { + const 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; // TODO: Add named fields. + } + } + + Vpart(d, part, result); + } + + // sqxtun_advsimd.html#SQXTUN_asisdmisc_N + public static void Sqxtun_S(Bits size, Bits Rn, Bits Rd) + { + /* 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; + + /* 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) = UnsignedSatQ(SInt(element), esize); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } + } + + Vpart(d, part, result); + } + + // sqxtun_advsimd.html#SQXTUN_asimdmisc_N + public static void Sqxtun_V(bool Q, Bits size, Bits Rn, Bits Rd) + { + /* 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; + + /* 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) = UnsignedSatQ(SInt(element), esize); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } + } + + Vpart(d, part, result); + } + + // suqadd_advsimd.html#SUQADD_asisdmisc_R + public static void Suqadd_S(Bits size, Bits Rn, Bits Rd) + { + const bool U = false; + + /* Decode Scalar */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + int esize = 8 << (int)UInt(size); int datasize = esize; - int part = 0; int elements = 1; bool unsigned = (U == true); @@ -3082,15 +3451,18 @@ namespace Ryujinx.Tests.Cpu.Tester /* CheckFPAdvSIMDEnabled64(); */ Bits result = new Bits(datasize); - Bits operand = V(2 * datasize, n); - Bits element; + Bits operand = V(datasize, n); + Bits operand2 = V(datasize, d); + BigInteger op1; + BigInteger op2; bool sat; for (int e = 0; e <= elements - 1; e++) { - element = Elem(operand, e, 2 * esize); + op1 = Int(Elem(operand, e, esize), !unsigned); + op2 = Int(Elem(operand2, e, esize), unsigned); - (Bits _result, bool _sat) = SatQ(Int(element, unsigned), esize, unsigned); + (Bits _result, bool _sat) = SatQ(op1 + op2, esize, unsigned); Elem(result, e, esize, _result); sat = _sat; @@ -3101,11 +3473,11 @@ namespace Ryujinx.Tests.Cpu.Tester } } - Vpart(d, part, result); + V(d, result); } - // sqxtn_advsimd.html#SQXTN_asimdmisc_N - public static void Sqxtn_V(bool Q, Bits size, Bits Rn, Bits Rd) + // suqadd_advsimd.html#SUQADD_asimdmisc_R + public static void Suqadd_V(bool Q, Bits size, Bits Rn, Bits Rd) { const bool U = false; @@ -3113,11 +3485,10 @@ namespace Ryujinx.Tests.Cpu.Tester int d = (int)UInt(Rd); int n = (int)UInt(Rn); - /* if size == '11' then ReservedValue(); */ + /* if size:Q == '110' then ReservedValue(); */ int esize = 8 << (int)UInt(size); - int datasize = 64; - int part = (int)UInt(Q); + int datasize = (Q ? 128 : 64); int elements = datasize / esize; bool unsigned = (U == true); @@ -3126,15 +3497,18 @@ namespace Ryujinx.Tests.Cpu.Tester /* CheckFPAdvSIMDEnabled64(); */ Bits result = new Bits(datasize); - Bits operand = V(2 * datasize, n); - Bits element; + Bits operand = V(datasize, n); + Bits operand2 = V(datasize, d); + BigInteger op1; + BigInteger op2; bool sat; for (int e = 0; e <= elements - 1; e++) { - element = Elem(operand, e, 2 * esize); + op1 = Int(Elem(operand, e, esize), !unsigned); + op2 = Int(Elem(operand2, e, esize), unsigned); - (Bits _result, bool _sat) = SatQ(Int(element, unsigned), esize, unsigned); + (Bits _result, bool _sat) = SatQ(op1 + op2, esize, unsigned); Elem(result, e, esize, _result); sat = _sat; @@ -3145,12 +3519,14 @@ namespace Ryujinx.Tests.Cpu.Tester } } - Vpart(d, part, result); + V(d, result); } - // sqxtun_advsimd.html#SQXTUN_asisdmisc_N - public static void Sqxtun_S(Bits size, Bits Rn, Bits Rd) + // uqxtn_advsimd.html#UQXTN_asisdmisc_N + public static void Uqxtn_S(Bits size, Bits Rn, Bits Rd) { + const bool U = true; + /* Decode Scalar */ int d = (int)UInt(Rd); int n = (int)UInt(Rn); @@ -3162,6 +3538,8 @@ namespace Ryujinx.Tests.Cpu.Tester int part = 0; int elements = 1; + bool unsigned = (U == true); + /* Operation */ /* CheckFPAdvSIMDEnabled64(); */ @@ -3174,7 +3552,7 @@ namespace Ryujinx.Tests.Cpu.Tester { element = Elem(operand, e, 2 * esize); - (Bits _result, bool _sat) = UnsignedSatQ(SInt(element), esize); + (Bits _result, bool _sat) = SatQ(Int(element, unsigned), esize, unsigned); Elem(result, e, esize, _result); sat = _sat; @@ -3188,9 +3566,11 @@ namespace Ryujinx.Tests.Cpu.Tester Vpart(d, part, result); } - // sqxtun_advsimd.html#SQXTUN_asimdmisc_N - public static void Sqxtun_V(bool Q, Bits size, Bits Rn, Bits Rd) + // uqxtn_advsimd.html#UQXTN_asimdmisc_N + public static void Uqxtn_V(bool Q, Bits size, Bits Rn, Bits Rd) { + const bool U = true; + /* Decode Vector */ int d = (int)UInt(Rd); int n = (int)UInt(Rn); @@ -3202,6 +3582,8 @@ namespace Ryujinx.Tests.Cpu.Tester int part = (int)UInt(Q); int elements = datasize / esize; + bool unsigned = (U == true); + /* Operation */ /* CheckFPAdvSIMDEnabled64(); */ @@ -3214,7 +3596,7 @@ namespace Ryujinx.Tests.Cpu.Tester { element = Elem(operand, e, 2 * esize); - (Bits _result, bool _sat) = UnsignedSatQ(SInt(element), esize); + (Bits _result, bool _sat) = SatQ(Int(element, unsigned), esize, unsigned); Elem(result, e, esize, _result); sat = _sat; @@ -3228,8 +3610,8 @@ namespace Ryujinx.Tests.Cpu.Tester Vpart(d, part, result); } - // uqxtn_advsimd.html#UQXTN_asisdmisc_N - public static void Uqxtn_S(Bits size, Bits Rn, Bits Rd) + // usqadd_advsimd.html#USQADD_asisdmisc_R + public static void Usqadd_S(Bits size, Bits Rn, Bits Rd) { const bool U = true; @@ -3237,11 +3619,8 @@ namespace Ryujinx.Tests.Cpu.Tester 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); @@ -3250,15 +3629,18 @@ namespace Ryujinx.Tests.Cpu.Tester /* CheckFPAdvSIMDEnabled64(); */ Bits result = new Bits(datasize); - Bits operand = V(2 * datasize, n); - Bits element; + Bits operand = V(datasize, n); + Bits operand2 = V(datasize, d); + BigInteger op1; + BigInteger op2; bool sat; for (int e = 0; e <= elements - 1; e++) { - element = Elem(operand, e, 2 * esize); + op1 = Int(Elem(operand, e, esize), !unsigned); + op2 = Int(Elem(operand2, e, esize), unsigned); - (Bits _result, bool _sat) = SatQ(Int(element, unsigned), esize, unsigned); + (Bits _result, bool _sat) = SatQ(op1 + op2, esize, unsigned); Elem(result, e, esize, _result); sat = _sat; @@ -3269,11 +3651,11 @@ namespace Ryujinx.Tests.Cpu.Tester } } - Vpart(d, part, result); + V(d, result); } - // uqxtn_advsimd.html#UQXTN_asimdmisc_N - public static void Uqxtn_V(bool Q, Bits size, Bits Rn, Bits Rd) + // usqadd_advsimd.html#USQADD_asimdmisc_R + public static void Usqadd_V(bool Q, Bits size, Bits Rn, Bits Rd) { const bool U = true; @@ -3281,11 +3663,10 @@ namespace Ryujinx.Tests.Cpu.Tester int d = (int)UInt(Rd); int n = (int)UInt(Rn); - /* if size == '11' then ReservedValue(); */ + /* if size:Q == '110' then ReservedValue(); */ int esize = 8 << (int)UInt(size); - int datasize = 64; - int part = (int)UInt(Q); + int datasize = (Q ? 128 : 64); int elements = datasize / esize; bool unsigned = (U == true); @@ -3294,15 +3675,18 @@ namespace Ryujinx.Tests.Cpu.Tester /* CheckFPAdvSIMDEnabled64(); */ Bits result = new Bits(datasize); - Bits operand = V(2 * datasize, n); - Bits element; + Bits operand = V(datasize, n); + Bits operand2 = V(datasize, d); + BigInteger op1; + BigInteger op2; bool sat; for (int e = 0; e <= elements - 1; e++) { - element = Elem(operand, e, 2 * esize); + op1 = Int(Elem(operand, e, esize), !unsigned); + op2 = Int(Elem(operand2, e, esize), unsigned); - (Bits _result, bool _sat) = SatQ(Int(element, unsigned), esize, unsigned); + (Bits _result, bool _sat) = SatQ(op1 + op2, esize, unsigned); Elem(result, e, esize, _result); sat = _sat; @@ -3313,7 +3697,7 @@ namespace Ryujinx.Tests.Cpu.Tester } } - Vpart(d, part, result); + V(d, result); } // xtn_advsimd.html @@ -4489,105 +4873,301 @@ namespace Ryujinx.Tests.Cpu.Tester element1 = Int(Elem(operand1, e, esize), unsigned); element2 = Int(Elem(operand2, e, esize), unsigned); - absdiff = Abs(element1 - element2).SubBigInteger(esize - 1, 0); + absdiff = Abs(element1 - element2).SubBigInteger(esize - 1, 0); + + Elem(result, e, esize, Elem(result, e, esize) + absdiff); + } + + V(d, result); + } + + // sabdl_advsimd.html + public static void Sabdl_V(bool Q, Bits size, Bits Rm, Bits Rn, Bits Rd) + { + const bool U = false; + const bool op = true; + + /* Decode */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + int m = (int)UInt(Rm); + + /* if size == '11' then ReservedValue(); */ + + int esize = 8 << (int)UInt(size); + int datasize = 64; + int part = (int)UInt(Q); + int elements = datasize / esize; + + bool accumulate = (op == false); + bool unsigned = (U == true); + + /* Operation */ + /* CheckFPAdvSIMDEnabled64(); */ + + Bits operand1 = Vpart(datasize, n, part); + Bits operand2 = Vpart(datasize, m, part); + BigInteger element1; + BigInteger element2; + Bits absdiff; + + Bits result = (accumulate ? V(2 * datasize, d) : Zeros(2 * datasize)); + + for (int e = 0; e <= elements - 1; e++) + { + element1 = Int(Elem(operand1, e, esize), unsigned); + element2 = Int(Elem(operand2, e, esize), unsigned); + + absdiff = Abs(element1 - element2).SubBigInteger(2 * esize - 1, 0); + + Elem(result, e, 2 * esize, Elem(result, e, 2 * esize) + absdiff); + } + + V(d, result); + } + + // saddw_advsimd.html + public static void Saddw_V(bool Q, Bits size, Bits Rm, Bits Rn, Bits Rd) + { + const bool U = false; + const bool o1 = false; + + /* Decode */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + int m = (int)UInt(Rm); + + /* if size == '11' then ReservedValue(); */ + + int esize = 8 << (int)UInt(size); + int datasize = 64; + int part = (int)UInt(Q); + int elements = datasize / esize; + + bool sub_op = (o1 == true); + bool unsigned = (U == true); + + /* Operation */ + /* CheckFPAdvSIMDEnabled64(); */ + + Bits result = new Bits(2 * datasize); + Bits operand1 = V(2 * datasize, n); + Bits operand2 = Vpart(datasize, m, part); + BigInteger element1; + BigInteger element2; + BigInteger sum; + + for (int e = 0; e <= elements - 1; e++) + { + element1 = Int(Elem(operand1, e, 2 * esize), unsigned); + element2 = Int(Elem(operand2, e, esize), unsigned); + + if (sub_op) + { + sum = element1 - element2; + } + else + { + sum = element1 + element2; + } + + Elem(result, e, 2 * esize, sum.SubBigInteger(2 * esize - 1, 0)); + } + + V(d, result); + } + + // sqadd_advsimd.html#SQADD_asisdsame_only + public static void Sqadd_S(Bits size, Bits Rm, Bits Rn, Bits Rd) + { + const bool U = false; + + /* Decode Scalar */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + int m = (int)UInt(Rm); + + int esize = 8 << (int)UInt(size); + int datasize = esize; + int elements = 1; + + bool unsigned = (U == true); + + /* Operation */ + /* CheckFPAdvSIMDEnabled64(); */ + + Bits result = new Bits(datasize); + Bits operand1 = V(datasize, n); + Bits operand2 = V(datasize, m); + BigInteger element1; + BigInteger element2; + BigInteger sum; + bool sat; + + for (int e = 0; e <= elements - 1; e++) + { + element1 = Int(Elem(operand1, e, esize), unsigned); + element2 = Int(Elem(operand2, e, esize), unsigned); + + sum = element1 + element2; + + (Bits _result, bool _sat) = SatQ(sum, esize, unsigned); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } + } + + V(d, result); + } + + // sqadd_advsimd.html#SQADD_asimdsame_only + public static void Sqadd_V(bool Q, Bits size, Bits Rm, Bits Rn, Bits Rd) + { + const bool U = false; + + /* Decode Vector */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + int m = (int)UInt(Rm); + + /* if size:Q == '110' then ReservedValue(); */ + + int esize = 8 << (int)UInt(size); + int datasize = (Q ? 128 : 64); + int elements = datasize / esize; + + bool unsigned = (U == true); + + /* Operation */ + /* CheckFPAdvSIMDEnabled64(); */ + + Bits result = new Bits(datasize); + Bits operand1 = V(datasize, n); + Bits operand2 = V(datasize, m); + BigInteger element1; + BigInteger element2; + BigInteger sum; + bool sat; + + for (int e = 0; e <= elements - 1; e++) + { + element1 = Int(Elem(operand1, e, esize), unsigned); + element2 = Int(Elem(operand2, e, esize), unsigned); + + sum = element1 + element2; - Elem(result, e, esize, Elem(result, e, esize) + absdiff); + (Bits _result, bool _sat) = SatQ(sum, esize, unsigned); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } } V(d, result); } - // sabdl_advsimd.html - public static void Sabdl_V(bool Q, Bits size, Bits Rm, Bits Rn, Bits Rd) + // sqsub_advsimd.html#SQSUB_asisdsame_only + public static void Sqsub_S(Bits size, Bits Rm, Bits Rn, Bits Rd) { const bool U = false; - const bool op = true; - /* Decode */ + /* Decode Scalar */ int d = (int)UInt(Rd); int n = (int)UInt(Rn); int m = (int)UInt(Rm); - /* if size == '11' then ReservedValue(); */ - int esize = 8 << (int)UInt(size); - int datasize = 64; - int part = (int)UInt(Q); - int elements = datasize / esize; + int datasize = esize; + int elements = 1; - bool accumulate = (op == false); bool unsigned = (U == true); /* Operation */ /* CheckFPAdvSIMDEnabled64(); */ - Bits operand1 = Vpart(datasize, n, part); - Bits operand2 = Vpart(datasize, m, part); + Bits result = new Bits(datasize); + Bits operand1 = V(datasize, n); + Bits operand2 = V(datasize, m); BigInteger element1; BigInteger element2; - Bits absdiff; - - Bits result = (accumulate ? V(2 * datasize, d) : Zeros(2 * datasize)); + BigInteger diff; + bool sat; for (int e = 0; e <= elements - 1; e++) { element1 = Int(Elem(operand1, e, esize), unsigned); element2 = Int(Elem(operand2, e, esize), unsigned); - absdiff = Abs(element1 - element2).SubBigInteger(2 * esize - 1, 0); + diff = element1 - element2; - Elem(result, e, 2 * esize, Elem(result, e, 2 * esize) + absdiff); + (Bits _result, bool _sat) = SatQ(diff, esize, unsigned); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } } V(d, result); } - // saddw_advsimd.html - public static void Saddw_V(bool Q, Bits size, Bits Rm, Bits Rn, Bits Rd) + // sqsub_advsimd.html#SQSUB_asimdsame_only + public static void Sqsub_V(bool Q, Bits size, Bits Rm, Bits Rn, Bits Rd) { const bool U = false; - const bool o1 = false; - /* Decode */ + /* Decode Vector */ int d = (int)UInt(Rd); int n = (int)UInt(Rn); int m = (int)UInt(Rm); - /* if size == '11' then ReservedValue(); */ + /* if size:Q == '110' then ReservedValue(); */ int esize = 8 << (int)UInt(size); - int datasize = 64; - int part = (int)UInt(Q); + int datasize = (Q ? 128 : 64); int elements = datasize / esize; - bool sub_op = (o1 == true); bool unsigned = (U == true); /* Operation */ /* CheckFPAdvSIMDEnabled64(); */ - Bits result = new Bits(2 * datasize); - Bits operand1 = V(2 * datasize, n); - Bits operand2 = Vpart(datasize, m, part); + Bits result = new Bits(datasize); + Bits operand1 = V(datasize, n); + Bits operand2 = V(datasize, m); BigInteger element1; BigInteger element2; - BigInteger sum; + BigInteger diff; + bool sat; for (int e = 0; e <= elements - 1; e++) { - element1 = Int(Elem(operand1, e, 2 * esize), unsigned); + element1 = Int(Elem(operand1, e, esize), unsigned); element2 = Int(Elem(operand2, e, esize), unsigned); - if (sub_op) - { - sum = element1 - element2; - } - else + diff = element1 - element2; + + (Bits _result, bool _sat) = SatQ(diff, esize, unsigned); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) { - sum = element1 + element2; + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. } - - Elem(result, e, 2 * esize, sum.SubBigInteger(2 * esize - 1, 0)); } V(d, result); @@ -5085,6 +5665,202 @@ namespace Ryujinx.Tests.Cpu.Tester V(d, result); } + // uqadd_advsimd.html#UQADD_asisdsame_only + public static void Uqadd_S(Bits size, Bits Rm, Bits Rn, Bits Rd) + { + const bool U = true; + + /* Decode Scalar */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + int m = (int)UInt(Rm); + + int esize = 8 << (int)UInt(size); + int datasize = esize; + int elements = 1; + + bool unsigned = (U == true); + + /* Operation */ + /* CheckFPAdvSIMDEnabled64(); */ + + Bits result = new Bits(datasize); + Bits operand1 = V(datasize, n); + Bits operand2 = V(datasize, m); + BigInteger element1; + BigInteger element2; + BigInteger sum; + bool sat; + + for (int e = 0; e <= elements - 1; e++) + { + element1 = Int(Elem(operand1, e, esize), unsigned); + element2 = Int(Elem(operand2, e, esize), unsigned); + + sum = element1 + element2; + + (Bits _result, bool _sat) = SatQ(sum, esize, unsigned); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } + } + + V(d, result); + } + + // uqadd_advsimd.html#UQADD_asimdsame_only + public static void Uqadd_V(bool Q, Bits size, Bits Rm, Bits Rn, Bits Rd) + { + const bool U = true; + + /* Decode Vector */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + int m = (int)UInt(Rm); + + /* if size:Q == '110' then ReservedValue(); */ + + int esize = 8 << (int)UInt(size); + int datasize = (Q ? 128 : 64); + int elements = datasize / esize; + + bool unsigned = (U == true); + + /* Operation */ + /* CheckFPAdvSIMDEnabled64(); */ + + Bits result = new Bits(datasize); + Bits operand1 = V(datasize, n); + Bits operand2 = V(datasize, m); + BigInteger element1; + BigInteger element2; + BigInteger sum; + bool sat; + + for (int e = 0; e <= elements - 1; e++) + { + element1 = Int(Elem(operand1, e, esize), unsigned); + element2 = Int(Elem(operand2, e, esize), unsigned); + + sum = element1 + element2; + + (Bits _result, bool _sat) = SatQ(sum, esize, unsigned); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } + } + + V(d, result); + } + + // uqsub_advsimd.html#UQSUB_asisdsame_only + public static void Uqsub_S(Bits size, Bits Rm, Bits Rn, Bits Rd) + { + const bool U = true; + + /* Decode Scalar */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + int m = (int)UInt(Rm); + + int esize = 8 << (int)UInt(size); + int datasize = esize; + int elements = 1; + + bool unsigned = (U == true); + + /* Operation */ + /* CheckFPAdvSIMDEnabled64(); */ + + Bits result = new Bits(datasize); + Bits operand1 = V(datasize, n); + Bits operand2 = V(datasize, m); + BigInteger element1; + BigInteger element2; + BigInteger diff; + bool sat; + + for (int e = 0; e <= elements - 1; e++) + { + element1 = Int(Elem(operand1, e, esize), unsigned); + element2 = Int(Elem(operand2, e, esize), unsigned); + + diff = element1 - element2; + + (Bits _result, bool _sat) = SatQ(diff, esize, unsigned); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } + } + + V(d, result); + } + + // uqsub_advsimd.html#UQSUB_asimdsame_only + public static void Uqsub_V(bool Q, Bits size, Bits Rm, Bits Rn, Bits Rd) + { + const bool U = true; + + /* Decode Vector */ + int d = (int)UInt(Rd); + int n = (int)UInt(Rn); + int m = (int)UInt(Rm); + + /* if size:Q == '110' then ReservedValue(); */ + + int esize = 8 << (int)UInt(size); + int datasize = (Q ? 128 : 64); + int elements = datasize / esize; + + bool unsigned = (U == true); + + /* Operation */ + /* CheckFPAdvSIMDEnabled64(); */ + + Bits result = new Bits(datasize); + Bits operand1 = V(datasize, n); + Bits operand2 = V(datasize, m); + BigInteger element1; + BigInteger element2; + BigInteger diff; + bool sat; + + for (int e = 0; e <= elements - 1; e++) + { + element1 = Int(Elem(operand1, e, esize), unsigned); + element2 = Int(Elem(operand2, e, esize), unsigned); + + diff = element1 - element2; + + (Bits _result, bool _sat) = SatQ(diff, esize, unsigned); + Elem(result, e, esize, _result); + sat = _sat; + + if (sat) + { + /* FPSR.QC = '1'; */ + FPSR[27] = true; // TODO: Add named fields. + } + } + + V(d, result); + } + // usubw_advsimd.html public static void Usubw_V(bool Q, Bits size, Bits Rm, Bits Rn, Bits Rd) { diff --git a/Ryujinx.Tests/Cpu/Tester/Pseudocode.cs b/Ryujinx.Tests/Cpu/Tester/Pseudocode.cs index 3a877fb1..6c4dfa92 100644 --- a/Ryujinx.Tests/Cpu/Tester/Pseudocode.cs +++ b/Ryujinx.Tests/Cpu/Tester/Pseudocode.cs @@ -1193,9 +1193,9 @@ namespace Ryujinx.Tests.Cpu.Tester result = BigInteger.Pow(2, N) - 1; saturated = true; } - else if (i < 0) + else if (i < (BigInteger)0) { - result = 0; + result = (BigInteger)0; saturated = true; } else -- cgit v1.2.3