Better impl of UBFX, add UDIV and SDIV

Now boots way further - now stuck on VMOV instruction.
This commit is contained in:
riperiperi 2019-12-28 01:43:04 +00:00 committed by Thog
parent aed13bcdd4
commit 7af22d43e5
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
2 changed files with 65 additions and 1 deletions

View file

@ -666,6 +666,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0010011xxxxxxxxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, typeof(OpCode32AluImm));
SetA32("<<<<0000011xxxxxxxxxxxxxxxx0xxxx", InstName.Rsb, InstEmit32.Rsb, typeof(OpCode32AluRsImm));
//RsReg missing
SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, typeof(OpCode32AluMla));
SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, typeof(OpCode32MemStEx));
SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, typeof(OpCode32MemStEx));
SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, typeof(OpCode32MemStEx));
@ -696,6 +697,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00010001xxxx0000xxxxxxx0xxxx", InstName.Tst, InstEmit32.Tst, typeof(OpCode32AluRsImm));
//RsReg missing
SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, typeof(OpCode32AluBf));
SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, typeof(OpCode32AluMla));
SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, typeof(OpCode32AluUmull));
SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, typeof(OpCode32AluUx));
SetA32("<<<<011011111111xxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, typeof(OpCode32AluUx));

View file

@ -288,6 +288,68 @@ namespace ARMeilleure.Instructions
EmitAluStore(context, res);
}
public static void Udiv(ArmEmitterContext context)
{
EmitDiv(context, true);
}
public static void Sdiv(ArmEmitterContext context)
{
EmitDiv(context, false);
}
public static void EmitDiv(ArmEmitterContext context, bool unsigned)
{
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
Operand n = GetAluN(context);
Operand m = GetAluM(context);
Operand zero = Const(m.Type, 0);
Operand divisorIsZero = context.ICompareEqual(m, zero);
Operand lblBadDiv = Label();
Operand lblEnd = Label();
context.BranchIfTrue(lblBadDiv, divisorIsZero);
if (!unsigned)
{
// If Rn == INT_MIN && Rm == -1, Rd = INT_MIN (overflow).
// assume this is the same as ARM64 for now - tests to follow.
Operand intMin = Const(int.MinValue);
Operand minus1 = Const(-1);
Operand nIsIntMin = context.ICompareEqual(n, intMin);
Operand mIsMinus1 = context.ICompareEqual(m, minus1);
Operand lblGoodDiv = Label();
context.BranchIfFalse(lblGoodDiv, context.BitwiseAnd(nIsIntMin, mIsMinus1));
EmitAluStore(context, intMin);
context.Branch(lblEnd);
context.MarkLabel(lblGoodDiv);
}
Operand res = unsigned
? context.DivideUI(n, m)
: context.Divide(n, m);
EmitAluStore(context, res);
context.Branch(lblEnd);
context.MarkLabel(lblBadDiv);
EmitAluStore(context, zero);
context.MarkLabel(lblEnd);
}
public static void Movt(ArmEmitterContext context)
{
OpCode32AluImm16 op = (OpCode32AluImm16)context.CurrOp;
@ -364,7 +426,7 @@ namespace ARMeilleure.Instructions
var mask = (int)(0xFFFFFFFF >> (31 - msb)) << op.Lsb;
Operand n = GetIntOrZR(context, op.Rn);
Operand res = context.ShiftRightUI(context.BitwiseAnd(n, Const(mask)), Const(op.Lsb));
Operand res = context.ShiftRightUI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb));
SetIntA32(context, op.Rd, res);
}