diff --git a/ARMeilleure/Decoders/DecoderHelper.cs b/ARMeilleure/Decoders/DecoderHelper.cs index bc41c61c6a..d949cdc6d0 100644 --- a/ARMeilleure/Decoders/DecoderHelper.cs +++ b/ARMeilleure/Decoders/DecoderHelper.cs @@ -10,7 +10,7 @@ namespace ARMeilleure.Decoders Imm8ToFP64Table = BuildImm8ToFP64Table(); } - public static readonly uint[] Imm8ToFP32Table; + public static readonly uint[] Imm8ToFP32Table; public static readonly ulong[] Imm8ToFP64Table; private static uint[] BuildImm8ToFP32Table() @@ -46,11 +46,11 @@ namespace ARMeilleure.Decoders } return MoveBit(imm, 7, 31) | MoveBit(~imm, 6, 30) | - MoveBit(imm, 6, 29) | MoveBit( imm, 6, 28) | - MoveBit(imm, 6, 27) | MoveBit( imm, 6, 26) | - MoveBit(imm, 6, 25) | MoveBit( imm, 5, 24) | - MoveBit(imm, 4, 23) | MoveBit( imm, 3, 22) | - MoveBit(imm, 2, 21) | MoveBit( imm, 1, 20) | + MoveBit(imm, 6, 29) | MoveBit(imm, 6, 28) | + MoveBit(imm, 6, 27) | MoveBit(imm, 6, 26) | + MoveBit(imm, 6, 25) | MoveBit(imm, 5, 24) | + MoveBit(imm, 4, 23) | MoveBit(imm, 3, 22) | + MoveBit(imm, 2, 21) | MoveBit(imm, 1, 20) | MoveBit(imm, 0, 19); } @@ -63,21 +63,21 @@ namespace ARMeilleure.Decoders } return MoveBit(imm, 7, 63) | MoveBit(~imm, 6, 62) | - MoveBit(imm, 6, 61) | MoveBit( imm, 6, 60) | - MoveBit(imm, 6, 59) | MoveBit( imm, 6, 58) | - MoveBit(imm, 6, 57) | MoveBit( imm, 6, 56) | - MoveBit(imm, 6, 55) | MoveBit( imm, 6, 54) | - MoveBit(imm, 5, 53) | MoveBit( imm, 4, 52) | - MoveBit(imm, 3, 51) | MoveBit( imm, 2, 50) | - MoveBit(imm, 1, 49) | MoveBit( imm, 0, 48); + MoveBit(imm, 6, 61) | MoveBit(imm, 6, 60) | + MoveBit(imm, 6, 59) | MoveBit(imm, 6, 58) | + MoveBit(imm, 6, 57) | MoveBit(imm, 6, 56) | + MoveBit(imm, 6, 55) | MoveBit(imm, 6, 54) | + MoveBit(imm, 5, 53) | MoveBit(imm, 4, 52) | + MoveBit(imm, 3, 51) | MoveBit(imm, 2, 50) | + MoveBit(imm, 1, 49) | MoveBit(imm, 0, 48); } public struct BitMask { public long WMask; public long TMask; - public int Pos; - public int Shift; + public int Pos; + public int Shift; public bool IsUndefined; public static BitMask Invalid => new BitMask { IsUndefined = true }; @@ -88,7 +88,7 @@ namespace ARMeilleure.Decoders int immS = (opCode >> 10) & 0x3f; int immR = (opCode >> 16) & 0x3f; - int n = (opCode >> 22) & 1; + int n = (opCode >> 22) & 1; int sf = (opCode >> 31) & 1; int length = BitUtils.HighestBitSet((~immS & 0x3f) | (n << 6)); @@ -115,7 +115,7 @@ namespace ARMeilleure.Decoders if (r > 0) { - wMask = BitUtils.RotateRight(wMask, r, size); + wMask = BitUtils.RotateRight(wMask, r, size); wMask &= BitUtils.FillWithOnes(size); } @@ -124,7 +124,7 @@ namespace ARMeilleure.Decoders WMask = BitUtils.Replicate(wMask, size), TMask = BitUtils.Replicate(tMask, size), - Pos = immS, + Pos = immS, Shift = immR }; } @@ -148,5 +148,19 @@ namespace ARMeilleure.Decoders { return (((long)opCode << 45) >> 48) & ~3; } + + public static bool VectorArgumentsInvalid(bool q, params int[] args) + { + if (q) { + for (int i = 0; i < args.Length; i++) + { + if ((args[i] & 1) == 1) + { + return true; + } + } + } + return false; + } } } \ No newline at end of file diff --git a/ARMeilleure/Decoders/OpCode32Simd.cs b/ARMeilleure/Decoders/OpCode32Simd.cs index 558b67dc48..a40098b190 100644 --- a/ARMeilleure/Decoders/OpCode32Simd.cs +++ b/ARMeilleure/Decoders/OpCode32Simd.cs @@ -23,6 +23,11 @@ namespace ARMeilleure.Decoders Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf); Vm = ((opCode >> 1) & 0x10) | ((opCode >> 0) & 0xf); + + if (this.GetType() == typeof(OpCode32Simd)) // subclasses have their own handling of Vx to account for before checking! + { + DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm); + } } } } diff --git a/ARMeilleure/Decoders/OpCode32SimdBinary.cs b/ARMeilleure/Decoders/OpCode32SimdBinary.cs index 9c94d111e5..fe0ec8ad10 100644 --- a/ARMeilleure/Decoders/OpCode32SimdBinary.cs +++ b/ARMeilleure/Decoders/OpCode32SimdBinary.cs @@ -12,6 +12,10 @@ namespace ARMeilleure.Decoders public OpCode32SimdBinary(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { Size = 3; + if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm, Vn)) + { + Instruction = InstDescriptor.Undefined; + } } } } diff --git a/ARMeilleure/Decoders/OpCode32SimdCmpZ.cs b/ARMeilleure/Decoders/OpCode32SimdCmpZ.cs index 157a516af2..eb5b08692f 100644 --- a/ARMeilleure/Decoders/OpCode32SimdCmpZ.cs +++ b/ARMeilleure/Decoders/OpCode32SimdCmpZ.cs @@ -9,6 +9,11 @@ namespace ARMeilleure.Decoders public OpCode32SimdCmpZ(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { Size = (opCode >> 18) & 0x3; //fvector size: 1 for 16 bit + + if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm)) + { + Instruction = InstDescriptor.Undefined; + } } } } diff --git a/ARMeilleure/Decoders/OpCode32SimdDupElem.cs b/ARMeilleure/Decoders/OpCode32SimdDupElem.cs index 3c1683f82b..a34f59cc84 100644 --- a/ARMeilleure/Decoders/OpCode32SimdDupElem.cs +++ b/ARMeilleure/Decoders/OpCode32SimdDupElem.cs @@ -4,10 +4,8 @@ using System.Text; namespace ARMeilleure.Decoders { - class OpCode32SimdDupElem : BaseOpCode32Simd + class OpCode32SimdDupElem : OpCode32Simd { - public bool Q { get; private set; } - public int Index { get; private set; } public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) @@ -31,13 +29,18 @@ namespace ARMeilleure.Decoders } else { - throw new Exception("Undefined"); + Instruction = InstDescriptor.Undefined; } Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf); Vm = ((opCode >> 1) & 0x10) | ((opCode >> 0) & 0xf); Q = (opCode & (1 << 6)) != 0; if (Q) RegisterSize = RegisterSize.Simd128; + + if (DecoderHelper.VectorArgumentsInvalid(Q, Vd)) + { + Instruction = InstDescriptor.Undefined; + } } } } diff --git a/ARMeilleure/Decoders/OpCode32SimdVdupGP.cs b/ARMeilleure/Decoders/OpCode32SimdDupGP.cs similarity index 60% rename from ARMeilleure/Decoders/OpCode32SimdVdupGP.cs rename to ARMeilleure/Decoders/OpCode32SimdDupGP.cs index 418b0a30dc..ca85143ab6 100644 --- a/ARMeilleure/Decoders/OpCode32SimdVdupGP.cs +++ b/ARMeilleure/Decoders/OpCode32SimdDupGP.cs @@ -4,23 +4,31 @@ using System.Text; namespace ARMeilleure.Decoders { - class OpCode32SimdVdupGP : OpCode32, IOpCode32Simd + class OpCode32SimdDupGP : OpCode32, IOpCode32Simd { - public int Elems => GetBytesCount() >> ((Size == 1) ? 1 : 2); public int Size { get; private set; } public int Vd { get; private set; } public int Rt { get; private set; } public bool Q { get; private set; } - public OpCode32SimdVdupGP(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + public OpCode32SimdDupGP(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { Size = 2 - (((opCode >> 21) & 0x2) | ((opCode >> 5) & 0x1)); //B:E - 0 for 32, 16 then 8. + if (Size == -1) + { + Instruction = InstDescriptor.Undefined; + } Q = ((opCode >> 21) & 0x1) != 0; RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64; Vd = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf); Rt = ((opCode >> 12) & 0xf); + + if (DecoderHelper.VectorArgumentsInvalid(Q, Vd)) + { + Instruction = InstDescriptor.Undefined; + } } } } diff --git a/ARMeilleure/Decoders/OpCode32SimdExt.cs b/ARMeilleure/Decoders/OpCode32SimdExt.cs new file mode 100644 index 0000000000..a2c82bfcb4 --- /dev/null +++ b/ARMeilleure/Decoders/OpCode32SimdExt.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ARMeilleure.Decoders +{ + class OpCode32SimdExt : OpCode32SimdReg + { + public int Immediate { get; private set; } + public OpCode32SimdExt(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Immediate = (opCode >> 8) & 0xf; + Size = 0; + if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm, Vn) || (!Q && Immediate > 7)) + { + Instruction = InstDescriptor.Undefined; + } + } + } +} diff --git a/ARMeilleure/Decoders/OpCode32SimdImm.cs b/ARMeilleure/Decoders/OpCode32SimdImm.cs index 9929369ac4..6aaa8af67b 100644 --- a/ARMeilleure/Decoders/OpCode32SimdImm.cs +++ b/ARMeilleure/Decoders/OpCode32SimdImm.cs @@ -33,6 +33,11 @@ namespace ARMeilleure.Decoders Size = parsedImm.Item2; RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64; + + if (DecoderHelper.VectorArgumentsInvalid(Q, Vd)) + { + Instruction = InstDescriptor.Undefined; + } } } } diff --git a/ARMeilleure/Decoders/OpCode32SimdImm6.cs b/ARMeilleure/Decoders/OpCode32SimdImm6.cs index a378849d8c..184af7eaa3 100644 --- a/ARMeilleure/Decoders/OpCode32SimdImm6.cs +++ b/ARMeilleure/Decoders/OpCode32SimdImm6.cs @@ -35,7 +35,12 @@ namespace ARMeilleure.Decoders } else { - throw new Exception("Unknown Encoding"); + Instruction = InstDescriptor.Undefined; + } + + if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm)) + { + Instruction = InstDescriptor.Undefined; } } } diff --git a/ARMeilleure/Decoders/OpCode32SimdMemImm.cs b/ARMeilleure/Decoders/OpCode32SimdMemImm.cs index 1863c7398e..6951603dd7 100644 --- a/ARMeilleure/Decoders/OpCode32SimdMemImm.cs +++ b/ARMeilleure/Decoders/OpCode32SimdMemImm.cs @@ -11,7 +11,6 @@ namespace ARMeilleure.Decoders public int Size { get; private set; } public bool Add { get; private set; } public int Immediate { get; private set; } - public int Elems => 1; public OpCode32SimdMemImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { @@ -27,8 +26,6 @@ namespace ARMeilleure.Decoders var single = Size != 0b11; - //RegisterSize = single ? RegisterSize.Simd32 : RegisterSize.Simd64; - if (single) { Vd = ((opCode >> 22) & 0x1) | ((opCode >> 11) & 0x1e); diff --git a/ARMeilleure/Decoders/OpCode32SimdMemMult.cs b/ARMeilleure/Decoders/OpCode32SimdMemMult.cs index 3e2a3bf7ff..4449e59ed8 100644 --- a/ARMeilleure/Decoders/OpCode32SimdMemMult.cs +++ b/ARMeilleure/Decoders/OpCode32SimdMemMult.cs @@ -9,13 +9,10 @@ namespace ARMeilleure.Decoders public int Rn { get; private set; } public int Vd { get; private set; } - public int RegisterRange - { get; private set; } + public int RegisterRange { get; private set; } public int Offset { get; private set; } public int PostOffset { get; private set; } - public bool IsLoad { get; private set; } - public bool DoubleWidth { get; private set; } public bool Add { get; private set; } @@ -28,6 +25,11 @@ namespace ARMeilleure.Decoders bool u = (opCode & (1 << 23)) != 0; bool p = (opCode & (1 << 24)) != 0; + if (p == u && w) + { + Instruction = InstDescriptor.Undefined; + } + DoubleWidth = (opCode & (1 << 8)) != 0; if (!DoubleWidth) @@ -60,6 +62,13 @@ namespace ARMeilleure.Decoders } IsLoad = isLoad; + + int regs = DoubleWidth ? RegisterRange / 2 : RegisterRange; + + if (RegisterRange == 0 || RegisterRange > 32 || Vd + regs > 32) + { + Instruction = InstDescriptor.Undefined; + } } } } diff --git a/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs b/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs index a163185a60..6c80bf31a8 100644 --- a/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs +++ b/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs @@ -15,7 +15,6 @@ namespace ARMeilleure.Decoders public bool RegisterIndex { get; private set; } public int Size { get; private set; } public bool Replicate { get; private set; } - public int Elems => GetBytesCount() >> Size; public int Increment { get; private set; } public OpCode32SimdMemSingle(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { diff --git a/ARMeilleure/Decoders/OpCode32SimdMovGp.cs b/ARMeilleure/Decoders/OpCode32SimdMovGp.cs index 88b859b3d0..2b8e92dad6 100644 --- a/ARMeilleure/Decoders/OpCode32SimdMovGp.cs +++ b/ARMeilleure/Decoders/OpCode32SimdMovGp.cs @@ -7,7 +7,6 @@ namespace ARMeilleure.Decoders class OpCode32SimdMovGp : OpCode32, IOpCode32Simd { public int Size => 2; - public int Elems => 1; public int Vn { get; private set; } public int Rt { get; private set; } diff --git a/ARMeilleure/Decoders/OpCode32SimdMovGpDouble.cs b/ARMeilleure/Decoders/OpCode32SimdMovGpDouble.cs index f83d70a0a3..dc7eb7a438 100644 --- a/ARMeilleure/Decoders/OpCode32SimdMovGpDouble.cs +++ b/ARMeilleure/Decoders/OpCode32SimdMovGpDouble.cs @@ -7,7 +7,6 @@ namespace ARMeilleure.Decoders class OpCode32SimdMovGpDouble : OpCode32, IOpCode32Simd { public int Size => 3; - public int Elems => 1; public int Vm { get; private set; } public int Rt { get; private set; } diff --git a/ARMeilleure/Decoders/OpCode32SimdMovGpElem.cs b/ARMeilleure/Decoders/OpCode32SimdMovGpElem.cs index b94fa5e193..1110a7d369 100644 --- a/ARMeilleure/Decoders/OpCode32SimdMovGpElem.cs +++ b/ARMeilleure/Decoders/OpCode32SimdMovGpElem.cs @@ -7,7 +7,6 @@ namespace ARMeilleure.Decoders class OpCode32SimdMovGpElem : OpCode32, IOpCode32Simd { public int Size { get; private set; } - public int Elems => 1; public int Vd { get; private set; } public int Rt { get; private set; } @@ -41,7 +40,7 @@ namespace ARMeilleure.Decoders } else { - throw new Exception("Undefined"); + Instruction = InstDescriptor.Undefined; } Vd = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf); diff --git a/ARMeilleure/Decoders/OpCode32SimdReg.cs b/ARMeilleure/Decoders/OpCode32SimdReg.cs index 7a1351a075..9e286d7e9b 100644 --- a/ARMeilleure/Decoders/OpCode32SimdReg.cs +++ b/ARMeilleure/Decoders/OpCode32SimdReg.cs @@ -15,6 +15,12 @@ namespace ARMeilleure.Decoders public OpCode32SimdReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { Vn = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf); + + // subclasses have their own handling of Vx to account for before checking! + if (this.GetType() == typeof(OpCode32SimdReg) && DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm, Vn)) + { + Instruction = InstDescriptor.Undefined; + } } } } diff --git a/ARMeilleure/Decoders/OpCode32SimdRegElem.cs b/ARMeilleure/Decoders/OpCode32SimdRegElem.cs index e4599def9b..df4bbe058f 100644 --- a/ARMeilleure/Decoders/OpCode32SimdRegElem.cs +++ b/ARMeilleure/Decoders/OpCode32SimdRegElem.cs @@ -14,9 +14,12 @@ namespace ARMeilleure.Decoders RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64; - if (Size == 0b11) throw new Exception("Unknown Encoding!"); - Vm = ((opCode >> 5) & 0x1) | ((opCode << 1) & 0x1e); + + if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vn) || (Size == 0 || (Size == 1 && F))) + { + Instruction = InstDescriptor.Undefined; + } } } } diff --git a/ARMeilleure/Decoders/OpCode32SimdS.cs b/ARMeilleure/Decoders/OpCode32SimdS.cs index 4e4bae55ff..ac6e041cc4 100644 --- a/ARMeilleure/Decoders/OpCode32SimdS.cs +++ b/ARMeilleure/Decoders/OpCode32SimdS.cs @@ -10,8 +10,6 @@ namespace ARMeilleure.Decoders public int Vm { get; private set; } public int Opc { get; protected set; } public int Size { get; protected set; } - public bool Q { get; private set; } - public int Elems => 1; public OpCode32SimdS(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { diff --git a/ARMeilleure/Decoders/OpCode32SimdSqrte.cs b/ARMeilleure/Decoders/OpCode32SimdSqrte.cs index a5b8ff3d5a..fe8cac1085 100644 --- a/ARMeilleure/Decoders/OpCode32SimdSqrte.cs +++ b/ARMeilleure/Decoders/OpCode32SimdSqrte.cs @@ -10,6 +10,11 @@ namespace ARMeilleure.Decoders { Size = (opCode >> 18) & 0x1; //fvector size: 1 for 16 bit F = ((opCode >> 8) & 0x1) != 0; + + if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm)) + { + Instruction = InstDescriptor.Undefined; + } } } } diff --git a/ARMeilleure/Decoders/OpCode32SimdTbl.cs b/ARMeilleure/Decoders/OpCode32SimdTbl.cs index ef18ce76bb..bf9f3ef8ed 100644 --- a/ARMeilleure/Decoders/OpCode32SimdTbl.cs +++ b/ARMeilleure/Decoders/OpCode32SimdTbl.cs @@ -7,6 +7,7 @@ namespace ARMeilleure.Decoders class OpCode32SimdTbl : OpCode32SimdReg { public int Length { get; private set; } + public OpCode32SimdTbl(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { Length = (opCode >> 8) & 3; @@ -14,6 +15,11 @@ namespace ARMeilleure.Decoders Opc = Q ? 1 : 0; Q = false; RegisterSize = RegisterSize.Simd64; + + if (Vn + Length + 1 > 32) + { + Instruction = InstDescriptor.Undefined; + } } } } diff --git a/ARMeilleure/Decoders/OpCode32SimdVext.cs b/ARMeilleure/Decoders/OpCode32SimdVext.cs deleted file mode 100644 index c378f095c2..0000000000 --- a/ARMeilleure/Decoders/OpCode32SimdVext.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace ARMeilleure.Decoders -{ - class OpCode32SimdVext : OpCode32SimdReg - { - public int Immediate { get; private set; } - public OpCode32SimdVext(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) - { - Immediate = (opCode >> 8) & 0xf; - Size = 0; - } - } -} diff --git a/ARMeilleure/Decoders/OpCode32System.cs b/ARMeilleure/Decoders/OpCode32System.cs index 0e4b4e8ea4..8721834466 100644 --- a/ARMeilleure/Decoders/OpCode32System.cs +++ b/ARMeilleure/Decoders/OpCode32System.cs @@ -6,13 +6,14 @@ namespace ARMeilleure.Decoders { class OpCode32System : OpCode32 { - public int Opc1 { get; internal set; } - public int CRn { get; internal set; } - public int Rt { get; internal set; } - public int Opc2 { get; internal set; } - public int CRm { get; internal set; } + public int Opc1 { get; private set; } + public int CRn { get; private set; } + public int Rt { get; private set; } + public int Opc2 { get; private set; } + public int CRm { get; private set; } + public int MrrcOp { get; private set; } - public int Coproc { get; internal set; } + public int Coproc { get; private set; } public OpCode32System(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { @@ -21,6 +22,7 @@ namespace ARMeilleure.Decoders Rt = (opCode >> 12) & 0xf; Opc2 = (opCode >> 5) & 0x7; CRm = (opCode >> 0) & 0xf; + MrrcOp = (opCode >> 4) & 0xf; Coproc = (opCode >> 8) & 0xf; } diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index 9f00d6928f..1c102b4de0 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -781,10 +781,10 @@ namespace ARMeilleure.Decoders SetA32("111111101x1111xxxxxx10>>x1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_R, typeof(OpCode32SimdCvtFI)); // the many fp32 to int encodings (fp) SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, typeof(OpCode32SimdRegS)); - SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, typeof(OpCode32SimdVdupGP)); + SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, typeof(OpCode32SimdDupGP)); SetA32("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, typeof(OpCode32SimdDupElem)); - SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, typeof(OpCode32SimdVext)); + SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, typeof(OpCode32SimdExt)); SetA32("111101001x10xxxxxxxxxx00xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemSingle)); SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); //regs = 1 @@ -818,7 +818,8 @@ namespace ARMeilleure.Decoders SetA32("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, typeof(OpCode32SimdReg)); SetA32("1111001x0x<>xxx0xxxx", InstName.VMMmn, InstEmit32.VmaxminNm_S, typeof(OpCode32SimdRegS)); + SetA32("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.VMMmn, InstEmit32.VmaxNm_S, typeof(OpCode32SimdRegS)); + SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.VMMmn, InstEmit32.VminNm_S, typeof(OpCode32SimdRegS)); SetA32("111100110xxxxxxxxxxx1111xxx1xxxx", InstName.VMMmn, InstEmit32.VmaxminNm_V, typeof(OpCode32SimdReg)); SetA32("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, typeof(OpCode32SimdRegS)); diff --git a/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs b/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs index b8967ad2c5..a6bac7be8a 100644 --- a/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs +++ b/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs @@ -55,7 +55,7 @@ namespace ARMeilleure.Instructions public static void Vdup(ArmEmitterContext context) { - OpCode32SimdVdupGP op = (OpCode32SimdVdupGP)context.CurrOp; + OpCode32SimdDupGP op = (OpCode32SimdDupGP)context.CurrOp; Operand insert = GetIntA32(context, op.Rt); @@ -112,7 +112,7 @@ namespace ARMeilleure.Instructions } public static void Vext(ArmEmitterContext context) { - OpCode32SimdVext op = (OpCode32SimdVext)context.CurrOp; + OpCode32SimdExt op = (OpCode32SimdExt)context.CurrOp; int elems = op.GetBytesCount(); int byteOff = op.Immediate; @@ -217,18 +217,20 @@ namespace ARMeilleure.Instructions } } - public static void VmaxminNm_S(ArmEmitterContext context) + public static void VmaxNm_S(ArmEmitterContext context) { - bool max = (context.CurrOp.RawOpCode & (1 << 6)) == 0; - _F32_F32_F32 f32 = max ? new _F32_F32_F32(SoftFloat32.FPMaxNum) : new _F32_F32_F32(SoftFloat32.FPMinNum); - _F64_F64_F64 f64 = max ? new _F64_F64_F64(SoftFloat64.FPMaxNum) : new _F64_F64_F64(SoftFloat64.FPMinNum); + EmitScalarBinaryOpF32(context, (op1, op2) => EmitSoftFloatCall(context, SoftFloat32.FPMaxNum, SoftFloat64.FPMaxNum, op1, op2)); + } - EmitScalarBinaryOpF32(context, (op1, op2) => EmitSoftFloatCall(context, f32, f64, op1, op2)); + public static void VminNm_S(ArmEmitterContext context) + { + EmitScalarBinaryOpF32(context, (op1, op2) => EmitSoftFloatCall(context, SoftFloat32.FPMinNum, SoftFloat64.FPMinNum, op1, op2)); } public static void VmaxminNm_V(ArmEmitterContext context) { - bool max = (context.CurrOp.RawOpCode & (1 << 21)) == 0; + OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; + bool max = (op.Size & 2) == 0; // op is high bit of size (not used for fp) _F32_F32_F32_Bool f32 = max ? new _F32_F32_F32_Bool(SoftFloat32.FPMaxNumFpscr) : new _F32_F32_F32_Bool(SoftFloat32.FPMinNumFpscr); _F64_F64_F64_Bool f64 = max ? new _F64_F64_F64_Bool(SoftFloat64.FPMaxNumFpscr) : new _F64_F64_F64_Bool(SoftFloat64.FPMinNumFpscr); @@ -309,7 +311,7 @@ namespace ARMeilleure.Instructions public static void Vmul_I(ArmEmitterContext context) { - if (((context.CurrOp.RawOpCode >> 24) & 1) != 0) throw new Exception("Polynomial mode not supported"); + if ((context.CurrOp as OpCode32SimdReg).U) throw new NotImplementedException("Polynomial mode not implemented"); EmitVectorBinaryOpSx32(context, (op1, op2) => context.Multiply(op1, op2)); } diff --git a/ARMeilleure/Instructions/InstEmitSimdCmp32.cs b/ARMeilleure/Instructions/InstEmitSimdCmp32.cs index bb119d9f47..2e8528d75c 100644 --- a/ARMeilleure/Instructions/InstEmitSimdCmp32.cs +++ b/ARMeilleure/Instructions/InstEmitSimdCmp32.cs @@ -202,7 +202,7 @@ namespace ARMeilleure.Instructions { OpCode32SimdS op = (OpCode32SimdS)context.CurrOp; - bool cmpWithZero = (op.RawOpCode & (1 << 16)) != 0; + bool cmpWithZero = (op.Opc & 2) != 0; { int fSize = op.Size & 1; OperandType type = fSize != 0 ? OperandType.FP64 : OperandType.FP32; diff --git a/ARMeilleure/Instructions/InstEmitSystem32.cs b/ARMeilleure/Instructions/InstEmitSystem32.cs index 4795ae9b09..f917f27237 100644 --- a/ARMeilleure/Instructions/InstEmitSystem32.cs +++ b/ARMeilleure/Instructions/InstEmitSystem32.cs @@ -56,11 +56,11 @@ namespace ARMeilleure.Instructions case 0b0001: //FPSCR dlg = new _Void_U32(NativeInterface.SetFpscr); break; case 0b0101: //MVFR2 - throw new Exception("MVFR2"); + throw new NotImplementedException("MVFR2"); case 0b0110: //MVFR1 - throw new Exception("MVFR1"); + throw new NotImplementedException("MVFR1"); case 0b0111: //MVFR0 - throw new Exception("MVFR0"); + throw new NotImplementedException("MVFR0"); case 0b1000: //FPEXC throw new NotImplementedException("Supervisor Only"); default: throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); @@ -154,7 +154,6 @@ namespace ARMeilleure.Instructions switch (op.Opc2) { case 5: // Data Memory Barrier Register - return; // SUPER TODO: DO NOT KNOW HOW TO IMPLEMENT THIS default: throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}."); } @@ -197,7 +196,7 @@ namespace ARMeilleure.Instructions throw new NotImplementedException($"Unknown MRC Coprocessor ID 0x{op.Coproc:X16} at 0x{op.Address:X16}."); } - var opc = (op.RawOpCode >> 4) & 0xf; + var opc = op.MrrcOp; Delegate dlg; switch (op.CRm)