aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ARMeilleure/Decoders/OpCodeTable.cs1
-rw-r--r--ARMeilleure/Instructions/InstEmitAlu32.cs18
-rw-r--r--ARMeilleure/Instructions/InstName.cs1
-rw-r--r--ARMeilleure/Translation/PTC/Ptc.cs2
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestAlu32.cs19
5 files changed, 40 insertions, 1 deletions
diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs
index 12ff051c..9eb92523 100644
--- a/ARMeilleure/Decoders/OpCodeTable.cs
+++ b/ARMeilleure/Decoders/OpCodeTable.cs
@@ -776,6 +776,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00010001xxxx0000xxxx0xx1xxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluRsReg.Create);
SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, OpCode32AluBf.Create);
SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, OpCode32AluMla.Create);
+ SetA32("<<<<01100111xxxxxxxx11111001xxxx", InstName.Uhadd8, InstEmit32.Uhadd8, OpCode32AluReg.Create);
SetA32("<<<<00000100xxxxxxxxxxxx1001xxxx", InstName.Umaal, InstEmit32.Umaal, OpCode32AluUmull.Create);
SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, OpCode32AluUmull.Create);
SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, OpCode32AluUmull.Create);
diff --git a/ARMeilleure/Instructions/InstEmitAlu32.cs b/ARMeilleure/Instructions/InstEmitAlu32.cs
index 49fce31d..5f55fcd1 100644
--- a/ARMeilleure/Instructions/InstEmitAlu32.cs
+++ b/ARMeilleure/Instructions/InstEmitAlu32.cs
@@ -472,6 +472,24 @@ namespace ARMeilleure.Instructions
EmitDiv(context, true);
}
+ public static void Uhadd8(ArmEmitterContext context)
+ {
+ OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
+
+ Operand m = GetIntA32(context, op.Rm);
+ Operand n = GetIntA32(context, op.Rn);
+
+ Operand xor, res;
+
+ res = context.BitwiseAnd(m, n);
+ xor = context.BitwiseExclusiveOr(m, n);
+ xor = context.ShiftRightUI(xor, Const(1));
+ xor = context.BitwiseAnd(xor, Const(0x7F7F7F7Fu));
+ res = context.Add(res, xor);
+
+ SetIntA32(context, op.Rd, res);
+ }
+
public static void Usat(ArmEmitterContext context)
{
OpCode32Sat op = (OpCode32Sat)context.CurrOp;
diff --git a/ARMeilleure/Instructions/InstName.cs b/ARMeilleure/Instructions/InstName.cs
index 9b4e8961..ce1c53cc 100644
--- a/ARMeilleure/Instructions/InstName.cs
+++ b/ARMeilleure/Instructions/InstName.cs
@@ -541,6 +541,7 @@ namespace ARMeilleure.Instructions
Trap,
Tst,
Ubfx,
+ Uhadd8,
Umaal,
Umlal,
Umull,
diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs
index 04cab561..4375832b 100644
--- a/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/ARMeilleure/Translation/PTC/Ptc.cs
@@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0";
- private const uint InternalVersion = 2721; //! To be incremented manually for each change to the ARMeilleure project.
+ private const uint InternalVersion = 2908; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";
diff --git a/Ryujinx.Tests/Cpu/CpuTestAlu32.cs b/Ryujinx.Tests/Cpu/CpuTestAlu32.cs
index c21bbe10..1867e27f 100644
--- a/Ryujinx.Tests/Cpu/CpuTestAlu32.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestAlu32.cs
@@ -111,6 +111,25 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
+
+ [Test, Pairwise]
+ public void Uhadd8([Values(0u, 0xdu)] uint rd,
+ [Values(1u)] uint rm,
+ [Values(2u)] uint rn,
+ [Random(RndCnt)] uint w0,
+ [Random(RndCnt)] uint w1,
+ [Random(RndCnt)] uint w2)
+ {
+ uint opcode = 0xE6700F90u; //UHADD8 R0, R0, R0
+
+ opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
+
+ uint sp = TestContext.CurrentContext.Random.NextUInt();
+
+ SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp);
+
+ CompareAgainstUnicorn();
+ }
#endif
}
}