aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Instructions
diff options
context:
space:
mode:
authormerry <git@mary.rs>2022-02-08 09:46:42 +0000
committerGitHub <noreply@github.com>2022-02-08 10:46:42 +0100
commit86b37d0ff7764ac62b1e9578b07a8b648a3bd55a (patch)
treef1500dddb5a4dad5c2d65a653e50b9a7dcee6287 /ARMeilleure/Instructions
parent863c5811903d9fe1020d966028ce6a030477be92 (diff)
ARMeilleure: A32: Implement SHSUB8 and UHSUB8 (#3089)1.1.21
* ARMeilleure: A32: Implement UHSUB8 * ARMeilleure: A32: Implement SHSUB8
Diffstat (limited to 'ARMeilleure/Instructions')
-rw-r--r--ARMeilleure/Instructions/InstEmitAlu32.cs45
-rw-r--r--ARMeilleure/Instructions/InstName.cs2
2 files changed, 47 insertions, 0 deletions
diff --git a/ARMeilleure/Instructions/InstEmitAlu32.cs b/ARMeilleure/Instructions/InstEmitAlu32.cs
index 9aff0261..66b8a8a7 100644
--- a/ARMeilleure/Instructions/InstEmitAlu32.cs
+++ b/ARMeilleure/Instructions/InstEmitAlu32.cs
@@ -392,6 +392,11 @@ namespace ARMeilleure.Instructions
EmitHadd8(context, false);
}
+ public static void Shsub8(ArmEmitterContext context)
+ {
+ EmitHsub8(context, false);
+ }
+
public static void Ssat(ArmEmitterContext context)
{
OpCode32Sat op = (OpCode32Sat)context.CurrOp;
@@ -482,6 +487,11 @@ namespace ARMeilleure.Instructions
EmitHadd8(context, true);
}
+ public static void Uhsub8(ArmEmitterContext context)
+ {
+ EmitHsub8(context, true);
+ }
+
public static void Usat(ArmEmitterContext context)
{
OpCode32Sat op = (OpCode32Sat)context.CurrOp;
@@ -681,6 +691,41 @@ namespace ARMeilleure.Instructions
SetIntA32(context, op.Rd, res);
}
+ private static void EmitHsub8(ArmEmitterContext context, bool unsigned)
+ {
+ OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
+
+ Operand m = GetIntA32(context, op.Rm);
+ Operand n = GetIntA32(context, op.Rn);
+ Operand left, right, carry, res;
+
+ // This relies on the equality x-y == (x^y) - (((x^y)&y) << 1).
+ // Note that x^y always contains the LSB of the result.
+ // Since we want to calculate (x+y)/2, we can instead calculate ((x^y)>>1) - ((x^y)&y).
+
+ carry = context.BitwiseExclusiveOr(m, n);
+ left = context.ShiftRightUI(carry, Const(1));
+ right = context.BitwiseAnd(carry, m);
+
+ // We must now perform a partitioned subtraction.
+ // We can do this because minuend contains 7 bit fields.
+ // We use the extra bit in minuend as a bit to borrow from; we set this bit.
+ // We invert this bit at the end as this tells us if that bit was borrowed from.
+
+ res = context.BitwiseOr(left, Const(0x80808080));
+ res = context.Subtract(res, right);
+ res = context.BitwiseExclusiveOr(res, Const(0x80808080));
+
+ if (!unsigned)
+ {
+ // We then sign extend the result into this bit.
+ carry = context.BitwiseAnd(carry, Const(0x80808080));
+ res = context.BitwiseExclusiveOr(res, carry);
+ }
+
+ SetIntA32(context, op.Rd, res);
+ }
+
private static void EmitSat(ArmEmitterContext context, int intMin, int intMax)
{
OpCode32Sat op = (OpCode32Sat)context.CurrOp;
diff --git a/ARMeilleure/Instructions/InstName.cs b/ARMeilleure/Instructions/InstName.cs
index 698979b9..3e016495 100644
--- a/ARMeilleure/Instructions/InstName.cs
+++ b/ARMeilleure/Instructions/InstName.cs
@@ -80,6 +80,7 @@ namespace ARMeilleure.Instructions
Sbcs,
Sbfm,
Sdiv,
+ Shsub8,
Smaddl,
Smsubl,
Smulh,
@@ -546,6 +547,7 @@ namespace ARMeilleure.Instructions
Tst,
Ubfx,
Uhadd8,
+ Uhsub8,
Umaal,
Umlal,
Umull,