Better impl of UBFX, add UDIV and SDIV
Now boots way further - now stuck on VMOV instruction.
This commit is contained in:
parent
aed13bcdd4
commit
7af22d43e5
2 changed files with 65 additions and 1 deletions
|
@ -666,6 +666,7 @@ namespace ARMeilleure.Decoders
|
||||||
SetA32("<<<<0010011xxxxxxxxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, typeof(OpCode32AluImm));
|
SetA32("<<<<0010011xxxxxxxxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, typeof(OpCode32AluImm));
|
||||||
SetA32("<<<<0000011xxxxxxxxxxxxxxxx0xxxx", InstName.Rsb, InstEmit32.Rsb, typeof(OpCode32AluRsImm));
|
SetA32("<<<<0000011xxxxxxxxxxxxxxxx0xxxx", InstName.Rsb, InstEmit32.Rsb, typeof(OpCode32AluRsImm));
|
||||||
//RsReg missing
|
//RsReg missing
|
||||||
|
SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, typeof(OpCode32AluMla));
|
||||||
SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, typeof(OpCode32MemStEx));
|
SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, typeof(OpCode32MemStEx));
|
||||||
SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, typeof(OpCode32MemStEx));
|
SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, typeof(OpCode32MemStEx));
|
||||||
SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, 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));
|
SetA32("<<<<00010001xxxx0000xxxxxxx0xxxx", InstName.Tst, InstEmit32.Tst, typeof(OpCode32AluRsImm));
|
||||||
//RsReg missing
|
//RsReg missing
|
||||||
SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, typeof(OpCode32AluBf));
|
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("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, typeof(OpCode32AluUmull));
|
||||||
SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, typeof(OpCode32AluUx));
|
SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, typeof(OpCode32AluUx));
|
||||||
SetA32("<<<<011011111111xxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, typeof(OpCode32AluUx));
|
SetA32("<<<<011011111111xxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, typeof(OpCode32AluUx));
|
||||||
|
|
|
@ -288,6 +288,68 @@ namespace ARMeilleure.Instructions
|
||||||
EmitAluStore(context, res);
|
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)
|
public static void Movt(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluImm16 op = (OpCode32AluImm16)context.CurrOp;
|
OpCode32AluImm16 op = (OpCode32AluImm16)context.CurrOp;
|
||||||
|
@ -364,7 +426,7 @@ namespace ARMeilleure.Instructions
|
||||||
var mask = (int)(0xFFFFFFFF >> (31 - msb)) << op.Lsb;
|
var mask = (int)(0xFFFFFFFF >> (31 - msb)) << op.Lsb;
|
||||||
|
|
||||||
Operand n = GetIntOrZR(context, op.Rn);
|
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);
|
SetIntA32(context, op.Rd, res);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue