public static void Smul__(ArmEmitterContext context) { OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; Operand n = GetIntA32(context, op.Rn); Operand m = GetIntA32(context, op.Rm); if (op.NHigh) { n = context.ShiftRightSI(n, Const(16)); } else { n = context.SignExtend16(OperandType.I32, n); } if (op.MHigh) { m = context.ShiftRightSI(m, Const(16)); } else { m = context.SignExtend16(OperandType.I32, m); } Operand res = context.Multiply(n, m); EmitGenericAluStoreA32(context, op.Rd, false, res); }
private static void EmitSmmul(ArmEmitterContext context, MullFlags flags) { OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn)); Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm)); Operand res = context.Multiply(n, m); if (flags.HasFlag(MullFlags.Add) && op.Ra != 0xf) { res = context.Add(context.ShiftLeft(context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Ra)), Const(32)), res); } else if (flags.HasFlag(MullFlags.Subtract)) { res = context.Subtract(context.ShiftLeft(context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Ra)), Const(32)), res); } if (op.R) { res = context.Add(res, Const(0x80000000L)); } Operand hi = context.ConvertI64ToI32(context.ShiftRightSI(res, Const(32))); EmitGenericAluStoreA32(context, op.Rd, false, hi); }
public static void Smlaw_(ArmEmitterContext context) { OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; Operand n = GetIntA32(context, op.Rn); Operand m = GetIntA32(context, op.Rm); Operand a = GetIntA32(context, op.Ra); if (op.MHigh) { m = context.SignExtend16(OperandType.I64, context.ShiftRightUI(m, Const(16))); } else { m = context.SignExtend16(OperandType.I64, m); } Operand res = context.Multiply(context.SignExtend32(OperandType.I64, n), m); Operand toAdd = context.ShiftLeft(context.SignExtend32(OperandType.I64, a), Const(16)); res = context.Add(res, toAdd); res = context.ShiftRightSI(res, Const(16)); Operand q = context.ICompareNotEqual(res, context.SignExtend32(OperandType.I64, res)); res = context.ConvertI64ToI32(res); UpdateQFlag(context, q); EmitGenericAluStoreA32(context, op.Rd, false, res); }
public static void Smlab(ArmEmitterContext context) { OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; Operand n = GetIntA32(context, op.Rn); Operand m = GetIntA32(context, op.Rm); if (op.NHigh) { n = context.SignExtend16(OperandType.I32, context.ShiftRightUI(n, Const(16))); } else { n = context.SignExtend16(OperandType.I32, n); } if (op.MHigh) { m = context.SignExtend16(OperandType.I32, context.ShiftRightUI(m, Const(16))); } else { m = context.SignExtend16(OperandType.I32, m); } Operand res = context.Multiply(n, m); Operand a = GetIntA32(context, op.Ra); res = context.Add(res, a); // TODO: set Q flag when last addition overflows (saturation)? EmitGenericAluStoreA32(context, op.Rd, false, res); }
public static void Mls(ArmEmitterContext context) { OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; Operand n = GetAluN(context); Operand m = GetAluM(context); Operand a = GetIntA32(context, op.Ra); Operand res = context.Subtract(a, context.Multiply(n, m)); EmitAluStore(context, res); }
public static void Mla(ArmEmitterContext context) { OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; Operand n = GetAluN(context); Operand m = GetAluM(context); Operand a = GetIntA32(context, op.Ra); Operand res = context.Add(a, context.Multiply(n, m)); if (op.SetFlags) { EmitNZFlagsCheck(context, res); } EmitAluStore(context, res); }
public static void Smulw_(ArmEmitterContext context) { OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; Operand n = GetIntA32(context, op.Rn); Operand m = GetIntA32(context, op.Rm); if (op.MHigh) { m = context.SignExtend16(OperandType.I64, context.ShiftRightUI(m, Const(16))); } else { m = context.SignExtend16(OperandType.I64, m); } Operand res = context.Multiply(context.SignExtend32(OperandType.I64, n), m); res = context.ShiftRightUI(res, Const(16)); res = context.ConvertI64ToI32(res); EmitGenericAluStoreA32(context, op.Rd, false, res); }