diff --git a/Disarm.Tests/LoadStoreTests.cs b/Disarm.Tests/LoadStoreTests.cs index 6163134..92a1294 100644 --- a/Disarm.Tests/LoadStoreTests.cs +++ b/Disarm.Tests/LoadStoreTests.cs @@ -35,8 +35,46 @@ public void LoadRegFromMemImmPostIndex() Assert.Equal(Arm64OperandKind.Memory, instruction.Op1Kind); Assert.Equal(Arm64Register.X20, instruction.MemBase); Assert.Equal(0x20, instruction.MemOffset); - Assert.Equal(MemoryIndexMode.PostIndex, instruction.MemIndexMode); + Assert.Equal(Arm64MemoryIndexMode.PostIndex, instruction.MemIndexMode); Assert.Equal("0x00000000 LDR X8, [X20], #0x20", instruction.ToString()); } + + [Fact] + public void TestLoadStoreMemoryTags() + { + var insn = DisassembleAndCheckMnemonic(0xD920341F, Arm64Mnemonic.STG); + + Assert.Equal(Arm64OperandKind.Register, insn.Op0Kind); + Assert.Equal(Arm64OperandKind.Memory, insn.Op1Kind); + + Assert.Equal(Arm64Register.X0, insn.Op0Reg); + Assert.Equal(Arm64Register.X31, insn.MemBase); + Assert.Equal(0x30, insn.MemOffset); + + Assert.Equal(Arm64MemoryIndexMode.PostIndex, insn.MemIndexMode); + + Assert.Equal("0x00000000 STG X0, [X31], #0x30", insn.ToString()); + + insn = DisassembleAndCheckMnemonic(0xD920041F, Arm64Mnemonic.STZGM); + Assert.Equal("0x00000000 STZGM X0, X31", insn.ToString()); + + insn = DisassembleAndCheckMnemonic(0xD960341F, Arm64Mnemonic.STZG); + Assert.Equal("0x00000000 STZG X0, [X31], #0x30", insn.ToString()); + + insn = DisassembleAndCheckMnemonic(0xD960001F, Arm64Mnemonic.LDG); + Assert.Equal("0x00000000 LDG X0, X31", insn.ToString()); + + insn = DisassembleAndCheckMnemonic(0xD9A0001F, Arm64Mnemonic.STGM); + Assert.Equal("0x00000000 STGM X0, X31", insn.ToString()); + + insn = DisassembleAndCheckMnemonic(0xD9A0341F, Arm64Mnemonic.ST2G); + Assert.Equal("0x00000000 ST2G X0, [X31], #0x30", insn.ToString()); + + insn = DisassembleAndCheckMnemonic(0xD9E0341F, Arm64Mnemonic.STZ2G); + Assert.Equal("0x00000000 STZ2G X0, [X31], #0x30", insn.ToString()); + + insn = DisassembleAndCheckMnemonic(0xD9E0001F, Arm64Mnemonic.LDGM); + Assert.Equal("0x00000000 LDGM X0, X31", insn.ToString()); + } } diff --git a/Disarm.Tests/SimdTest.cs b/Disarm.Tests/SimdTest.cs index 8a40843..5045915 100644 --- a/Disarm.Tests/SimdTest.cs +++ b/Disarm.Tests/SimdTest.cs @@ -209,4 +209,20 @@ public void TestCryptoThreeRegSha() Assert.Equal("0x00000000 SHA256SU1 V0.4S, V1.4S, V2.4S", insn.ToString()); } + + [Fact] + public void TestAdvancedSimdThreeSame() + { + var insn = DisassembleAndCheckMnemonic(0x0EA21C20, Arm64Mnemonic.ORR); + + Assert.Equal(Arm64OperandKind.Register, insn.Op0Kind); + Assert.Equal(Arm64OperandKind.Register, insn.Op1Kind); + Assert.Equal(Arm64OperandKind.Register, insn.Op2Kind); + + Assert.Equal(Arm64Register.V0, insn.Op0Reg); + Assert.Equal(Arm64Register.V1, insn.Op1Reg); + Assert.Equal(Arm64Register.V2, insn.Op2Reg); + + Assert.Equal("0x00000000 ORR V0.8B, V1.8B, V2.8B", insn.ToString()); + } } diff --git a/Disarm/Arm64Instruction.cs b/Disarm/Arm64Instruction.cs index aa83732..c752312 100644 --- a/Disarm/Arm64Instruction.cs +++ b/Disarm/Arm64Instruction.cs @@ -39,7 +39,7 @@ public Arm64Instruction() Op4Arrangement = Arm64ArrangementSpecifier.None; MemBase = Arm64Register.INVALID; MemAddendReg = Arm64Register.INVALID; - MemIndexMode = MemoryIndexMode.Offset; + MemIndexMode = Arm64MemoryIndexMode.Offset; MemOffset = 0; MemExtendOrShiftAmount = 0; Op0VectorElement = default; @@ -106,8 +106,8 @@ public Arm64Instruction() public Arm64Register MemBase { get; internal set; } public Arm64Register MemAddendReg { get; internal set; } - public MemoryIndexMode MemIndexMode { get; internal set; } - public bool MemIsPreIndexed => MemIndexMode == MemoryIndexMode.PreIndex; + public Arm64MemoryIndexMode MemIndexMode { get; internal set; } + public bool MemIsPreIndexed => MemIndexMode == Arm64MemoryIndexMode.PreIndex; public long MemOffset { get; internal set; } public Arm64ExtendType MemExtendType { get; internal set; } public Arm64ShiftType MemShiftType { get; internal set; } @@ -203,7 +203,7 @@ private void AppendMemory(StringBuilder sb) if(MemAddendReg != Arm64Register.INVALID) sb.Append(", ").Append(MemAddendReg.ToString()); - if (MemOffset != 0 && MemIndexMode != MemoryIndexMode.PostIndex) + if (MemOffset != 0 && MemIndexMode != Arm64MemoryIndexMode.PostIndex) { sb.Append(' ') .Append(MemOffset < 0 ? '-' : '+') @@ -221,9 +221,9 @@ private void AppendMemory(StringBuilder sb) sb.Append(']'); - if (MemIndexMode == MemoryIndexMode.PreIndex) + if (MemIndexMode == Arm64MemoryIndexMode.PreIndex) sb.Append('!'); - else if(MemIndexMode == MemoryIndexMode.PostIndex && MemOffset != 0) + else if(MemIndexMode == Arm64MemoryIndexMode.PostIndex && MemOffset != 0) sb.Append(", #0x").Append(MemOffset.ToString("X")); } } diff --git a/Disarm/MemoryIndexMode.cs b/Disarm/Arm64MemoryIndexMode.cs similarity index 66% rename from Disarm/MemoryIndexMode.cs rename to Disarm/Arm64MemoryIndexMode.cs index dce126d..ea908bf 100644 --- a/Disarm/MemoryIndexMode.cs +++ b/Disarm/Arm64MemoryIndexMode.cs @@ -1,6 +1,6 @@ namespace Disarm; -public enum MemoryIndexMode +public enum Arm64MemoryIndexMode { PreIndex, PostIndex, diff --git a/Disarm/InternalDisassembly/Arm64CommonUtils.cs b/Disarm/InternalDisassembly/Arm64CommonUtils.cs index 49a8002..5de5926 100644 --- a/Disarm/InternalDisassembly/Arm64CommonUtils.cs +++ b/Disarm/InternalDisassembly/Arm64CommonUtils.cs @@ -8,6 +8,9 @@ namespace Disarm.InternalDisassembly; /// internal static class Arm64CommonUtils { + public const int LOG2_TAG_GRANULE = 4; + public const int TAG_GRANULE = 1 << LOG2_TAG_GRANULE; + /// /// Extends the given bit array to the given length by continuously adding the leftmost bit to the left until the length is reached. /// @@ -20,7 +23,7 @@ private static BitArray SignExtend(BitArray value, int size) var startOffset = size - value.Length; //Copy bottom n bits of value to result - for (var i = startOffset; i < size - 1; i++) + for (var i = startOffset; i < size; i++) { result[i] = value[i - startOffset]; } diff --git a/Disarm/InternalDisassembly/Arm64LoadsStores.cs b/Disarm/InternalDisassembly/Arm64LoadsStores.cs index aeefa4c..3874052 100644 --- a/Disarm/InternalDisassembly/Arm64LoadsStores.cs +++ b/Disarm/InternalDisassembly/Arm64LoadsStores.cs @@ -69,10 +69,13 @@ private static Arm64Instruction DisassembleAdvancedLoadStore(uint instruction) private static Arm64Instruction DisassembleLoadStoreMemoryTags(uint instruction) { var opc = (instruction >> 22) & 0b11; // Bits 22-23 - var offset = Arm64CommonUtils.SignExtend((instruction >> 12) & 0b1_1111_1111, 9, 64) << (1 << 4); // Bits 12-20 + var imm9 = (long) (instruction >> 12) & 0b1_1111_1111; // Bits 12-20 var op2 = (instruction >> 10) & 0b11; // Bits 10-11 var rn = (int)(instruction >> 5) & 0b1_1111; // Bits 5-9 var rt = (int)instruction & 0b1_1111; // Bits 0-5 + + imm9 = Arm64CommonUtils.SignExtend(imm9, 9, 64); + var offset = imm9 << Arm64CommonUtils.LOG2_TAG_GRANULE; return opc switch { @@ -82,16 +85,16 @@ private static Arm64Instruction DisassembleLoadStoreMemoryTags(uint instruction) MnemonicCategory = Arm64MnemonicCategory.MemoryTagging, MemIndexMode = op2 switch { - 0b01 => MemoryIndexMode.PostIndex, - 0b10 => MemoryIndexMode.Offset, - 0b11 => MemoryIndexMode.PreIndex, + 0b01 => Arm64MemoryIndexMode.PostIndex, + 0b10 => Arm64MemoryIndexMode.Offset, + 0b11 => Arm64MemoryIndexMode.PreIndex, _ => throw new Arm64UndefinedInstructionException("Bad memory index mode") }, MemOffset = offset, Op0Kind = Arm64OperandKind.Register, - Op1Kind = Arm64OperandKind.Register, + Op1Kind = Arm64OperandKind.Memory, Op0Reg = Arm64Register.X0 + rn, - Op1Reg = Arm64Register.X0 + rt + MemBase = Arm64Register.X0 + rt }, 0b00 when offset == 0 => new() { @@ -106,7 +109,7 @@ private static Arm64Instruction DisassembleLoadStoreMemoryTags(uint instruction) { Mnemonic = Arm64Mnemonic.LDG, MnemonicCategory = Arm64MnemonicCategory.MemoryTagging, - MemIndexMode = MemoryIndexMode.Offset, + MemIndexMode = Arm64MemoryIndexMode.Offset, MemOffset = offset, Op0Kind = Arm64OperandKind.Register, Op1Kind = Arm64OperandKind.Register, @@ -119,16 +122,16 @@ private static Arm64Instruction DisassembleLoadStoreMemoryTags(uint instruction) MnemonicCategory = Arm64MnemonicCategory.MemoryTagging, MemIndexMode = op2 switch { - 0b01 => MemoryIndexMode.PostIndex, - 0b10 => MemoryIndexMode.Offset, - 0b11 => MemoryIndexMode.PreIndex, + 0b01 => Arm64MemoryIndexMode.PostIndex, + 0b10 => Arm64MemoryIndexMode.Offset, + 0b11 => Arm64MemoryIndexMode.PreIndex, _ => throw new Arm64UndefinedInstructionException("Bad memory index mode") }, MemOffset = offset, Op0Kind = Arm64OperandKind.Register, - Op1Kind = Arm64OperandKind.Register, + Op1Kind = Arm64OperandKind.Memory, Op0Reg = Arm64Register.X0 + rn, - Op1Reg = Arm64Register.X0 + rt + MemBase = Arm64Register.X0 + rt }, 0b10 when offset != 0 => new() { @@ -136,16 +139,16 @@ private static Arm64Instruction DisassembleLoadStoreMemoryTags(uint instruction) MnemonicCategory = Arm64MnemonicCategory.MemoryTagging, MemIndexMode = op2 switch { - 0b01 => MemoryIndexMode.PostIndex, - 0b10 => MemoryIndexMode.Offset, - 0b11 => MemoryIndexMode.PreIndex, + 0b01 => Arm64MemoryIndexMode.PostIndex, + 0b10 => Arm64MemoryIndexMode.Offset, + 0b11 => Arm64MemoryIndexMode.PreIndex, _ => throw new Arm64UndefinedInstructionException("Bad memory index mode") }, MemOffset = offset, Op0Kind = Arm64OperandKind.Register, - Op1Kind = Arm64OperandKind.Register, + Op1Kind = Arm64OperandKind.Memory, Op0Reg = Arm64Register.X0 + rn, - Op1Reg = Arm64Register.X0 + rt + MemBase = Arm64Register.X0 + rt }, 0b10 when offset == 0 && op2 == 0 => new() { @@ -162,16 +165,16 @@ private static Arm64Instruction DisassembleLoadStoreMemoryTags(uint instruction) MnemonicCategory = Arm64MnemonicCategory.MemoryTagging, MemIndexMode = op2 switch { - 0b01 => MemoryIndexMode.PostIndex, - 0b10 => MemoryIndexMode.Offset, - 0b11 => MemoryIndexMode.PreIndex, + 0b01 => Arm64MemoryIndexMode.PostIndex, + 0b10 => Arm64MemoryIndexMode.Offset, + 0b11 => Arm64MemoryIndexMode.PreIndex, _ => throw new Arm64UndefinedInstructionException("Bad memory index mode") }, MemOffset = offset, Op0Kind = Arm64OperandKind.Register, - Op1Kind = Arm64OperandKind.Register, + Op1Kind = Arm64OperandKind.Memory, Op0Reg = Arm64Register.X0 + rn, - Op1Reg = Arm64Register.X0 + rt + MemBase = Arm64Register.X0 + rt }, 0b11 when offset == 0 && op2 == 0 => new() { @@ -336,9 +339,9 @@ private static Arm64Instruction DisassembleLoadStorePairs(uint instruction) return op2 switch { 0b00 => LoadStoreNoAllocatePairs(instruction), //load/store no-allocate pairs - 0b01 => LoadStoreRegisterPair(instruction, MemoryIndexMode.PostIndex), //load/store register pair (post-indexed) - 0b10 => LoadStoreRegisterPair(instruction, MemoryIndexMode.Offset), //load/store register pair (offset) - 0b11 => LoadStoreRegisterPair(instruction, MemoryIndexMode.PreIndex), //load/store register pair (pre-indexed) + 0b01 => LoadStoreRegisterPair(instruction, Arm64MemoryIndexMode.PostIndex), //load/store register pair (post-indexed) + 0b10 => LoadStoreRegisterPair(instruction, Arm64MemoryIndexMode.Offset), //load/store register pair (offset) + 0b11 => LoadStoreRegisterPair(instruction, Arm64MemoryIndexMode.PreIndex), //load/store register pair (pre-indexed) _ => throw new("Loads/store pairs: Impossible op2 value") }; } @@ -371,14 +374,14 @@ private static Arm64Instruction DisassembleLoadStoreRegisterOrAtomic(uint instru return op4 switch { 0b00 => LoadStoreRegisterFromImmUnscaled(instruction), //Load/store (reg), (unscaled immediate) - 0b01 => LoadStoreRegisterFromImm(instruction, MemoryIndexMode.PostIndex), //Load/store (reg), (post-indexed immediate) + 0b01 => LoadStoreRegisterFromImm(instruction, Arm64MemoryIndexMode.PostIndex), //Load/store (reg), (post-indexed immediate) 0b10 => LoadStoreRegisterUnprivileged(instruction), //Load/store (reg), (unprivileged) - 0b11 => LoadStoreRegisterFromImm(instruction, MemoryIndexMode.PreIndex), //Load/Store (reg), (pre-indexed immediate) + 0b11 => LoadStoreRegisterFromImm(instruction, Arm64MemoryIndexMode.PreIndex), //Load/Store (reg), (pre-indexed immediate) _ => throw new("Impossible op4"), }; } - private static Arm64Instruction LoadStoreRegisterFromImm(uint instruction, MemoryIndexMode memoryIndexMode) + private static Arm64Instruction LoadStoreRegisterFromImm(uint instruction, Arm64MemoryIndexMode memoryIndexMode) { // Load/store immediate pre-indexed @@ -492,7 +495,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction) { Mnemonic = Arm64Mnemonic.STNP, MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister, - MemIndexMode = MemoryIndexMode.Offset, + MemIndexMode = Arm64MemoryIndexMode.Offset, MemOffset = offset, MemBase = (opc == 0b00 ? Arm64Register.W0 : Arm64Register.X0) + rn, Op0Kind = Arm64OperandKind.Register, @@ -505,7 +508,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction) { Mnemonic = Arm64Mnemonic.LDNP, MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister, - MemIndexMode = MemoryIndexMode.Offset, + MemIndexMode = Arm64MemoryIndexMode.Offset, MemOffset = offset, MemBase = (opc == 0b00 ? Arm64Register.W0 : Arm64Register.X0) + rn, Op0Kind = Arm64OperandKind.Register, @@ -518,7 +521,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction) { Mnemonic = Arm64Mnemonic.STNP, MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister, - MemIndexMode = MemoryIndexMode.Offset, + MemIndexMode = Arm64MemoryIndexMode.Offset, MemOffset = offset, MemBase = Arm64Register.X0 + rn, Op0Kind = Arm64OperandKind.Register, @@ -531,7 +534,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction) { Mnemonic = Arm64Mnemonic.STNP, MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister, - MemIndexMode = MemoryIndexMode.Offset, + MemIndexMode = Arm64MemoryIndexMode.Offset, MemOffset = offset, MemBase = Arm64Register.X0 + rn, Op0Kind = Arm64OperandKind.Register, @@ -544,7 +547,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction) { Mnemonic = Arm64Mnemonic.STNP, MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister, - MemIndexMode = MemoryIndexMode.Offset, + MemIndexMode = Arm64MemoryIndexMode.Offset, MemOffset = offset, MemBase = Arm64Register.X0 + rn, Op0Kind = Arm64OperandKind.Register, @@ -557,7 +560,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction) { Mnemonic = Arm64Mnemonic.LDNP, MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister, - MemIndexMode = MemoryIndexMode.Offset, + MemIndexMode = Arm64MemoryIndexMode.Offset, MemOffset = offset, MemBase = Arm64Register.X0 + rn, Op0Kind = Arm64OperandKind.Register, @@ -570,7 +573,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction) { Mnemonic = Arm64Mnemonic.LDNP, MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister, - MemIndexMode = MemoryIndexMode.Offset, + MemIndexMode = Arm64MemoryIndexMode.Offset, MemOffset = offset, MemBase = Arm64Register.X0 + rn, Op0Kind = Arm64OperandKind.Register, @@ -583,7 +586,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction) { Mnemonic = Arm64Mnemonic.LDNP, MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister, - MemIndexMode = MemoryIndexMode.Offset, + MemIndexMode = Arm64MemoryIndexMode.Offset, MemOffset = offset, MemBase = Arm64Register.X0 + rn, Op0Kind = Arm64OperandKind.Register, @@ -596,7 +599,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction) }; } - private static Arm64Instruction LoadStoreRegisterPair(uint instruction, MemoryIndexMode mode) + private static Arm64Instruction LoadStoreRegisterPair(uint instruction, Arm64MemoryIndexMode mode) { //Page C4-559 @@ -761,7 +764,7 @@ private static Arm64Instruction LoadStoreRegFromImmUnsigned(uint instruction) Op0Reg = regT, MemBase = regN, MemOffset = immediate, - MemIndexMode = MemoryIndexMode.Offset, + MemIndexMode = Arm64MemoryIndexMode.Offset, MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister, }; } @@ -880,7 +883,7 @@ private static Arm64Instruction LoadStoreRegisterFromRegisterOffset(uint instruc Op0Reg = baseReg + rt, MemBase = Arm64Register.X0 + rn, MemAddendReg = secondRegBase + rm, - MemIndexMode = MemoryIndexMode.Offset, + MemIndexMode = Arm64MemoryIndexMode.Offset, MemExtendType = isShiftedRegister ? Arm64ExtendType.NONE : extendKind, MemShiftType = isShiftedRegister ? Arm64ShiftType.LSL : Arm64ShiftType.NONE, MemExtendOrShiftAmount = shiftAmount, @@ -986,7 +989,7 @@ private static Arm64Instruction LoadStoreRegisterFromImmUnscaled(uint instructio Op0Reg = regT, MemBase = regN, MemOffset = immediate, - MemIndexMode = MemoryIndexMode.Offset, + MemIndexMode = Arm64MemoryIndexMode.Offset, MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister, }; } diff --git a/Disarm/InternalDisassembly/Arm64ScalarAdvancedSimd.cs b/Disarm/InternalDisassembly/Arm64ScalarAdvancedSimd.cs index 6091852..df6a7ec 100644 --- a/Disarm/InternalDisassembly/Arm64ScalarAdvancedSimd.cs +++ b/Disarm/InternalDisassembly/Arm64ScalarAdvancedSimd.cs @@ -167,153 +167,14 @@ public static Arm64Instruction ThreeDifferent(uint instruction) }; } + //"Advanced SIMD Scalar Three Same" derived from C4-587 + //Note this is NOT the "Advanced SIMD Three Same" - that's in Adm64NonScalarAdvancedSimd.AdvancedSimdThreeSame public static Arm64Instruction ThreeSame(uint instruction) { - var q = (instruction >> 30) & 1; - var u = instruction.TestBit(29); - var size = (instruction >> 22) & 0b11; - var rm = (int)(instruction >> 16) & 0b1_1111; - var opcode = (instruction >> 11) & 0b1_1111; - var rn = (int)(instruction >> 5) & 0b1_1111; - var rd = (int)instruction & 0b1_1111; - - Arm64ArrangementSpecifier arrangement; - - if (opcode == 0b00011) // AND or BIC or ORR or ORN or EOR or BSL or BIT or BIF - { - arrangement = q switch - { - 0 => Arm64ArrangementSpecifier.EightB, - 1 => Arm64ArrangementSpecifier.SixteenB, - _ => throw new ArgumentOutOfRangeException() - }; - } - else if (opcode is >= 0b11000 and <= 0b11111) - { - arrangement = (instruction.TestBit(22) ? 1 : 0, q) switch - { - (0, 0) => Arm64ArrangementSpecifier.TwoS, - (0, 1) => Arm64ArrangementSpecifier.FourS, - (1, 1) => Arm64ArrangementSpecifier.TwoD, - _ => throw new Arm64UndefinedInstructionException("RESERVED") - }; - } - else - { - arrangement = (size, q) switch - { - (0b00, 0) => Arm64ArrangementSpecifier.EightB, - (0b00, 1) => Arm64ArrangementSpecifier.SixteenB, - (0b01, 0) => Arm64ArrangementSpecifier.FourH, - (0b01, 1) => Arm64ArrangementSpecifier.EightH, - (0b10, 0) => Arm64ArrangementSpecifier.TwoS, - (0b10, 1) => Arm64ArrangementSpecifier.FourS, - _ => throw new Arm64UndefinedInstructionException("RESERVED") - }; - } - return new() { - Mnemonic = u switch - { - false => opcode switch - { - 0b00000 => Arm64Mnemonic.SHADD, - 0b00001 => Arm64Mnemonic.SQADD, - 0b00010 => Arm64Mnemonic.SRHADD, - 0b00100 => Arm64Mnemonic.SHSUB, - 0b00101 => Arm64Mnemonic.SQSUB, - 0b00110 => Arm64Mnemonic.CMGT, - 0b00111 => Arm64Mnemonic.CMGE, - 0b01000 => Arm64Mnemonic.SSHL, - 0b01001 => Arm64Mnemonic.SQSHL, - 0b01010 => Arm64Mnemonic.SRSHL, - 0b01011 => Arm64Mnemonic.SQRSHL, - 0b01100 => Arm64Mnemonic.SMAX, - 0b01101 => Arm64Mnemonic.SMIN, - 0b01110 => Arm64Mnemonic.SABD, - 0b01111 => Arm64Mnemonic.SABA, - 0b10000 => Arm64Mnemonic.ADD, - 0b10001 => Arm64Mnemonic.CMTST, - 0b10010 => Arm64Mnemonic.MLA, - 0b10011 => Arm64Mnemonic.MUL, - 0b10100 => Arm64Mnemonic.SMAXP, - 0b10101 => Arm64Mnemonic.SMINP, - 0b10110 => Arm64Mnemonic.SQDMULH, - 0b10111 => Arm64Mnemonic.ADDP, - 0b11000 when size is 0 or 1 => Arm64Mnemonic.FMAXNM, // other arrangment - 0b11001 when size is 0 or 1 => Arm64Mnemonic.FMLA, - 0b11010 when size is 0 or 1 => Arm64Mnemonic.FADD, - 0b11011 when size is 0 or 1 => Arm64Mnemonic.FMULX, - 0b11100 when size is 0 or 1 => Arm64Mnemonic.FCMEQ, - 0b11110 when size is 0 or 1 => Arm64Mnemonic.FMAX, - 0b11111 when size is 0 or 1 => Arm64Mnemonic.FRECPS, - 0b00011 when size is 0 => Arm64Mnemonic.AND, // again other arrangment - // 0b11101 when size is 0 => Arm64Mnemonic.FMLAL, too hard // again other arrangment - 0b00011 when size is 1 => Arm64Mnemonic.BIC, // again other arrangment... - 0b11000 when size is 2 or 3 => Arm64Mnemonic.FMINNM, - 0b11001 when size is 2 or 3 => Arm64Mnemonic.FMLS, - 0b11010 when size is 2 or 3 => Arm64Mnemonic.FSUB, - 0b11110 when size is 2 or 3 => Arm64Mnemonic.FMIN, - 0b11111 when size is 2 or 3 => Arm64Mnemonic.FRSORTS, - 0b00011 when size is 2 => Arm64Mnemonic.ORR, - //0b11101 when size is 2 => Arm64Mnemonic.FMLSL, too hard - 0b00011 when size is 3 => Arm64Mnemonic.ORN, - _ => throw new Arm64UndefinedInstructionException("Unallocated or unimplemented") - }, - true => opcode switch - { - 0b00000 => Arm64Mnemonic.UHADD, - 0b00001 => Arm64Mnemonic.UQADD, - 0b00010 => Arm64Mnemonic.URHADD, - 0b00100 => Arm64Mnemonic.UHSUB, - 0b00101 => Arm64Mnemonic.UQSUB, - 0b00110 => Arm64Mnemonic.CMHL, - 0b00111 => Arm64Mnemonic.CMHS, - 0b01000 => Arm64Mnemonic.USHL, - 0b01001 => Arm64Mnemonic.UQSHL, - 0b01010 => Arm64Mnemonic.URSHL, - 0b01011 => Arm64Mnemonic.UQRSHL, - 0b01100 => Arm64Mnemonic.UMAX, - 0b01101 => Arm64Mnemonic.UMIN, - 0b01110 => Arm64Mnemonic.UABD, - 0b01111 => Arm64Mnemonic.UABA, - 0b10000 => Arm64Mnemonic.SUB, - 0b10001 => Arm64Mnemonic.CMEO, - 0b10010 => Arm64Mnemonic.MLS, - 0b10011 => Arm64Mnemonic.PMUL, - 0b10100 => Arm64Mnemonic.UMAXP, - 0b10101 => Arm64Mnemonic.UMINP, - 0b10110 => Arm64Mnemonic.SQRDMULH, - 0b11000 when size is 0 or 1 => Arm64Mnemonic.FMAXNMP, - 0b11010 when size is 0 or 1 => Arm64Mnemonic.FADDP, - 0b11011 when size is 0 or 1 => Arm64Mnemonic.FMUL, - 0b11100 when size is 0 or 1 => Arm64Mnemonic.FCMGE, - 0b11101 when size is 0 or 1 => Arm64Mnemonic.FACGE, - 0b11110 when size is 0 or 1 => Arm64Mnemonic.FMAXP, - 0b11111 when size is 0 or 1 => Arm64Mnemonic.FDIV, - 0b00011 when size is 0 => Arm64Mnemonic.EOR, - //0b11001 when size is 0 => Arm64Mnemonic.FMLAL2, - 0b00011 when size is 1 => Arm64Mnemonic.BSL, - 0b11000 when size is 2 or 3 => Arm64Mnemonic.FABD, - 0b11100 when size is 2 or 3 => Arm64Mnemonic.FCMGT, - 0b11101 when size is 2 or 3 => Arm64Mnemonic.FACGT, - 0b11110 when size is 2 or 3 => Arm64Mnemonic.FMINP, - 0b00011 when size is 2 => Arm64Mnemonic.BIT, - 0b00011 when size is 3 => Arm64Mnemonic.BIF, - _ => throw new Arm64UndefinedInstructionException("Unallocated or unimplemented") - } - }, - MnemonicCategory = Arm64MnemonicCategory.Unspecified, // TODO Could be comparison or math - Op0Kind = Arm64OperandKind.Register, - Op1Kind = Arm64OperandKind.Register, - Op2Kind = Arm64OperandKind.Register, - Op0Arrangement = arrangement, - Op1Arrangement = arrangement, - Op2Arrangement = arrangement, - Op0Reg = Arm64Register.V0 + rd, - Op1Reg = Arm64Register.V0 + rn, - Op2Reg = Arm64Register.V0 + rm, + Mnemonic = Arm64Mnemonic.UNIMPLEMENTED, + MnemonicCategory = Arm64MnemonicCategory.SimdScalarMath, }; }