diff --git a/ARMeilleure/Instructions/InstEmitAlu.cs b/ARMeilleure/Instructions/InstEmitAlu.cs index 06838f8ef7..52ddd4f8c8 100644 --- a/ARMeilleure/Instructions/InstEmitAlu.cs +++ b/ARMeilleure/Instructions/InstEmitAlu.cs @@ -267,61 +267,6 @@ namespace ARMeilleure.Instructions SetAluDOrZR(context, context.RotateRight(GetAluN(context), GetAluMShift(context))); } - public static void Sdiv(EmitterContext context) => EmitDiv(context, unsigned: false); - public static void Udiv(EmitterContext context) => EmitDiv(context, unsigned: true); - - private static void EmitDiv(EmitterContext context, bool unsigned) - { - OpCodeDiv op = (OpCodeDiv)context.CurrOp; - - //If Rm == 0, Rd = 0 (division by zero). - Operand n = GetIntOrZR(op, op.Rn); - Operand m = GetIntOrZR(op, op.Rm); - - Operand divisorIsZero = context.ICompareEqual(m, Const(m.Type, 0)); - - Operand lblBadDiv = Label(); - Operand lblEnd = Label(); - - context.BranchIfTrue(lblBadDiv, divisorIsZero); - - if (!unsigned) - { - //If Rn == INT_MIN && Rm == -1, Rd = INT_MIN (overflow). - bool is32Bits = op.RegisterSize == RegisterSize.Int32; - - Operand intMin = is32Bits ? Const(int.MinValue) : Const(long.MinValue); - Operand minus1 = is32Bits ? Const(-1) : Const(-1L); - - Operand nIsIntMin = context.ICompareEqual(n, intMin); - Operand mIsMinus1 = context.ICompareEqual(m, minus1); - - Operand lblGoodDiv = Label(); - - context.BranchIfFalse(lblGoodDiv, context.BitwiseAnd(nIsIntMin, mIsMinus1)); - - SetAluDOrZR(context, intMin); - - context.Branch(lblEnd); - - context.MarkLabel(lblGoodDiv); - } - - Operand d = unsigned - ? context.IDivideUI(n, m) - : context.IDivide (n, m); - - SetAluDOrZR(context, d); - - context.Branch(lblEnd); - - context.MarkLabel(lblBadDiv); - - SetAluDOrZR(context, Const(op.GetOperandType(), 0)); - - context.MarkLabel(lblEnd); - } - private static Operand GetAluMShift(EmitterContext context) { IOpCodeAluRs op = (IOpCodeAluRs)context.CurrOp; diff --git a/ARMeilleure/Instructions/InstEmitDiv.cs b/ARMeilleure/Instructions/InstEmitDiv.cs new file mode 100644 index 0000000000..cfe20e2585 --- /dev/null +++ b/ARMeilleure/Instructions/InstEmitDiv.cs @@ -0,0 +1,67 @@ +using ARMeilleure.Decoders; +using ARMeilleure.IntermediateRepresentation; +using ARMeilleure.Translation; + +using static ARMeilleure.Instructions.InstEmitHelper; +using static ARMeilleure.IntermediateRepresentation.OperandHelper; + +namespace ARMeilleure.Instructions +{ + static partial class InstEmit + { + public static void Sdiv(EmitterContext context) => EmitDiv(context, unsigned: false); + public static void Udiv(EmitterContext context) => EmitDiv(context, unsigned: true); + + private static void EmitDiv(EmitterContext context, bool unsigned) + { + OpCodeDiv op = (OpCodeDiv)context.CurrOp; + + //If Rm == 0, Rd = 0 (division by zero). + Operand n = GetIntOrZR(op, op.Rn); + Operand m = GetIntOrZR(op, op.Rm); + + Operand divisorIsZero = context.ICompareEqual(m, Const(m.Type, 0)); + + Operand lblBadDiv = Label(); + Operand lblEnd = Label(); + + context.BranchIfTrue(lblBadDiv, divisorIsZero); + + if (!unsigned) + { + //If Rn == INT_MIN && Rm == -1, Rd = INT_MIN (overflow). + bool is32Bits = op.RegisterSize == RegisterSize.Int32; + + Operand intMin = is32Bits ? Const(int.MinValue) : Const(long.MinValue); + Operand minus1 = is32Bits ? Const(-1) : Const(-1L); + + Operand nIsIntMin = context.ICompareEqual(n, intMin); + Operand mIsMinus1 = context.ICompareEqual(m, minus1); + + Operand lblGoodDiv = Label(); + + context.BranchIfFalse(lblGoodDiv, context.BitwiseAnd(nIsIntMin, mIsMinus1)); + + SetAluDOrZR(context, intMin); + + context.Branch(lblEnd); + + context.MarkLabel(lblGoodDiv); + } + + Operand d = unsigned + ? context.IDivideUI(n, m) + : context.IDivide (n, m); + + SetAluDOrZR(context, d); + + context.Branch(lblEnd); + + context.MarkLabel(lblBadDiv); + + SetAluDOrZR(context, Const(op.GetOperandType(), 0)); + + context.MarkLabel(lblEnd); + } + } +}