diff --git a/ARMeilleure/CodeGen/X86/Assembler.cs b/ARMeilleure/CodeGen/X86/Assembler.cs index f0fab1c5b3..e9eb4d1a71 100644 --- a/ARMeilleure/CodeGen/X86/Assembler.cs +++ b/ARMeilleure/CodeGen/X86/Assembler.cs @@ -63,6 +63,7 @@ namespace ARMeilleure.CodeGen.X86 Add(X86Instruction.Bswap, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000fc8, InstFlags.RegOnly)); Add(X86Instruction.Cmovcc, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f40, InstFlags.None)); Add(X86Instruction.Cmp, new InstInfo(0x000039, 0x070083, 0x070081, BadOp, 0x00003b, InstFlags.None)); + Add(X86Instruction.Div, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x0600f7, InstFlags.None)); Add(X86Instruction.Idiv, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x0700f7, InstFlags.None)); Add(X86Instruction.Imul, new InstInfo(BadOp, 0x00006b, 0x000069, BadOp, 0x000faf, InstFlags.None)); Add(X86Instruction.Mov, new InstInfo(0x000089, BadOp, 0x0000c7, 0x0000b8, 0x00008b, InstFlags.None)); @@ -141,6 +142,11 @@ namespace ARMeilleure.CodeGen.X86 WriteByte(0x99); } + public void Div(Operand source) + { + WriteInstruction(null, source, X86Instruction.Div); + } + public void Idiv(Operand source) { WriteInstruction(null, source, X86Instruction.Idiv); @@ -649,9 +655,17 @@ namespace ARMeilleure.CodeGen.X86 } } - if (source != null && source.Kind == OperandKind.Register) + if (source != null) { - SetRegisterHighBit(source.GetRegister(), (rrm ? 0 : 2)); + if (source.Type == OperandType.I64) + { + rexPrefix |= 0x48; + } + + if (source.Kind == OperandKind.Register) + { + SetRegisterHighBit(source.GetRegister(), (rrm ? 0 : 2)); + } } return rexPrefix; diff --git a/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/ARMeilleure/CodeGen/X86/CodeGenerator.cs index 0a15eda0c5..6b2bff4321 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenerator.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenerator.cs @@ -40,6 +40,7 @@ namespace ARMeilleure.CodeGen.X86 Add(Instruction.Copy, GenerateCopy); Add(Instruction.CountLeadingZeros, GenerateCountLeadingZeros); Add(Instruction.Divide, GenerateDivide); + Add(Instruction.DivideUI, GenerateDivideUI); Add(Instruction.Fill, GenerateFill); Add(Instruction.Load, GenerateLoad); Add(Instruction.LoadFromContext, GenerateLoadFromContext); @@ -321,6 +322,16 @@ namespace ARMeilleure.CodeGen.X86 context.Assembler.Idiv(divisor); } + private static void GenerateDivideUI(CodeGenContext context, Operation operation) + { + Operand divisor = operation.GetSource(1); + + Operand rdx = Register(X86Register.Rdx, OperandType.I32); + + context.Assembler.Xor(rdx, rdx); + context.Assembler.Div(divisor); + } + private static void GenerateFill(CodeGenContext context, Operation operation) { Operand dest = operation.Dest; @@ -587,9 +598,9 @@ namespace ARMeilleure.CodeGen.X86 return new Operand(reg.Index, reg.Type, OperandType.I32); } - private static Operand Register(X86Register register) + private static Operand Register(X86Register register, OperandType type = OperandType.I64) { - return new Operand((int)register, RegisterType.Integer, OperandType.I64); + return new Operand((int)register, RegisterType.Integer, type); } } } \ No newline at end of file diff --git a/ARMeilleure/CodeGen/X86/X86Instruction.cs b/ARMeilleure/CodeGen/X86/X86Instruction.cs index a79bad41a7..26d016c179 100644 --- a/ARMeilleure/CodeGen/X86/X86Instruction.cs +++ b/ARMeilleure/CodeGen/X86/X86Instruction.cs @@ -8,6 +8,7 @@ namespace ARMeilleure.CodeGen.X86 Bswap, Cmovcc, Cmp, + Div, Idiv, Imul, Mov, diff --git a/ARMeilleure/Decoders/OpCodeDiv.cs b/ARMeilleure/Decoders/OpCodeDiv.cs new file mode 100644 index 0000000000..127bff0af9 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeDiv.cs @@ -0,0 +1,12 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeDiv : OpCodeAlu + { + public int Rm { get; private set; } + + public OpCodeDiv(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rm = (opCode >> 16) & 0x1f; + } + } +} \ No newline at end of file diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index f46afdc35c..08f9ade886 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -155,7 +155,7 @@ namespace ARMeilleure.Decoders SetA64("x1111010000xxxxx000000xxxxxxxxxx", InstName.Sbcs, InstEmit.Sbcs, typeof(OpCodeAluRs)); SetA64("00010011000xxxxx0xxxxxxxxxxxxxxx", InstName.Sbfm, InstEmit.Sbfm, typeof(OpCodeBfm)); SetA64("1001001101xxxxxxxxxxxxxxxxxxxxxx", InstName.Sbfm, InstEmit.Sbfm, typeof(OpCodeBfm)); - SetA64("x0011010110xxxxx000011xxxxxxxxxx", InstName.Sdiv, InstEmit.Sdiv, typeof(OpCodeMul)); + SetA64("x0011010110xxxxx000011xxxxxxxxxx", InstName.Sdiv, InstEmit.Sdiv, typeof(OpCodeDiv)); SetA64("10011011001xxxxx0xxxxxxxxxxxxxxx", InstName.Smaddl, InstEmit.Smaddl, typeof(OpCodeMul)); SetA64("10011011001xxxxx1xxxxxxxxxxxxxxx", InstName.Smsubl, InstEmit.Smsubl, typeof(OpCodeMul)); SetA64("10011011010xxxxx0xxxxxxxxxxxxxxx", InstName.Smulh, null, typeof(OpCodeMul)); @@ -184,7 +184,7 @@ namespace ARMeilleure.Decoders SetA64("x0110110xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tbz, InstEmit.Tbz, typeof(OpCodeBImmTest)); SetA64("01010011000xxxxx0xxxxxxxxxxxxxxx", InstName.Ubfm, InstEmit.Ubfm, typeof(OpCodeBfm)); SetA64("1101001101xxxxxxxxxxxxxxxxxxxxxx", InstName.Ubfm, InstEmit.Ubfm, typeof(OpCodeBfm)); - SetA64("x0011010110xxxxx000010xxxxxxxxxx", InstName.Udiv, InstEmit.Udiv, typeof(OpCodeMul)); + SetA64("x0011010110xxxxx000010xxxxxxxxxx", InstName.Udiv, InstEmit.Udiv, typeof(OpCodeDiv)); SetA64("10011011101xxxxx0xxxxxxxxxxxxxxx", InstName.Umaddl, InstEmit.Umaddl, typeof(OpCodeMul)); SetA64("10011011101xxxxx1xxxxxxxxxxxxxxx", InstName.Umsubl, InstEmit.Umsubl, typeof(OpCodeMul)); SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", InstName.Umulh, null, typeof(OpCodeMul)); diff --git a/ARMeilleure/Instructions/InstEmitAlu.cs b/ARMeilleure/Instructions/InstEmitAlu.cs index 21076b9719..06838f8ef7 100644 --- a/ARMeilleure/Instructions/InstEmitAlu.cs +++ b/ARMeilleure/Instructions/InstEmitAlu.cs @@ -272,13 +272,13 @@ namespace ARMeilleure.Instructions private static void EmitDiv(EmitterContext context, bool unsigned) { - OpCodeMul op = (OpCodeMul)context.CurrOp; + 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(op.GetOperandType(), 0)); + Operand divisorIsZero = context.ICompareEqual(m, Const(m.Type, 0)); Operand lblBadDiv = Label(); Operand lblEnd = Label(); @@ -294,7 +294,7 @@ namespace ARMeilleure.Instructions Operand minus1 = is32Bits ? Const(-1) : Const(-1L); Operand nIsIntMin = context.ICompareEqual(n, intMin); - Operand mIsMinus1 = context.ICompareEqual(n, minus1); + Operand mIsMinus1 = context.ICompareEqual(m, minus1); Operand lblGoodDiv = Label();