diff options
Diffstat (limited to 'ARMeilleure/Instructions')
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs | 143 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdHelper.cs | 10 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdHelper32.cs | 71 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdShift32.cs | 168 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSystem32.cs | 36 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstName.cs | 12 |
6 files changed, 351 insertions, 89 deletions
diff --git a/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs b/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs index ed6b2a31..79b376e9 100644 --- a/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs +++ b/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs @@ -777,6 +777,13 @@ namespace ARMeilleure.Instructions } } + public static void Vmlal_I(ArmEmitterContext context) + { + OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; + + EmitVectorTernaryLongOpI32(context, (d, n, m) => context.Add(d, context.Multiply(n, m)), !op.U); + } + public static void Vmls_S(ArmEmitterContext context) { if (Optimizations.FastFP && Optimizations.UseSse2) @@ -992,6 +999,13 @@ namespace ARMeilleure.Instructions } } + public static void Vpaddl(ArmEmitterContext context) + { + OpCode32Simd op = (OpCode32Simd)context.CurrOp; + + EmitVectorPairwiseLongOpI32(context, (op1, op2) => context.Add(op1, op2), (op.Opc & 1) == 0); + } + public static void Vpmax_V(ArmEmitterContext context) { if (Optimizations.FastFP && Optimizations.UseSse2) @@ -1014,7 +1028,7 @@ namespace ARMeilleure.Instructions } else { - EmitVectorPairwiseOpI32(context, (op1, op2) => + EmitVectorPairwiseOpI32(context, (op1, op2) => { Operand greater = op.U ? context.ICompareGreaterUI(op1, op2) : context.ICompareGreater(op1, op2); return context.ConditionalSelect(greater, op1, op2); @@ -1052,6 +1066,62 @@ namespace ARMeilleure.Instructions } } + public static void Vqadd(ArmEmitterContext context) + { + OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; + + EmitSaturatingAddSubBinaryOp(context, add: true, !op.U); + } + + public static void Vqdmulh(ArmEmitterContext context) + { + OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; + int eSize = 8 << op.Size; + + EmitVectorBinaryOpI32(context, (op1, op2) => + { + if (op.Size == 2) + { + op1 = context.SignExtend32(OperandType.I64, op1); + op2 = context.SignExtend32(OperandType.I64, op2); + } + + Operand res = context.Multiply(op1, op2); + res = context.ShiftRightSI(res, Const(eSize - 1)); + res = EmitSatQ(context, res, eSize, signedSrc: true, signedDst: true); + + if (op.Size == 2) + { + res = context.ConvertI64ToI32(res); + } + + return res; + }, signed: true); + } + + public static void Vqmovn(ArmEmitterContext context) + { + OpCode32SimdMovn op = (OpCode32SimdMovn)context.CurrOp; + + bool signed = !op.Q; + + EmitVectorUnaryNarrowOp32(context, (op1) => EmitSatQ(context, op1, 8 << op.Size, signed, signed), signed); + } + + public static void Vqmovun(ArmEmitterContext context) + { + OpCode32SimdMovn op = (OpCode32SimdMovn)context.CurrOp; + + EmitVectorUnaryNarrowOp32(context, (op1) => EmitSatQ(context, op1, 8 << op.Size, signedSrc: true, signedDst: false), signed: true); + } + + public static void Vqsub(ArmEmitterContext context) + { + OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; + + EmitSaturatingAddSubBinaryOp(context, add: false, !op.U); + } + public static void Vrev(ArmEmitterContext context) { OpCode32SimdRev op = (OpCode32SimdRev)context.CurrOp; @@ -1202,6 +1272,30 @@ namespace ARMeilleure.Instructions } } + public static void Vrhadd(ArmEmitterContext context) + { + OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; + + EmitVectorBinaryOpI32(context, (op1, op2) => + { + if (op.Size == 2) + { + op1 = context.ZeroExtend32(OperandType.I64, op1); + op2 = context.ZeroExtend32(OperandType.I64, op2); + } + + Operand res = context.Add(context.Add(op1, op2), Const(op1.Type, 1L)); + res = context.ShiftRightUI(res, Const(1)); + + if (op.Size == 2) + { + res = context.ConvertI64ToI32(res); + } + + return res; + }, !op.U); + } + public static void Vrsqrte(ArmEmitterContext context) { OpCode32SimdSqrte op = (OpCode32SimdSqrte)context.CurrOp; @@ -1349,6 +1443,13 @@ namespace ARMeilleure.Instructions } } + public static void Vsubl_I(ArmEmitterContext context) + { + OpCode32SimdRegLong op = (OpCode32SimdRegLong)context.CurrOp; + + EmitVectorBinaryLongOpI32(context, (op1, op2) => context.Subtract(op1, op2), !op.U); + } + public static void Vsubw_I(ArmEmitterContext context) { OpCode32SimdRegWide op = (OpCode32SimdRegWide)context.CurrOp; @@ -1356,6 +1457,46 @@ namespace ARMeilleure.Instructions EmitVectorBinaryWideOpI32(context, (op1, op2) => context.Subtract(op1, op2), !op.U); } + private static void EmitSaturatingAddSubBinaryOp(ArmEmitterContext context, bool add, bool signed) + { + OpCode32Simd op = (OpCode32Simd)context.CurrOp; + + EmitVectorBinaryOpI32(context, (ne, me) => + { + if (op.Size <= 2) + { + if (op.Size == 2) + { + ne = signed ? context.SignExtend32(OperandType.I64, ne) : context.ZeroExtend32(OperandType.I64, ne); + me = signed ? context.SignExtend32(OperandType.I64, me) : context.ZeroExtend32(OperandType.I64, me); + } + + Operand res = add ? context.Add(ne, me) : context.Subtract(ne, me); + + res = EmitSatQ(context, res, 8 << op.Size, signedSrc: true, signed); + + if (op.Size == 2) + { + res = context.ConvertI64ToI32(res); + } + + return res; + } + else if (add) /* if (op.Size == 3) */ + { + return signed + ? EmitBinarySignedSatQAdd(context, ne, me) + : EmitBinaryUnsignedSatQAdd(context, ne, me); + } + else /* if (sub) */ + { + return signed + ? EmitBinarySignedSatQSub(context, ne, me) + : EmitBinaryUnsignedSatQSub(context, ne, me); + } + }, signed); + } + private static void EmitSse41MaxMinNumOpF32(ArmEmitterContext context, bool isMaxNum, bool scalar) { IOpCode32Simd op = (IOpCode32Simd)context.CurrOp; diff --git a/ARMeilleure/Instructions/InstEmitSimdHelper.cs b/ARMeilleure/Instructions/InstEmitSimdHelper.cs index 805656d2..27b5c130 100644 --- a/ARMeilleure/Instructions/InstEmitSimdHelper.cs +++ b/ARMeilleure/Instructions/InstEmitSimdHelper.cs @@ -1281,7 +1281,7 @@ namespace ARMeilleure.Instructions public static void EmitSseOrAvxExitFtzAndDazModesOpF(ArmEmitterContext context, Operand isTrue = default) { - isTrue = isTrue == default + isTrue = isTrue == default ? context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz))) : isTrue; @@ -1612,7 +1612,7 @@ namespace ARMeilleure.Instructions } // long BinarySignedSatQAdd(long op1, long op2); - private static Operand EmitBinarySignedSatQAdd(ArmEmitterContext context, Operand op1, Operand op2) + public static Operand EmitBinarySignedSatQAdd(ArmEmitterContext context, Operand op1, Operand op2) { Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64); @@ -1639,7 +1639,7 @@ namespace ARMeilleure.Instructions } // ulong BinaryUnsignedSatQAdd(ulong op1, ulong op2); - private static Operand EmitBinaryUnsignedSatQAdd(ArmEmitterContext context, Operand op1, Operand op2) + public static Operand EmitBinaryUnsignedSatQAdd(ArmEmitterContext context, Operand op1, Operand op2) { Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64); @@ -1660,7 +1660,7 @@ namespace ARMeilleure.Instructions } // long BinarySignedSatQSub(long op1, long op2); - private static Operand EmitBinarySignedSatQSub(ArmEmitterContext context, Operand op1, Operand op2) + public static Operand EmitBinarySignedSatQSub(ArmEmitterContext context, Operand op1, Operand op2) { Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64); @@ -1687,7 +1687,7 @@ namespace ARMeilleure.Instructions } // ulong BinaryUnsignedSatQSub(ulong op1, ulong op2); - private static Operand EmitBinaryUnsignedSatQSub(ArmEmitterContext context, Operand op1, Operand op2) + public static Operand EmitBinaryUnsignedSatQSub(ArmEmitterContext context, Operand op1, Operand op2) { Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64); diff --git a/ARMeilleure/Instructions/InstEmitSimdHelper32.cs b/ARMeilleure/Instructions/InstEmitSimdHelper32.cs index 07ff481c..c530985f 100644 --- a/ARMeilleure/Instructions/InstEmitSimdHelper32.cs +++ b/ARMeilleure/Instructions/InstEmitSimdHelper32.cs @@ -219,6 +219,25 @@ namespace ARMeilleure.Instructions // Integer + public static void EmitVectorUnaryAccumulateOpI32(ArmEmitterContext context, Func1I emit, bool signed) + { + OpCode32Simd op = (OpCode32Simd)context.CurrOp; + + Operand res = GetVecA32(op.Qd); + + int elems = op.GetBytesCount() >> op.Size; + + for (int index = 0; index < elems; index++) + { + Operand de = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size, signed); + Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, signed); + + res = EmitVectorInsert(context, res, context.Add(de, emit(me)), op.Id + index, op.Size); + } + + context.Copy(GetVecA32(op.Qd), res); + } + public static void EmitVectorUnaryOpI32(ArmEmitterContext context, Func1I emit, bool signed) { OpCode32Simd op = (OpCode32Simd)context.CurrOp; @@ -385,6 +404,18 @@ namespace ARMeilleure.Instructions EmitVectorUnaryOpI32(context, emit, true); } + public static void EmitVectorUnaryOpSx32(ArmEmitterContext context, Func1I emit, bool accumulate) + { + if (accumulate) + { + EmitVectorUnaryAccumulateOpI32(context, emit, true); + } + else + { + EmitVectorUnaryOpI32(context, emit, true); + } + } + public static void EmitVectorBinaryOpSx32(ArmEmitterContext context, Func2I emit) { EmitVectorBinaryOpI32(context, emit, true); @@ -400,6 +431,18 @@ namespace ARMeilleure.Instructions EmitVectorUnaryOpI32(context, emit, false); } + public static void EmitVectorUnaryOpZx32(ArmEmitterContext context, Func1I emit, bool accumulate) + { + if (accumulate) + { + EmitVectorUnaryAccumulateOpI32(context, emit, false); + } + else + { + EmitVectorUnaryOpI32(context, emit, false); + } + } + public static void EmitVectorBinaryOpZx32(ArmEmitterContext context, Func2I emit) { EmitVectorBinaryOpI32(context, emit, false); @@ -592,6 +635,34 @@ namespace ARMeilleure.Instructions context.Copy(GetVecA32(op.Qd), res); } + public static void EmitVectorPairwiseLongOpI32(ArmEmitterContext context, Func2I emit, bool signed) + { + OpCode32Simd op = (OpCode32Simd)context.CurrOp; + + int elems = (op.Q ? 16 : 8) >> op.Size; + int pairs = elems >> 1; + int id = (op.Vd & 1) * pairs; + + Operand res = GetVecA32(op.Qd); + + for (int index = 0; index < pairs; index++) + { + int pairIndex = index << 1; + Operand m1 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex, op.Size, signed); + Operand m2 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex + 1, op.Size, signed); + + if (op.Size == 2) + { + m1 = signed ? context.SignExtend32(OperandType.I64, m1) : context.ZeroExtend32(OperandType.I64, m1); + m2 = signed ? context.SignExtend32(OperandType.I64, m2) : context.ZeroExtend32(OperandType.I64, m2); + } + + res = EmitVectorInsert(context, res, emit(m1, m2), id + index, op.Size + 1); + } + + context.Copy(GetVecA32(op.Qd), res); + } + // Narrow public static void EmitVectorUnaryNarrowOp32(ArmEmitterContext context, Func1I emit, bool signed = false) diff --git a/ARMeilleure/Instructions/InstEmitSimdShift32.cs b/ARMeilleure/Instructions/InstEmitSimdShift32.cs index 6dcfe065..e0968b7b 100644 --- a/ARMeilleure/Instructions/InstEmitSimdShift32.cs +++ b/ARMeilleure/Instructions/InstEmitSimdShift32.cs @@ -33,64 +33,24 @@ namespace ARMeilleure.Instructions EmitShrImmSaturatingNarrowOp(context, op.U ? ShrImmSaturatingNarrowFlags.VectorZxZx : ShrImmSaturatingNarrowFlags.VectorSxSx); } - public static void Vrshr(ArmEmitterContext context) + public static void Vqshrun(ArmEmitterContext context) { - OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp; - int shift = GetImmShr(op); - long roundConst = 1L << (shift - 1); - - if (op.U) - { - if (op.Size < 2) - { - EmitVectorUnaryOpZx32(context, (op1) => - { - op1 = context.Add(op1, Const(op1.Type, roundConst)); - - return context.ShiftRightUI(op1, Const(shift)); - }); - } - else if (op.Size == 2) - { - EmitVectorUnaryOpZx32(context, (op1) => - { - op1 = context.ZeroExtend32(OperandType.I64, op1); - op1 = context.Add(op1, Const(op1.Type, roundConst)); + EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx); + } - return context.ConvertI64ToI32(context.ShiftRightUI(op1, Const(shift))); - }); - } - else /* if (op.Size == 3) */ - { - EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: false, roundConst, shift)); - } - } - else - { - if (op.Size < 2) - { - EmitVectorUnaryOpSx32(context, (op1) => - { - op1 = context.Add(op1, Const(op1.Type, roundConst)); + public static void Vrshr(ArmEmitterContext context) + { + EmitRoundShrImmOp(context, accumulate: false); + } - return context.ShiftRightSI(op1, Const(shift)); - }); - } - else if (op.Size == 2) - { - EmitVectorUnaryOpSx32(context, (op1) => - { - op1 = context.SignExtend32(OperandType.I64, op1); - op1 = context.Add(op1, Const(op1.Type, roundConst)); + public static void Vrshrn(ArmEmitterContext context) + { + EmitRoundShrImmNarrowOp(context, signed: false); + } - return context.ConvertI64ToI32(context.ShiftRightSI(op1, Const(shift))); - }); - } - else /* if (op.Size == 3) */ - { - EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: true, roundConst, shift)); - } - } + public static void Vrsra(ArmEmitterContext context) + { + EmitRoundShrImmOp(context, accumulate: true); } public static void Vshl(ArmEmitterContext context) @@ -191,6 +151,89 @@ namespace ARMeilleure.Instructions } } + public static void EmitRoundShrImmOp(ArmEmitterContext context, bool accumulate) + { + OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp; + int shift = GetImmShr(op); + long roundConst = 1L << (shift - 1); + + if (op.U) + { + if (op.Size < 2) + { + EmitVectorUnaryOpZx32(context, (op1) => + { + op1 = context.Add(op1, Const(op1.Type, roundConst)); + + return context.ShiftRightUI(op1, Const(shift)); + }, accumulate); + } + else if (op.Size == 2) + { + EmitVectorUnaryOpZx32(context, (op1) => + { + op1 = context.ZeroExtend32(OperandType.I64, op1); + op1 = context.Add(op1, Const(op1.Type, roundConst)); + + return context.ConvertI64ToI32(context.ShiftRightUI(op1, Const(shift))); + }, accumulate); + } + else /* if (op.Size == 3) */ + { + EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: false, roundConst, shift), accumulate); + } + } + else + { + if (op.Size < 2) + { + EmitVectorUnaryOpSx32(context, (op1) => + { + op1 = context.Add(op1, Const(op1.Type, roundConst)); + + return context.ShiftRightSI(op1, Const(shift)); + }, accumulate); + } + else if (op.Size == 2) + { + EmitVectorUnaryOpSx32(context, (op1) => + { + op1 = context.SignExtend32(OperandType.I64, op1); + op1 = context.Add(op1, Const(op1.Type, roundConst)); + + return context.ConvertI64ToI32(context.ShiftRightSI(op1, Const(shift))); + }, accumulate); + } + else /* if (op.Size == 3) */ + { + EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: true, roundConst, shift), accumulate); + } + } + } + + private static void EmitRoundShrImmNarrowOp(ArmEmitterContext context, bool signed) + { + OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp; + + int shift = GetImmShr(op); + long roundConst = 1L << (shift - 1); + + EmitVectorUnaryNarrowOp32(context, (op1) => + { + if (op.Size <= 1) + { + op1 = context.Add(op1, Const(op1.Type, roundConst)); + op1 = signed ? context.ShiftRightSI(op1, Const(shift)) : context.ShiftRightUI(op1, Const(shift)); + } + else /* if (op.Size == 2 && round) */ + { + op1 = EmitShrImm64(context, op1, signed, roundConst, shift); // shift <= 32 + } + + return op1; + }, signed); + } + private static Operand EmitShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size, bool unsigned) { if (shiftLsB.Type == OperandType.I64) @@ -289,7 +332,7 @@ namespace ARMeilleure.Instructions op1 = EmitShrImm64(context, op1, signedSrc, roundConst, shift); // shift <= 32 } - return EmitSatQ(context, op1, 8 << op.Size, signedDst); + return EmitSatQ(context, op1, 8 << op.Size, signedSrc, signedDst); }, signedSrc); } @@ -313,15 +356,20 @@ namespace ARMeilleure.Instructions return context.Call(info, value, Const(roundConst), Const(shift)); } - private static Operand EmitSatQ(ArmEmitterContext context, Operand value, int eSize, bool signed) + private static Operand EmitSatQ(ArmEmitterContext context, Operand value, int eSize, bool signedSrc, bool signedDst) { Debug.Assert(eSize <= 32); - long intMin = signed ? -(1L << (eSize - 1)) : 0; - long intMax = signed ? (1L << (eSize - 1)) - 1 : (1L << eSize) - 1; + long intMin = signedDst ? -(1L << (eSize - 1)) : 0; + long intMax = signedDst ? (1L << (eSize - 1)) - 1 : (1L << eSize) - 1; + + Operand gt = signedSrc + ? context.ICompareGreater(value, Const(value.Type, intMax)) + : context.ICompareGreaterUI(value, Const(value.Type, intMax)); - Operand gt = context.ICompareGreater(value, Const(value.Type, intMax)); - Operand lt = context.ICompareLess(value, Const(value.Type, intMin)); + Operand lt = signedSrc + ? context.ICompareLess(value, Const(value.Type, intMin)) + : context.ICompareLessUI(value, Const(value.Type, intMin)); value = context.ConditionalSelect(gt, Const(value.Type, intMax), value); value = context.ConditionalSelect(lt, Const(value.Type, intMin), value); diff --git a/ARMeilleure/Instructions/InstEmitSystem32.cs b/ARMeilleure/Instructions/InstEmitSystem32.cs index 674a4438..acd17045 100644 --- a/ARMeilleure/Instructions/InstEmitSystem32.cs +++ b/ARMeilleure/Instructions/InstEmitSystem32.cs @@ -16,18 +16,13 @@ namespace ARMeilleure.Instructions { OpCode32System op = (OpCode32System)context.CurrOp; - if (op.Coproc != 15) + if (op.Coproc != 15 || op.Opc1 != 0) { InstEmit.Und(context); return; } - if (op.Opc1 != 0) - { - throw new NotImplementedException($"Unknown MRC Opc1 0x{op.Opc1:X16} at 0x{op.Address:X16}."); - } - MethodInfo info; switch (op.CRn) @@ -35,7 +30,7 @@ namespace ARMeilleure.Instructions case 13: // Process and Thread Info. if (op.CRm != 0) { - throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}."); + throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X} at 0x{op.Address:X} (0x{op.RawOpCode:X})."); } switch (op.Opc2) @@ -44,7 +39,7 @@ namespace ARMeilleure.Instructions info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032)); break; default: - throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}."); + throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X})."); } break; @@ -59,11 +54,11 @@ namespace ARMeilleure.Instructions return; // No-op. default: - throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}."); + throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16} (0x{op.RawOpCode:X})."); } default: - throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}."); + throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16} (0x{op.RawOpCode:X})."); } default: @@ -77,18 +72,13 @@ namespace ARMeilleure.Instructions { OpCode32System op = (OpCode32System)context.CurrOp; - if (op.Coproc != 15) + if (op.Coproc != 15 || op.Opc1 != 0) { InstEmit.Und(context); return; } - if (op.Opc1 != 0) - { - throw new NotImplementedException($"Unknown MRC Opc1 0x{op.Opc1:X16} at 0x{op.Address:X16}."); - } - MethodInfo info; switch (op.CRn) @@ -96,7 +86,7 @@ namespace ARMeilleure.Instructions case 13: // Process and Thread Info. if (op.CRm != 0) { - throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}."); + throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X} at 0x{op.Address:X} (0x{op.RawOpCode:X})."); } switch (op.Opc2) @@ -108,13 +98,13 @@ namespace ARMeilleure.Instructions info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidr32)); break; default: - throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}."); + throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X})."); } break; default: - throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); + throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X} at 0x{op.Address:X}."); } if (op.Rt == RegisterAlias.Aarch32Pc) @@ -154,13 +144,13 @@ namespace ARMeilleure.Instructions info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)); break; default: - throw new NotImplementedException($"Unknown MRRC Opc1 0x{opc:X16} at 0x{op.Address:X16}."); + throw new NotImplementedException($"Unknown MRRC Opc1 0x{opc:X} at 0x{op.Address:X} (0x{op.RawOpCode:X})."); } break; default: - throw new NotImplementedException($"Unknown MRRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); + throw new NotImplementedException($"Unknown MRRC 0x{op.RawOpCode:X} at 0x{op.Address:X}."); } Operand result = context.Call(info); @@ -265,7 +255,7 @@ namespace ARMeilleure.Instructions case 0b1000: // FPEXC throw new NotImplementedException("Supervisor Only"); default: - throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); + throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X} at 0x{op.Address:X}."); } } @@ -288,7 +278,7 @@ namespace ARMeilleure.Instructions case 0b1000: // FPEXC throw new NotImplementedException("Supervisor Only"); default: - throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); + throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X} at 0x{op.Address:X}."); } } diff --git a/ARMeilleure/Instructions/InstName.cs b/ARMeilleure/Instructions/InstName.cs index c667ba5f..0d63820b 100644 --- a/ARMeilleure/Instructions/InstName.cs +++ b/ARMeilleure/Instructions/InstName.cs @@ -601,6 +601,7 @@ namespace ARMeilleure.Instructions Vmin, Vminnm, Vmla, + Vmlal, Vmls, Vmlsl, Vmov, @@ -618,15 +619,24 @@ namespace ARMeilleure.Instructions Vorn, Vorr, Vpadd, + Vpaddl, Vpmax, Vpmin, + Vqadd, + Vqdmulh, + Vqmovn, + Vqmovun, Vqrshrn, Vqrshrun, Vqshrn, + Vqshrun, + Vqsub, Vrev, + Vrhadd, Vrint, Vrintx, Vrshr, + Vrshrn, Vsel, Vshl, Vshll, @@ -643,8 +653,10 @@ namespace ARMeilleure.Instructions Vrecps, Vrsqrte, Vrsqrts, + Vrsra, Vsra, Vsub, + Vsubl, Vsubw, Vtbl, Vtrn, |
