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 EmitHadd8(ArmEmitterContext context, bool unsigned) { OpCode32AluReg op = (OpCode32AluReg)context.CurrOp; Operand m = GetIntA32(context, op.Rm); Operand n = GetIntA32(context, op.Rn); Operand xor, res, carry; // This relies on the equality x+y == ((x&y) << 1) + (x^y). // 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) + ((x^y)>>1). // We mask by 0x7F to remove the LSB so that it doesn't leak into the field below. res = context.BitwiseAnd(m, n); carry = context.BitwiseExclusiveOr(m, n); xor = context.ShiftRightUI(carry, Const(1)); xor = context.BitwiseAnd(xor, Const(0x7F7F7F7Fu)); res = context.Add(res, xor); if (!unsigned) { // Propagates the sign bit from (x^y)>>1 upwards by one. carry = context.BitwiseAnd(carry, Const(0x80808080u)); res = context.BitwiseExclusiveOr(res, carry); } SetIntA32(context, op.Rd, res); }
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); }