ARMeilleure: A32: Implement SHSUB8 and UHSUB8 (#3089)
* ARMeilleure: A32: Implement UHSUB8 * ARMeilleure: A32: Implement SHSUB8
This commit is contained in:
parent
863c581190
commit
86b37d0ff7
4 changed files with 87 additions and 0 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue