Implement the DivideUI IR instruction and fix 64-bits IDIV

This commit is contained in:
gdkchan 2019-05-29 20:31:21 -03:00
parent b289a3fc32
commit 0ca624a9da
6 changed files with 47 additions and 9 deletions

View file

@ -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;

View file

@ -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);
}
}
}

View file

@ -8,6 +8,7 @@ namespace ARMeilleure.CodeGen.X86
Bswap,
Cmovcc,
Cmp,
Div,
Idiv,
Imul,
Mov,

View file

@ -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;
}
}
}

View file

@ -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));

View file

@ -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();