|
|
@@ -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;
|