diff options
Diffstat (limited to 'src/Ryujinx.Cpu/LightningJit/Arm32')
57 files changed, 28807 insertions, 0 deletions
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/A32Compiler.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/A32Compiler.cs new file mode 100644 index 00000000..7f6024d4 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/A32Compiler.cs @@ -0,0 +1,30 @@ +using ARMeilleure.Common; +using ARMeilleure.Memory; +using Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64; +using System; +using System.Runtime.InteropServices; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + static class A32Compiler + { + public static CompiledFunction Compile( + CpuPreset cpuPreset, + IMemoryManager memoryManager, + ulong address, + AddressTable<ulong> funcTable, + IntPtr dispatchStubPtr, + bool isThumb, + Architecture targetArch) + { + if (targetArch == Architecture.Arm64) + { + return Compiler.Compile(cpuPreset, memoryManager, address, funcTable, dispatchStubPtr, isThumb); + } + else + { + throw new PlatformNotSupportedException(); + } + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs new file mode 100644 index 00000000..4729f694 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs @@ -0,0 +1,101 @@ +using System.Collections.Generic; +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + class Block + { + public readonly ulong Address; + public readonly ulong EndAddress; + public readonly List<InstInfo> Instructions; + public readonly bool EndsWithBranch; + public readonly bool HasHostCall; + public readonly bool IsTruncated; + public readonly bool IsLoopEnd; + public readonly bool IsThumb; + + public Block( + ulong address, + ulong endAddress, + List<InstInfo> instructions, + bool endsWithBranch, + bool hasHostCall, + bool isTruncated, + bool isLoopEnd, + bool isThumb) + { + Debug.Assert(isThumb || (int)((endAddress - address) / 4) == instructions.Count); + + Address = address; + EndAddress = endAddress; + Instructions = instructions; + EndsWithBranch = endsWithBranch; + HasHostCall = hasHostCall; + IsTruncated = isTruncated; + IsLoopEnd = isLoopEnd; + IsThumb = isThumb; + } + + public (Block, Block) SplitAtAddress(ulong address) + { + int splitIndex = FindSplitIndex(address); + + if (splitIndex < 0) + { + return (null, null); + } + + int splitCount = Instructions.Count - splitIndex; + + // Technically those are valid, but we don't want to create empty blocks. + Debug.Assert(splitIndex != 0); + Debug.Assert(splitCount != 0); + + Block leftBlock = new( + Address, + address, + Instructions.GetRange(0, splitIndex), + false, + HasHostCall, + false, + false, + IsThumb); + + Block rightBlock = new( + address, + EndAddress, + Instructions.GetRange(splitIndex, splitCount), + EndsWithBranch, + HasHostCall, + IsTruncated, + IsLoopEnd, + IsThumb); + + return (leftBlock, rightBlock); + } + + private int FindSplitIndex(ulong address) + { + if (IsThumb) + { + ulong pc = Address; + + for (int index = 0; index < Instructions.Count; index++) + { + if (pc == address) + { + return index; + } + + pc += Instructions[index].Flags.HasFlag(InstFlags.Thumb16) ? 2UL : 4UL; + } + + return -1; + } + else + { + return (int)((address - Address) / 4); + } + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/BranchType.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/BranchType.cs new file mode 100644 index 00000000..6d9fdf2c --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/BranchType.cs @@ -0,0 +1,15 @@ +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + enum BranchType + { + Branch, + Call, + IndirectBranch, + TableBranchByte, + TableBranchHalfword, + IndirectCall, + SyncPoint, + SoftwareInterrupt, + ReadCntpct, + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/CodeGenContext.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/CodeGenContext.cs new file mode 100644 index 00000000..f55e2bb9 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/CodeGenContext.cs @@ -0,0 +1,198 @@ +using ARMeilleure.Memory; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + class CodeGenContext + { + public CodeWriter CodeWriter { get; } + public Assembler Arm64Assembler { get; } + public RegisterAllocator RegisterAllocator { get; } + + public MemoryManagerType MemoryManagerType { get; } + + private uint _instructionAddress; + + public bool IsThumb { get; } + public uint Pc { get; private set; } + public bool InITBlock { get; private set; } + + private InstInfo _nextInstruction; + private bool _skipNextInstruction; + + private readonly ArmCondition[] _itConditions; + private int _itCount; + + private readonly List<PendingBranch> _pendingBranches; + + private bool _nzcvModified; + + public CodeGenContext(CodeWriter codeWriter, Assembler arm64Assembler, RegisterAllocator registerAllocator, MemoryManagerType mmType, bool isThumb) + { + CodeWriter = codeWriter; + Arm64Assembler = arm64Assembler; + RegisterAllocator = registerAllocator; + MemoryManagerType = mmType; + _itConditions = new ArmCondition[4]; + _pendingBranches = new(); + IsThumb = isThumb; + } + + public void SetPc(uint address) + { + // Due to historical reasons, the PC value is always 2 instructions ahead on 32-bit Arm CPUs. + Pc = address + (IsThumb ? 4u : 8u); + _instructionAddress = address; + } + + public void SetNextInstruction(InstInfo info) + { + _nextInstruction = info; + } + + public InstInfo PeekNextInstruction() + { + return _nextInstruction; + } + + public void SetSkipNextInstruction() + { + _skipNextInstruction = true; + } + + public bool ConsumeSkipNextInstruction() + { + bool skip = _skipNextInstruction; + _skipNextInstruction = false; + + return skip; + } + + public void AddPendingBranch(InstName name, int offset) + { + _pendingBranches.Add(new(BranchType.Branch, Pc + (uint)offset, 0u, name, CodeWriter.InstructionPointer)); + } + + public void AddPendingCall(uint targetAddress, uint nextAddress) + { + _pendingBranches.Add(new(BranchType.Call, targetAddress, nextAddress, InstName.BlI, CodeWriter.InstructionPointer)); + + RegisterAllocator.EnsureTempGprRegisters(1); + RegisterAllocator.MarkGprAsUsed(RegisterUtils.LrRegister); + } + + public void AddPendingIndirectBranch(InstName name, uint targetRegister) + { + _pendingBranches.Add(new(BranchType.IndirectBranch, targetRegister, 0u, name, CodeWriter.InstructionPointer)); + + RegisterAllocator.MarkGprAsUsed((int)targetRegister); + } + + public void AddPendingTableBranch(uint rn, uint rm, bool halfword) + { + _pendingBranches.Add(new(halfword ? BranchType.TableBranchHalfword : BranchType.TableBranchByte, rn, rm, InstName.Tbb, CodeWriter.InstructionPointer)); + + RegisterAllocator.EnsureTempGprRegisters(2); + RegisterAllocator.MarkGprAsUsed((int)rn); + RegisterAllocator.MarkGprAsUsed((int)rm); + } + + public void AddPendingIndirectCall(uint targetRegister, uint nextAddress) + { + _pendingBranches.Add(new(BranchType.IndirectCall, targetRegister, nextAddress, InstName.BlxR, CodeWriter.InstructionPointer)); + + RegisterAllocator.EnsureTempGprRegisters(targetRegister == RegisterUtils.LrRegister ? 1 : 0); + RegisterAllocator.MarkGprAsUsed((int)targetRegister); + RegisterAllocator.MarkGprAsUsed(RegisterUtils.LrRegister); + } + + public void AddPendingSyncPoint() + { + _pendingBranches.Add(new(BranchType.SyncPoint, 0, 0, default, CodeWriter.InstructionPointer)); + + RegisterAllocator.EnsureTempGprRegisters(1); + } + + public void AddPendingBkpt(uint imm) + { + _pendingBranches.Add(new(BranchType.SoftwareInterrupt, imm, _instructionAddress, InstName.Bkpt, CodeWriter.InstructionPointer)); + + RegisterAllocator.EnsureTempGprRegisters(1); + } + + public void AddPendingSvc(uint imm) + { + _pendingBranches.Add(new(BranchType.SoftwareInterrupt, imm, _instructionAddress, InstName.Svc, CodeWriter.InstructionPointer)); + + RegisterAllocator.EnsureTempGprRegisters(1); + } + + public void AddPendingUdf(uint imm) + { + _pendingBranches.Add(new(BranchType.SoftwareInterrupt, imm, _instructionAddress, InstName.Udf, CodeWriter.InstructionPointer)); + + RegisterAllocator.EnsureTempGprRegisters(1); + } + + public void AddPendingReadCntpct(uint rt, uint rt2) + { + _pendingBranches.Add(new(BranchType.ReadCntpct, rt, rt2, InstName.Mrrc, CodeWriter.InstructionPointer)); + + RegisterAllocator.EnsureTempGprRegisters(1); + } + + public IEnumerable<PendingBranch> GetPendingBranches() + { + return _pendingBranches; + } + + public void SetItBlockStart(ReadOnlySpan<ArmCondition> conditions) + { + _itCount = conditions.Length; + + for (int index = 0; index < conditions.Length; index++) + { + _itConditions[index] = conditions[index]; + } + + InITBlock = true; + } + + public bool ConsumeItCondition(out ArmCondition condition) + { + if (_itCount != 0) + { + condition = _itConditions[--_itCount]; + + return true; + } + + condition = ArmCondition.Al; + + return false; + } + + public void UpdateItState() + { + if (_itCount == 0) + { + InITBlock = false; + } + } + + public void SetNzcvModified() + { + _nzcvModified = true; + } + + public bool ConsumeNzcvModified() + { + bool modified = _nzcvModified; + _nzcvModified = false; + + return modified; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Decoder.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Decoder.cs new file mode 100644 index 00000000..e0a18e66 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Decoder.cs @@ -0,0 +1,546 @@ +using ARMeilleure.Memory; +using Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + static class Decoder<T> where T : IInstEmit + { + public static MultiBlock DecodeMulti(CpuPreset cpuPreset, IMemoryManager memoryManager, ulong address, bool isThumb) + { + List<Block> blocks = new(); + List<ulong> branchTargets = new(); + + while (true) + { + Block block = Decode(cpuPreset, memoryManager, address, isThumb); + + if (!block.IsTruncated && TryGetBranchTarget(block, out ulong targetAddress)) + { + branchTargets.Add(targetAddress); + } + + blocks.Add(block); + + if (block.IsTruncated || !HasNextBlock(block, block.EndAddress - 4UL, branchTargets)) + { + break; + } + + address = block.EndAddress; + } + + branchTargets.Sort(); + SplitBlocks(blocks, branchTargets); + + return new(blocks); + } + + private static bool TryGetBranchTarget(Block block, out ulong targetAddress) + { + // PC is 2 instructions ahead, since the end address is already one instruction after the last one, we just need to add + // another instruction. + + ulong pc = block.EndAddress + (block.IsThumb ? 2UL : 4UL); + + return TryGetBranchTarget(block.Instructions[^1].Name, block.Instructions[^1].Flags, pc, block.Instructions[^1].Encoding, block.IsThumb, out targetAddress); + } + + private static bool TryGetBranchTarget(InstName name, InstFlags flags, ulong pc, uint encoding, bool isThumb, out ulong targetAddress) + { + int originalOffset; + + switch (name) + { + case InstName.B: + if (isThumb) + { + if (flags.HasFlag(InstFlags.Thumb16)) + { + if ((encoding & (1u << 29)) != 0) + { + InstImm11b16w11 inst = new(encoding); + + originalOffset = ImmUtils.ExtractT16SImm11Times2(inst.Imm11); + } + else + { + InstCondb24w4Imm8b16w8 inst = new(encoding); + + originalOffset = ImmUtils.ExtractT16SImm8Times2(inst.Imm8); + } + } + else + { + if ((encoding & (1u << 12)) != 0) + { + InstSb26w1Imm10b16w10J1b13w1J2b11w1Imm11b0w11 inst = new(encoding); + + originalOffset = ImmUtils.CombineSImm24Times2(inst.Imm11, inst.Imm10, inst.J1, inst.J2, inst.S); + } + else + { + InstSb26w1Condb22w4Imm6b16w6J1b13w1J2b11w1Imm11b0w11 inst = new(encoding); + + originalOffset = ImmUtils.CombineSImm20Times2(inst.Imm11, inst.Imm6, inst.J1, inst.J2, inst.S); + } + } + } + else + { + originalOffset = ImmUtils.ExtractSImm24Times4(encoding); + } + + targetAddress = pc + (ulong)originalOffset; + Debug.Assert((targetAddress & 1) == 0); + + return true; + + case InstName.Cbnz: + originalOffset = ImmUtils.ExtractT16UImm5Times2(encoding); + targetAddress = pc + (ulong)originalOffset; + Debug.Assert((targetAddress & 1) == 0); + + return true; + } + + targetAddress = 0; + + return false; + } + + private static void SplitBlocks(List<Block> blocks, List<ulong> branchTargets) + { + int btIndex = 0; + + while (btIndex < branchTargets.Count) + { + for (int blockIndex = 0; blockIndex < blocks.Count && btIndex < branchTargets.Count; blockIndex++) + { + Block block = blocks[blockIndex]; + ulong currentBranchTarget = branchTargets[btIndex]; + + while (currentBranchTarget >= block.Address && currentBranchTarget < block.EndAddress) + { + if (block.Address != currentBranchTarget) + { + (Block leftBlock, Block rightBlock) = block.SplitAtAddress(currentBranchTarget); + + if (leftBlock != null && rightBlock != null) + { + blocks.Insert(blockIndex, leftBlock); + blocks[blockIndex + 1] = rightBlock; + + block = leftBlock; + } + else + { + // Split can only fail in thumb mode, where the instruction size is not fixed. + + Debug.Assert(block.IsThumb); + } + } + + btIndex++; + + while (btIndex < branchTargets.Count && branchTargets[btIndex] == currentBranchTarget) + { + btIndex++; + } + + if (btIndex >= branchTargets.Count) + { + break; + } + + currentBranchTarget = branchTargets[btIndex]; + } + } + + Debug.Assert(btIndex < int.MaxValue); + btIndex++; + } + } + + private static bool HasNextBlock(in Block block, ulong pc, List<ulong> branchTargets) + { + InstFlags lastInstFlags = block.Instructions[^1].Flags; + + // Thumb has separate encodings for conditional and unconditional branch instructions. + if (lastInstFlags.HasFlag(InstFlags.Cond) && (block.IsThumb || (ArmCondition)(block.Instructions[^1].Encoding >> 28) < ArmCondition.Al)) + { + return true; + } + + switch (block.Instructions[^1].Name) + { + case InstName.B: + return branchTargets.Contains(pc + 4UL) || + (TryGetBranchTarget(block, out ulong targetAddress) && targetAddress >= pc && targetAddress < pc + 0x1000); + + case InstName.Bx: + case InstName.Bxj: + return branchTargets.Contains(pc + 4UL); + + case InstName.Cbnz: + case InstName.BlI: + case InstName.BlxR: + return true; + } + + if (WritesToPC(block.Instructions[^1].Encoding, block.Instructions[^1].Name, lastInstFlags, block.IsThumb)) + { + return branchTargets.Contains(pc + 4UL); + } + + return !block.EndsWithBranch; + } + + private static Block Decode(CpuPreset cpuPreset, IMemoryManager memoryManager, ulong address, bool isThumb) + { + ulong startAddress = address; + + List<InstInfo> insts = new(); + + uint encoding; + InstMeta meta; + InstFlags extraFlags = InstFlags.None; + bool hasHostCall = false; + bool isTruncated = false; + + do + { + if (!memoryManager.IsMapped(address)) + { + encoding = 0; + meta = default; + isTruncated = true; + break; + } + + if (isThumb) + { + encoding = (uint)memoryManager.Read<ushort>(address) << 16; + address += 2UL; + + extraFlags = InstFlags.Thumb16; + + if (!InstTableT16<T>.TryGetMeta(encoding, cpuPreset.Version, cpuPreset.Features, out meta)) + { + encoding |= memoryManager.Read<ushort>(address); + + if (InstTableT32<T>.TryGetMeta(encoding, cpuPreset.Version, cpuPreset.Features, out meta)) + { + address += 2UL; + extraFlags = InstFlags.None; + } + } + } + else + { + encoding = memoryManager.Read<uint>(address); + address += 4UL; + + meta = InstTableA32<T>.GetMeta(encoding, cpuPreset.Version, cpuPreset.Features); + } + + if (meta.Name.IsSystemOrCall() && !hasHostCall) + { + hasHostCall = meta.Name.IsCall() || InstEmitSystem.NeedsCall(meta.Name); + } + + insts.Add(new(encoding, meta.Name, meta.EmitFunc, meta.Flags | extraFlags)); + } + while (!IsControlFlow(encoding, meta.Name, meta.Flags | extraFlags, isThumb)); + + bool isLoopEnd = false; + + if (!isTruncated && IsBackwardsBranch(meta.Name, encoding)) + { + hasHostCall = true; + isLoopEnd = true; + } + + return new( + startAddress, + address, + insts, + !isTruncated, + hasHostCall, + isTruncated, + isLoopEnd, + isThumb); + } + + private static bool IsControlFlow(uint encoding, InstName name, InstFlags flags, bool isThumb) + { + switch (name) + { + case InstName.B: + case InstName.BlI: + case InstName.BlxR: + case InstName.Bx: + case InstName.Bxj: + case InstName.Cbnz: + case InstName.Tbb: + return true; + } + + return WritesToPC(encoding, name, flags, isThumb); + } + + public static bool WritesToPC(uint encoding, InstName name, InstFlags flags, bool isThumb) + { + return (GetRegisterWriteMask(encoding, name, flags, isThumb) & (1u << RegisterUtils.PcRegister)) != 0; + } + + private static uint GetRegisterWriteMask(uint encoding, InstName name, InstFlags flags, bool isThumb) + { + uint mask = 0; + + if (isThumb) + { + if (flags.HasFlag(InstFlags.Thumb16)) + { + if (flags.HasFlag(InstFlags.Rdn)) + { + mask |= 1u << RegisterUtils.ExtractRdn(flags, encoding); + } + + if (flags.HasFlag(InstFlags.Rd)) + { + mask |= 1u << RegisterUtils.ExtractRdT16(flags, encoding); + } + + Debug.Assert(!flags.HasFlag(InstFlags.RdHi)); + + if (IsRegisterWrite(flags, InstFlags.Rt)) + { + mask |= 1u << RegisterUtils.ExtractRtT16(flags, encoding); + } + + Debug.Assert(!flags.HasFlag(InstFlags.Rt2)); + + if (IsRegisterWrite(flags, InstFlags.Rlist)) + { + mask |= (byte)(encoding >> 16); + + if (name == InstName.Push) + { + mask |= (encoding >> 10) & 0x4000; // LR + } + else if (name == InstName.Pop) + { + mask |= (encoding >> 9) & 0x8000; // PC + } + } + + Debug.Assert(!flags.HasFlag(InstFlags.WBack)); + } + else + { + if (flags.HasFlag(InstFlags.Rd)) + { + mask |= 1u << RegisterUtils.ExtractRdT32(flags, encoding); + } + + if (flags.HasFlag(InstFlags.RdLo)) + { + mask |= 1u << RegisterUtils.ExtractRdLoT32(encoding); + } + + if (flags.HasFlag(InstFlags.RdHi)) + { + mask |= 1u << RegisterUtils.ExtractRdHiT32(encoding); + } + + if (IsRegisterWrite(flags, InstFlags.Rt) && IsRtWrite(name, encoding) && !IsR15RtEncodingSpecial(name, encoding)) + { + mask |= 1u << RegisterUtils.ExtractRtT32(encoding); + } + + if (IsRegisterWrite(flags, InstFlags.Rt2) && IsRtWrite(name, encoding)) + { + mask |= 1u << RegisterUtils.ExtractRt2T32(encoding); + } + + if (IsRegisterWrite(flags, InstFlags.Rlist)) + { + mask |= (ushort)encoding; + } + + if (flags.HasFlag(InstFlags.WBack) && HasWriteBackT32(name, encoding)) + { + mask |= 1u << RegisterUtils.ExtractRn(encoding); // This is at the same bit position as A32. + } + } + } + else + { + if (flags.HasFlag(InstFlags.Rd)) + { + mask |= 1u << RegisterUtils.ExtractRd(flags, encoding); + } + + if (flags.HasFlag(InstFlags.RdHi)) + { + mask |= 1u << RegisterUtils.ExtractRdHi(encoding); + } + + if (IsRegisterWrite(flags, InstFlags.Rt) && IsRtWrite(name, encoding) && !IsR15RtEncodingSpecial(name, encoding)) + { + mask |= 1u << RegisterUtils.ExtractRt(encoding); + } + + if (IsRegisterWrite(flags, InstFlags.Rt2) && IsRtWrite(name, encoding)) + { + mask |= 1u << RegisterUtils.ExtractRt2(encoding); + } + + if (IsRegisterWrite(flags, InstFlags.Rlist)) + { + mask |= (ushort)encoding; + } + + if (flags.HasFlag(InstFlags.WBack) && HasWriteBack(name, encoding)) + { + mask |= 1u << RegisterUtils.ExtractRn(encoding); + } + } + + return mask; + } + + private static bool IsRtWrite(InstName name, uint encoding) + { + // Some instructions can move GPR to FP/SIMD or FP/SIMD to GPR depending on the encoding. + // Detect those cases so that we can tell if we're actually doing a register write. + + switch (name) + { + case InstName.VmovD: + case InstName.VmovH: + case InstName.VmovS: + case InstName.VmovSs: + return (encoding & (1u << 20)) != 0; + } + + return true; + } + + private static bool HasWriteBack(InstName name, uint encoding) + { + if (IsLoadStoreMultiple(name)) + { + return (encoding & (1u << 21)) != 0; + } + + if (IsVLDnVSTn(name)) + { + return (encoding & 0xf) != RegisterUtils.PcRegister; + } + + bool w = (encoding & (1u << 21)) != 0; + bool p = (encoding & (1u << 24)) != 0; + + return !p || w; + } + + private static bool HasWriteBackT32(InstName name, uint encoding) + { + if (IsLoadStoreMultiple(name)) + { + return (encoding & (1u << 21)) != 0; + } + + if (IsVLDnVSTn(name)) + { + return (encoding & 0xf) != RegisterUtils.PcRegister; + } + + return (encoding & (1u << 8)) != 0; + } + + private static bool IsLoadStoreMultiple(InstName name) + { + switch (name) + { + case InstName.Ldm: + case InstName.Ldmda: + case InstName.Ldmdb: + case InstName.LdmE: + case InstName.Ldmib: + case InstName.LdmU: + case InstName.Stm: + case InstName.Stmda: + case InstName.Stmdb: + case InstName.Stmib: + case InstName.StmU: + case InstName.Fldmx: + case InstName.Fstmx: + case InstName.Vldm: + case InstName.Vstm: + return true; + } + + return false; + } + + private static bool IsVLDnVSTn(InstName name) + { + switch (name) + { + case InstName.Vld11: + case InstName.Vld1A: + case InstName.Vld1M: + case InstName.Vld21: + case InstName.Vld2A: + case InstName.Vld2M: + case InstName.Vld31: + case InstName.Vld3A: + case InstName.Vld3M: + case InstName.Vld41: + case InstName.Vld4A: + case InstName.Vld4M: + case InstName.Vst11: + case InstName.Vst1M: + case InstName.Vst21: + case InstName.Vst2M: + case InstName.Vst31: + case InstName.Vst3M: + case InstName.Vst41: + case InstName.Vst4M: + return true; + } + + return false; + } + + private static bool IsR15RtEncodingSpecial(InstName name, uint encoding) + { + if (name == InstName.Vmrs) + { + return ((encoding >> 16) & 0xf) == 1; + } + + return false; + } + + private static bool IsRegisterWrite(InstFlags flags, InstFlags testFlag) + { + return flags.HasFlag(testFlag) && !flags.HasFlag(InstFlags.ReadRd); + } + + private static bool IsBackwardsBranch(InstName name, uint encoding) + { + if (name == InstName.B) + { + return ImmUtils.ExtractSImm24Times4(encoding) < 0; + } + + return false; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/IInstEmit.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/IInstEmit.cs new file mode 100644 index 00000000..32dc5aeb --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/IInstEmit.cs @@ -0,0 +1,1231 @@ +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + interface IInstEmit + { + static abstract void AdcIA1(CodeGenContext context, uint encoding); + static abstract void AdcIT1(CodeGenContext context, uint encoding); + static abstract void AdcRA1(CodeGenContext context, uint encoding); + static abstract void AdcRT1(CodeGenContext context, uint encoding); + static abstract void AdcRT2(CodeGenContext context, uint encoding); + static abstract void AdcRrA1(CodeGenContext context, uint encoding); + static abstract void AddIA1(CodeGenContext context, uint encoding); + static abstract void AddIT1(CodeGenContext context, uint encoding); + static abstract void AddIT2(CodeGenContext context, uint encoding); + static abstract void AddIT3(CodeGenContext context, uint encoding); + static abstract void AddIT4(CodeGenContext context, uint encoding); + static abstract void AddRA1(CodeGenContext context, uint encoding); + static abstract void AddRT1(CodeGenContext context, uint encoding); + static abstract void AddRT2(CodeGenContext context, uint encoding); + static abstract void AddRT3(CodeGenContext context, uint encoding); + static abstract void AddRrA1(CodeGenContext context, uint encoding); + static abstract void AddSpIA1(CodeGenContext context, uint encoding); + static abstract void AddSpIT1(CodeGenContext context, uint encoding); + static abstract void AddSpIT2(CodeGenContext context, uint encoding); + static abstract void AddSpIT3(CodeGenContext context, uint encoding); + static abstract void AddSpIT4(CodeGenContext context, uint encoding); + static abstract void AddSpRA1(CodeGenContext context, uint encoding); + static abstract void AddSpRT1(CodeGenContext context, uint encoding); + static abstract void AddSpRT2(CodeGenContext context, uint encoding); + static abstract void AddSpRT3(CodeGenContext context, uint encoding); + static abstract void AdrA1(CodeGenContext context, uint encoding); + static abstract void AdrA2(CodeGenContext context, uint encoding); + static abstract void AdrT1(CodeGenContext context, uint encoding); + static abstract void AdrT2(CodeGenContext context, uint encoding); + static abstract void AdrT3(CodeGenContext context, uint encoding); + static abstract void AesdA1(CodeGenContext context, uint encoding); + static abstract void AesdT1(CodeGenContext context, uint encoding); + static abstract void AeseA1(CodeGenContext context, uint encoding); + static abstract void AeseT1(CodeGenContext context, uint encoding); + static abstract void AesimcA1(CodeGenContext context, uint encoding); + static abstract void AesimcT1(CodeGenContext context, uint encoding); + static abstract void AesmcA1(CodeGenContext context, uint encoding); + static abstract void AesmcT1(CodeGenContext context, uint encoding); + static abstract void AndIA1(CodeGenContext context, uint encoding); + static abstract void AndIT1(CodeGenContext context, uint encoding); + static abstract void AndRA1(CodeGenContext context, uint encoding); + static abstract void AndRT1(CodeGenContext context, uint encoding); + static abstract void AndRT2(CodeGenContext context, uint encoding); + static abstract void AndRrA1(CodeGenContext context, uint encoding); + static abstract void BA1(CodeGenContext context, uint encoding); + static abstract void BT1(CodeGenContext context, uint encoding); + static abstract void BT2(CodeGenContext context, uint encoding); + static abstract void BT3(CodeGenContext context, uint encoding); + static abstract void BT4(CodeGenContext context, uint encoding); + static abstract void BfcA1(CodeGenContext context, uint encoding); + static abstract void BfcT1(CodeGenContext context, uint encoding); + static abstract void BfiA1(CodeGenContext context, uint encoding); + static abstract void BfiT1(CodeGenContext context, uint encoding); + static abstract void BicIA1(CodeGenContext context, uint encoding); + static abstract void BicIT1(CodeGenContext context, uint encoding); + static abstract void BicRA1(CodeGenContext context, uint encoding); + static abstract void BicRT1(CodeGenContext context, uint encoding); + static abstract void BicRT2(CodeGenContext context, uint encoding); + static abstract void BicRrA1(CodeGenContext context, uint encoding); + static abstract void BkptA1(CodeGenContext context, uint encoding); + static abstract void BkptT1(CodeGenContext context, uint encoding); + static abstract void BlxRA1(CodeGenContext context, uint encoding); + static abstract void BlxRT1(CodeGenContext context, uint encoding); + static abstract void BlIA1(CodeGenContext context, uint encoding); + static abstract void BlIA2(CodeGenContext context, uint encoding); + static abstract void BlIT1(CodeGenContext context, uint encoding); + static abstract void BlIT2(CodeGenContext context, uint encoding); + static abstract void BxA1(CodeGenContext context, uint encoding); + static abstract void BxT1(CodeGenContext context, uint encoding); + static abstract void BxjA1(CodeGenContext context, uint encoding); + static abstract void BxjT1(CodeGenContext context, uint encoding); + static abstract void CbnzT1(CodeGenContext context, uint encoding); + static abstract void ClrbhbA1(CodeGenContext context, uint encoding); + static abstract void ClrbhbT1(CodeGenContext context, uint encoding); + static abstract void ClrexA1(CodeGenContext context, uint encoding); + static abstract void ClrexT1(CodeGenContext context, uint encoding); + static abstract void ClzA1(CodeGenContext context, uint encoding); + static abstract void ClzT1(CodeGenContext context, uint encoding); + static abstract void CmnIA1(CodeGenContext context, uint encoding); + static abstract void CmnIT1(CodeGenContext context, uint encoding); + static abstract void CmnRA1(CodeGenContext context, uint encoding); + static abstract void CmnRT1(CodeGenContext context, uint encoding); + static abstract void CmnRT2(CodeGenContext context, uint encoding); + static abstract void CmnRrA1(CodeGenContext context, uint encoding); + static abstract void CmpIA1(CodeGenContext context, uint encoding); + static abstract void CmpIT1(CodeGenContext context, uint encoding); + static abstract void CmpIT2(CodeGenContext context, uint encoding); + static abstract void CmpRA1(CodeGenContext context, uint encoding); + static abstract void CmpRT1(CodeGenContext context, uint encoding); + static abstract void CmpRT2(CodeGenContext context, uint encoding); + static abstract void CmpRT3(CodeGenContext context, uint encoding); + static abstract void CmpRrA1(CodeGenContext context, uint encoding); + static abstract void CpsA1(CodeGenContext context, uint encoding); + static abstract void CpsT1(CodeGenContext context, uint encoding); + static abstract void CpsT2(CodeGenContext context, uint encoding); + static abstract void Crc32A1(CodeGenContext context, uint encoding); + static abstract void Crc32T1(CodeGenContext context, uint encoding); + static abstract void Crc32cA1(CodeGenContext context, uint encoding); + static abstract void Crc32cT1(CodeGenContext context, uint encoding); + static abstract void CsdbA1(CodeGenContext context, uint encoding); + static abstract void CsdbT1(CodeGenContext context, uint encoding); + static abstract void DbgA1(CodeGenContext context, uint encoding); + static abstract void DbgT1(CodeGenContext context, uint encoding); + static abstract void Dcps1T1(CodeGenContext context, uint encoding); + static abstract void Dcps2T1(CodeGenContext context, uint encoding); + static abstract void Dcps3T1(CodeGenContext context, uint encoding); + static abstract void DmbA1(CodeGenContext context, uint encoding); + static abstract void DmbT1(CodeGenContext context, uint encoding); + static abstract void DsbA1(CodeGenContext context, uint encoding); + static abstract void DsbT1(CodeGenContext context, uint encoding); + static abstract void EorIA1(CodeGenContext context, uint encoding); + static abstract void EorIT1(CodeGenContext context, uint encoding); + static abstract void EorRA1(CodeGenContext context, uint encoding); + static abstract void EorRT1(CodeGenContext context, uint encoding); + static abstract void EorRT2(CodeGenContext context, uint encoding); + static abstract void EorRrA1(CodeGenContext context, uint encoding); + static abstract void EretA1(CodeGenContext context, uint encoding); + static abstract void EretT1(CodeGenContext context, uint encoding); + static abstract void EsbA1(CodeGenContext context, uint encoding); + static abstract void EsbT1(CodeGenContext context, uint encoding); + static abstract void FldmxA1(CodeGenContext context, uint encoding); + static abstract void FldmxT1(CodeGenContext context, uint encoding); + static abstract void FstmxA1(CodeGenContext context, uint encoding); + static abstract void FstmxT1(CodeGenContext context, uint encoding); + static abstract void HltA1(CodeGenContext context, uint encoding); + static abstract void HltT1(CodeGenContext context, uint encoding); + static abstract void HvcA1(CodeGenContext context, uint encoding); + static abstract void HvcT1(CodeGenContext context, uint encoding); + static abstract void IsbA1(CodeGenContext context, uint encoding); + static abstract void IsbT1(CodeGenContext context, uint encoding); + static abstract void ItT1(CodeGenContext context, uint encoding); + static abstract void LdaA1(CodeGenContext context, uint encoding); + static abstract void LdaT1(CodeGenContext context, uint encoding); + static abstract void LdabA1(CodeGenContext context, uint encoding); + static abstract void LdabT1(CodeGenContext context, uint encoding); + static abstract void LdaexA1(CodeGenContext context, uint encoding); + static abstract void LdaexT1(CodeGenContext context, uint encoding); + static abstract void LdaexbA1(CodeGenContext context, uint encoding); + static abstract void LdaexbT1(CodeGenContext context, uint encoding); + static abstract void LdaexdA1(CodeGenContext context, uint encoding); + static abstract void LdaexdT1(CodeGenContext context, uint encoding); + static abstract void LdaexhA1(CodeGenContext context, uint encoding); + static abstract void LdaexhT1(CodeGenContext context, uint encoding); + static abstract void LdahA1(CodeGenContext context, uint encoding); + static abstract void LdahT1(CodeGenContext context, uint encoding); + static abstract void LdcIA1(CodeGenContext context, uint encoding); + static abstract void LdcIT1(CodeGenContext context, uint encoding); + static abstract void LdcLA1(CodeGenContext context, uint encoding); + static abstract void LdcLT1(CodeGenContext context, uint encoding); + static abstract void LdmA1(CodeGenContext context, uint encoding); + static abstract void LdmT1(CodeGenContext context, uint encoding); + static abstract void LdmT2(CodeGenContext context, uint encoding); + static abstract void LdmdaA1(CodeGenContext context, uint encoding); + static abstract void LdmdbA1(CodeGenContext context, uint encoding); + static abstract void LdmdbT1(CodeGenContext context, uint encoding); + static abstract void LdmibA1(CodeGenContext context, uint encoding); + static abstract void LdmEA1(CodeGenContext context, uint encoding); + static abstract void LdmUA1(CodeGenContext context, uint encoding); + static abstract void LdrbtA1(CodeGenContext context, uint encoding); + static abstract void LdrbtA2(CodeGenContext context, uint encoding); + static abstract void LdrbtT1(CodeGenContext context, uint encoding); + static abstract void LdrbIA1(CodeGenContext context, uint encoding); + static abstract void LdrbIT1(CodeGenContext context, uint encoding); + static abstract void LdrbIT2(CodeGenContext context, uint encoding); + static abstract void LdrbIT3(CodeGenContext context, uint encoding); + static abstract void LdrbLA1(CodeGenContext context, uint encoding); + static abstract void LdrbLT1(CodeGenContext context, uint encoding); + static abstract void LdrbRA1(CodeGenContext context, uint encoding); + static abstract void LdrbRT1(CodeGenContext context, uint encoding); + static abstract void LdrbRT2(CodeGenContext context, uint encoding); + static abstract void LdrdIA1(CodeGenContext context, uint encoding); + static abstract void LdrdIT1(CodeGenContext context, uint encoding); + static abstract void LdrdLA1(CodeGenContext context, uint encoding); + static abstract void LdrdLT1(CodeGenContext context, uint encoding); + static abstract void LdrdRA1(CodeGenContext context, uint encoding); + static abstract void LdrexA1(CodeGenContext context, uint encoding); + static abstract void LdrexT1(CodeGenContext context, uint encoding); + static abstract void LdrexbA1(CodeGenContext context, uint encoding); + static abstract void LdrexbT1(CodeGenContext context, uint encoding); + static abstract void LdrexdA1(CodeGenContext context, uint encoding); + static abstract void LdrexdT1(CodeGenContext context, uint encoding); + static abstract void LdrexhA1(CodeGenContext context, uint encoding); + static abstract void LdrexhT1(CodeGenContext context, uint encoding); + static abstract void LdrhtA1(CodeGenContext context, uint encoding); + static abstract void LdrhtA2(CodeGenContext context, uint encoding); + static abstract void LdrhtT1(CodeGenContext context, uint encoding); + static abstract void LdrhIA1(CodeGenContext context, uint encoding); + static abstract void LdrhIT1(CodeGenContext context, uint encoding); + static abstract void LdrhIT2(CodeGenContext context, uint encoding); + static abstract void LdrhIT3(CodeGenContext context, uint encoding); + static abstract void LdrhLA1(CodeGenContext context, uint encoding); + static abstract void LdrhLT1(CodeGenContext context, uint encoding); + static abstract void LdrhRA1(CodeGenContext context, uint encoding); + static abstract void LdrhRT1(CodeGenContext context, uint encoding); + static abstract void LdrhRT2(CodeGenContext context, uint encoding); + static abstract void LdrsbtA1(CodeGenContext context, uint encoding); + static abstract void LdrsbtA2(CodeGenContext context, uint encoding); + static abstract void LdrsbtT1(CodeGenContext context, uint encoding); + static abstract void LdrsbIA1(CodeGenContext context, uint encoding); + static abstract void LdrsbIT1(CodeGenContext context, uint encoding); + static abstract void LdrsbIT2(CodeGenContext context, uint encoding); + static abstract void LdrsbLA1(CodeGenContext context, uint encoding); + static abstract void LdrsbLT1(CodeGenContext context, uint encoding); + static abstract void LdrsbRA1(CodeGenContext context, uint encoding); + static abstract void LdrsbRT1(CodeGenContext context, uint encoding); + static abstract void LdrsbRT2(CodeGenContext context, uint encoding); + static abstract void LdrshtA1(CodeGenContext context, uint encoding); + static abstract void LdrshtA2(CodeGenContext context, uint encoding); + static abstract void LdrshtT1(CodeGenContext context, uint encoding); + static abstract void LdrshIA1(CodeGenContext context, uint encoding); + static abstract void LdrshIT1(CodeGenContext context, uint encoding); + static abstract void LdrshIT2(CodeGenContext context, uint encoding); + static abstract void LdrshLA1(CodeGenContext context, uint encoding); + static abstract void LdrshLT1(CodeGenContext context, uint encoding); + static abstract void LdrshRA1(CodeGenContext context, uint encoding); + static abstract void LdrshRT1(CodeGenContext context, uint encoding); + static abstract void LdrshRT2(CodeGenContext context, uint encoding); + static abstract void LdrtA1(CodeGenContext context, uint encoding); + static abstract void LdrtA2(CodeGenContext context, uint encoding); + static abstract void LdrtT1(CodeGenContext context, uint encoding); + static abstract void LdrIA1(CodeGenContext context, uint encoding); + static abstract void LdrIT1(CodeGenContext context, uint encoding); + static abstract void LdrIT2(CodeGenContext context, uint encoding); + static abstract void LdrIT3(CodeGenContext context, uint encoding); + static abstract void LdrIT4(CodeGenContext context, uint encoding); + static abstract void LdrLA1(CodeGenContext context, uint encoding); + static abstract void LdrLT1(CodeGenContext context, uint encoding); + static abstract void LdrLT2(CodeGenContext context, uint encoding); + static abstract void LdrRA1(CodeGenContext context, uint encoding); + static abstract void LdrRT1(CodeGenContext context, uint encoding); + static abstract void LdrRT2(CodeGenContext context, uint encoding); + static abstract void McrA1(CodeGenContext context, uint encoding); + static abstract void McrT1(CodeGenContext context, uint encoding); + static abstract void McrrA1(CodeGenContext context, uint encoding); + static abstract void McrrT1(CodeGenContext context, uint encoding); + static abstract void MlaA1(CodeGenContext context, uint encoding); + static abstract void MlaT1(CodeGenContext context, uint encoding); + static abstract void MlsA1(CodeGenContext context, uint encoding); + static abstract void MlsT1(CodeGenContext context, uint encoding); + static abstract void MovtA1(CodeGenContext context, uint encoding); + static abstract void MovtT1(CodeGenContext context, uint encoding); + static abstract void MovIA1(CodeGenContext context, uint encoding); + static abstract void MovIA2(CodeGenContext context, uint encoding); + static abstract void MovIT1(CodeGenContext context, uint encoding); + static abstract void MovIT2(CodeGenContext context, uint encoding); + static abstract void MovIT3(CodeGenContext context, uint encoding); + static abstract void MovRA1(CodeGenContext context, uint encoding); + static abstract void MovRT1(CodeGenContext context, uint encoding); + static abstract void MovRT2(CodeGenContext context, uint encoding); + static abstract void MovRT3(CodeGenContext context, uint encoding); + static abstract void MovRrA1(CodeGenContext context, uint encoding); + static abstract void MovRrT1(CodeGenContext context, uint encoding); + static abstract void MovRrT2(CodeGenContext context, uint encoding); + static abstract void MrcA1(CodeGenContext context, uint encoding); + static abstract void MrcT1(CodeGenContext context, uint encoding); + static abstract void MrrcA1(CodeGenContext context, uint encoding); + static abstract void MrrcT1(CodeGenContext context, uint encoding); + static abstract void MrsA1(CodeGenContext context, uint encoding); + static abstract void MrsT1(CodeGenContext context, uint encoding); + static abstract void MrsBrA1(CodeGenContext context, uint encoding); + static abstract void MrsBrT1(CodeGenContext context, uint encoding); + static abstract void MsrBrA1(CodeGenContext context, uint encoding); + static abstract void MsrBrT1(CodeGenContext context, uint encoding); + static abstract void MsrIA1(CodeGenContext context, uint encoding); + static abstract void MsrRA1(CodeGenContext context, uint encoding); + static abstract void MsrRT1(CodeGenContext context, uint encoding); + static abstract void MulA1(CodeGenContext context, uint encoding); + static abstract void MulT1(CodeGenContext context, uint encoding); + static abstract void MulT2(CodeGenContext context, uint encoding); + static abstract void MvnIA1(CodeGenContext context, uint encoding); + static abstract void MvnIT1(CodeGenContext context, uint encoding); + static abstract void MvnRA1(CodeGenContext context, uint encoding); + static abstract void MvnRT1(CodeGenContext context, uint encoding); + static abstract void MvnRT2(CodeGenContext context, uint encoding); + static abstract void MvnRrA1(CodeGenContext context, uint encoding); + static abstract void NopA1(CodeGenContext context, uint encoding); + static abstract void NopT1(CodeGenContext context, uint encoding); + static abstract void NopT2(CodeGenContext context, uint encoding); + static abstract void OrnIT1(CodeGenContext context, uint encoding); + static abstract void OrnRT1(CodeGenContext context, uint encoding); + static abstract void OrrIA1(CodeGenContext context, uint encoding); + static abstract void OrrIT1(CodeGenContext context, uint encoding); + static abstract void OrrRA1(CodeGenContext context, uint encoding); + static abstract void OrrRT1(CodeGenContext context, uint encoding); + static abstract void OrrRT2(CodeGenContext context, uint encoding); + static abstract void OrrRrA1(CodeGenContext context, uint encoding); + static abstract void PkhA1(CodeGenContext context, uint encoding); + static abstract void PkhT1(CodeGenContext context, uint encoding); + static abstract void PldIA1(CodeGenContext context, uint encoding); + static abstract void PldIT1(CodeGenContext context, uint encoding); + static abstract void PldIT2(CodeGenContext context, uint encoding); + static abstract void PldLA1(CodeGenContext context, uint encoding); + static abstract void PldLT1(CodeGenContext context, uint encoding); + static abstract void PldRA1(CodeGenContext context, uint encoding); + static abstract void PldRT1(CodeGenContext context, uint encoding); + static abstract void PliIA1(CodeGenContext context, uint encoding); + static abstract void PliIT1(CodeGenContext context, uint encoding); + static abstract void PliIT2(CodeGenContext context, uint encoding); + static abstract void PliIT3(CodeGenContext context, uint encoding); + static abstract void PliRA1(CodeGenContext context, uint encoding); + static abstract void PliRT1(CodeGenContext context, uint encoding); + static abstract void PopT1(CodeGenContext context, uint encoding); + static abstract void PssbbA1(CodeGenContext context, uint encoding); + static abstract void PssbbT1(CodeGenContext context, uint encoding); + static abstract void PushT1(CodeGenContext context, uint encoding); + static abstract void QaddA1(CodeGenContext context, uint encoding); + static abstract void QaddT1(CodeGenContext context, uint encoding); + static abstract void Qadd16A1(CodeGenContext context, uint encoding); + static abstract void Qadd16T1(CodeGenContext context, uint encoding); + static abstract void Qadd8A1(CodeGenContext context, uint encoding); + static abstract void Qadd8T1(CodeGenContext context, uint encoding); + static abstract void QasxA1(CodeGenContext context, uint encoding); + static abstract void QasxT1(CodeGenContext context, uint encoding); + static abstract void QdaddA1(CodeGenContext context, uint encoding); + static abstract void QdaddT1(CodeGenContext context, uint encoding); + static abstract void QdsubA1(CodeGenContext context, uint encoding); + static abstract void QdsubT1(CodeGenContext context, uint encoding); + static abstract void QsaxA1(CodeGenContext context, uint encoding); + static abstract void QsaxT1(CodeGenContext context, uint encoding); + static abstract void QsubA1(CodeGenContext context, uint encoding); + static abstract void QsubT1(CodeGenContext context, uint encoding); + static abstract void Qsub16A1(CodeGenContext context, uint encoding); + static abstract void Qsub16T1(CodeGenContext context, uint encoding); + static abstract void Qsub8A1(CodeGenContext context, uint encoding); + static abstract void Qsub8T1(CodeGenContext context, uint encoding); + static abstract void RbitA1(CodeGenContext context, uint encoding); + static abstract void RbitT1(CodeGenContext context, uint encoding); + static abstract void RevA1(CodeGenContext context, uint encoding); + static abstract void RevT1(CodeGenContext context, uint encoding); + static abstract void RevT2(CodeGenContext context, uint encoding); + static abstract void Rev16A1(CodeGenContext context, uint encoding); + static abstract void Rev16T1(CodeGenContext context, uint encoding); + static abstract void Rev16T2(CodeGenContext context, uint encoding); + static abstract void RevshA1(CodeGenContext context, uint encoding); + static abstract void RevshT1(CodeGenContext context, uint encoding); + static abstract void RevshT2(CodeGenContext context, uint encoding); + static abstract void RfeA1(CodeGenContext context, uint encoding); + static abstract void RfeT1(CodeGenContext context, uint encoding); + static abstract void RfeT2(CodeGenContext context, uint encoding); + static abstract void RsbIA1(CodeGenContext context, uint encoding); + static abstract void RsbIT1(CodeGenContext context, uint encoding); + static abstract void RsbIT2(CodeGenContext context, uint encoding); + static abstract void RsbRA1(CodeGenContext context, uint encoding); + static abstract void RsbRT1(CodeGenContext context, uint encoding); + static abstract void RsbRrA1(CodeGenContext context, uint encoding); + static abstract void RscIA1(CodeGenContext context, uint encoding); + static abstract void RscRA1(CodeGenContext context, uint encoding); + static abstract void RscRrA1(CodeGenContext context, uint encoding); + static abstract void Sadd16A1(CodeGenContext context, uint encoding); + static abstract void Sadd16T1(CodeGenContext context, uint encoding); + static abstract void Sadd8A1(CodeGenContext context, uint encoding); + static abstract void Sadd8T1(CodeGenContext context, uint encoding); + static abstract void SasxA1(CodeGenContext context, uint encoding); + static abstract void SasxT1(CodeGenContext context, uint encoding); + static abstract void SbA1(CodeGenContext context, uint encoding); + static abstract void SbT1(CodeGenContext context, uint encoding); + static abstract void SbcIA1(CodeGenContext context, uint encoding); + static abstract void SbcIT1(CodeGenContext context, uint encoding); + static abstract void SbcRA1(CodeGenContext context, uint encoding); + static abstract void SbcRT1(CodeGenContext context, uint encoding); + static abstract void SbcRT2(CodeGenContext context, uint encoding); + static abstract void SbcRrA1(CodeGenContext context, uint encoding); + static abstract void SbfxA1(CodeGenContext context, uint encoding); + static abstract void SbfxT1(CodeGenContext context, uint encoding); + static abstract void SdivA1(CodeGenContext context, uint encoding); + static abstract void SdivT1(CodeGenContext context, uint encoding); + static abstract void SelA1(CodeGenContext context, uint encoding); + static abstract void SelT1(CodeGenContext context, uint encoding); + static abstract void SetendA1(CodeGenContext context, uint encoding); + static abstract void SetendT1(CodeGenContext context, uint encoding); + static abstract void SetpanA1(CodeGenContext context, uint encoding); + static abstract void SetpanT1(CodeGenContext context, uint encoding); + static abstract void SevA1(CodeGenContext context, uint encoding); + static abstract void SevT1(CodeGenContext context, uint encoding); + static abstract void SevT2(CodeGenContext context, uint encoding); + static abstract void SevlA1(CodeGenContext context, uint encoding); + static abstract void SevlT1(CodeGenContext context, uint encoding); + static abstract void SevlT2(CodeGenContext context, uint encoding); + static abstract void Sha1cA1(CodeGenContext context, uint encoding); + static abstract void Sha1cT1(CodeGenContext context, uint encoding); + static abstract void Sha1hA1(CodeGenContext context, uint encoding); + static abstract void Sha1hT1(CodeGenContext context, uint encoding); + static abstract void Sha1mA1(CodeGenContext context, uint encoding); + static abstract void Sha1mT1(CodeGenContext context, uint encoding); + static abstract void Sha1pA1(CodeGenContext context, uint encoding); + static abstract void Sha1pT1(CodeGenContext context, uint encoding); + static abstract void Sha1su0A1(CodeGenContext context, uint encoding); + static abstract void Sha1su0T1(CodeGenContext context, uint encoding); + static abstract void Sha1su1A1(CodeGenContext context, uint encoding); + static abstract void Sha1su1T1(CodeGenContext context, uint encoding); + static abstract void Sha256hA1(CodeGenContext context, uint encoding); + static abstract void Sha256hT1(CodeGenContext context, uint encoding); + static abstract void Sha256h2A1(CodeGenContext context, uint encoding); + static abstract void Sha256h2T1(CodeGenContext context, uint encoding); + static abstract void Sha256su0A1(CodeGenContext context, uint encoding); + static abstract void Sha256su0T1(CodeGenContext context, uint encoding); + static abstract void Sha256su1A1(CodeGenContext context, uint encoding); + static abstract void Sha256su1T1(CodeGenContext context, uint encoding); + static abstract void Shadd16A1(CodeGenContext context, uint encoding); + static abstract void Shadd16T1(CodeGenContext context, uint encoding); + static abstract void Shadd8A1(CodeGenContext context, uint encoding); + static abstract void Shadd8T1(CodeGenContext context, uint encoding); + static abstract void ShasxA1(CodeGenContext context, uint encoding); + static abstract void ShasxT1(CodeGenContext context, uint encoding); + static abstract void ShsaxA1(CodeGenContext context, uint encoding); + static abstract void ShsaxT1(CodeGenContext context, uint encoding); + static abstract void Shsub16A1(CodeGenContext context, uint encoding); + static abstract void Shsub16T1(CodeGenContext context, uint encoding); + static abstract void Shsub8A1(CodeGenContext context, uint encoding); + static abstract void Shsub8T1(CodeGenContext context, uint encoding); + static abstract void SmcA1(CodeGenContext context, uint encoding); + static abstract void SmcT1(CodeGenContext context, uint encoding); + static abstract void SmlabbA1(CodeGenContext context, uint encoding); + static abstract void SmlabbT1(CodeGenContext context, uint encoding); + static abstract void SmladA1(CodeGenContext context, uint encoding); + static abstract void SmladT1(CodeGenContext context, uint encoding); + static abstract void SmlalA1(CodeGenContext context, uint encoding); + static abstract void SmlalT1(CodeGenContext context, uint encoding); + static abstract void SmlalbbA1(CodeGenContext context, uint encoding); + static abstract void SmlalbbT1(CodeGenContext context, uint encoding); + static abstract void SmlaldA1(CodeGenContext context, uint encoding); + static abstract void SmlaldT1(CodeGenContext context, uint encoding); + static abstract void SmlawbA1(CodeGenContext context, uint encoding); + static abstract void SmlawbT1(CodeGenContext context, uint encoding); + static abstract void SmlsdA1(CodeGenContext context, uint encoding); + static abstract void SmlsdT1(CodeGenContext context, uint encoding); + static abstract void SmlsldA1(CodeGenContext context, uint encoding); + static abstract void SmlsldT1(CodeGenContext context, uint encoding); + static abstract void SmmlaA1(CodeGenContext context, uint encoding); + static abstract void SmmlaT1(CodeGenContext context, uint encoding); + static abstract void SmmlsA1(CodeGenContext context, uint encoding); + static abstract void SmmlsT1(CodeGenContext context, uint encoding); + static abstract void SmmulA1(CodeGenContext context, uint encoding); + static abstract void SmmulT1(CodeGenContext context, uint encoding); + static abstract void SmuadA1(CodeGenContext context, uint encoding); + static abstract void SmuadT1(CodeGenContext context, uint encoding); + static abstract void SmulbbA1(CodeGenContext context, uint encoding); + static abstract void SmulbbT1(CodeGenContext context, uint encoding); + static abstract void SmullA1(CodeGenContext context, uint encoding); + static abstract void SmullT1(CodeGenContext context, uint encoding); + static abstract void SmulwbA1(CodeGenContext context, uint encoding); + static abstract void SmulwbT1(CodeGenContext context, uint encoding); + static abstract void SmusdA1(CodeGenContext context, uint encoding); + static abstract void SmusdT1(CodeGenContext context, uint encoding); + static abstract void SrsA1(CodeGenContext context, uint encoding); + static abstract void SrsT1(CodeGenContext context, uint encoding); + static abstract void SrsT2(CodeGenContext context, uint encoding); + static abstract void SsatA1(CodeGenContext context, uint encoding); + static abstract void SsatT1(CodeGenContext context, uint encoding); + static abstract void Ssat16A1(CodeGenContext context, uint encoding); + static abstract void Ssat16T1(CodeGenContext context, uint encoding); + static abstract void SsaxA1(CodeGenContext context, uint encoding); + static abstract void SsaxT1(CodeGenContext context, uint encoding); + static abstract void SsbbA1(CodeGenContext context, uint encoding); + static abstract void SsbbT1(CodeGenContext context, uint encoding); + static abstract void Ssub16A1(CodeGenContext context, uint encoding); + static abstract void Ssub16T1(CodeGenContext context, uint encoding); + static abstract void Ssub8A1(CodeGenContext context, uint encoding); + static abstract void Ssub8T1(CodeGenContext context, uint encoding); + static abstract void StcA1(CodeGenContext context, uint encoding); + static abstract void StcT1(CodeGenContext context, uint encoding); + static abstract void StlA1(CodeGenContext context, uint encoding); + static abstract void StlT1(CodeGenContext context, uint encoding); + static abstract void StlbA1(CodeGenContext context, uint encoding); + static abstract void StlbT1(CodeGenContext context, uint encoding); + static abstract void StlexA1(CodeGenContext context, uint encoding); + static abstract void StlexT1(CodeGenContext context, uint encoding); + static abstract void StlexbA1(CodeGenContext context, uint encoding); + static abstract void StlexbT1(CodeGenContext context, uint encoding); + static abstract void StlexdA1(CodeGenContext context, uint encoding); + static abstract void StlexdT1(CodeGenContext context, uint encoding); + static abstract void StlexhA1(CodeGenContext context, uint encoding); + static abstract void StlexhT1(CodeGenContext context, uint encoding); + static abstract void StlhA1(CodeGenContext context, uint encoding); + static abstract void StlhT1(CodeGenContext context, uint encoding); + static abstract void StmA1(CodeGenContext context, uint encoding); + static abstract void StmT1(CodeGenContext context, uint encoding); + static abstract void StmT2(CodeGenContext context, uint encoding); + static abstract void StmdaA1(CodeGenContext context, uint encoding); + static abstract void StmdbA1(CodeGenContext context, uint encoding); + static abstract void StmdbT1(CodeGenContext context, uint encoding); + static abstract void StmibA1(CodeGenContext context, uint encoding); + static abstract void StmUA1(CodeGenContext context, uint encoding); + static abstract void StrbtA1(CodeGenContext context, uint encoding); + static abstract void StrbtA2(CodeGenContext context, uint encoding); + static abstract void StrbtT1(CodeGenContext context, uint encoding); + static abstract void StrbIA1(CodeGenContext context, uint encoding); + static abstract void StrbIT1(CodeGenContext context, uint encoding); + static abstract void StrbIT2(CodeGenContext context, uint encoding); + static abstract void StrbIT3(CodeGenContext context, uint encoding); + static abstract void StrbRA1(CodeGenContext context, uint encoding); + static abstract void StrbRT1(CodeGenContext context, uint encoding); + static abstract void StrbRT2(CodeGenContext context, uint encoding); + static abstract void StrdIA1(CodeGenContext context, uint encoding); + static abstract void StrdIT1(CodeGenContext context, uint encoding); + static abstract void StrdRA1(CodeGenContext context, uint encoding); + static abstract void StrexA1(CodeGenContext context, uint encoding); + static abstract void StrexT1(CodeGenContext context, uint encoding); + static abstract void StrexbA1(CodeGenContext context, uint encoding); + static abstract void StrexbT1(CodeGenContext context, uint encoding); + static abstract void StrexdA1(CodeGenContext context, uint encoding); + static abstract void StrexdT1(CodeGenContext context, uint encoding); + static abstract void StrexhA1(CodeGenContext context, uint encoding); + static abstract void StrexhT1(CodeGenContext context, uint encoding); + static abstract void StrhtA1(CodeGenContext context, uint encoding); + static abstract void StrhtA2(CodeGenContext context, uint encoding); + static abstract void StrhtT1(CodeGenContext context, uint encoding); + static abstract void StrhIA1(CodeGenContext context, uint encoding); + static abstract void StrhIT1(CodeGenContext context, uint encoding); + static abstract void StrhIT2(CodeGenContext context, uint encoding); + static abstract void StrhIT3(CodeGenContext context, uint encoding); + static abstract void StrhRA1(CodeGenContext context, uint encoding); + static abstract void StrhRT1(CodeGenContext context, uint encoding); + static abstract void StrhRT2(CodeGenContext context, uint encoding); + static abstract void StrtA1(CodeGenContext context, uint encoding); + static abstract void StrtA2(CodeGenContext context, uint encoding); + static abstract void StrtT1(CodeGenContext context, uint encoding); + static abstract void StrIA1(CodeGenContext context, uint encoding); + static abstract void StrIT1(CodeGenContext context, uint encoding); + static abstract void StrIT2(CodeGenContext context, uint encoding); + static abstract void StrIT3(CodeGenContext context, uint encoding); + static abstract void StrIT4(CodeGenContext context, uint encoding); + static abstract void StrRA1(CodeGenContext context, uint encoding); + static abstract void StrRT1(CodeGenContext context, uint encoding); + static abstract void StrRT2(CodeGenContext context, uint encoding); + static abstract void SubIA1(CodeGenContext context, uint encoding); + static abstract void SubIT1(CodeGenContext context, uint encoding); + static abstract void SubIT2(CodeGenContext context, uint encoding); + static abstract void SubIT3(CodeGenContext context, uint encoding); + static abstract void SubIT4(CodeGenContext context, uint encoding); + static abstract void SubIT5(CodeGenContext context, uint encoding); + static abstract void SubRA1(CodeGenContext context, uint encoding); + static abstract void SubRT1(CodeGenContext context, uint encoding); + static abstract void SubRT2(CodeGenContext context, uint encoding); + static abstract void SubRrA1(CodeGenContext context, uint encoding); + static abstract void SubSpIA1(CodeGenContext context, uint encoding); + static abstract void SubSpIT1(CodeGenContext context, uint encoding); + static abstract void SubSpIT2(CodeGenContext context, uint encoding); + static abstract void SubSpIT3(CodeGenContext context, uint encoding); + static abstract void SubSpRA1(CodeGenContext context, uint encoding); + static abstract void SubSpRT1(CodeGenContext context, uint encoding); + static abstract void SvcA1(CodeGenContext context, uint encoding); + static abstract void SvcT1(CodeGenContext context, uint encoding); + static abstract void SxtabA1(CodeGenContext context, uint encoding); + static abstract void SxtabT1(CodeGenContext context, uint encoding); + static abstract void Sxtab16A1(CodeGenContext context, uint encoding); + static abstract void Sxtab16T1(CodeGenContext context, uint encoding); + static abstract void SxtahA1(CodeGenContext context, uint encoding); + static abstract void SxtahT1(CodeGenContext context, uint encoding); + static abstract void SxtbA1(CodeGenContext context, uint encoding); + static abstract void SxtbT1(CodeGenContext context, uint encoding); + static abstract void SxtbT2(CodeGenContext context, uint encoding); + static abstract void Sxtb16A1(CodeGenContext context, uint encoding); + static abstract void Sxtb16T1(CodeGenContext context, uint encoding); + static abstract void SxthA1(CodeGenContext context, uint encoding); + static abstract void SxthT1(CodeGenContext context, uint encoding); + static abstract void SxthT2(CodeGenContext context, uint encoding); + static abstract void TbbT1(CodeGenContext context, uint encoding); + static abstract void TeqIA1(CodeGenContext context, uint encoding); + static abstract void TeqIT1(CodeGenContext context, uint encoding); + static abstract void TeqRA1(CodeGenContext context, uint encoding); + static abstract void TeqRT1(CodeGenContext context, uint encoding); + static abstract void TeqRrA1(CodeGenContext context, uint encoding); + static abstract void TsbA1(CodeGenContext context, uint encoding); + static abstract void TsbT1(CodeGenContext context, uint encoding); + static abstract void TstIA1(CodeGenContext context, uint encoding); + static abstract void TstIT1(CodeGenContext context, uint encoding); + static abstract void TstRA1(CodeGenContext context, uint encoding); + static abstract void TstRT1(CodeGenContext context, uint encoding); + static abstract void TstRT2(CodeGenContext context, uint encoding); + static abstract void TstRrA1(CodeGenContext context, uint encoding); + static abstract void Uadd16A1(CodeGenContext context, uint encoding); + static abstract void Uadd16T1(CodeGenContext context, uint encoding); + static abstract void Uadd8A1(CodeGenContext context, uint encoding); + static abstract void Uadd8T1(CodeGenContext context, uint encoding); + static abstract void UasxA1(CodeGenContext context, uint encoding); + static abstract void UasxT1(CodeGenContext context, uint encoding); + static abstract void UbfxA1(CodeGenContext context, uint encoding); + static abstract void UbfxT1(CodeGenContext context, uint encoding); + static abstract void UdfA1(CodeGenContext context, uint encoding); + static abstract void UdfT1(CodeGenContext context, uint encoding); + static abstract void UdfT2(CodeGenContext context, uint encoding); + static abstract void UdivA1(CodeGenContext context, uint encoding); + static abstract void UdivT1(CodeGenContext context, uint encoding); + static abstract void Uhadd16A1(CodeGenContext context, uint encoding); + static abstract void Uhadd16T1(CodeGenContext context, uint encoding); + static abstract void Uhadd8A1(CodeGenContext context, uint encoding); + static abstract void Uhadd8T1(CodeGenContext context, uint encoding); + static abstract void UhasxA1(CodeGenContext context, uint encoding); + static abstract void UhasxT1(CodeGenContext context, uint encoding); + static abstract void UhsaxA1(CodeGenContext context, uint encoding); + static abstract void UhsaxT1(CodeGenContext context, uint encoding); + static abstract void Uhsub16A1(CodeGenContext context, uint encoding); + static abstract void Uhsub16T1(CodeGenContext context, uint encoding); + static abstract void Uhsub8A1(CodeGenContext context, uint encoding); + static abstract void Uhsub8T1(CodeGenContext context, uint encoding); + static abstract void UmaalA1(CodeGenContext context, uint encoding); + static abstract void UmaalT1(CodeGenContext context, uint encoding); + static abstract void UmlalA1(CodeGenContext context, uint encoding); + static abstract void UmlalT1(CodeGenContext context, uint encoding); + static abstract void UmullA1(CodeGenContext context, uint encoding); + static abstract void UmullT1(CodeGenContext context, uint encoding); + static abstract void Uqadd16A1(CodeGenContext context, uint encoding); + static abstract void Uqadd16T1(CodeGenContext context, uint encoding); + static abstract void Uqadd8A1(CodeGenContext context, uint encoding); + static abstract void Uqadd8T1(CodeGenContext context, uint encoding); + static abstract void UqasxA1(CodeGenContext context, uint encoding); + static abstract void UqasxT1(CodeGenContext context, uint encoding); + static abstract void UqsaxA1(CodeGenContext context, uint encoding); + static abstract void UqsaxT1(CodeGenContext context, uint encoding); + static abstract void Uqsub16A1(CodeGenContext context, uint encoding); + static abstract void Uqsub16T1(CodeGenContext context, uint encoding); + static abstract void Uqsub8A1(CodeGenContext context, uint encoding); + static abstract void Uqsub8T1(CodeGenContext context, uint encoding); + static abstract void Usad8A1(CodeGenContext context, uint encoding); + static abstract void Usad8T1(CodeGenContext context, uint encoding); + static abstract void Usada8A1(CodeGenContext context, uint encoding); + static abstract void Usada8T1(CodeGenContext context, uint encoding); + static abstract void UsatA1(CodeGenContext context, uint encoding); + static abstract void UsatT1(CodeGenContext context, uint encoding); + static abstract void Usat16A1(CodeGenContext context, uint encoding); + static abstract void Usat16T1(CodeGenContext context, uint encoding); + static abstract void UsaxA1(CodeGenContext context, uint encoding); + static abstract void UsaxT1(CodeGenContext context, uint encoding); + static abstract void Usub16A1(CodeGenContext context, uint encoding); + static abstract void Usub16T1(CodeGenContext context, uint encoding); + static abstract void Usub8A1(CodeGenContext context, uint encoding); + static abstract void Usub8T1(CodeGenContext context, uint encoding); + static abstract void UxtabA1(CodeGenContext context, uint encoding); + static abstract void UxtabT1(CodeGenContext context, uint encoding); + static abstract void Uxtab16A1(CodeGenContext context, uint encoding); + static abstract void Uxtab16T1(CodeGenContext context, uint encoding); + static abstract void UxtahA1(CodeGenContext context, uint encoding); + static abstract void UxtahT1(CodeGenContext context, uint encoding); + static abstract void UxtbA1(CodeGenContext context, uint encoding); + static abstract void UxtbT1(CodeGenContext context, uint encoding); + static abstract void UxtbT2(CodeGenContext context, uint encoding); + static abstract void Uxtb16A1(CodeGenContext context, uint encoding); + static abstract void Uxtb16T1(CodeGenContext context, uint encoding); + static abstract void UxthA1(CodeGenContext context, uint encoding); + static abstract void UxthT1(CodeGenContext context, uint encoding); + static abstract void UxthT2(CodeGenContext context, uint encoding); + static abstract void VabaA1(CodeGenContext context, uint encoding); + static abstract void VabaT1(CodeGenContext context, uint encoding); + static abstract void VabalA1(CodeGenContext context, uint encoding); + static abstract void VabalT1(CodeGenContext context, uint encoding); + static abstract void VabdlIA1(CodeGenContext context, uint encoding); + static abstract void VabdlIT1(CodeGenContext context, uint encoding); + static abstract void VabdFA1(CodeGenContext context, uint encoding); + static abstract void VabdFT1(CodeGenContext context, uint encoding); + static abstract void VabdIA1(CodeGenContext context, uint encoding); + static abstract void VabdIT1(CodeGenContext context, uint encoding); + static abstract void VabsA1(CodeGenContext context, uint encoding); + static abstract void VabsA2(CodeGenContext context, uint encoding); + static abstract void VabsT1(CodeGenContext context, uint encoding); + static abstract void VabsT2(CodeGenContext context, uint encoding); + static abstract void VacgeA1(CodeGenContext context, uint encoding); + static abstract void VacgeT1(CodeGenContext context, uint encoding); + static abstract void VacgtA1(CodeGenContext context, uint encoding); + static abstract void VacgtT1(CodeGenContext context, uint encoding); + static abstract void VaddhnA1(CodeGenContext context, uint encoding); + static abstract void VaddhnT1(CodeGenContext context, uint encoding); + static abstract void VaddlA1(CodeGenContext context, uint encoding); + static abstract void VaddlT1(CodeGenContext context, uint encoding); + static abstract void VaddwA1(CodeGenContext context, uint encoding); + static abstract void VaddwT1(CodeGenContext context, uint encoding); + static abstract void VaddFA1(CodeGenContext context, uint encoding); + static abstract void VaddFA2(CodeGenContext context, uint encoding); + static abstract void VaddFT1(CodeGenContext context, uint encoding); + static abstract void VaddFT2(CodeGenContext context, uint encoding); + static abstract void VaddIA1(CodeGenContext context, uint encoding); + static abstract void VaddIT1(CodeGenContext context, uint encoding); + static abstract void VandRA1(CodeGenContext context, uint encoding); + static abstract void VandRT1(CodeGenContext context, uint encoding); + static abstract void VbicIA1(CodeGenContext context, uint encoding); + static abstract void VbicIA2(CodeGenContext context, uint encoding); + static abstract void VbicIT1(CodeGenContext context, uint encoding); + static abstract void VbicIT2(CodeGenContext context, uint encoding); + static abstract void VbicRA1(CodeGenContext context, uint encoding); + static abstract void VbicRT1(CodeGenContext context, uint encoding); + static abstract void VbifA1(CodeGenContext context, uint encoding); + static abstract void VbifT1(CodeGenContext context, uint encoding); + static abstract void VbitA1(CodeGenContext context, uint encoding); + static abstract void VbitT1(CodeGenContext context, uint encoding); + static abstract void VbslA1(CodeGenContext context, uint encoding); + static abstract void VbslT1(CodeGenContext context, uint encoding); + static abstract void VcaddA1(CodeGenContext context, uint encoding); + static abstract void VcaddT1(CodeGenContext context, uint encoding); + static abstract void VceqIA1(CodeGenContext context, uint encoding); + static abstract void VceqIT1(CodeGenContext context, uint encoding); + static abstract void VceqRA1(CodeGenContext context, uint encoding); + static abstract void VceqRA2(CodeGenContext context, uint encoding); + static abstract void VceqRT1(CodeGenContext context, uint encoding); + static abstract void VceqRT2(CodeGenContext context, uint encoding); + static abstract void VcgeIA1(CodeGenContext context, uint encoding); + static abstract void VcgeIT1(CodeGenContext context, uint encoding); + static abstract void VcgeRA1(CodeGenContext context, uint encoding); + static abstract void VcgeRA2(CodeGenContext context, uint encoding); + static abstract void VcgeRT1(CodeGenContext context, uint encoding); + static abstract void VcgeRT2(CodeGenContext context, uint encoding); + static abstract void VcgtIA1(CodeGenContext context, uint encoding); + static abstract void VcgtIT1(CodeGenContext context, uint encoding); + static abstract void VcgtRA1(CodeGenContext context, uint encoding); + static abstract void VcgtRA2(CodeGenContext context, uint encoding); + static abstract void VcgtRT1(CodeGenContext context, uint encoding); + static abstract void VcgtRT2(CodeGenContext context, uint encoding); + static abstract void VcleIA1(CodeGenContext context, uint encoding); + static abstract void VcleIT1(CodeGenContext context, uint encoding); + static abstract void VclsA1(CodeGenContext context, uint encoding); + static abstract void VclsT1(CodeGenContext context, uint encoding); + static abstract void VcltIA1(CodeGenContext context, uint encoding); + static abstract void VcltIT1(CodeGenContext context, uint encoding); + static abstract void VclzA1(CodeGenContext context, uint encoding); + static abstract void VclzT1(CodeGenContext context, uint encoding); + static abstract void VcmlaA1(CodeGenContext context, uint encoding); + static abstract void VcmlaT1(CodeGenContext context, uint encoding); + static abstract void VcmlaSA1(CodeGenContext context, uint encoding); + static abstract void VcmlaST1(CodeGenContext context, uint encoding); + static abstract void VcmpA1(CodeGenContext context, uint encoding); + static abstract void VcmpA2(CodeGenContext context, uint encoding); + static abstract void VcmpT1(CodeGenContext context, uint encoding); + static abstract void VcmpT2(CodeGenContext context, uint encoding); + static abstract void VcmpeA1(CodeGenContext context, uint encoding); + static abstract void VcmpeA2(CodeGenContext context, uint encoding); + static abstract void VcmpeT1(CodeGenContext context, uint encoding); + static abstract void VcmpeT2(CodeGenContext context, uint encoding); + static abstract void VcntA1(CodeGenContext context, uint encoding); + static abstract void VcntT1(CodeGenContext context, uint encoding); + static abstract void VcvtaAsimdA1(CodeGenContext context, uint encoding); + static abstract void VcvtaAsimdT1(CodeGenContext context, uint encoding); + static abstract void VcvtaVfpA1(CodeGenContext context, uint encoding); + static abstract void VcvtaVfpT1(CodeGenContext context, uint encoding); + static abstract void VcvtbA1(CodeGenContext context, uint encoding); + static abstract void VcvtbT1(CodeGenContext context, uint encoding); + static abstract void VcvtbBfsA1(CodeGenContext context, uint encoding); + static abstract void VcvtbBfsT1(CodeGenContext context, uint encoding); + static abstract void VcvtmAsimdA1(CodeGenContext context, uint encoding); + static abstract void VcvtmAsimdT1(CodeGenContext context, uint encoding); + static abstract void VcvtmVfpA1(CodeGenContext context, uint encoding); + static abstract void VcvtmVfpT1(CodeGenContext context, uint encoding); + static abstract void VcvtnAsimdA1(CodeGenContext context, uint encoding); + static abstract void VcvtnAsimdT1(CodeGenContext context, uint encoding); + static abstract void VcvtnVfpA1(CodeGenContext context, uint encoding); + static abstract void VcvtnVfpT1(CodeGenContext context, uint encoding); + static abstract void VcvtpAsimdA1(CodeGenContext context, uint encoding); + static abstract void VcvtpAsimdT1(CodeGenContext context, uint encoding); + static abstract void VcvtpVfpA1(CodeGenContext context, uint encoding); + static abstract void VcvtpVfpT1(CodeGenContext context, uint encoding); + static abstract void VcvtrIvA1(CodeGenContext context, uint encoding); + static abstract void VcvtrIvT1(CodeGenContext context, uint encoding); + static abstract void VcvttA1(CodeGenContext context, uint encoding); + static abstract void VcvttT1(CodeGenContext context, uint encoding); + static abstract void VcvttBfsA1(CodeGenContext context, uint encoding); + static abstract void VcvttBfsT1(CodeGenContext context, uint encoding); + static abstract void VcvtBfsA1(CodeGenContext context, uint encoding); + static abstract void VcvtBfsT1(CodeGenContext context, uint encoding); + static abstract void VcvtDsA1(CodeGenContext context, uint encoding); + static abstract void VcvtDsT1(CodeGenContext context, uint encoding); + static abstract void VcvtHsA1(CodeGenContext context, uint encoding); + static abstract void VcvtHsT1(CodeGenContext context, uint encoding); + static abstract void VcvtIsA1(CodeGenContext context, uint encoding); + static abstract void VcvtIsT1(CodeGenContext context, uint encoding); + static abstract void VcvtIvA1(CodeGenContext context, uint encoding); + static abstract void VcvtIvT1(CodeGenContext context, uint encoding); + static abstract void VcvtViA1(CodeGenContext context, uint encoding); + static abstract void VcvtViT1(CodeGenContext context, uint encoding); + static abstract void VcvtXsA1(CodeGenContext context, uint encoding); + static abstract void VcvtXsT1(CodeGenContext context, uint encoding); + static abstract void VcvtXvA1(CodeGenContext context, uint encoding); + static abstract void VcvtXvT1(CodeGenContext context, uint encoding); + static abstract void VdivA1(CodeGenContext context, uint encoding); + static abstract void VdivT1(CodeGenContext context, uint encoding); + static abstract void VdotA1(CodeGenContext context, uint encoding); + static abstract void VdotT1(CodeGenContext context, uint encoding); + static abstract void VdotSA1(CodeGenContext context, uint encoding); + static abstract void VdotST1(CodeGenContext context, uint encoding); + static abstract void VdupRA1(CodeGenContext context, uint encoding); + static abstract void VdupRT1(CodeGenContext context, uint encoding); + static abstract void VdupSA1(CodeGenContext context, uint encoding); + static abstract void VdupST1(CodeGenContext context, uint encoding); + static abstract void VeorA1(CodeGenContext context, uint encoding); + static abstract void VeorT1(CodeGenContext context, uint encoding); + static abstract void VextA1(CodeGenContext context, uint encoding); + static abstract void VextT1(CodeGenContext context, uint encoding); + static abstract void VfmaA1(CodeGenContext context, uint encoding); + static abstract void VfmaA2(CodeGenContext context, uint encoding); + static abstract void VfmaT1(CodeGenContext context, uint encoding); + static abstract void VfmaT2(CodeGenContext context, uint encoding); + static abstract void VfmalA1(CodeGenContext context, uint encoding); + static abstract void VfmalT1(CodeGenContext context, uint encoding); + static abstract void VfmalSA1(CodeGenContext context, uint encoding); + static abstract void VfmalST1(CodeGenContext context, uint encoding); + static abstract void VfmaBfA1(CodeGenContext context, uint encoding); + static abstract void VfmaBfT1(CodeGenContext context, uint encoding); + static abstract void VfmaBfsA1(CodeGenContext context, uint encoding); + static abstract void VfmaBfsT1(CodeGenContext context, uint encoding); + static abstract void VfmsA1(CodeGenContext context, uint encoding); + static abstract void VfmsA2(CodeGenContext context, uint encoding); + static abstract void VfmsT1(CodeGenContext context, uint encoding); + static abstract void VfmsT2(CodeGenContext context, uint encoding); + static abstract void VfmslA1(CodeGenContext context, uint encoding); + static abstract void VfmslT1(CodeGenContext context, uint encoding); + static abstract void VfmslSA1(CodeGenContext context, uint encoding); + static abstract void VfmslST1(CodeGenContext context, uint encoding); + static abstract void VfnmaA1(CodeGenContext context, uint encoding); + static abstract void VfnmaT1(CodeGenContext context, uint encoding); + static abstract void VfnmsA1(CodeGenContext context, uint encoding); + static abstract void VfnmsT1(CodeGenContext context, uint encoding); + static abstract void VhaddA1(CodeGenContext context, uint encoding); + static abstract void VhaddT1(CodeGenContext context, uint encoding); + static abstract void VhsubA1(CodeGenContext context, uint encoding); + static abstract void VhsubT1(CodeGenContext context, uint encoding); + static abstract void VinsA1(CodeGenContext context, uint encoding); + static abstract void VinsT1(CodeGenContext context, uint encoding); + static abstract void VjcvtA1(CodeGenContext context, uint encoding); + static abstract void VjcvtT1(CodeGenContext context, uint encoding); + static abstract void Vld11A1(CodeGenContext context, uint encoding); + static abstract void Vld11A2(CodeGenContext context, uint encoding); + static abstract void Vld11A3(CodeGenContext context, uint encoding); + static abstract void Vld11T1(CodeGenContext context, uint encoding); + static abstract void Vld11T2(CodeGenContext context, uint encoding); + static abstract void Vld11T3(CodeGenContext context, uint encoding); + static abstract void Vld1AA1(CodeGenContext context, uint encoding); + static abstract void Vld1AT1(CodeGenContext context, uint encoding); + static abstract void Vld1MA1(CodeGenContext context, uint encoding); + static abstract void Vld1MA2(CodeGenContext context, uint encoding); + static abstract void Vld1MA3(CodeGenContext context, uint encoding); + static abstract void Vld1MA4(CodeGenContext context, uint encoding); + static abstract void Vld1MT1(CodeGenContext context, uint encoding); + static abstract void Vld1MT2(CodeGenContext context, uint encoding); + static abstract void Vld1MT3(CodeGenContext context, uint encoding); + static abstract void Vld1MT4(CodeGenContext context, uint encoding); + static abstract void Vld21A1(CodeGenContext context, uint encoding); + static abstract void Vld21A2(CodeGenContext context, uint encoding); + static abstract void Vld21A3(CodeGenContext context, uint encoding); + static abstract void Vld21T1(CodeGenContext context, uint encoding); + static abstract void Vld21T2(CodeGenContext context, uint encoding); + static abstract void Vld21T3(CodeGenContext context, uint encoding); + static abstract void Vld2AA1(CodeGenContext context, uint encoding); + static abstract void Vld2AT1(CodeGenContext context, uint encoding); + static abstract void Vld2MA1(CodeGenContext context, uint encoding); + static abstract void Vld2MA2(CodeGenContext context, uint encoding); + static abstract void Vld2MT1(CodeGenContext context, uint encoding); + static abstract void Vld2MT2(CodeGenContext context, uint encoding); + static abstract void Vld31A1(CodeGenContext context, uint encoding); + static abstract void Vld31A2(CodeGenContext context, uint encoding); + static abstract void Vld31A3(CodeGenContext context, uint encoding); + static abstract void Vld31T1(CodeGenContext context, uint encoding); + static abstract void Vld31T2(CodeGenContext context, uint encoding); + static abstract void Vld31T3(CodeGenContext context, uint encoding); + static abstract void Vld3AA1(CodeGenContext context, uint encoding); + static abstract void Vld3AT1(CodeGenContext context, uint encoding); + static abstract void Vld3MA1(CodeGenContext context, uint encoding); + static abstract void Vld3MT1(CodeGenContext context, uint encoding); + static abstract void Vld41A1(CodeGenContext context, uint encoding); + static abstract void Vld41A2(CodeGenContext context, uint encoding); + static abstract void Vld41A3(CodeGenContext context, uint encoding); + static abstract void Vld41T1(CodeGenContext context, uint encoding); + static abstract void Vld41T2(CodeGenContext context, uint encoding); + static abstract void Vld41T3(CodeGenContext context, uint encoding); + static abstract void Vld4AA1(CodeGenContext context, uint encoding); + static abstract void Vld4AT1(CodeGenContext context, uint encoding); + static abstract void Vld4MA1(CodeGenContext context, uint encoding); + static abstract void Vld4MT1(CodeGenContext context, uint encoding); + static abstract void VldmA1(CodeGenContext context, uint encoding); + static abstract void VldmA2(CodeGenContext context, uint encoding); + static abstract void VldmT1(CodeGenContext context, uint encoding); + static abstract void VldmT2(CodeGenContext context, uint encoding); + static abstract void VldrIA1(CodeGenContext context, uint encoding); + static abstract void VldrIT1(CodeGenContext context, uint encoding); + static abstract void VldrLA1(CodeGenContext context, uint encoding); + static abstract void VldrLT1(CodeGenContext context, uint encoding); + static abstract void VmaxnmA1(CodeGenContext context, uint encoding); + static abstract void VmaxnmA2(CodeGenContext context, uint encoding); + static abstract void VmaxnmT1(CodeGenContext context, uint encoding); + static abstract void VmaxnmT2(CodeGenContext context, uint encoding); + static abstract void VmaxFA1(CodeGenContext context, uint encoding); + static abstract void VmaxFT1(CodeGenContext context, uint encoding); + static abstract void VmaxIA1(CodeGenContext context, uint encoding); + static abstract void VmaxIT1(CodeGenContext context, uint encoding); + static abstract void VminnmA1(CodeGenContext context, uint encoding); + static abstract void VminnmA2(CodeGenContext context, uint encoding); + static abstract void VminnmT1(CodeGenContext context, uint encoding); + static abstract void VminnmT2(CodeGenContext context, uint encoding); + static abstract void VminFA1(CodeGenContext context, uint encoding); + static abstract void VminFT1(CodeGenContext context, uint encoding); + static abstract void VminIA1(CodeGenContext context, uint encoding); + static abstract void VminIT1(CodeGenContext context, uint encoding); + static abstract void VmlalIA1(CodeGenContext context, uint encoding); + static abstract void VmlalIT1(CodeGenContext context, uint encoding); + static abstract void VmlalSA1(CodeGenContext context, uint encoding); + static abstract void VmlalST1(CodeGenContext context, uint encoding); + static abstract void VmlaFA1(CodeGenContext context, uint encoding); + static abstract void VmlaFA2(CodeGenContext context, uint encoding); + static abstract void VmlaFT1(CodeGenContext context, uint encoding); + static abstract void VmlaFT2(CodeGenContext context, uint encoding); + static abstract void VmlaIA1(CodeGenContext context, uint encoding); + static abstract void VmlaIT1(CodeGenContext context, uint encoding); + static abstract void VmlaSA1(CodeGenContext context, uint encoding); + static abstract void VmlaST1(CodeGenContext context, uint encoding); + static abstract void VmlslIA1(CodeGenContext context, uint encoding); + static abstract void VmlslIT1(CodeGenContext context, uint encoding); + static abstract void VmlslSA1(CodeGenContext context, uint encoding); + static abstract void VmlslST1(CodeGenContext context, uint encoding); + static abstract void VmlsFA1(CodeGenContext context, uint encoding); + static abstract void VmlsFA2(CodeGenContext context, uint encoding); + static abstract void VmlsFT1(CodeGenContext context, uint encoding); + static abstract void VmlsFT2(CodeGenContext context, uint encoding); + static abstract void VmlsIA1(CodeGenContext context, uint encoding); + static abstract void VmlsIT1(CodeGenContext context, uint encoding); + static abstract void VmlsSA1(CodeGenContext context, uint encoding); + static abstract void VmlsST1(CodeGenContext context, uint encoding); + static abstract void VmmlaA1(CodeGenContext context, uint encoding); + static abstract void VmmlaT1(CodeGenContext context, uint encoding); + static abstract void VmovlA1(CodeGenContext context, uint encoding); + static abstract void VmovlT1(CodeGenContext context, uint encoding); + static abstract void VmovnA1(CodeGenContext context, uint encoding); + static abstract void VmovnT1(CodeGenContext context, uint encoding); + static abstract void VmovxA1(CodeGenContext context, uint encoding); + static abstract void VmovxT1(CodeGenContext context, uint encoding); + static abstract void VmovDA1(CodeGenContext context, uint encoding); + static abstract void VmovDT1(CodeGenContext context, uint encoding); + static abstract void VmovHA1(CodeGenContext context, uint encoding); + static abstract void VmovHT1(CodeGenContext context, uint encoding); + static abstract void VmovIA1(CodeGenContext context, uint encoding); + static abstract void VmovIA2(CodeGenContext context, uint encoding); + static abstract void VmovIA3(CodeGenContext context, uint encoding); + static abstract void VmovIA4(CodeGenContext context, uint encoding); + static abstract void VmovIA5(CodeGenContext context, uint encoding); + static abstract void VmovIT1(CodeGenContext context, uint encoding); + static abstract void VmovIT2(CodeGenContext context, uint encoding); + static abstract void VmovIT3(CodeGenContext context, uint encoding); + static abstract void VmovIT4(CodeGenContext context, uint encoding); + static abstract void VmovIT5(CodeGenContext context, uint encoding); + static abstract void VmovRA2(CodeGenContext context, uint encoding); + static abstract void VmovRT2(CodeGenContext context, uint encoding); + static abstract void VmovRsA1(CodeGenContext context, uint encoding); + static abstract void VmovRsT1(CodeGenContext context, uint encoding); + static abstract void VmovSA1(CodeGenContext context, uint encoding); + static abstract void VmovST1(CodeGenContext context, uint encoding); + static abstract void VmovSrA1(CodeGenContext context, uint encoding); + static abstract void VmovSrT1(CodeGenContext context, uint encoding); + static abstract void VmovSsA1(CodeGenContext context, uint encoding); + static abstract void VmovSsT1(CodeGenContext context, uint encoding); + static abstract void VmrsA1(CodeGenContext context, uint encoding); + static abstract void VmrsT1(CodeGenContext context, uint encoding); + static abstract void VmsrA1(CodeGenContext context, uint encoding); + static abstract void VmsrT1(CodeGenContext context, uint encoding); + static abstract void VmullIA1(CodeGenContext context, uint encoding); + static abstract void VmullIT1(CodeGenContext context, uint encoding); + static abstract void VmullSA1(CodeGenContext context, uint encoding); + static abstract void VmullST1(CodeGenContext context, uint encoding); + static abstract void VmulFA1(CodeGenContext context, uint encoding); + static abstract void VmulFA2(CodeGenContext context, uint encoding); + static abstract void VmulFT1(CodeGenContext context, uint encoding); + static abstract void VmulFT2(CodeGenContext context, uint encoding); + static abstract void VmulIA1(CodeGenContext context, uint encoding); + static abstract void VmulIT1(CodeGenContext context, uint encoding); + static abstract void VmulSA1(CodeGenContext context, uint encoding); + static abstract void VmulST1(CodeGenContext context, uint encoding); + static abstract void VmvnIA1(CodeGenContext context, uint encoding); + static abstract void VmvnIA2(CodeGenContext context, uint encoding); + static abstract void VmvnIA3(CodeGenContext context, uint encoding); + static abstract void VmvnIT1(CodeGenContext context, uint encoding); + static abstract void VmvnIT2(CodeGenContext context, uint encoding); + static abstract void VmvnIT3(CodeGenContext context, uint encoding); + static abstract void VmvnRA1(CodeGenContext context, uint encoding); + static abstract void VmvnRT1(CodeGenContext context, uint encoding); + static abstract void VnegA1(CodeGenContext context, uint encoding); + static abstract void VnegA2(CodeGenContext context, uint encoding); + static abstract void VnegT1(CodeGenContext context, uint encoding); + static abstract void VnegT2(CodeGenContext context, uint encoding); + static abstract void VnmlaA1(CodeGenContext context, uint encoding); + static abstract void VnmlaT1(CodeGenContext context, uint encoding); + static abstract void VnmlsA1(CodeGenContext context, uint encoding); + static abstract void VnmlsT1(CodeGenContext context, uint encoding); + static abstract void VnmulA1(CodeGenContext context, uint encoding); + static abstract void VnmulT1(CodeGenContext context, uint encoding); + static abstract void VornRA1(CodeGenContext context, uint encoding); + static abstract void VornRT1(CodeGenContext context, uint encoding); + static abstract void VorrIA1(CodeGenContext context, uint encoding); + static abstract void VorrIA2(CodeGenContext context, uint encoding); + static abstract void VorrIT1(CodeGenContext context, uint encoding); + static abstract void VorrIT2(CodeGenContext context, uint encoding); + static abstract void VorrRA1(CodeGenContext context, uint encoding); + static abstract void VorrRT1(CodeGenContext context, uint encoding); + static abstract void VpadalA1(CodeGenContext context, uint encoding); + static abstract void VpadalT1(CodeGenContext context, uint encoding); + static abstract void VpaddlA1(CodeGenContext context, uint encoding); + static abstract void VpaddlT1(CodeGenContext context, uint encoding); + static abstract void VpaddFA1(CodeGenContext context, uint encoding); + static abstract void VpaddFT1(CodeGenContext context, uint encoding); + static abstract void VpaddIA1(CodeGenContext context, uint encoding); + static abstract void VpaddIT1(CodeGenContext context, uint encoding); + static abstract void VpmaxFA1(CodeGenContext context, uint encoding); + static abstract void VpmaxFT1(CodeGenContext context, uint encoding); + static abstract void VpmaxIA1(CodeGenContext context, uint encoding); + static abstract void VpmaxIT1(CodeGenContext context, uint encoding); + static abstract void VpminFA1(CodeGenContext context, uint encoding); + static abstract void VpminFT1(CodeGenContext context, uint encoding); + static abstract void VpminIA1(CodeGenContext context, uint encoding); + static abstract void VpminIT1(CodeGenContext context, uint encoding); + static abstract void VqabsA1(CodeGenContext context, uint encoding); + static abstract void VqabsT1(CodeGenContext context, uint encoding); + static abstract void VqaddA1(CodeGenContext context, uint encoding); + static abstract void VqaddT1(CodeGenContext context, uint encoding); + static abstract void VqdmlalA1(CodeGenContext context, uint encoding); + static abstract void VqdmlalA2(CodeGenContext context, uint encoding); + static abstract void VqdmlalT1(CodeGenContext context, uint encoding); + static abstract void VqdmlalT2(CodeGenContext context, uint encoding); + static abstract void VqdmlslA1(CodeGenContext context, uint encoding); + static abstract void VqdmlslA2(CodeGenContext context, uint encoding); + static abstract void VqdmlslT1(CodeGenContext context, uint encoding); + static abstract void VqdmlslT2(CodeGenContext context, uint encoding); + static abstract void VqdmulhA1(CodeGenContext context, uint encoding); + static abstract void VqdmulhA2(CodeGenContext context, uint encoding); + static abstract void VqdmulhT1(CodeGenContext context, uint encoding); + static abstract void VqdmulhT2(CodeGenContext context, uint encoding); + static abstract void VqdmullA1(CodeGenContext context, uint encoding); + static abstract void VqdmullA2(CodeGenContext context, uint encoding); + static abstract void VqdmullT1(CodeGenContext context, uint encoding); + static abstract void VqdmullT2(CodeGenContext context, uint encoding); + static abstract void VqmovnA1(CodeGenContext context, uint encoding); + static abstract void VqmovnT1(CodeGenContext context, uint encoding); + static abstract void VqnegA1(CodeGenContext context, uint encoding); + static abstract void VqnegT1(CodeGenContext context, uint encoding); + static abstract void VqrdmlahA1(CodeGenContext context, uint encoding); + static abstract void VqrdmlahA2(CodeGenContext context, uint encoding); + static abstract void VqrdmlahT1(CodeGenContext context, uint encoding); + static abstract void VqrdmlahT2(CodeGenContext context, uint encoding); + static abstract void VqrdmlshA1(CodeGenContext context, uint encoding); + static abstract void VqrdmlshA2(CodeGenContext context, uint encoding); + static abstract void VqrdmlshT1(CodeGenContext context, uint encoding); + static abstract void VqrdmlshT2(CodeGenContext context, uint encoding); + static abstract void VqrdmulhA1(CodeGenContext context, uint encoding); + static abstract void VqrdmulhA2(CodeGenContext context, uint encoding); + static abstract void VqrdmulhT1(CodeGenContext context, uint encoding); + static abstract void VqrdmulhT2(CodeGenContext context, uint encoding); + static abstract void VqrshlA1(CodeGenContext context, uint encoding); + static abstract void VqrshlT1(CodeGenContext context, uint encoding); + static abstract void VqrshrnA1(CodeGenContext context, uint encoding); + static abstract void VqrshrnT1(CodeGenContext context, uint encoding); + static abstract void VqshlIA1(CodeGenContext context, uint encoding); + static abstract void VqshlIT1(CodeGenContext context, uint encoding); + static abstract void VqshlRA1(CodeGenContext context, uint encoding); + static abstract void VqshlRT1(CodeGenContext context, uint encoding); + static abstract void VqshrnA1(CodeGenContext context, uint encoding); + static abstract void VqshrnT1(CodeGenContext context, uint encoding); + static abstract void VqsubA1(CodeGenContext context, uint encoding); + static abstract void VqsubT1(CodeGenContext context, uint encoding); + static abstract void VraddhnA1(CodeGenContext context, uint encoding); + static abstract void VraddhnT1(CodeGenContext context, uint encoding); + static abstract void VrecpeA1(CodeGenContext context, uint encoding); + static abstract void VrecpeT1(CodeGenContext context, uint encoding); + static abstract void VrecpsA1(CodeGenContext context, uint encoding); + static abstract void VrecpsT1(CodeGenContext context, uint encoding); + static abstract void Vrev16A1(CodeGenContext context, uint encoding); + static abstract void Vrev16T1(CodeGenContext context, uint encoding); + static abstract void Vrev32A1(CodeGenContext context, uint encoding); + static abstract void Vrev32T1(CodeGenContext context, uint encoding); + static abstract void Vrev64A1(CodeGenContext context, uint encoding); + static abstract void Vrev64T1(CodeGenContext context, uint encoding); + static abstract void VrhaddA1(CodeGenContext context, uint encoding); + static abstract void VrhaddT1(CodeGenContext context, uint encoding); + static abstract void VrintaAsimdA1(CodeGenContext context, uint encoding); + static abstract void VrintaAsimdT1(CodeGenContext context, uint encoding); + static abstract void VrintaVfpA1(CodeGenContext context, uint encoding); + static abstract void VrintaVfpT1(CodeGenContext context, uint encoding); + static abstract void VrintmAsimdA1(CodeGenContext context, uint encoding); + static abstract void VrintmAsimdT1(CodeGenContext context, uint encoding); + static abstract void VrintmVfpA1(CodeGenContext context, uint encoding); + static abstract void VrintmVfpT1(CodeGenContext context, uint encoding); + static abstract void VrintnAsimdA1(CodeGenContext context, uint encoding); + static abstract void VrintnAsimdT1(CodeGenContext context, uint encoding); + static abstract void VrintnVfpA1(CodeGenContext context, uint encoding); + static abstract void VrintnVfpT1(CodeGenContext context, uint encoding); + static abstract void VrintpAsimdA1(CodeGenContext context, uint encoding); + static abstract void VrintpAsimdT1(CodeGenContext context, uint encoding); + static abstract void VrintpVfpA1(CodeGenContext context, uint encoding); + static abstract void VrintpVfpT1(CodeGenContext context, uint encoding); + static abstract void VrintrVfpA1(CodeGenContext context, uint encoding); + static abstract void VrintrVfpT1(CodeGenContext context, uint encoding); + static abstract void VrintxAsimdA1(CodeGenContext context, uint encoding); + static abstract void VrintxAsimdT1(CodeGenContext context, uint encoding); + static abstract void VrintxVfpA1(CodeGenContext context, uint encoding); + static abstract void VrintxVfpT1(CodeGenContext context, uint encoding); + static abstract void VrintzAsimdA1(CodeGenContext context, uint encoding); + static abstract void VrintzAsimdT1(CodeGenContext context, uint encoding); + static abstract void VrintzVfpA1(CodeGenContext context, uint encoding); + static abstract void VrintzVfpT1(CodeGenContext context, uint encoding); + static abstract void VrshlA1(CodeGenContext context, uint encoding); + static abstract void VrshlT1(CodeGenContext context, uint encoding); + static abstract void VrshrA1(CodeGenContext context, uint encoding); + static abstract void VrshrT1(CodeGenContext context, uint encoding); + static abstract void VrshrnA1(CodeGenContext context, uint encoding); + static abstract void VrshrnT1(CodeGenContext context, uint encoding); + static abstract void VrsqrteA1(CodeGenContext context, uint encoding); + static abstract void VrsqrteT1(CodeGenContext context, uint encoding); + static abstract void VrsqrtsA1(CodeGenContext context, uint encoding); + static abstract void VrsqrtsT1(CodeGenContext context, uint encoding); + static abstract void VrsraA1(CodeGenContext context, uint encoding); + static abstract void VrsraT1(CodeGenContext context, uint encoding); + static abstract void VrsubhnA1(CodeGenContext context, uint encoding); + static abstract void VrsubhnT1(CodeGenContext context, uint encoding); + static abstract void VsdotA1(CodeGenContext context, uint encoding); + static abstract void VsdotT1(CodeGenContext context, uint encoding); + static abstract void VsdotSA1(CodeGenContext context, uint encoding); + static abstract void VsdotST1(CodeGenContext context, uint encoding); + static abstract void VselA1(CodeGenContext context, uint encoding); + static abstract void VselT1(CodeGenContext context, uint encoding); + static abstract void VshllA1(CodeGenContext context, uint encoding); + static abstract void VshllA2(CodeGenContext context, uint encoding); + static abstract void VshllT1(CodeGenContext context, uint encoding); + static abstract void VshllT2(CodeGenContext context, uint encoding); + static abstract void VshlIA1(CodeGenContext context, uint encoding); + static abstract void VshlIT1(CodeGenContext context, uint encoding); + static abstract void VshlRA1(CodeGenContext context, uint encoding); + static abstract void VshlRT1(CodeGenContext context, uint encoding); + static abstract void VshrA1(CodeGenContext context, uint encoding); + static abstract void VshrT1(CodeGenContext context, uint encoding); + static abstract void VshrnA1(CodeGenContext context, uint encoding); + static abstract void VshrnT1(CodeGenContext context, uint encoding); + static abstract void VsliA1(CodeGenContext context, uint encoding); + static abstract void VsliT1(CodeGenContext context, uint encoding); + static abstract void VsmmlaA1(CodeGenContext context, uint encoding); + static abstract void VsmmlaT1(CodeGenContext context, uint encoding); + static abstract void VsqrtA1(CodeGenContext context, uint encoding); + static abstract void VsqrtT1(CodeGenContext context, uint encoding); + static abstract void VsraA1(CodeGenContext context, uint encoding); + static abstract void VsraT1(CodeGenContext context, uint encoding); + static abstract void VsriA1(CodeGenContext context, uint encoding); + static abstract void VsriT1(CodeGenContext context, uint encoding); + static abstract void Vst11A1(CodeGenContext context, uint encoding); + static abstract void Vst11A2(CodeGenContext context, uint encoding); + static abstract void Vst11A3(CodeGenContext context, uint encoding); + static abstract void Vst11T1(CodeGenContext context, uint encoding); + static abstract void Vst11T2(CodeGenContext context, uint encoding); + static abstract void Vst11T3(CodeGenContext context, uint encoding); + static abstract void Vst1MA1(CodeGenContext context, uint encoding); + static abstract void Vst1MA2(CodeGenContext context, uint encoding); + static abstract void Vst1MA3(CodeGenContext context, uint encoding); + static abstract void Vst1MA4(CodeGenContext context, uint encoding); + static abstract void Vst1MT1(CodeGenContext context, uint encoding); + static abstract void Vst1MT2(CodeGenContext context, uint encoding); + static abstract void Vst1MT3(CodeGenContext context, uint encoding); + static abstract void Vst1MT4(CodeGenContext context, uint encoding); + static abstract void Vst21A1(CodeGenContext context, uint encoding); + static abstract void Vst21A2(CodeGenContext context, uint encoding); + static abstract void Vst21A3(CodeGenContext context, uint encoding); + static abstract void Vst21T1(CodeGenContext context, uint encoding); + static abstract void Vst21T2(CodeGenContext context, uint encoding); + static abstract void Vst21T3(CodeGenContext context, uint encoding); + static abstract void Vst2MA1(CodeGenContext context, uint encoding); + static abstract void Vst2MA2(CodeGenContext context, uint encoding); + static abstract void Vst2MT1(CodeGenContext context, uint encoding); + static abstract void Vst2MT2(CodeGenContext context, uint encoding); + static abstract void Vst31A1(CodeGenContext context, uint encoding); + static abstract void Vst31A2(CodeGenContext context, uint encoding); + static abstract void Vst31A3(CodeGenContext context, uint encoding); + static abstract void Vst31T1(CodeGenContext context, uint encoding); + static abstract void Vst31T2(CodeGenContext context, uint encoding); + static abstract void Vst31T3(CodeGenContext context, uint encoding); + static abstract void Vst3MA1(CodeGenContext context, uint encoding); + static abstract void Vst3MT1(CodeGenContext context, uint encoding); + static abstract void Vst41A1(CodeGenContext context, uint encoding); + static abstract void Vst41A2(CodeGenContext context, uint encoding); + static abstract void Vst41A3(CodeGenContext context, uint encoding); + static abstract void Vst41T1(CodeGenContext context, uint encoding); + static abstract void Vst41T2(CodeGenContext context, uint encoding); + static abstract void Vst41T3(CodeGenContext context, uint encoding); + static abstract void Vst4MA1(CodeGenContext context, uint encoding); + static abstract void Vst4MT1(CodeGenContext context, uint encoding); + static abstract void VstmA1(CodeGenContext context, uint encoding); + static abstract void VstmA2(CodeGenContext context, uint encoding); + static abstract void VstmT1(CodeGenContext context, uint encoding); + static abstract void VstmT2(CodeGenContext context, uint encoding); + static abstract void VstrA1(CodeGenContext context, uint encoding); + static abstract void VstrT1(CodeGenContext context, uint encoding); + static abstract void VsubhnA1(CodeGenContext context, uint encoding); + static abstract void VsubhnT1(CodeGenContext context, uint encoding); + static abstract void VsublA1(CodeGenContext context, uint encoding); + static abstract void VsublT1(CodeGenContext context, uint encoding); + static abstract void VsubwA1(CodeGenContext context, uint encoding); + static abstract void VsubwT1(CodeGenContext context, uint encoding); + static abstract void VsubFA1(CodeGenContext context, uint encoding); + static abstract void VsubFA2(CodeGenContext context, uint encoding); + static abstract void VsubFT1(CodeGenContext context, uint encoding); + static abstract void VsubFT2(CodeGenContext context, uint encoding); + static abstract void VsubIA1(CodeGenContext context, uint encoding); + static abstract void VsubIT1(CodeGenContext context, uint encoding); + static abstract void VsudotSA1(CodeGenContext context, uint encoding); + static abstract void VsudotST1(CodeGenContext context, uint encoding); + static abstract void VswpA1(CodeGenContext context, uint encoding); + static abstract void VswpT1(CodeGenContext context, uint encoding); + static abstract void VtblA1(CodeGenContext context, uint encoding); + static abstract void VtblT1(CodeGenContext context, uint encoding); + static abstract void VtrnA1(CodeGenContext context, uint encoding); + static abstract void VtrnT1(CodeGenContext context, uint encoding); + static abstract void VtstA1(CodeGenContext context, uint encoding); + static abstract void VtstT1(CodeGenContext context, uint encoding); + static abstract void VudotA1(CodeGenContext context, uint encoding); + static abstract void VudotT1(CodeGenContext context, uint encoding); + static abstract void VudotSA1(CodeGenContext context, uint encoding); + static abstract void VudotST1(CodeGenContext context, uint encoding); + static abstract void VummlaA1(CodeGenContext context, uint encoding); + static abstract void VummlaT1(CodeGenContext context, uint encoding); + static abstract void VusdotA1(CodeGenContext context, uint encoding); + static abstract void VusdotT1(CodeGenContext context, uint encoding); + static abstract void VusdotSA1(CodeGenContext context, uint encoding); + static abstract void VusdotST1(CodeGenContext context, uint encoding); + static abstract void VusmmlaA1(CodeGenContext context, uint encoding); + static abstract void VusmmlaT1(CodeGenContext context, uint encoding); + static abstract void VuzpA1(CodeGenContext context, uint encoding); + static abstract void VuzpT1(CodeGenContext context, uint encoding); + static abstract void VzipA1(CodeGenContext context, uint encoding); + static abstract void VzipT1(CodeGenContext context, uint encoding); + static abstract void WfeA1(CodeGenContext context, uint encoding); + static abstract void WfeT1(CodeGenContext context, uint encoding); + static abstract void WfeT2(CodeGenContext context, uint encoding); + static abstract void WfiA1(CodeGenContext context, uint encoding); + static abstract void WfiT1(CodeGenContext context, uint encoding); + static abstract void WfiT2(CodeGenContext context, uint encoding); + static abstract void YieldA1(CodeGenContext context, uint encoding); + static abstract void YieldT1(CodeGenContext context, uint encoding); + static abstract void YieldT2(CodeGenContext context, uint encoding); + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/ImmUtils.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/ImmUtils.cs new file mode 100644 index 00000000..516845fc --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/ImmUtils.cs @@ -0,0 +1,137 @@ +using System.Numerics; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + static class ImmUtils + { + public static uint ExpandImm(uint imm) + { + return BitOperations.RotateRight((byte)imm, (int)(imm >> 8) * 2); + } + + public static bool ExpandedImmRotated(uint imm) + { + return (imm >> 8) != 0; + } + + public static uint ExpandImm(uint imm8, uint imm3, uint i) + { + uint imm = CombineImmU12(imm8, imm3, i); + + if (imm >> 10 == 0) + { + return ((imm >> 8) & 3) switch + { + 0 => (byte)imm, + 1 => (byte)imm * 0x00010001u, + 2 => (byte)imm * 0x01000100u, + 3 => (byte)imm * 0x01010101u, + _ => 0, + }; + } + else + { + return BitOperations.RotateRight(0x80u | (byte)imm, (int)(imm >> 7)); + } + } + + public static bool ExpandedImmRotated(uint imm8, uint imm3, uint i) + { + uint imm = CombineImmU12(imm8, imm3, i); + + return (imm >> 7) != 0; + } + + public static uint CombineImmU5(uint imm2, uint imm3) + { + return imm2 | (imm3 << 2); + } + + public static uint CombineImmU5IImm4(uint i, uint imm4) + { + return i | (imm4 << 1); + } + + public static uint CombineImmU8(uint imm4l, uint imm4h) + { + return imm4l | (imm4h << 4); + } + + public static uint CombineImmU8(uint imm4, uint imm3, uint i) + { + return imm4 | (imm3 << 4) | (i << 7); + } + + public static uint CombineImmU12(uint imm8, uint imm3, uint i) + { + return imm8 | (imm3 << 8) | (i << 11); + } + + public static uint CombineImmU16(uint imm12, uint imm4) + { + return imm12 | (imm4 << 12); + } + + public static uint CombineImmU16(uint imm8, uint imm3, uint i, uint imm4) + { + return imm8 | (imm3 << 8) | (i << 11) | (imm4 << 12); + } + + public static int CombineSImm20Times2(uint imm11, uint imm6, uint j1, uint j2, uint s) + { + int imm32 = (int)(imm11 | (imm6 << 11) | (j1 << 17) | (j2 << 18) | (s << 19)); + + return (imm32 << 13) >> 12; + } + + public static int CombineSImm24Times2(uint imm11, uint imm10, uint j1, uint j2, uint s) + { + uint i1 = j1 ^ s ^ 1; + uint i2 = j2 ^ s ^ 1; + + int imm32 = (int)(imm11 | (imm10 << 11) | (i2 << 21) | (i1 << 22) | (s << 23)); + + return (imm32 << 8) >> 7; + } + + public static int CombineSImm24Times4(uint imm10L, uint imm10H, uint j1, uint j2, uint s) + { + uint i1 = j1 ^ s ^ 1; + uint i2 = j2 ^ s ^ 1; + + int imm32 = (int)(imm10L | (imm10H << 10) | (i2 << 20) | (i1 << 21) | (s << 22)); + + return (imm32 << 9) >> 7; + } + + public static uint CombineRegisterList(uint registerList, uint m) + { + return registerList | (m << 14); + } + + public static uint CombineRegisterList(uint registerList, uint m, uint p) + { + return registerList | (m << 14) | (p << 15); + } + + public static int ExtractSImm24Times4(uint encoding) + { + return (int)(encoding << 8) >> 6; + } + + public static int ExtractT16UImm5Times2(uint encoding) + { + return (int)(encoding >> 18) & 0x3e; + } + + public static int ExtractT16SImm8Times2(uint encoding) + { + return (int)(encoding << 24) >> 23; + } + + public static int ExtractT16SImm11Times2(uint encoding) + { + return (int)(encoding << 21) >> 20; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstDecoders.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstDecoders.cs new file mode 100644 index 00000000..41b105e4 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstDecoders.cs @@ -0,0 +1,2927 @@ +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + readonly struct InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm12b0w12 + { + private readonly uint _value; + public InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstIb26w1Sb20w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 + { + private readonly uint _value; + public InstIb26w1Sb20w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint I => (_value >> 26) & 0x1; + } + + readonly struct InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 5) & 0x3; + public readonly uint Imm5 => (_value >> 7) & 0x1F; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRmb19w3Rdnb16w3 + { + private readonly uint _value; + public InstRmb19w3Rdnb16w3(uint value) => _value = value; + public readonly uint Rdn => (_value >> 16) & 0x7; + public readonly uint Rm => (_value >> 19) & 0x7; + } + + readonly struct InstSb20w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 + { + private readonly uint _value; + public InstSb20w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 4) & 0x3; + public readonly uint Imm2 => (_value >> 6) & 0x3; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + } + + readonly struct InstCondb28w4Sb20w1Rnb16w4Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Sb20w1Rnb16w4Rdb12w4Rsb8w4Stypeb5w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 5) & 0x3; + public readonly uint Rs => (_value >> 8) & 0xF; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstImm3b22w3Rnb19w3Rdb16w3 + { + private readonly uint _value; + public InstImm3b22w3Rnb19w3Rdb16w3(uint value) => _value = value; + public readonly uint Rd => (_value >> 16) & 0x7; + public readonly uint Rn => (_value >> 19) & 0x7; + public readonly uint Imm3 => (_value >> 22) & 0x7; + } + + readonly struct InstRdnb24w3Imm8b16w8 + { + private readonly uint _value; + public InstRdnb24w3Imm8b16w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 16) & 0xFF; + public readonly uint Rdn => (_value >> 24) & 0x7; + } + + readonly struct InstIb26w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 + { + private readonly uint _value; + public InstIb26w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint I => (_value >> 26) & 0x1; + } + + readonly struct InstRmb22w3Rnb19w3Rdb16w3 + { + private readonly uint _value; + public InstRmb22w3Rnb19w3Rdb16w3(uint value) => _value = value; + public readonly uint Rd => (_value >> 16) & 0x7; + public readonly uint Rn => (_value >> 19) & 0x7; + public readonly uint Rm => (_value >> 22) & 0x7; + } + + readonly struct InstDnb23w1Rmb19w4Rdnb16w3 + { + private readonly uint _value; + public InstDnb23w1Rmb19w4Rdnb16w3(uint value) => _value = value; + public readonly uint Rdn => (_value >> 16) & 0x7; + public readonly uint Rm => (_value >> 19) & 0xF; + public readonly uint Dn => (_value >> 23) & 0x1; + } + + readonly struct InstCondb28w4Sb20w1Rdb12w4Imm12b0w12 + { + private readonly uint _value; + public InstCondb28w4Sb20w1Rdb12w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRdb24w3Imm8b16w8 + { + private readonly uint _value; + public InstRdb24w3Imm8b16w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 16) & 0xFF; + public readonly uint Rd => (_value >> 24) & 0x7; + } + + readonly struct InstImm7b16w7 + { + private readonly uint _value; + public InstImm7b16w7(uint value) => _value = value; + public readonly uint Imm7 => (_value >> 16) & 0x7F; + } + + readonly struct InstIb26w1Sb20w1Imm3b12w3Rdb8w4Imm8b0w8 + { + private readonly uint _value; + public InstIb26w1Sb20w1Imm3b12w3Rdb8w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint I => (_value >> 26) & 0x1; + } + + readonly struct InstIb26w1Imm3b12w3Rdb8w4Imm8b0w8 + { + private readonly uint _value; + public InstIb26w1Imm3b12w3Rdb8w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint I => (_value >> 26) & 0x1; + } + + readonly struct InstCondb28w4Sb20w1Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Sb20w1Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 5) & 0x3; + public readonly uint Imm5 => (_value >> 7) & 0x1F; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstDmb23w1Rdmb16w3 + { + private readonly uint _value; + public InstDmb23w1Rdmb16w3(uint value) => _value = value; + public readonly uint Rdm => (_value >> 16) & 0x7; + public readonly uint Dm => (_value >> 23) & 0x1; + } + + readonly struct InstRmb19w4 + { + private readonly uint _value; + public InstRmb19w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 19) & 0xF; + } + + readonly struct InstSb20w1Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 + { + private readonly uint _value; + public InstSb20w1Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 4) & 0x3; + public readonly uint Imm2 => (_value >> 6) & 0x3; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint S => (_value >> 20) & 0x1; + } + + readonly struct InstCondb28w4Rdb12w4Imm12b0w12 + { + private readonly uint _value; + public InstCondb28w4Rdb12w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Size => (_value >> 18) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstCondb28w4Imm24b0w24 + { + private readonly uint _value; + public InstCondb28w4Imm24b0w24(uint value) => _value = value; + public readonly uint Imm24 => (_value >> 0) & 0xFFFFFF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstCondb24w4Imm8b16w8 + { + private readonly uint _value; + public InstCondb24w4Imm8b16w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 16) & 0xFF; + public readonly uint Cond => (_value >> 24) & 0xF; + } + + readonly struct InstImm11b16w11 + { + private readonly uint _value; + public InstImm11b16w11(uint value) => _value = value; + public readonly uint Imm11 => (_value >> 16) & 0x7FF; + } + + readonly struct InstSb26w1Condb22w4Imm6b16w6J1b13w1J2b11w1Imm11b0w11 + { + private readonly uint _value; + public InstSb26w1Condb22w4Imm6b16w6J1b13w1J2b11w1Imm11b0w11(uint value) => _value = value; + public readonly uint Imm11 => (_value >> 0) & 0x7FF; + public readonly uint J2 => (_value >> 11) & 0x1; + public readonly uint J1 => (_value >> 13) & 0x1; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint Cond => (_value >> 22) & 0xF; + public readonly uint S => (_value >> 26) & 0x1; + } + + readonly struct InstSb26w1Imm10b16w10J1b13w1J2b11w1Imm11b0w11 + { + private readonly uint _value; + public InstSb26w1Imm10b16w10J1b13w1J2b11w1Imm11b0w11(uint value) => _value = value; + public readonly uint Imm11 => (_value >> 0) & 0x7FF; + public readonly uint J2 => (_value >> 11) & 0x1; + public readonly uint J1 => (_value >> 13) & 0x1; + public readonly uint Imm10 => (_value >> 16) & 0x3FF; + public readonly uint S => (_value >> 26) & 0x1; + } + + readonly struct InstCondb28w4Msbb16w5Rdb12w4Lsbb7w5 + { + private readonly uint _value; + public InstCondb28w4Msbb16w5Rdb12w4Lsbb7w5(uint value) => _value = value; + public readonly uint Lsb => (_value >> 7) & 0x1F; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Msb => (_value >> 16) & 0x1F; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstImm3b12w3Rdb8w4Imm2b6w2Msbb0w5 + { + private readonly uint _value; + public InstImm3b12w3Rdb8w4Imm2b6w2Msbb0w5(uint value) => _value = value; + public readonly uint Msb => (_value >> 0) & 0x1F; + public readonly uint Imm2 => (_value >> 6) & 0x3; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + } + + readonly struct InstCondb28w4Msbb16w5Rdb12w4Lsbb7w5Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Msbb16w5Rdb12w4Lsbb7w5Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint Lsb => (_value >> 7) & 0x1F; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Msb => (_value >> 16) & 0x1F; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Imm3b12w3Rdb8w4Imm2b6w2Msbb0w5 + { + private readonly uint _value; + public InstRnb16w4Imm3b12w3Rdb8w4Imm2b6w2Msbb0w5(uint value) => _value = value; + public readonly uint Msb => (_value >> 0) & 0x1F; + public readonly uint Imm2 => (_value >> 6) & 0x3; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Imm12b8w12Imm4b0w4 + { + private readonly uint _value; + public InstCondb28w4Imm12b8w12Imm4b0w4(uint value) => _value = value; + public readonly uint Imm4 => (_value >> 0) & 0xF; + public readonly uint Imm12 => (_value >> 8) & 0xFFF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstImm8b16w8 + { + private readonly uint _value; + public InstImm8b16w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 16) & 0xFF; + } + + readonly struct InstCondb28w4Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstHb24w1Imm24b0w24 + { + private readonly uint _value; + public InstHb24w1Imm24b0w24(uint value) => _value = value; + public readonly uint Imm24 => (_value >> 0) & 0xFFFFFF; + public readonly uint H => (_value >> 24) & 0x1; + } + + readonly struct InstSb26w1Imm10hb16w10J1b13w1J2b11w1Imm10lb1w10Hb0w1 + { + private readonly uint _value; + public InstSb26w1Imm10hb16w10J1b13w1J2b11w1Imm10lb1w10Hb0w1(uint value) => _value = value; + public readonly uint H => (_value >> 0) & 0x1; + public readonly uint Imm10l => (_value >> 1) & 0x3FF; + public readonly uint J2 => (_value >> 11) & 0x1; + public readonly uint J1 => (_value >> 13) & 0x1; + public readonly uint Imm10h => (_value >> 16) & 0x3FF; + public readonly uint S => (_value >> 26) & 0x1; + } + + readonly struct InstRmb16w4 + { + private readonly uint _value; + public InstRmb16w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 16) & 0xF; + } + + readonly struct InstOpb27w1Ib25w1Imm5b19w5Rnb16w3 + { + private readonly uint _value; + public InstOpb27w1Ib25w1Imm5b19w5Rnb16w3(uint value) => _value = value; + public readonly uint Rn => (_value >> 16) & 0x7; + public readonly uint Imm5 => (_value >> 19) & 0x1F; + public readonly uint I => (_value >> 25) & 0x1; + public readonly uint Op => (_value >> 27) & 0x1; + } + + readonly struct InstCondb28w4 + { + private readonly uint _value; + public InstCondb28w4(uint value) => _value = value; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstCondb28w4Rdb12w4Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdb12w4Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rdb8w4Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rdb8w4Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rnb16w4Imm12b0w12 + { + private readonly uint _value; + public InstCondb28w4Rnb16w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstIb26w1Rnb16w4Imm3b12w3Imm8b0w8 + { + private readonly uint _value; + public InstIb26w1Rnb16w4Imm3b12w3Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint I => (_value >> 26) & 0x1; + } + + readonly struct InstCondb28w4Rnb16w4Imm5b7w5Stypeb5w2Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Rnb16w4Imm5b7w5Stypeb5w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 5) & 0x3; + public readonly uint Imm5 => (_value >> 7) & 0x1F; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRmb19w3Rnb16w3 + { + private readonly uint _value; + public InstRmb19w3Rnb16w3(uint value) => _value = value; + public readonly uint Rn => (_value >> 16) & 0x7; + public readonly uint Rm => (_value >> 19) & 0x7; + } + + readonly struct InstRnb16w4Imm3b12w3Imm2b6w2Stypeb4w2Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Imm3b12w3Imm2b6w2Stypeb4w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 4) & 0x3; + public readonly uint Imm2 => (_value >> 6) & 0x3; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rnb16w4Rsb8w4Stypeb5w2Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Rnb16w4Rsb8w4Stypeb5w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 5) & 0x3; + public readonly uint Rs => (_value >> 8) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb24w3Imm8b16w8 + { + private readonly uint _value; + public InstRnb24w3Imm8b16w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 16) & 0xFF; + public readonly uint Rn => (_value >> 24) & 0x7; + } + + readonly struct InstNb23w1Rmb19w4Rnb16w3 + { + private readonly uint _value; + public InstNb23w1Rmb19w4Rnb16w3(uint value) => _value = value; + public readonly uint Rn => (_value >> 16) & 0x7; + public readonly uint Rm => (_value >> 19) & 0xF; + public readonly uint N => (_value >> 23) & 0x1; + } + + readonly struct InstImodb18w2Mb17w1Ab8w1Ib7w1Fb6w1Modeb0w5 + { + private readonly uint _value; + public InstImodb18w2Mb17w1Ab8w1Ib7w1Fb6w1Modeb0w5(uint value) => _value = value; + public readonly uint Mode => (_value >> 0) & 0x1F; + public readonly uint F => (_value >> 6) & 0x1; + public readonly uint I => (_value >> 7) & 0x1; + public readonly uint A => (_value >> 8) & 0x1; + public readonly uint M => (_value >> 17) & 0x1; + public readonly uint Imod => (_value >> 18) & 0x3; + } + + readonly struct InstImb20w1Ab18w1Ib17w1Fb16w1 + { + private readonly uint _value; + public InstImb20w1Ab18w1Ib17w1Fb16w1(uint value) => _value = value; + public readonly uint F => (_value >> 16) & 0x1; + public readonly uint I => (_value >> 17) & 0x1; + public readonly uint A => (_value >> 18) & 0x1; + public readonly uint Im => (_value >> 20) & 0x1; + } + + readonly struct InstImodb9w2Mb8w1Ab7w1Ib6w1Fb5w1Modeb0w5 + { + private readonly uint _value; + public InstImodb9w2Mb8w1Ab7w1Ib6w1Fb5w1Modeb0w5(uint value) => _value = value; + public readonly uint Mode => (_value >> 0) & 0x1F; + public readonly uint F => (_value >> 5) & 0x1; + public readonly uint I => (_value >> 6) & 0x1; + public readonly uint A => (_value >> 7) & 0x1; + public readonly uint M => (_value >> 8) & 0x1; + public readonly uint Imod => (_value >> 9) & 0x3; + } + + readonly struct InstCondb28w4Szb21w2Rnb16w4Rdb12w4Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Szb21w2Rnb16w4Rdb12w4Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint Sz => (_value >> 21) & 0x3; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rdb8w4Szb4w2Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rdb8w4Szb4w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Sz => (_value >> 4) & 0x3; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Optionb0w4 + { + private readonly uint _value; + public InstCondb28w4Optionb0w4(uint value) => _value = value; + public readonly uint Option => (_value >> 0) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstOptionb0w4 + { + private readonly uint _value; + public InstOptionb0w4(uint value) => _value = value; + public readonly uint Option => (_value >> 0) & 0xF; + } + + readonly struct InstCondb28w4Pb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm871b1w7 + { + private readonly uint _value; + public InstCondb28w4Pb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm871b1w7(uint value) => _value = value; + public readonly uint Imm871 => (_value >> 1) & 0x7F; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstPb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm871b1w7 + { + private readonly uint _value; + public InstPb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm871b1w7(uint value) => _value = value; + public readonly uint Imm871 => (_value >> 1) & 0x7F; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + } + + readonly struct InstImm6b16w6 + { + private readonly uint _value; + public InstImm6b16w6(uint value) => _value = value; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + } + + readonly struct InstFirstcondb20w4Maskb16w4 + { + private readonly uint _value; + public InstFirstcondb20w4Maskb16w4(uint value) => _value = value; + public readonly uint Mask => (_value >> 16) & 0xF; + public readonly uint Firstcond => (_value >> 20) & 0xF; + } + + readonly struct InstCondb28w4Rnb16w4Rtb12w4 + { + private readonly uint _value; + public InstCondb28w4Rnb16w4Rtb12w4(uint value) => _value = value; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rtb12w4 + { + private readonly uint _value; + public InstRnb16w4Rtb12w4(uint value) => _value = value; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstRnb16w4Rtb12w4Rt2b8w4 + { + private readonly uint _value; + public InstRnb16w4Rtb12w4Rt2b8w4(uint value) => _value = value; + public readonly uint Rt2 => (_value >> 8) & 0xF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Imm8b0w8 + { + private readonly uint _value; + public InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstPb24w1Ub23w1Wb21w1Rnb16w4Imm8b0w8 + { + private readonly uint _value; + public InstPb24w1Ub23w1Wb21w1Rnb16w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + } + + readonly struct InstCondb28w4Pb24w1Ub23w1Wb21w1Imm8b0w8 + { + private readonly uint _value; + public InstCondb28w4Pb24w1Ub23w1Wb21w1Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstPb24w1Ub23w1Wb21w1Imm8b0w8 + { + private readonly uint _value; + public InstPb24w1Ub23w1Wb21w1Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + } + + readonly struct InstCondb28w4Wb21w1Rnb16w4RegisterListb0w16 + { + private readonly uint _value; + public InstCondb28w4Wb21w1Rnb16w4RegisterListb0w16(uint value) => _value = value; + public readonly uint RegisterList => (_value >> 0) & 0xFFFF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb24w3RegisterListb16w8 + { + private readonly uint _value; + public InstRnb24w3RegisterListb16w8(uint value) => _value = value; + public readonly uint RegisterList => (_value >> 16) & 0xFF; + public readonly uint Rn => (_value >> 24) & 0x7; + } + + readonly struct InstWb21w1Rnb16w4Pb15w1Mb14w1RegisterListb0w14 + { + private readonly uint _value; + public InstWb21w1Rnb16w4Pb15w1Mb14w1RegisterListb0w14(uint value) => _value = value; + public readonly uint RegisterList => (_value >> 0) & 0x3FFF; + public readonly uint M => (_value >> 14) & 0x1; + public readonly uint P => (_value >> 15) & 0x1; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + } + + readonly struct InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm12b0w12 + { + private readonly uint _value; + public InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm5b7w5Stypeb5w2Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm5b7w5Stypeb5w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 5) & 0x3; + public readonly uint Imm5 => (_value >> 7) & 0x1F; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rtb12w4Imm8b0w8 + { + private readonly uint _value; + public InstRnb16w4Rtb12w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm12b0w12 + { + private readonly uint _value; + public InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstImm5b22w5Rnb19w3Rtb16w3 + { + private readonly uint _value; + public InstImm5b22w5Rnb19w3Rtb16w3(uint value) => _value = value; + public readonly uint Rt => (_value >> 16) & 0x7; + public readonly uint Rn => (_value >> 19) & 0x7; + public readonly uint Imm5 => (_value >> 22) & 0x1F; + } + + readonly struct InstRnb16w4Rtb12w4Imm12b0w12 + { + private readonly uint _value; + public InstRnb16w4Rtb12w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstRnb16w4Rtb12w4Pb10w1Ub9w1Wb8w1Imm8b0w8 + { + private readonly uint _value; + public InstRnb16w4Rtb12w4Pb10w1Ub9w1Wb8w1Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint W => (_value >> 8) & 0x1; + public readonly uint U => (_value >> 9) & 0x1; + public readonly uint P => (_value >> 10) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Pb24w1Ub23w1Wb21w1Rtb12w4Imm12b0w12 + { + private readonly uint _value; + public InstCondb28w4Pb24w1Ub23w1Wb21w1Rtb12w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstUb23w1Rtb12w4Imm12b0w12 + { + private readonly uint _value; + public InstUb23w1Rtb12w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint U => (_value >> 23) & 0x1; + } + + readonly struct InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm5b7w5Stypeb5w2Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm5b7w5Stypeb5w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 5) & 0x3; + public readonly uint Imm5 => (_value >> 7) & 0x1F; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRmb22w3Rnb19w3Rtb16w3 + { + private readonly uint _value; + public InstRmb22w3Rnb19w3Rtb16w3(uint value) => _value = value; + public readonly uint Rt => (_value >> 16) & 0x7; + public readonly uint Rn => (_value >> 19) & 0x7; + public readonly uint Rm => (_value >> 22) & 0x7; + } + + readonly struct InstRnb16w4Rtb12w4Imm2b4w2Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rtb12w4Imm2b4w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Imm2 => (_value >> 4) & 0x3; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4 + { + private readonly uint _value; + public InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4(uint value) => _value = value; + public readonly uint Imm4l => (_value >> 0) & 0xF; + public readonly uint Imm4h => (_value >> 8) & 0xF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstPb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Rt2b8w4Imm8b0w8 + { + private readonly uint _value; + public InstPb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Rt2b8w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rt2 => (_value >> 8) & 0xF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + } + + readonly struct InstCondb28w4Ub23w1Rtb12w4Imm4hb8w4Imm4lb0w4 + { + private readonly uint _value; + public InstCondb28w4Ub23w1Rtb12w4Imm4hb8w4Imm4lb0w4(uint value) => _value = value; + public readonly uint Imm4l => (_value >> 0) & 0xF; + public readonly uint Imm4h => (_value >> 8) & 0xF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstPb24w1Ub23w1Wb21w1Rtb12w4Rt2b8w4Imm8b0w8 + { + private readonly uint _value; + public InstPb24w1Ub23w1Wb21w1Rtb12w4Rt2b8w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rt2 => (_value >> 8) & 0xF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + } + + readonly struct InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4 + { + private readonly uint _value; + public InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4(uint value) => _value = value; + public readonly uint Imm4l => (_value >> 0) & 0xF; + public readonly uint Imm4h => (_value >> 8) & 0xF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstCondb28w4Ub23w1Rnb16w4Rtb12w4Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Ub23w1Rnb16w4Rtb12w4Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstCondb28w4Pb24w1Ub23w1Wb21w1Rtb12w4Imm4hb8w4Imm4lb0w4 + { + private readonly uint _value; + public InstCondb28w4Pb24w1Ub23w1Wb21w1Rtb12w4Imm4hb8w4Imm4lb0w4(uint value) => _value = value; + public readonly uint Imm4l => (_value >> 0) & 0xF; + public readonly uint Imm4h => (_value >> 8) & 0xF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRtb24w3Imm8b16w8 + { + private readonly uint _value; + public InstRtb24w3Imm8b16w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 16) & 0xFF; + public readonly uint Rt => (_value >> 24) & 0x7; + } + + readonly struct InstCondb28w4Opc1b21w3Crnb16w4Rtb12w4Coproc0b8w1Opc2b5w3Crmb0w4 + { + private readonly uint _value; + public InstCondb28w4Opc1b21w3Crnb16w4Rtb12w4Coproc0b8w1Opc2b5w3Crmb0w4(uint value) => _value = value; + public readonly uint Crm => (_value >> 0) & 0xF; + public readonly uint Opc2 => (_value >> 5) & 0x7; + public readonly uint Coproc0 => (_value >> 8) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Crn => (_value >> 16) & 0xF; + public readonly uint Opc1 => (_value >> 21) & 0x7; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstOpc1b21w3Crnb16w4Rtb12w4Coproc0b8w1Opc2b5w3Crmb0w4 + { + private readonly uint _value; + public InstOpc1b21w3Crnb16w4Rtb12w4Coproc0b8w1Opc2b5w3Crmb0w4(uint value) => _value = value; + public readonly uint Crm => (_value >> 0) & 0xF; + public readonly uint Opc2 => (_value >> 5) & 0x7; + public readonly uint Coproc0 => (_value >> 8) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Crn => (_value >> 16) & 0xF; + public readonly uint Opc1 => (_value >> 21) & 0x7; + } + + readonly struct InstCondb28w4Rt2b16w4Rtb12w4Coproc0b8w1Opc1b4w4Crmb0w4 + { + private readonly uint _value; + public InstCondb28w4Rt2b16w4Rtb12w4Coproc0b8w1Opc1b4w4Crmb0w4(uint value) => _value = value; + public readonly uint Crm => (_value >> 0) & 0xF; + public readonly uint Opc1 => (_value >> 4) & 0xF; + public readonly uint Coproc0 => (_value >> 8) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rt2 => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRt2b16w4Rtb12w4Coproc0b8w1Opc1b4w4Crmb0w4 + { + private readonly uint _value; + public InstRt2b16w4Rtb12w4Coproc0b8w1Opc1b4w4Crmb0w4(uint value) => _value = value; + public readonly uint Crm => (_value >> 0) & 0xF; + public readonly uint Opc1 => (_value >> 4) & 0xF; + public readonly uint Coproc0 => (_value >> 8) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rt2 => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Sb20w1Rdb16w4Rab12w4Rmb8w4Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Sb20w1Rdb16w4Rab12w4Rmb8w4Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Ra => (_value >> 12) & 0xF; + public readonly uint Rd => (_value >> 16) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rab12w4Rdb8w4Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rab12w4Rdb8w4Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Ra => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rdb16w4Rab12w4Rmb8w4Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdb16w4Rab12w4Rmb8w4Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Ra => (_value >> 12) & 0xF; + public readonly uint Rd => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstCondb28w4Imm4b16w4Rdb12w4Imm12b0w12 + { + private readonly uint _value; + public InstCondb28w4Imm4b16w4Rdb12w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Imm4 => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstIb26w1Imm4b16w4Imm3b12w3Rdb8w4Imm8b0w8 + { + private readonly uint _value; + public InstIb26w1Imm4b16w4Imm3b12w3Rdb8w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint Imm4 => (_value >> 16) & 0xF; + public readonly uint I => (_value >> 26) & 0x1; + } + + readonly struct InstDb23w1Rmb19w4Rdb16w3 + { + private readonly uint _value; + public InstDb23w1Rmb19w4Rdb16w3(uint value) => _value = value; + public readonly uint Rd => (_value >> 16) & 0x7; + public readonly uint Rm => (_value >> 19) & 0xF; + public readonly uint D => (_value >> 23) & 0x1; + } + + readonly struct InstOpb27w2Imm5b22w5Rmb19w3Rdb16w3 + { + private readonly uint _value; + public InstOpb27w2Imm5b22w5Rmb19w3Rdb16w3(uint value) => _value = value; + public readonly uint Rd => (_value >> 16) & 0x7; + public readonly uint Rm => (_value >> 19) & 0x7; + public readonly uint Imm5 => (_value >> 22) & 0x1F; + public readonly uint Op => (_value >> 27) & 0x3; + } + + readonly struct InstCondb28w4Sb20w1Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Sb20w1Rdb12w4Rsb8w4Stypeb5w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 5) & 0x3; + public readonly uint Rs => (_value >> 8) & 0xF; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRsb19w3Rdmb16w3 + { + private readonly uint _value; + public InstRsb19w3Rdmb16w3(uint value) => _value = value; + public readonly uint Rdm => (_value >> 16) & 0x7; + public readonly uint Rs => (_value >> 19) & 0x7; + } + + readonly struct InstStypeb21w2Sb20w1Rmb16w4Rdb8w4Rsb0w4 + { + private readonly uint _value; + public InstStypeb21w2Sb20w1Rmb16w4Rdb8w4Rsb0w4(uint value) => _value = value; + public readonly uint Rs => (_value >> 0) & 0xF; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Rm => (_value >> 16) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint Stype => (_value >> 21) & 0x3; + } + + readonly struct InstCondb28w4Rb22w1Rdb12w4 + { + private readonly uint _value; + public InstCondb28w4Rb22w1Rdb12w4(uint value) => _value = value; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint R => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRb20w1Rdb8w4 + { + private readonly uint _value; + public InstRb20w1Rdb8w4(uint value) => _value = value; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint R => (_value >> 20) & 0x1; + } + + readonly struct InstCondb28w4Rb22w1M1b16w4Rdb12w4Mb8w1 + { + private readonly uint _value; + public InstCondb28w4Rb22w1M1b16w4Rdb12w4Mb8w1(uint value) => _value = value; + public readonly uint M => (_value >> 8) & 0x1; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint M1 => (_value >> 16) & 0xF; + public readonly uint R => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRb20w1M1b16w4Rdb8w4Mb4w1 + { + private readonly uint _value; + public InstRb20w1M1b16w4Rdb8w4Mb4w1(uint value) => _value = value; + public readonly uint M => (_value >> 4) & 0x1; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint M1 => (_value >> 16) & 0xF; + public readonly uint R => (_value >> 20) & 0x1; + } + + readonly struct InstCondb28w4Rb22w1M1b16w4Mb8w1Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rb22w1M1b16w4Mb8w1Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 8) & 0x1; + public readonly uint M1 => (_value >> 16) & 0xF; + public readonly uint R => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRb20w1Rnb16w4M1b8w4Mb4w1 + { + private readonly uint _value; + public InstRb20w1Rnb16w4M1b8w4Mb4w1(uint value) => _value = value; + public readonly uint M => (_value >> 4) & 0x1; + public readonly uint M1 => (_value >> 8) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint R => (_value >> 20) & 0x1; + } + + readonly struct InstCondb28w4Rb22w1Maskb16w4Imm12b0w12 + { + private readonly uint _value; + public InstCondb28w4Rb22w1Maskb16w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Mask => (_value >> 16) & 0xF; + public readonly uint R => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstCondb28w4Rb22w1Maskb16w4Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rb22w1Maskb16w4Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint Mask => (_value >> 16) & 0xF; + public readonly uint R => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRb20w1Rnb16w4Maskb8w4 + { + private readonly uint _value; + public InstRb20w1Rnb16w4Maskb8w4(uint value) => _value = value; + public readonly uint Mask => (_value >> 8) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint R => (_value >> 20) & 0x1; + } + + readonly struct InstCondb28w4Sb20w1Rdb16w4Rmb8w4Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Sb20w1Rdb16w4Rmb8w4Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Rd => (_value >> 16) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb19w3Rdmb16w3 + { + private readonly uint _value; + public InstRnb19w3Rdmb16w3(uint value) => _value = value; + public readonly uint Rdm => (_value >> 16) & 0x7; + public readonly uint Rn => (_value >> 19) & 0x7; + } + + readonly struct InstRmb19w3Rdb16w3 + { + private readonly uint _value; + public InstRmb19w3Rdb16w3(uint value) => _value = value; + public readonly uint Rd => (_value >> 16) & 0x7; + public readonly uint Rm => (_value >> 19) & 0x7; + } + + readonly struct InstCondb28w4Rnb16w4Rdb12w4Imm5b7w5Tbb6w1Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Rnb16w4Rdb12w4Imm5b7w5Tbb6w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Tb => (_value >> 6) & 0x1; + public readonly uint Imm5 => (_value >> 7) & 0x1F; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Imm3b12w3Rdb8w4Imm2b6w2Tbb5w1Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Imm3b12w3Rdb8w4Imm2b6w2Tbb5w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Tb => (_value >> 5) & 0x1; + public readonly uint Imm2 => (_value >> 6) & 0x3; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstUb23w1Rb22w1Rnb16w4Imm12b0w12 + { + private readonly uint _value; + public InstUb23w1Rb22w1Rnb16w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint R => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + } + + readonly struct InstWb21w1Rnb16w4Imm12b0w12 + { + private readonly uint _value; + public InstWb21w1Rnb16w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + } + + readonly struct InstWb21w1Rnb16w4Imm8b0w8 + { + private readonly uint _value; + public InstWb21w1Rnb16w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + } + + readonly struct InstUb23w1Imm12b0w12 + { + private readonly uint _value; + public InstUb23w1Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint U => (_value >> 23) & 0x1; + } + + readonly struct InstUb23w1Rb22w1Rnb16w4Imm5b7w5Stypeb5w2Rmb0w4 + { + private readonly uint _value; + public InstUb23w1Rb22w1Rnb16w4Imm5b7w5Stypeb5w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 5) & 0x3; + public readonly uint Imm5 => (_value >> 7) & 0x1F; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint R => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + } + + readonly struct InstWb21w1Rnb16w4Imm2b4w2Rmb0w4 + { + private readonly uint _value; + public InstWb21w1Rnb16w4Imm2b4w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Imm2 => (_value >> 4) & 0x3; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + } + + readonly struct InstUb23w1Rnb16w4Imm12b0w12 + { + private readonly uint _value; + public InstUb23w1Rnb16w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint U => (_value >> 23) & 0x1; + } + + readonly struct InstRnb16w4Imm12b0w12 + { + private readonly uint _value; + public InstRnb16w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstRnb16w4Imm8b0w8 + { + private readonly uint _value; + public InstRnb16w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstUb23w1Rnb16w4Imm5b7w5Stypeb5w2Rmb0w4 + { + private readonly uint _value; + public InstUb23w1Rnb16w4Imm5b7w5Stypeb5w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Stype => (_value >> 5) & 0x3; + public readonly uint Imm5 => (_value >> 7) & 0x1F; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint U => (_value >> 23) & 0x1; + } + + readonly struct InstRnb16w4Imm2b4w2Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Imm2b4w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Imm2 => (_value >> 4) & 0x3; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstPb24w1RegisterListb16w8 + { + private readonly uint _value; + public InstPb24w1RegisterListb16w8(uint value) => _value = value; + public readonly uint RegisterList => (_value >> 16) & 0xFF; + public readonly uint P => (_value >> 24) & 0x1; + } + + readonly struct InstMb24w1RegisterListb16w8 + { + private readonly uint _value; + public InstMb24w1RegisterListb16w8(uint value) => _value = value; + public readonly uint RegisterList => (_value >> 16) & 0xFF; + public readonly uint M => (_value >> 24) & 0x1; + } + + readonly struct InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Rnb16w4Rdb12w4Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb19w3Rdb16w3 + { + private readonly uint _value; + public InstRnb19w3Rdb16w3(uint value) => _value = value; + public readonly uint Rd => (_value >> 16) & 0x7; + public readonly uint Rn => (_value >> 19) & 0x7; + } + + readonly struct InstCondb28w4Widthm1b16w5Rdb12w4Lsbb7w5Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Widthm1b16w5Rdb12w4Lsbb7w5Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint Lsb => (_value >> 7) & 0x1F; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Widthm1 => (_value >> 16) & 0x1F; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Imm3b12w3Rdb8w4Imm2b6w2Widthm1b0w5 + { + private readonly uint _value; + public InstRnb16w4Imm3b12w3Rdb8w4Imm2b6w2Widthm1b0w5(uint value) => _value = value; + public readonly uint Widthm1 => (_value >> 0) & 0x1F; + public readonly uint Imm2 => (_value >> 6) & 0x3; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rdb16w4Rmb8w4Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdb16w4Rmb8w4Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Rd => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstEb9w1 + { + private readonly uint _value; + public InstEb9w1(uint value) => _value = value; + public readonly uint E => (_value >> 9) & 0x1; + } + + readonly struct InstEb19w1 + { + private readonly uint _value; + public InstEb19w1(uint value) => _value = value; + public readonly uint E => (_value >> 19) & 0x1; + } + + readonly struct InstImm1b9w1 + { + private readonly uint _value; + public InstImm1b9w1(uint value) => _value = value; + public readonly uint Imm1 => (_value >> 9) & 0x1; + } + + readonly struct InstImm1b19w1 + { + private readonly uint _value; + public InstImm1b19w1(uint value) => _value = value; + public readonly uint Imm1 => (_value >> 19) & 0x1; + } + + readonly struct InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstCondb28w4Rdb16w4Rab12w4Rmb8w4Mb6w1Nb5w1Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdb16w4Rab12w4Rmb8w4Mb6w1Nb5w1Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint N => (_value >> 5) & 0x1; + public readonly uint M => (_value >> 6) & 0x1; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Ra => (_value >> 12) & 0xF; + public readonly uint Rd => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rab12w4Rdb8w4Nb5w1Mb4w1Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rab12w4Rdb8w4Nb5w1Mb4w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 4) & 0x1; + public readonly uint N => (_value >> 5) & 0x1; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Ra => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rdb16w4Rab12w4Rmb8w4Mb5w1Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdb16w4Rab12w4Rmb8w4Mb5w1Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Ra => (_value >> 12) & 0xF; + public readonly uint Rd => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rab12w4Rdb8w4Mb4w1Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rab12w4Rdb8w4Mb4w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 4) & 0x1; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Ra => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Sb20w1Rdhib16w4Rdlob12w4Rmb8w4Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Sb20w1Rdhib16w4Rdlob12w4Rmb8w4Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Rdlo => (_value >> 12) & 0xF; + public readonly uint Rdhi => (_value >> 16) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rdlob12w4Rdhib8w4Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rdlob12w4Rdhib8w4Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Rdhi => (_value >> 8) & 0xF; + public readonly uint Rdlo => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rdhib16w4Rdlob12w4Rmb8w4Mb6w1Nb5w1Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdhib16w4Rdlob12w4Rmb8w4Mb6w1Nb5w1Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint N => (_value >> 5) & 0x1; + public readonly uint M => (_value >> 6) & 0x1; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Rdlo => (_value >> 12) & 0xF; + public readonly uint Rdhi => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rdlob12w4Rdhib8w4Nb5w1Mb4w1Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rdlob12w4Rdhib8w4Nb5w1Mb4w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 4) & 0x1; + public readonly uint N => (_value >> 5) & 0x1; + public readonly uint Rdhi => (_value >> 8) & 0xF; + public readonly uint Rdlo => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rdhib16w4Rdlob12w4Rmb8w4Mb5w1Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdhib16w4Rdlob12w4Rmb8w4Mb5w1Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Rdlo => (_value >> 12) & 0xF; + public readonly uint Rdhi => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rdlob12w4Rdhib8w4Mb4w1Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rdlob12w4Rdhib8w4Mb4w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 4) & 0x1; + public readonly uint Rdhi => (_value >> 8) & 0xF; + public readonly uint Rdlo => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rdb16w4Rab12w4Rmb8w4Mb6w1Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdb16w4Rab12w4Rmb8w4Mb6w1Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 6) & 0x1; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Ra => (_value >> 12) & 0xF; + public readonly uint Rd => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstCondb28w4Rdb16w4Rab12w4Rmb8w4Rb5w1Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdb16w4Rab12w4Rmb8w4Rb5w1Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint R => (_value >> 5) & 0x1; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Ra => (_value >> 12) & 0xF; + public readonly uint Rd => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rab12w4Rdb8w4Rb4w1Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rab12w4Rdb8w4Rb4w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint R => (_value >> 4) & 0x1; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Ra => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rdb16w4Rmb8w4Rb5w1Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdb16w4Rmb8w4Rb5w1Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint R => (_value >> 5) & 0x1; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Rd => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rdb8w4Rb4w1Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rdb8w4Rb4w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint R => (_value >> 4) & 0x1; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rdb16w4Rmb8w4Mb5w1Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdb16w4Rmb8w4Mb5w1Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Rd => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rdb8w4Mb4w1Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rdb8w4Mb4w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 4) & 0x1; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rdb16w4Rmb8w4Mb6w1Nb5w1Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdb16w4Rmb8w4Mb6w1Nb5w1Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint N => (_value >> 5) & 0x1; + public readonly uint M => (_value >> 6) & 0x1; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Rd => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rdb8w4Nb5w1Mb4w1Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rdb8w4Nb5w1Mb4w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 4) & 0x1; + public readonly uint N => (_value >> 5) & 0x1; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rdb16w4Rmb8w4Mb6w1Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdb16w4Rmb8w4Mb6w1Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 6) & 0x1; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Rd => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstCondb28w4SatImmb16w5Rdb12w4Imm5b7w5Shb6w1Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4SatImmb16w5Rdb12w4Imm5b7w5Shb6w1Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint Sh => (_value >> 6) & 0x1; + public readonly uint Imm5 => (_value >> 7) & 0x1F; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint SatImm => (_value >> 16) & 0x1F; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstShb21w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2SatImmb0w5 + { + private readonly uint _value; + public InstShb21w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2SatImmb0w5(uint value) => _value = value; + public readonly uint SatImm => (_value >> 0) & 0x1F; + public readonly uint Imm2 => (_value >> 6) & 0x3; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Imm3 => (_value >> 12) & 0x7; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint Sh => (_value >> 21) & 0x1; + } + + readonly struct InstCondb28w4SatImmb16w4Rdb12w4Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4SatImmb16w4Rdb12w4Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint SatImm => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rdb8w4SatImmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rdb8w4SatImmb0w4(uint value) => _value = value; + public readonly uint SatImm => (_value >> 0) & 0xF; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rnb16w4Rtb0w4 + { + private readonly uint _value; + public InstCondb28w4Rnb16w4Rtb0w4(uint value) => _value = value; + public readonly uint Rt => (_value >> 0) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstCondb28w4Rnb16w4Rdb12w4Rtb0w4 + { + private readonly uint _value; + public InstCondb28w4Rnb16w4Rdb12w4Rtb0w4(uint value) => _value = value; + public readonly uint Rt => (_value >> 0) & 0xF; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rtb12w4Rdb0w4 + { + private readonly uint _value; + public InstRnb16w4Rtb12w4Rdb0w4(uint value) => _value = value; + public readonly uint Rd => (_value >> 0) & 0xF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstRnb16w4Rtb12w4Rt2b8w4Rdb0w4 + { + private readonly uint _value; + public InstRnb16w4Rtb12w4Rt2b8w4Rdb0w4(uint value) => _value = value; + public readonly uint Rd => (_value >> 0) & 0xF; + public readonly uint Rt2 => (_value >> 8) & 0xF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstWb21w1Rnb16w4Mb14w1RegisterListb0w14 + { + private readonly uint _value; + public InstWb21w1Rnb16w4Mb14w1RegisterListb0w14(uint value) => _value = value; + public readonly uint RegisterList => (_value >> 0) & 0x3FFF; + public readonly uint M => (_value >> 14) & 0x1; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + } + + readonly struct InstRnb16w4Rtb12w4Rdb8w4Imm8b0w8 + { + private readonly uint _value; + public InstRnb16w4Rtb12w4Rdb8w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rnb16w4Rdb12w4Rotateb10w2Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Rnb16w4Rdb12w4Rotateb10w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Rotate => (_value >> 10) & 0x3; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRnb16w4Rdb8w4Rotateb4w2Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Rdb8w4Rotateb4w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Rotate => (_value >> 4) & 0x3; + public readonly uint Rd => (_value >> 8) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rdb12w4Rotateb10w2Rmb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdb12w4Rotateb10w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Rotate => (_value >> 10) & 0x3; + public readonly uint Rd => (_value >> 12) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRdb8w4Rotateb4w2Rmb0w4 + { + private readonly uint _value; + public InstRdb8w4Rotateb4w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Rotate => (_value >> 4) & 0x3; + public readonly uint Rd => (_value >> 8) & 0xF; + } + + readonly struct InstRnb16w4Hb4w1Rmb0w4 + { + private readonly uint _value; + public InstRnb16w4Hb4w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint H => (_value >> 4) & 0x1; + public readonly uint Rn => (_value >> 16) & 0xF; + } + + readonly struct InstImm12b8w12Imm4b0w4 + { + private readonly uint _value; + public InstImm12b8w12Imm4b0w4(uint value) => _value = value; + public readonly uint Imm4 => (_value >> 0) & 0xF; + public readonly uint Imm12 => (_value >> 8) & 0xFFF; + } + + readonly struct InstImm4b16w4Imm12b0w12 + { + private readonly uint _value; + public InstImm4b16w4Imm12b0w12(uint value) => _value = value; + public readonly uint Imm12 => (_value >> 0) & 0xFFF; + public readonly uint Imm4 => (_value >> 16) & 0xF; + } + + readonly struct InstCondb28w4Rdhib16w4Rdlob12w4Rmb8w4Rnb0w4 + { + private readonly uint _value; + public InstCondb28w4Rdhib16w4Rdlob12w4Rmb8w4Rnb0w4(uint value) => _value = value; + public readonly uint Rn => (_value >> 0) & 0xF; + public readonly uint Rm => (_value >> 8) & 0xF; + public readonly uint Rdlo => (_value >> 12) & 0xF; + public readonly uint Rdhi => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 24) & 0x1; + } + + readonly struct InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 28) & 0x1; + } + + readonly struct InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 24) & 0x1; + } + + readonly struct InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 28) & 0x1; + } + + readonly struct InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Sz => (_value >> 20) & 0x1; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint F => (_value >> 10) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Size => (_value >> 18) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstCondb28w4Db22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstCondb28w4Db22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 + { + private readonly uint _value; + public InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4(uint value) => _value = value; + public readonly uint Imm4 => (_value >> 0) & 0xF; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm3 => (_value >> 16) & 0x7; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint I => (_value >> 24) & 0x1; + } + + readonly struct InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 + { + private readonly uint _value; + public InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4(uint value) => _value = value; + public readonly uint Imm4 => (_value >> 0) & 0xF; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm3 => (_value >> 16) & 0x7; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint I => (_value >> 28) & 0x1; + } + + readonly struct InstRotb24w1Db22w1Sb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstRotb24w1Db22w1Sb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Rot => (_value >> 24) & 0x1; + } + + readonly struct InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Size => (_value >> 18) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstRotb23w2Db22w1Sb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstRotb23w2Db22w1Sb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint S => (_value >> 20) & 0x1; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Rot => (_value >> 23) & 0x3; + } + + readonly struct InstSb23w1Db22w1Rotb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstSb23w1Db22w1Rotb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Rot => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint S => (_value >> 23) & 0x1; + } + + readonly struct InstCondb28w4Db22w1Vdb12w4Sizeb8w2 + { + private readonly uint _value; + public InstCondb28w4Db22w1Vdb12w4Sizeb8w2(uint value) => _value = value; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstDb22w1Vdb12w4Sizeb8w2 + { + private readonly uint _value; + public InstDb22w1Vdb12w4Sizeb8w2(uint value) => _value = value; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint Op => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Size => (_value >> 18) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Op => (_value >> 7) & 0x1; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstCondb28w4Db22w1Opb16w1Vdb12w4Szb8w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstCondb28w4Db22w1Opb16w1Vdb12w4Szb8w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Sz => (_value >> 8) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Op => (_value >> 16) & 0x1; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstDb22w1Opb16w1Vdb12w4Szb8w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Opb16w1Vdb12w4Szb8w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Sz => (_value >> 8) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Op => (_value >> 16) & 0x1; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstCondb28w4Db22w1Vdb12w4Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstCondb28w4Db22w1Vdb12w4Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstDb22w1Vdb12w4Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Vdb12w4Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Sizeb18w2Vdb12w4Opb8w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Sizeb18w2Vdb12w4Opb8w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Op => (_value >> 8) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Size => (_value >> 18) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Sizeb18w2Vdb12w4Opb7w2Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Sizeb18w2Vdb12w4Opb7w2Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint Op => (_value >> 7) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Size => (_value >> 18) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstCondb28w4Db22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstCondb28w4Db22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Op => (_value >> 7) & 0x1; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstUb24w1Db22w1Imm6b16w6Vdb12w4Opb8w2Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb24w1Db22w1Imm6b16w6Vdb12w4Opb8w2Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint Op => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 24) & 0x1; + } + + readonly struct InstUb28w1Db22w1Imm6b16w6Vdb12w4Opb8w2Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb28w1Db22w1Imm6b16w6Vdb12w4Opb8w2Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint Op => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 28) & 0x1; + } + + readonly struct InstCondb28w4Db22w1Opb18w1Ub16w1Vdb12w4Sfb8w2Sxb7w1Ib5w1Imm4b0w4 + { + private readonly uint _value; + public InstCondb28w4Db22w1Opb18w1Ub16w1Vdb12w4Sfb8w2Sxb7w1Ib5w1Imm4b0w4(uint value) => _value = value; + public readonly uint Imm4 => (_value >> 0) & 0xF; + public readonly uint I => (_value >> 5) & 0x1; + public readonly uint Sx => (_value >> 7) & 0x1; + public readonly uint Sf => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint U => (_value >> 16) & 0x1; + public readonly uint Op => (_value >> 18) & 0x1; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstDb22w1Opb18w1Ub16w1Vdb12w4Sfb8w2Sxb7w1Ib5w1Imm4b0w4 + { + private readonly uint _value; + public InstDb22w1Opb18w1Ub16w1Vdb12w4Sfb8w2Sxb7w1Ib5w1Imm4b0w4(uint value) => _value = value; + public readonly uint Imm4 => (_value >> 0) & 0xF; + public readonly uint I => (_value >> 5) & 0x1; + public readonly uint Sx => (_value >> 7) & 0x1; + public readonly uint Sf => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint U => (_value >> 16) & 0x1; + public readonly uint Op => (_value >> 18) & 0x1; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstCondb28w4Bb22w1Qb21w1Vdb16w4Rtb12w4Db7w1Eb5w1 + { + private readonly uint _value; + public InstCondb28w4Bb22w1Qb21w1Vdb16w4Rtb12w4Db7w1Eb5w1(uint value) => _value = value; + public readonly uint E => (_value >> 5) & 0x1; + public readonly uint D => (_value >> 7) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Vd => (_value >> 16) & 0xF; + public readonly uint Q => (_value >> 21) & 0x1; + public readonly uint B => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstBb22w1Qb21w1Vdb16w4Rtb12w4Db7w1Eb5w1 + { + private readonly uint _value; + public InstBb22w1Qb21w1Vdb16w4Rtb12w4Db7w1Eb5w1(uint value) => _value = value; + public readonly uint E => (_value >> 5) & 0x1; + public readonly uint D => (_value >> 7) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Vd => (_value >> 16) & 0xF; + public readonly uint Q => (_value >> 21) & 0x1; + public readonly uint B => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Imm4b16w4Vdb12w4Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Imm4b16w4Vdb12w4Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm4 => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Vnb16w4Vdb12w4Imm4b8w4Nb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Vnb16w4Vdb12w4Imm4b8w4Nb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Imm4 => (_value >> 8) & 0xF; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 + { + private readonly uint _value; + public InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint IndexAlign => (_value >> 4) & 0xF; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Tb5w1Ab4w1Rmb0w4 + { + private readonly uint _value; + public InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Tb5w1Ab4w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint A => (_value >> 4) & 0x1; + public readonly uint T => (_value >> 5) & 0x1; + public readonly uint Size => (_value >> 6) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 + { + private readonly uint _value; + public InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint Align => (_value >> 4) & 0x3; + public readonly uint Size => (_value >> 6) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Tb5w1Rmb0w4 + { + private readonly uint _value; + public InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Tb5w1Rmb0w4(uint value) => _value = value; + public readonly uint Rm => (_value >> 0) & 0xF; + public readonly uint T => (_value >> 5) & 0x1; + public readonly uint Size => (_value >> 6) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstCondb28w4Pb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm8b0w8 + { + private readonly uint _value; + public InstCondb28w4Pb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstPb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm8b0w8 + { + private readonly uint _value; + public InstPb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint W => (_value >> 21) & 0x1; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint P => (_value >> 24) & 0x1; + } + + readonly struct InstCondb28w4Ub23w1Db22w1Rnb16w4Vdb12w4Sizeb8w2Imm8b0w8 + { + private readonly uint _value; + public InstCondb28w4Ub23w1Db22w1Rnb16w4Vdb12w4Sizeb8w2Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstUb23w1Db22w1Rnb16w4Vdb12w4Sizeb8w2Imm8b0w8 + { + private readonly uint _value; + public InstUb23w1Db22w1Rnb16w4Vdb12w4Sizeb8w2Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Rn => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + } + + readonly struct InstCondb28w4Ub23w1Db22w1Vdb12w4Sizeb8w2Imm8b0w8 + { + private readonly uint _value; + public InstCondb28w4Ub23w1Db22w1Vdb12w4Sizeb8w2Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstUb23w1Db22w1Vdb12w4Sizeb8w2Imm8b0w8 + { + private readonly uint _value; + public InstUb23w1Db22w1Vdb12w4Sizeb8w2Imm8b0w8(uint value) => _value = value; + public readonly uint Imm8 => (_value >> 0) & 0xFF; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 23) & 0x1; + } + + readonly struct InstQb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Fb8w1Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstQb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Fb8w1Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint F => (_value >> 8) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Q => (_value >> 24) & 0x1; + } + + readonly struct InstQb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Fb8w1Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstQb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Fb8w1Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint F => (_value >> 8) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Q => (_value >> 28) & 0x1; + } + + readonly struct InstDb22w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstUb24w1Db22w1Imm3hb19w3Vdb12w4Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb24w1Db22w1Imm3hb19w3Vdb12w4Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm3h => (_value >> 19) & 0x7; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 24) & 0x1; + } + + readonly struct InstUb28w1Db22w1Imm3hb19w3Vdb12w4Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb28w1Db22w1Imm3hb19w3Vdb12w4Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm3h => (_value >> 19) & 0x7; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 28) & 0x1; + } + + readonly struct InstCondb28w4Opb20w1Rt2b16w4Rtb12w4Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstCondb28w4Opb20w1Rt2b16w4Rtb12w4Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rt2 => (_value >> 16) & 0xF; + public readonly uint Op => (_value >> 20) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstOpb20w1Rt2b16w4Rtb12w4Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstOpb20w1Rt2b16w4Rtb12w4Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Rt2 => (_value >> 16) & 0xF; + public readonly uint Op => (_value >> 20) & 0x1; + } + + readonly struct InstCondb28w4Opb20w1Vnb16w4Rtb12w4Nb7w1 + { + private readonly uint _value; + public InstCondb28w4Opb20w1Vnb16w4Rtb12w4Nb7w1(uint value) => _value = value; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Op => (_value >> 20) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstOpb20w1Vnb16w4Rtb12w4Nb7w1 + { + private readonly uint _value; + public InstOpb20w1Vnb16w4Rtb12w4Nb7w1(uint value) => _value = value; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Op => (_value >> 20) & 0x1; + } + + readonly struct InstCondb28w4Db22w1Imm4hb16w4Vdb12w4Sizeb8w2Imm4lb0w4 + { + private readonly uint _value; + public InstCondb28w4Db22w1Imm4hb16w4Vdb12w4Sizeb8w2Imm4lb0w4(uint value) => _value = value; + public readonly uint Imm4l => (_value >> 0) & 0xF; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm4h => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstDb22w1Imm4hb16w4Vdb12w4Sizeb8w2Imm4lb0w4 + { + private readonly uint _value; + public InstDb22w1Imm4hb16w4Vdb12w4Sizeb8w2Imm4lb0w4(uint value) => _value = value; + public readonly uint Imm4l => (_value >> 0) & 0xF; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm4h => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstCondb28w4Opc1b21w2Vdb16w4Rtb12w4Db7w1Opc2b5w2 + { + private readonly uint _value; + public InstCondb28w4Opc1b21w2Vdb16w4Rtb12w4Db7w1Opc2b5w2(uint value) => _value = value; + public readonly uint Opc2 => (_value >> 5) & 0x3; + public readonly uint D => (_value >> 7) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Vd => (_value >> 16) & 0xF; + public readonly uint Opc1 => (_value >> 21) & 0x3; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstOpc1b21w2Vdb16w4Rtb12w4Db7w1Opc2b5w2 + { + private readonly uint _value; + public InstOpc1b21w2Vdb16w4Rtb12w4Db7w1Opc2b5w2(uint value) => _value = value; + public readonly uint Opc2 => (_value >> 5) & 0x3; + public readonly uint D => (_value >> 7) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Vd => (_value >> 16) & 0xF; + public readonly uint Opc1 => (_value >> 21) & 0x3; + } + + readonly struct InstCondb28w4Ub23w1Opc1b21w2Vnb16w4Rtb12w4Nb7w1Opc2b5w2 + { + private readonly uint _value; + public InstCondb28w4Ub23w1Opc1b21w2Vnb16w4Rtb12w4Nb7w1Opc2b5w2(uint value) => _value = value; + public readonly uint Opc2 => (_value >> 5) & 0x3; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Opc1 => (_value >> 21) & 0x3; + public readonly uint U => (_value >> 23) & 0x1; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstUb23w1Opc1b21w2Vnb16w4Rtb12w4Nb7w1Opc2b5w2 + { + private readonly uint _value; + public InstUb23w1Opc1b21w2Vnb16w4Rtb12w4Nb7w1Opc2b5w2(uint value) => _value = value; + public readonly uint Opc2 => (_value >> 5) & 0x3; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Opc1 => (_value >> 21) & 0x3; + public readonly uint U => (_value >> 23) & 0x1; + } + + readonly struct InstCondb28w4Regb16w4Rtb12w4 + { + private readonly uint _value; + public InstCondb28w4Regb16w4Rtb12w4(uint value) => _value = value; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Reg => (_value >> 16) & 0xF; + public readonly uint Cond => (_value >> 28) & 0xF; + } + + readonly struct InstRegb16w4Rtb12w4 + { + private readonly uint _value; + public InstRegb16w4Rtb12w4(uint value) => _value = value; + public readonly uint Rt => (_value >> 12) & 0xF; + public readonly uint Reg => (_value >> 16) & 0xF; + } + + readonly struct InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Opb9w1Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Opb9w1Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Op => (_value >> 9) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 24) & 0x1; + } + + readonly struct InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Opb9w1Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Opb9w1Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Op => (_value >> 9) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 28) & 0x1; + } + + readonly struct InstOpb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstOpb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Op => (_value >> 24) & 0x1; + } + + readonly struct InstOpb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstOpb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Op => (_value >> 28) & 0x1; + } + + readonly struct InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Sz => (_value >> 20) & 0x1; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstQb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstQb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Q => (_value >> 24) & 0x1; + } + + readonly struct InstQb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstQb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Size => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint Q => (_value >> 28) & 0x1; + } + + readonly struct InstDb22w1Sizeb18w2Vdb12w4Opb6w2Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Sizeb18w2Vdb12w4Opb6w2Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Op => (_value >> 6) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Size => (_value >> 18) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstUb24w1Db22w1Imm6b16w6Vdb12w4Opb8w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb24w1Db22w1Imm6b16w6Vdb12w4Opb8w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Op => (_value >> 8) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 24) & 0x1; + } + + readonly struct InstUb28w1Db22w1Imm6b16w6Vdb12w4Opb8w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb28w1Db22w1Imm6b16w6Vdb12w4Opb8w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Op => (_value >> 8) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 28) & 0x1; + } + + readonly struct InstUb24w1Db22w1Imm6b16w6Vdb12w4Opb8w1Lb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb24w1Db22w1Imm6b16w6Vdb12w4Opb8w1Lb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint L => (_value >> 7) & 0x1; + public readonly uint Op => (_value >> 8) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 24) & 0x1; + } + + readonly struct InstUb28w1Db22w1Imm6b16w6Vdb12w4Opb8w1Lb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb28w1Db22w1Imm6b16w6Vdb12w4Opb8w1Lb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint L => (_value >> 7) & 0x1; + public readonly uint Op => (_value >> 8) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 28) & 0x1; + } + + readonly struct InstDb22w1Sizeb18w2Vdb12w4Fb8w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Sizeb18w2Vdb12w4Fb8w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint F => (_value >> 8) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Size => (_value >> 18) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstUb24w1Db22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb24w1Db22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint L => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 24) & 0x1; + } + + readonly struct InstUb28w1Db22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb28w1Db22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint L => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 28) & 0x1; + } + + readonly struct InstDb22w1Imm6b16w6Vdb12w4Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Imm6b16w6Vdb12w4Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Ccb20w2Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Ccb20w2Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Size => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint Cc => (_value >> 20) & 0x3; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstUb24w1Db22w1Imm6b16w6Vdb12w4Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb24w1Db22w1Imm6b16w6Vdb12w4Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 24) & 0x1; + } + + readonly struct InstUb28w1Db22w1Imm6b16w6Vdb12w4Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstUb28w1Db22w1Imm6b16w6Vdb12w4Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint D => (_value >> 22) & 0x1; + public readonly uint U => (_value >> 28) & 0x1; + } + + readonly struct InstDb22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint L => (_value >> 7) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Imm6 => (_value >> 16) & 0x3F; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Vdb12w4Qb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Vdb12w4Qb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Q => (_value >> 6) & 0x1; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } + + readonly struct InstDb22w1Vnb16w4Vdb12w4Lenb8w2Nb7w1Opb6w1Mb5w1Vmb0w4 + { + private readonly uint _value; + public InstDb22w1Vnb16w4Vdb12w4Lenb8w2Nb7w1Opb6w1Mb5w1Vmb0w4(uint value) => _value = value; + public readonly uint Vm => (_value >> 0) & 0xF; + public readonly uint M => (_value >> 5) & 0x1; + public readonly uint Op => (_value >> 6) & 0x1; + public readonly uint N => (_value >> 7) & 0x1; + public readonly uint Len => (_value >> 8) & 0x3; + public readonly uint Vd => (_value >> 12) & 0xF; + public readonly uint Vn => (_value >> 16) & 0xF; + public readonly uint D => (_value >> 22) & 0x1; + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstFlags.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstFlags.cs new file mode 100644 index 00000000..a1937e08 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstFlags.cs @@ -0,0 +1,63 @@ +using System; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + [Flags] + enum InstFlags + { + None = 0, + Cond = 1 << 0, + Rd = 1 << 1, + RdLo = 1 << 2, + RdHi = 1 << 3, + Rdn = 1 << 4, + Dn = 1 << 5, + Rt = 1 << 6, + Rt2 = 1 << 7, + Rlist = 1 << 8, + Rd16 = 1 << 9, + ReadRd = 1 << 10, + WBack = 1 << 11, + Thumb16 = 1 << 12, + + RdnDn = Rdn | Dn, + RdRd16 = Rd | Rd16, + RtRt2 = Rt | Rt2, + RdLoRdHi = RdLo | RdHi, + RdLoHi = Rd | RdHi, + RdRtRead = Rd | RtRead, + RdRtReadRd16 = Rd | RtRead | Rd16, + RdRt2Read = Rd | Rt2 | RtRead, + RdRt2ReadRd16 = Rd | Rt2 | RtRead | Rd16, + RtRd16 = Rt | Rd16, + RtWBack = Rt | WBack, + Rt2WBack = Rt2 | RtWBack, + RtRead = Rt | ReadRd, + RtReadRd16 = Rt | ReadRd | Rd16, + Rt2Read = Rt2 | RtRead, + RtReadWBack = RtRead | WBack, + Rt2ReadWBack = Rt2 | RtReadWBack, + RlistWBack = Rlist | WBack, + RlistRead = Rlist | ReadRd, + RlistReadWBack = Rlist | ReadRd | WBack, + + CondRd = Cond | Rd, + CondRdLoHi = Cond | Rd | RdHi, + CondRt = Cond | Rt, + CondRt2 = Cond | Rt | Rt2, + CondRd16 = Cond | Rd | Rd16, + CondWBack = Cond | WBack, + CondRdRtRead = Cond | Rd | RtRead, + CondRdRt2Read = Cond | Rd | Rt2 | RtRead, + CondRtWBack = Cond | RtWBack, + CondRt2WBack = Cond | Rt2 | RtWBack, + CondRtRead = Cond | RtRead, + CondRt2Read = Cond | Rt2 | RtRead, + CondRtReadWBack = Cond | RtReadWBack, + CondRt2ReadWBack = Cond | Rt2 | RtReadWBack, + CondRlist = Cond | Rlist, + CondRlistWBack = Cond | Rlist | WBack, + CondRlistRead = Cond | Rlist | ReadRd, + CondRlistReadWBack = Cond | Rlist | ReadRd | WBack, + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstInfo.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstInfo.cs new file mode 100644 index 00000000..80481ec6 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstInfo.cs @@ -0,0 +1,20 @@ +using System; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + readonly struct InstInfo + { + public readonly uint Encoding; + public readonly InstName Name; + public readonly Action<CodeGenContext, uint> EmitFunc; + public readonly InstFlags Flags; + + public InstInfo(uint encoding, InstName name, Action<CodeGenContext, uint> emitFunc, InstFlags flags) + { + Encoding = encoding; + Name = name; + EmitFunc = emitFunc; + Flags = flags; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstInfoForTable.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstInfoForTable.cs new file mode 100644 index 00000000..25739d56 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstInfoForTable.cs @@ -0,0 +1,79 @@ +using Ryujinx.Cpu.LightningJit.Table; +using System; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + readonly struct InstInfoForTable : IInstInfo + { + public uint Encoding { get; } + public uint EncodingMask { get; } + public InstEncoding[] Constraints { get; } + public InstMeta Meta { get; } + public IsaVersion Version => Meta.Version; + public IsaFeature Feature => Meta.Feature; + + public InstInfoForTable( + uint encoding, + uint encodingMask, + InstEncoding[] constraints, + InstName name, + Action<CodeGenContext, uint> emitFunc, + IsaVersion isaVersion, + IsaFeature isaFeature, + InstFlags flags) + { + Encoding = encoding; + EncodingMask = encodingMask; + Constraints = constraints; + Meta = new(name, emitFunc, isaVersion, isaFeature, flags); + } + + public InstInfoForTable( + uint encoding, + uint encodingMask, + InstEncoding[] constraints, + InstName name, + Action<CodeGenContext, uint> emitFunc, + IsaVersion isaVersion, + InstFlags flags) : this(encoding, encodingMask, constraints, name, emitFunc, isaVersion, IsaFeature.None, flags) + { + } + + public InstInfoForTable( + uint encoding, + uint encodingMask, + InstName name, + Action<CodeGenContext, uint> emitFunc, + IsaVersion isaVersion, + IsaFeature isaFeature, + InstFlags flags) : this(encoding, encodingMask, null, name, emitFunc, isaVersion, isaFeature, flags) + { + } + + public InstInfoForTable( + uint encoding, + uint encodingMask, + InstName name, + Action<CodeGenContext, uint> emitFunc, + IsaVersion isaVersion, + InstFlags flags) : this(encoding, encodingMask, null, name, emitFunc, isaVersion, IsaFeature.None, flags) + { + } + + public bool IsConstrained(uint encoding) + { + if (Constraints != null) + { + foreach (InstEncoding constraint in Constraints) + { + if ((encoding & constraint.EncodingMask) == constraint.Encoding) + { + return true; + } + } + } + + return false; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstMeta.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstMeta.cs new file mode 100644 index 00000000..64eb41bb --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstMeta.cs @@ -0,0 +1,22 @@ +using System; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + readonly struct InstMeta + { + public readonly InstName Name; + public readonly Action<CodeGenContext, uint> EmitFunc; + public readonly IsaVersion Version; + public readonly IsaFeature Feature; + public readonly InstFlags Flags; + + public InstMeta(InstName name, Action<CodeGenContext, uint> emitFunc, IsaVersion isaVersion, IsaFeature isaFeature, InstFlags flags) + { + Name = name; + EmitFunc = emitFunc; + Version = isaVersion; + Feature = isaFeature; + Flags = flags; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstName.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstName.cs new file mode 100644 index 00000000..2ee67aa0 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstName.cs @@ -0,0 +1,562 @@ +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + enum InstName + { + AdcI, + AdcR, + AdcRr, + AddI, + AddR, + AddRr, + AddSpI, + AddSpR, + Adr, + Aesd, + Aese, + Aesimc, + Aesmc, + AndI, + AndR, + AndRr, + B, + Bfc, + Bfi, + BicI, + BicR, + BicRr, + Bkpt, + BlxR, + BlI, + Bx, + Bxj, + Cbnz, + Clrbhb, + Clrex, + Clz, + CmnI, + CmnR, + CmnRr, + CmpI, + CmpR, + CmpRr, + Cps, + Crc32, + Crc32c, + Csdb, + Dbg, + Dcps1, + Dcps2, + Dcps3, + Dmb, + Dsb, + EorI, + EorR, + EorRr, + Eret, + Esb, + Fldmx, + Fstmx, + Hlt, + Hvc, + Isb, + It, + Lda, + Ldab, + Ldaex, + Ldaexb, + Ldaexd, + Ldaexh, + Ldah, + LdcI, + LdcL, + Ldm, + Ldmda, + Ldmdb, + Ldmib, + LdmE, + LdmU, + Ldrbt, + LdrbI, + LdrbL, + LdrbR, + LdrdI, + LdrdL, + LdrdR, + Ldrex, + Ldrexb, + Ldrexd, + Ldrexh, + Ldrht, + LdrhI, + LdrhL, + LdrhR, + Ldrsbt, + LdrsbI, + LdrsbL, + LdrsbR, + Ldrsht, + LdrshI, + LdrshL, + LdrshR, + Ldrt, + LdrI, + LdrL, + LdrR, + Mcr, + Mcrr, + Mla, + Mls, + Movt, + MovI, + MovR, + MovRr, + Mrc, + Mrrc, + Mrs, + MrsBr, + MsrBr, + MsrI, + MsrR, + Mul, + MvnI, + MvnR, + MvnRr, + Nop, + OrnI, + OrnR, + OrrI, + OrrR, + OrrRr, + Pkh, + PldI, + PldL, + PldR, + PliI, + PliR, + Pop, + Pssbb, + Push, + Qadd, + Qadd16, + Qadd8, + Qasx, + Qdadd, + Qdsub, + Qsax, + Qsub, + Qsub16, + Qsub8, + Rbit, + Rev, + Rev16, + Revsh, + Rfe, + RsbI, + RsbR, + RsbRr, + RscI, + RscR, + RscRr, + Sadd16, + Sadd8, + Sasx, + Sb, + SbcI, + SbcR, + SbcRr, + Sbfx, + Sdiv, + Sel, + Setend, + Setpan, + Sev, + Sevl, + Sha1c, + Sha1h, + Sha1m, + Sha1p, + Sha1su0, + Sha1su1, + Sha256h, + Sha256h2, + Sha256su0, + Sha256su1, + Shadd16, + Shadd8, + Shasx, + Shsax, + Shsub16, + Shsub8, + Smc, + Smlabb, + Smlad, + Smlal, + Smlalbb, + Smlald, + Smlawb, + Smlsd, + Smlsld, + Smmla, + Smmls, + Smmul, + Smuad, + Smulbb, + Smull, + Smulwb, + Smusd, + Srs, + Ssat, + Ssat16, + Ssax, + Ssbb, + Ssub16, + Ssub8, + Stc, + Stl, + Stlb, + Stlex, + Stlexb, + Stlexd, + Stlexh, + Stlh, + Stm, + Stmda, + Stmdb, + Stmib, + StmU, + Strbt, + StrbI, + StrbR, + StrdI, + StrdR, + Strex, + Strexb, + Strexd, + Strexh, + Strht, + StrhI, + StrhR, + Strt, + StrI, + StrR, + SubI, + SubR, + SubRr, + SubSpI, + SubSpR, + Svc, + Sxtab, + Sxtab16, + Sxtah, + Sxtb, + Sxtb16, + Sxth, + Tbb, + TeqI, + TeqR, + TeqRr, + Tsb, + TstI, + TstR, + TstRr, + Uadd16, + Uadd8, + Uasx, + Ubfx, + Udf, + Udiv, + Uhadd16, + Uhadd8, + Uhasx, + Uhsax, + Uhsub16, + Uhsub8, + Umaal, + Umlal, + Umull, + Uqadd16, + Uqadd8, + Uqasx, + Uqsax, + Uqsub16, + Uqsub8, + Usad8, + Usada8, + Usat, + Usat16, + Usax, + Usub16, + Usub8, + Uxtab, + Uxtab16, + Uxtah, + Uxtb, + Uxtb16, + Uxth, + Vaba, + Vabal, + VabdlI, + VabdF, + VabdI, + Vabs, + Vacge, + Vacgt, + Vaddhn, + Vaddl, + Vaddw, + VaddF, + VaddI, + VandR, + VbicI, + VbicR, + Vbif, + Vbit, + Vbsl, + Vcadd, + VceqI, + VceqR, + VcgeI, + VcgeR, + VcgtI, + VcgtR, + VcleI, + Vcls, + VcltI, + Vclz, + Vcmla, + VcmlaS, + Vcmp, + Vcmpe, + Vcnt, + VcvtaAsimd, + VcvtaVfp, + Vcvtb, + VcvtbBfs, + VcvtmAsimd, + VcvtmVfp, + VcvtnAsimd, + VcvtnVfp, + VcvtpAsimd, + VcvtpVfp, + VcvtrIv, + Vcvtt, + VcvttBfs, + VcvtBfs, + VcvtDs, + VcvtHs, + VcvtIs, + VcvtIv, + VcvtVi, + VcvtXs, + VcvtXv, + Vdiv, + Vdot, + VdotS, + VdupR, + VdupS, + Veor, + Vext, + Vfma, + Vfmal, + VfmalS, + VfmaBf, + VfmaBfs, + Vfms, + Vfmsl, + VfmslS, + Vfnma, + Vfnms, + Vhadd, + Vhsub, + Vins, + Vjcvt, + Vld11, + Vld1A, + Vld1M, + Vld21, + Vld2A, + Vld2M, + Vld31, + Vld3A, + Vld3M, + Vld41, + Vld4A, + Vld4M, + Vldm, + VldrI, + VldrL, + Vmaxnm, + VmaxF, + VmaxI, + Vminnm, + VminF, + VminI, + VmlalI, + VmlalS, + VmlaF, + VmlaI, + VmlaS, + VmlslI, + VmlslS, + VmlsF, + VmlsI, + VmlsS, + Vmmla, + Vmovl, + Vmovn, + Vmovx, + VmovD, + VmovH, + VmovI, + VmovR, + VmovRs, + VmovS, + VmovSr, + VmovSs, + Vmrs, + Vmsr, + VmullI, + VmullS, + VmulF, + VmulI, + VmulS, + VmvnI, + VmvnR, + Vneg, + Vnmla, + Vnmls, + Vnmul, + VornR, + VorrI, + VorrR, + Vpadal, + Vpaddl, + VpaddF, + VpaddI, + VpmaxF, + VpmaxI, + VpminF, + VpminI, + Vqabs, + Vqadd, + Vqdmlal, + Vqdmlsl, + Vqdmulh, + Vqdmull, + Vqmovn, + Vqneg, + Vqrdmlah, + Vqrdmlsh, + Vqrdmulh, + Vqrshl, + Vqrshrn, + VqshlI, + VqshlR, + Vqshrn, + Vqsub, + Vraddhn, + Vrecpe, + Vrecps, + Vrev16, + Vrev32, + Vrev64, + Vrhadd, + VrintaAsimd, + VrintaVfp, + VrintmAsimd, + VrintmVfp, + VrintnAsimd, + VrintnVfp, + VrintpAsimd, + VrintpVfp, + VrintrVfp, + VrintxAsimd, + VrintxVfp, + VrintzAsimd, + VrintzVfp, + Vrshl, + Vrshr, + Vrshrn, + Vrsqrte, + Vrsqrts, + Vrsra, + Vrsubhn, + Vsdot, + VsdotS, + Vsel, + Vshll, + VshlI, + VshlR, + Vshr, + Vshrn, + Vsli, + Vsmmla, + Vsqrt, + Vsra, + Vsri, + Vst11, + Vst1M, + Vst21, + Vst2M, + Vst31, + Vst3M, + Vst41, + Vst4M, + Vstm, + Vstr, + Vsubhn, + Vsubl, + Vsubw, + VsubF, + VsubI, + VsudotS, + Vswp, + Vtbl, + Vtrn, + Vtst, + Vudot, + VudotS, + Vummla, + Vusdot, + VusdotS, + Vusmmla, + Vuzp, + Vzip, + Wfe, + Wfi, + Yield, + } + + static class InstNameExtensions + { + public static bool IsCall(this InstName name) + { + return name == InstName.BlI || name == InstName.BlxR; + } + + public static bool IsSystem(this InstName name) + { + switch (name) + { + case InstName.Mcr: + case InstName.Mcrr: + case InstName.Mrc: + case InstName.Mrs: + case InstName.MrsBr: + case InstName.MsrBr: + case InstName.MsrI: + case InstName.MsrR: + case InstName.Mrrc: + case InstName.Svc: + return true; + } + + return false; + } + + public static bool IsSystemOrCall(this InstName name) + { + return name.IsSystem() || name.IsCall(); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableA32.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableA32.cs new file mode 100644 index 00000000..2168c0b9 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableA32.cs @@ -0,0 +1,1194 @@ +using Ryujinx.Cpu.LightningJit.Table; +using System.Collections.Generic; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + static class InstTableA32<T> where T : IInstEmit + { + private static readonly InstTableLevel<InstInfoForTable> _table; + + static InstTableA32() + { + InstEncoding[] condConstraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + }; + + InstEncoding[] condRnsRnConstraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x000F0000, 0x001F0000), + new(0x000D0000, 0x000F0000), + }; + + InstEncoding[] condRnConstraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x000D0000, 0x000F0000), + }; + + InstEncoding[] vdVmConstraints = new InstEncoding[] + { + new(0x00001000, 0x00001000), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] condRnConstraints2 = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x0000000F, 0x0000000F), + }; + + InstEncoding[] optionConstraints = new InstEncoding[] + { + new(0x00000000, 0x0000000F), + }; + + InstEncoding[] condPuwPwPuwPuwConstraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x00000000, 0x01A00000), + new(0x01000000, 0x01200000), + new(0x00200000, 0x01A00000), + new(0x01A00000, 0x01A00000), + }; + + InstEncoding[] condRnPuwConstraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x000F0000, 0x000F0000), + new(0x00000000, 0x01A00000), + }; + + InstEncoding[] condPuwConstraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x00000000, 0x01A00000), + }; + + InstEncoding[] condRnPwConstraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x000F0000, 0x000F0000), + new(0x00200000, 0x01200000), + }; + + InstEncoding[] condPwConstraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x00200000, 0x01200000), + }; + + InstEncoding[] condRnConstraints3 = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x000F0000, 0x000F0000), + }; + + InstEncoding[] condMaskrConstraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x00000000, 0x004F0000), + }; + + InstEncoding[] rnConstraints = new InstEncoding[] + { + new(0x000F0000, 0x000F0000), + }; + + InstEncoding[] vdVnVmConstraints = new InstEncoding[] + { + new(0x00001000, 0x00001000), + new(0x00010000, 0x00010000), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] condRaConstraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x0000F000, 0x0000F000), + }; + + InstEncoding[] sizeQvdQvnQvmConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] sizeVdConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00001000, 0x00001000), + }; + + InstEncoding[] qvdQvnQvmConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] sizeQvdQvmConstraints = new InstEncoding[] + { + new(0x000C0000, 0x000C0000), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] sizeVnVmConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00010000, 0x00010000), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] sizeVdOpvnConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00001000, 0x00001000), + new(0x00010100, 0x00010100), + }; + + InstEncoding[] cmodeCmodeQvdConstraints = new InstEncoding[] + { + new(0x00000000, 0x00000100), + new(0x00000C00, 0x00000C00), + new(0x00001040, 0x00001040), + }; + + InstEncoding[] qvdQvnQvmOpConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + new(0x00000000, 0x00300000), + }; + + InstEncoding[] qvdQvnQvmSizeConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + new(0x00300000, 0x00300000), + }; + + InstEncoding[] qvdQvnConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + }; + + InstEncoding[] qvdQvmConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] sizeConstraints = new InstEncoding[] + { + new(0x00000000, 0x00000300), + }; + + InstEncoding[] vmConstraints = new InstEncoding[] + { + new(0x00000001, 0x00000001), + }; + + InstEncoding[] opvdOpvmConstraints = new InstEncoding[] + { + new(0x00001100, 0x00001100), + new(0x00000001, 0x00000101), + }; + + InstEncoding[] imm6Opimm6Imm6QvdQvmConstraints = new InstEncoding[] + { + new(0x00000000, 0x00380000), + new(0x00200000, 0x00300200), + new(0x00000000, 0x00200000), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] condQvdEbConstraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x00210000, 0x00210000), + new(0x00400020, 0x00400020), + }; + + InstEncoding[] imm4QvdConstraints = new InstEncoding[] + { + new(0x00000000, 0x00070000), + new(0x00001040, 0x00001040), + }; + + InstEncoding[] qvdQvnQvmQimm4Constraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + new(0x00000800, 0x00000840), + }; + + InstEncoding[] qvdConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + }; + + InstEncoding[] vdVnConstraints = new InstEncoding[] + { + new(0x00001000, 0x00001000), + new(0x00010000, 0x00010000), + }; + + InstEncoding[] sizeConstraints2 = new InstEncoding[] + { + new(0x00000C00, 0x00000C00), + }; + + InstEncoding[] sizeIndexAlignIndexAlignConstraints = new InstEncoding[] + { + new(0x00000C00, 0x00000C00), + new(0x00000010, 0x00000030), + new(0x00000020, 0x00000030), + }; + + InstEncoding[] sizeSizeaConstraints = new InstEncoding[] + { + new(0x000000C0, 0x000000C0), + new(0x00000010, 0x000000D0), + }; + + InstEncoding[] alignConstraints = new InstEncoding[] + { + new(0x00000020, 0x00000020), + }; + + InstEncoding[] alignConstraints2 = new InstEncoding[] + { + new(0x00000030, 0x00000030), + }; + + InstEncoding[] sizeConstraints3 = new InstEncoding[] + { + new(0x000000C0, 0x000000C0), + }; + + InstEncoding[] alignSizeConstraints = new InstEncoding[] + { + new(0x00000030, 0x00000030), + new(0x000000C0, 0x000000C0), + }; + + InstEncoding[] sizeAConstraints = new InstEncoding[] + { + new(0x000000C0, 0x000000C0), + new(0x00000010, 0x00000010), + }; + + InstEncoding[] sizeAlignConstraints = new InstEncoding[] + { + new(0x000000C0, 0x000000C0), + new(0x00000020, 0x00000020), + }; + + InstEncoding[] sizeIndexAlignConstraints = new InstEncoding[] + { + new(0x00000C00, 0x00000C00), + new(0x00000030, 0x00000030), + }; + + InstEncoding[] sizeaConstraints = new InstEncoding[] + { + new(0x000000C0, 0x000000D0), + }; + + InstEncoding[] sizeSizeVdConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00000000, 0x00300000), + new(0x00001000, 0x00001000), + }; + + InstEncoding[] sizeQvdQvnConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x01001000, 0x01001000), + new(0x01010000, 0x01010000), + }; + + InstEncoding[] imm3hImm3hImm3hImm3hImm3hVdConstraints = new InstEncoding[] + { + new(0x00000000, 0x00380000), + new(0x00180000, 0x00380000), + new(0x00280000, 0x00380000), + new(0x00300000, 0x00380000), + new(0x00380000, 0x00380000), + new(0x00001000, 0x00001000), + }; + + InstEncoding[] sizeVmConstraints = new InstEncoding[] + { + new(0x000C0000, 0x000C0000), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] condOpc1opc2Constraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x00000040, 0x00400060), + }; + + InstEncoding[] condUopc1opc2Uopc1opc2Constraints = new InstEncoding[] + { + new(0xF0000000, 0xF0000000), + new(0x00800000, 0x00C00060), + new(0x00000040, 0x00400060), + }; + + InstEncoding[] sizeOpuOpsizeVdConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x01000200, 0x01000200), + new(0x00100200, 0x00300200), + new(0x00001000, 0x00001000), + }; + + InstEncoding[] sizeOpsizeOpsizeQvdQvnQvmConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x01100000, 0x01300000), + new(0x01200000, 0x01300000), + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] cmodeQvdConstraints = new InstEncoding[] + { + new(0x00000E00, 0x00000E00), + new(0x00001040, 0x00001040), + }; + + InstEncoding[] qConstraints = new InstEncoding[] + { + new(0x00000040, 0x00000040), + }; + + InstEncoding[] sizeQConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00000040, 0x00000040), + }; + + InstEncoding[] sizeConstraints4 = new InstEncoding[] + { + new(0x00300000, 0x00300000), + }; + + InstEncoding[] qvdQvnQvmSizeSizeConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + new(0x00000000, 0x00300000), + new(0x00300000, 0x00300000), + }; + + InstEncoding[] sizeSizeQvdQvnConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00000000, 0x00300000), + new(0x01001000, 0x01001000), + new(0x01010000, 0x01010000), + }; + + InstEncoding[] opSizeVmConstraints = new InstEncoding[] + { + new(0x00000000, 0x000000C0), + new(0x000C0000, 0x000C0000), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] qvdQvmQvnConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + new(0x00010040, 0x00010040), + }; + + InstEncoding[] imm6UopVmConstraints = new InstEncoding[] + { + new(0x00000000, 0x00380000), + new(0x00000000, 0x01000100), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] imm6lUopQvdQvmConstraints = new InstEncoding[] + { + new(0x00000000, 0x00380080), + new(0x00000000, 0x01000100), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] qvdQvmSizeSizeConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + new(0x00000000, 0x000C0000), + new(0x000C0000, 0x000C0000), + }; + + InstEncoding[] sizeSizeSizeQvdQvmConstraints = new InstEncoding[] + { + new(0x00040000, 0x000C0000), + new(0x00080000, 0x000C0000), + new(0x000C0000, 0x000C0000), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] sizeSizeQvdQvmConstraints = new InstEncoding[] + { + new(0x00080000, 0x000C0000), + new(0x000C0000, 0x000C0000), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] imm6lQvdQvmConstraints = new InstEncoding[] + { + new(0x00000000, 0x00380080), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] imm6VmConstraints = new InstEncoding[] + { + new(0x00000000, 0x00380000), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] imm6VdImm6Imm6Imm6Constraints = new InstEncoding[] + { + new(0x00000000, 0x00380000), + new(0x00001000, 0x00001000), + new(0x00080000, 0x003F0000), + new(0x00100000, 0x003F0000), + new(0x00200000, 0x003F0000), + }; + + InstEncoding[] sizeVdConstraints2 = new InstEncoding[] + { + new(0x000C0000, 0x000C0000), + new(0x00001000, 0x00001000), + }; + + InstEncoding[] sizeQsizeQvdQvmConstraints = new InstEncoding[] + { + new(0x000C0000, 0x000C0000), + new(0x00080000, 0x000C0040), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + List<InstInfoForTable> insts = new() + { + new(0x02A00000, 0x0FE00000, condConstraints, InstName.AdcI, T.AdcIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00A00000, 0x0FE00010, condConstraints, InstName.AdcR, T.AdcRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00A00010, 0x0FE00090, condConstraints, InstName.AdcRr, T.AdcRrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x02800000, 0x0FE00000, condRnsRnConstraints, InstName.AddI, T.AddIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00800000, 0x0FE00010, condRnConstraints, InstName.AddR, T.AddRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00800010, 0x0FE00090, condConstraints, InstName.AddRr, T.AddRrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x028D0000, 0x0FEF0000, condConstraints, InstName.AddSpI, T.AddSpIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x008D0000, 0x0FEF0010, condConstraints, InstName.AddSpR, T.AddSpRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x028F0000, 0x0FFF0000, condConstraints, InstName.Adr, T.AdrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x024F0000, 0x0FFF0000, condConstraints, InstName.Adr, T.AdrA2, IsaVersion.v80, InstFlags.CondRd), + new(0xF3B00340, 0xFFBF0FD0, vdVmConstraints, InstName.Aesd, T.AesdA1, IsaVersion.v80, IsaFeature.FeatAes, InstFlags.None), + new(0xF3B00300, 0xFFBF0FD0, vdVmConstraints, InstName.Aese, T.AeseA1, IsaVersion.v80, IsaFeature.FeatAes, InstFlags.None), + new(0xF3B003C0, 0xFFBF0FD0, vdVmConstraints, InstName.Aesimc, T.AesimcA1, IsaVersion.v80, IsaFeature.FeatAes, InstFlags.None), + new(0xF3B00380, 0xFFBF0FD0, vdVmConstraints, InstName.Aesmc, T.AesmcA1, IsaVersion.v80, IsaFeature.FeatAes, InstFlags.None), + new(0x02000000, 0x0FE00000, condConstraints, InstName.AndI, T.AndIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00000000, 0x0FE00010, condConstraints, InstName.AndR, T.AndRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00000010, 0x0FE00090, condConstraints, InstName.AndRr, T.AndRrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x0A000000, 0x0F000000, condConstraints, InstName.B, T.BA1, IsaVersion.v80, InstFlags.Cond), + new(0x07C0001F, 0x0FE0007F, condConstraints, InstName.Bfc, T.BfcA1, IsaVersion.v80, InstFlags.CondRd), + new(0x07C00010, 0x0FE00070, condRnConstraints2, InstName.Bfi, T.BfiA1, IsaVersion.v80, InstFlags.CondRd), + new(0x03C00000, 0x0FE00000, condConstraints, InstName.BicI, T.BicIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x01C00000, 0x0FE00010, condConstraints, InstName.BicR, T.BicRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x01C00010, 0x0FE00090, condConstraints, InstName.BicRr, T.BicRrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x01200070, 0x0FF000F0, condConstraints, InstName.Bkpt, T.BkptA1, IsaVersion.v80, InstFlags.Cond), + new(0x012FFF30, 0x0FFFFFF0, condConstraints, InstName.BlxR, T.BlxRA1, IsaVersion.v80, InstFlags.Cond), + new(0x0B000000, 0x0F000000, condConstraints, InstName.BlI, T.BlIA1, IsaVersion.v80, InstFlags.Cond), + new(0xFA000000, 0xFE000000, InstName.BlI, T.BlIA2, IsaVersion.v80, InstFlags.None), + new(0x012FFF10, 0x0FFFFFF0, condConstraints, InstName.Bx, T.BxA1, IsaVersion.v80, InstFlags.Cond), + new(0x012FFF20, 0x0FFFFFF0, condConstraints, InstName.Bxj, T.BxjA1, IsaVersion.v80, InstFlags.Cond), + new(0x0320F016, 0x0FFFFFFF, condConstraints, InstName.Clrbhb, T.ClrbhbA1, IsaVersion.v89, IsaFeature.FeatClrbhb, InstFlags.Cond), + new(0xF57FF01F, 0xFFFFFFFF, InstName.Clrex, T.ClrexA1, IsaVersion.v80, InstFlags.None), + new(0x016F0F10, 0x0FFF0FF0, condConstraints, InstName.Clz, T.ClzA1, IsaVersion.v80, InstFlags.CondRd), + new(0x03700000, 0x0FF0F000, condConstraints, InstName.CmnI, T.CmnIA1, IsaVersion.v80, InstFlags.Cond), + new(0x01700000, 0x0FF0F010, condConstraints, InstName.CmnR, T.CmnRA1, IsaVersion.v80, InstFlags.Cond), + new(0x01700010, 0x0FF0F090, condConstraints, InstName.CmnRr, T.CmnRrA1, IsaVersion.v80, InstFlags.Cond), + new(0x03500000, 0x0FF0F000, condConstraints, InstName.CmpI, T.CmpIA1, IsaVersion.v80, InstFlags.Cond), + new(0x01500000, 0x0FF0F010, condConstraints, InstName.CmpR, T.CmpRA1, IsaVersion.v80, InstFlags.Cond), + new(0x01500010, 0x0FF0F090, condConstraints, InstName.CmpRr, T.CmpRrA1, IsaVersion.v80, InstFlags.Cond), + new(0xF1000000, 0xFFF1FE20, InstName.Cps, T.CpsA1, IsaVersion.v80, InstFlags.None), + new(0x01000040, 0x0F900FF0, condConstraints, InstName.Crc32, T.Crc32A1, IsaVersion.v80, IsaFeature.FeatCrc32, InstFlags.CondRd), + new(0x01000240, 0x0F900FF0, condConstraints, InstName.Crc32c, T.Crc32cA1, IsaVersion.v80, IsaFeature.FeatCrc32, InstFlags.CondRd), + new(0x0320F014, 0x0FFFFFFF, condConstraints, InstName.Csdb, T.CsdbA1, IsaVersion.v80, InstFlags.Cond), + new(0x0320F0F0, 0x0FFFFFF0, condConstraints, InstName.Dbg, T.DbgA1, IsaVersion.v80, InstFlags.Cond), + new(0xF57FF050, 0xFFFFFFF0, InstName.Dmb, T.DmbA1, IsaVersion.v80, InstFlags.None), + new(0xF57FF040, 0xFFFFFFF0, optionConstraints, InstName.Dsb, T.DsbA1, IsaVersion.v80, InstFlags.None), + new(0x02200000, 0x0FE00000, condConstraints, InstName.EorI, T.EorIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00200000, 0x0FE00010, condConstraints, InstName.EorR, T.EorRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00200010, 0x0FE00090, condConstraints, InstName.EorRr, T.EorRrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x0160006E, 0x0FFFFFFF, condConstraints, InstName.Eret, T.EretA1, IsaVersion.v80, InstFlags.Cond), + new(0x0320F010, 0x0FFFFFFF, condConstraints, InstName.Esb, T.EsbA1, IsaVersion.v82, IsaFeature.FeatRas, InstFlags.Cond), + new(0x0C100B01, 0x0E100F01, condPuwPwPuwPuwConstraints, InstName.Fldmx, T.FldmxA1, IsaVersion.v80, InstFlags.CondWBack), + new(0x0C000B01, 0x0E100F01, condPuwPwPuwPuwConstraints, InstName.Fstmx, T.FstmxA1, IsaVersion.v80, InstFlags.CondWBack), + new(0x01000070, 0x0FF000F0, condConstraints, InstName.Hlt, T.HltA1, IsaVersion.v80, InstFlags.Cond), + new(0x01400070, 0x0FF000F0, condConstraints, InstName.Hvc, T.HvcA1, IsaVersion.v80, InstFlags.Cond), + new(0xF57FF060, 0xFFFFFFF0, InstName.Isb, T.IsbA1, IsaVersion.v80, InstFlags.None), + new(0x01900C9F, 0x0FF00FFF, condConstraints, InstName.Lda, T.LdaA1, IsaVersion.v80, InstFlags.CondRt), + new(0x01D00C9F, 0x0FF00FFF, condConstraints, InstName.Ldab, T.LdabA1, IsaVersion.v80, InstFlags.CondRt), + new(0x01900E9F, 0x0FF00FFF, condConstraints, InstName.Ldaex, T.LdaexA1, IsaVersion.v80, InstFlags.CondRt), + new(0x01D00E9F, 0x0FF00FFF, condConstraints, InstName.Ldaexb, T.LdaexbA1, IsaVersion.v80, InstFlags.CondRt), + new(0x01B00E9F, 0x0FF00FFF, condConstraints, InstName.Ldaexd, T.LdaexdA1, IsaVersion.v80, InstFlags.CondRt2), + new(0x01F00E9F, 0x0FF00FFF, condConstraints, InstName.Ldaexh, T.LdaexhA1, IsaVersion.v80, InstFlags.CondRt), + new(0x01F00C9F, 0x0FF00FFF, condConstraints, InstName.Ldah, T.LdahA1, IsaVersion.v80, InstFlags.CondRt), + new(0x0C105E00, 0x0E50FF00, condRnPuwConstraints, InstName.LdcI, T.LdcIA1, IsaVersion.v80, InstFlags.CondWBack), + new(0x0C1F5E00, 0x0E5FFF00, condPuwConstraints, InstName.LdcL, T.LdcLA1, IsaVersion.v80, InstFlags.CondWBack), + new(0x08900000, 0x0FD00000, condConstraints, InstName.Ldm, T.LdmA1, IsaVersion.v80, InstFlags.CondRlistWBack), + new(0x08100000, 0x0FD00000, condConstraints, InstName.Ldmda, T.LdmdaA1, IsaVersion.v80, InstFlags.CondRlistWBack), + new(0x09100000, 0x0FD00000, condConstraints, InstName.Ldmdb, T.LdmdbA1, IsaVersion.v80, InstFlags.CondRlistWBack), + new(0x09900000, 0x0FD00000, condConstraints, InstName.Ldmib, T.LdmibA1, IsaVersion.v80, InstFlags.CondRlistWBack), + new(0x08508000, 0x0E508000, condConstraints, InstName.LdmE, T.LdmEA1, IsaVersion.v80, InstFlags.CondRlistWBack), + new(0x08500000, 0x0E708000, condConstraints, InstName.LdmU, T.LdmUA1, IsaVersion.v80, InstFlags.CondRlist), + new(0x04700000, 0x0F700000, condConstraints, InstName.Ldrbt, T.LdrbtA1, IsaVersion.v80, InstFlags.CondRt), + new(0x06700000, 0x0F700010, condConstraints, InstName.Ldrbt, T.LdrbtA2, IsaVersion.v80, InstFlags.CondRt), + new(0x04500000, 0x0E500000, condRnPwConstraints, InstName.LdrbI, T.LdrbIA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x045F0000, 0x0E5F0000, condPwConstraints, InstName.LdrbL, T.LdrbLA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x06500000, 0x0E500010, condPwConstraints, InstName.LdrbR, T.LdrbRA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x004000D0, 0x0E5000F0, condRnConstraints3, InstName.LdrdI, T.LdrdIA1, IsaVersion.v80, InstFlags.CondRt2WBack), + new(0x014F00D0, 0x0F7F00F0, condConstraints, InstName.LdrdL, T.LdrdLA1, IsaVersion.v80, InstFlags.CondRt2), + new(0x000000D0, 0x0E500FF0, condConstraints, InstName.LdrdR, T.LdrdRA1, IsaVersion.v80, InstFlags.CondRt2WBack), + new(0x01900F9F, 0x0FF00FFF, condConstraints, InstName.Ldrex, T.LdrexA1, IsaVersion.v80, InstFlags.CondRt), + new(0x01D00F9F, 0x0FF00FFF, condConstraints, InstName.Ldrexb, T.LdrexbA1, IsaVersion.v80, InstFlags.CondRt), + new(0x01B00F9F, 0x0FF00FFF, condConstraints, InstName.Ldrexd, T.LdrexdA1, IsaVersion.v80, InstFlags.CondRt2), + new(0x01F00F9F, 0x0FF00FFF, condConstraints, InstName.Ldrexh, T.LdrexhA1, IsaVersion.v80, InstFlags.CondRt), + new(0x007000B0, 0x0F7000F0, condConstraints, InstName.Ldrht, T.LdrhtA1, IsaVersion.v80, InstFlags.CondRt), + new(0x003000B0, 0x0F700FF0, condConstraints, InstName.Ldrht, T.LdrhtA2, IsaVersion.v80, InstFlags.CondRt), + new(0x005000B0, 0x0E5000F0, condRnPwConstraints, InstName.LdrhI, T.LdrhIA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x005F00B0, 0x0E5F00F0, condPwConstraints, InstName.LdrhL, T.LdrhLA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x001000B0, 0x0E500FF0, condPwConstraints, InstName.LdrhR, T.LdrhRA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x007000D0, 0x0F7000F0, condConstraints, InstName.Ldrsbt, T.LdrsbtA1, IsaVersion.v80, InstFlags.CondRt), + new(0x003000D0, 0x0F700FF0, condConstraints, InstName.Ldrsbt, T.LdrsbtA2, IsaVersion.v80, InstFlags.CondRt), + new(0x005000D0, 0x0E5000F0, condRnPwConstraints, InstName.LdrsbI, T.LdrsbIA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x005F00D0, 0x0E5F00F0, condPwConstraints, InstName.LdrsbL, T.LdrsbLA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x001000D0, 0x0E500FF0, condPwConstraints, InstName.LdrsbR, T.LdrsbRA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x007000F0, 0x0F7000F0, condConstraints, InstName.Ldrsht, T.LdrshtA1, IsaVersion.v80, InstFlags.CondRt), + new(0x003000F0, 0x0F700FF0, condConstraints, InstName.Ldrsht, T.LdrshtA2, IsaVersion.v80, InstFlags.CondRt), + new(0x005000F0, 0x0E5000F0, condRnPwConstraints, InstName.LdrshI, T.LdrshIA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x005F00F0, 0x0E5F00F0, condPwConstraints, InstName.LdrshL, T.LdrshLA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x001000F0, 0x0E500FF0, condPwConstraints, InstName.LdrshR, T.LdrshRA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x04300000, 0x0F700000, condConstraints, InstName.Ldrt, T.LdrtA1, IsaVersion.v80, InstFlags.CondRt), + new(0x06300000, 0x0F700010, condConstraints, InstName.Ldrt, T.LdrtA2, IsaVersion.v80, InstFlags.CondRt), + new(0x04100000, 0x0E500000, condRnPwConstraints, InstName.LdrI, T.LdrIA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x041F0000, 0x0E5F0000, condPwConstraints, InstName.LdrL, T.LdrLA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x06100000, 0x0E500010, condPwConstraints, InstName.LdrR, T.LdrRA1, IsaVersion.v80, InstFlags.CondRtWBack), + new(0x0E000E10, 0x0F100E10, condConstraints, InstName.Mcr, T.McrA1, IsaVersion.v80, InstFlags.CondRt), + new(0x0C400E00, 0x0FF00E00, condConstraints, InstName.Mcrr, T.McrrA1, IsaVersion.v80, InstFlags.CondRt), + new(0x00200090, 0x0FE000F0, condConstraints, InstName.Mla, T.MlaA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x00600090, 0x0FF000F0, condConstraints, InstName.Mls, T.MlsA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x03400000, 0x0FF00000, condConstraints, InstName.Movt, T.MovtA1, IsaVersion.v80, InstFlags.CondRd), + new(0x03A00000, 0x0FEF0000, condConstraints, InstName.MovI, T.MovIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x03000000, 0x0FF00000, condConstraints, InstName.MovI, T.MovIA2, IsaVersion.v80, InstFlags.CondRd), + new(0x01A00000, 0x0FEF0010, condConstraints, InstName.MovR, T.MovRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x01A00010, 0x0FEF0090, condConstraints, InstName.MovRr, T.MovRrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x0E100E10, 0x0F100E10, condConstraints, InstName.Mrc, T.MrcA1, IsaVersion.v80, InstFlags.CondRt), + new(0x0C500E00, 0x0FF00E00, condConstraints, InstName.Mrrc, T.MrrcA1, IsaVersion.v80, InstFlags.CondRt), + new(0x010F0000, 0x0FBF0FFF, condConstraints, InstName.Mrs, T.MrsA1, IsaVersion.v80, InstFlags.CondRd), + new(0x01000200, 0x0FB00EFF, condConstraints, InstName.MrsBr, T.MrsBrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x0120F200, 0x0FB0FEF0, condConstraints, InstName.MsrBr, T.MsrBrA1, IsaVersion.v80, InstFlags.Cond), + new(0x0320F000, 0x0FB0F000, condMaskrConstraints, InstName.MsrI, T.MsrIA1, IsaVersion.v80, InstFlags.Cond), + new(0x0120F000, 0x0FB0FFF0, condConstraints, InstName.MsrR, T.MsrRA1, IsaVersion.v80, InstFlags.Cond), + new(0x00000090, 0x0FE0F0F0, condConstraints, InstName.Mul, T.MulA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x03E00000, 0x0FEF0000, condConstraints, InstName.MvnI, T.MvnIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x01E00000, 0x0FEF0010, condConstraints, InstName.MvnR, T.MvnRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x01E00010, 0x0FEF0090, condConstraints, InstName.MvnRr, T.MvnRrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x0320F000, 0x0FFFFFFF, condConstraints, InstName.Nop, T.NopA1, IsaVersion.v80, InstFlags.Cond), + new(0x03800000, 0x0FE00000, condConstraints, InstName.OrrI, T.OrrIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x01800000, 0x0FE00010, condConstraints, InstName.OrrR, T.OrrRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x01800010, 0x0FE00090, condConstraints, InstName.OrrRr, T.OrrRrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06800010, 0x0FF00030, condConstraints, InstName.Pkh, T.PkhA1, IsaVersion.v80, InstFlags.CondRd), + new(0xF510F000, 0xFF30F000, rnConstraints, InstName.PldI, T.PldIA1, IsaVersion.v80, InstFlags.None), + new(0xF55FF000, 0xFF7FF000, InstName.PldL, T.PldLA1, IsaVersion.v80, InstFlags.None), + new(0xF710F000, 0xFF30F010, InstName.PldR, T.PldRA1, IsaVersion.v80, InstFlags.None), + new(0xF450F000, 0xFF70F000, InstName.PliI, T.PliIA1, IsaVersion.v80, InstFlags.None), + new(0xF650F000, 0xFF70F010, InstName.PliR, T.PliRA1, IsaVersion.v80, InstFlags.None), + new(0xF57FF044, 0xFFFFFFFF, InstName.Pssbb, T.PssbbA1, IsaVersion.v80, InstFlags.None), + new(0x01000050, 0x0FF00FF0, condConstraints, InstName.Qadd, T.QaddA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06200F10, 0x0FF00FF0, condConstraints, InstName.Qadd16, T.Qadd16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06200F90, 0x0FF00FF0, condConstraints, InstName.Qadd8, T.Qadd8A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06200F30, 0x0FF00FF0, condConstraints, InstName.Qasx, T.QasxA1, IsaVersion.v80, InstFlags.CondRd), + new(0x01400050, 0x0FF00FF0, condConstraints, InstName.Qdadd, T.QdaddA1, IsaVersion.v80, InstFlags.CondRd), + new(0x01600050, 0x0FF00FF0, condConstraints, InstName.Qdsub, T.QdsubA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06200F50, 0x0FF00FF0, condConstraints, InstName.Qsax, T.QsaxA1, IsaVersion.v80, InstFlags.CondRd), + new(0x01200050, 0x0FF00FF0, condConstraints, InstName.Qsub, T.QsubA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06200F70, 0x0FF00FF0, condConstraints, InstName.Qsub16, T.Qsub16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06200FF0, 0x0FF00FF0, condConstraints, InstName.Qsub8, T.Qsub8A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06FF0F30, 0x0FFF0FF0, condConstraints, InstName.Rbit, T.RbitA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06BF0F30, 0x0FFF0FF0, condConstraints, InstName.Rev, T.RevA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06BF0FB0, 0x0FFF0FF0, condConstraints, InstName.Rev16, T.Rev16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06FF0FB0, 0x0FFF0FF0, condConstraints, InstName.Revsh, T.RevshA1, IsaVersion.v80, InstFlags.CondRd), + new(0xF8100A00, 0xFE50FFFF, InstName.Rfe, T.RfeA1, IsaVersion.v80, InstFlags.WBack), + new(0x02600000, 0x0FE00000, condConstraints, InstName.RsbI, T.RsbIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00600000, 0x0FE00010, condConstraints, InstName.RsbR, T.RsbRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00600010, 0x0FE00090, condConstraints, InstName.RsbRr, T.RsbRrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x02E00000, 0x0FE00000, condConstraints, InstName.RscI, T.RscIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00E00000, 0x0FE00010, condConstraints, InstName.RscR, T.RscRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00E00010, 0x0FE00090, condConstraints, InstName.RscRr, T.RscRrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06100F10, 0x0FF00FF0, condConstraints, InstName.Sadd16, T.Sadd16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06100F90, 0x0FF00FF0, condConstraints, InstName.Sadd8, T.Sadd8A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06100F30, 0x0FF00FF0, condConstraints, InstName.Sasx, T.SasxA1, IsaVersion.v80, InstFlags.CondRd), + new(0xF57FF070, 0xFFFFFFFF, InstName.Sb, T.SbA1, IsaVersion.v85, IsaFeature.FeatSb, InstFlags.None), + new(0x02C00000, 0x0FE00000, condConstraints, InstName.SbcI, T.SbcIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00C00000, 0x0FE00010, condConstraints, InstName.SbcR, T.SbcRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00C00010, 0x0FE00090, condConstraints, InstName.SbcRr, T.SbcRrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x07A00050, 0x0FE00070, condConstraints, InstName.Sbfx, T.SbfxA1, IsaVersion.v80, InstFlags.CondRd), + new(0x0710F010, 0x0FF0F0F0, condConstraints, InstName.Sdiv, T.SdivA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x06800FB0, 0x0FF00FF0, condConstraints, InstName.Sel, T.SelA1, IsaVersion.v80, InstFlags.CondRd), + new(0xF1010000, 0xFFFFFDFF, InstName.Setend, T.SetendA1, IsaVersion.v80, InstFlags.None), + new(0xF1100000, 0xFFFFFDFF, InstName.Setpan, T.SetpanA1, IsaVersion.v81, IsaFeature.FeatPan, InstFlags.None), + new(0x0320F004, 0x0FFFFFFF, condConstraints, InstName.Sev, T.SevA1, IsaVersion.v80, InstFlags.Cond), + new(0x0320F005, 0x0FFFFFFF, condConstraints, InstName.Sevl, T.SevlA1, IsaVersion.v80, InstFlags.Cond), + new(0xF2000C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha1c, T.Sha1cA1, IsaVersion.v80, IsaFeature.FeatSha1, InstFlags.None), + new(0xF3B902C0, 0xFFBF0FD0, vdVmConstraints, InstName.Sha1h, T.Sha1hA1, IsaVersion.v80, IsaFeature.FeatSha1, InstFlags.None), + new(0xF2200C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha1m, T.Sha1mA1, IsaVersion.v80, IsaFeature.FeatSha1, InstFlags.None), + new(0xF2100C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha1p, T.Sha1pA1, IsaVersion.v80, IsaFeature.FeatSha1, InstFlags.None), + new(0xF2300C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha1su0, T.Sha1su0A1, IsaVersion.v80, IsaFeature.FeatSha1, InstFlags.None), + new(0xF3BA0380, 0xFFBF0FD0, vdVmConstraints, InstName.Sha1su1, T.Sha1su1A1, IsaVersion.v80, IsaFeature.FeatSha1, InstFlags.None), + new(0xF3000C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha256h, T.Sha256hA1, IsaVersion.v80, IsaFeature.FeatSha256, InstFlags.None), + new(0xF3100C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha256h2, T.Sha256h2A1, IsaVersion.v80, IsaFeature.FeatSha256, InstFlags.None), + new(0xF3BA03C0, 0xFFBF0FD0, vdVmConstraints, InstName.Sha256su0, T.Sha256su0A1, IsaVersion.v80, IsaFeature.FeatSha256, InstFlags.None), + new(0xF3200C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha256su1, T.Sha256su1A1, IsaVersion.v80, IsaFeature.FeatSha256, InstFlags.None), + new(0x06300F10, 0x0FF00FF0, condConstraints, InstName.Shadd16, T.Shadd16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06300F90, 0x0FF00FF0, condConstraints, InstName.Shadd8, T.Shadd8A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06300F30, 0x0FF00FF0, condConstraints, InstName.Shasx, T.ShasxA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06300F50, 0x0FF00FF0, condConstraints, InstName.Shsax, T.ShsaxA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06300F70, 0x0FF00FF0, condConstraints, InstName.Shsub16, T.Shsub16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06300FF0, 0x0FF00FF0, condConstraints, InstName.Shsub8, T.Shsub8A1, IsaVersion.v80, InstFlags.CondRd), + new(0x01600070, 0x0FFFFFF0, condConstraints, InstName.Smc, T.SmcA1, IsaVersion.v80, InstFlags.Cond), + new(0x01000080, 0x0FF00090, condConstraints, InstName.Smlabb, T.SmlabbA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x07000010, 0x0FF000D0, condRaConstraints, InstName.Smlad, T.SmladA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x00E00090, 0x0FE000F0, condConstraints, InstName.Smlal, T.SmlalA1, IsaVersion.v80, InstFlags.CondRdLoHi), + new(0x01400080, 0x0FF00090, condConstraints, InstName.Smlalbb, T.SmlalbbA1, IsaVersion.v80, InstFlags.CondRdLoHi), + new(0x07400010, 0x0FF000D0, condConstraints, InstName.Smlald, T.SmlaldA1, IsaVersion.v80, InstFlags.CondRdLoHi), + new(0x01200080, 0x0FF000B0, condConstraints, InstName.Smlawb, T.SmlawbA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x07000050, 0x0FF000D0, condRaConstraints, InstName.Smlsd, T.SmlsdA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x07400050, 0x0FF000D0, condConstraints, InstName.Smlsld, T.SmlsldA1, IsaVersion.v80, InstFlags.CondRdLoHi), + new(0x07500010, 0x0FF000D0, condRaConstraints, InstName.Smmla, T.SmmlaA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x075000D0, 0x0FF000D0, condConstraints, InstName.Smmls, T.SmmlsA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x0750F010, 0x0FF0F0D0, condConstraints, InstName.Smmul, T.SmmulA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x0700F010, 0x0FF0F0D0, condConstraints, InstName.Smuad, T.SmuadA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x01600080, 0x0FF0F090, condConstraints, InstName.Smulbb, T.SmulbbA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x00C00090, 0x0FE000F0, condConstraints, InstName.Smull, T.SmullA1, IsaVersion.v80, InstFlags.CondRdLoHi), + new(0x012000A0, 0x0FF0F0B0, condConstraints, InstName.Smulwb, T.SmulwbA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x0700F050, 0x0FF0F0D0, condConstraints, InstName.Smusd, T.SmusdA1, IsaVersion.v80, InstFlags.CondRd16), + new(0xF84D0500, 0xFE5FFFE0, InstName.Srs, T.SrsA1, IsaVersion.v80, InstFlags.WBack), + new(0x06A00010, 0x0FE00030, condConstraints, InstName.Ssat, T.SsatA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06A00F30, 0x0FF00FF0, condConstraints, InstName.Ssat16, T.Ssat16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06100F50, 0x0FF00FF0, condConstraints, InstName.Ssax, T.SsaxA1, IsaVersion.v80, InstFlags.CondRd), + new(0xF57FF040, 0xFFFFFFFF, InstName.Ssbb, T.SsbbA1, IsaVersion.v80, InstFlags.None), + new(0x06100F70, 0x0FF00FF0, condConstraints, InstName.Ssub16, T.Ssub16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06100FF0, 0x0FF00FF0, condConstraints, InstName.Ssub8, T.Ssub8A1, IsaVersion.v80, InstFlags.CondRd), + new(0x0C005E00, 0x0E50FF00, condPuwConstraints, InstName.Stc, T.StcA1, IsaVersion.v80, InstFlags.CondWBack), + new(0x0180FC90, 0x0FF0FFF0, condConstraints, InstName.Stl, T.StlA1, IsaVersion.v80, InstFlags.CondRtRead), + new(0x01C0FC90, 0x0FF0FFF0, condConstraints, InstName.Stlb, T.StlbA1, IsaVersion.v80, InstFlags.CondRtRead), + new(0x01800E90, 0x0FF00FF0, condConstraints, InstName.Stlex, T.StlexA1, IsaVersion.v80, InstFlags.CondRdRtRead), + new(0x01C00E90, 0x0FF00FF0, condConstraints, InstName.Stlexb, T.StlexbA1, IsaVersion.v80, InstFlags.CondRdRtRead), + new(0x01A00E90, 0x0FF00FF0, condConstraints, InstName.Stlexd, T.StlexdA1, IsaVersion.v80, InstFlags.CondRdRt2Read), + new(0x01E00E90, 0x0FF00FF0, condConstraints, InstName.Stlexh, T.StlexhA1, IsaVersion.v80, InstFlags.CondRdRtRead), + new(0x01E0FC90, 0x0FF0FFF0, condConstraints, InstName.Stlh, T.StlhA1, IsaVersion.v80, InstFlags.CondRtRead), + new(0x08800000, 0x0FD00000, condConstraints, InstName.Stm, T.StmA1, IsaVersion.v80, InstFlags.CondRlistReadWBack), + new(0x08000000, 0x0FD00000, condConstraints, InstName.Stmda, T.StmdaA1, IsaVersion.v80, InstFlags.CondRlistReadWBack), + new(0x09000000, 0x0FD00000, condConstraints, InstName.Stmdb, T.StmdbA1, IsaVersion.v80, InstFlags.CondRlistReadWBack), + new(0x09800000, 0x0FD00000, condConstraints, InstName.Stmib, T.StmibA1, IsaVersion.v80, InstFlags.CondRlistReadWBack), + new(0x08400000, 0x0E700000, condConstraints, InstName.StmU, T.StmUA1, IsaVersion.v80, InstFlags.CondRlistRead), + new(0x04600000, 0x0F700000, condConstraints, InstName.Strbt, T.StrbtA1, IsaVersion.v80, InstFlags.CondRtRead), + new(0x06600000, 0x0F700010, condConstraints, InstName.Strbt, T.StrbtA2, IsaVersion.v80, InstFlags.CondRtRead), + new(0x04400000, 0x0E500000, condPwConstraints, InstName.StrbI, T.StrbIA1, IsaVersion.v80, InstFlags.CondRtReadWBack), + new(0x06400000, 0x0E500010, condPwConstraints, InstName.StrbR, T.StrbRA1, IsaVersion.v80, InstFlags.CondRtReadWBack), + new(0x004000F0, 0x0E5000F0, condConstraints, InstName.StrdI, T.StrdIA1, IsaVersion.v80, InstFlags.CondRt2ReadWBack), + new(0x000000F0, 0x0E500FF0, condConstraints, InstName.StrdR, T.StrdRA1, IsaVersion.v80, InstFlags.CondRt2ReadWBack), + new(0x01800F90, 0x0FF00FF0, condConstraints, InstName.Strex, T.StrexA1, IsaVersion.v80, InstFlags.CondRdRtRead), + new(0x01C00F90, 0x0FF00FF0, condConstraints, InstName.Strexb, T.StrexbA1, IsaVersion.v80, InstFlags.CondRdRtRead), + new(0x01A00F90, 0x0FF00FF0, condConstraints, InstName.Strexd, T.StrexdA1, IsaVersion.v80, InstFlags.CondRdRt2Read), + new(0x01E00F90, 0x0FF00FF0, condConstraints, InstName.Strexh, T.StrexhA1, IsaVersion.v80, InstFlags.CondRdRtRead), + new(0x006000B0, 0x0F7000F0, condConstraints, InstName.Strht, T.StrhtA1, IsaVersion.v80, InstFlags.CondRtRead), + new(0x002000B0, 0x0F700FF0, condConstraints, InstName.Strht, T.StrhtA2, IsaVersion.v80, InstFlags.CondRtRead), + new(0x004000B0, 0x0E5000F0, condPwConstraints, InstName.StrhI, T.StrhIA1, IsaVersion.v80, InstFlags.CondRtReadWBack), + new(0x000000B0, 0x0E500FF0, condPwConstraints, InstName.StrhR, T.StrhRA1, IsaVersion.v80, InstFlags.CondRtReadWBack), + new(0x04200000, 0x0F700000, condConstraints, InstName.Strt, T.StrtA1, IsaVersion.v80, InstFlags.CondRtRead), + new(0x06200000, 0x0F700010, condConstraints, InstName.Strt, T.StrtA2, IsaVersion.v80, InstFlags.CondRtRead), + new(0x04000000, 0x0E500000, condPwConstraints, InstName.StrI, T.StrIA1, IsaVersion.v80, InstFlags.CondRtReadWBack), + new(0x06000000, 0x0E500010, condPwConstraints, InstName.StrR, T.StrRA1, IsaVersion.v80, InstFlags.CondRtReadWBack), + new(0x02400000, 0x0FE00000, condRnsRnConstraints, InstName.SubI, T.SubIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00400000, 0x0FE00010, condRnConstraints, InstName.SubR, T.SubRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x00400010, 0x0FE00090, condConstraints, InstName.SubRr, T.SubRrA1, IsaVersion.v80, InstFlags.CondRd), + new(0x024D0000, 0x0FEF0000, condConstraints, InstName.SubSpI, T.SubSpIA1, IsaVersion.v80, InstFlags.CondRd), + new(0x004D0000, 0x0FEF0010, condConstraints, InstName.SubSpR, T.SubSpRA1, IsaVersion.v80, InstFlags.CondRd), + new(0x0F000000, 0x0F000000, condConstraints, InstName.Svc, T.SvcA1, IsaVersion.v80, InstFlags.Cond), + new(0x06A00070, 0x0FF003F0, condRnConstraints3, InstName.Sxtab, T.SxtabA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06800070, 0x0FF003F0, condRnConstraints3, InstName.Sxtab16, T.Sxtab16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06B00070, 0x0FF003F0, condRnConstraints3, InstName.Sxtah, T.SxtahA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06AF0070, 0x0FFF03F0, condConstraints, InstName.Sxtb, T.SxtbA1, IsaVersion.v80, InstFlags.CondRd), + new(0x068F0070, 0x0FFF03F0, condConstraints, InstName.Sxtb16, T.Sxtb16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06BF0070, 0x0FFF03F0, condConstraints, InstName.Sxth, T.SxthA1, IsaVersion.v80, InstFlags.CondRd), + new(0x03300000, 0x0FF0F000, condConstraints, InstName.TeqI, T.TeqIA1, IsaVersion.v80, InstFlags.Cond), + new(0x01300000, 0x0FF0F010, condConstraints, InstName.TeqR, T.TeqRA1, IsaVersion.v80, InstFlags.Cond), + new(0x01300010, 0x0FF0F090, condConstraints, InstName.TeqRr, T.TeqRrA1, IsaVersion.v80, InstFlags.Cond), + new(0x0320F012, 0x0FFFFFFF, condConstraints, InstName.Tsb, T.TsbA1, IsaVersion.v84, IsaFeature.FeatTrf, InstFlags.Cond), + new(0x03100000, 0x0FF0F000, condConstraints, InstName.TstI, T.TstIA1, IsaVersion.v80, InstFlags.Cond), + new(0x01100000, 0x0FF0F010, condConstraints, InstName.TstR, T.TstRA1, IsaVersion.v80, InstFlags.Cond), + new(0x01100010, 0x0FF0F090, condConstraints, InstName.TstRr, T.TstRrA1, IsaVersion.v80, InstFlags.Cond), + new(0x06500F10, 0x0FF00FF0, condConstraints, InstName.Uadd16, T.Uadd16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06500F90, 0x0FF00FF0, condConstraints, InstName.Uadd8, T.Uadd8A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06500F30, 0x0FF00FF0, condConstraints, InstName.Uasx, T.UasxA1, IsaVersion.v80, InstFlags.CondRd), + new(0x07E00050, 0x0FE00070, condConstraints, InstName.Ubfx, T.UbfxA1, IsaVersion.v80, InstFlags.CondRd), + new(0xE7F000F0, 0xFFF000F0, InstName.Udf, T.UdfA1, IsaVersion.v80, InstFlags.None), + new(0x0730F010, 0x0FF0F0F0, condConstraints, InstName.Udiv, T.UdivA1, IsaVersion.v80, InstFlags.CondRd16), + new(0x06700F10, 0x0FF00FF0, condConstraints, InstName.Uhadd16, T.Uhadd16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06700F90, 0x0FF00FF0, condConstraints, InstName.Uhadd8, T.Uhadd8A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06700F30, 0x0FF00FF0, condConstraints, InstName.Uhasx, T.UhasxA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06700F50, 0x0FF00FF0, condConstraints, InstName.Uhsax, T.UhsaxA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06700F70, 0x0FF00FF0, condConstraints, InstName.Uhsub16, T.Uhsub16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06700FF0, 0x0FF00FF0, condConstraints, InstName.Uhsub8, T.Uhsub8A1, IsaVersion.v80, InstFlags.CondRd), + new(0x00400090, 0x0FF000F0, condConstraints, InstName.Umaal, T.UmaalA1, IsaVersion.v80, InstFlags.CondRdLoHi), + new(0x00A00090, 0x0FE000F0, condConstraints, InstName.Umlal, T.UmlalA1, IsaVersion.v80, InstFlags.CondRdLoHi), + new(0x00800090, 0x0FE000F0, condConstraints, InstName.Umull, T.UmullA1, IsaVersion.v80, InstFlags.CondRdLoHi), + new(0x06600F10, 0x0FF00FF0, condConstraints, InstName.Uqadd16, T.Uqadd16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06600F90, 0x0FF00FF0, condConstraints, InstName.Uqadd8, T.Uqadd8A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06600F30, 0x0FF00FF0, condConstraints, InstName.Uqasx, T.UqasxA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06600F50, 0x0FF00FF0, condConstraints, InstName.Uqsax, T.UqsaxA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06600F70, 0x0FF00FF0, condConstraints, InstName.Uqsub16, T.Uqsub16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06600FF0, 0x0FF00FF0, condConstraints, InstName.Uqsub8, T.Uqsub8A1, IsaVersion.v80, InstFlags.CondRd), + new(0x0780F010, 0x0FF0F0F0, condConstraints, InstName.Usad8, T.Usad8A1, IsaVersion.v80, InstFlags.CondRd16), + new(0x07800010, 0x0FF000F0, condRaConstraints, InstName.Usada8, T.Usada8A1, IsaVersion.v80, InstFlags.CondRd16), + new(0x06E00010, 0x0FE00030, condConstraints, InstName.Usat, T.UsatA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06E00F30, 0x0FF00FF0, condConstraints, InstName.Usat16, T.Usat16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06500F50, 0x0FF00FF0, condConstraints, InstName.Usax, T.UsaxA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06500F70, 0x0FF00FF0, condConstraints, InstName.Usub16, T.Usub16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06500FF0, 0x0FF00FF0, condConstraints, InstName.Usub8, T.Usub8A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06E00070, 0x0FF003F0, condRnConstraints3, InstName.Uxtab, T.UxtabA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06C00070, 0x0FF003F0, condRnConstraints3, InstName.Uxtab16, T.Uxtab16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06F00070, 0x0FF003F0, condRnConstraints3, InstName.Uxtah, T.UxtahA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06EF0070, 0x0FFF03F0, condConstraints, InstName.Uxtb, T.UxtbA1, IsaVersion.v80, InstFlags.CondRd), + new(0x06CF0070, 0x0FFF03F0, condConstraints, InstName.Uxtb16, T.Uxtb16A1, IsaVersion.v80, InstFlags.CondRd), + new(0x06FF0070, 0x0FFF03F0, condConstraints, InstName.Uxth, T.UxthA1, IsaVersion.v80, InstFlags.CondRd), + new(0xF2000710, 0xFE800F10, sizeQvdQvnQvmConstraints, InstName.Vaba, T.VabaA1, IsaVersion.v80, InstFlags.None), + new(0xF2800500, 0xFE800F50, sizeVdConstraints, InstName.Vabal, T.VabalA1, IsaVersion.v80, InstFlags.None), + new(0xF2800700, 0xFE800F50, sizeVdConstraints, InstName.VabdlI, T.VabdlIA1, IsaVersion.v80, InstFlags.None), + new(0xF3200D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VabdF, T.VabdFA1, IsaVersion.v80, InstFlags.None), + new(0xF3300D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VabdF, T.VabdFA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2000700, 0xFE800F10, sizeQvdQvnQvmConstraints, InstName.VabdI, T.VabdIA1, IsaVersion.v80, InstFlags.None), + new(0xF3B10300, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vabs, T.VabsA1, IsaVersion.v80, InstFlags.None), + new(0xF3B90700, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.Vabs, T.VabsA1, IsaVersion.v80, InstFlags.None), + new(0xF3B50700, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.Vabs, T.VabsA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0EB00AC0, 0x0FBF0ED0, condConstraints, InstName.Vabs, T.VabsA2, IsaVersion.v80, InstFlags.Cond), + new(0x0EB009C0, 0x0FBF0FD0, condConstraints, InstName.Vabs, T.VabsA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF3000E10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vacge, T.VacgeA1, IsaVersion.v80, InstFlags.None), + new(0xF3100E10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vacge, T.VacgeA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3200E10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vacgt, T.VacgtA1, IsaVersion.v80, InstFlags.None), + new(0xF3300E10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vacgt, T.VacgtA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2800400, 0xFF800F50, sizeVnVmConstraints, InstName.Vaddhn, T.VaddhnA1, IsaVersion.v80, InstFlags.None), + new(0xF2800000, 0xFE800F50, sizeVdOpvnConstraints, InstName.Vaddl, T.VaddlA1, IsaVersion.v80, InstFlags.None), + new(0xF2800100, 0xFE800F50, sizeVdOpvnConstraints, InstName.Vaddw, T.VaddwA1, IsaVersion.v80, InstFlags.None), + new(0xF2000D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VaddF, T.VaddFA1, IsaVersion.v80, InstFlags.None), + new(0xF2100D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VaddF, T.VaddFA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0E300A00, 0x0FB00E50, condConstraints, InstName.VaddF, T.VaddFA2, IsaVersion.v80, InstFlags.Cond), + new(0x0E300900, 0x0FB00F50, condConstraints, InstName.VaddF, T.VaddFA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF2000800, 0xFF800F10, qvdQvnQvmConstraints, InstName.VaddI, T.VaddIA1, IsaVersion.v80, InstFlags.None), + new(0xF2000110, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VandR, T.VandRA1, IsaVersion.v80, InstFlags.None), + new(0xF2800130, 0xFEB809B0, cmodeCmodeQvdConstraints, InstName.VbicI, T.VbicIA1, IsaVersion.v80, InstFlags.None), + new(0xF2800930, 0xFEB80DB0, cmodeCmodeQvdConstraints, InstName.VbicI, T.VbicIA2, IsaVersion.v80, InstFlags.None), + new(0xF2100110, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VbicR, T.VbicRA1, IsaVersion.v80, InstFlags.None), + new(0xF3300110, 0xFFB00F10, qvdQvnQvmOpConstraints, InstName.Vbif, T.VbifA1, IsaVersion.v80, InstFlags.None), + new(0xF3200110, 0xFFB00F10, qvdQvnQvmOpConstraints, InstName.Vbit, T.VbitA1, IsaVersion.v80, InstFlags.None), + new(0xF3100110, 0xFFB00F10, qvdQvnQvmOpConstraints, InstName.Vbsl, T.VbslA1, IsaVersion.v80, InstFlags.None), + new(0xFC900800, 0xFEB00F10, qvdQvnQvmConstraints, InstName.Vcadd, T.VcaddA1, IsaVersion.v83, IsaFeature.FeatFcma, InstFlags.None), + new(0xFC800800, 0xFEB00F10, qvdQvnQvmConstraints, InstName.Vcadd, T.VcaddA1, IsaVersion.v83, IsaFeature.FeatFcma | IsaFeature.FeatFp16, InstFlags.None), + new(0xF3B10100, 0xFFB30F90, sizeQvdQvmConstraints, InstName.VceqI, T.VceqIA1, IsaVersion.v80, InstFlags.None), + new(0xF3B90500, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.VceqI, T.VceqIA1, IsaVersion.v80, InstFlags.None), + new(0xF3B50500, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.VceqI, T.VceqIA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3000810, 0xFF800F10, qvdQvnQvmSizeConstraints, InstName.VceqR, T.VceqRA1, IsaVersion.v80, InstFlags.None), + new(0xF2000E00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VceqR, T.VceqRA2, IsaVersion.v80, InstFlags.None), + new(0xF2100E00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VceqR, T.VceqRA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3B10080, 0xFFB30F90, sizeQvdQvmConstraints, InstName.VcgeI, T.VcgeIA1, IsaVersion.v80, InstFlags.None), + new(0xF3B90480, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.VcgeI, T.VcgeIA1, IsaVersion.v80, InstFlags.None), + new(0xF3B50480, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.VcgeI, T.VcgeIA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2000310, 0xFE800F10, qvdQvnQvmSizeConstraints, InstName.VcgeR, T.VcgeRA1, IsaVersion.v80, InstFlags.None), + new(0xF3000E00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VcgeR, T.VcgeRA2, IsaVersion.v80, InstFlags.None), + new(0xF3100E00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VcgeR, T.VcgeRA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3B10000, 0xFFB30F90, sizeQvdQvmConstraints, InstName.VcgtI, T.VcgtIA1, IsaVersion.v80, InstFlags.None), + new(0xF3B90400, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.VcgtI, T.VcgtIA1, IsaVersion.v80, InstFlags.None), + new(0xF3B50400, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.VcgtI, T.VcgtIA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2000300, 0xFE800F10, qvdQvnQvmSizeConstraints, InstName.VcgtR, T.VcgtRA1, IsaVersion.v80, InstFlags.None), + new(0xF3200E00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VcgtR, T.VcgtRA2, IsaVersion.v80, InstFlags.None), + new(0xF3300E00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VcgtR, T.VcgtRA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3B10180, 0xFFB30F90, sizeQvdQvmConstraints, InstName.VcleI, T.VcleIA1, IsaVersion.v80, InstFlags.None), + new(0xF3B90580, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.VcleI, T.VcleIA1, IsaVersion.v80, InstFlags.None), + new(0xF3B50580, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.VcleI, T.VcleIA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3B00400, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vcls, T.VclsA1, IsaVersion.v80, InstFlags.None), + new(0xF3B10200, 0xFFB30F90, sizeQvdQvmConstraints, InstName.VcltI, T.VcltIA1, IsaVersion.v80, InstFlags.None), + new(0xF3B90600, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.VcltI, T.VcltIA1, IsaVersion.v80, InstFlags.None), + new(0xF3B50600, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.VcltI, T.VcltIA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3B00480, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vclz, T.VclzA1, IsaVersion.v80, InstFlags.None), + new(0xFC200800, 0xFE200F10, qvdQvnQvmConstraints, InstName.Vcmla, T.VcmlaA1, IsaVersion.v83, IsaFeature.FeatFcma, InstFlags.None), + new(0xFE000800, 0xFF000F10, qvdQvnConstraints, InstName.VcmlaS, T.VcmlaSA1, IsaVersion.v83, IsaFeature.FeatFcma, InstFlags.None), + new(0x0EB40A40, 0x0FBF0ED0, condConstraints, InstName.Vcmp, T.VcmpA1, IsaVersion.v80, InstFlags.Cond), + new(0x0EB40940, 0x0FBF0FD0, condConstraints, InstName.Vcmp, T.VcmpA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0x0EB50A40, 0x0FBF0EFF, condConstraints, InstName.Vcmp, T.VcmpA2, IsaVersion.v80, InstFlags.Cond), + new(0x0EB50940, 0x0FBF0FFF, condConstraints, InstName.Vcmp, T.VcmpA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0x0EB40AC0, 0x0FBF0ED0, condConstraints, InstName.Vcmpe, T.VcmpeA1, IsaVersion.v80, InstFlags.Cond), + new(0x0EB409C0, 0x0FBF0FD0, condConstraints, InstName.Vcmpe, T.VcmpeA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0x0EB50AC0, 0x0FBF0EFF, condConstraints, InstName.Vcmpe, T.VcmpeA2, IsaVersion.v80, InstFlags.Cond), + new(0x0EB509C0, 0x0FBF0FFF, condConstraints, InstName.Vcmpe, T.VcmpeA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF3B00500, 0xFFBF0F90, qvdQvmConstraints, InstName.Vcnt, T.VcntA1, IsaVersion.v80, InstFlags.None), + new(0xF3BB0000, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtaAsimd, T.VcvtaAsimdA1, IsaVersion.v80, InstFlags.None), + new(0xF3B70000, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtaAsimd, T.VcvtaAsimdA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEBC0A40, 0xFFBF0E50, sizeConstraints, InstName.VcvtaVfp, T.VcvtaVfpA1, IsaVersion.v80, InstFlags.None), + new(0xFEBC0940, 0xFFBF0F50, sizeConstraints, InstName.VcvtaVfp, T.VcvtaVfpA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0EB20A40, 0x0FBE0ED0, condConstraints, InstName.Vcvtb, T.VcvtbA1, IsaVersion.v80, InstFlags.Cond), + new(0x0EB30940, 0x0FBF0FD0, condConstraints, InstName.VcvtbBfs, T.VcvtbBfsA1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.Cond), + new(0xF3BB0300, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtmAsimd, T.VcvtmAsimdA1, IsaVersion.v80, InstFlags.None), + new(0xF3B70300, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtmAsimd, T.VcvtmAsimdA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEBF0A40, 0xFFBF0E50, sizeConstraints, InstName.VcvtmVfp, T.VcvtmVfpA1, IsaVersion.v80, InstFlags.None), + new(0xFEBF0940, 0xFFBF0F50, sizeConstraints, InstName.VcvtmVfp, T.VcvtmVfpA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3BB0100, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtnAsimd, T.VcvtnAsimdA1, IsaVersion.v80, InstFlags.None), + new(0xF3B70100, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtnAsimd, T.VcvtnAsimdA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEBD0A40, 0xFFBF0E50, sizeConstraints, InstName.VcvtnVfp, T.VcvtnVfpA1, IsaVersion.v80, InstFlags.None), + new(0xFEBD0940, 0xFFBF0F50, sizeConstraints, InstName.VcvtnVfp, T.VcvtnVfpA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3BB0200, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtpAsimd, T.VcvtpAsimdA1, IsaVersion.v80, InstFlags.None), + new(0xF3B70200, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtpAsimd, T.VcvtpAsimdA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEBE0A40, 0xFFBF0E50, sizeConstraints, InstName.VcvtpVfp, T.VcvtpVfpA1, IsaVersion.v80, InstFlags.None), + new(0xFEBE0940, 0xFFBF0F50, sizeConstraints, InstName.VcvtpVfp, T.VcvtpVfpA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0EBC0A40, 0x0FBE0ED0, condConstraints, InstName.VcvtrIv, T.VcvtrIvA1, IsaVersion.v80, InstFlags.Cond), + new(0x0EBC0940, 0x0FBE0FD0, condConstraints, InstName.VcvtrIv, T.VcvtrIvA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0x0EB20AC0, 0x0FBE0ED0, condConstraints, InstName.Vcvtt, T.VcvttA1, IsaVersion.v80, InstFlags.Cond), + new(0x0EB309C0, 0x0FBF0FD0, condConstraints, InstName.VcvttBfs, T.VcvttBfsA1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.Cond), + new(0xF3B60640, 0xFFBF0FD0, vmConstraints, InstName.VcvtBfs, T.VcvtBfsA1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0x0EB70AC0, 0x0FBF0ED0, condConstraints, InstName.VcvtDs, T.VcvtDsA1, IsaVersion.v80, InstFlags.Cond), + new(0xF3B60600, 0xFFBF0ED0, opvdOpvmConstraints, InstName.VcvtHs, T.VcvtHsA1, IsaVersion.v80, InstFlags.None), + new(0xF3BB0600, 0xFFBF0E10, qvdQvmConstraints, InstName.VcvtIs, T.VcvtIsA1, IsaVersion.v80, InstFlags.None), + new(0xF3B70600, 0xFFBF0E10, qvdQvmConstraints, InstName.VcvtIs, T.VcvtIsA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0EBC0AC0, 0x0FBE0ED0, condConstraints, InstName.VcvtIv, T.VcvtIvA1, IsaVersion.v80, InstFlags.Cond), + new(0x0EBC09C0, 0x0FBE0FD0, condConstraints, InstName.VcvtIv, T.VcvtIvA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0x0EB80A40, 0x0FBF0E50, condConstraints, InstName.VcvtVi, T.VcvtViA1, IsaVersion.v80, InstFlags.Cond), + new(0x0EB80940, 0x0FBF0F50, condConstraints, InstName.VcvtVi, T.VcvtViA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF2800E10, 0xFE800E90, imm6Opimm6Imm6QvdQvmConstraints, InstName.VcvtXs, T.VcvtXsA1, IsaVersion.v80, InstFlags.None), + new(0xF2800C10, 0xFE800E90, imm6Opimm6Imm6QvdQvmConstraints, InstName.VcvtXs, T.VcvtXsA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0EBA0A40, 0x0FBA0E50, condConstraints, InstName.VcvtXv, T.VcvtXvA1, IsaVersion.v80, InstFlags.Cond), + new(0x0EBA0940, 0x0FBA0F50, condConstraints, InstName.VcvtXv, T.VcvtXvA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0x0E800A00, 0x0FB00E50, condConstraints, InstName.Vdiv, T.VdivA1, IsaVersion.v80, InstFlags.Cond), + new(0x0E800900, 0x0FB00F50, condConstraints, InstName.Vdiv, T.VdivA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xFC000D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vdot, T.VdotA1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0xFE000D00, 0xFFB00F10, qvdQvnConstraints, InstName.VdotS, T.VdotSA1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0x0E800B10, 0x0F900F5F, condQvdEbConstraints, InstName.VdupR, T.VdupRA1, IsaVersion.v80, InstFlags.CondRtRead), + new(0xF3B00C00, 0xFFB00F90, imm4QvdConstraints, InstName.VdupS, T.VdupSA1, IsaVersion.v80, InstFlags.None), + new(0xF3000110, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Veor, T.VeorA1, IsaVersion.v80, InstFlags.None), + new(0xF2B00000, 0xFFB00010, qvdQvnQvmQimm4Constraints, InstName.Vext, T.VextA1, IsaVersion.v80, InstFlags.None), + new(0xF2000C10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vfma, T.VfmaA1, IsaVersion.v80, InstFlags.None), + new(0xF2100C10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vfma, T.VfmaA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0EA00A00, 0x0FB00E50, condConstraints, InstName.Vfma, T.VfmaA2, IsaVersion.v80, InstFlags.Cond), + new(0x0EA00900, 0x0FB00F50, condConstraints, InstName.Vfma, T.VfmaA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xFC200810, 0xFFB00F10, qvdConstraints, InstName.Vfmal, T.VfmalA1, IsaVersion.v82, IsaFeature.FeatFhm, InstFlags.None), + new(0xFE000810, 0xFFB00F10, qvdConstraints, InstName.VfmalS, T.VfmalSA1, IsaVersion.v82, IsaFeature.FeatFhm, InstFlags.None), + new(0xFC300810, 0xFFB00F10, vdVnVmConstraints, InstName.VfmaBf, T.VfmaBfA1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0xFE300810, 0xFFB00F10, vdVnConstraints, InstName.VfmaBfs, T.VfmaBfsA1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0xF2200C10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vfms, T.VfmsA1, IsaVersion.v80, InstFlags.None), + new(0xF2300C10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vfms, T.VfmsA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0EA00A40, 0x0FB00E50, condConstraints, InstName.Vfms, T.VfmsA2, IsaVersion.v80, InstFlags.Cond), + new(0x0EA00940, 0x0FB00F50, condConstraints, InstName.Vfms, T.VfmsA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xFCA00810, 0xFFB00F10, qvdConstraints, InstName.Vfmsl, T.VfmslA1, IsaVersion.v82, IsaFeature.FeatFhm, InstFlags.None), + new(0xFE100810, 0xFFB00F10, qvdConstraints, InstName.VfmslS, T.VfmslSA1, IsaVersion.v82, IsaFeature.FeatFhm, InstFlags.None), + new(0x0E900A40, 0x0FB00E50, condConstraints, InstName.Vfnma, T.VfnmaA1, IsaVersion.v80, InstFlags.Cond), + new(0x0E900940, 0x0FB00F50, condConstraints, InstName.Vfnma, T.VfnmaA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0x0E900A00, 0x0FB00E50, condConstraints, InstName.Vfnms, T.VfnmsA1, IsaVersion.v80, InstFlags.Cond), + new(0x0E900900, 0x0FB00F50, condConstraints, InstName.Vfnms, T.VfnmsA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF2000000, 0xFE800F10, qvdQvnQvmSizeConstraints, InstName.Vhadd, T.VhaddA1, IsaVersion.v80, InstFlags.None), + new(0xF2000200, 0xFE800F10, qvdQvnQvmSizeConstraints, InstName.Vhsub, T.VhsubA1, IsaVersion.v80, InstFlags.None), + new(0xFEB00AC0, 0xFFBF0FD0, InstName.Vins, T.VinsA1, IsaVersion.v82, IsaFeature.FeatFp16, InstFlags.None), + new(0x0EB90BC0, 0x0FBF0FD0, condConstraints, InstName.Vjcvt, T.VjcvtA1, IsaVersion.v83, IsaFeature.FeatJscvt, InstFlags.Cond), + new(0xF4A00000, 0xFFB00F10, sizeConstraints2, InstName.Vld11, T.Vld11A1, IsaVersion.v80, InstFlags.None), + new(0xF4A00400, 0xFFB00F20, sizeConstraints2, InstName.Vld11, T.Vld11A2, IsaVersion.v80, InstFlags.None), + new(0xF4A00800, 0xFFB00F40, sizeIndexAlignIndexAlignConstraints, InstName.Vld11, T.Vld11A3, IsaVersion.v80, InstFlags.None), + new(0xF4A00C00, 0xFFB00F00, sizeSizeaConstraints, InstName.Vld1A, T.Vld1AA1, IsaVersion.v80, InstFlags.None), + new(0xF4200700, 0xFFB00F00, alignConstraints, InstName.Vld1M, T.Vld1MA1, IsaVersion.v80, InstFlags.None), + new(0xF4200A00, 0xFFB00F00, alignConstraints2, InstName.Vld1M, T.Vld1MA2, IsaVersion.v80, InstFlags.None), + new(0xF4200600, 0xFFB00F00, alignConstraints, InstName.Vld1M, T.Vld1MA3, IsaVersion.v80, InstFlags.None), + new(0xF4200200, 0xFFB00F00, InstName.Vld1M, T.Vld1MA4, IsaVersion.v80, InstFlags.None), + new(0xF4A00100, 0xFFB00F00, sizeConstraints2, InstName.Vld21, T.Vld21A1, IsaVersion.v80, InstFlags.None), + new(0xF4A00500, 0xFFB00F00, sizeConstraints2, InstName.Vld21, T.Vld21A2, IsaVersion.v80, InstFlags.None), + new(0xF4A00900, 0xFFB00F20, sizeConstraints2, InstName.Vld21, T.Vld21A3, IsaVersion.v80, InstFlags.None), + new(0xF4A00D00, 0xFFB00F00, sizeConstraints3, InstName.Vld2A, T.Vld2AA1, IsaVersion.v80, InstFlags.None), + new(0xF4200800, 0xFFB00E00, alignSizeConstraints, InstName.Vld2M, T.Vld2MA1, IsaVersion.v80, InstFlags.None), + new(0xF4200300, 0xFFB00F00, sizeConstraints3, InstName.Vld2M, T.Vld2MA2, IsaVersion.v80, InstFlags.None), + new(0xF4A00200, 0xFFB00F10, sizeConstraints2, InstName.Vld31, T.Vld31A1, IsaVersion.v80, InstFlags.None), + new(0xF4A00600, 0xFFB00F10, sizeConstraints2, InstName.Vld31, T.Vld31A2, IsaVersion.v80, InstFlags.None), + new(0xF4A00A00, 0xFFB00F30, sizeConstraints2, InstName.Vld31, T.Vld31A3, IsaVersion.v80, InstFlags.None), + new(0xF4A00E00, 0xFFB00F10, sizeAConstraints, InstName.Vld3A, T.Vld3AA1, IsaVersion.v80, InstFlags.None), + new(0xF4200400, 0xFFB00E00, sizeAlignConstraints, InstName.Vld3M, T.Vld3MA1, IsaVersion.v80, InstFlags.None), + new(0xF4A00300, 0xFFB00F00, sizeConstraints2, InstName.Vld41, T.Vld41A1, IsaVersion.v80, InstFlags.None), + new(0xF4A00700, 0xFFB00F00, sizeConstraints2, InstName.Vld41, T.Vld41A2, IsaVersion.v80, InstFlags.None), + new(0xF4A00B00, 0xFFB00F00, sizeIndexAlignConstraints, InstName.Vld41, T.Vld41A3, IsaVersion.v80, InstFlags.None), + new(0xF4A00F00, 0xFFB00F00, sizeaConstraints, InstName.Vld4A, T.Vld4AA1, IsaVersion.v80, InstFlags.None), + new(0xF4200000, 0xFFB00E00, sizeConstraints3, InstName.Vld4M, T.Vld4MA1, IsaVersion.v80, InstFlags.None), + new(0x0C100B00, 0x0E100F01, condPuwPwPuwPuwConstraints, InstName.Vldm, T.VldmA1, IsaVersion.v80, InstFlags.CondWBack), + new(0x0C100A00, 0x0E100F00, condPuwPwPuwPuwConstraints, InstName.Vldm, T.VldmA2, IsaVersion.v80, InstFlags.CondWBack), + new(0x0D100A00, 0x0F300E00, condRnConstraints3, InstName.VldrI, T.VldrIA1, IsaVersion.v80, InstFlags.Cond), + new(0x0D100900, 0x0F300F00, condRnConstraints3, InstName.VldrI, T.VldrIA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0x0D1F0A00, 0x0F3F0E00, condConstraints, InstName.VldrL, T.VldrLA1, IsaVersion.v80, InstFlags.Cond), + new(0x0D1F0900, 0x0F3F0F00, condConstraints, InstName.VldrL, T.VldrLA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF3000F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vmaxnm, T.VmaxnmA1, IsaVersion.v80, InstFlags.None), + new(0xF3100F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vmaxnm, T.VmaxnmA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFE800A00, 0xFFB00E50, sizeConstraints, InstName.Vmaxnm, T.VmaxnmA2, IsaVersion.v80, InstFlags.None), + new(0xFE800900, 0xFFB00F50, sizeConstraints, InstName.Vmaxnm, T.VmaxnmA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2000F00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmaxF, T.VmaxFA1, IsaVersion.v80, InstFlags.None), + new(0xF2100F00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmaxF, T.VmaxFA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2000600, 0xFE800F10, qvdQvnQvmSizeConstraints, InstName.VmaxI, T.VmaxIA1, IsaVersion.v80, InstFlags.None), + new(0xF3200F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vminnm, T.VminnmA1, IsaVersion.v80, InstFlags.None), + new(0xF3300F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vminnm, T.VminnmA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFE800A40, 0xFFB00E50, sizeConstraints, InstName.Vminnm, T.VminnmA2, IsaVersion.v80, InstFlags.None), + new(0xFE800940, 0xFFB00F50, sizeConstraints, InstName.Vminnm, T.VminnmA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2200F00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VminF, T.VminFA1, IsaVersion.v80, InstFlags.None), + new(0xF2300F00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VminF, T.VminFA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2000610, 0xFE800F10, qvdQvnQvmSizeConstraints, InstName.VminI, T.VminIA1, IsaVersion.v80, InstFlags.None), + new(0xF2800800, 0xFE800F50, sizeVdConstraints, InstName.VmlalI, T.VmlalIA1, IsaVersion.v80, InstFlags.None), + new(0xF2800240, 0xFE800F50, sizeSizeVdConstraints, InstName.VmlalS, T.VmlalSA1, IsaVersion.v80, InstFlags.None), + new(0xF2000D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmlaF, T.VmlaFA1, IsaVersion.v80, InstFlags.None), + new(0xF2100D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmlaF, T.VmlaFA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0E000A00, 0x0FB00E50, condConstraints, InstName.VmlaF, T.VmlaFA2, IsaVersion.v80, InstFlags.Cond), + new(0x0E000900, 0x0FB00F50, condConstraints, InstName.VmlaF, T.VmlaFA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF2000900, 0xFF800F10, sizeQvdQvnQvmConstraints, InstName.VmlaI, T.VmlaIA1, IsaVersion.v80, InstFlags.None), + new(0xF2A00040, 0xFEA00E50, sizeQvdQvnConstraints, InstName.VmlaS, T.VmlaSA1, IsaVersion.v80, InstFlags.None), + new(0xF2900040, 0xFEB00F50, sizeQvdQvnConstraints, InstName.VmlaS, T.VmlaSA1, IsaVersion.v80, InstFlags.None), + new(0xF2900140, 0xFEB00F50, sizeQvdQvnConstraints, InstName.VmlaS, T.VmlaSA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2800A00, 0xFE800F50, sizeVdConstraints, InstName.VmlslI, T.VmlslIA1, IsaVersion.v80, InstFlags.None), + new(0xF2800640, 0xFE800F50, sizeSizeVdConstraints, InstName.VmlslS, T.VmlslSA1, IsaVersion.v80, InstFlags.None), + new(0xF2200D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmlsF, T.VmlsFA1, IsaVersion.v80, InstFlags.None), + new(0xF2300D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmlsF, T.VmlsFA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0E000A40, 0x0FB00E50, condConstraints, InstName.VmlsF, T.VmlsFA2, IsaVersion.v80, InstFlags.Cond), + new(0x0E000940, 0x0FB00F50, condConstraints, InstName.VmlsF, T.VmlsFA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF3000900, 0xFF800F10, sizeQvdQvnQvmConstraints, InstName.VmlsI, T.VmlsIA1, IsaVersion.v80, InstFlags.None), + new(0xF2A00440, 0xFEA00E50, sizeQvdQvnConstraints, InstName.VmlsS, T.VmlsSA1, IsaVersion.v80, InstFlags.None), + new(0xF2900440, 0xFEB00F50, sizeQvdQvnConstraints, InstName.VmlsS, T.VmlsSA1, IsaVersion.v80, InstFlags.None), + new(0xF2900540, 0xFEB00F50, sizeQvdQvnConstraints, InstName.VmlsS, T.VmlsSA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFC000C40, 0xFFB00F50, vdVnVmConstraints, InstName.Vmmla, T.VmmlaA1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0xF2800A10, 0xFE870FD0, imm3hImm3hImm3hImm3hImm3hVdConstraints, InstName.Vmovl, T.VmovlA1, IsaVersion.v80, InstFlags.None), + new(0xF3B20200, 0xFFB30FD0, sizeVmConstraints, InstName.Vmovn, T.VmovnA1, IsaVersion.v80, InstFlags.None), + new(0xFEB00A40, 0xFFBF0FD0, InstName.Vmovx, T.VmovxA1, IsaVersion.v82, IsaFeature.FeatFp16, InstFlags.None), + new(0x0C400B10, 0x0FE00FD0, condConstraints, InstName.VmovD, T.VmovDA1, IsaVersion.v80, InstFlags.CondRt2Read), + new(0x0E000910, 0x0FE00F7F, condConstraints, InstName.VmovH, T.VmovHA1, IsaVersion.v82, IsaFeature.FeatFp16, InstFlags.CondRt), + new(0xF2800010, 0xFEB809B0, qvdConstraints, InstName.VmovI, T.VmovIA1, IsaVersion.v80, InstFlags.None), + new(0x0EB00A00, 0x0FB00EF0, condConstraints, InstName.VmovI, T.VmovIA2, IsaVersion.v80, InstFlags.Cond), + new(0x0EB00900, 0x0FB00FF0, condConstraints, InstName.VmovI, T.VmovIA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF2800810, 0xFEB80DB0, qvdConstraints, InstName.VmovI, T.VmovIA3, IsaVersion.v80, InstFlags.None), + new(0xF2800C10, 0xFEB80CB0, qvdConstraints, InstName.VmovI, T.VmovIA4, IsaVersion.v80, InstFlags.None), + new(0xF2800E30, 0xFEB80FB0, qvdConstraints, InstName.VmovI, T.VmovIA5, IsaVersion.v80, InstFlags.None), + new(0x0EB00A40, 0x0FBF0ED0, condConstraints, InstName.VmovR, T.VmovRA2, IsaVersion.v80, InstFlags.Cond), + new(0x0E000B10, 0x0F900F1F, condOpc1opc2Constraints, InstName.VmovRs, T.VmovRsA1, IsaVersion.v80, InstFlags.CondRtRead), + new(0x0E000A10, 0x0FE00F7F, condConstraints, InstName.VmovS, T.VmovSA1, IsaVersion.v80, InstFlags.CondRtRead), + new(0x0E100B10, 0x0F100F1F, condUopc1opc2Uopc1opc2Constraints, InstName.VmovSr, T.VmovSrA1, IsaVersion.v80, InstFlags.CondRt), + new(0x0C400A10, 0x0FE00FD0, condConstraints, InstName.VmovSs, T.VmovSsA1, IsaVersion.v80, InstFlags.CondRt2Read), + new(0x0EF00A10, 0x0FF00FFF, condConstraints, InstName.Vmrs, T.VmrsA1, IsaVersion.v80, InstFlags.CondRt), + new(0x0EE00A10, 0x0FF00FFF, condConstraints, InstName.Vmsr, T.VmsrA1, IsaVersion.v80, InstFlags.CondRtRead), + new(0xF2800C00, 0xFE800D50, sizeOpuOpsizeVdConstraints, InstName.VmullI, T.VmullIA1, IsaVersion.v80, InstFlags.None), + new(0xF2800A40, 0xFE800F50, sizeSizeVdConstraints, InstName.VmullS, T.VmullSA1, IsaVersion.v80, InstFlags.None), + new(0xF3000D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmulF, T.VmulFA1, IsaVersion.v80, InstFlags.None), + new(0xF3100D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmulF, T.VmulFA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0E200A00, 0x0FB00E50, condConstraints, InstName.VmulF, T.VmulFA2, IsaVersion.v80, InstFlags.Cond), + new(0x0E200900, 0x0FB00F50, condConstraints, InstName.VmulF, T.VmulFA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF2000910, 0xFE800F10, sizeOpsizeOpsizeQvdQvnQvmConstraints, InstName.VmulI, T.VmulIA1, IsaVersion.v80, InstFlags.None), + new(0xF2A00840, 0xFEA00E50, sizeQvdQvnConstraints, InstName.VmulS, T.VmulSA1, IsaVersion.v80, InstFlags.None), + new(0xF2900840, 0xFEB00F50, sizeQvdQvnConstraints, InstName.VmulS, T.VmulSA1, IsaVersion.v80, InstFlags.None), + new(0xF2900940, 0xFEB00F50, sizeQvdQvnConstraints, InstName.VmulS, T.VmulSA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2800030, 0xFEB809B0, cmodeQvdConstraints, InstName.VmvnI, T.VmvnIA1, IsaVersion.v80, InstFlags.None), + new(0xF2800830, 0xFEB80DB0, cmodeQvdConstraints, InstName.VmvnI, T.VmvnIA2, IsaVersion.v80, InstFlags.None), + new(0xF2800C30, 0xFEB80EB0, cmodeQvdConstraints, InstName.VmvnI, T.VmvnIA3, IsaVersion.v80, InstFlags.None), + new(0xF3B00580, 0xFFBF0F90, qvdQvmConstraints, InstName.VmvnR, T.VmvnRA1, IsaVersion.v80, InstFlags.None), + new(0xF3B10380, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vneg, T.VnegA1, IsaVersion.v80, InstFlags.None), + new(0xF3B90780, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.Vneg, T.VnegA1, IsaVersion.v80, InstFlags.None), + new(0xF3B50780, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.Vneg, T.VnegA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0EB10A40, 0x0FBF0ED0, condConstraints, InstName.Vneg, T.VnegA2, IsaVersion.v80, InstFlags.Cond), + new(0x0EB10940, 0x0FBF0FD0, condConstraints, InstName.Vneg, T.VnegA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0x0E100A40, 0x0FB00E50, condConstraints, InstName.Vnmla, T.VnmlaA1, IsaVersion.v80, InstFlags.Cond), + new(0x0E100940, 0x0FB00F50, condConstraints, InstName.Vnmla, T.VnmlaA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0x0E100A00, 0x0FB00E50, condConstraints, InstName.Vnmls, T.VnmlsA1, IsaVersion.v80, InstFlags.Cond), + new(0x0E100900, 0x0FB00F50, condConstraints, InstName.Vnmls, T.VnmlsA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0x0E200A40, 0x0FB00E50, condConstraints, InstName.Vnmul, T.VnmulA1, IsaVersion.v80, InstFlags.Cond), + new(0x0E200940, 0x0FB00F50, condConstraints, InstName.Vnmul, T.VnmulA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF2300110, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VornR, T.VornRA1, IsaVersion.v80, InstFlags.None), + new(0xF2800110, 0xFEB809B0, cmodeCmodeQvdConstraints, InstName.VorrI, T.VorrIA1, IsaVersion.v80, InstFlags.None), + new(0xF2800910, 0xFEB80DB0, cmodeCmodeQvdConstraints, InstName.VorrI, T.VorrIA2, IsaVersion.v80, InstFlags.None), + new(0xF2200110, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VorrR, T.VorrRA1, IsaVersion.v80, InstFlags.None), + new(0xF3B00600, 0xFFB30F10, sizeQvdQvmConstraints, InstName.Vpadal, T.VpadalA1, IsaVersion.v80, InstFlags.None), + new(0xF3B00200, 0xFFB30F10, sizeQvdQvmConstraints, InstName.Vpaddl, T.VpaddlA1, IsaVersion.v80, InstFlags.None), + new(0xF3000D00, 0xFFB00F10, qConstraints, InstName.VpaddF, T.VpaddFA1, IsaVersion.v80, InstFlags.None), + new(0xF3100D00, 0xFFB00F10, qConstraints, InstName.VpaddF, T.VpaddFA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2000B10, 0xFF800F10, sizeQConstraints, InstName.VpaddI, T.VpaddIA1, IsaVersion.v80, InstFlags.None), + new(0xF3000F00, 0xFFB00F50, InstName.VpmaxF, T.VpmaxFA1, IsaVersion.v80, InstFlags.None), + new(0xF3100F00, 0xFFB00F50, InstName.VpmaxF, T.VpmaxFA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2000A00, 0xFE800F50, sizeConstraints4, InstName.VpmaxI, T.VpmaxIA1, IsaVersion.v80, InstFlags.None), + new(0xF3200F00, 0xFFB00F50, InstName.VpminF, T.VpminFA1, IsaVersion.v80, InstFlags.None), + new(0xF3300F00, 0xFFB00F50, InstName.VpminF, T.VpminFA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2000A10, 0xFE800F50, sizeConstraints4, InstName.VpminI, T.VpminIA1, IsaVersion.v80, InstFlags.None), + new(0xF3B00700, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vqabs, T.VqabsA1, IsaVersion.v80, InstFlags.None), + new(0xF2000010, 0xFE800F10, qvdQvnQvmConstraints, InstName.Vqadd, T.VqaddA1, IsaVersion.v80, InstFlags.None), + new(0xF2800900, 0xFF800F50, sizeSizeVdConstraints, InstName.Vqdmlal, T.VqdmlalA1, IsaVersion.v80, InstFlags.None), + new(0xF2800340, 0xFF800F50, sizeSizeVdConstraints, InstName.Vqdmlal, T.VqdmlalA2, IsaVersion.v80, InstFlags.None), + new(0xF2800B00, 0xFF800F50, sizeSizeVdConstraints, InstName.Vqdmlsl, T.VqdmlslA1, IsaVersion.v80, InstFlags.None), + new(0xF2800740, 0xFF800F50, sizeSizeVdConstraints, InstName.Vqdmlsl, T.VqdmlslA2, IsaVersion.v80, InstFlags.None), + new(0xF2000B00, 0xFF800F10, qvdQvnQvmSizeSizeConstraints, InstName.Vqdmulh, T.VqdmulhA1, IsaVersion.v80, InstFlags.None), + new(0xF2800C40, 0xFE800F50, sizeSizeQvdQvnConstraints, InstName.Vqdmulh, T.VqdmulhA2, IsaVersion.v80, InstFlags.None), + new(0xF2800D00, 0xFF800F50, sizeSizeVdConstraints, InstName.Vqdmull, T.VqdmullA1, IsaVersion.v80, InstFlags.None), + new(0xF2800B40, 0xFF800F50, sizeSizeVdConstraints, InstName.Vqdmull, T.VqdmullA2, IsaVersion.v80, InstFlags.None), + new(0xF3B20200, 0xFFB30F10, opSizeVmConstraints, InstName.Vqmovn, T.VqmovnA1, IsaVersion.v80, InstFlags.None), + new(0xF3B00780, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vqneg, T.VqnegA1, IsaVersion.v80, InstFlags.None), + new(0xF3000B10, 0xFF800F10, qvdQvnQvmSizeSizeConstraints, InstName.Vqrdmlah, T.VqrdmlahA1, IsaVersion.v81, IsaFeature.FeatRdm, InstFlags.None), + new(0xF2800E40, 0xFE800F50, sizeSizeQvdQvnConstraints, InstName.Vqrdmlah, T.VqrdmlahA2, IsaVersion.v81, IsaFeature.FeatRdm, InstFlags.None), + new(0xF3000C10, 0xFF800F10, qvdQvnQvmSizeSizeConstraints, InstName.Vqrdmlsh, T.VqrdmlshA1, IsaVersion.v81, IsaFeature.FeatRdm, InstFlags.None), + new(0xF2800F40, 0xFE800F50, sizeSizeQvdQvnConstraints, InstName.Vqrdmlsh, T.VqrdmlshA2, IsaVersion.v81, IsaFeature.FeatRdm, InstFlags.None), + new(0xF3000B00, 0xFF800F10, qvdQvnQvmSizeSizeConstraints, InstName.Vqrdmulh, T.VqrdmulhA1, IsaVersion.v80, InstFlags.None), + new(0xF2800D40, 0xFE800F50, sizeSizeQvdQvnConstraints, InstName.Vqrdmulh, T.VqrdmulhA2, IsaVersion.v80, InstFlags.None), + new(0xF2000510, 0xFE800F10, qvdQvmQvnConstraints, InstName.Vqrshl, T.VqrshlA1, IsaVersion.v80, InstFlags.None), + new(0xF2800850, 0xFE800ED0, imm6UopVmConstraints, InstName.Vqrshrn, T.VqrshrnA1, IsaVersion.v80, InstFlags.None), + new(0xF2800610, 0xFE800E10, imm6lUopQvdQvmConstraints, InstName.VqshlI, T.VqshlIA1, IsaVersion.v80, InstFlags.None), + new(0xF2000410, 0xFE800F10, qvdQvmQvnConstraints, InstName.VqshlR, T.VqshlRA1, IsaVersion.v80, InstFlags.None), + new(0xF2800810, 0xFE800ED0, imm6UopVmConstraints, InstName.Vqshrn, T.VqshrnA1, IsaVersion.v80, InstFlags.None), + new(0xF2000210, 0xFE800F10, qvdQvnQvmConstraints, InstName.Vqsub, T.VqsubA1, IsaVersion.v80, InstFlags.None), + new(0xF3800400, 0xFF800F50, sizeVnVmConstraints, InstName.Vraddhn, T.VraddhnA1, IsaVersion.v80, InstFlags.None), + new(0xF3B30400, 0xFFB30E90, qvdQvmSizeSizeConstraints, InstName.Vrecpe, T.VrecpeA1, IsaVersion.v80, InstFlags.None), + new(0xF2000F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vrecps, T.VrecpsA1, IsaVersion.v80, InstFlags.None), + new(0xF2100F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vrecps, T.VrecpsA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3B00100, 0xFFB30F90, sizeSizeSizeQvdQvmConstraints, InstName.Vrev16, T.Vrev16A1, IsaVersion.v80, InstFlags.None), + new(0xF3B00080, 0xFFB30F90, sizeSizeQvdQvmConstraints, InstName.Vrev32, T.Vrev32A1, IsaVersion.v80, InstFlags.None), + new(0xF3B00000, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vrev64, T.Vrev64A1, IsaVersion.v80, InstFlags.None), + new(0xF2000100, 0xFE800F10, qvdQvnQvmSizeConstraints, InstName.Vrhadd, T.VrhaddA1, IsaVersion.v80, InstFlags.None), + new(0xF3BA0500, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintaAsimd, T.VrintaAsimdA1, IsaVersion.v80, InstFlags.None), + new(0xF3B60500, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintaAsimd, T.VrintaAsimdA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEB80A40, 0xFFBF0ED0, sizeConstraints, InstName.VrintaVfp, T.VrintaVfpA1, IsaVersion.v80, InstFlags.None), + new(0xFEB80940, 0xFFBF0FD0, sizeConstraints, InstName.VrintaVfp, T.VrintaVfpA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3BA0680, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintmAsimd, T.VrintmAsimdA1, IsaVersion.v80, InstFlags.None), + new(0xF3B60680, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintmAsimd, T.VrintmAsimdA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEBB0A40, 0xFFBF0ED0, sizeConstraints, InstName.VrintmVfp, T.VrintmVfpA1, IsaVersion.v80, InstFlags.None), + new(0xFEBB0940, 0xFFBF0FD0, sizeConstraints, InstName.VrintmVfp, T.VrintmVfpA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3BA0400, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintnAsimd, T.VrintnAsimdA1, IsaVersion.v80, InstFlags.None), + new(0xF3B60400, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintnAsimd, T.VrintnAsimdA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEB90A40, 0xFFBF0ED0, sizeConstraints, InstName.VrintnVfp, T.VrintnVfpA1, IsaVersion.v80, InstFlags.None), + new(0xFEB90940, 0xFFBF0FD0, sizeConstraints, InstName.VrintnVfp, T.VrintnVfpA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF3BA0780, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintpAsimd, T.VrintpAsimdA1, IsaVersion.v80, InstFlags.None), + new(0xF3B60780, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintpAsimd, T.VrintpAsimdA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEBA0A40, 0xFFBF0ED0, sizeConstraints, InstName.VrintpVfp, T.VrintpVfpA1, IsaVersion.v80, InstFlags.None), + new(0xFEBA0940, 0xFFBF0FD0, sizeConstraints, InstName.VrintpVfp, T.VrintpVfpA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0EB60A40, 0x0FBF0ED0, condConstraints, InstName.VrintrVfp, T.VrintrVfpA1, IsaVersion.v80, InstFlags.Cond), + new(0x0EB60940, 0x0FBF0FD0, condConstraints, InstName.VrintrVfp, T.VrintrVfpA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF3BA0480, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintxAsimd, T.VrintxAsimdA1, IsaVersion.v80, InstFlags.None), + new(0xF3B60480, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintxAsimd, T.VrintxAsimdA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0EB70A40, 0x0FBF0ED0, condConstraints, InstName.VrintxVfp, T.VrintxVfpA1, IsaVersion.v80, InstFlags.Cond), + new(0x0EB70940, 0x0FBF0FD0, condConstraints, InstName.VrintxVfp, T.VrintxVfpA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF3BA0580, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintzAsimd, T.VrintzAsimdA1, IsaVersion.v80, InstFlags.None), + new(0xF3B60580, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintzAsimd, T.VrintzAsimdA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0EB60AC0, 0x0FBF0ED0, condConstraints, InstName.VrintzVfp, T.VrintzVfpA1, IsaVersion.v80, InstFlags.Cond), + new(0x0EB609C0, 0x0FBF0FD0, condConstraints, InstName.VrintzVfp, T.VrintzVfpA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF2000500, 0xFE800F10, qvdQvmQvnConstraints, InstName.Vrshl, T.VrshlA1, IsaVersion.v80, InstFlags.None), + new(0xF2800210, 0xFE800F10, imm6lQvdQvmConstraints, InstName.Vrshr, T.VrshrA1, IsaVersion.v80, InstFlags.None), + new(0xF2800850, 0xFF800FD0, imm6VmConstraints, InstName.Vrshrn, T.VrshrnA1, IsaVersion.v80, InstFlags.None), + new(0xF3B30480, 0xFFB30E90, qvdQvmSizeSizeConstraints, InstName.Vrsqrte, T.VrsqrteA1, IsaVersion.v80, InstFlags.None), + new(0xF2200F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vrsqrts, T.VrsqrtsA1, IsaVersion.v80, InstFlags.None), + new(0xF2300F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vrsqrts, T.VrsqrtsA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2800310, 0xFE800F10, imm6lQvdQvmConstraints, InstName.Vrsra, T.VrsraA1, IsaVersion.v80, InstFlags.None), + new(0xF3800600, 0xFF800F50, sizeVnVmConstraints, InstName.Vrsubhn, T.VrsubhnA1, IsaVersion.v80, InstFlags.None), + new(0xFC200D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vsdot, T.VsdotA1, IsaVersion.v82, IsaFeature.FeatDotprod, InstFlags.None), + new(0xFE200D00, 0xFFB00F10, qvdQvnConstraints, InstName.VsdotS, T.VsdotSA1, IsaVersion.v82, IsaFeature.FeatDotprod, InstFlags.None), + new(0xFE000A00, 0xFF800E50, sizeConstraints, InstName.Vsel, T.VselA1, IsaVersion.v80, InstFlags.None), + new(0xFE000900, 0xFF800F50, sizeConstraints, InstName.Vsel, T.VselA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xF2800A10, 0xFE800FD0, imm6VdImm6Imm6Imm6Constraints, InstName.Vshll, T.VshllA1, IsaVersion.v80, InstFlags.None), + new(0xF3B20300, 0xFFB30FD0, sizeVdConstraints2, InstName.Vshll, T.VshllA2, IsaVersion.v80, InstFlags.None), + new(0xF2800510, 0xFF800F10, imm6lQvdQvmConstraints, InstName.VshlI, T.VshlIA1, IsaVersion.v80, InstFlags.None), + new(0xF2000400, 0xFE800F10, qvdQvmQvnConstraints, InstName.VshlR, T.VshlRA1, IsaVersion.v80, InstFlags.None), + new(0xF2800010, 0xFE800F10, imm6lQvdQvmConstraints, InstName.Vshr, T.VshrA1, IsaVersion.v80, InstFlags.None), + new(0xF2800810, 0xFF800FD0, imm6VmConstraints, InstName.Vshrn, T.VshrnA1, IsaVersion.v80, InstFlags.None), + new(0xF3800510, 0xFF800F10, imm6lQvdQvmConstraints, InstName.Vsli, T.VsliA1, IsaVersion.v80, InstFlags.None), + new(0xFC200C40, 0xFFB00F50, vdVnVmConstraints, InstName.Vsmmla, T.VsmmlaA1, IsaVersion.v82, IsaFeature.FeatAa32i8mm, InstFlags.None), + new(0x0EB10AC0, 0x0FBF0ED0, condConstraints, InstName.Vsqrt, T.VsqrtA1, IsaVersion.v80, InstFlags.Cond), + new(0x0EB109C0, 0x0FBF0FD0, condConstraints, InstName.Vsqrt, T.VsqrtA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF2800110, 0xFE800F10, imm6lQvdQvmConstraints, InstName.Vsra, T.VsraA1, IsaVersion.v80, InstFlags.None), + new(0xF3800410, 0xFF800F10, imm6lQvdQvmConstraints, InstName.Vsri, T.VsriA1, IsaVersion.v80, InstFlags.None), + new(0xF4800000, 0xFFB00F10, sizeConstraints2, InstName.Vst11, T.Vst11A1, IsaVersion.v80, InstFlags.None), + new(0xF4800400, 0xFFB00F20, sizeConstraints2, InstName.Vst11, T.Vst11A2, IsaVersion.v80, InstFlags.None), + new(0xF4800800, 0xFFB00F40, sizeIndexAlignIndexAlignConstraints, InstName.Vst11, T.Vst11A3, IsaVersion.v80, InstFlags.None), + new(0xF4000700, 0xFFB00F00, alignConstraints, InstName.Vst1M, T.Vst1MA1, IsaVersion.v80, InstFlags.None), + new(0xF4000A00, 0xFFB00F00, alignConstraints2, InstName.Vst1M, T.Vst1MA2, IsaVersion.v80, InstFlags.None), + new(0xF4000600, 0xFFB00F00, alignConstraints, InstName.Vst1M, T.Vst1MA3, IsaVersion.v80, InstFlags.None), + new(0xF4000200, 0xFFB00F00, InstName.Vst1M, T.Vst1MA4, IsaVersion.v80, InstFlags.None), + new(0xF4800100, 0xFFB00F00, sizeConstraints2, InstName.Vst21, T.Vst21A1, IsaVersion.v80, InstFlags.None), + new(0xF4800500, 0xFFB00F00, sizeConstraints2, InstName.Vst21, T.Vst21A2, IsaVersion.v80, InstFlags.None), + new(0xF4800900, 0xFFB00F20, sizeConstraints2, InstName.Vst21, T.Vst21A3, IsaVersion.v80, InstFlags.None), + new(0xF4000800, 0xFFB00E00, alignSizeConstraints, InstName.Vst2M, T.Vst2MA1, IsaVersion.v80, InstFlags.None), + new(0xF4000300, 0xFFB00F00, sizeConstraints3, InstName.Vst2M, T.Vst2MA2, IsaVersion.v80, InstFlags.None), + new(0xF4800200, 0xFFB00F10, sizeConstraints2, InstName.Vst31, T.Vst31A1, IsaVersion.v80, InstFlags.None), + new(0xF4800600, 0xFFB00F10, sizeConstraints2, InstName.Vst31, T.Vst31A2, IsaVersion.v80, InstFlags.None), + new(0xF4800A00, 0xFFB00F30, sizeConstraints2, InstName.Vst31, T.Vst31A3, IsaVersion.v80, InstFlags.None), + new(0xF4000400, 0xFFB00E00, sizeAlignConstraints, InstName.Vst3M, T.Vst3MA1, IsaVersion.v80, InstFlags.None), + new(0xF4800300, 0xFFB00F00, sizeConstraints2, InstName.Vst41, T.Vst41A1, IsaVersion.v80, InstFlags.None), + new(0xF4800700, 0xFFB00F00, sizeConstraints2, InstName.Vst41, T.Vst41A2, IsaVersion.v80, InstFlags.None), + new(0xF4800B00, 0xFFB00F00, sizeIndexAlignConstraints, InstName.Vst41, T.Vst41A3, IsaVersion.v80, InstFlags.None), + new(0xF4000000, 0xFFB00E00, sizeConstraints3, InstName.Vst4M, T.Vst4MA1, IsaVersion.v80, InstFlags.None), + new(0x0C000B00, 0x0E100F01, condPuwPwPuwPuwConstraints, InstName.Vstm, T.VstmA1, IsaVersion.v80, InstFlags.CondWBack), + new(0x0C000A00, 0x0E100F00, condPuwPwPuwPuwConstraints, InstName.Vstm, T.VstmA2, IsaVersion.v80, InstFlags.CondWBack), + new(0x0D000A00, 0x0F300E00, condConstraints, InstName.Vstr, T.VstrA1, IsaVersion.v80, InstFlags.Cond), + new(0x0D000900, 0x0F300F00, condConstraints, InstName.Vstr, T.VstrA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF2800600, 0xFF800F50, sizeVnVmConstraints, InstName.Vsubhn, T.VsubhnA1, IsaVersion.v80, InstFlags.None), + new(0xF2800200, 0xFE800F50, sizeVdOpvnConstraints, InstName.Vsubl, T.VsublA1, IsaVersion.v80, InstFlags.None), + new(0xF2800300, 0xFE800F50, sizeVdOpvnConstraints, InstName.Vsubw, T.VsubwA1, IsaVersion.v80, InstFlags.None), + new(0xF2200D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VsubF, T.VsubFA1, IsaVersion.v80, InstFlags.None), + new(0xF2300D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VsubF, T.VsubFA1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0x0E300A40, 0x0FB00E50, condConstraints, InstName.VsubF, T.VsubFA2, IsaVersion.v80, InstFlags.Cond), + new(0x0E300940, 0x0FB00F50, condConstraints, InstName.VsubF, T.VsubFA2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.Cond), + new(0xF3000800, 0xFF800F10, qvdQvnQvmConstraints, InstName.VsubI, T.VsubIA1, IsaVersion.v80, InstFlags.None), + new(0xFE800D10, 0xFFB00F10, qvdQvnConstraints, InstName.VsudotS, T.VsudotSA1, IsaVersion.v82, IsaFeature.FeatAa32i8mm, InstFlags.None), + new(0xF3B20000, 0xFFBF0F90, qvdQvmConstraints, InstName.Vswp, T.VswpA1, IsaVersion.v80, InstFlags.None), + new(0xF3B00800, 0xFFB00C10, InstName.Vtbl, T.VtblA1, IsaVersion.v80, InstFlags.None), + new(0xF3B20080, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vtrn, T.VtrnA1, IsaVersion.v80, InstFlags.None), + new(0xF2000810, 0xFF800F10, qvdQvnQvmSizeConstraints, InstName.Vtst, T.VtstA1, IsaVersion.v80, InstFlags.None), + new(0xFC200D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vudot, T.VudotA1, IsaVersion.v82, IsaFeature.FeatDotprod, InstFlags.None), + new(0xFE200D10, 0xFFB00F10, qvdQvnConstraints, InstName.VudotS, T.VudotSA1, IsaVersion.v82, IsaFeature.FeatDotprod, InstFlags.None), + new(0xFC200C50, 0xFFB00F50, vdVnVmConstraints, InstName.Vummla, T.VummlaA1, IsaVersion.v82, IsaFeature.FeatAa32i8mm, InstFlags.None), + new(0xFCA00D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vusdot, T.VusdotA1, IsaVersion.v82, IsaFeature.FeatAa32i8mm, InstFlags.None), + new(0xFE800D00, 0xFFB00F10, qvdQvnConstraints, InstName.VusdotS, T.VusdotSA1, IsaVersion.v82, IsaFeature.FeatAa32i8mm, InstFlags.None), + new(0xFCA00C40, 0xFFB00F50, vdVnVmConstraints, InstName.Vusmmla, T.VusmmlaA1, IsaVersion.v82, IsaFeature.FeatAa32i8mm, InstFlags.None), + new(0xF3B20100, 0xFFB30F90, sizeQsizeQvdQvmConstraints, InstName.Vuzp, T.VuzpA1, IsaVersion.v80, InstFlags.None), + new(0xF3B20180, 0xFFB30F90, sizeQsizeQvdQvmConstraints, InstName.Vzip, T.VzipA1, IsaVersion.v80, InstFlags.None), + new(0x0320F002, 0x0FFFFFFF, condConstraints, InstName.Wfe, T.WfeA1, IsaVersion.v80, InstFlags.Cond), + new(0x0320F003, 0x0FFFFFFF, condConstraints, InstName.Wfi, T.WfiA1, IsaVersion.v80, InstFlags.Cond), + new(0x0320F001, 0x0FFFFFFF, condConstraints, InstName.Yield, T.YieldA1, IsaVersion.v80, InstFlags.Cond), + }; + + _table = new(insts); + } + + public static InstMeta GetMeta(uint encoding, IsaVersion version, IsaFeature features) + { + if (_table.TryFind(encoding, version, features, out InstInfoForTable info)) + { + return info.Meta; + } + + return new(InstName.Udf, T.UdfA1, IsaVersion.v80, IsaFeature.None, InstFlags.None); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT16.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT16.cs new file mode 100644 index 00000000..7ff5f6c9 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT16.cs @@ -0,0 +1,146 @@ +using Ryujinx.Cpu.LightningJit.Table; +using System.Collections.Generic; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + static class InstTableT16<T> where T : IInstEmit + { + private static readonly InstTableLevel<InstInfoForTable> _table; + + static InstTableT16() + { + InstEncoding[] rmRdndnConstraints = new InstEncoding[] + { + new(0x00680000, 0x00780000), + new(0x00850000, 0x00870000), + }; + + InstEncoding[] rmConstraints = new InstEncoding[] + { + new(0x00680000, 0x00780000), + }; + + InstEncoding[] condCondConstraints = new InstEncoding[] + { + new(0x0E000000, 0x0F000000), + new(0x0F000000, 0x0F000000), + }; + + InstEncoding[] maskConstraints = new InstEncoding[] + { + new(0x00000000, 0x000F0000), + }; + + InstEncoding[] opConstraints = new InstEncoding[] + { + new(0x18000000, 0x18000000), + }; + + InstEncoding[] opOpOpOpConstraints = new InstEncoding[] + { + new(0x00000000, 0x03C00000), + new(0x00400000, 0x03C00000), + new(0x01400000, 0x03C00000), + new(0x01800000, 0x03C00000), + }; + + List<InstInfoForTable> insts = new() + { + new(0x41400000, 0xFFC00000, InstName.AdcR, T.AdcRT1, IsaVersion.v80, InstFlags.Rdn), + new(0x1C000000, 0xFE000000, InstName.AddI, T.AddIT1, IsaVersion.v80, InstFlags.Rd), + new(0x30000000, 0xF8000000, InstName.AddI, T.AddIT2, IsaVersion.v80, InstFlags.Rdn), + new(0x18000000, 0xFE000000, InstName.AddR, T.AddRT1, IsaVersion.v80, InstFlags.Rd), + new(0x44000000, 0xFF000000, rmRdndnConstraints, InstName.AddR, T.AddRT2, IsaVersion.v80, InstFlags.RdnDn), + new(0xA8000000, 0xF8000000, InstName.AddSpI, T.AddSpIT1, IsaVersion.v80, InstFlags.RdRd16), + new(0xB0000000, 0xFF800000, InstName.AddSpI, T.AddSpIT2, IsaVersion.v80, InstFlags.None), + new(0x44680000, 0xFF780000, InstName.AddSpR, T.AddSpRT1, IsaVersion.v80, InstFlags.None), + new(0x44850000, 0xFF870000, rmConstraints, InstName.AddSpR, T.AddSpRT2, IsaVersion.v80, InstFlags.None), + new(0xA0000000, 0xF8000000, InstName.Adr, T.AdrT1, IsaVersion.v80, InstFlags.RdRd16), + new(0x40000000, 0xFFC00000, InstName.AndR, T.AndRT1, IsaVersion.v80, InstFlags.Rdn), + new(0xD0000000, 0xF0000000, condCondConstraints, InstName.B, T.BT1, IsaVersion.v80, InstFlags.Cond), + new(0xE0000000, 0xF8000000, InstName.B, T.BT2, IsaVersion.v80, InstFlags.None), + new(0x43800000, 0xFFC00000, InstName.BicR, T.BicRT1, IsaVersion.v80, InstFlags.Rdn), + new(0xBE000000, 0xFF000000, InstName.Bkpt, T.BkptT1, IsaVersion.v80, InstFlags.None), + new(0x47800000, 0xFF870000, InstName.BlxR, T.BlxRT1, IsaVersion.v80, InstFlags.None), + new(0x47000000, 0xFF870000, InstName.Bx, T.BxT1, IsaVersion.v80, InstFlags.None), + new(0xB1000000, 0xF5000000, InstName.Cbnz, T.CbnzT1, IsaVersion.v80, InstFlags.None), + new(0x42C00000, 0xFFC00000, InstName.CmnR, T.CmnRT1, IsaVersion.v80, InstFlags.None), + new(0x28000000, 0xF8000000, InstName.CmpI, T.CmpIT1, IsaVersion.v80, InstFlags.None), + new(0x42800000, 0xFFC00000, InstName.CmpR, T.CmpRT1, IsaVersion.v80, InstFlags.None), + new(0x45000000, 0xFF000000, InstName.CmpR, T.CmpRT2, IsaVersion.v80, InstFlags.None), + new(0xB6600000, 0xFFE80000, InstName.Cps, T.CpsT1, IsaVersion.v80, InstFlags.None), + new(0x40400000, 0xFFC00000, InstName.EorR, T.EorRT1, IsaVersion.v80, InstFlags.Rdn), + new(0xBA800000, 0xFFC00000, InstName.Hlt, T.HltT1, IsaVersion.v80, InstFlags.None), + new(0xBF000000, 0xFF000000, maskConstraints, InstName.It, T.ItT1, IsaVersion.v80, InstFlags.None), + new(0xC8000000, 0xF8000000, InstName.Ldm, T.LdmT1, IsaVersion.v80, InstFlags.Rlist), + new(0x78000000, 0xF8000000, InstName.LdrbI, T.LdrbIT1, IsaVersion.v80, InstFlags.Rt), + new(0x5C000000, 0xFE000000, InstName.LdrbR, T.LdrbRT1, IsaVersion.v80, InstFlags.Rt), + new(0x88000000, 0xF8000000, InstName.LdrhI, T.LdrhIT1, IsaVersion.v80, InstFlags.Rt), + new(0x5A000000, 0xFE000000, InstName.LdrhR, T.LdrhRT1, IsaVersion.v80, InstFlags.Rt), + new(0x56000000, 0xFE000000, InstName.LdrsbR, T.LdrsbRT1, IsaVersion.v80, InstFlags.Rt), + new(0x5E000000, 0xFE000000, InstName.LdrshR, T.LdrshRT1, IsaVersion.v80, InstFlags.Rt), + new(0x68000000, 0xF8000000, InstName.LdrI, T.LdrIT1, IsaVersion.v80, InstFlags.Rt), + new(0x98000000, 0xF8000000, InstName.LdrI, T.LdrIT2, IsaVersion.v80, InstFlags.RtRd16), + new(0x48000000, 0xF8000000, InstName.LdrL, T.LdrLT1, IsaVersion.v80, InstFlags.RtRd16), + new(0x58000000, 0xFE000000, InstName.LdrR, T.LdrRT1, IsaVersion.v80, InstFlags.Rt), + new(0x20000000, 0xF8000000, InstName.MovI, T.MovIT1, IsaVersion.v80, InstFlags.RdRd16), + new(0x46000000, 0xFF000000, InstName.MovR, T.MovRT1, IsaVersion.v80, InstFlags.Rd), + new(0x00000000, 0xE0000000, opConstraints, InstName.MovR, T.MovRT2, IsaVersion.v80, InstFlags.Rd), + new(0x40000000, 0xFE000000, opOpOpOpConstraints, InstName.MovRr, T.MovRrT1, IsaVersion.v80, InstFlags.None), + new(0x43400000, 0xFFC00000, InstName.Mul, T.MulT1, IsaVersion.v80, InstFlags.None), + new(0x43C00000, 0xFFC00000, InstName.MvnR, T.MvnRT1, IsaVersion.v80, InstFlags.Rd), + new(0xBF000000, 0xFFFF0000, InstName.Nop, T.NopT1, IsaVersion.v80, InstFlags.None), + new(0x43000000, 0xFFC00000, InstName.OrrR, T.OrrRT1, IsaVersion.v80, InstFlags.Rdn), + new(0xBC000000, 0xFE000000, InstName.Pop, T.PopT1, IsaVersion.v80, InstFlags.Rlist), + new(0xB4000000, 0xFE000000, InstName.Push, T.PushT1, IsaVersion.v80, InstFlags.RlistRead), + new(0xBA000000, 0xFFC00000, InstName.Rev, T.RevT1, IsaVersion.v80, InstFlags.Rd), + new(0xBA400000, 0xFFC00000, InstName.Rev16, T.Rev16T1, IsaVersion.v80, InstFlags.Rd), + new(0xBAC00000, 0xFFC00000, InstName.Revsh, T.RevshT1, IsaVersion.v80, InstFlags.Rd), + new(0x42400000, 0xFFC00000, InstName.RsbI, T.RsbIT1, IsaVersion.v80, InstFlags.Rd), + new(0x41800000, 0xFFC00000, InstName.SbcR, T.SbcRT1, IsaVersion.v80, InstFlags.Rdn), + new(0xB6500000, 0xFFF70000, InstName.Setend, T.SetendT1, IsaVersion.v80, InstFlags.None), + new(0xB6100000, 0xFFF70000, InstName.Setpan, T.SetpanT1, IsaVersion.v81, IsaFeature.FeatPan, InstFlags.None), + new(0xBF400000, 0xFFFF0000, InstName.Sev, T.SevT1, IsaVersion.v80, InstFlags.None), + new(0xBF500000, 0xFFFF0000, InstName.Sevl, T.SevlT1, IsaVersion.v80, InstFlags.None), + new(0xC0000000, 0xF8000000, InstName.Stm, T.StmT1, IsaVersion.v80, InstFlags.RlistRead), + new(0x70000000, 0xF8000000, InstName.StrbI, T.StrbIT1, IsaVersion.v80, InstFlags.RtRead), + new(0x54000000, 0xFE000000, InstName.StrbR, T.StrbRT1, IsaVersion.v80, InstFlags.RtRead), + new(0x80000000, 0xF8000000, InstName.StrhI, T.StrhIT1, IsaVersion.v80, InstFlags.RtRead), + new(0x52000000, 0xFE000000, InstName.StrhR, T.StrhRT1, IsaVersion.v80, InstFlags.RtRead), + new(0x60000000, 0xF8000000, InstName.StrI, T.StrIT1, IsaVersion.v80, InstFlags.RtRead), + new(0x90000000, 0xF8000000, InstName.StrI, T.StrIT2, IsaVersion.v80, InstFlags.RtReadRd16), + new(0x50000000, 0xFE000000, InstName.StrR, T.StrRT1, IsaVersion.v80, InstFlags.RtRead), + new(0x1E000000, 0xFE000000, InstName.SubI, T.SubIT1, IsaVersion.v80, InstFlags.Rd), + new(0x38000000, 0xF8000000, InstName.SubI, T.SubIT2, IsaVersion.v80, InstFlags.Rdn), + new(0x1A000000, 0xFE000000, InstName.SubR, T.SubRT1, IsaVersion.v80, InstFlags.Rd), + new(0xB0800000, 0xFF800000, InstName.SubSpI, T.SubSpIT1, IsaVersion.v80, InstFlags.None), + new(0xDF000000, 0xFF000000, InstName.Svc, T.SvcT1, IsaVersion.v80, InstFlags.None), + new(0xB2400000, 0xFFC00000, InstName.Sxtb, T.SxtbT1, IsaVersion.v80, InstFlags.Rd), + new(0xB2000000, 0xFFC00000, InstName.Sxth, T.SxthT1, IsaVersion.v80, InstFlags.Rd), + new(0x42000000, 0xFFC00000, InstName.TstR, T.TstRT1, IsaVersion.v80, InstFlags.None), + new(0xDE000000, 0xFF000000, InstName.Udf, T.UdfT1, IsaVersion.v80, InstFlags.None), + new(0xB2C00000, 0xFFC00000, InstName.Uxtb, T.UxtbT1, IsaVersion.v80, InstFlags.Rd), + new(0xB2800000, 0xFFC00000, InstName.Uxth, T.UxthT1, IsaVersion.v80, InstFlags.Rd), + new(0xBF200000, 0xFFFF0000, InstName.Wfe, T.WfeT1, IsaVersion.v80, InstFlags.None), + new(0xBF300000, 0xFFFF0000, InstName.Wfi, T.WfiT1, IsaVersion.v80, InstFlags.None), + new(0xBF100000, 0xFFFF0000, InstName.Yield, T.YieldT1, IsaVersion.v80, InstFlags.None), + }; + + _table = new(insts); + } + + public static bool TryGetMeta(uint encoding, IsaVersion version, IsaFeature features, out InstMeta meta) + { + if (_table.TryFind(encoding, version, features, out InstInfoForTable info)) + { + meta = info.Meta; + + return true; + } + + meta = new(InstName.Udf, T.UdfA1, IsaVersion.v80, IsaFeature.None, InstFlags.None); + + return false; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT32.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT32.cs new file mode 100644 index 00000000..4a11effd --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT32.cs @@ -0,0 +1,1212 @@ +using Ryujinx.Cpu.LightningJit.Table; +using System.Collections.Generic; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + static class InstTableT32<T> where T : IInstEmit + { + private static readonly InstTableLevel<InstInfoForTable> _table; + + static InstTableT32() + { + InstEncoding[] rnRdsConstraints = new InstEncoding[] + { + new(0x000D0000, 0x000F0000), + new(0x00100F00, 0x00100F00), + }; + + InstEncoding[] rnRnConstraints = new InstEncoding[] + { + new(0x000D0000, 0x000F0000), + new(0x000F0000, 0x000F0000), + }; + + InstEncoding[] rdsConstraints = new InstEncoding[] + { + new(0x00100F00, 0x00100F00), + }; + + InstEncoding[] vdVmConstraints = new InstEncoding[] + { + new(0x00001000, 0x00001000), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] condCondCondConstraints = new InstEncoding[] + { + new(0x03800000, 0x03C00000), + new(0x03C00000, 0x03C00000), + new(0x03800000, 0x03800000), + }; + + InstEncoding[] rnConstraints = new InstEncoding[] + { + new(0x000F0000, 0x000F0000), + }; + + InstEncoding[] hConstraints = new InstEncoding[] + { + new(0x00000001, 0x00000001), + }; + + InstEncoding[] imodmConstraints = new InstEncoding[] + { + new(0x00000000, 0x00000700), + }; + + InstEncoding[] optionConstraints = new InstEncoding[] + { + new(0x00000000, 0x0000000F), + }; + + InstEncoding[] puwPwPuwPuwConstraints = new InstEncoding[] + { + new(0x00000000, 0x01A00000), + new(0x01000000, 0x01200000), + new(0x00200000, 0x01A00000), + new(0x01A00000, 0x01A00000), + }; + + InstEncoding[] rnPuwConstraints = new InstEncoding[] + { + new(0x000F0000, 0x000F0000), + new(0x00000000, 0x01A00000), + }; + + InstEncoding[] puwConstraints = new InstEncoding[] + { + new(0x00000000, 0x01A00000), + }; + + InstEncoding[] rnRtConstraints = new InstEncoding[] + { + new(0x000F0000, 0x000F0000), + new(0x0000F000, 0x0000F000), + }; + + InstEncoding[] rnRtpuwPuwPwConstraints = new InstEncoding[] + { + new(0x000F0000, 0x000F0000), + new(0x0000F400, 0x0000F700), + new(0x00000600, 0x00000700), + new(0x00000000, 0x00000500), + }; + + InstEncoding[] rtConstraints = new InstEncoding[] + { + new(0x0000F000, 0x0000F000), + }; + + InstEncoding[] rnPwConstraints = new InstEncoding[] + { + new(0x000F0000, 0x000F0000), + new(0x00000000, 0x01200000), + }; + + InstEncoding[] pwConstraints = new InstEncoding[] + { + new(0x00000000, 0x01200000), + }; + + InstEncoding[] rnPuwPwConstraints = new InstEncoding[] + { + new(0x000F0000, 0x000F0000), + new(0x00000600, 0x00000700), + new(0x00000000, 0x00000500), + }; + + InstEncoding[] raConstraints = new InstEncoding[] + { + new(0x0000F000, 0x0000F000), + }; + + InstEncoding[] sTConstraints = new InstEncoding[] + { + new(0x00100000, 0x00100000), + new(0x00000010, 0x00000010), + }; + + InstEncoding[] vdVnVmConstraints = new InstEncoding[] + { + new(0x00001000, 0x00001000), + new(0x00010000, 0x00010000), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] shimm2imm3Constraints = new InstEncoding[] + { + new(0x00200000, 0x002070C0), + }; + + InstEncoding[] rnimm8Constraints = new InstEncoding[] + { + new(0x000E0000, 0x000F00FF), + }; + + InstEncoding[] sizeQvdQvnQvmConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] sizeVdConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00001000, 0x00001000), + }; + + InstEncoding[] qvdQvnQvmConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] sizeQvdQvmConstraints = new InstEncoding[] + { + new(0x000C0000, 0x000C0000), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] sizeVnVmConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00010000, 0x00010000), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] sizeVdOpvnConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00001000, 0x00001000), + new(0x00010100, 0x00010100), + }; + + InstEncoding[] cmodeCmodeQvdConstraints = new InstEncoding[] + { + new(0x00000000, 0x00000100), + new(0x00000C00, 0x00000C00), + new(0x00001040, 0x00001040), + }; + + InstEncoding[] qvdQvnQvmOpConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + new(0x00000000, 0x00300000), + }; + + InstEncoding[] qvdQvnQvmSizeConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + new(0x00300000, 0x00300000), + }; + + InstEncoding[] qvdQvnConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + }; + + InstEncoding[] qvdQvmConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] sizeConstraints = new InstEncoding[] + { + new(0x00000000, 0x00000300), + }; + + InstEncoding[] vmConstraints = new InstEncoding[] + { + new(0x00000001, 0x00000001), + }; + + InstEncoding[] opvdOpvmConstraints = new InstEncoding[] + { + new(0x00001100, 0x00001100), + new(0x00000001, 0x00000101), + }; + + InstEncoding[] imm6Opimm6Imm6QvdQvmConstraints = new InstEncoding[] + { + new(0x00000000, 0x00380000), + new(0x00200000, 0x00300200), + new(0x00000000, 0x00200000), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] qvdEbConstraints = new InstEncoding[] + { + new(0x00210000, 0x00210000), + new(0x00400020, 0x00400020), + }; + + InstEncoding[] imm4QvdConstraints = new InstEncoding[] + { + new(0x00000000, 0x00070000), + new(0x00001040, 0x00001040), + }; + + InstEncoding[] qvdQvnQvmQimm4Constraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + new(0x00000800, 0x00000840), + }; + + InstEncoding[] qvdConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + }; + + InstEncoding[] vdVnConstraints = new InstEncoding[] + { + new(0x00001000, 0x00001000), + new(0x00010000, 0x00010000), + }; + + InstEncoding[] sizeConstraints2 = new InstEncoding[] + { + new(0x00000C00, 0x00000C00), + }; + + InstEncoding[] sizeIndexAlignIndexAlignConstraints = new InstEncoding[] + { + new(0x00000C00, 0x00000C00), + new(0x00000010, 0x00000030), + new(0x00000020, 0x00000030), + }; + + InstEncoding[] sizeSizeaConstraints = new InstEncoding[] + { + new(0x000000C0, 0x000000C0), + new(0x00000010, 0x000000D0), + }; + + InstEncoding[] alignConstraints = new InstEncoding[] + { + new(0x00000020, 0x00000020), + }; + + InstEncoding[] alignConstraints2 = new InstEncoding[] + { + new(0x00000030, 0x00000030), + }; + + InstEncoding[] sizeConstraints3 = new InstEncoding[] + { + new(0x000000C0, 0x000000C0), + }; + + InstEncoding[] alignSizeConstraints = new InstEncoding[] + { + new(0x00000030, 0x00000030), + new(0x000000C0, 0x000000C0), + }; + + InstEncoding[] sizeAConstraints = new InstEncoding[] + { + new(0x000000C0, 0x000000C0), + new(0x00000010, 0x00000010), + }; + + InstEncoding[] sizeAlignConstraints = new InstEncoding[] + { + new(0x000000C0, 0x000000C0), + new(0x00000020, 0x00000020), + }; + + InstEncoding[] sizeIndexAlignConstraints = new InstEncoding[] + { + new(0x00000C00, 0x00000C00), + new(0x00000030, 0x00000030), + }; + + InstEncoding[] sizeaConstraints = new InstEncoding[] + { + new(0x000000C0, 0x000000D0), + }; + + InstEncoding[] sizeSizeVdConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00000000, 0x00300000), + new(0x00001000, 0x00001000), + }; + + InstEncoding[] sizeQvdQvnConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x10001000, 0x10001000), + new(0x10010000, 0x10010000), + }; + + InstEncoding[] imm3hImm3hImm3hImm3hImm3hVdConstraints = new InstEncoding[] + { + new(0x00000000, 0x00380000), + new(0x00180000, 0x00380000), + new(0x00280000, 0x00380000), + new(0x00300000, 0x00380000), + new(0x00380000, 0x00380000), + new(0x00001000, 0x00001000), + }; + + InstEncoding[] sizeVmConstraints = new InstEncoding[] + { + new(0x000C0000, 0x000C0000), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] opc1opc2Constraints = new InstEncoding[] + { + new(0x00000040, 0x00400060), + }; + + InstEncoding[] uopc1opc2Uopc1opc2Constraints = new InstEncoding[] + { + new(0x00800000, 0x00C00060), + new(0x00000040, 0x00400060), + }; + + InstEncoding[] sizeOpuOpsizeVdConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x10000200, 0x10000200), + new(0x00100200, 0x00300200), + new(0x00001000, 0x00001000), + }; + + InstEncoding[] sizeOpsizeOpsizeQvdQvnQvmConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x10100000, 0x10300000), + new(0x10200000, 0x10300000), + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] cmodeQvdConstraints = new InstEncoding[] + { + new(0x00000E00, 0x00000E00), + new(0x00001040, 0x00001040), + }; + + InstEncoding[] qConstraints = new InstEncoding[] + { + new(0x00000040, 0x00000040), + }; + + InstEncoding[] sizeQConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00000040, 0x00000040), + }; + + InstEncoding[] sizeConstraints4 = new InstEncoding[] + { + new(0x00300000, 0x00300000), + }; + + InstEncoding[] qvdQvnQvmSizeSizeConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00010040, 0x00010040), + new(0x00000041, 0x00000041), + new(0x00000000, 0x00300000), + new(0x00300000, 0x00300000), + }; + + InstEncoding[] sizeSizeQvdQvnConstraints = new InstEncoding[] + { + new(0x00300000, 0x00300000), + new(0x00000000, 0x00300000), + new(0x10001000, 0x10001000), + new(0x10010000, 0x10010000), + }; + + InstEncoding[] opSizeVmConstraints = new InstEncoding[] + { + new(0x00000000, 0x000000C0), + new(0x000C0000, 0x000C0000), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] qvdQvmQvnConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + new(0x00010040, 0x00010040), + }; + + InstEncoding[] imm6UopVmConstraints = new InstEncoding[] + { + new(0x00000000, 0x00380000), + new(0x00000000, 0x10000100), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] imm6lUopQvdQvmConstraints = new InstEncoding[] + { + new(0x00000000, 0x00380080), + new(0x00000000, 0x10000100), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] qvdQvmSizeSizeConstraints = new InstEncoding[] + { + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + new(0x00000000, 0x000C0000), + new(0x000C0000, 0x000C0000), + }; + + InstEncoding[] sizeSizeSizeQvdQvmConstraints = new InstEncoding[] + { + new(0x00040000, 0x000C0000), + new(0x00080000, 0x000C0000), + new(0x000C0000, 0x000C0000), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] sizeSizeQvdQvmConstraints = new InstEncoding[] + { + new(0x00080000, 0x000C0000), + new(0x000C0000, 0x000C0000), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] imm6lQvdQvmConstraints = new InstEncoding[] + { + new(0x00000000, 0x00380080), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + InstEncoding[] imm6VmConstraints = new InstEncoding[] + { + new(0x00000000, 0x00380000), + new(0x00000001, 0x00000001), + }; + + InstEncoding[] imm6VdImm6Imm6Imm6Constraints = new InstEncoding[] + { + new(0x00000000, 0x00380000), + new(0x00001000, 0x00001000), + new(0x00080000, 0x003F0000), + new(0x00100000, 0x003F0000), + new(0x00200000, 0x003F0000), + }; + + InstEncoding[] sizeVdConstraints2 = new InstEncoding[] + { + new(0x000C0000, 0x000C0000), + new(0x00001000, 0x00001000), + }; + + InstEncoding[] sizeQsizeQvdQvmConstraints = new InstEncoding[] + { + new(0x000C0000, 0x000C0000), + new(0x00080000, 0x000C0040), + new(0x00001040, 0x00001040), + new(0x00000041, 0x00000041), + }; + + List<InstInfoForTable> insts = new() + { + new(0xF1400000, 0xFBE08000, InstName.AdcI, T.AdcIT1, IsaVersion.v80, InstFlags.Rd), + new(0xEB400000, 0xFFE08000, InstName.AdcR, T.AdcRT2, IsaVersion.v80, InstFlags.Rd), + new(0xF1000000, 0xFBE08000, rnRdsConstraints, InstName.AddI, T.AddIT3, IsaVersion.v80, InstFlags.Rd), + new(0xF2000000, 0xFBF08000, rnRnConstraints, InstName.AddI, T.AddIT4, IsaVersion.v80, InstFlags.Rd), + new(0xEB000000, 0xFFE08000, rnRdsConstraints, InstName.AddR, T.AddRT3, IsaVersion.v80, InstFlags.Rd), + new(0xF10D0000, 0xFBEF8000, rdsConstraints, InstName.AddSpI, T.AddSpIT3, IsaVersion.v80, InstFlags.Rd), + new(0xF20D0000, 0xFBFF8000, InstName.AddSpI, T.AddSpIT4, IsaVersion.v80, InstFlags.Rd), + new(0xEB0D0000, 0xFFEF8000, rdsConstraints, InstName.AddSpR, T.AddSpRT3, IsaVersion.v80, InstFlags.Rd), + new(0xF2AF0000, 0xFBFF8000, InstName.Adr, T.AdrT2, IsaVersion.v80, InstFlags.Rd), + new(0xF20F0000, 0xFBFF8000, InstName.Adr, T.AdrT3, IsaVersion.v80, InstFlags.Rd), + new(0xFFB00340, 0xFFBF0FD0, vdVmConstraints, InstName.Aesd, T.AesdT1, IsaVersion.v80, IsaFeature.FeatAes, InstFlags.None), + new(0xFFB00300, 0xFFBF0FD0, vdVmConstraints, InstName.Aese, T.AeseT1, IsaVersion.v80, IsaFeature.FeatAes, InstFlags.None), + new(0xFFB003C0, 0xFFBF0FD0, vdVmConstraints, InstName.Aesimc, T.AesimcT1, IsaVersion.v80, IsaFeature.FeatAes, InstFlags.None), + new(0xFFB00380, 0xFFBF0FD0, vdVmConstraints, InstName.Aesmc, T.AesmcT1, IsaVersion.v80, IsaFeature.FeatAes, InstFlags.None), + new(0xF0000000, 0xFBE08000, rdsConstraints, InstName.AndI, T.AndIT1, IsaVersion.v80, InstFlags.Rd), + new(0xEA000000, 0xFFE08000, rdsConstraints, InstName.AndR, T.AndRT2, IsaVersion.v80, InstFlags.Rd), + new(0xF0008000, 0xF800D000, condCondCondConstraints, InstName.B, T.BT3, IsaVersion.v80, InstFlags.Cond), + new(0xF0009000, 0xF800D000, InstName.B, T.BT4, IsaVersion.v80, InstFlags.None), + new(0xF36F0000, 0xFFFF8020, InstName.Bfc, T.BfcT1, IsaVersion.v80, InstFlags.Rd), + new(0xF3600000, 0xFFF08020, rnConstraints, InstName.Bfi, T.BfiT1, IsaVersion.v80, InstFlags.Rd), + new(0xF0200000, 0xFBE08000, InstName.BicI, T.BicIT1, IsaVersion.v80, InstFlags.Rd), + new(0xEA200000, 0xFFE08000, InstName.BicR, T.BicRT2, IsaVersion.v80, InstFlags.Rd), + new(0xF000D000, 0xF800D000, InstName.BlI, T.BlIT1, IsaVersion.v80, InstFlags.None), + new(0xF000C000, 0xF800D000, hConstraints, InstName.BlI, T.BlIT2, IsaVersion.v80, InstFlags.None), + new(0xF3C08F00, 0xFFF0FFFF, InstName.Bxj, T.BxjT1, IsaVersion.v80, InstFlags.None), + new(0xF3AF8016, 0xFFFFFFFF, InstName.Clrbhb, T.ClrbhbT1, IsaVersion.v89, IsaFeature.FeatClrbhb, InstFlags.None), + new(0xF3BF8F2F, 0xFFFFFFFF, InstName.Clrex, T.ClrexT1, IsaVersion.v80, InstFlags.None), + new(0xFAB0F080, 0xFFF0F0F0, InstName.Clz, T.ClzT1, IsaVersion.v80, InstFlags.Rd), + new(0xF1100F00, 0xFBF08F00, InstName.CmnI, T.CmnIT1, IsaVersion.v80, InstFlags.None), + new(0xEB100F00, 0xFFF08F00, InstName.CmnR, T.CmnRT2, IsaVersion.v80, InstFlags.None), + new(0xF1B00F00, 0xFBF08F00, InstName.CmpI, T.CmpIT2, IsaVersion.v80, InstFlags.None), + new(0xEBB00F00, 0xFFF08F00, InstName.CmpR, T.CmpRT3, IsaVersion.v80, InstFlags.None), + new(0xF3AF8000, 0xFFFFF800, imodmConstraints, InstName.Cps, T.CpsT2, IsaVersion.v80, InstFlags.None), + new(0xFAC0F080, 0xFFF0F0C0, InstName.Crc32, T.Crc32T1, IsaVersion.v80, IsaFeature.FeatCrc32, InstFlags.Rd), + new(0xFAD0F080, 0xFFF0F0C0, InstName.Crc32c, T.Crc32cT1, IsaVersion.v80, IsaFeature.FeatCrc32, InstFlags.Rd), + new(0xF3AF8014, 0xFFFFFFFF, InstName.Csdb, T.CsdbT1, IsaVersion.v80, InstFlags.None), + new(0xF3AF80F0, 0xFFFFFFF0, InstName.Dbg, T.DbgT1, IsaVersion.v80, InstFlags.None), + new(0xF78F8001, 0xFFFFFFFF, InstName.Dcps1, T.Dcps1T1, IsaVersion.v80, InstFlags.None), + new(0xF78F8002, 0xFFFFFFFF, InstName.Dcps2, T.Dcps2T1, IsaVersion.v80, InstFlags.None), + new(0xF78F8003, 0xFFFFFFFF, InstName.Dcps3, T.Dcps3T1, IsaVersion.v80, InstFlags.None), + new(0xF3BF8F50, 0xFFFFFFF0, InstName.Dmb, T.DmbT1, IsaVersion.v80, InstFlags.None), + new(0xF3BF8F40, 0xFFFFFFF0, optionConstraints, InstName.Dsb, T.DsbT1, IsaVersion.v80, InstFlags.None), + new(0xF0800000, 0xFBE08000, rdsConstraints, InstName.EorI, T.EorIT1, IsaVersion.v80, InstFlags.Rd), + new(0xEA800000, 0xFFE08000, rdsConstraints, InstName.EorR, T.EorRT2, IsaVersion.v80, InstFlags.Rd), + new(0xF3DE8F00, 0xFFFFFFFF, InstName.Eret, T.EretT1, IsaVersion.v80, InstFlags.None), + new(0xF3AF8010, 0xFFFFFFFF, InstName.Esb, T.EsbT1, IsaVersion.v82, IsaFeature.FeatRas, InstFlags.None), + new(0xEC100B01, 0xFE100F01, puwPwPuwPuwConstraints, InstName.Fldmx, T.FldmxT1, IsaVersion.v80, InstFlags.WBack), + new(0xEC000B01, 0xFE100F01, puwPwPuwPuwConstraints, InstName.Fstmx, T.FstmxT1, IsaVersion.v80, InstFlags.WBack), + new(0xF7E08000, 0xFFF0F000, InstName.Hvc, T.HvcT1, IsaVersion.v80, InstFlags.None), + new(0xF3BF8F60, 0xFFFFFFF0, InstName.Isb, T.IsbT1, IsaVersion.v80, InstFlags.None), + new(0xE8D00FAF, 0xFFF00FFF, InstName.Lda, T.LdaT1, IsaVersion.v80, InstFlags.Rt), + new(0xE8D00F8F, 0xFFF00FFF, InstName.Ldab, T.LdabT1, IsaVersion.v80, InstFlags.Rt), + new(0xE8D00FEF, 0xFFF00FFF, InstName.Ldaex, T.LdaexT1, IsaVersion.v80, InstFlags.Rt), + new(0xE8D00FCF, 0xFFF00FFF, InstName.Ldaexb, T.LdaexbT1, IsaVersion.v80, InstFlags.Rt), + new(0xE8D000FF, 0xFFF000FF, InstName.Ldaexd, T.LdaexdT1, IsaVersion.v80, InstFlags.RtRt2), + new(0xE8D00FDF, 0xFFF00FFF, InstName.Ldaexh, T.LdaexhT1, IsaVersion.v80, InstFlags.Rt), + new(0xE8D00F9F, 0xFFF00FFF, InstName.Ldah, T.LdahT1, IsaVersion.v80, InstFlags.Rt), + new(0xEC105E00, 0xFE50FF00, rnPuwConstraints, InstName.LdcI, T.LdcIT1, IsaVersion.v80, InstFlags.WBack), + new(0xEC1F5E00, 0xFE5FFF00, puwConstraints, InstName.LdcL, T.LdcLT1, IsaVersion.v80, InstFlags.WBack), + new(0xE8900000, 0xFFD00000, InstName.Ldm, T.LdmT2, IsaVersion.v80, InstFlags.RlistWBack), + new(0xE9100000, 0xFFD00000, InstName.Ldmdb, T.LdmdbT1, IsaVersion.v80, InstFlags.RlistWBack), + new(0xF8100E00, 0xFFF00F00, rnConstraints, InstName.Ldrbt, T.LdrbtT1, IsaVersion.v80, InstFlags.Rt), + new(0xF8900000, 0xFFF00000, rnRtConstraints, InstName.LdrbI, T.LdrbIT2, IsaVersion.v80, InstFlags.Rt), + new(0xF8100800, 0xFFF00800, rnRtpuwPuwPwConstraints, InstName.LdrbI, T.LdrbIT3, IsaVersion.v80, InstFlags.RtWBack), + new(0xF81F0000, 0xFF7F0000, rtConstraints, InstName.LdrbL, T.LdrbLT1, IsaVersion.v80, InstFlags.Rt), + new(0xF8100000, 0xFFF00FC0, rnRtConstraints, InstName.LdrbR, T.LdrbRT2, IsaVersion.v80, InstFlags.Rt), + new(0xE8500000, 0xFE500000, rnPwConstraints, InstName.LdrdI, T.LdrdIT1, IsaVersion.v80, InstFlags.Rt2WBack), + new(0xE85F0000, 0xFE5F0000, pwConstraints, InstName.LdrdL, T.LdrdLT1, IsaVersion.v80, InstFlags.Rt2WBack), + new(0xE8500F00, 0xFFF00F00, InstName.Ldrex, T.LdrexT1, IsaVersion.v80, InstFlags.Rt), + new(0xE8D00F4F, 0xFFF00FFF, InstName.Ldrexb, T.LdrexbT1, IsaVersion.v80, InstFlags.Rt), + new(0xE8D0007F, 0xFFF000FF, InstName.Ldrexd, T.LdrexdT1, IsaVersion.v80, InstFlags.RtRt2), + new(0xE8D00F5F, 0xFFF00FFF, InstName.Ldrexh, T.LdrexhT1, IsaVersion.v80, InstFlags.Rt), + new(0xF8300E00, 0xFFF00F00, rnConstraints, InstName.Ldrht, T.LdrhtT1, IsaVersion.v80, InstFlags.Rt), + new(0xF8B00000, 0xFFF00000, rnRtConstraints, InstName.LdrhI, T.LdrhIT2, IsaVersion.v80, InstFlags.Rt), + new(0xF8300800, 0xFFF00800, rnRtpuwPuwPwConstraints, InstName.LdrhI, T.LdrhIT3, IsaVersion.v80, InstFlags.RtWBack), + new(0xF83F0000, 0xFF7F0000, rtConstraints, InstName.LdrhL, T.LdrhLT1, IsaVersion.v80, InstFlags.Rt), + new(0xF8300000, 0xFFF00FC0, rnRtConstraints, InstName.LdrhR, T.LdrhRT2, IsaVersion.v80, InstFlags.Rt), + new(0xF9100E00, 0xFFF00F00, rnConstraints, InstName.Ldrsbt, T.LdrsbtT1, IsaVersion.v80, InstFlags.Rt), + new(0xF9900000, 0xFFF00000, rnRtConstraints, InstName.LdrsbI, T.LdrsbIT1, IsaVersion.v80, InstFlags.Rt), + new(0xF9100800, 0xFFF00800, rnRtpuwPuwPwConstraints, InstName.LdrsbI, T.LdrsbIT2, IsaVersion.v80, InstFlags.RtWBack), + new(0xF91F0000, 0xFF7F0000, rtConstraints, InstName.LdrsbL, T.LdrsbLT1, IsaVersion.v80, InstFlags.Rt), + new(0xF9100000, 0xFFF00FC0, rnRtConstraints, InstName.LdrsbR, T.LdrsbRT2, IsaVersion.v80, InstFlags.Rt), + new(0xF9300E00, 0xFFF00F00, rnConstraints, InstName.Ldrsht, T.LdrshtT1, IsaVersion.v80, InstFlags.Rt), + new(0xF9B00000, 0xFFF00000, rnRtConstraints, InstName.LdrshI, T.LdrshIT1, IsaVersion.v80, InstFlags.Rt), + new(0xF9300800, 0xFFF00800, rnRtpuwPuwPwConstraints, InstName.LdrshI, T.LdrshIT2, IsaVersion.v80, InstFlags.RtWBack), + new(0xF93F0000, 0xFF7F0000, rtConstraints, InstName.LdrshL, T.LdrshLT1, IsaVersion.v80, InstFlags.Rt), + new(0xF9300000, 0xFFF00FC0, rnRtConstraints, InstName.LdrshR, T.LdrshRT2, IsaVersion.v80, InstFlags.Rt), + new(0xF8500E00, 0xFFF00F00, rnConstraints, InstName.Ldrt, T.LdrtT1, IsaVersion.v80, InstFlags.Rt), + new(0xF8D00000, 0xFFF00000, rnConstraints, InstName.LdrI, T.LdrIT3, IsaVersion.v80, InstFlags.Rt), + new(0xF8500800, 0xFFF00800, rnPuwPwConstraints, InstName.LdrI, T.LdrIT4, IsaVersion.v80, InstFlags.RtWBack), + new(0xF85F0000, 0xFF7F0000, InstName.LdrL, T.LdrLT2, IsaVersion.v80, InstFlags.Rt), + new(0xF8500000, 0xFFF00FC0, rnConstraints, InstName.LdrR, T.LdrRT2, IsaVersion.v80, InstFlags.Rt), + new(0xEE000E10, 0xFF100E10, InstName.Mcr, T.McrT1, IsaVersion.v80, InstFlags.Rt), + new(0xEC400E00, 0xFFF00E00, InstName.Mcrr, T.McrrT1, IsaVersion.v80, InstFlags.Rt), + new(0xFB000000, 0xFFF000F0, raConstraints, InstName.Mla, T.MlaT1, IsaVersion.v80, InstFlags.Rd), + new(0xFB000010, 0xFFF000F0, InstName.Mls, T.MlsT1, IsaVersion.v80, InstFlags.Rd), + new(0xF2C00000, 0xFBF08000, InstName.Movt, T.MovtT1, IsaVersion.v80, InstFlags.Rd), + new(0xF04F0000, 0xFBEF8000, InstName.MovI, T.MovIT2, IsaVersion.v80, InstFlags.Rd), + new(0xF2400000, 0xFBF08000, InstName.MovI, T.MovIT3, IsaVersion.v80, InstFlags.Rd), + new(0xEA4F0000, 0xFFEF8000, InstName.MovR, T.MovRT3, IsaVersion.v80, InstFlags.Rd), + new(0xFA00F000, 0xFF80F0F0, InstName.MovRr, T.MovRrT2, IsaVersion.v80, InstFlags.Rd), + new(0xEE100E10, 0xFF100E10, InstName.Mrc, T.MrcT1, IsaVersion.v80, InstFlags.Rt), + new(0xEC500E00, 0xFFF00E00, InstName.Mrrc, T.MrrcT1, IsaVersion.v80, InstFlags.Rt), + new(0xF3EF8000, 0xFFEFF0FF, InstName.Mrs, T.MrsT1, IsaVersion.v80, InstFlags.Rd), + new(0xF3E08020, 0xFFE0F0EF, InstName.MrsBr, T.MrsBrT1, IsaVersion.v80, InstFlags.Rd), + new(0xF3808020, 0xFFE0F0EF, InstName.MsrBr, T.MsrBrT1, IsaVersion.v80, InstFlags.None), + new(0xF3808000, 0xFFE0F0FF, InstName.MsrR, T.MsrRT1, IsaVersion.v80, InstFlags.None), + new(0xFB00F000, 0xFFF0F0F0, InstName.Mul, T.MulT2, IsaVersion.v80, InstFlags.Rd), + new(0xF06F0000, 0xFBEF8000, InstName.MvnI, T.MvnIT1, IsaVersion.v80, InstFlags.Rd), + new(0xEA6F0000, 0xFFEF8000, InstName.MvnR, T.MvnRT2, IsaVersion.v80, InstFlags.Rd), + new(0xF3AF8000, 0xFFFFFFFF, InstName.Nop, T.NopT2, IsaVersion.v80, InstFlags.None), + new(0xF0600000, 0xFBE08000, rnConstraints, InstName.OrnI, T.OrnIT1, IsaVersion.v80, InstFlags.Rd), + new(0xEA600000, 0xFFE08000, rnConstraints, InstName.OrnR, T.OrnRT1, IsaVersion.v80, InstFlags.Rd), + new(0xF0400000, 0xFBE08000, rnConstraints, InstName.OrrI, T.OrrIT1, IsaVersion.v80, InstFlags.Rd), + new(0xEA400000, 0xFFE08000, rnConstraints, InstName.OrrR, T.OrrRT2, IsaVersion.v80, InstFlags.Rd), + new(0xEAC00000, 0xFFF08010, sTConstraints, InstName.Pkh, T.PkhT1, IsaVersion.v80, InstFlags.Rd), + new(0xF890F000, 0xFFD0F000, rnConstraints, InstName.PldI, T.PldIT1, IsaVersion.v80, InstFlags.WBack), + new(0xF810FC00, 0xFFD0FF00, rnConstraints, InstName.PldI, T.PldIT2, IsaVersion.v80, InstFlags.WBack), + new(0xF81FF000, 0xFF7FF000, InstName.PldL, T.PldLT1, IsaVersion.v80, InstFlags.None), + new(0xF810F000, 0xFFD0FFC0, rnConstraints, InstName.PldR, T.PldRT1, IsaVersion.v80, InstFlags.WBack), + new(0xF990F000, 0xFFF0F000, rnConstraints, InstName.PliI, T.PliIT1, IsaVersion.v80, InstFlags.None), + new(0xF910FC00, 0xFFF0FF00, rnConstraints, InstName.PliI, T.PliIT2, IsaVersion.v80, InstFlags.None), + new(0xF91FF000, 0xFF7FF000, InstName.PliI, T.PliIT3, IsaVersion.v80, InstFlags.None), + new(0xF910F000, 0xFFF0FFC0, rnConstraints, InstName.PliR, T.PliRT1, IsaVersion.v80, InstFlags.None), + new(0xF3BF8F44, 0xFFFFFFFF, InstName.Pssbb, T.PssbbT1, IsaVersion.v80, InstFlags.None), + new(0xFA80F080, 0xFFF0F0F0, InstName.Qadd, T.QaddT1, IsaVersion.v80, InstFlags.Rd), + new(0xFA90F010, 0xFFF0F0F0, InstName.Qadd16, T.Qadd16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFA80F010, 0xFFF0F0F0, InstName.Qadd8, T.Qadd8T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAA0F010, 0xFFF0F0F0, InstName.Qasx, T.QasxT1, IsaVersion.v80, InstFlags.Rd), + new(0xFA80F090, 0xFFF0F0F0, InstName.Qdadd, T.QdaddT1, IsaVersion.v80, InstFlags.Rd), + new(0xFA80F0B0, 0xFFF0F0F0, InstName.Qdsub, T.QdsubT1, IsaVersion.v80, InstFlags.Rd), + new(0xFAE0F010, 0xFFF0F0F0, InstName.Qsax, T.QsaxT1, IsaVersion.v80, InstFlags.Rd), + new(0xFA80F0A0, 0xFFF0F0F0, InstName.Qsub, T.QsubT1, IsaVersion.v80, InstFlags.Rd), + new(0xFAD0F010, 0xFFF0F0F0, InstName.Qsub16, T.Qsub16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAC0F010, 0xFFF0F0F0, InstName.Qsub8, T.Qsub8T1, IsaVersion.v80, InstFlags.Rd), + new(0xFA90F0A0, 0xFFF0F0F0, InstName.Rbit, T.RbitT1, IsaVersion.v80, InstFlags.Rd), + new(0xFA90F080, 0xFFF0F0F0, InstName.Rev, T.RevT2, IsaVersion.v80, InstFlags.Rd), + new(0xFA90F090, 0xFFF0F0F0, InstName.Rev16, T.Rev16T2, IsaVersion.v80, InstFlags.Rd), + new(0xFA90F0B0, 0xFFF0F0F0, InstName.Revsh, T.RevshT2, IsaVersion.v80, InstFlags.Rd), + new(0xE810C000, 0xFFD0FFFF, InstName.Rfe, T.RfeT1, IsaVersion.v80, InstFlags.WBack), + new(0xE990C000, 0xFFD0FFFF, InstName.Rfe, T.RfeT2, IsaVersion.v80, InstFlags.WBack), + new(0xF1C00000, 0xFBE08000, InstName.RsbI, T.RsbIT2, IsaVersion.v80, InstFlags.Rd), + new(0xEBC00000, 0xFFE08000, InstName.RsbR, T.RsbRT1, IsaVersion.v80, InstFlags.Rd), + new(0xFA90F000, 0xFFF0F0F0, InstName.Sadd16, T.Sadd16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFA80F000, 0xFFF0F0F0, InstName.Sadd8, T.Sadd8T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAA0F000, 0xFFF0F0F0, InstName.Sasx, T.SasxT1, IsaVersion.v80, InstFlags.Rd), + new(0xF3BF8F70, 0xFFFFFFFF, InstName.Sb, T.SbT1, IsaVersion.v85, IsaFeature.FeatSb, InstFlags.None), + new(0xF1600000, 0xFBE08000, InstName.SbcI, T.SbcIT1, IsaVersion.v80, InstFlags.Rd), + new(0xEB600000, 0xFFE08000, InstName.SbcR, T.SbcRT2, IsaVersion.v80, InstFlags.Rd), + new(0xF3400000, 0xFFF08020, InstName.Sbfx, T.SbfxT1, IsaVersion.v80, InstFlags.Rd), + new(0xFB90F0F0, 0xFFF0F0F0, InstName.Sdiv, T.SdivT1, IsaVersion.v80, InstFlags.Rd), + new(0xFAA0F080, 0xFFF0F0F0, InstName.Sel, T.SelT1, IsaVersion.v80, InstFlags.Rd), + new(0xF3AF8004, 0xFFFFFFFF, InstName.Sev, T.SevT2, IsaVersion.v80, InstFlags.None), + new(0xF3AF8005, 0xFFFFFFFF, InstName.Sevl, T.SevlT2, IsaVersion.v80, InstFlags.None), + new(0xEF000C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha1c, T.Sha1cT1, IsaVersion.v80, IsaFeature.FeatSha1, InstFlags.None), + new(0xFFB902C0, 0xFFBF0FD0, vdVmConstraints, InstName.Sha1h, T.Sha1hT1, IsaVersion.v80, IsaFeature.FeatSha1, InstFlags.None), + new(0xEF200C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha1m, T.Sha1mT1, IsaVersion.v80, IsaFeature.FeatSha1, InstFlags.None), + new(0xEF100C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha1p, T.Sha1pT1, IsaVersion.v80, IsaFeature.FeatSha1, InstFlags.None), + new(0xEF300C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha1su0, T.Sha1su0T1, IsaVersion.v80, IsaFeature.FeatSha1, InstFlags.None), + new(0xFFBA0380, 0xFFBF0FD0, vdVmConstraints, InstName.Sha1su1, T.Sha1su1T1, IsaVersion.v80, IsaFeature.FeatSha1, InstFlags.None), + new(0xFF000C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha256h, T.Sha256hT1, IsaVersion.v80, IsaFeature.FeatSha256, InstFlags.None), + new(0xFF100C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha256h2, T.Sha256h2T1, IsaVersion.v80, IsaFeature.FeatSha256, InstFlags.None), + new(0xFFBA03C0, 0xFFBF0FD0, vdVmConstraints, InstName.Sha256su0, T.Sha256su0T1, IsaVersion.v80, IsaFeature.FeatSha256, InstFlags.None), + new(0xFF200C40, 0xFFB00F50, vdVnVmConstraints, InstName.Sha256su1, T.Sha256su1T1, IsaVersion.v80, IsaFeature.FeatSha256, InstFlags.None), + new(0xFA90F020, 0xFFF0F0F0, InstName.Shadd16, T.Shadd16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFA80F020, 0xFFF0F0F0, InstName.Shadd8, T.Shadd8T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAA0F020, 0xFFF0F0F0, InstName.Shasx, T.ShasxT1, IsaVersion.v80, InstFlags.Rd), + new(0xFAE0F020, 0xFFF0F0F0, InstName.Shsax, T.ShsaxT1, IsaVersion.v80, InstFlags.Rd), + new(0xFAD0F020, 0xFFF0F0F0, InstName.Shsub16, T.Shsub16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAC0F020, 0xFFF0F0F0, InstName.Shsub8, T.Shsub8T1, IsaVersion.v80, InstFlags.Rd), + new(0xF7F08000, 0xFFF0FFFF, InstName.Smc, T.SmcT1, IsaVersion.v80, InstFlags.None), + new(0xFB100000, 0xFFF000C0, raConstraints, InstName.Smlabb, T.SmlabbT1, IsaVersion.v80, InstFlags.Rd), + new(0xFB200000, 0xFFF000E0, raConstraints, InstName.Smlad, T.SmladT1, IsaVersion.v80, InstFlags.Rd), + new(0xFBC00000, 0xFFF000F0, InstName.Smlal, T.SmlalT1, IsaVersion.v80, InstFlags.RdLoRdHi), + new(0xFBC00080, 0xFFF000C0, InstName.Smlalbb, T.SmlalbbT1, IsaVersion.v80, InstFlags.RdLoRdHi), + new(0xFBC000C0, 0xFFF000E0, InstName.Smlald, T.SmlaldT1, IsaVersion.v80, InstFlags.RdLoRdHi), + new(0xFB300000, 0xFFF000E0, raConstraints, InstName.Smlawb, T.SmlawbT1, IsaVersion.v80, InstFlags.Rd), + new(0xFB400000, 0xFFF000E0, raConstraints, InstName.Smlsd, T.SmlsdT1, IsaVersion.v80, InstFlags.Rd), + new(0xFBD000C0, 0xFFF000E0, InstName.Smlsld, T.SmlsldT1, IsaVersion.v80, InstFlags.RdLoRdHi), + new(0xFB500000, 0xFFF000E0, raConstraints, InstName.Smmla, T.SmmlaT1, IsaVersion.v80, InstFlags.Rd), + new(0xFB600000, 0xFFF000E0, InstName.Smmls, T.SmmlsT1, IsaVersion.v80, InstFlags.Rd), + new(0xFB50F000, 0xFFF0F0E0, InstName.Smmul, T.SmmulT1, IsaVersion.v80, InstFlags.Rd), + new(0xFB20F000, 0xFFF0F0E0, InstName.Smuad, T.SmuadT1, IsaVersion.v80, InstFlags.Rd), + new(0xFB10F000, 0xFFF0F0C0, InstName.Smulbb, T.SmulbbT1, IsaVersion.v80, InstFlags.Rd), + new(0xFB800000, 0xFFF000F0, InstName.Smull, T.SmullT1, IsaVersion.v80, InstFlags.RdLoRdHi), + new(0xFB30F000, 0xFFF0F0E0, InstName.Smulwb, T.SmulwbT1, IsaVersion.v80, InstFlags.Rd), + new(0xFB40F000, 0xFFF0F0E0, InstName.Smusd, T.SmusdT1, IsaVersion.v80, InstFlags.Rd), + new(0xE80DC000, 0xFFDFFFE0, InstName.Srs, T.SrsT1, IsaVersion.v80, InstFlags.WBack), + new(0xE98DC000, 0xFFDFFFE0, InstName.Srs, T.SrsT2, IsaVersion.v80, InstFlags.WBack), + new(0xF3000000, 0xFFD08020, shimm2imm3Constraints, InstName.Ssat, T.SsatT1, IsaVersion.v80, InstFlags.Rd), + new(0xF3200000, 0xFFF0F0F0, InstName.Ssat16, T.Ssat16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAE0F000, 0xFFF0F0F0, InstName.Ssax, T.SsaxT1, IsaVersion.v80, InstFlags.Rd), + new(0xF3BF8F40, 0xFFFFFFFF, InstName.Ssbb, T.SsbbT1, IsaVersion.v80, InstFlags.None), + new(0xFAD0F000, 0xFFF0F0F0, InstName.Ssub16, T.Ssub16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAC0F000, 0xFFF0F0F0, InstName.Ssub8, T.Ssub8T1, IsaVersion.v80, InstFlags.Rd), + new(0xEC005E00, 0xFE50FF00, puwConstraints, InstName.Stc, T.StcT1, IsaVersion.v80, InstFlags.WBack), + new(0xE8C00FAF, 0xFFF00FFF, InstName.Stl, T.StlT1, IsaVersion.v80, InstFlags.RtRead), + new(0xE8C00F8F, 0xFFF00FFF, InstName.Stlb, T.StlbT1, IsaVersion.v80, InstFlags.RtRead), + new(0xE8C00FE0, 0xFFF00FF0, InstName.Stlex, T.StlexT1, IsaVersion.v80, InstFlags.RdRtReadRd16), + new(0xE8C00FC0, 0xFFF00FF0, InstName.Stlexb, T.StlexbT1, IsaVersion.v80, InstFlags.RdRtReadRd16), + new(0xE8C000F0, 0xFFF000F0, InstName.Stlexd, T.StlexdT1, IsaVersion.v80, InstFlags.RdRt2ReadRd16), + new(0xE8C00FD0, 0xFFF00FF0, InstName.Stlexh, T.StlexhT1, IsaVersion.v80, InstFlags.RdRtReadRd16), + new(0xE8C00F9F, 0xFFF00FFF, InstName.Stlh, T.StlhT1, IsaVersion.v80, InstFlags.RtRead), + new(0xE8800000, 0xFFD08000, InstName.Stm, T.StmT2, IsaVersion.v80, InstFlags.RlistReadWBack), + new(0xE9000000, 0xFFD08000, InstName.Stmdb, T.StmdbT1, IsaVersion.v80, InstFlags.RlistReadWBack), + new(0xF8000E00, 0xFFF00F00, rnConstraints, InstName.Strbt, T.StrbtT1, IsaVersion.v80, InstFlags.RtRead), + new(0xF8800000, 0xFFF00000, rnConstraints, InstName.StrbI, T.StrbIT2, IsaVersion.v80, InstFlags.RtRead), + new(0xF8000800, 0xFFF00800, rnPuwPwConstraints, InstName.StrbI, T.StrbIT3, IsaVersion.v80, InstFlags.RtReadWBack), + new(0xF8000000, 0xFFF00FC0, rnConstraints, InstName.StrbR, T.StrbRT2, IsaVersion.v80, InstFlags.RtRead), + new(0xE8400000, 0xFE500000, rnPwConstraints, InstName.StrdI, T.StrdIT1, IsaVersion.v80, InstFlags.Rt2ReadWBack), + new(0xE8400000, 0xFFF00000, InstName.Strex, T.StrexT1, IsaVersion.v80, InstFlags.RdRtRead), + new(0xE8C00F40, 0xFFF00FF0, InstName.Strexb, T.StrexbT1, IsaVersion.v80, InstFlags.RdRtReadRd16), + new(0xE8C00070, 0xFFF000F0, InstName.Strexd, T.StrexdT1, IsaVersion.v80, InstFlags.RdRt2ReadRd16), + new(0xE8C00F50, 0xFFF00FF0, InstName.Strexh, T.StrexhT1, IsaVersion.v80, InstFlags.RdRtReadRd16), + new(0xF8200E00, 0xFFF00F00, rnConstraints, InstName.Strht, T.StrhtT1, IsaVersion.v80, InstFlags.RtRead), + new(0xF8A00000, 0xFFF00000, rnConstraints, InstName.StrhI, T.StrhIT2, IsaVersion.v80, InstFlags.RtRead), + new(0xF8200800, 0xFFF00800, rnPuwPwConstraints, InstName.StrhI, T.StrhIT3, IsaVersion.v80, InstFlags.RtReadWBack), + new(0xF8200000, 0xFFF00FC0, rnConstraints, InstName.StrhR, T.StrhRT2, IsaVersion.v80, InstFlags.RtRead), + new(0xF8400E00, 0xFFF00F00, rnConstraints, InstName.Strt, T.StrtT1, IsaVersion.v80, InstFlags.RtRead), + new(0xF8C00000, 0xFFF00000, rnConstraints, InstName.StrI, T.StrIT3, IsaVersion.v80, InstFlags.RtRead), + new(0xF8400800, 0xFFF00800, rnPuwPwConstraints, InstName.StrI, T.StrIT4, IsaVersion.v80, InstFlags.RtReadWBack), + new(0xF8400000, 0xFFF00FC0, rnConstraints, InstName.StrR, T.StrRT2, IsaVersion.v80, InstFlags.RtRead), + new(0xF1A00000, 0xFBE08000, rnRdsConstraints, InstName.SubI, T.SubIT3, IsaVersion.v80, InstFlags.Rd), + new(0xF2A00000, 0xFBF08000, rnRnConstraints, InstName.SubI, T.SubIT4, IsaVersion.v80, InstFlags.Rd), + new(0xF3D08F00, 0xFFF0FF00, rnimm8Constraints, InstName.SubI, T.SubIT5, IsaVersion.v80, InstFlags.None), + new(0xEBA00000, 0xFFE08000, rnRdsConstraints, InstName.SubR, T.SubRT2, IsaVersion.v80, InstFlags.Rd), + new(0xF1AD0000, 0xFBEF8000, rdsConstraints, InstName.SubSpI, T.SubSpIT2, IsaVersion.v80, InstFlags.Rd), + new(0xF2AD0000, 0xFBFF8000, InstName.SubSpI, T.SubSpIT3, IsaVersion.v80, InstFlags.Rd), + new(0xEBAD0000, 0xFFEF8000, rdsConstraints, InstName.SubSpR, T.SubSpRT1, IsaVersion.v80, InstFlags.Rd), + new(0xFA40F080, 0xFFF0F0C0, rnConstraints, InstName.Sxtab, T.SxtabT1, IsaVersion.v80, InstFlags.Rd), + new(0xFA20F080, 0xFFF0F0C0, rnConstraints, InstName.Sxtab16, T.Sxtab16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFA00F080, 0xFFF0F0C0, rnConstraints, InstName.Sxtah, T.SxtahT1, IsaVersion.v80, InstFlags.Rd), + new(0xFA4FF080, 0xFFFFF0C0, InstName.Sxtb, T.SxtbT2, IsaVersion.v80, InstFlags.Rd), + new(0xFA2FF080, 0xFFFFF0C0, InstName.Sxtb16, T.Sxtb16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFA0FF080, 0xFFFFF0C0, InstName.Sxth, T.SxthT2, IsaVersion.v80, InstFlags.Rd), + new(0xE8D0F000, 0xFFF0FFE0, InstName.Tbb, T.TbbT1, IsaVersion.v80, InstFlags.None), + new(0xF0900F00, 0xFBF08F00, InstName.TeqI, T.TeqIT1, IsaVersion.v80, InstFlags.None), + new(0xEA900F00, 0xFFF08F00, InstName.TeqR, T.TeqRT1, IsaVersion.v80, InstFlags.None), + new(0xF3AF8012, 0xFFFFFFFF, InstName.Tsb, T.TsbT1, IsaVersion.v84, IsaFeature.FeatTrf, InstFlags.None), + new(0xF0100F00, 0xFBF08F00, InstName.TstI, T.TstIT1, IsaVersion.v80, InstFlags.None), + new(0xEA100F00, 0xFFF08F00, InstName.TstR, T.TstRT2, IsaVersion.v80, InstFlags.None), + new(0xFA90F040, 0xFFF0F0F0, InstName.Uadd16, T.Uadd16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFA80F040, 0xFFF0F0F0, InstName.Uadd8, T.Uadd8T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAA0F040, 0xFFF0F0F0, InstName.Uasx, T.UasxT1, IsaVersion.v80, InstFlags.Rd), + new(0xF3C00000, 0xFFF08020, InstName.Ubfx, T.UbfxT1, IsaVersion.v80, InstFlags.Rd), + new(0xF7F0A000, 0xFFF0F000, InstName.Udf, T.UdfT2, IsaVersion.v80, InstFlags.None), + new(0xFBB0F0F0, 0xFFF0F0F0, InstName.Udiv, T.UdivT1, IsaVersion.v80, InstFlags.Rd), + new(0xFA90F060, 0xFFF0F0F0, InstName.Uhadd16, T.Uhadd16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFA80F060, 0xFFF0F0F0, InstName.Uhadd8, T.Uhadd8T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAA0F060, 0xFFF0F0F0, InstName.Uhasx, T.UhasxT1, IsaVersion.v80, InstFlags.Rd), + new(0xFAE0F060, 0xFFF0F0F0, InstName.Uhsax, T.UhsaxT1, IsaVersion.v80, InstFlags.Rd), + new(0xFAD0F060, 0xFFF0F0F0, InstName.Uhsub16, T.Uhsub16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAC0F060, 0xFFF0F0F0, InstName.Uhsub8, T.Uhsub8T1, IsaVersion.v80, InstFlags.Rd), + new(0xFBE00060, 0xFFF000F0, InstName.Umaal, T.UmaalT1, IsaVersion.v80, InstFlags.RdLoRdHi), + new(0xFBE00000, 0xFFF000F0, InstName.Umlal, T.UmlalT1, IsaVersion.v80, InstFlags.RdLoRdHi), + new(0xFBA00000, 0xFFF000F0, InstName.Umull, T.UmullT1, IsaVersion.v80, InstFlags.RdLoRdHi), + new(0xFA90F050, 0xFFF0F0F0, InstName.Uqadd16, T.Uqadd16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFA80F050, 0xFFF0F0F0, InstName.Uqadd8, T.Uqadd8T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAA0F050, 0xFFF0F0F0, InstName.Uqasx, T.UqasxT1, IsaVersion.v80, InstFlags.Rd), + new(0xFAE0F050, 0xFFF0F0F0, InstName.Uqsax, T.UqsaxT1, IsaVersion.v80, InstFlags.Rd), + new(0xFAD0F050, 0xFFF0F0F0, InstName.Uqsub16, T.Uqsub16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAC0F050, 0xFFF0F0F0, InstName.Uqsub8, T.Uqsub8T1, IsaVersion.v80, InstFlags.Rd), + new(0xFB70F000, 0xFFF0F0F0, InstName.Usad8, T.Usad8T1, IsaVersion.v80, InstFlags.Rd), + new(0xFB700000, 0xFFF000F0, raConstraints, InstName.Usada8, T.Usada8T1, IsaVersion.v80, InstFlags.Rd), + new(0xF3800000, 0xFFD08020, shimm2imm3Constraints, InstName.Usat, T.UsatT1, IsaVersion.v80, InstFlags.Rd), + new(0xF3A00000, 0xFFF0F0F0, InstName.Usat16, T.Usat16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAE0F040, 0xFFF0F0F0, InstName.Usax, T.UsaxT1, IsaVersion.v80, InstFlags.Rd), + new(0xFAD0F040, 0xFFF0F0F0, InstName.Usub16, T.Usub16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFAC0F040, 0xFFF0F0F0, InstName.Usub8, T.Usub8T1, IsaVersion.v80, InstFlags.Rd), + new(0xFA50F080, 0xFFF0F0C0, rnConstraints, InstName.Uxtab, T.UxtabT1, IsaVersion.v80, InstFlags.Rd), + new(0xFA30F080, 0xFFF0F0C0, rnConstraints, InstName.Uxtab16, T.Uxtab16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFA10F080, 0xFFF0F0C0, rnConstraints, InstName.Uxtah, T.UxtahT1, IsaVersion.v80, InstFlags.Rd), + new(0xFA5FF080, 0xFFFFF0C0, InstName.Uxtb, T.UxtbT2, IsaVersion.v80, InstFlags.Rd), + new(0xFA3FF080, 0xFFFFF0C0, InstName.Uxtb16, T.Uxtb16T1, IsaVersion.v80, InstFlags.Rd), + new(0xFA1FF080, 0xFFFFF0C0, InstName.Uxth, T.UxthT2, IsaVersion.v80, InstFlags.Rd), + new(0xEF000710, 0xEF800F10, sizeQvdQvnQvmConstraints, InstName.Vaba, T.VabaT1, IsaVersion.v80, InstFlags.None), + new(0xEF800500, 0xEF800F50, sizeVdConstraints, InstName.Vabal, T.VabalT1, IsaVersion.v80, InstFlags.None), + new(0xEF800700, 0xEF800F50, sizeVdConstraints, InstName.VabdlI, T.VabdlIT1, IsaVersion.v80, InstFlags.None), + new(0xFF200D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VabdF, T.VabdFT1, IsaVersion.v80, InstFlags.None), + new(0xFF300D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VabdF, T.VabdFT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000700, 0xEF800F10, sizeQvdQvnQvmConstraints, InstName.VabdI, T.VabdIT1, IsaVersion.v80, InstFlags.None), + new(0xFFB10300, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vabs, T.VabsT1, IsaVersion.v80, InstFlags.None), + new(0xFFB90700, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.Vabs, T.VabsT1, IsaVersion.v80, InstFlags.None), + new(0xFFB50700, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.Vabs, T.VabsT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEB00AC0, 0xFFBF0ED0, InstName.Vabs, T.VabsT2, IsaVersion.v80, InstFlags.None), + new(0xEEB009C0, 0xFFBF0FD0, InstName.Vabs, T.VabsT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFF000E10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vacge, T.VacgeT1, IsaVersion.v80, InstFlags.None), + new(0xFF100E10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vacge, T.VacgeT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFF200E10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vacgt, T.VacgtT1, IsaVersion.v80, InstFlags.None), + new(0xFF300E10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vacgt, T.VacgtT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF800400, 0xFF800F50, sizeVnVmConstraints, InstName.Vaddhn, T.VaddhnT1, IsaVersion.v80, InstFlags.None), + new(0xEF800000, 0xEF800F50, sizeVdOpvnConstraints, InstName.Vaddl, T.VaddlT1, IsaVersion.v80, InstFlags.None), + new(0xEF800100, 0xEF800F50, sizeVdOpvnConstraints, InstName.Vaddw, T.VaddwT1, IsaVersion.v80, InstFlags.None), + new(0xEF000D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VaddF, T.VaddFT1, IsaVersion.v80, InstFlags.None), + new(0xEF100D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VaddF, T.VaddFT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEE300A00, 0xFFB00E50, InstName.VaddF, T.VaddFT2, IsaVersion.v80, InstFlags.None), + new(0xEE300900, 0xFFB00F50, InstName.VaddF, T.VaddFT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000800, 0xFF800F10, qvdQvnQvmConstraints, InstName.VaddI, T.VaddIT1, IsaVersion.v80, InstFlags.None), + new(0xEF000110, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VandR, T.VandRT1, IsaVersion.v80, InstFlags.None), + new(0xEF800130, 0xEFB809B0, cmodeCmodeQvdConstraints, InstName.VbicI, T.VbicIT1, IsaVersion.v80, InstFlags.None), + new(0xEF800930, 0xEFB80DB0, cmodeCmodeQvdConstraints, InstName.VbicI, T.VbicIT2, IsaVersion.v80, InstFlags.None), + new(0xEF100110, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VbicR, T.VbicRT1, IsaVersion.v80, InstFlags.None), + new(0xFF300110, 0xFFB00F10, qvdQvnQvmOpConstraints, InstName.Vbif, T.VbifT1, IsaVersion.v80, InstFlags.None), + new(0xFF200110, 0xFFB00F10, qvdQvnQvmOpConstraints, InstName.Vbit, T.VbitT1, IsaVersion.v80, InstFlags.None), + new(0xFF100110, 0xFFB00F10, qvdQvnQvmOpConstraints, InstName.Vbsl, T.VbslT1, IsaVersion.v80, InstFlags.None), + new(0xFC900800, 0xFEB00F10, qvdQvnQvmConstraints, InstName.Vcadd, T.VcaddT1, IsaVersion.v83, IsaFeature.FeatFcma, InstFlags.None), + new(0xFC800800, 0xFEB00F10, qvdQvnQvmConstraints, InstName.Vcadd, T.VcaddT1, IsaVersion.v83, IsaFeature.FeatFcma | IsaFeature.FeatFp16, InstFlags.None), + new(0xFFB10100, 0xFFB30F90, sizeQvdQvmConstraints, InstName.VceqI, T.VceqIT1, IsaVersion.v80, InstFlags.None), + new(0xFFB90500, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.VceqI, T.VceqIT1, IsaVersion.v80, InstFlags.None), + new(0xFFB50500, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.VceqI, T.VceqIT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFF000810, 0xFF800F10, qvdQvnQvmSizeConstraints, InstName.VceqR, T.VceqRT1, IsaVersion.v80, InstFlags.None), + new(0xEF000E00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VceqR, T.VceqRT2, IsaVersion.v80, InstFlags.None), + new(0xEF100E00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VceqR, T.VceqRT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFB10080, 0xFFB30F90, sizeQvdQvmConstraints, InstName.VcgeI, T.VcgeIT1, IsaVersion.v80, InstFlags.None), + new(0xFFB90480, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.VcgeI, T.VcgeIT1, IsaVersion.v80, InstFlags.None), + new(0xFFB50480, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.VcgeI, T.VcgeIT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000310, 0xEF800F10, qvdQvnQvmSizeConstraints, InstName.VcgeR, T.VcgeRT1, IsaVersion.v80, InstFlags.None), + new(0xFF000E00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VcgeR, T.VcgeRT2, IsaVersion.v80, InstFlags.None), + new(0xFF100E00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VcgeR, T.VcgeRT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFB10000, 0xFFB30F90, sizeQvdQvmConstraints, InstName.VcgtI, T.VcgtIT1, IsaVersion.v80, InstFlags.None), + new(0xFFB90400, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.VcgtI, T.VcgtIT1, IsaVersion.v80, InstFlags.None), + new(0xFFB50400, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.VcgtI, T.VcgtIT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000300, 0xEF800F10, qvdQvnQvmSizeConstraints, InstName.VcgtR, T.VcgtRT1, IsaVersion.v80, InstFlags.None), + new(0xFF200E00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VcgtR, T.VcgtRT2, IsaVersion.v80, InstFlags.None), + new(0xFF300E00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VcgtR, T.VcgtRT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFB10180, 0xFFB30F90, sizeQvdQvmConstraints, InstName.VcleI, T.VcleIT1, IsaVersion.v80, InstFlags.None), + new(0xFFB90580, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.VcleI, T.VcleIT1, IsaVersion.v80, InstFlags.None), + new(0xFFB50580, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.VcleI, T.VcleIT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFB00400, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vcls, T.VclsT1, IsaVersion.v80, InstFlags.None), + new(0xFFB10200, 0xFFB30F90, sizeQvdQvmConstraints, InstName.VcltI, T.VcltIT1, IsaVersion.v80, InstFlags.None), + new(0xFFB90600, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.VcltI, T.VcltIT1, IsaVersion.v80, InstFlags.None), + new(0xFFB50600, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.VcltI, T.VcltIT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFB00480, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vclz, T.VclzT1, IsaVersion.v80, InstFlags.None), + new(0xFC200800, 0xFE200F10, qvdQvnQvmConstraints, InstName.Vcmla, T.VcmlaT1, IsaVersion.v83, IsaFeature.FeatFcma, InstFlags.None), + new(0xFE000800, 0xFF000F10, qvdQvnConstraints, InstName.VcmlaS, T.VcmlaST1, IsaVersion.v83, IsaFeature.FeatFcma, InstFlags.None), + new(0xEEB40A40, 0xFFBF0ED0, InstName.Vcmp, T.VcmpT1, IsaVersion.v80, InstFlags.None), + new(0xEEB40940, 0xFFBF0FD0, InstName.Vcmp, T.VcmpT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEB50A40, 0xFFBF0EFF, InstName.Vcmp, T.VcmpT2, IsaVersion.v80, InstFlags.None), + new(0xEEB50940, 0xFFBF0FFF, InstName.Vcmp, T.VcmpT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEB40AC0, 0xFFBF0ED0, InstName.Vcmpe, T.VcmpeT1, IsaVersion.v80, InstFlags.None), + new(0xEEB409C0, 0xFFBF0FD0, InstName.Vcmpe, T.VcmpeT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEB50AC0, 0xFFBF0EFF, InstName.Vcmpe, T.VcmpeT2, IsaVersion.v80, InstFlags.None), + new(0xEEB509C0, 0xFFBF0FFF, InstName.Vcmpe, T.VcmpeT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFB00500, 0xFFBF0F90, qvdQvmConstraints, InstName.Vcnt, T.VcntT1, IsaVersion.v80, InstFlags.None), + new(0xFFBB0000, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtaAsimd, T.VcvtaAsimdT1, IsaVersion.v80, InstFlags.None), + new(0xFFB70000, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtaAsimd, T.VcvtaAsimdT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEBC0A40, 0xFFBF0E50, sizeConstraints, InstName.VcvtaVfp, T.VcvtaVfpT1, IsaVersion.v80, InstFlags.None), + new(0xFEBC0940, 0xFFBF0F50, sizeConstraints, InstName.VcvtaVfp, T.VcvtaVfpT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEB20A40, 0xFFBE0ED0, InstName.Vcvtb, T.VcvtbT1, IsaVersion.v80, InstFlags.None), + new(0xEEB30940, 0xFFBF0FD0, InstName.VcvtbBfs, T.VcvtbBfsT1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0xFFBB0300, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtmAsimd, T.VcvtmAsimdT1, IsaVersion.v80, InstFlags.None), + new(0xFFB70300, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtmAsimd, T.VcvtmAsimdT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEBF0A40, 0xFFBF0E50, sizeConstraints, InstName.VcvtmVfp, T.VcvtmVfpT1, IsaVersion.v80, InstFlags.None), + new(0xFEBF0940, 0xFFBF0F50, sizeConstraints, InstName.VcvtmVfp, T.VcvtmVfpT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFBB0100, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtnAsimd, T.VcvtnAsimdT1, IsaVersion.v80, InstFlags.None), + new(0xFFB70100, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtnAsimd, T.VcvtnAsimdT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEBD0A40, 0xFFBF0E50, sizeConstraints, InstName.VcvtnVfp, T.VcvtnVfpT1, IsaVersion.v80, InstFlags.None), + new(0xFEBD0940, 0xFFBF0F50, sizeConstraints, InstName.VcvtnVfp, T.VcvtnVfpT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFBB0200, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtpAsimd, T.VcvtpAsimdT1, IsaVersion.v80, InstFlags.None), + new(0xFFB70200, 0xFFBF0F10, qvdQvmConstraints, InstName.VcvtpAsimd, T.VcvtpAsimdT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEBE0A40, 0xFFBF0E50, sizeConstraints, InstName.VcvtpVfp, T.VcvtpVfpT1, IsaVersion.v80, InstFlags.None), + new(0xFEBE0940, 0xFFBF0F50, sizeConstraints, InstName.VcvtpVfp, T.VcvtpVfpT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEBC0A40, 0xFFBE0ED0, InstName.VcvtrIv, T.VcvtrIvT1, IsaVersion.v80, InstFlags.None), + new(0xEEBC0940, 0xFFBE0FD0, InstName.VcvtrIv, T.VcvtrIvT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEB20AC0, 0xFFBE0ED0, InstName.Vcvtt, T.VcvttT1, IsaVersion.v80, InstFlags.None), + new(0xEEB309C0, 0xFFBF0FD0, InstName.VcvttBfs, T.VcvttBfsT1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0xFFB60640, 0xFFBF0FD0, vmConstraints, InstName.VcvtBfs, T.VcvtBfsT1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0xEEB70AC0, 0xFFBF0ED0, InstName.VcvtDs, T.VcvtDsT1, IsaVersion.v80, InstFlags.None), + new(0xFFB60600, 0xFFBF0ED0, opvdOpvmConstraints, InstName.VcvtHs, T.VcvtHsT1, IsaVersion.v80, InstFlags.None), + new(0xFFBB0600, 0xFFBF0E10, qvdQvmConstraints, InstName.VcvtIs, T.VcvtIsT1, IsaVersion.v80, InstFlags.None), + new(0xFFB70600, 0xFFBF0E10, qvdQvmConstraints, InstName.VcvtIs, T.VcvtIsT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEBC0AC0, 0xFFBE0ED0, InstName.VcvtIv, T.VcvtIvT1, IsaVersion.v80, InstFlags.None), + new(0xEEBC09C0, 0xFFBE0FD0, InstName.VcvtIv, T.VcvtIvT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEB80A40, 0xFFBF0E50, InstName.VcvtVi, T.VcvtViT1, IsaVersion.v80, InstFlags.None), + new(0xEEB80940, 0xFFBF0F50, InstName.VcvtVi, T.VcvtViT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF800E10, 0xEF800E90, imm6Opimm6Imm6QvdQvmConstraints, InstName.VcvtXs, T.VcvtXsT1, IsaVersion.v80, InstFlags.None), + new(0xEF800C10, 0xEF800E90, imm6Opimm6Imm6QvdQvmConstraints, InstName.VcvtXs, T.VcvtXsT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEBA0A40, 0xFFBA0E50, InstName.VcvtXv, T.VcvtXvT1, IsaVersion.v80, InstFlags.None), + new(0xEEBA0940, 0xFFBA0F50, InstName.VcvtXv, T.VcvtXvT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEE800A00, 0xFFB00E50, InstName.Vdiv, T.VdivT1, IsaVersion.v80, InstFlags.None), + new(0xEE800900, 0xFFB00F50, InstName.Vdiv, T.VdivT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFC000D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vdot, T.VdotT1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0xFE000D00, 0xFFB00F10, qvdQvnConstraints, InstName.VdotS, T.VdotST1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0xEE800B10, 0xFF900F5F, qvdEbConstraints, InstName.VdupR, T.VdupRT1, IsaVersion.v80, InstFlags.RtRead), + new(0xFFB00C00, 0xFFB00F90, imm4QvdConstraints, InstName.VdupS, T.VdupST1, IsaVersion.v80, InstFlags.None), + new(0xFF000110, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Veor, T.VeorT1, IsaVersion.v80, InstFlags.None), + new(0xEFB00000, 0xFFB00010, qvdQvnQvmQimm4Constraints, InstName.Vext, T.VextT1, IsaVersion.v80, InstFlags.None), + new(0xEF000C10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vfma, T.VfmaT1, IsaVersion.v80, InstFlags.None), + new(0xEF100C10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vfma, T.VfmaT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEA00A00, 0xFFB00E50, InstName.Vfma, T.VfmaT2, IsaVersion.v80, InstFlags.None), + new(0xEEA00900, 0xFFB00F50, InstName.Vfma, T.VfmaT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFC200810, 0xFFB00F10, qvdConstraints, InstName.Vfmal, T.VfmalT1, IsaVersion.v82, IsaFeature.FeatFhm, InstFlags.None), + new(0xFE000810, 0xFFB00F10, qvdConstraints, InstName.VfmalS, T.VfmalST1, IsaVersion.v82, IsaFeature.FeatFhm, InstFlags.None), + new(0xFC300810, 0xFFB00F10, vdVnVmConstraints, InstName.VfmaBf, T.VfmaBfT1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0xFE300810, 0xFFB00F10, vdVnConstraints, InstName.VfmaBfs, T.VfmaBfsT1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0xEF200C10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vfms, T.VfmsT1, IsaVersion.v80, InstFlags.None), + new(0xEF300C10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vfms, T.VfmsT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEA00A40, 0xFFB00E50, InstName.Vfms, T.VfmsT2, IsaVersion.v80, InstFlags.None), + new(0xEEA00940, 0xFFB00F50, InstName.Vfms, T.VfmsT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFCA00810, 0xFFB00F10, qvdConstraints, InstName.Vfmsl, T.VfmslT1, IsaVersion.v82, IsaFeature.FeatFhm, InstFlags.None), + new(0xFE100810, 0xFFB00F10, qvdConstraints, InstName.VfmslS, T.VfmslST1, IsaVersion.v82, IsaFeature.FeatFhm, InstFlags.None), + new(0xEE900A40, 0xFFB00E50, InstName.Vfnma, T.VfnmaT1, IsaVersion.v80, InstFlags.None), + new(0xEE900940, 0xFFB00F50, InstName.Vfnma, T.VfnmaT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEE900A00, 0xFFB00E50, InstName.Vfnms, T.VfnmsT1, IsaVersion.v80, InstFlags.None), + new(0xEE900900, 0xFFB00F50, InstName.Vfnms, T.VfnmsT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000000, 0xEF800F10, qvdQvnQvmSizeConstraints, InstName.Vhadd, T.VhaddT1, IsaVersion.v80, InstFlags.None), + new(0xEF000200, 0xEF800F10, qvdQvnQvmSizeConstraints, InstName.Vhsub, T.VhsubT1, IsaVersion.v80, InstFlags.None), + new(0xFEB00AC0, 0xFFBF0FD0, InstName.Vins, T.VinsT1, IsaVersion.v82, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEB90BC0, 0xFFBF0FD0, InstName.Vjcvt, T.VjcvtT1, IsaVersion.v83, IsaFeature.FeatJscvt, InstFlags.None), + new(0xF9A00000, 0xFFB00F10, sizeConstraints2, InstName.Vld11, T.Vld11T1, IsaVersion.v80, InstFlags.None), + new(0xF9A00400, 0xFFB00F20, sizeConstraints2, InstName.Vld11, T.Vld11T2, IsaVersion.v80, InstFlags.None), + new(0xF9A00800, 0xFFB00F40, sizeIndexAlignIndexAlignConstraints, InstName.Vld11, T.Vld11T3, IsaVersion.v80, InstFlags.None), + new(0xF9A00C00, 0xFFB00F00, sizeSizeaConstraints, InstName.Vld1A, T.Vld1AT1, IsaVersion.v80, InstFlags.None), + new(0xF9200700, 0xFFB00F00, alignConstraints, InstName.Vld1M, T.Vld1MT1, IsaVersion.v80, InstFlags.None), + new(0xF9200A00, 0xFFB00F00, alignConstraints2, InstName.Vld1M, T.Vld1MT2, IsaVersion.v80, InstFlags.None), + new(0xF9200600, 0xFFB00F00, alignConstraints, InstName.Vld1M, T.Vld1MT3, IsaVersion.v80, InstFlags.None), + new(0xF9200200, 0xFFB00F00, InstName.Vld1M, T.Vld1MT4, IsaVersion.v80, InstFlags.None), + new(0xF9A00100, 0xFFB00F00, sizeConstraints2, InstName.Vld21, T.Vld21T1, IsaVersion.v80, InstFlags.None), + new(0xF9A00500, 0xFFB00F00, sizeConstraints2, InstName.Vld21, T.Vld21T2, IsaVersion.v80, InstFlags.None), + new(0xF9A00900, 0xFFB00F20, sizeConstraints2, InstName.Vld21, T.Vld21T3, IsaVersion.v80, InstFlags.None), + new(0xF9A00D00, 0xFFB00F00, sizeConstraints3, InstName.Vld2A, T.Vld2AT1, IsaVersion.v80, InstFlags.None), + new(0xF9200800, 0xFFB00E00, alignSizeConstraints, InstName.Vld2M, T.Vld2MT1, IsaVersion.v80, InstFlags.None), + new(0xF9200300, 0xFFB00F00, sizeConstraints3, InstName.Vld2M, T.Vld2MT2, IsaVersion.v80, InstFlags.None), + new(0xF9A00200, 0xFFB00F10, sizeConstraints2, InstName.Vld31, T.Vld31T1, IsaVersion.v80, InstFlags.None), + new(0xF9A00600, 0xFFB00F10, sizeConstraints2, InstName.Vld31, T.Vld31T2, IsaVersion.v80, InstFlags.None), + new(0xF9A00A00, 0xFFB00F30, sizeConstraints2, InstName.Vld31, T.Vld31T3, IsaVersion.v80, InstFlags.None), + new(0xF9A00E00, 0xFFB00F10, sizeAConstraints, InstName.Vld3A, T.Vld3AT1, IsaVersion.v80, InstFlags.None), + new(0xF9200400, 0xFFB00E00, sizeAlignConstraints, InstName.Vld3M, T.Vld3MT1, IsaVersion.v80, InstFlags.None), + new(0xF9A00300, 0xFFB00F00, sizeConstraints2, InstName.Vld41, T.Vld41T1, IsaVersion.v80, InstFlags.None), + new(0xF9A00700, 0xFFB00F00, sizeConstraints2, InstName.Vld41, T.Vld41T2, IsaVersion.v80, InstFlags.None), + new(0xF9A00B00, 0xFFB00F00, sizeIndexAlignConstraints, InstName.Vld41, T.Vld41T3, IsaVersion.v80, InstFlags.None), + new(0xF9A00F00, 0xFFB00F00, sizeaConstraints, InstName.Vld4A, T.Vld4AT1, IsaVersion.v80, InstFlags.None), + new(0xF9200000, 0xFFB00E00, sizeConstraints3, InstName.Vld4M, T.Vld4MT1, IsaVersion.v80, InstFlags.None), + new(0xEC100B00, 0xFE100F01, puwPwPuwPuwConstraints, InstName.Vldm, T.VldmT1, IsaVersion.v80, InstFlags.WBack), + new(0xEC100A00, 0xFE100F00, puwPwPuwPuwConstraints, InstName.Vldm, T.VldmT2, IsaVersion.v80, InstFlags.WBack), + new(0xED100A00, 0xFF300E00, rnConstraints, InstName.VldrI, T.VldrIT1, IsaVersion.v80, InstFlags.None), + new(0xED100900, 0xFF300F00, rnConstraints, InstName.VldrI, T.VldrIT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xED1F0A00, 0xFF3F0E00, InstName.VldrL, T.VldrLT1, IsaVersion.v80, InstFlags.None), + new(0xED1F0900, 0xFF3F0F00, InstName.VldrL, T.VldrLT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFF000F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vmaxnm, T.VmaxnmT1, IsaVersion.v80, InstFlags.None), + new(0xFF100F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vmaxnm, T.VmaxnmT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFE800A00, 0xFFB00E50, sizeConstraints, InstName.Vmaxnm, T.VmaxnmT2, IsaVersion.v80, InstFlags.None), + new(0xFE800900, 0xFFB00F50, sizeConstraints, InstName.Vmaxnm, T.VmaxnmT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000F00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmaxF, T.VmaxFT1, IsaVersion.v80, InstFlags.None), + new(0xEF100F00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmaxF, T.VmaxFT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000600, 0xEF800F10, qvdQvnQvmSizeConstraints, InstName.VmaxI, T.VmaxIT1, IsaVersion.v80, InstFlags.None), + new(0xFF200F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vminnm, T.VminnmT1, IsaVersion.v80, InstFlags.None), + new(0xFF300F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vminnm, T.VminnmT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFE800A40, 0xFFB00E50, sizeConstraints, InstName.Vminnm, T.VminnmT2, IsaVersion.v80, InstFlags.None), + new(0xFE800940, 0xFFB00F50, sizeConstraints, InstName.Vminnm, T.VminnmT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF200F00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VminF, T.VminFT1, IsaVersion.v80, InstFlags.None), + new(0xEF300F00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VminF, T.VminFT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000610, 0xEF800F10, qvdQvnQvmSizeConstraints, InstName.VminI, T.VminIT1, IsaVersion.v80, InstFlags.None), + new(0xEF800800, 0xEF800F50, sizeVdConstraints, InstName.VmlalI, T.VmlalIT1, IsaVersion.v80, InstFlags.None), + new(0xEF800240, 0xEF800F50, sizeSizeVdConstraints, InstName.VmlalS, T.VmlalST1, IsaVersion.v80, InstFlags.None), + new(0xEF000D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmlaF, T.VmlaFT1, IsaVersion.v80, InstFlags.None), + new(0xEF100D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmlaF, T.VmlaFT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEE000A00, 0xFFB00E50, InstName.VmlaF, T.VmlaFT2, IsaVersion.v80, InstFlags.None), + new(0xEE000900, 0xFFB00F50, InstName.VmlaF, T.VmlaFT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000900, 0xFF800F10, sizeQvdQvnQvmConstraints, InstName.VmlaI, T.VmlaIT1, IsaVersion.v80, InstFlags.None), + new(0xEFA00040, 0xEFA00E50, sizeQvdQvnConstraints, InstName.VmlaS, T.VmlaST1, IsaVersion.v80, InstFlags.None), + new(0xEF900040, 0xEFB00F50, sizeQvdQvnConstraints, InstName.VmlaS, T.VmlaST1, IsaVersion.v80, InstFlags.None), + new(0xEF900140, 0xEFB00F50, sizeQvdQvnConstraints, InstName.VmlaS, T.VmlaST1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF800A00, 0xEF800F50, sizeVdConstraints, InstName.VmlslI, T.VmlslIT1, IsaVersion.v80, InstFlags.None), + new(0xEF800640, 0xEF800F50, sizeSizeVdConstraints, InstName.VmlslS, T.VmlslST1, IsaVersion.v80, InstFlags.None), + new(0xEF200D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmlsF, T.VmlsFT1, IsaVersion.v80, InstFlags.None), + new(0xEF300D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmlsF, T.VmlsFT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEE000A40, 0xFFB00E50, InstName.VmlsF, T.VmlsFT2, IsaVersion.v80, InstFlags.None), + new(0xEE000940, 0xFFB00F50, InstName.VmlsF, T.VmlsFT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFF000900, 0xFF800F10, sizeQvdQvnQvmConstraints, InstName.VmlsI, T.VmlsIT1, IsaVersion.v80, InstFlags.None), + new(0xEFA00440, 0xEFA00E50, sizeQvdQvnConstraints, InstName.VmlsS, T.VmlsST1, IsaVersion.v80, InstFlags.None), + new(0xEF900440, 0xEFB00F50, sizeQvdQvnConstraints, InstName.VmlsS, T.VmlsST1, IsaVersion.v80, InstFlags.None), + new(0xEF900540, 0xEFB00F50, sizeQvdQvnConstraints, InstName.VmlsS, T.VmlsST1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFC000C40, 0xFFB00F50, vdVnVmConstraints, InstName.Vmmla, T.VmmlaT1, IsaVersion.v86, IsaFeature.FeatAa32bf16, InstFlags.None), + new(0xEF800A10, 0xEF870FD0, imm3hImm3hImm3hImm3hImm3hVdConstraints, InstName.Vmovl, T.VmovlT1, IsaVersion.v80, InstFlags.None), + new(0xFFB20200, 0xFFB30FD0, sizeVmConstraints, InstName.Vmovn, T.VmovnT1, IsaVersion.v80, InstFlags.None), + new(0xFEB00A40, 0xFFBF0FD0, InstName.Vmovx, T.VmovxT1, IsaVersion.v82, IsaFeature.FeatFp16, InstFlags.None), + new(0xEC400B10, 0xFFE00FD0, InstName.VmovD, T.VmovDT1, IsaVersion.v80, InstFlags.Rt2Read), + new(0xEE000910, 0xFFE00F7F, InstName.VmovH, T.VmovHT1, IsaVersion.v82, IsaFeature.FeatFp16, InstFlags.Rt), + new(0xEF800010, 0xEFB809B0, qvdConstraints, InstName.VmovI, T.VmovIT1, IsaVersion.v80, InstFlags.None), + new(0xEEB00A00, 0xFFB00EF0, InstName.VmovI, T.VmovIT2, IsaVersion.v80, InstFlags.None), + new(0xEEB00900, 0xFFB00FF0, InstName.VmovI, T.VmovIT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF800810, 0xEFB80DB0, qvdConstraints, InstName.VmovI, T.VmovIT3, IsaVersion.v80, InstFlags.None), + new(0xEF800C10, 0xEFB80CB0, qvdConstraints, InstName.VmovI, T.VmovIT4, IsaVersion.v80, InstFlags.None), + new(0xEF800E30, 0xEFB80FB0, qvdConstraints, InstName.VmovI, T.VmovIT5, IsaVersion.v80, InstFlags.None), + new(0xEEB00A40, 0xFFBF0ED0, InstName.VmovR, T.VmovRT2, IsaVersion.v80, InstFlags.None), + new(0xEE000B10, 0xFF900F1F, opc1opc2Constraints, InstName.VmovRs, T.VmovRsT1, IsaVersion.v80, InstFlags.RtRead), + new(0xEE000A10, 0xFFE00F7F, InstName.VmovS, T.VmovST1, IsaVersion.v80, InstFlags.RtRead), + new(0xEE100B10, 0xFF100F1F, uopc1opc2Uopc1opc2Constraints, InstName.VmovSr, T.VmovSrT1, IsaVersion.v80, InstFlags.Rt), + new(0xEC400A10, 0xFFE00FD0, InstName.VmovSs, T.VmovSsT1, IsaVersion.v80, InstFlags.Rt2Read), + new(0xEEF00A10, 0xFFF00FFF, InstName.Vmrs, T.VmrsT1, IsaVersion.v80, InstFlags.Rt), + new(0xEEE00A10, 0xFFF00FFF, InstName.Vmsr, T.VmsrT1, IsaVersion.v80, InstFlags.RtRead), + new(0xEF800C00, 0xEF800D50, sizeOpuOpsizeVdConstraints, InstName.VmullI, T.VmullIT1, IsaVersion.v80, InstFlags.None), + new(0xEF800A40, 0xEF800F50, sizeSizeVdConstraints, InstName.VmullS, T.VmullST1, IsaVersion.v80, InstFlags.None), + new(0xFF000D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmulF, T.VmulFT1, IsaVersion.v80, InstFlags.None), + new(0xFF100D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VmulF, T.VmulFT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEE200A00, 0xFFB00E50, InstName.VmulF, T.VmulFT2, IsaVersion.v80, InstFlags.None), + new(0xEE200900, 0xFFB00F50, InstName.VmulF, T.VmulFT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000910, 0xEF800F10, sizeOpsizeOpsizeQvdQvnQvmConstraints, InstName.VmulI, T.VmulIT1, IsaVersion.v80, InstFlags.None), + new(0xEFA00840, 0xEFA00E50, sizeQvdQvnConstraints, InstName.VmulS, T.VmulST1, IsaVersion.v80, InstFlags.None), + new(0xEF900840, 0xEFB00F50, sizeQvdQvnConstraints, InstName.VmulS, T.VmulST1, IsaVersion.v80, InstFlags.None), + new(0xEF900940, 0xEFB00F50, sizeQvdQvnConstraints, InstName.VmulS, T.VmulST1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF800030, 0xEFB809B0, cmodeQvdConstraints, InstName.VmvnI, T.VmvnIT1, IsaVersion.v80, InstFlags.None), + new(0xEF800830, 0xEFB80DB0, cmodeQvdConstraints, InstName.VmvnI, T.VmvnIT2, IsaVersion.v80, InstFlags.None), + new(0xEF800C30, 0xEFB80EB0, cmodeQvdConstraints, InstName.VmvnI, T.VmvnIT3, IsaVersion.v80, InstFlags.None), + new(0xFFB00580, 0xFFBF0F90, qvdQvmConstraints, InstName.VmvnR, T.VmvnRT1, IsaVersion.v80, InstFlags.None), + new(0xFFB10380, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vneg, T.VnegT1, IsaVersion.v80, InstFlags.None), + new(0xFFB90780, 0xFFBB0F90, sizeQvdQvmConstraints, InstName.Vneg, T.VnegT1, IsaVersion.v80, InstFlags.None), + new(0xFFB50780, 0xFFBF0F90, sizeQvdQvmConstraints, InstName.Vneg, T.VnegT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEB10A40, 0xFFBF0ED0, InstName.Vneg, T.VnegT2, IsaVersion.v80, InstFlags.None), + new(0xEEB10940, 0xFFBF0FD0, InstName.Vneg, T.VnegT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEE100A40, 0xFFB00E50, InstName.Vnmla, T.VnmlaT1, IsaVersion.v80, InstFlags.None), + new(0xEE100940, 0xFFB00F50, InstName.Vnmla, T.VnmlaT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEE100A00, 0xFFB00E50, InstName.Vnmls, T.VnmlsT1, IsaVersion.v80, InstFlags.None), + new(0xEE100900, 0xFFB00F50, InstName.Vnmls, T.VnmlsT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEE200A40, 0xFFB00E50, InstName.Vnmul, T.VnmulT1, IsaVersion.v80, InstFlags.None), + new(0xEE200940, 0xFFB00F50, InstName.Vnmul, T.VnmulT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF300110, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VornR, T.VornRT1, IsaVersion.v80, InstFlags.None), + new(0xEF800110, 0xEFB809B0, cmodeCmodeQvdConstraints, InstName.VorrI, T.VorrIT1, IsaVersion.v80, InstFlags.None), + new(0xEF800910, 0xEFB80DB0, cmodeCmodeQvdConstraints, InstName.VorrI, T.VorrIT2, IsaVersion.v80, InstFlags.None), + new(0xEF200110, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VorrR, T.VorrRT1, IsaVersion.v80, InstFlags.None), + new(0xFFB00600, 0xFFB30F10, sizeQvdQvmConstraints, InstName.Vpadal, T.VpadalT1, IsaVersion.v80, InstFlags.None), + new(0xFFB00200, 0xFFB30F10, sizeQvdQvmConstraints, InstName.Vpaddl, T.VpaddlT1, IsaVersion.v80, InstFlags.None), + new(0xFF000D00, 0xFFB00F10, qConstraints, InstName.VpaddF, T.VpaddFT1, IsaVersion.v80, InstFlags.None), + new(0xFF100D00, 0xFFB00F10, qConstraints, InstName.VpaddF, T.VpaddFT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000B10, 0xFF800F10, sizeQConstraints, InstName.VpaddI, T.VpaddIT1, IsaVersion.v80, InstFlags.None), + new(0xFF000F00, 0xFFB00F50, InstName.VpmaxF, T.VpmaxFT1, IsaVersion.v80, InstFlags.None), + new(0xFF100F00, 0xFFB00F50, InstName.VpmaxF, T.VpmaxFT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000A00, 0xEF800F50, sizeConstraints4, InstName.VpmaxI, T.VpmaxIT1, IsaVersion.v80, InstFlags.None), + new(0xFF200F00, 0xFFB00F50, InstName.VpminF, T.VpminFT1, IsaVersion.v80, InstFlags.None), + new(0xFF300F00, 0xFFB00F50, InstName.VpminF, T.VpminFT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000A10, 0xEF800F50, sizeConstraints4, InstName.VpminI, T.VpminIT1, IsaVersion.v80, InstFlags.None), + new(0xFFB00700, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vqabs, T.VqabsT1, IsaVersion.v80, InstFlags.None), + new(0xEF000010, 0xEF800F10, qvdQvnQvmConstraints, InstName.Vqadd, T.VqaddT1, IsaVersion.v80, InstFlags.None), + new(0xEF800900, 0xFF800F50, sizeSizeVdConstraints, InstName.Vqdmlal, T.VqdmlalT1, IsaVersion.v80, InstFlags.None), + new(0xEF800340, 0xFF800F50, sizeSizeVdConstraints, InstName.Vqdmlal, T.VqdmlalT2, IsaVersion.v80, InstFlags.None), + new(0xEF800B00, 0xFF800F50, sizeSizeVdConstraints, InstName.Vqdmlsl, T.VqdmlslT1, IsaVersion.v80, InstFlags.None), + new(0xEF800740, 0xFF800F50, sizeSizeVdConstraints, InstName.Vqdmlsl, T.VqdmlslT2, IsaVersion.v80, InstFlags.None), + new(0xEF000B00, 0xFF800F10, qvdQvnQvmSizeSizeConstraints, InstName.Vqdmulh, T.VqdmulhT1, IsaVersion.v80, InstFlags.None), + new(0xEF800C40, 0xEF800F50, sizeSizeQvdQvnConstraints, InstName.Vqdmulh, T.VqdmulhT2, IsaVersion.v80, InstFlags.None), + new(0xEF800D00, 0xFF800F50, sizeSizeVdConstraints, InstName.Vqdmull, T.VqdmullT1, IsaVersion.v80, InstFlags.None), + new(0xEF800B40, 0xFF800F50, sizeSizeVdConstraints, InstName.Vqdmull, T.VqdmullT2, IsaVersion.v80, InstFlags.None), + new(0xFFB20200, 0xFFB30F10, opSizeVmConstraints, InstName.Vqmovn, T.VqmovnT1, IsaVersion.v80, InstFlags.None), + new(0xFFB00780, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vqneg, T.VqnegT1, IsaVersion.v80, InstFlags.None), + new(0xFF000B10, 0xFF800F10, qvdQvnQvmSizeSizeConstraints, InstName.Vqrdmlah, T.VqrdmlahT1, IsaVersion.v81, IsaFeature.FeatRdm, InstFlags.None), + new(0xEF800E40, 0xEF800F50, sizeSizeQvdQvnConstraints, InstName.Vqrdmlah, T.VqrdmlahT2, IsaVersion.v81, IsaFeature.FeatRdm, InstFlags.None), + new(0xFF000C10, 0xFF800F10, qvdQvnQvmSizeSizeConstraints, InstName.Vqrdmlsh, T.VqrdmlshT1, IsaVersion.v81, IsaFeature.FeatRdm, InstFlags.None), + new(0xEF800F40, 0xEF800F50, sizeSizeQvdQvnConstraints, InstName.Vqrdmlsh, T.VqrdmlshT2, IsaVersion.v81, IsaFeature.FeatRdm, InstFlags.None), + new(0xFF000B00, 0xFF800F10, qvdQvnQvmSizeSizeConstraints, InstName.Vqrdmulh, T.VqrdmulhT1, IsaVersion.v80, InstFlags.None), + new(0xEF800D40, 0xEF800F50, sizeSizeQvdQvnConstraints, InstName.Vqrdmulh, T.VqrdmulhT2, IsaVersion.v80, InstFlags.None), + new(0xEF000510, 0xEF800F10, qvdQvmQvnConstraints, InstName.Vqrshl, T.VqrshlT1, IsaVersion.v80, InstFlags.None), + new(0xEF800850, 0xEF800ED0, imm6UopVmConstraints, InstName.Vqrshrn, T.VqrshrnT1, IsaVersion.v80, InstFlags.None), + new(0xEF800610, 0xEF800E10, imm6lUopQvdQvmConstraints, InstName.VqshlI, T.VqshlIT1, IsaVersion.v80, InstFlags.None), + new(0xEF000410, 0xEF800F10, qvdQvmQvnConstraints, InstName.VqshlR, T.VqshlRT1, IsaVersion.v80, InstFlags.None), + new(0xEF800810, 0xEF800ED0, imm6UopVmConstraints, InstName.Vqshrn, T.VqshrnT1, IsaVersion.v80, InstFlags.None), + new(0xEF000210, 0xEF800F10, qvdQvnQvmConstraints, InstName.Vqsub, T.VqsubT1, IsaVersion.v80, InstFlags.None), + new(0xFF800400, 0xFF800F50, sizeVnVmConstraints, InstName.Vraddhn, T.VraddhnT1, IsaVersion.v80, InstFlags.None), + new(0xFFB30400, 0xFFB30E90, qvdQvmSizeSizeConstraints, InstName.Vrecpe, T.VrecpeT1, IsaVersion.v80, InstFlags.None), + new(0xEF000F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vrecps, T.VrecpsT1, IsaVersion.v80, InstFlags.None), + new(0xEF100F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vrecps, T.VrecpsT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFB00100, 0xFFB30F90, sizeSizeSizeQvdQvmConstraints, InstName.Vrev16, T.Vrev16T1, IsaVersion.v80, InstFlags.None), + new(0xFFB00080, 0xFFB30F90, sizeSizeQvdQvmConstraints, InstName.Vrev32, T.Vrev32T1, IsaVersion.v80, InstFlags.None), + new(0xFFB00000, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vrev64, T.Vrev64T1, IsaVersion.v80, InstFlags.None), + new(0xEF000100, 0xEF800F10, qvdQvnQvmSizeConstraints, InstName.Vrhadd, T.VrhaddT1, IsaVersion.v80, InstFlags.None), + new(0xFFBA0500, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintaAsimd, T.VrintaAsimdT1, IsaVersion.v80, InstFlags.None), + new(0xFFB60500, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintaAsimd, T.VrintaAsimdT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEB80A40, 0xFFBF0ED0, sizeConstraints, InstName.VrintaVfp, T.VrintaVfpT1, IsaVersion.v80, InstFlags.None), + new(0xFEB80940, 0xFFBF0FD0, sizeConstraints, InstName.VrintaVfp, T.VrintaVfpT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFBA0680, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintmAsimd, T.VrintmAsimdT1, IsaVersion.v80, InstFlags.None), + new(0xFFB60680, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintmAsimd, T.VrintmAsimdT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEBB0A40, 0xFFBF0ED0, sizeConstraints, InstName.VrintmVfp, T.VrintmVfpT1, IsaVersion.v80, InstFlags.None), + new(0xFEBB0940, 0xFFBF0FD0, sizeConstraints, InstName.VrintmVfp, T.VrintmVfpT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFBA0400, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintnAsimd, T.VrintnAsimdT1, IsaVersion.v80, InstFlags.None), + new(0xFFB60400, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintnAsimd, T.VrintnAsimdT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEB90A40, 0xFFBF0ED0, sizeConstraints, InstName.VrintnVfp, T.VrintnVfpT1, IsaVersion.v80, InstFlags.None), + new(0xFEB90940, 0xFFBF0FD0, sizeConstraints, InstName.VrintnVfp, T.VrintnVfpT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFBA0780, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintpAsimd, T.VrintpAsimdT1, IsaVersion.v80, InstFlags.None), + new(0xFFB60780, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintpAsimd, T.VrintpAsimdT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFEBA0A40, 0xFFBF0ED0, sizeConstraints, InstName.VrintpVfp, T.VrintpVfpT1, IsaVersion.v80, InstFlags.None), + new(0xFEBA0940, 0xFFBF0FD0, sizeConstraints, InstName.VrintpVfp, T.VrintpVfpT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEB60A40, 0xFFBF0ED0, InstName.VrintrVfp, T.VrintrVfpT1, IsaVersion.v80, InstFlags.None), + new(0xEEB60940, 0xFFBF0FD0, InstName.VrintrVfp, T.VrintrVfpT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFBA0480, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintxAsimd, T.VrintxAsimdT1, IsaVersion.v80, InstFlags.None), + new(0xFFB60480, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintxAsimd, T.VrintxAsimdT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEB70A40, 0xFFBF0ED0, InstName.VrintxVfp, T.VrintxVfpT1, IsaVersion.v80, InstFlags.None), + new(0xEEB70940, 0xFFBF0FD0, InstName.VrintxVfp, T.VrintxVfpT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFFBA0580, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintzAsimd, T.VrintzAsimdT1, IsaVersion.v80, InstFlags.None), + new(0xFFB60580, 0xFFBF0F90, qvdQvmConstraints, InstName.VrintzAsimd, T.VrintzAsimdT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEEB60AC0, 0xFFBF0ED0, InstName.VrintzVfp, T.VrintzVfpT1, IsaVersion.v80, InstFlags.None), + new(0xEEB609C0, 0xFFBF0FD0, InstName.VrintzVfp, T.VrintzVfpT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF000500, 0xEF800F10, qvdQvmQvnConstraints, InstName.Vrshl, T.VrshlT1, IsaVersion.v80, InstFlags.None), + new(0xEF800210, 0xEF800F10, imm6lQvdQvmConstraints, InstName.Vrshr, T.VrshrT1, IsaVersion.v80, InstFlags.None), + new(0xEF800850, 0xFF800FD0, imm6VmConstraints, InstName.Vrshrn, T.VrshrnT1, IsaVersion.v80, InstFlags.None), + new(0xFFB30480, 0xFFB30E90, qvdQvmSizeSizeConstraints, InstName.Vrsqrte, T.VrsqrteT1, IsaVersion.v80, InstFlags.None), + new(0xEF200F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vrsqrts, T.VrsqrtsT1, IsaVersion.v80, InstFlags.None), + new(0xEF300F10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vrsqrts, T.VrsqrtsT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF800310, 0xEF800F10, imm6lQvdQvmConstraints, InstName.Vrsra, T.VrsraT1, IsaVersion.v80, InstFlags.None), + new(0xFF800600, 0xFF800F50, sizeVnVmConstraints, InstName.Vrsubhn, T.VrsubhnT1, IsaVersion.v80, InstFlags.None), + new(0xFC200D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vsdot, T.VsdotT1, IsaVersion.v82, IsaFeature.FeatDotprod, InstFlags.None), + new(0xFE200D00, 0xFFB00F10, qvdQvnConstraints, InstName.VsdotS, T.VsdotST1, IsaVersion.v82, IsaFeature.FeatDotprod, InstFlags.None), + new(0xFE000A00, 0xFF800E50, sizeConstraints, InstName.Vsel, T.VselT1, IsaVersion.v80, InstFlags.None), + new(0xFE000900, 0xFF800F50, sizeConstraints, InstName.Vsel, T.VselT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF800A10, 0xEF800FD0, imm6VdImm6Imm6Imm6Constraints, InstName.Vshll, T.VshllT1, IsaVersion.v80, InstFlags.None), + new(0xFFB20300, 0xFFB30FD0, sizeVdConstraints2, InstName.Vshll, T.VshllT2, IsaVersion.v80, InstFlags.None), + new(0xEF800510, 0xFF800F10, imm6lQvdQvmConstraints, InstName.VshlI, T.VshlIT1, IsaVersion.v80, InstFlags.None), + new(0xEF000400, 0xEF800F10, qvdQvmQvnConstraints, InstName.VshlR, T.VshlRT1, IsaVersion.v80, InstFlags.None), + new(0xEF800010, 0xEF800F10, imm6lQvdQvmConstraints, InstName.Vshr, T.VshrT1, IsaVersion.v80, InstFlags.None), + new(0xEF800810, 0xFF800FD0, imm6VmConstraints, InstName.Vshrn, T.VshrnT1, IsaVersion.v80, InstFlags.None), + new(0xFF800510, 0xFF800F10, imm6lQvdQvmConstraints, InstName.Vsli, T.VsliT1, IsaVersion.v80, InstFlags.None), + new(0xFC200C40, 0xFFB00F50, vdVnVmConstraints, InstName.Vsmmla, T.VsmmlaT1, IsaVersion.v82, IsaFeature.FeatAa32i8mm, InstFlags.None), + new(0xEEB10AC0, 0xFFBF0ED0, InstName.Vsqrt, T.VsqrtT1, IsaVersion.v80, InstFlags.None), + new(0xEEB109C0, 0xFFBF0FD0, InstName.Vsqrt, T.VsqrtT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF800110, 0xEF800F10, imm6lQvdQvmConstraints, InstName.Vsra, T.VsraT1, IsaVersion.v80, InstFlags.None), + new(0xFF800410, 0xFF800F10, imm6lQvdQvmConstraints, InstName.Vsri, T.VsriT1, IsaVersion.v80, InstFlags.None), + new(0xF9800000, 0xFFB00F10, sizeConstraints2, InstName.Vst11, T.Vst11T1, IsaVersion.v80, InstFlags.None), + new(0xF9800400, 0xFFB00F20, sizeConstraints2, InstName.Vst11, T.Vst11T2, IsaVersion.v80, InstFlags.None), + new(0xF9800800, 0xFFB00F40, sizeIndexAlignIndexAlignConstraints, InstName.Vst11, T.Vst11T3, IsaVersion.v80, InstFlags.None), + new(0xF9000700, 0xFFB00F00, alignConstraints, InstName.Vst1M, T.Vst1MT1, IsaVersion.v80, InstFlags.None), + new(0xF9000A00, 0xFFB00F00, alignConstraints2, InstName.Vst1M, T.Vst1MT2, IsaVersion.v80, InstFlags.None), + new(0xF9000600, 0xFFB00F00, alignConstraints, InstName.Vst1M, T.Vst1MT3, IsaVersion.v80, InstFlags.None), + new(0xF9000200, 0xFFB00F00, InstName.Vst1M, T.Vst1MT4, IsaVersion.v80, InstFlags.None), + new(0xF9800100, 0xFFB00F00, sizeConstraints2, InstName.Vst21, T.Vst21T1, IsaVersion.v80, InstFlags.None), + new(0xF9800500, 0xFFB00F00, sizeConstraints2, InstName.Vst21, T.Vst21T2, IsaVersion.v80, InstFlags.None), + new(0xF9800900, 0xFFB00F20, sizeConstraints2, InstName.Vst21, T.Vst21T3, IsaVersion.v80, InstFlags.None), + new(0xF9000800, 0xFFB00E00, alignSizeConstraints, InstName.Vst2M, T.Vst2MT1, IsaVersion.v80, InstFlags.None), + new(0xF9000300, 0xFFB00F00, sizeConstraints3, InstName.Vst2M, T.Vst2MT2, IsaVersion.v80, InstFlags.None), + new(0xF9800200, 0xFFB00F10, sizeConstraints2, InstName.Vst31, T.Vst31T1, IsaVersion.v80, InstFlags.None), + new(0xF9800600, 0xFFB00F10, sizeConstraints2, InstName.Vst31, T.Vst31T2, IsaVersion.v80, InstFlags.None), + new(0xF9800A00, 0xFFB00F30, sizeConstraints2, InstName.Vst31, T.Vst31T3, IsaVersion.v80, InstFlags.None), + new(0xF9000400, 0xFFB00E00, sizeAlignConstraints, InstName.Vst3M, T.Vst3MT1, IsaVersion.v80, InstFlags.None), + new(0xF9800300, 0xFFB00F00, sizeConstraints2, InstName.Vst41, T.Vst41T1, IsaVersion.v80, InstFlags.None), + new(0xF9800700, 0xFFB00F00, sizeConstraints2, InstName.Vst41, T.Vst41T2, IsaVersion.v80, InstFlags.None), + new(0xF9800B00, 0xFFB00F00, sizeIndexAlignConstraints, InstName.Vst41, T.Vst41T3, IsaVersion.v80, InstFlags.None), + new(0xF9000000, 0xFFB00E00, sizeConstraints3, InstName.Vst4M, T.Vst4MT1, IsaVersion.v80, InstFlags.None), + new(0xEC000B00, 0xFE100F01, puwPwPuwPuwConstraints, InstName.Vstm, T.VstmT1, IsaVersion.v80, InstFlags.WBack), + new(0xEC000A00, 0xFE100F00, puwPwPuwPuwConstraints, InstName.Vstm, T.VstmT2, IsaVersion.v80, InstFlags.WBack), + new(0xED000A00, 0xFF300E00, InstName.Vstr, T.VstrT1, IsaVersion.v80, InstFlags.None), + new(0xED000900, 0xFF300F00, InstName.Vstr, T.VstrT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEF800600, 0xFF800F50, sizeVnVmConstraints, InstName.Vsubhn, T.VsubhnT1, IsaVersion.v80, InstFlags.None), + new(0xEF800200, 0xEF800F50, sizeVdOpvnConstraints, InstName.Vsubl, T.VsublT1, IsaVersion.v80, InstFlags.None), + new(0xEF800300, 0xEF800F50, sizeVdOpvnConstraints, InstName.Vsubw, T.VsubwT1, IsaVersion.v80, InstFlags.None), + new(0xEF200D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VsubF, T.VsubFT1, IsaVersion.v80, InstFlags.None), + new(0xEF300D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.VsubF, T.VsubFT1, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xEE300A40, 0xFFB00E50, InstName.VsubF, T.VsubFT2, IsaVersion.v80, InstFlags.None), + new(0xEE300940, 0xFFB00F50, InstName.VsubF, T.VsubFT2, IsaVersion.v80, IsaFeature.FeatFp16, InstFlags.None), + new(0xFF000800, 0xFF800F10, qvdQvnQvmConstraints, InstName.VsubI, T.VsubIT1, IsaVersion.v80, InstFlags.None), + new(0xFE800D10, 0xFFB00F10, qvdQvnConstraints, InstName.VsudotS, T.VsudotST1, IsaVersion.v82, IsaFeature.FeatAa32i8mm, InstFlags.None), + new(0xFFB20000, 0xFFBF0F90, qvdQvmConstraints, InstName.Vswp, T.VswpT1, IsaVersion.v80, InstFlags.None), + new(0xFFB00800, 0xFFB00C10, InstName.Vtbl, T.VtblT1, IsaVersion.v80, InstFlags.None), + new(0xFFB20080, 0xFFB30F90, sizeQvdQvmConstraints, InstName.Vtrn, T.VtrnT1, IsaVersion.v80, InstFlags.None), + new(0xEF000810, 0xFF800F10, qvdQvnQvmSizeConstraints, InstName.Vtst, T.VtstT1, IsaVersion.v80, InstFlags.None), + new(0xFC200D10, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vudot, T.VudotT1, IsaVersion.v82, IsaFeature.FeatDotprod, InstFlags.None), + new(0xFE200D10, 0xFFB00F10, qvdQvnConstraints, InstName.VudotS, T.VudotST1, IsaVersion.v82, IsaFeature.FeatDotprod, InstFlags.None), + new(0xFC200C50, 0xFFB00F50, vdVnVmConstraints, InstName.Vummla, T.VummlaT1, IsaVersion.v82, IsaFeature.FeatAa32i8mm, InstFlags.None), + new(0xFCA00D00, 0xFFB00F10, qvdQvnQvmConstraints, InstName.Vusdot, T.VusdotT1, IsaVersion.v82, IsaFeature.FeatAa32i8mm, InstFlags.None), + new(0xFE800D00, 0xFFB00F10, qvdQvnConstraints, InstName.VusdotS, T.VusdotST1, IsaVersion.v82, IsaFeature.FeatAa32i8mm, InstFlags.None), + new(0xFCA00C40, 0xFFB00F50, vdVnVmConstraints, InstName.Vusmmla, T.VusmmlaT1, IsaVersion.v82, IsaFeature.FeatAa32i8mm, InstFlags.None), + new(0xFFB20100, 0xFFB30F90, sizeQsizeQvdQvmConstraints, InstName.Vuzp, T.VuzpT1, IsaVersion.v80, InstFlags.None), + new(0xFFB20180, 0xFFB30F90, sizeQsizeQvdQvmConstraints, InstName.Vzip, T.VzipT1, IsaVersion.v80, InstFlags.None), + new(0xF3AF8002, 0xFFFFFFFF, InstName.Wfe, T.WfeT2, IsaVersion.v80, InstFlags.None), + new(0xF3AF8003, 0xFFFFFFFF, InstName.Wfi, T.WfiT2, IsaVersion.v80, InstFlags.None), + new(0xF3AF8001, 0xFFFFFFFF, InstName.Yield, T.YieldT2, IsaVersion.v80, InstFlags.None), + }; + + _table = new(insts); + } + + public static bool TryGetMeta(uint encoding, IsaVersion version, IsaFeature features, out InstMeta meta) + { + if (_table.TryFind(encoding, version, features, out InstInfoForTable info)) + { + meta = info.Meta; + + return true; + } + + meta = new(InstName.Udf, T.UdfA1, IsaVersion.v80, IsaFeature.None, InstFlags.None); + + return false; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/MultiBlock.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/MultiBlock.cs new file mode 100644 index 00000000..a213c222 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/MultiBlock.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + class MultiBlock + { + public readonly List<Block> Blocks; + public readonly bool HasHostCall; + public readonly bool IsTruncated; + + public MultiBlock(List<Block> blocks) + { + Blocks = blocks; + + Block block = blocks[0]; + + HasHostCall = block.HasHostCall; + + for (int index = 1; index < blocks.Count; index++) + { + block = blocks[index]; + + HasHostCall |= block.HasHostCall; + } + + block = blocks[^1]; + + IsTruncated = block.IsTruncated; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/PendingBranch.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/PendingBranch.cs new file mode 100644 index 00000000..8f48cd07 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/PendingBranch.cs @@ -0,0 +1,20 @@ +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + readonly struct PendingBranch + { + public readonly BranchType BranchType; + public readonly uint TargetAddress; + public readonly uint NextAddress; + public readonly InstName Name; + public readonly int WriterPointer; + + public PendingBranch(BranchType branchType, uint targetAddress, uint nextAddress, InstName name, int writerPointer) + { + BranchType = branchType; + TargetAddress = targetAddress; + NextAddress = nextAddress; + Name = name; + WriterPointer = writerPointer; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/RegisterAllocator.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/RegisterAllocator.cs new file mode 100644 index 00000000..6c705722 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/RegisterAllocator.cs @@ -0,0 +1,169 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System; +using System.Numerics; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + class RegisterAllocator + { + public const int MaxTemps = 1; + + private uint _gprMask; + private uint _fpSimdMask; + + public int FixedContextRegister { get; } + public int FixedPageTableRegister { get; } + + public uint UsedGprsMask { get; private set; } + public uint UsedFpSimdMask { get; private set; } + + public RegisterAllocator() + { + _gprMask = ushort.MaxValue; + _fpSimdMask = ushort.MaxValue; + + FixedContextRegister = AllocateTempRegisterWithPreferencing(); + FixedPageTableRegister = AllocateTempRegisterWithPreferencing(); + } + + public void MarkGprAsUsed(int index) + { + UsedGprsMask |= 1u << index; + } + + public void MarkFpSimdAsUsed(int index) + { + UsedFpSimdMask |= 1u << index; + } + + public void MarkFpSimdRangeAsUsed(int index, int count) + { + UsedFpSimdMask |= (uint.MaxValue >> (32 - count)) << index; + } + + public Operand RemapGprRegister(int index) + { + MarkGprAsUsed(index); + + return new Operand(OperandKind.Register, OperandType.I32, (ulong)index); + } + + public Operand RemapFpRegister(int index, bool isFP32) + { + MarkFpSimdAsUsed(index); + + return new Operand(OperandKind.Register, isFP32 ? OperandType.FP32 : OperandType.FP64, (ulong)index); + } + + public Operand RemapSimdRegister(int index) + { + MarkFpSimdAsUsed(index); + + return new Operand(OperandKind.Register, OperandType.V128, (ulong)index); + } + + public Operand RemapSimdRegister(int index, int count) + { + MarkFpSimdRangeAsUsed(index, count); + + return new Operand(OperandKind.Register, OperandType.V128, (ulong)index); + } + + public void EnsureTempGprRegisters(int count) + { + if (count != 0) + { + Span<int> registers = stackalloc int[count]; + + for (int index = 0; index < count; index++) + { + registers[index] = AllocateTempGprRegister(); + } + + for (int index = 0; index < count; index++) + { + FreeTempGprRegister(registers[index]); + } + } + } + + public int AllocateTempGprRegister() + { + int index = AllocateTempRegister(ref _gprMask, AbiConstants.ReservedRegsMask); + + MarkGprAsUsed(index); + + return index; + } + + private int AllocateTempRegisterWithPreferencing() + { + int firstCalleeSaved = BitOperations.TrailingZeroCount(~_gprMask & AbiConstants.GprCalleeSavedRegsMask); + if (firstCalleeSaved < 32) + { + uint regMask = 1u << firstCalleeSaved; + if ((regMask & AbiConstants.ReservedRegsMask) == 0) + { + _gprMask |= regMask; + + return firstCalleeSaved; + } + } + + return AllocateTempRegister(ref _gprMask, AbiConstants.ReservedRegsMask); + } + + public int AllocateTempFpSimdRegister() + { + int index = AllocateTempRegister(ref _fpSimdMask, 0); + + MarkFpSimdAsUsed(index); + + return index; + } + + public ScopedRegister AllocateTempGprRegisterScoped() + { + return new(this, new(OperandKind.Register, OperandType.I32, (ulong)AllocateTempGprRegister())); + } + + public ScopedRegister AllocateTempFpRegisterScoped(bool isFP32) + { + return new(this, new(OperandKind.Register, isFP32 ? OperandType.FP32 : OperandType.FP64, (ulong)AllocateTempFpSimdRegister())); + } + + public ScopedRegister AllocateTempSimdRegisterScoped() + { + return new(this, new(OperandKind.Register, OperandType.V128, (ulong)AllocateTempFpSimdRegister())); + } + + public void FreeTempGprRegister(int index) + { + FreeTempRegister(ref _gprMask, index); + } + + public void FreeTempFpSimdRegister(int index) + { + FreeTempRegister(ref _fpSimdMask, index); + } + + private static int AllocateTempRegister(ref uint mask, uint reservedMask) + { + int index = BitOperations.TrailingZeroCount(~(mask | reservedMask)); + if (index == sizeof(uint) * 8) + { + throw new InvalidOperationException("No free registers."); + } + + mask |= 1u << index; + + return index; + } + + private static void FreeTempRegister(ref uint mask, int index) + { + mask &= ~(1u << index); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/RegisterUtils.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/RegisterUtils.cs new file mode 100644 index 00000000..8fbdeb73 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/RegisterUtils.cs @@ -0,0 +1,109 @@ +using System; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + static class RegisterUtils + { + public const int SpRegister = 13; + public const int LrRegister = 14; + public const int PcRegister = 15; + + private const int RmBit = 0; + private const int RdRtBit = 12; + private const int RdHiRnBit = 16; + + private const int RdRtT16Bit = 16; + private const int RdRtT16AltBit = 24; + + private const int RdRt2RdHiT32Bit = 8; + private const int RdT32AltBit = 0; + private const int RtRdLoT32Bit = 12; + + public static int ExtractRt(uint encoding) + { + return (int)(encoding >> RdRtBit) & 0xf; + } + + public static int ExtractRt2(uint encoding) + { + return (int)GetRt2((uint)ExtractRt(encoding)); + } + + public static int ExtractRd(InstFlags flags, uint encoding) + { + return flags.HasFlag(InstFlags.Rd16) ? ExtractRn(encoding) : ExtractRd(encoding); + } + + public static int ExtractRd(uint encoding) + { + return (int)(encoding >> RdRtBit) & 0xf; + } + + public static int ExtractRdHi(uint encoding) + { + return (int)(encoding >> RdHiRnBit) & 0xf; + } + + public static int ExtractRn(uint encoding) + { + return (int)(encoding >> RdHiRnBit) & 0xf; + } + + public static int ExtractRm(uint encoding) + { + return (int)(encoding >> RmBit) & 0xf; + } + + public static uint GetRt2(uint rt) + { + return Math.Min(rt + 1, PcRegister); + } + + public static int ExtractRdn(InstFlags flags, uint encoding) + { + if (flags.HasFlag(InstFlags.Dn)) + { + return ((int)(encoding >> RdRtT16Bit) & 7) | (int)((encoding >> 4) & 8); + } + else + { + return ExtractRdT16(flags, encoding); + } + } + + public static int ExtractRdT16(InstFlags flags, uint encoding) + { + return flags.HasFlag(InstFlags.Rd16) ? (int)(encoding >> RdRtT16AltBit) & 7 : (int)(encoding >> RdRtT16Bit) & 7; + } + + public static int ExtractRtT16(InstFlags flags, uint encoding) + { + return flags.HasFlag(InstFlags.Rd16) ? (int)(encoding >> RdRtT16AltBit) & 7 : (int)(encoding >> RdRtT16Bit) & 7; + } + + public static int ExtractRdT32(InstFlags flags, uint encoding) + { + return flags.HasFlag(InstFlags.Rd16) ? (int)(encoding >> RdT32AltBit) & 0xf : (int)(encoding >> RdRt2RdHiT32Bit) & 0xf; + } + + public static int ExtractRdLoT32(uint encoding) + { + return (int)(encoding >> RtRdLoT32Bit) & 0xf; + } + + public static int ExtractRdHiT32(uint encoding) + { + return (int)(encoding >> RdRt2RdHiT32Bit) & 0xf; + } + + public static int ExtractRtT32(uint encoding) + { + return (int)(encoding >> RtRdLoT32Bit) & 0xf; + } + + public static int ExtractRt2T32(uint encoding) + { + return (int)(encoding >> RdRt2RdHiT32Bit) & 0xf; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/ScopedRegister.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/ScopedRegister.cs new file mode 100644 index 00000000..18b1416e --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/ScopedRegister.cs @@ -0,0 +1,39 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using System; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + readonly struct ScopedRegister : IDisposable + { + private readonly RegisterAllocator _registerAllocator; + private readonly Operand _operand; + private readonly bool _isAllocated; + + public readonly Operand Operand => _operand; + public readonly bool IsAllocated => _isAllocated; + + public ScopedRegister(RegisterAllocator registerAllocator, Operand operand, bool isAllocated = true) + { + _registerAllocator = registerAllocator; + _operand = operand; + _isAllocated = isAllocated; + } + + public readonly void Dispose() + { + if (!_isAllocated) + { + return; + } + + if (_operand.Type.IsInteger()) + { + _registerAllocator.FreeTempGprRegister(_operand.AsInt32()); + } + else + { + _registerAllocator.FreeTempFpSimdRegister(_operand.AsInt32()); + } + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs new file mode 100644 index 00000000..1e8a8915 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs @@ -0,0 +1,789 @@ +using ARMeilleure.Common; +using ARMeilleure.Memory; +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Numerics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class Compiler + { + public const uint UsableGprsMask = 0x7fff; + public const uint UsableFpSimdMask = 0xffff; + public const uint UsablePStateMask = 0xf0000000; + + private const int Encodable26BitsOffsetLimit = 0x2000000; + + private readonly struct Context + { + public readonly CodeWriter Writer; + public readonly RegisterAllocator RegisterAllocator; + public readonly MemoryManagerType MemoryManagerType; + public readonly TailMerger TailMerger; + public readonly AddressTable<ulong> FuncTable; + public readonly IntPtr DispatchStubPointer; + + private readonly RegisterSaveRestore _registerSaveRestore; + private readonly IntPtr _pageTablePointer; + + public Context( + CodeWriter writer, + RegisterAllocator registerAllocator, + MemoryManagerType mmType, + TailMerger tailMerger, + AddressTable<ulong> funcTable, + RegisterSaveRestore registerSaveRestore, + IntPtr dispatchStubPointer, + IntPtr pageTablePointer) + { + Writer = writer; + RegisterAllocator = registerAllocator; + MemoryManagerType = mmType; + TailMerger = tailMerger; + FuncTable = funcTable; + _registerSaveRestore = registerSaveRestore; + DispatchStubPointer = dispatchStubPointer; + _pageTablePointer = pageTablePointer; + } + + public readonly int GetReservedStackOffset() + { + return _registerSaveRestore.GetReservedStackOffset(); + } + + public readonly void WritePrologueAt(int instructionPointer) + { + CodeWriter writer = new(); + Assembler asm = new(writer); + + _registerSaveRestore.WritePrologue(ref asm); + + // If needed, set up the fixed registers with the pointers we will use. + // First one is the context pointer (passed as first argument), + // second one is the page table or address space base, it is at a fixed memory location and considered constant. + + if (RegisterAllocator.FixedContextRegister != 0) + { + asm.Mov(Register(RegisterAllocator.FixedContextRegister), Register(0)); + } + + asm.Mov(Register(RegisterAllocator.FixedPageTableRegister), (ulong)_pageTablePointer); + + LoadFromContext(ref asm); + + // Write the prologue at the specified position in our writer. + Writer.WriteInstructionsAt(instructionPointer, writer); + } + + public readonly void WriteEpilogueWithoutContext() + { + Assembler asm = new(Writer); + + _registerSaveRestore.WriteEpilogue(ref asm); + } + + public void LoadFromContext() + { + Assembler asm = new(Writer); + + LoadFromContext(ref asm); + } + + private void LoadFromContext(ref Assembler asm) + { + LoadGprFromContext(ref asm, RegisterAllocator.UsedGprsMask & UsableGprsMask, NativeContextOffsets.GprBaseOffset); + LoadFpSimdFromContext(ref asm, RegisterAllocator.UsedFpSimdMask & UsableFpSimdMask, NativeContextOffsets.FpSimdBaseOffset); + LoadPStateFromContext(ref asm, UsablePStateMask, NativeContextOffsets.FlagsBaseOffset); + } + + public void StoreToContext() + { + Assembler asm = new(Writer); + + StoreToContext(ref asm); + } + + private void StoreToContext(ref Assembler asm) + { + StoreGprToContext(ref asm, RegisterAllocator.UsedGprsMask & UsableGprsMask, NativeContextOffsets.GprBaseOffset); + StoreFpSimdToContext(ref asm, RegisterAllocator.UsedFpSimdMask & UsableFpSimdMask, NativeContextOffsets.FpSimdBaseOffset); + StorePStateToContext(ref asm, UsablePStateMask, NativeContextOffsets.FlagsBaseOffset); + } + + private void LoadGprFromContext(ref Assembler asm, uint mask, int baseOffset) + { + Operand contextPtr = Register(RegisterAllocator.FixedContextRegister); + + while (mask != 0) + { + int reg = BitOperations.TrailingZeroCount(mask); + int offset = baseOffset + reg * 8; + + if (reg < 31 && (mask & (2u << reg)) != 0 && offset < RegisterSaveRestore.Encodable9BitsOffsetLimit) + { + mask &= ~(3u << reg); + + asm.LdpRiUn(Register(reg), Register(reg + 1), contextPtr, offset); + } + else + { + mask &= ~(1u << reg); + + asm.LdrRiUn(Register(reg), contextPtr, offset); + } + } + } + + private void LoadFpSimdFromContext(ref Assembler asm, uint mask, int baseOffset) + { + Operand contextPtr = Register(RegisterAllocator.FixedContextRegister); + + while (mask != 0) + { + int reg = BitOperations.TrailingZeroCount(mask); + int offset = baseOffset + reg * 16; + + mask &= ~(1u << reg); + + asm.LdrRiUn(Register(reg, OperandType.V128), contextPtr, offset); + } + } + + private void LoadPStateFromContext(ref Assembler asm, uint mask, int baseOffset) + { + if (mask == 0) + { + return; + } + + Operand contextPtr = Register(RegisterAllocator.FixedContextRegister); + + using ScopedRegister tempRegister = RegisterAllocator.AllocateTempGprRegisterScoped(); + + asm.LdrRiUn(tempRegister.Operand, contextPtr, baseOffset); + asm.MsrNzcv(tempRegister.Operand); + } + + private void StoreGprToContext(ref Assembler asm, uint mask, int baseOffset) + { + Operand contextPtr = Register(RegisterAllocator.FixedContextRegister); + + while (mask != 0) + { + int reg = BitOperations.TrailingZeroCount(mask); + int offset = baseOffset + reg * 8; + + if (reg < 31 && (mask & (2u << reg)) != 0 && offset < RegisterSaveRestore.Encodable9BitsOffsetLimit) + { + mask &= ~(3u << reg); + + asm.StpRiUn(Register(reg), Register(reg + 1), contextPtr, offset); + } + else + { + mask &= ~(1u << reg); + + asm.StrRiUn(Register(reg), contextPtr, offset); + } + } + } + + private void StoreFpSimdToContext(ref Assembler asm, uint mask, int baseOffset) + { + Operand contextPtr = Register(RegisterAllocator.FixedContextRegister); + + while (mask != 0) + { + int reg = BitOperations.TrailingZeroCount(mask); + int offset = baseOffset + reg * 16; + + mask &= ~(1u << reg); + + asm.StrRiUn(Register(reg, OperandType.V128), contextPtr, offset); + } + } + + private void StorePStateToContext(ref Assembler asm, uint mask, int baseOffset) + { + if (mask == 0) + { + return; + } + + Operand contextPtr = Register(RegisterAllocator.FixedContextRegister); + + using ScopedRegister tempRegister = RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempRegister2 = RegisterAllocator.AllocateTempGprRegisterScoped(); + + asm.LdrRiUn(tempRegister.Operand, contextPtr, baseOffset); + asm.MrsNzcv(tempRegister2.Operand); + asm.And(tempRegister.Operand, tempRegister.Operand, InstEmitCommon.Const(0xfffffff)); + asm.Orr(tempRegister.Operand, tempRegister.Operand, tempRegister2.Operand); + asm.StrRiUn(tempRegister.Operand, contextPtr, baseOffset); + } + } + + public static CompiledFunction Compile(CpuPreset cpuPreset, IMemoryManager memoryManager, ulong address, AddressTable<ulong> funcTable, IntPtr dispatchStubPtr, bool isThumb) + { + MultiBlock multiBlock = Decoder<InstEmit>.DecodeMulti(cpuPreset, memoryManager, address, isThumb); + + Dictionary<ulong, int> targets = new(); + + CodeWriter writer = new(); + RegisterAllocator regAlloc = new(); + Assembler asm = new(writer); + CodeGenContext cgContext = new(writer, asm, regAlloc, memoryManager.Type, isThumb); + ArmCondition lastCondition = ArmCondition.Al; + int lastConditionIp = 0; + + // Required for load/store to context. + regAlloc.EnsureTempGprRegisters(2); + + ulong pc = address; + + for (int blockIndex = 0; blockIndex < multiBlock.Blocks.Count; blockIndex++) + { + Block block = multiBlock.Blocks[blockIndex]; + + Debug.Assert(block.Address == pc); + + targets.Add(pc, writer.InstructionPointer); + + for (int index = 0; index < block.Instructions.Count; index++) + { + InstInfo instInfo = block.Instructions[index]; + + if (index < block.Instructions.Count - 1) + { + cgContext.SetNextInstruction(block.Instructions[index + 1]); + } + else + { + cgContext.SetNextInstruction(default); + } + + SetConditionalStart(cgContext, ref lastCondition, ref lastConditionIp, instInfo.Name, instInfo.Flags, instInfo.Encoding); + + if (block.IsLoopEnd && index == block.Instructions.Count - 1) + { + // If this is a loop, the code might run for a long time uninterrupted. + // We insert a "sync point" here to ensure the loop can be interrupted if needed. + + cgContext.AddPendingSyncPoint(); + + asm.B(0); + } + + cgContext.SetPc((uint)pc); + + instInfo.EmitFunc(cgContext, instInfo.Encoding); + + if (cgContext.ConsumeNzcvModified()) + { + ForceConditionalEnd(cgContext, ref lastCondition, lastConditionIp); + } + + cgContext.UpdateItState(); + + pc += instInfo.Flags.HasFlag(InstFlags.Thumb16) ? 2UL : 4UL; + } + + if (Decoder<InstEmit>.WritesToPC(block.Instructions[^1].Encoding, block.Instructions[^1].Name, block.Instructions[^1].Flags, block.IsThumb)) + { + // If the block ends with a PC register write, then we have a branch from register. + + InstEmitCommon.SetThumbFlag(cgContext, regAlloc.RemapGprRegister(RegisterUtils.PcRegister)); + + cgContext.AddPendingIndirectBranch(block.Instructions[^1].Name, RegisterUtils.PcRegister); + + asm.B(0); + } + + ForceConditionalEnd(cgContext, ref lastCondition, lastConditionIp); + } + + RegisterSaveRestore rsr = new( + regAlloc.UsedGprsMask & AbiConstants.GprCalleeSavedRegsMask, + regAlloc.UsedFpSimdMask & AbiConstants.FpSimdCalleeSavedRegsMask, + OperandType.FP64, + multiBlock.HasHostCall, + multiBlock.HasHostCall ? CalculateStackSizeForCallSpill(regAlloc.UsedGprsMask, regAlloc.UsedFpSimdMask, UsablePStateMask) : 0); + + TailMerger tailMerger = new(); + + Context context = new(writer, regAlloc, memoryManager.Type, tailMerger, funcTable, rsr, dispatchStubPtr, memoryManager.PageTablePointer); + + InstInfo lastInstruction = multiBlock.Blocks[^1].Instructions[^1]; + bool lastInstIsConditional = GetCondition(lastInstruction, isThumb) != ArmCondition.Al; + + if (multiBlock.IsTruncated || lastInstIsConditional || lastInstruction.Name.IsCall() || IsConditionalBranch(lastInstruction)) + { + WriteTailCallConstant(context, ref asm, (uint)pc); + } + + IEnumerable<PendingBranch> pendingBranches = cgContext.GetPendingBranches(); + + foreach (PendingBranch pendingBranch in pendingBranches) + { + RewriteBranchInstructionWithTarget(context, pendingBranch, targets); + } + + tailMerger.WriteReturn(writer, context.WriteEpilogueWithoutContext); + + context.WritePrologueAt(0); + + return new(writer.AsByteSpan(), (int)(pc - address)); + } + + private static int CalculateStackSizeForCallSpill(uint gprUseMask, uint fpSimdUseMask, uint pStateUseMask) + { + // Note that we don't discard callee saved FP/SIMD register because only the lower 64 bits is callee saved, + // so if the function is using the full register, that won't be enough. + // We could do better, but it's likely not worth it since this case happens very rarely in practice. + + return BitOperations.PopCount(gprUseMask & ~AbiConstants.GprCalleeSavedRegsMask) * 8 + + BitOperations.PopCount(fpSimdUseMask) * 16 + + (pStateUseMask != 0 ? 8 : 0); + } + + private static void SetConditionalStart( + CodeGenContext context, + ref ArmCondition condition, + ref int instructionPointer, + InstName name, + InstFlags flags, + uint encoding) + { + if (!context.ConsumeItCondition(out ArmCondition currentCond)) + { + currentCond = GetCondition(name, flags, encoding, context.IsThumb); + } + + if (currentCond != condition) + { + WriteConditionalEnd(context, condition, instructionPointer); + + condition = currentCond; + + if (currentCond != ArmCondition.Al) + { + instructionPointer = context.CodeWriter.InstructionPointer; + context.Arm64Assembler.B(currentCond.Invert(), 0); + } + } + } + + private static bool IsConditionalBranch(in InstInfo instInfo) + { + return instInfo.Name == InstName.B && (ArmCondition)(instInfo.Encoding >> 28) != ArmCondition.Al; + } + + private static ArmCondition GetCondition(in InstInfo instInfo, bool isThumb) + { + return GetCondition(instInfo.Name, instInfo.Flags, instInfo.Encoding, isThumb); + } + + private static ArmCondition GetCondition(InstName name, InstFlags flags, uint encoding, bool isThumb) + { + // For branch, we handle conditional execution on the instruction itself. + bool hasCond = flags.HasFlag(InstFlags.Cond) && !CanHandleConditionalInstruction(name, encoding, isThumb); + + return hasCond ? (ArmCondition)(encoding >> 28) : ArmCondition.Al; + } + + private static bool CanHandleConditionalInstruction(InstName name, uint encoding, bool isThumb) + { + if (name == InstName.B) + { + return true; + } + + // We can use CSEL for conditional MOV from registers, as long the instruction is not setting flags. + // We don't handle thumb right now because the condition comes from the IT block which would be more complicated to handle. + if (name == InstName.MovR && !isThumb && (encoding & (1u << 20)) == 0) + { + return true; + } + + return false; + } + + private static void ForceConditionalEnd(CodeGenContext context, ref ArmCondition condition, int instructionPointer) + { + WriteConditionalEnd(context, condition, instructionPointer); + + condition = ArmCondition.Al; + } + + private static void WriteConditionalEnd(CodeGenContext context, ArmCondition condition, int instructionPointer) + { + if (condition != ArmCondition.Al) + { + int delta = context.CodeWriter.InstructionPointer - instructionPointer; + uint branchInst = context.CodeWriter.ReadInstructionAt(instructionPointer) | (((uint)delta & 0x7ffff) << 5); + Debug.Assert((int)((branchInst & ~0x1fu) << 8) >> 11 == delta * 4); + + context.CodeWriter.WriteInstructionAt(instructionPointer, branchInst); + } + } + + private static void RewriteBranchInstructionWithTarget(in Context context, in PendingBranch pendingBranch, Dictionary<ulong, int> targets) + { + switch (pendingBranch.BranchType) + { + case BranchType.Branch: + RewriteBranchInstructionWithTarget(context, pendingBranch.Name, pendingBranch.TargetAddress, pendingBranch.WriterPointer, targets); + break; + case BranchType.Call: + RewriteCallInstructionWithTarget(context, pendingBranch.TargetAddress, pendingBranch.NextAddress, pendingBranch.WriterPointer); + break; + case BranchType.IndirectBranch: + RewriteIndirectBranchInstructionWithTarget(context, pendingBranch.Name, pendingBranch.TargetAddress, pendingBranch.WriterPointer); + break; + case BranchType.TableBranchByte: + case BranchType.TableBranchHalfword: + RewriteTableBranchInstructionWithTarget( + context, + pendingBranch.BranchType == BranchType.TableBranchHalfword, + pendingBranch.TargetAddress, + pendingBranch.NextAddress, + pendingBranch.WriterPointer); + break; + case BranchType.IndirectCall: + RewriteIndirectCallInstructionWithTarget(context, pendingBranch.TargetAddress, pendingBranch.NextAddress, pendingBranch.WriterPointer); + break; + case BranchType.SyncPoint: + case BranchType.SoftwareInterrupt: + case BranchType.ReadCntpct: + RewriteHostCall(context, pendingBranch.Name, pendingBranch.BranchType, pendingBranch.TargetAddress, pendingBranch.NextAddress, pendingBranch.WriterPointer); + break; + default: + Debug.Fail($"Invalid branch type '{pendingBranch.BranchType}'"); + break; + } + } + + private static void RewriteBranchInstructionWithTarget(in Context context, InstName name, uint targetAddress, int branchIndex, Dictionary<ulong, int> targets) + { + CodeWriter writer = context.Writer; + Assembler asm = new(writer); + + int delta; + int targetIndex; + uint encoding = writer.ReadInstructionAt(branchIndex); + + if (encoding == 0x14000000) + { + // Unconditional branch. + + if (targets.TryGetValue(targetAddress, out targetIndex)) + { + delta = targetIndex - branchIndex; + + if (delta >= -Encodable26BitsOffsetLimit && delta < Encodable26BitsOffsetLimit) + { + writer.WriteInstructionAt(branchIndex, encoding | (uint)(delta & 0x3ffffff)); + + return; + } + } + + targetIndex = writer.InstructionPointer; + delta = targetIndex - branchIndex; + + writer.WriteInstructionAt(branchIndex, encoding | (uint)(delta & 0x3ffffff)); + WriteTailCallConstant(context, ref asm, targetAddress); + } + else + { + // Conditional branch. + + uint branchMask = 0x7ffff; + int branchMax = (int)(branchMask + 1) / 2; + + if (targets.TryGetValue(targetAddress, out targetIndex)) + { + delta = targetIndex - branchIndex; + + if (delta >= -branchMax && delta < branchMax) + { + writer.WriteInstructionAt(branchIndex, encoding | (uint)((delta & branchMask) << 5)); + + return; + } + } + + targetIndex = writer.InstructionPointer; + delta = targetIndex - branchIndex; + + if (delta >= -branchMax && delta < branchMax) + { + writer.WriteInstructionAt(branchIndex, encoding | (uint)((delta & branchMask) << 5)); + WriteTailCallConstant(context, ref asm, targetAddress); + } + else + { + // If the branch target is too far away, we use a regular unconditional branch + // instruction instead which has a much higher range. + // We branch directly to the end of the function, where we put the conditional branch, + // and then branch back to the next instruction or return the branch target depending + // on the branch being taken or not. + + uint branchInst = 0x14000000u | ((uint)delta & 0x3ffffff); + Debug.Assert((int)(branchInst << 6) >> 4 == delta * 4); + + writer.WriteInstructionAt(branchIndex, branchInst); + + int movedBranchIndex = writer.InstructionPointer; + + writer.WriteInstruction(0u); // Placeholder + asm.B((branchIndex + 1 - writer.InstructionPointer) * 4); + + delta = writer.InstructionPointer - movedBranchIndex; + + writer.WriteInstructionAt(movedBranchIndex, encoding | (uint)((delta & branchMask) << 5)); + WriteTailCallConstant(context, ref asm, targetAddress); + } + } + + Debug.Assert(name == InstName.B || name == InstName.Cbnz, $"Unknown branch instruction \"{name}\"."); + } + + private static void RewriteCallInstructionWithTarget(in Context context, uint targetAddress, uint nextAddress, int branchIndex) + { + CodeWriter writer = context.Writer; + Assembler asm = new(writer); + + WriteBranchToCurrentPosition(context, branchIndex); + + asm.Mov(context.RegisterAllocator.RemapGprRegister(RegisterUtils.LrRegister), nextAddress); + + context.StoreToContext(); + InstEmitFlow.WriteCallWithGuestAddress( + writer, + ref asm, + context.RegisterAllocator, + context.TailMerger, + context.WriteEpilogueWithoutContext, + context.FuncTable, + context.DispatchStubPointer, + context.GetReservedStackOffset(), + nextAddress, + InstEmitCommon.Const((int)targetAddress)); + context.LoadFromContext(); + + // Branch back to the next instruction (after the call). + asm.B((branchIndex + 1 - writer.InstructionPointer) * 4); + } + + private static void RewriteIndirectBranchInstructionWithTarget(in Context context, InstName name, uint targetRegister, int branchIndex) + { + CodeWriter writer = context.Writer; + Assembler asm = new(writer); + + WriteBranchToCurrentPosition(context, branchIndex); + + using ScopedRegister target = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + asm.And(target.Operand, context.RegisterAllocator.RemapGprRegister((int)targetRegister), InstEmitCommon.Const(~1)); + + context.StoreToContext(); + + if ((name == InstName.Bx && targetRegister == RegisterUtils.LrRegister) || + name == InstName.Ldm || + name == InstName.Ldmda || + name == InstName.Ldmdb || + name == InstName.Ldmib) + { + // Arm32 does not have a return instruction, instead returns are implemented + // either using BX LR (for leaf functions), or POP { ... PC }. + + asm.Mov(Register(0), target.Operand); + + context.TailMerger.AddUnconditionalReturn(writer, asm); + } + else + { + InstEmitFlow.WriteCallWithGuestAddress( + writer, + ref asm, + context.RegisterAllocator, + context.TailMerger, + context.WriteEpilogueWithoutContext, + context.FuncTable, + context.DispatchStubPointer, + context.GetReservedStackOffset(), + 0u, + target.Operand, + isTail: true); + } + } + + private static void RewriteTableBranchInstructionWithTarget(in Context context, bool halfword, uint rn, uint rm, int branchIndex) + { + CodeWriter writer = context.Writer; + Assembler asm = new(writer); + + WriteBranchToCurrentPosition(context, branchIndex); + + using ScopedRegister target = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + asm.Add( + target.Operand, + context.RegisterAllocator.RemapGprRegister((int)rn), + context.RegisterAllocator.RemapGprRegister((int)rm), + ArmShiftType.Lsl, + halfword ? 1 : 0); + + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, asm, target.Operand, target.Operand); + + if (halfword) + { + asm.LdrhRiUn(target.Operand, target.Operand, 0); + } + else + { + asm.LdrbRiUn(target.Operand, target.Operand, 0); + } + + asm.Add(target.Operand, context.RegisterAllocator.RemapGprRegister(RegisterUtils.PcRegister), target.Operand, ArmShiftType.Lsl, 1); + + context.StoreToContext(); + + InstEmitFlow.WriteCallWithGuestAddress( + writer, + ref asm, + context.RegisterAllocator, + context.TailMerger, + context.WriteEpilogueWithoutContext, + context.FuncTable, + context.DispatchStubPointer, + context.GetReservedStackOffset(), + 0u, + target.Operand, + isTail: true); + } + + private static void RewriteIndirectCallInstructionWithTarget(in Context context, uint targetRegister, uint nextAddress, int branchIndex) + { + CodeWriter writer = context.Writer; + Assembler asm = new(writer); + + WriteBranchToCurrentPosition(context, branchIndex); + + using ScopedRegister target = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + asm.And(target.Operand, context.RegisterAllocator.RemapGprRegister((int)targetRegister), InstEmitCommon.Const(~1)); + asm.Mov(context.RegisterAllocator.RemapGprRegister(RegisterUtils.LrRegister), nextAddress); + + context.StoreToContext(); + InstEmitFlow.WriteCallWithGuestAddress( + writer, + ref asm, + context.RegisterAllocator, + context.TailMerger, + context.WriteEpilogueWithoutContext, + context.FuncTable, + context.DispatchStubPointer, + context.GetReservedStackOffset(), + nextAddress & ~1u, + target.Operand); + context.LoadFromContext(); + + // Branch back to the next instruction (after the call). + asm.B((branchIndex + 1 - writer.InstructionPointer) * 4); + } + + private static void RewriteHostCall(in Context context, InstName name, BranchType type, uint imm, uint pc, int branchIndex) + { + CodeWriter writer = context.Writer; + Assembler asm = new(writer); + + uint encoding = writer.ReadInstructionAt(branchIndex); + int targetIndex = writer.InstructionPointer; + int delta = targetIndex - branchIndex; + + writer.WriteInstructionAt(branchIndex, encoding | (uint)(delta & 0x3ffffff)); + + switch (type) + { + case BranchType.SyncPoint: + InstEmitSystem.WriteSyncPoint(context.Writer, context.RegisterAllocator, context.TailMerger, context.GetReservedStackOffset()); + break; + case BranchType.SoftwareInterrupt: + context.StoreToContext(); + switch (name) + { + case InstName.Bkpt: + InstEmitSystem.WriteBkpt(context.Writer, context.RegisterAllocator, context.TailMerger, context.GetReservedStackOffset(), pc, imm); + break; + case InstName.Svc: + InstEmitSystem.WriteSvc(context.Writer, context.RegisterAllocator, context.TailMerger, context.GetReservedStackOffset(), pc, imm); + break; + case InstName.Udf: + InstEmitSystem.WriteUdf(context.Writer, context.RegisterAllocator, context.TailMerger, context.GetReservedStackOffset(), pc, imm); + break; + } + context.LoadFromContext(); + break; + case BranchType.ReadCntpct: + InstEmitSystem.WriteReadCntpct(context.Writer, context.RegisterAllocator, context.GetReservedStackOffset(), (int)imm, (int)pc); + break; + default: + Debug.Fail($"Invalid branch type '{type}'"); + break; + } + + // Branch back to the next instruction. + asm.B((branchIndex + 1 - writer.InstructionPointer) * 4); + } + + private static void WriteBranchToCurrentPosition(in Context context, int branchIndex) + { + CodeWriter writer = context.Writer; + + int targetIndex = writer.InstructionPointer; + + if (branchIndex + 1 == targetIndex) + { + writer.RemoveLastInstruction(); + } + else + { + uint encoding = writer.ReadInstructionAt(branchIndex); + int delta = targetIndex - branchIndex; + + writer.WriteInstructionAt(branchIndex, encoding | (uint)(delta & 0x3ffffff)); + } + } + + private static void WriteTailCallConstant(in Context context, ref Assembler asm, uint address) + { + context.StoreToContext(); + InstEmitFlow.WriteCallWithGuestAddress( + context.Writer, + ref asm, + context.RegisterAllocator, + context.TailMerger, + context.WriteEpilogueWithoutContext, + context.FuncTable, + context.DispatchStubPointer, + context.GetReservedStackOffset(), + 0u, + InstEmitCommon.Const((int)address), + isTail: true); + } + + private static Operand Register(int register, OperandType type = OperandType.I64) + { + return new Operand(register, RegisterType.Integer, type); + } + + public static void PrintStats() + { + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmit.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmit.cs new file mode 100644 index 00000000..48891932 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmit.cs @@ -0,0 +1,8502 @@ +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + class InstEmit : IInstEmit + { + public static void AdcIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.AdcI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm12), inst.S != 0); + } + + public static void AdcIT1(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.AdcI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void AdcRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.AdcR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void AdcRT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdnb16w3 inst = new(encoding); + + InstEmitAlu.AdcR(context, inst.Rdn, inst.Rdn, inst.Rm, 0, 0, !context.InITBlock); + } + + public static void AdcRT2(CodeGenContext context, uint encoding) + { + InstSb20w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.AdcR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void AdcRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.AdcRr(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void AddIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.AddI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm12), inst.S != 0); + } + + public static void AddIT1(CodeGenContext context, uint encoding) + { + InstImm3b22w3Rnb19w3Rdb16w3 inst = new(encoding); + + InstEmitAlu.AddI(context, inst.Rd, inst.Rn, inst.Imm3, !context.InITBlock); + } + + public static void AddIT2(CodeGenContext context, uint encoding) + { + InstRdnb24w3Imm8b16w8 inst = new(encoding); + + InstEmitAlu.AddI(context, inst.Rdn, inst.Rdn, inst.Imm8, !context.InITBlock); + } + + public static void AddIT3(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.AddI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void AddIT4(CodeGenContext context, uint encoding) + { + InstIb26w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.AddI(context, inst.Rd, inst.Rn, ImmUtils.CombineImmU12(inst.Imm8, inst.Imm3, inst.I), false); + } + + public static void AddRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.AddR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void AddRT1(CodeGenContext context, uint encoding) + { + InstRmb22w3Rnb19w3Rdb16w3 inst = new(encoding); + + InstEmitAlu.AddR(context, inst.Rd, inst.Rn, inst.Rm, 0, 0, !context.InITBlock); + } + + public static void AddRT2(CodeGenContext context, uint encoding) + { + InstDnb23w1Rmb19w4Rdnb16w3 inst = new(encoding); + + uint rdn = (inst.Dn << 3) | inst.Rdn; + + InstEmitAlu.AddR(context, rdn, rdn, inst.Rm, 0, 0, false); + } + + public static void AddRT3(CodeGenContext context, uint encoding) + { + InstSb20w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.AddR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void AddRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.AddRr(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void AddSpIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.AddI(context, inst.Rd, RegisterUtils.SpRegister, ImmUtils.ExpandImm(inst.Imm12), inst.S != 0); + } + + public static void AddSpIT1(CodeGenContext context, uint encoding) + { + InstRdb24w3Imm8b16w8 inst = new(encoding); + + InstEmitAlu.AddI(context, inst.Rd, RegisterUtils.SpRegister, inst.Imm8 << 2, false); + } + + public static void AddSpIT2(CodeGenContext context, uint encoding) + { + InstImm7b16w7 inst = new(encoding); + + InstEmitAlu.AddI(context, RegisterUtils.SpRegister, RegisterUtils.SpRegister, inst.Imm7 << 2, false); + } + + public static void AddSpIT3(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.AddI(context, inst.Rd, RegisterUtils.SpRegister, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void AddSpIT4(CodeGenContext context, uint encoding) + { + InstIb26w1Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.AddI(context, inst.Rd, RegisterUtils.SpRegister, ImmUtils.CombineImmU12(inst.Imm8, inst.Imm3, inst.I), false); + } + + public static void AddSpRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.AddR(context, inst.Rd, RegisterUtils.SpRegister, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void AddSpRT1(CodeGenContext context, uint encoding) + { + InstDmb23w1Rdmb16w3 inst = new(encoding); + + uint rdm = inst.Rdm | (inst.Dm << 3); + + InstEmitAlu.AddR(context, rdm, RegisterUtils.SpRegister, rdm, 0, 0, false); + } + + public static void AddSpRT2(CodeGenContext context, uint encoding) + { + InstRmb19w4 inst = new(encoding); + + InstEmitAlu.AddR(context, RegisterUtils.SpRegister, RegisterUtils.SpRegister, inst.Rm, 0, 0, false); + } + + public static void AddSpRT3(CodeGenContext context, uint encoding) + { + InstSb20w1Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.AddR(context, inst.Rd, RegisterUtils.SpRegister, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void AdrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.Adr(context, inst.Rd, ImmUtils.ExpandImm(inst.Imm12), true); + } + + public static void AdrA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.Adr(context, inst.Rd, ImmUtils.ExpandImm(inst.Imm12), false); + } + + public static void AdrT1(CodeGenContext context, uint encoding) + { + InstRdb24w3Imm8b16w8 inst = new(encoding); + + InstEmitAlu.Adr(context, inst.Rd, inst.Imm8 << 2, true); + } + + public static void AdrT2(CodeGenContext context, uint encoding) + { + InstIb26w1Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.Adr(context, inst.Rd, ImmUtils.CombineImmU12(inst.Imm8, inst.Imm3, inst.I), false); + } + + public static void AdrT3(CodeGenContext context, uint encoding) + { + InstIb26w1Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.Adr(context, inst.Rd, ImmUtils.CombineImmU12(inst.Imm8, inst.Imm3, inst.I), true); + } + + public static void AesdA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCrypto.Aesd(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void AesdT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCrypto.Aesd(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void AeseA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCrypto.Aese(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void AeseT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCrypto.Aese(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void AesimcA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCrypto.Aesimc(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void AesimcT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCrypto.Aesimc(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void AesmcA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCrypto.Aesmc(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void AesmcT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCrypto.Aesmc(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void AndIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.AndI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm12), ImmUtils.ExpandedImmRotated(inst.Imm12), inst.S != 0); + } + + public static void AndIT1(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.AndI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), ImmUtils.ExpandedImmRotated(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void AndRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.AndR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void AndRT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdnb16w3 inst = new(encoding); + + InstEmitAlu.AndR(context, inst.Rdn, inst.Rdn, inst.Rm, 0, 0, !context.InITBlock); + } + + public static void AndRT2(CodeGenContext context, uint encoding) + { + InstSb20w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.AndR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void AndRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.AndRr(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void BA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Imm24b0w24 inst = new(encoding); + + InstEmitFlow.B(context, ImmUtils.ExtractSImm24Times4(inst.Imm24), (ArmCondition)inst.Cond); + } + + public static void BT1(CodeGenContext context, uint encoding) + { + InstCondb24w4Imm8b16w8 inst = new(encoding); + + InstEmitFlow.B(context, ImmUtils.ExtractT16SImm8Times2(inst.Imm8), (ArmCondition)inst.Cond); + } + + public static void BT2(CodeGenContext context, uint encoding) + { + InstImm11b16w11 inst = new(encoding); + + InstEmitFlow.B(context, ImmUtils.ExtractT16SImm11Times2(inst.Imm11), ArmCondition.Al); + } + + public static void BT3(CodeGenContext context, uint encoding) + { + InstSb26w1Condb22w4Imm6b16w6J1b13w1J2b11w1Imm11b0w11 inst = new(encoding); + + InstEmitFlow.B(context, ImmUtils.CombineSImm20Times2(inst.Imm11, inst.Imm6, inst.J1, inst.J2, inst.S), (ArmCondition)inst.Cond); + } + + public static void BT4(CodeGenContext context, uint encoding) + { + InstSb26w1Imm10b16w10J1b13w1J2b11w1Imm11b0w11 inst = new(encoding); + + InstEmitFlow.B(context, ImmUtils.CombineSImm24Times2(inst.Imm11, inst.Imm10, inst.J1, inst.J2, inst.S), ArmCondition.Al); + } + + public static void BfcA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Msbb16w5Rdb12w4Lsbb7w5 inst = new(encoding); + + InstEmitBit.Bfc(context, inst.Rd, inst.Lsb, inst.Msb); + } + + public static void BfcT1(CodeGenContext context, uint encoding) + { + InstImm3b12w3Rdb8w4Imm2b6w2Msbb0w5 inst = new(encoding); + + InstEmitBit.Bfc(context, inst.Rd, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.Msb); + } + + public static void BfiA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Msbb16w5Rdb12w4Lsbb7w5Rnb0w4 inst = new(encoding); + + InstEmitBit.Bfi(context, inst.Rd, inst.Rn, inst.Lsb, inst.Msb); + } + + public static void BfiT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Imm3b12w3Rdb8w4Imm2b6w2Msbb0w5 inst = new(encoding); + + InstEmitBit.Bfi(context, inst.Rd, inst.Rn, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.Msb); + } + + public static void BicIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.BicI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm12), ImmUtils.ExpandedImmRotated(inst.Imm12), inst.S != 0); + } + + public static void BicIT1(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.BicI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), ImmUtils.ExpandedImmRotated(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void BicRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.BicR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void BicRT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdnb16w3 inst = new(encoding); + + InstEmitAlu.BicR(context, inst.Rdn, inst.Rdn, inst.Rm, 0, 0, !context.InITBlock); + } + + public static void BicRT2(CodeGenContext context, uint encoding) + { + InstSb20w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.BicR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void BicRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.BicRr(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void BkptA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Imm12b8w12Imm4b0w4 inst = new(encoding); + + InstEmitSystem.Bkpt(context, ImmUtils.CombineImmU16(inst.Imm12, inst.Imm4)); + } + + public static void BkptT1(CodeGenContext context, uint encoding) + { + InstImm8b16w8 inst = new(encoding); + + InstEmitSystem.Bkpt(context, inst.Imm8); + } + + public static void BlxRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rmb0w4 inst = new(encoding); + + InstEmitFlow.Blx(context, inst.Rm, false); + } + + public static void BlxRT1(CodeGenContext context, uint encoding) + { + InstRmb19w4 inst = new(encoding); + + InstEmitFlow.Blx(context, inst.Rm, true); + } + + public static void BlIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Imm24b0w24 inst = new(encoding); + + InstEmitFlow.Bl(context, ImmUtils.ExtractSImm24Times4(inst.Imm24), false, false); + } + + public static void BlIA2(CodeGenContext context, uint encoding) + { + InstHb24w1Imm24b0w24 inst = new(encoding); + + InstEmitFlow.Bl(context, ImmUtils.ExtractSImm24Times4(inst.Imm24) | ((int)inst.H << 1), false, true); + } + + public static void BlIT1(CodeGenContext context, uint encoding) + { + InstSb26w1Imm10b16w10J1b13w1J2b11w1Imm11b0w11 inst = new(encoding); + + InstEmitFlow.Bl(context, ImmUtils.CombineSImm24Times2(inst.Imm11, inst.Imm10, inst.J1, inst.J2, inst.S), true, true); + } + + public static void BlIT2(CodeGenContext context, uint encoding) + { + InstSb26w1Imm10hb16w10J1b13w1J2b11w1Imm10lb1w10Hb0w1 inst = new(encoding); + + InstEmitFlow.Bl(context, ImmUtils.CombineSImm24Times4(inst.Imm10l, inst.Imm10h, inst.J1, inst.J2, inst.S), true, false); + } + + public static void BxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rmb0w4 inst = new(encoding); + + InstEmitFlow.Bx(context, inst.Rm); + } + + public static void BxT1(CodeGenContext context, uint encoding) + { + InstRmb19w4 inst = new(encoding); + + InstEmitFlow.Bx(context, inst.Rm); + } + + public static void BxjA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rmb0w4 inst = new(encoding); + + InstEmitFlow.Bx(context, inst.Rm); + } + + public static void BxjT1(CodeGenContext context, uint encoding) + { + InstRmb16w4 inst = new(encoding); + + InstEmitFlow.Bx(context, inst.Rm); + } + + public static void CbnzT1(CodeGenContext context, uint encoding) + { + InstOpb27w1Ib25w1Imm5b19w5Rnb16w3 inst = new(encoding); + + InstEmitFlow.Cbnz(context, inst.Rn, (int)((inst.Imm5 << 1) | (inst.I << 6)), inst.Op != 0); + } + + public static void ClrbhbA1(CodeGenContext context, uint encoding) + { + _ = new InstCondb28w4(encoding); + + throw new NotImplementedException(); + } + + public static void ClrbhbT1(CodeGenContext context, uint encoding) + { + throw new NotImplementedException(); + } + + public static void ClrexA1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Clrex(); + } + + public static void ClrexT1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Clrex(); + } + + public static void ClzA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitBit.Clz(context, inst.Rd, inst.Rm); + } + + public static void ClzT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitBit.Clz(context, inst.Rd, inst.Rm); + } + + public static void CmnIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.CmnI(context, inst.Rn, ImmUtils.ExpandImm(inst.Imm12)); + } + + public static void CmnIT1(CodeGenContext context, uint encoding) + { + InstIb26w1Rnb16w4Imm3b12w3Imm8b0w8 inst = new(encoding); + + InstEmitAlu.CmnI(context, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I)); + } + + public static void CmnRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.CmnR(context, inst.Rn, inst.Rm, inst.Stype, inst.Imm5); + } + + public static void CmnRT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rnb16w3 inst = new(encoding); + + InstEmitAlu.CmnR(context, inst.Rn, inst.Rm, 0, 0); + } + + public static void CmnRT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Imm3b12w3Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.CmnR(context, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3)); + } + + public static void CmnRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.CmnRr(context, inst.Rn, inst.Rm, inst.Stype, inst.Rs); + } + + public static void CmpIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.CmpI(context, inst.Rn, ImmUtils.ExpandImm(inst.Imm12)); + } + + public static void CmpIT1(CodeGenContext context, uint encoding) + { + InstRnb24w3Imm8b16w8 inst = new(encoding); + + InstEmitAlu.CmpI(context, inst.Rn, inst.Imm8); + } + + public static void CmpIT2(CodeGenContext context, uint encoding) + { + InstIb26w1Rnb16w4Imm3b12w3Imm8b0w8 inst = new(encoding); + + InstEmitAlu.CmpI(context, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I)); + } + + public static void CmpRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.CmpR(context, inst.Rn, inst.Rm, inst.Stype, inst.Imm5); + } + + public static void CmpRT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rnb16w3 inst = new(encoding); + + InstEmitAlu.CmpR(context, inst.Rn, inst.Rm, 0, 0); + } + + public static void CmpRT2(CodeGenContext context, uint encoding) + { + InstNb23w1Rmb19w4Rnb16w3 inst = new(encoding); + + InstEmitAlu.CmpR(context, inst.Rn | (inst.N << 3), inst.Rm, 0, 0); + } + + public static void CmpRT3(CodeGenContext context, uint encoding) + { + InstRnb16w4Imm3b12w3Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.CmpR(context, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3)); + } + + public static void CmpRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.CmpRr(context, inst.Rn, inst.Rm, inst.Stype, inst.Rs); + } + + public static void CpsA1(CodeGenContext context, uint encoding) + { + InstImodb18w2Mb17w1Ab8w1Ib7w1Fb6w1Modeb0w5 inst = new(encoding); + + InstEmitSystem.Cps(context, inst.Imod, inst.M, inst.A, inst.I, inst.F, inst.Mode); + } + + public static void CpsT1(CodeGenContext context, uint encoding) + { + InstImb20w1Ab18w1Ib17w1Fb16w1 inst = new(encoding); + + InstEmitSystem.Cps(context, inst.Im, 0, inst.A, inst.I, inst.F, 0); + } + + public static void CpsT2(CodeGenContext context, uint encoding) + { + InstImodb9w2Mb8w1Ab7w1Ib6w1Fb5w1Modeb0w5 inst = new(encoding); + + InstEmitSystem.Cps(context, inst.Imod, inst.M, inst.A, inst.I, inst.F, inst.Mode); + } + + public static void Crc32A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Szb21w2Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitCrc32.Crc32(context, inst.Rd, inst.Rn, inst.Rm, inst.Sz); + } + + public static void Crc32T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Szb4w2Rmb0w4 inst = new(encoding); + + InstEmitCrc32.Crc32(context, inst.Rd, inst.Rn, inst.Rm, inst.Sz); + } + + public static void Crc32cA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Szb21w2Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitCrc32.Crc32c(context, inst.Rd, inst.Rn, inst.Rm, inst.Sz); + } + + public static void Crc32cT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Szb4w2Rmb0w4 inst = new(encoding); + + InstEmitCrc32.Crc32c(context, inst.Rd, inst.Rn, inst.Rm, inst.Sz); + } + + public static void CsdbA1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Csdb(); + } + + public static void CsdbT1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Csdb(); + } + + public static void DbgA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Optionb0w4 inst = new(encoding); + + InstEmitSystem.Dbg(context, inst.Option); + } + + public static void DbgT1(CodeGenContext context, uint encoding) + { + InstOptionb0w4 inst = new(encoding); + + InstEmitSystem.Dbg(context, inst.Option); + } + + public static void Dcps1T1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void Dcps2T1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void Dcps3T1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void DmbA1(CodeGenContext context, uint encoding) + { + InstOptionb0w4 inst = new(encoding); + + context.Arm64Assembler.Dmb(inst.Option); + } + + public static void DmbT1(CodeGenContext context, uint encoding) + { + InstOptionb0w4 inst = new(encoding); + + context.Arm64Assembler.Dmb(inst.Option); + } + + public static void DsbA1(CodeGenContext context, uint encoding) + { + InstOptionb0w4 inst = new(encoding); + + context.Arm64Assembler.Dsb(inst.Option); + } + + public static void DsbT1(CodeGenContext context, uint encoding) + { + InstOptionb0w4 inst = new(encoding); + + context.Arm64Assembler.Dsb(inst.Option); + } + + public static void EorIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.EorI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm12), ImmUtils.ExpandedImmRotated(inst.Imm12), inst.S != 0); + } + + public static void EorIT1(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.EorI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), ImmUtils.ExpandedImmRotated(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void EorRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.EorR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void EorRT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdnb16w3 inst = new(encoding); + + InstEmitAlu.EorR(context, inst.Rdn, inst.Rdn, inst.Rm, 0, 0, !context.InITBlock); + } + + public static void EorRT2(CodeGenContext context, uint encoding) + { + InstSb20w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.EorR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void EorRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.EorRr(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void EretA1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void EretT1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void EsbA1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Esb(); + } + + public static void EsbT1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Esb(); + } + + public static void FldmxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm871b1w7 inst = new(encoding); + + InstEmitNeonMemory.Vldm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Imm871, inst.U != 0, inst.W != 0, singleRegs: false); + } + + public static void FldmxT1(CodeGenContext context, uint encoding) + { + InstPb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm871b1w7 inst = new(encoding); + + InstEmitNeonMemory.Vldm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Imm871, inst.U != 0, inst.W != 0, singleRegs: false); + } + + public static void FstmxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm871b1w7 inst = new(encoding); + + InstEmitNeonMemory.Vstm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Imm871, inst.U != 0, inst.W != 0, singleRegs: false); + } + + public static void FstmxT1(CodeGenContext context, uint encoding) + { + InstPb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm871b1w7 inst = new(encoding); + + InstEmitNeonMemory.Vstm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Imm871, inst.U != 0, inst.W != 0, singleRegs: false); + } + + public static void HltA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Imm12b8w12Imm4b0w4 inst = new(encoding); + + InstEmitSystem.Hlt(context, ImmUtils.CombineImmU16(inst.Imm12, inst.Imm4)); + } + + public static void HltT1(CodeGenContext context, uint encoding) + { + InstImm6b16w6 inst = new(encoding); + + InstEmitSystem.Hlt(context, inst.Imm6); + } + + public static void HvcA1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void HvcT1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void IsbA1(CodeGenContext context, uint encoding) + { + InstOptionb0w4 inst = new(encoding); + + context.Arm64Assembler.Isb(inst.Option); + } + + public static void IsbT1(CodeGenContext context, uint encoding) + { + InstOptionb0w4 inst = new(encoding); + + context.Arm64Assembler.Isb(inst.Option); + } + + public static void ItT1(CodeGenContext context, uint encoding) + { + InstFirstcondb20w4Maskb16w4 inst = new(encoding); + + InstEmitFlow.It(context, inst.Firstcond, inst.Mask); + } + + public static void LdaA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Lda(context, inst.Rt, inst.Rn); + } + + public static void LdaT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Lda(context, inst.Rt, inst.Rn); + } + + public static void LdabA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldab(context, inst.Rt, inst.Rn); + } + + public static void LdabT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldab(context, inst.Rt, inst.Rn); + } + + public static void LdaexA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldaex(context, inst.Rt, inst.Rn); + } + + public static void LdaexT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldaex(context, inst.Rt, inst.Rn); + } + + public static void LdaexbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldaexb(context, inst.Rt, inst.Rn); + } + + public static void LdaexbT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldaexb(context, inst.Rt, inst.Rn); + } + + public static void LdaexdA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldaexd(context, inst.Rt, RegisterUtils.GetRt2(inst.Rt), inst.Rn); + } + + public static void LdaexdT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Rt2b8w4 inst = new(encoding); + + InstEmitMemory.Ldaexd(context, inst.Rt, inst.Rt2, inst.Rn); + } + + public static void LdaexhA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldaexh(context, inst.Rt, inst.Rn); + } + + public static void LdaexhT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldaexh(context, inst.Rt, inst.Rn); + } + + public static void LdahA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldah(context, inst.Rt, inst.Rn); + } + + public static void LdahT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldah(context, inst.Rt, inst.Rn); + } + + public static void LdcIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdcI(context, inst.Rn, (int)inst.Imm8 << 2, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdcIT1(CodeGenContext context, uint encoding) + { + InstPb24w1Ub23w1Wb21w1Rnb16w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdcI(context, inst.Rn, (int)inst.Imm8 << 2, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdcLA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdcL(context, inst.Imm8 << 2, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdcLT1(CodeGenContext context, uint encoding) + { + InstPb24w1Ub23w1Wb21w1Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdcL(context, inst.Imm8 << 2, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdmA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Wb21w1Rnb16w4RegisterListb0w16 inst = new(encoding); + + InstEmitMemory.Ldm(context, inst.Rn, inst.RegisterList, inst.W != 0); + } + + public static void LdmT1(CodeGenContext context, uint encoding) + { + InstRnb24w3RegisterListb16w8 inst = new(encoding); + + InstEmitMemory.Ldm(context, inst.Rn, inst.RegisterList, false); + } + + public static void LdmT2(CodeGenContext context, uint encoding) + { + InstWb21w1Rnb16w4Pb15w1Mb14w1RegisterListb0w14 inst = new(encoding); + + InstEmitMemory.Ldm(context, inst.Rn, ImmUtils.CombineRegisterList(inst.RegisterList, inst.M, inst.P), inst.W != 0); + } + + public static void LdmdaA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Wb21w1Rnb16w4RegisterListb0w16 inst = new(encoding); + + InstEmitMemory.Ldmda(context, inst.Rn, inst.RegisterList, inst.W != 0); + } + + public static void LdmdbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Wb21w1Rnb16w4RegisterListb0w16 inst = new(encoding); + + InstEmitMemory.Ldmdb(context, inst.Rn, inst.RegisterList, inst.W != 0); + } + + public static void LdmdbT1(CodeGenContext context, uint encoding) + { + InstWb21w1Rnb16w4Pb15w1Mb14w1RegisterListb0w14 inst = new(encoding); + + InstEmitMemory.Ldmdb(context, inst.Rn, ImmUtils.CombineRegisterList(inst.RegisterList, inst.M, inst.P), inst.W != 0); + } + + public static void LdmibA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Wb21w1Rnb16w4RegisterListb0w16 inst = new(encoding); + + InstEmitMemory.Ldmib(context, inst.Rn, inst.RegisterList, inst.W != 0); + } + + public static void LdmEA1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void LdmUA1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void LdrbtA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrbtI(context, inst.Rt, inst.Rn, (int)inst.Imm12, postIndex: true, inst.U != 0); + } + + public static void LdrbtA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrbtR(context, inst.Rt, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, postIndex: true, inst.U != 0); + } + + public static void LdrbtT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdrbtI(context, inst.Rt, inst.Rn, (int)inst.Imm8, postIndex: false, true); + } + + public static void LdrbIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrbI(context, inst.Rt, inst.Rn, (int)inst.Imm12, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrbIT1(CodeGenContext context, uint encoding) + { + InstImm5b22w5Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.LdrbI(context, inst.Rt, inst.Rn, (int)inst.Imm5, true, true, false); + } + + public static void LdrbIT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrbI(context, inst.Rt, inst.Rn, (int)inst.Imm12, true, true, false); + } + + public static void LdrbIT3(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Pb10w1Ub9w1Wb8w1Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdrbI(context, inst.Rt, inst.Rn, (int)inst.Imm8, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrbLA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrbL(context, inst.Rt, inst.Imm12, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrbLT1(CodeGenContext context, uint encoding) + { + InstUb23w1Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrbL(context, inst.Rt, inst.Imm12, true, inst.U != 0, false); + } + + public static void LdrbRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrbR(context, inst.Rt, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrbRT1(CodeGenContext context, uint encoding) + { + InstRmb22w3Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.LdrbR(context, inst.Rt, inst.Rn, inst.Rm, 0, 0, true, true, false); + } + + public static void LdrbRT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm2b4w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrbR(context, inst.Rt, inst.Rn, inst.Rm, 0, inst.Imm2, true, true, false); + } + + public static void LdrdIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.LdrdI(context, inst.Rt, RegisterUtils.GetRt2(inst.Rt), inst.Rn, ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrdIT1(CodeGenContext context, uint encoding) + { + InstPb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Rt2b8w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdrdI(context, inst.Rt, inst.Rt2, inst.Rn, inst.Imm8 << 2, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrdLA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.LdrdL(context, inst.Rt, RegisterUtils.GetRt2(inst.Rt), ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), true, inst.U != 0, false); + } + + public static void LdrdLT1(CodeGenContext context, uint encoding) + { + InstPb24w1Ub23w1Wb21w1Rtb12w4Rt2b8w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdrdL(context, inst.Rt, inst.Rt2, inst.Imm8, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrdRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrdR(context, inst.Rt, RegisterUtils.GetRt2(inst.Rt), inst.Rn, inst.Rm, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrexA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldrex(context, inst.Rt, inst.Rn); + } + + public static void LdrexT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.Ldrex(context, inst.Rt, inst.Rn); + } + + public static void LdrexbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldrexb(context, inst.Rt, inst.Rn); + } + + public static void LdrexbT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldrexb(context, inst.Rt, inst.Rn); + } + + public static void LdrexdA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldrexd(context, inst.Rt, RegisterUtils.GetRt2(inst.Rt), inst.Rn); + } + + public static void LdrexdT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Rt2b8w4 inst = new(encoding); + + InstEmitMemory.Ldrexd(context, inst.Rt, inst.Rt2, inst.Rn); + } + + public static void LdrexhA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldrexh(context, inst.Rt, inst.Rn); + } + + public static void LdrexhT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Ldrexh(context, inst.Rt, inst.Rn); + } + + public static void LdrhtA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.LdrhtI(context, inst.Rt, inst.Rn, (int)ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), postIndex: true, inst.U != 0); + } + + public static void LdrhtA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrhtR(context, inst.Rt, inst.Rn, inst.Rm, postIndex: true, inst.U != 0); + } + + public static void LdrhtT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdrhtI(context, inst.Rt, inst.Rn, (int)inst.Imm8, postIndex: false, true); + } + + public static void LdrhIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.LdrhI(context, inst.Rt, inst.Rn, (int)ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrhIT1(CodeGenContext context, uint encoding) + { + InstImm5b22w5Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.LdrhI(context, inst.Rt, inst.Rn, (int)inst.Imm5 << 1, true, true, false); + } + + public static void LdrhIT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrhI(context, inst.Rt, inst.Rn, (int)inst.Imm12, true, true, false); + } + + public static void LdrhIT3(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Pb10w1Ub9w1Wb8w1Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdrhI(context, inst.Rt, inst.Rn, (int)inst.Imm8, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrhLA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.LdrhL(context, inst.Rt, ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrhLT1(CodeGenContext context, uint encoding) + { + InstUb23w1Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrhL(context, inst.Rt, inst.Imm12, true, inst.U != 0, false); + } + + public static void LdrhRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrhR(context, inst.Rt, inst.Rn, inst.Rm, 0, 0, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrhRT1(CodeGenContext context, uint encoding) + { + InstRmb22w3Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.LdrhR(context, inst.Rt, inst.Rn, inst.Rm, 0, 0, true, true, false); + } + + public static void LdrhRT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm2b4w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrhR(context, inst.Rt, inst.Rn, inst.Rm, 0, inst.Imm2, true, true, false); + } + + public static void LdrsbtA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.LdrsbtI(context, inst.Rt, inst.Rn, (int)ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), postIndex: true, inst.U != 0); + } + + public static void LdrsbtA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrsbtR(context, inst.Rt, inst.Rn, inst.Rm, postIndex: true, inst.U != 0); + } + + public static void LdrsbtT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdrsbtI(context, inst.Rt, inst.Rn, (int)inst.Imm8, postIndex: false, true); + } + + public static void LdrsbIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.LdrsbI(context, inst.Rt, inst.Rn, (int)ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrsbIT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrsbI(context, inst.Rt, inst.Rn, (int)inst.Imm12, true, true, false); + } + + public static void LdrsbIT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Pb10w1Ub9w1Wb8w1Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdrsbI(context, inst.Rt, inst.Rn, (int)inst.Imm8, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrsbLA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.LdrsbL(context, inst.Rt, ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrsbLT1(CodeGenContext context, uint encoding) + { + InstUb23w1Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrsbL(context, inst.Rt, inst.Imm12, true, inst.U != 0, false); + } + + public static void LdrsbRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrsbR(context, inst.Rt, inst.Rn, inst.Rm, 0, 0, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrsbRT1(CodeGenContext context, uint encoding) + { + InstRmb22w3Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.LdrsbR(context, inst.Rt, inst.Rn, inst.Rm, 0, 0, true, true, false); + } + + public static void LdrsbRT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm2b4w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrsbR(context, inst.Rt, inst.Rn, inst.Rm, 0, inst.Imm2, true, true, false); + } + + public static void LdrshtA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.LdrshtI(context, inst.Rt, inst.Rn, (int)ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), postIndex: true, inst.U != 0); + } + + public static void LdrshtA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrshtR(context, inst.Rt, inst.Rn, inst.Rm, postIndex: true, inst.U != 0); + } + + public static void LdrshtT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdrshtI(context, inst.Rt, inst.Rn, (int)inst.Imm8, postIndex: false, true); + } + + public static void LdrshIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.LdrshI(context, inst.Rt, inst.Rn, (int)ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrshIT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrshI(context, inst.Rt, inst.Rn, (int)inst.Imm12, true, true, false); + } + + public static void LdrshIT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Pb10w1Ub9w1Wb8w1Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdrshI(context, inst.Rt, inst.Rn, (int)inst.Imm8, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrshLA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.LdrshL(context, inst.Rt, ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrshLT1(CodeGenContext context, uint encoding) + { + InstUb23w1Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrshL(context, inst.Rt, inst.Imm12, true, inst.U != 0, false); + } + + public static void LdrshRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrshR(context, inst.Rt, inst.Rn, inst.Rm, 0, 0, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrshRT1(CodeGenContext context, uint encoding) + { + InstRmb22w3Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.LdrshR(context, inst.Rt, inst.Rn, inst.Rm, 0, 0, true, true, false); + } + + public static void LdrshRT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm2b4w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrshR(context, inst.Rt, inst.Rn, inst.Rm, 0, inst.Imm2, true, true, false); + } + + public static void LdrtA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrtI(context, inst.Rt, inst.Rn, (int)inst.Imm12, postIndex: true, inst.U != 0); + } + + public static void LdrtA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrtR(context, inst.Rt, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, postIndex: true, inst.U != 0); + } + + public static void LdrtT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdrtI(context, inst.Rt, inst.Rn, (int)inst.Imm8, postIndex: false, true); + } + + public static void LdrIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrI(context, inst.Rt, inst.Rn, (int)inst.Imm12, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrIT1(CodeGenContext context, uint encoding) + { + InstImm5b22w5Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.LdrI(context, inst.Rt, inst.Rn, (int)inst.Imm5 << 2, true, true, false); + } + + public static void LdrIT2(CodeGenContext context, uint encoding) + { + InstRtb24w3Imm8b16w8 inst = new(encoding); + + InstEmitMemory.LdrI(context, inst.Rt, RegisterUtils.SpRegister, (int)inst.Imm8 << 2, true, true, false); + } + + public static void LdrIT3(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrI(context, inst.Rt, inst.Rn, (int)inst.Imm12, true, true, false); + } + + public static void LdrIT4(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Pb10w1Ub9w1Wb8w1Imm8b0w8 inst = new(encoding); + + InstEmitMemory.LdrI(context, inst.Rt, inst.Rn, (int)inst.Imm8, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrLA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrL(context, inst.Rt, inst.Imm12, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrLT1(CodeGenContext context, uint encoding) + { + InstRtb24w3Imm8b16w8 inst = new(encoding); + + InstEmitMemory.LdrL(context, inst.Rt, inst.Imm8 << 2, true, true, false); + } + + public static void LdrLT2(CodeGenContext context, uint encoding) + { + InstUb23w1Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.LdrL(context, inst.Rt, inst.Imm12, true, inst.U != 0, false); + } + + public static void LdrRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrR(context, inst.Rt, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void LdrRT1(CodeGenContext context, uint encoding) + { + InstRmb22w3Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.LdrR(context, inst.Rt, inst.Rn, inst.Rm, 0, 0, true, true, false); + } + + public static void LdrRT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm2b4w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.LdrR(context, inst.Rt, inst.Rn, inst.Rm, 0, inst.Imm2, true, true, false); + } + + public static void McrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Opc1b21w3Crnb16w4Rtb12w4Coproc0b8w1Opc2b5w3Crmb0w4 inst = new(encoding); + + InstEmitSystem.Mcr(context, encoding, inst.Coproc0 | 0xe, inst.Opc1, inst.Rt, inst.Crn, inst.Crm, inst.Opc2); + } + + public static void McrT1(CodeGenContext context, uint encoding) + { + InstOpc1b21w3Crnb16w4Rtb12w4Coproc0b8w1Opc2b5w3Crmb0w4 inst = new(encoding); + + InstEmitSystem.Mcr(context, encoding, inst.Coproc0 | 0xe, inst.Opc1, inst.Rt, inst.Crn, inst.Crm, inst.Opc2); + } + + public static void McrrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rt2b16w4Rtb12w4Coproc0b8w1Opc1b4w4Crmb0w4 inst = new(encoding); + + InstEmitSystem.Mcrr(context, encoding, inst.Coproc0 | 0xe, inst.Opc1, inst.Rt, inst.Crm); + } + + public static void McrrT1(CodeGenContext context, uint encoding) + { + InstRt2b16w4Rtb12w4Coproc0b8w1Opc1b4w4Crmb0w4 inst = new(encoding); + + InstEmitSystem.Mcrr(context, encoding, inst.Coproc0 | 0xe, inst.Opc1, inst.Rt, inst.Crm); + } + + public static void MlaA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdb16w4Rab12w4Rmb8w4Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Mla(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra); + } + + public static void MlaT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rab12w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Mla(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra); + } + + public static void MlsA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rab12w4Rmb8w4Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Mls(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra); + } + + public static void MlsT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rab12w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Mls(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra); + } + + public static void MovtA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Imm4b16w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMove.Movt(context, inst.Rd, ImmUtils.CombineImmU16(inst.Imm12, inst.Imm4)); + } + + public static void MovtT1(CodeGenContext context, uint encoding) + { + InstIb26w1Imm4b16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitMove.Movt(context, inst.Rd, ImmUtils.CombineImmU16(inst.Imm8, inst.Imm3, inst.I, inst.Imm4)); + } + + public static void MovIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMove.MovI(context, inst.Rd, ImmUtils.ExpandImm(inst.Imm12), ImmUtils.ExpandedImmRotated(inst.Imm12), inst.S != 0); + } + + public static void MovIA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Imm4b16w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMove.MovI(context, inst.Rd, ImmUtils.CombineImmU16(inst.Imm12, inst.Imm4), false, false); + } + + public static void MovIT1(CodeGenContext context, uint encoding) + { + InstRdb24w3Imm8b16w8 inst = new(encoding); + + InstEmitMove.MovI(context, inst.Rd, inst.Imm8, false, !context.InITBlock); + } + + public static void MovIT2(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitMove.MovI(context, inst.Rd, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), ImmUtils.ExpandedImmRotated(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void MovIT3(CodeGenContext context, uint encoding) + { + InstIb26w1Imm4b16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitMove.MovI(context, inst.Rd, ImmUtils.CombineImmU16(inst.Imm8, inst.Imm3, inst.I, inst.Imm4), false, false); + } + + public static void MovRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMove.MovR(context, inst.Cond, inst.Rd, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void MovRT1(CodeGenContext context, uint encoding) + { + InstDb23w1Rmb19w4Rdb16w3 inst = new(encoding); + + InstEmitMove.MovR(context, inst.Rd | (inst.D << 3), inst.Rm, 0, 0, false); + } + + public static void MovRT2(CodeGenContext context, uint encoding) + { + InstOpb27w2Imm5b22w5Rmb19w3Rdb16w3 inst = new(encoding); + + InstEmitMove.MovR(context, inst.Rd, inst.Rm, inst.Op, inst.Imm5, !context.InITBlock); + } + + public static void MovRT3(CodeGenContext context, uint encoding) + { + InstSb20w1Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitMove.MovR(context, inst.Rd, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void MovRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMove.MovRr(context, inst.Rd, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void MovRrT1(CodeGenContext context, uint encoding) + { + InstRsb19w3Rdmb16w3 inst = new(encoding); + + InstEmitMove.MovRr(context, inst.Rdm, inst.Rdm, ((encoding >> 7) & 2) | ((encoding >> 6) & 1), inst.Rs, !context.InITBlock); + } + + public static void MovRrT2(CodeGenContext context, uint encoding) + { + InstStypeb21w2Sb20w1Rmb16w4Rdb8w4Rsb0w4 inst = new(encoding); + + InstEmitMove.MovRr(context, inst.Rd, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void MrcA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Opc1b21w3Crnb16w4Rtb12w4Coproc0b8w1Opc2b5w3Crmb0w4 inst = new(encoding); + + InstEmitSystem.Mrc(context, encoding, inst.Coproc0 | 0xe, inst.Opc1, inst.Rt, inst.Crn, inst.Crm, inst.Opc2); + } + + public static void MrcT1(CodeGenContext context, uint encoding) + { + InstOpc1b21w3Crnb16w4Rtb12w4Coproc0b8w1Opc2b5w3Crmb0w4 inst = new(encoding); + + InstEmitSystem.Mrc(context, encoding, inst.Coproc0 | 0xe, inst.Opc1, inst.Rt, inst.Crn, inst.Crm, inst.Opc2); + } + + public static void MrrcA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rt2b16w4Rtb12w4Coproc0b8w1Opc1b4w4Crmb0w4 inst = new(encoding); + + InstEmitSystem.Mrrc(context, encoding, inst.Coproc0 | 0xe, inst.Opc1, inst.Rt, inst.Rt2, inst.Crm); + } + + public static void MrrcT1(CodeGenContext context, uint encoding) + { + InstRt2b16w4Rtb12w4Coproc0b8w1Opc1b4w4Crmb0w4 inst = new(encoding); + + InstEmitSystem.Mrrc(context, encoding, inst.Coproc0 | 0xe, inst.Opc1, inst.Rt, inst.Rt2, inst.Crm); + } + + public static void MrsA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rb22w1Rdb12w4 inst = new(encoding); + + InstEmitSystem.Mrs(context, inst.Rd, inst.R != 0); + } + + public static void MrsT1(CodeGenContext context, uint encoding) + { + InstRb20w1Rdb8w4 inst = new(encoding); + + InstEmitSystem.Mrs(context, inst.Rd, inst.R != 0); + } + + public static void MrsBrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rb22w1M1b16w4Rdb12w4Mb8w1 inst = new(encoding); + + InstEmitSystem.MrsBr(context, inst.Rd, inst.M1 | (inst.M << 4), inst.R != 0); + } + + public static void MrsBrT1(CodeGenContext context, uint encoding) + { + InstRb20w1M1b16w4Rdb8w4Mb4w1 inst = new(encoding); + + InstEmitSystem.MrsBr(context, inst.Rd, inst.M1 | (inst.M << 4), inst.R != 0); + } + + public static void MsrBrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rb22w1M1b16w4Mb8w1Rnb0w4 inst = new(encoding); + + InstEmitSystem.MsrBr(context, inst.Rn, inst.M1 | (inst.M << 4), inst.R != 0); + } + + public static void MsrBrT1(CodeGenContext context, uint encoding) + { + InstRb20w1Rnb16w4M1b8w4Mb4w1 inst = new(encoding); + + InstEmitSystem.MsrBr(context, inst.Rn, inst.M1 | (inst.M << 4), inst.R != 0); + } + + public static void MsrIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rb22w1Maskb16w4Imm12b0w12 inst = new(encoding); + + InstEmitSystem.MsrI(context, inst.Imm12, inst.Mask, inst.R != 0); + } + + public static void MsrRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rb22w1Maskb16w4Rnb0w4 inst = new(encoding); + + InstEmitSystem.MsrR(context, inst.Rn, inst.Mask, inst.R != 0); + } + + public static void MsrRT1(CodeGenContext context, uint encoding) + { + InstRb20w1Rnb16w4Maskb8w4 inst = new(encoding); + + InstEmitSystem.MsrR(context, inst.Rn, inst.Mask, inst.R != 0); + } + + public static void MulA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdb16w4Rmb8w4Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Mul(context, inst.Rd, inst.Rn, inst.Rm, inst.S != 0); + } + + public static void MulT1(CodeGenContext context, uint encoding) + { + InstRnb19w3Rdmb16w3 inst = new(encoding); + + InstEmitMultiply.Mul(context, inst.Rdm, inst.Rn, inst.Rdm, !context.InITBlock); + } + + public static void MulT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Mul(context, inst.Rd, inst.Rn, inst.Rm, false); + } + + public static void MvnIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMove.MvnI(context, inst.Rd, ImmUtils.ExpandImm(inst.Imm12), ImmUtils.ExpandedImmRotated(inst.Imm12), inst.S != 0); + } + + public static void MvnIT1(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitMove.MvnI(context, inst.Rd, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), ImmUtils.ExpandedImmRotated(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void MvnRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMove.MvnR(context, inst.Rd, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void MvnRT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdb16w3 inst = new(encoding); + + InstEmitMove.MvnR(context, inst.Rd, inst.Rm, 0, 0, !context.InITBlock); + } + + public static void MvnRT2(CodeGenContext context, uint encoding) + { + InstSb20w1Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitMove.MvnR(context, inst.Rd, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void MvnRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMove.MvnRr(context, inst.Rd, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void NopA1(CodeGenContext context, uint encoding) + { + } + + public static void NopT1(CodeGenContext context, uint encoding) + { + } + + public static void NopT2(CodeGenContext context, uint encoding) + { + } + + public static void OrnIT1(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.OrnI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), ImmUtils.ExpandedImmRotated(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void OrnRT1(CodeGenContext context, uint encoding) + { + InstSb20w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.OrnR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void OrrIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.OrrI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm12), ImmUtils.ExpandedImmRotated(inst.Imm12), inst.S != 0); + } + + public static void OrrIT1(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.OrrI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), ImmUtils.ExpandedImmRotated(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void OrrRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.OrrR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void OrrRT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdnb16w3 inst = new(encoding); + + InstEmitAlu.OrrR(context, inst.Rdn, inst.Rdn, inst.Rm, 0, 0, !context.InITBlock); + } + + public static void OrrRT2(CodeGenContext context, uint encoding) + { + InstSb20w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.OrrR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void OrrRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.OrrRr(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void PkhA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Imm5b7w5Tbb6w1Rmb0w4 inst = new(encoding); + + InstEmitMove.Pkh(context, inst.Rd, inst.Rn, inst.Rm, inst.Tb != 0, inst.Imm5); + } + + public static void PkhT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Imm3b12w3Rdb8w4Imm2b6w2Tbb5w1Rmb0w4 inst = new(encoding); + + InstEmitMove.Pkh(context, inst.Rd, inst.Rn, inst.Rm, inst.Tb != 0, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3)); + } + + public static void PldIA1(CodeGenContext context, uint encoding) + { + InstUb23w1Rb22w1Rnb16w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.PldI(context, inst.Rn, inst.Imm12, inst.U != 0, inst.R != 0); + } + + public static void PldIT1(CodeGenContext context, uint encoding) + { + InstWb21w1Rnb16w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.PldI(context, inst.Rn, inst.Imm12, true, inst.W == 0); + } + + public static void PldIT2(CodeGenContext context, uint encoding) + { + InstWb21w1Rnb16w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.PldI(context, inst.Rn, inst.Imm8, false, inst.W == 0); + } + + public static void PldLA1(CodeGenContext context, uint encoding) + { + InstUb23w1Imm12b0w12 inst = new(encoding); + + InstEmitMemory.PldL(context, inst.Imm12, inst.U != 0); + } + + public static void PldLT1(CodeGenContext context, uint encoding) + { + InstUb23w1Imm12b0w12 inst = new(encoding); + + InstEmitMemory.PldL(context, inst.Imm12, inst.U != 0); + } + + public static void PldRA1(CodeGenContext context, uint encoding) + { + InstUb23w1Rb22w1Rnb16w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.PldR(context, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.U != 0, inst.R != 0); + } + + public static void PldRT1(CodeGenContext context, uint encoding) + { + InstWb21w1Rnb16w4Imm2b4w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.PldR(context, inst.Rn, inst.Rm, 0, inst.Imm2, true, inst.W == 0); + } + + public static void PliIA1(CodeGenContext context, uint encoding) + { + InstUb23w1Rnb16w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.PliI(context, inst.Rn, inst.Imm12, inst.U != 0); + } + + public static void PliIT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.PliI(context, inst.Rn, inst.Imm12, true); + } + + public static void PliIT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.PliI(context, inst.Rn, inst.Imm8, false); + } + + public static void PliIT3(CodeGenContext context, uint encoding) + { + InstUb23w1Imm12b0w12 inst = new(encoding); + + InstEmitMemory.PliL(context, inst.Imm12, inst.U != 0); + } + + public static void PliRA1(CodeGenContext context, uint encoding) + { + InstUb23w1Rnb16w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.PliR(context, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.U != 0); + } + + public static void PliRT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Imm2b4w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.PliR(context, inst.Rn, inst.Rm, 0, inst.Imm2, true); + } + + public static void PopT1(CodeGenContext context, uint encoding) + { + InstPb24w1RegisterListb16w8 inst = new(encoding); + + InstEmitMemory.Ldm(context, RegisterUtils.SpRegister, inst.RegisterList | (inst.P << RegisterUtils.PcRegister), true); + } + + public static void PssbbA1(CodeGenContext context, uint encoding) + { + throw new NotImplementedException(); + } + + public static void PssbbT1(CodeGenContext context, uint encoding) + { + throw new NotImplementedException(); + } + + public static void PushT1(CodeGenContext context, uint encoding) + { + InstMb24w1RegisterListb16w8 inst = new(encoding); + + InstEmitMemory.Stmdb(context, RegisterUtils.SpRegister, inst.RegisterList | (inst.M << RegisterUtils.LrRegister), true); + } + + public static void QaddA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qadd(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void QaddT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qadd(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Qadd16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qadd16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Qadd16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qadd16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Qadd8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qadd8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Qadd8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qadd8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void QasxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qasx(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void QasxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qasx(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void QdaddA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qdadd(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void QdaddT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qdadd(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void QdsubA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qdsub(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void QdsubT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qdsub(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void QsaxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qsax(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void QsaxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qsax(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void QsubA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qsub(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void QsubT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qsub(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Qsub16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qsub16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Qsub16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qsub16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Qsub8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qsub8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Qsub8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Qsub8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void RbitA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitBit.Rbit(context, inst.Rd, inst.Rm); + } + + public static void RbitT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitBit.Rbit(context, inst.Rd, inst.Rm); + } + + public static void RevA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitBit.Rev(context, inst.Rd, inst.Rm); + } + + public static void RevT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdb16w3 inst = new(encoding); + + InstEmitBit.Rev(context, inst.Rd, inst.Rm); + } + + public static void RevT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitBit.Rev(context, inst.Rd, inst.Rm); + } + + public static void Rev16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitBit.Rev16(context, inst.Rd, inst.Rm); + } + + public static void Rev16T1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdb16w3 inst = new(encoding); + + InstEmitBit.Rev16(context, inst.Rd, inst.Rm); + } + + public static void Rev16T2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitBit.Rev16(context, inst.Rd, inst.Rm); + } + + public static void RevshA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitBit.Revsh(context, inst.Rd, inst.Rm); + } + + public static void RevshT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdb16w3 inst = new(encoding); + + InstEmitBit.Revsh(context, inst.Rd, inst.Rm); + } + + public static void RevshT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitBit.Revsh(context, inst.Rd, inst.Rm); + } + + public static void RfeA1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void RfeT1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void RfeT2(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void RsbIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.RsbI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm12), inst.S != 0); + } + + public static void RsbIT1(CodeGenContext context, uint encoding) + { + InstRnb19w3Rdb16w3 inst = new(encoding); + + InstEmitAlu.RsbI(context, inst.Rd, inst.Rn, 0, !context.InITBlock); + } + + public static void RsbIT2(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.RsbI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void RsbRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.RsbR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void RsbRT1(CodeGenContext context, uint encoding) + { + InstSb20w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.RsbR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void RsbRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.RsbRr(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void RscIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.RscI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm12), inst.S != 0); + } + + public static void RscRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.RscR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void RscRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.RscRr(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void Sadd16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Sadd16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Sadd16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Sadd16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Sadd8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Sadd8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Sadd8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Sadd8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void SasxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Sasx(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void SasxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Sasx(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void SbA1(CodeGenContext context, uint encoding) + { + throw new NotImplementedException(); + } + + public static void SbT1(CodeGenContext context, uint encoding) + { + throw new NotImplementedException(); + } + + public static void SbcIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.SbcI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm12), inst.S != 0); + } + + public static void SbcIT1(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.SbcI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void SbcRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.SbcR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void SbcRT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdnb16w3 inst = new(encoding); + + InstEmitAlu.SbcR(context, inst.Rdn, inst.Rdn, inst.Rm, 0, 0, !context.InITBlock); + } + + public static void SbcRT2(CodeGenContext context, uint encoding) + { + InstSb20w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.SbcR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void SbcRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.SbcRr(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void SbfxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Widthm1b16w5Rdb12w4Lsbb7w5Rnb0w4 inst = new(encoding); + + InstEmitBit.Sbfx(context, inst.Rd, inst.Rn, inst.Lsb, inst.Widthm1); + } + + public static void SbfxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Imm3b12w3Rdb8w4Imm2b6w2Widthm1b0w5 inst = new(encoding); + + InstEmitBit.Sbfx(context, inst.Rd, inst.Rn, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.Widthm1); + } + + public static void SdivA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rmb8w4Rnb0w4 inst = new(encoding); + + InstEmitDivide.Sdiv(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void SdivT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitDivide.Sdiv(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void SelA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Sel(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void SelT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Sel(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void SetendA1(CodeGenContext context, uint encoding) + { + InstEb9w1 inst = new(encoding); + + InstEmitSystem.Setend(context, inst.E != 0); + } + + public static void SetendT1(CodeGenContext context, uint encoding) + { + InstEb19w1 inst = new(encoding); + + InstEmitSystem.Setend(context, inst.E != 0); + } + + public static void SetpanA1(CodeGenContext context, uint encoding) + { + _ = new InstImm1b9w1(encoding); + + throw new NotImplementedException(); + } + + public static void SetpanT1(CodeGenContext context, uint encoding) + { + _ = new InstImm1b19w1(encoding); + + throw new NotImplementedException(); + } + + public static void SevA1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Sev(); + } + + public static void SevT1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Sev(); + } + + public static void SevT2(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Sev(); + } + + public static void SevlA1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Sevl(); + } + + public static void SevlT1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Sevl(); + } + + public static void SevlT2(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Sevl(); + } + + public static void Sha1cA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha1c(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha1cT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha1c(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha1hA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha1h(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void Sha1hT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha1h(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void Sha1mA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha1m(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha1mT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha1m(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha1pA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha1p(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha1pT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha1p(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha1su0A1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha1su0(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha1su0T1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha1su0(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha1su1A1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha1su1(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void Sha1su1T1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha1su1(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void Sha256hA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha256h(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha256hT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha256h(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha256h2A1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha256h2(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha256h2T1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha256h2(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha256su0A1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha256su0(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void Sha256su0T1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha256su0(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void Sha256su1A1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha256su1(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Sha256su1T1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonHash.Sha256su1(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void Shadd16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Shadd16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Shadd16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Shadd16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Shadd8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Shadd8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Shadd8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Shadd8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void ShasxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Shasx(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void ShasxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Shasx(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void ShsaxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Shsax(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void ShsaxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Shsax(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Shsub16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Shsub16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Shsub16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Shsub16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Shsub8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Shsub8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Shsub8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Shsub8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void SmcA1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void SmcT1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void SmlabbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rab12w4Rmb8w4Mb6w1Nb5w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smlabb(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra, inst.N != 0, inst.M != 0); + } + + public static void SmlabbT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rab12w4Rdb8w4Nb5w1Mb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smlabb(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra, inst.N != 0, inst.M != 0); + } + + public static void SmladA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rab12w4Rmb8w4Mb5w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smlad(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra, inst.M != 0); + } + + public static void SmladT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rab12w4Rdb8w4Mb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smlad(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra, inst.M != 0); + } + + public static void SmlalA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdhib16w4Rdlob12w4Rmb8w4Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smlal(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, inst.S != 0); + } + + public static void SmlalT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdlob12w4Rdhib8w4Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smlal(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, false); + } + + public static void SmlalbbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdhib16w4Rdlob12w4Rmb8w4Mb6w1Nb5w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smlalbb(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, inst.N != 0, inst.M != 0); + } + + public static void SmlalbbT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdlob12w4Rdhib8w4Nb5w1Mb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smlalbb(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, inst.N != 0, inst.M != 0); + } + + public static void SmlaldA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdhib16w4Rdlob12w4Rmb8w4Mb5w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smlald(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, inst.M != 0); + } + + public static void SmlaldT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdlob12w4Rdhib8w4Mb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smlald(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, inst.M != 0); + } + + public static void SmlawbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rab12w4Rmb8w4Mb6w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smlawb(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra, inst.M != 0); + } + + public static void SmlawbT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rab12w4Rdb8w4Mb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smlawb(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra, inst.M != 0); + } + + public static void SmlsdA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rab12w4Rmb8w4Mb5w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smlsd(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra, inst.M != 0); + } + + public static void SmlsdT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rab12w4Rdb8w4Mb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smlsd(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra, inst.M != 0); + } + + public static void SmlsldA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdhib16w4Rdlob12w4Rmb8w4Mb5w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smlsld(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, inst.M != 0); + } + + public static void SmlsldT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdlob12w4Rdhib8w4Mb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smlsld(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, inst.M != 0); + } + + public static void SmmlaA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rab12w4Rmb8w4Rb5w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smmla(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra, inst.R != 0); + } + + public static void SmmlaT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rab12w4Rdb8w4Rb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smmla(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra, inst.R != 0); + } + + public static void SmmlsA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rab12w4Rmb8w4Rb5w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smmls(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra, inst.R != 0); + } + + public static void SmmlsT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rab12w4Rdb8w4Rb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smmls(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra, inst.R != 0); + } + + public static void SmmulA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rmb8w4Rb5w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smmul(context, inst.Rd, inst.Rn, inst.Rm, inst.R != 0); + } + + public static void SmmulT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smmul(context, inst.Rd, inst.Rn, inst.Rm, inst.R != 0); + } + + public static void SmuadA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rmb8w4Mb5w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smuad(context, inst.Rd, inst.Rn, inst.Rm, inst.M != 0); + } + + public static void SmuadT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Mb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smuad(context, inst.Rd, inst.Rn, inst.Rm, inst.M != 0); + } + + public static void SmulbbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rmb8w4Mb6w1Nb5w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smulbb(context, inst.Rd, inst.Rn, inst.Rm, inst.N != 0, inst.M != 0); + } + + public static void SmulbbT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Nb5w1Mb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smulbb(context, inst.Rd, inst.Rn, inst.Rm, inst.N != 0, inst.M != 0); + } + + public static void SmullA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdhib16w4Rdlob12w4Rmb8w4Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smull(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, inst.S != 0); + } + + public static void SmullT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdlob12w4Rdhib8w4Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smull(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, false); + } + + public static void SmulwbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rmb8w4Mb6w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smulwb(context, inst.Rd, inst.Rn, inst.Rm, inst.M != 0); + } + + public static void SmulwbT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Mb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smulwb(context, inst.Rd, inst.Rn, inst.Rm, inst.M != 0); + } + + public static void SmusdA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rmb8w4Mb5w1Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Smusd(context, inst.Rd, inst.Rn, inst.Rm, inst.M != 0); + } + + public static void SmusdT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Mb4w1Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Smusd(context, inst.Rd, inst.Rn, inst.Rm, inst.M != 0); + } + + public static void SrsA1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void SrsT1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void SrsT2(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void SsatA1(CodeGenContext context, uint encoding) + { + InstCondb28w4SatImmb16w5Rdb12w4Imm5b7w5Shb6w1Rnb0w4 inst = new(encoding); + + InstEmitSaturate.Ssat(context, inst.Rd, inst.SatImm, inst.Rn, inst.Sh != 0, inst.Imm5); + } + + public static void SsatT1(CodeGenContext context, uint encoding) + { + InstShb21w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2SatImmb0w5 inst = new(encoding); + + InstEmitSaturate.Ssat(context, inst.Rd, inst.SatImm, inst.Rn, inst.Sh != 0, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3)); + } + + public static void Ssat16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4SatImmb16w4Rdb12w4Rnb0w4 inst = new(encoding); + + InstEmitSaturate.Ssat16(context, inst.Rd, inst.SatImm, inst.Rn); + } + + public static void Ssat16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4SatImmb0w4 inst = new(encoding); + + InstEmitSaturate.Ssat16(context, inst.Rd, inst.SatImm, inst.Rn); + } + + public static void SsaxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Ssax(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void SsaxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Ssax(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void SsbbA1(CodeGenContext context, uint encoding) + { + throw new NotImplementedException(); + } + + public static void SsbbT1(CodeGenContext context, uint encoding) + { + throw new NotImplementedException(); + } + + public static void Ssub16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Ssub16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Ssub16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Ssub16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Ssub8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Ssub8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Ssub8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Ssub8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void StcA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.Stc(context, inst.Rn, (int)inst.Imm8 << 2, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StcT1(CodeGenContext context, uint encoding) + { + InstPb24w1Ub23w1Wb21w1Rnb16w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.Stc(context, inst.Rn, (int)inst.Imm8 << 2, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StlA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb0w4 inst = new(encoding); + + InstEmitMemory.Stl(context, inst.Rt, inst.Rn); + } + + public static void StlT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Stl(context, inst.Rt, inst.Rn); + } + + public static void StlbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb0w4 inst = new(encoding); + + InstEmitMemory.Stlb(context, inst.Rt, inst.Rn); + } + + public static void StlbT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Stlb(context, inst.Rt, inst.Rn); + } + + public static void StlexA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rtb0w4 inst = new(encoding); + + InstEmitMemory.Stlex(context, inst.Rd, inst.Rt, inst.Rn); + } + + public static void StlexT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Rdb0w4 inst = new(encoding); + + InstEmitMemory.Stlex(context, inst.Rd, inst.Rt, inst.Rn); + } + + public static void StlexbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rtb0w4 inst = new(encoding); + + InstEmitMemory.Stlexb(context, inst.Rd, inst.Rt, inst.Rn); + } + + public static void StlexbT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Rdb0w4 inst = new(encoding); + + InstEmitMemory.Stlexb(context, inst.Rd, inst.Rt, inst.Rn); + } + + public static void StlexdA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rtb0w4 inst = new(encoding); + + InstEmitMemory.Stlexd(context, inst.Rd, inst.Rt, RegisterUtils.GetRt2(inst.Rt), inst.Rn); + } + + public static void StlexdT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Rt2b8w4Rdb0w4 inst = new(encoding); + + InstEmitMemory.Stlexd(context, inst.Rd, inst.Rt, inst.Rt2, inst.Rn); + } + + public static void StlexhA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rtb0w4 inst = new(encoding); + + InstEmitMemory.Stlexh(context, inst.Rd, inst.Rt, inst.Rn); + } + + public static void StlexhT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Rdb0w4 inst = new(encoding); + + InstEmitMemory.Stlexh(context, inst.Rd, inst.Rt, inst.Rn); + } + + public static void StlhA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rtb0w4 inst = new(encoding); + + InstEmitMemory.Stlh(context, inst.Rt, inst.Rn); + } + + public static void StlhT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4 inst = new(encoding); + + InstEmitMemory.Stlh(context, inst.Rt, inst.Rn); + } + + public static void StmA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Wb21w1Rnb16w4RegisterListb0w16 inst = new(encoding); + + InstEmitMemory.Stm(context, inst.Rn, inst.RegisterList, inst.W != 0); + } + + public static void StmT1(CodeGenContext context, uint encoding) + { + InstRnb24w3RegisterListb16w8 inst = new(encoding); + + InstEmitMemory.Stm(context, inst.Rn, inst.RegisterList, false); + } + + public static void StmT2(CodeGenContext context, uint encoding) + { + InstWb21w1Rnb16w4Mb14w1RegisterListb0w14 inst = new(encoding); + + InstEmitMemory.Stm(context, inst.Rn, ImmUtils.CombineRegisterList(inst.RegisterList, inst.M), inst.W != 0); + } + + public static void StmdaA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Wb21w1Rnb16w4RegisterListb0w16 inst = new(encoding); + + InstEmitMemory.Stmda(context, inst.Rn, inst.RegisterList, inst.W != 0); + } + + public static void StmdbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Wb21w1Rnb16w4RegisterListb0w16 inst = new(encoding); + + InstEmitMemory.Stmdb(context, inst.Rn, inst.RegisterList, inst.W != 0); + } + + public static void StmdbT1(CodeGenContext context, uint encoding) + { + InstWb21w1Rnb16w4Mb14w1RegisterListb0w14 inst = new(encoding); + + InstEmitMemory.Stmdb(context, inst.Rn, ImmUtils.CombineRegisterList(inst.RegisterList, inst.M), inst.W != 0); + } + + public static void StmibA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Wb21w1Rnb16w4RegisterListb0w16 inst = new(encoding); + + InstEmitMemory.Stmib(context, inst.Rn, inst.RegisterList, inst.W != 0); + } + + public static void StmUA1(CodeGenContext context, uint encoding) + { + InstEmitSystem.PrivilegedInstruction(context, encoding); + } + + public static void StrbtA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.StrbtI(context, inst.Rt, inst.Rn, (int)inst.Imm12, postIndex: true, inst.U != 0); + } + + public static void StrbtA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.StrbtR(context, inst.Rt, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, postIndex: true, inst.U != 0); + } + + public static void StrbtT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.StrbtI(context, inst.Rt, inst.Rn, (int)inst.Imm8, postIndex: false, true); + } + + public static void StrbIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.StrbI(context, inst.Rt, inst.Rn, (int)inst.Imm12, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StrbIT1(CodeGenContext context, uint encoding) + { + InstImm5b22w5Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.StrbI(context, inst.Rt, inst.Rn, (int)inst.Imm5, true, true, false); + } + + public static void StrbIT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.StrbI(context, inst.Rt, inst.Rn, (int)inst.Imm12, true, true, false); + } + + public static void StrbIT3(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Pb10w1Ub9w1Wb8w1Imm8b0w8 inst = new(encoding); + + InstEmitMemory.StrbI(context, inst.Rt, inst.Rn, (int)inst.Imm8, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StrbRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.StrbR(context, inst.Rt, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StrbRT1(CodeGenContext context, uint encoding) + { + InstRmb22w3Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.StrbR(context, inst.Rt, inst.Rn, inst.Rm, 0, 0, true, true, false); + } + + public static void StrbRT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm2b4w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.StrbR(context, inst.Rt, inst.Rn, inst.Rm, 0, inst.Imm2, true, true, false); + } + + public static void StrdIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.StrdI(context, inst.Rt, RegisterUtils.GetRt2(inst.Rt), inst.Rn, ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StrdIT1(CodeGenContext context, uint encoding) + { + InstPb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Rt2b8w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.StrdI(context, inst.Rt, inst.Rt2, inst.Rn, inst.Imm8 << 2, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StrdRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Rmb0w4 inst = new(encoding); + + InstEmitMemory.StrdR(context, inst.Rt, RegisterUtils.GetRt2(inst.Rt), inst.Rn, inst.Rm, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StrexA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rtb0w4 inst = new(encoding); + + InstEmitMemory.Strex(context, inst.Rd, inst.Rt, inst.Rn); + } + + public static void StrexT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.Strex(context, inst.Rd, inst.Rt, inst.Rn); + } + + public static void StrexbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rtb0w4 inst = new(encoding); + + InstEmitMemory.Strexb(context, inst.Rd, inst.Rt, inst.Rn); + } + + public static void StrexbT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Rdb0w4 inst = new(encoding); + + InstEmitMemory.Strexb(context, inst.Rd, inst.Rt, inst.Rn); + } + + public static void StrexdA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rtb0w4 inst = new(encoding); + + InstEmitMemory.Strexd(context, inst.Rd, inst.Rt, RegisterUtils.GetRt2(inst.Rt), inst.Rn); + } + + public static void StrexdT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Rt2b8w4Rdb0w4 inst = new(encoding); + + InstEmitMemory.Strexd(context, inst.Rd, inst.Rt, inst.Rt2, inst.Rn); + } + + public static void StrexhA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rtb0w4 inst = new(encoding); + + InstEmitMemory.Strexh(context, inst.Rd, inst.Rt, inst.Rn); + } + + public static void StrexhT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Rdb0w4 inst = new(encoding); + + InstEmitMemory.Strexh(context, inst.Rd, inst.Rt, inst.Rn); + } + + public static void StrhtA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.StrhtI(context, inst.Rt, inst.Rn, (int)ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), postIndex: true, inst.U != 0); + } + + public static void StrhtA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Rmb0w4 inst = new(encoding); + + InstEmitMemory.StrhtR(context, inst.Rt, inst.Rn, inst.Rm, postIndex: true, inst.U != 0); + } + + public static void StrhtT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.StrhtI(context, inst.Rt, inst.Rn, (int)inst.Imm8, postIndex: false, true); + } + + public static void StrhIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm4hb8w4Imm4lb0w4 inst = new(encoding); + + InstEmitMemory.StrhI(context, inst.Rt, inst.Rn, (int)ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StrhIT1(CodeGenContext context, uint encoding) + { + InstImm5b22w5Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.StrhI(context, inst.Rt, inst.Rn, (int)inst.Imm5 << 1, true, true, false); + } + + public static void StrhIT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.StrhI(context, inst.Rt, inst.Rn, (int)inst.Imm12, true, true, false); + } + + public static void StrhIT3(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Pb10w1Ub9w1Wb8w1Imm8b0w8 inst = new(encoding); + + InstEmitMemory.StrhI(context, inst.Rt, inst.Rn, (int)inst.Imm8, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StrhRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Rmb0w4 inst = new(encoding); + + InstEmitMemory.StrhR(context, inst.Rt, inst.Rn, inst.Rm, 0, 0, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StrhRT1(CodeGenContext context, uint encoding) + { + InstRmb22w3Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.StrhR(context, inst.Rt, inst.Rn, inst.Rm, 0, 0, true, true, false); + } + + public static void StrhRT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm2b4w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.StrhR(context, inst.Rt, inst.Rn, inst.Rm, 0, inst.Imm2, true, true, false); + } + + public static void StrtA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.StrtI(context, inst.Rt, inst.Rn, (int)inst.Imm12, postIndex: true, inst.U != 0); + } + + public static void StrtA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Rnb16w4Rtb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.StrtR(context, inst.Rt, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, postIndex: true, inst.U != 0); + } + + public static void StrtT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm8b0w8 inst = new(encoding); + + InstEmitMemory.StrtI(context, inst.Rt, inst.Rn, (int)inst.Imm8, postIndex: false, true); + } + + public static void StrIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.StrI(context, inst.Rt, inst.Rn, (int)inst.Imm12, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StrIT1(CodeGenContext context, uint encoding) + { + InstImm5b22w5Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.StrI(context, inst.Rt, inst.Rn, (int)inst.Imm5 << 2, true, true, false); + } + + public static void StrIT2(CodeGenContext context, uint encoding) + { + InstRtb24w3Imm8b16w8 inst = new(encoding); + + InstEmitMemory.StrI(context, inst.Rt, RegisterUtils.SpRegister, (int)inst.Imm8 << 2, true, true, false); + } + + public static void StrIT3(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm12b0w12 inst = new(encoding); + + InstEmitMemory.StrI(context, inst.Rt, inst.Rn, (int)inst.Imm12, true, true, false); + } + + public static void StrIT4(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Pb10w1Ub9w1Wb8w1Imm8b0w8 inst = new(encoding); + + InstEmitMemory.StrI(context, inst.Rt, inst.Rn, (int)inst.Imm8, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StrRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Wb21w1Rnb16w4Rtb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.StrR(context, inst.Rt, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.P != 0, inst.U != 0, inst.W != 0); + } + + public static void StrRT1(CodeGenContext context, uint encoding) + { + InstRmb22w3Rnb19w3Rtb16w3 inst = new(encoding); + + InstEmitMemory.StrR(context, inst.Rt, inst.Rn, inst.Rm, 0, 0, true, true, false); + } + + public static void StrRT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Rtb12w4Imm2b4w2Rmb0w4 inst = new(encoding); + + InstEmitMemory.StrR(context, inst.Rt, inst.Rn, inst.Rm, 0, inst.Imm2, true, true, false); + } + + public static void SubIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.SubI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm12), inst.S != 0); + } + + public static void SubIT1(CodeGenContext context, uint encoding) + { + InstImm3b22w3Rnb19w3Rdb16w3 inst = new(encoding); + + InstEmitAlu.SubI(context, inst.Rd, inst.Rn, inst.Imm3, !context.InITBlock); + } + + public static void SubIT2(CodeGenContext context, uint encoding) + { + InstRdnb24w3Imm8b16w8 inst = new(encoding); + + InstEmitAlu.SubI(context, inst.Rdn, inst.Rdn, inst.Imm8, !context.InITBlock); + } + + public static void SubIT3(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.SubI(context, inst.Rd, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void SubIT4(CodeGenContext context, uint encoding) + { + InstIb26w1Rnb16w4Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.SubI(context, inst.Rd, inst.Rn, ImmUtils.CombineImmU12(inst.Imm8, inst.Imm3, inst.I), false); + } + + public static void SubIT5(CodeGenContext context, uint encoding) + { + InstRnb16w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.SubI(context, RegisterUtils.PcRegister, inst.Rn, inst.Imm8, true); + } + + public static void SubRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.SubR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void SubRT1(CodeGenContext context, uint encoding) + { + InstRmb22w3Rnb19w3Rdb16w3 inst = new(encoding); + + InstEmitAlu.SubR(context, inst.Rd, inst.Rn, inst.Rm, 0, 0, !context.InITBlock); + } + + public static void SubRT2(CodeGenContext context, uint encoding) + { + InstSb20w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.SubR(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), !context.InITBlock); + } + + public static void SubRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rnb16w4Rdb12w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.SubRr(context, inst.Rd, inst.Rn, inst.Rm, inst.Stype, inst.Rs, inst.S != 0); + } + + public static void SubSpIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdb12w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.SubI(context, inst.Rd, RegisterUtils.SpRegister, ImmUtils.ExpandImm(inst.Imm12), inst.S != 0); + } + + public static void SubSpIT1(CodeGenContext context, uint encoding) + { + InstImm7b16w7 inst = new(encoding); + + InstEmitAlu.SubI(context, RegisterUtils.SpRegister, RegisterUtils.SpRegister, inst.Imm7 << 2, false); + } + + public static void SubSpIT2(CodeGenContext context, uint encoding) + { + InstIb26w1Sb20w1Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.SubI(context, inst.Rd, RegisterUtils.SpRegister, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), inst.S != 0); + } + + public static void SubSpIT3(CodeGenContext context, uint encoding) + { + InstIb26w1Imm3b12w3Rdb8w4Imm8b0w8 inst = new(encoding); + + InstEmitAlu.SubI(context, inst.Rd, RegisterUtils.SpRegister, ImmUtils.CombineImmU12(inst.Imm8, inst.Imm3, inst.I), false); + } + + public static void SubSpRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.SubR(context, inst.Rd, RegisterUtils.SpRegister, inst.Rm, inst.Stype, inst.Imm5, inst.S != 0); + } + + public static void SubSpRT1(CodeGenContext context, uint encoding) + { + InstSb20w1Imm3b12w3Rdb8w4Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.SubR(context, inst.Rd, RegisterUtils.SpRegister, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.S != 0); + } + + public static void SvcA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Imm24b0w24 inst = new(encoding); + + InstEmitSystem.Svc(context, inst.Imm24); + } + + public static void SvcT1(CodeGenContext context, uint encoding) + { + InstImm8b16w8 inst = new(encoding); + + InstEmitSystem.Svc(context, inst.Imm8); + } + + public static void SxtabA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rotateb10w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Sxtab(context, inst.Rd, inst.Rn, inst.Rm, inst.Rotate); + } + + public static void SxtabT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rotateb4w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Sxtab(context, inst.Rd, inst.Rn, inst.Rm, inst.Rotate); + } + + public static void Sxtab16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rotateb10w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Sxtab16(context, inst.Rd, inst.Rn, inst.Rm, inst.Rotate); + } + + public static void Sxtab16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rotateb4w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Sxtab16(context, inst.Rd, inst.Rn, inst.Rm, inst.Rotate); + } + + public static void SxtahA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rotateb10w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Sxtah(context, inst.Rd, inst.Rn, inst.Rm, inst.Rotate); + } + + public static void SxtahT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rotateb4w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Sxtah(context, inst.Rd, inst.Rn, inst.Rm, inst.Rotate); + } + + public static void SxtbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Rotateb10w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Sxtb(context, inst.Rd, inst.Rm, inst.Rotate); + } + + public static void SxtbT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdb16w3 inst = new(encoding); + + InstEmitExtension.Sxtb(context, inst.Rd, inst.Rm, 0); + } + + public static void SxtbT2(CodeGenContext context, uint encoding) + { + InstRdb8w4Rotateb4w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Sxtb(context, inst.Rd, inst.Rm, inst.Rotate); + } + + public static void Sxtb16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Rotateb10w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Sxtb16(context, inst.Rd, inst.Rm, inst.Rotate); + } + + public static void Sxtb16T1(CodeGenContext context, uint encoding) + { + InstRdb8w4Rotateb4w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Sxtb16(context, inst.Rd, inst.Rm, inst.Rotate); + } + + public static void SxthA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Rotateb10w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Sxth(context, inst.Rd, inst.Rm, inst.Rotate); + } + + public static void SxthT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdb16w3 inst = new(encoding); + + InstEmitExtension.Sxth(context, inst.Rd, inst.Rm, 0); + } + + public static void SxthT2(CodeGenContext context, uint encoding) + { + InstRdb8w4Rotateb4w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Sxth(context, inst.Rd, inst.Rm, inst.Rotate); + } + + public static void TbbT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Hb4w1Rmb0w4 inst = new(encoding); + + InstEmitFlow.Tbb(context, inst.Rn, inst.Rm, inst.H != 0); + } + + public static void TeqIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.TeqI(context, inst.Rn, ImmUtils.ExpandImm(inst.Imm12), ImmUtils.ExpandedImmRotated(inst.Imm12)); + } + + public static void TeqIT1(CodeGenContext context, uint encoding) + { + InstIb26w1Rnb16w4Imm3b12w3Imm8b0w8 inst = new(encoding); + + InstEmitAlu.TeqI(context, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), ImmUtils.ExpandedImmRotated(inst.Imm8, inst.Imm3, inst.I)); + } + + public static void TeqRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.TeqR(context, inst.Rn, inst.Rm, inst.Stype, inst.Imm5); + } + + public static void TeqRT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Imm3b12w3Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.TeqR(context, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3)); + } + + public static void TeqRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.TeqRr(context, inst.Rn, inst.Rm, inst.Stype, inst.Rs); + } + + public static void TsbA1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Tsb(); + } + + public static void TsbT1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Tsb(); + } + + public static void TstIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Imm12b0w12 inst = new(encoding); + + InstEmitAlu.TstI(context, inst.Rn, ImmUtils.ExpandImm(inst.Imm12), ImmUtils.ExpandedImmRotated(inst.Imm12)); + } + + public static void TstIT1(CodeGenContext context, uint encoding) + { + InstIb26w1Rnb16w4Imm3b12w3Imm8b0w8 inst = new(encoding); + + InstEmitAlu.TstI(context, inst.Rn, ImmUtils.ExpandImm(inst.Imm8, inst.Imm3, inst.I), ImmUtils.ExpandedImmRotated(inst.Imm8, inst.Imm3, inst.I)); + } + + public static void TstRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Imm5b7w5Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.TstR(context, inst.Rn, inst.Rm, inst.Stype, inst.Imm5); + } + + public static void TstRT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rnb16w3 inst = new(encoding); + + InstEmitAlu.TstR(context, inst.Rn, inst.Rm, 0, 0); + } + + public static void TstRT2(CodeGenContext context, uint encoding) + { + InstRnb16w4Imm3b12w3Imm2b6w2Stypeb4w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.TstR(context, inst.Rn, inst.Rm, inst.Stype, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3)); + } + + public static void TstRrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rsb8w4Stypeb5w2Rmb0w4 inst = new(encoding); + + InstEmitAlu.TstRr(context, inst.Rn, inst.Rm, inst.Stype, inst.Rs); + } + + public static void Uadd16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Uadd16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uadd16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Uadd16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uadd8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Uadd8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uadd8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Uadd8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UasxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Uasx(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UasxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Uasx(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UbfxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Widthm1b16w5Rdb12w4Lsbb7w5Rnb0w4 inst = new(encoding); + + InstEmitBit.Ubfx(context, inst.Rd, inst.Rn, inst.Lsb, inst.Widthm1); + } + + public static void UbfxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Imm3b12w3Rdb8w4Imm2b6w2Widthm1b0w5 inst = new(encoding); + + InstEmitBit.Ubfx(context, inst.Rd, inst.Rn, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3), inst.Widthm1); + } + + public static void UdfA1(CodeGenContext context, uint encoding) + { + InstImm12b8w12Imm4b0w4 inst = new(encoding); + + InstEmitSystem.Udf(context, encoding, ImmUtils.CombineImmU16(inst.Imm12, inst.Imm4)); + } + + public static void UdfT1(CodeGenContext context, uint encoding) + { + InstImm8b16w8 inst = new(encoding); + + InstEmitSystem.Udf(context, encoding, inst.Imm8); + } + + public static void UdfT2(CodeGenContext context, uint encoding) + { + InstImm4b16w4Imm12b0w12 inst = new(encoding); + + InstEmitSystem.Udf(context, encoding, ImmUtils.CombineImmU16(inst.Imm12, inst.Imm4)); + } + + public static void UdivA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rmb8w4Rnb0w4 inst = new(encoding); + + InstEmitDivide.Udiv(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UdivT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitDivide.Udiv(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uhadd16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Uhadd16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uhadd16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Uhadd16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uhadd8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Uhadd8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uhadd8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Uhadd8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UhasxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Uhasx(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UhasxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Uhasx(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UhsaxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Uhsax(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UhsaxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Uhsax(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uhsub16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Uhsub16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uhsub16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Uhsub16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uhsub8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Uhsub8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uhsub8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitHalve.Uhsub8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UmaalA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdhib16w4Rdlob12w4Rmb8w4Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Umaal(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm); + } + + public static void UmaalT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdlob12w4Rdhib8w4Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Umaal(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm); + } + + public static void UmlalA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdhib16w4Rdlob12w4Rmb8w4Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Umlal(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, inst.S != 0); + } + + public static void UmlalT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdlob12w4Rdhib8w4Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Umlal(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, false); + } + + public static void UmullA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Sb20w1Rdhib16w4Rdlob12w4Rmb8w4Rnb0w4 inst = new(encoding); + + InstEmitMultiply.Umull(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, inst.S != 0); + } + + public static void UmullT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdlob12w4Rdhib8w4Rmb0w4 inst = new(encoding); + + InstEmitMultiply.Umull(context, inst.Rdlo, inst.Rdhi, inst.Rn, inst.Rm, false); + } + + public static void Uqadd16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Uqadd16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uqadd16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Uqadd16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uqadd8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Uqadd8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uqadd8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Uqadd8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UqasxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Uqasx(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UqasxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Uqasx(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UqsaxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Uqsax(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UqsaxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Uqsax(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uqsub16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Uqsub16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uqsub16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Uqsub16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uqsub8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Uqsub8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Uqsub8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitSaturate.Uqsub8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Usad8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rmb8w4Rnb0w4 inst = new(encoding); + + InstEmitAbsDiff.Usad8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Usad8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitAbsDiff.Usad8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Usada8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb16w4Rab12w4Rmb8w4Rnb0w4 inst = new(encoding); + + InstEmitAbsDiff.Usada8(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra); + } + + public static void Usada8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rab12w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitAbsDiff.Usada8(context, inst.Rd, inst.Rn, inst.Rm, inst.Ra); + } + + public static void UsatA1(CodeGenContext context, uint encoding) + { + InstCondb28w4SatImmb16w5Rdb12w4Imm5b7w5Shb6w1Rnb0w4 inst = new(encoding); + + InstEmitSaturate.Usat(context, inst.Rd, inst.SatImm, inst.Rn, inst.Sh != 0, inst.Imm5); + } + + public static void UsatT1(CodeGenContext context, uint encoding) + { + InstShb21w1Rnb16w4Imm3b12w3Rdb8w4Imm2b6w2SatImmb0w5 inst = new(encoding); + + InstEmitSaturate.Usat(context, inst.Rd, inst.SatImm, inst.Rn, inst.Sh != 0, ImmUtils.CombineImmU5(inst.Imm2, inst.Imm3)); + } + + public static void Usat16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4SatImmb16w4Rdb12w4Rnb0w4 inst = new(encoding); + + InstEmitSaturate.Usat16(context, inst.Rd, inst.SatImm, inst.Rn); + } + + public static void Usat16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4SatImmb0w4 inst = new(encoding); + + InstEmitSaturate.Usat16(context, inst.Rd, inst.SatImm, inst.Rn); + } + + public static void UsaxA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Usax(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UsaxT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Usax(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Usub16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Usub16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Usub16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Usub16(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Usub8A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Usub8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void Usub8T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rmb0w4 inst = new(encoding); + + InstEmitGE.Usub8(context, inst.Rd, inst.Rn, inst.Rm); + } + + public static void UxtabA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rotateb10w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Uxtab(context, inst.Rd, inst.Rn, inst.Rm, inst.Rotate); + } + + public static void UxtabT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rotateb4w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Uxtab(context, inst.Rd, inst.Rn, inst.Rm, inst.Rotate); + } + + public static void Uxtab16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rotateb10w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Uxtab16(context, inst.Rd, inst.Rn, inst.Rm, inst.Rotate); + } + + public static void Uxtab16T1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rotateb4w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Uxtab16(context, inst.Rd, inst.Rn, inst.Rm, inst.Rotate); + } + + public static void UxtahA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rnb16w4Rdb12w4Rotateb10w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Uxtah(context, inst.Rd, inst.Rn, inst.Rm, inst.Rotate); + } + + public static void UxtahT1(CodeGenContext context, uint encoding) + { + InstRnb16w4Rdb8w4Rotateb4w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Uxtah(context, inst.Rd, inst.Rn, inst.Rm, inst.Rotate); + } + + public static void UxtbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Rotateb10w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Uxtb(context, inst.Rd, inst.Rm, inst.Rotate); + } + + public static void UxtbT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdb16w3 inst = new(encoding); + + InstEmitExtension.Uxtb(context, inst.Rd, inst.Rm, 0); + } + + public static void UxtbT2(CodeGenContext context, uint encoding) + { + InstRdb8w4Rotateb4w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Uxtb(context, inst.Rd, inst.Rm, inst.Rotate); + } + + public static void Uxtb16A1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Rotateb10w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Uxtb16(context, inst.Rd, inst.Rm, inst.Rotate); + } + + public static void Uxtb16T1(CodeGenContext context, uint encoding) + { + InstRdb8w4Rotateb4w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Uxtb16(context, inst.Rd, inst.Rm, inst.Rotate); + } + + public static void UxthA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Rdb12w4Rotateb10w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Uxth(context, inst.Rd, inst.Rm, inst.Rotate); + } + + public static void UxthT1(CodeGenContext context, uint encoding) + { + InstRmb19w3Rdb16w3 inst = new(encoding); + + InstEmitExtension.Uxth(context, inst.Rd, inst.Rm, 0); + } + + public static void UxthT2(CodeGenContext context, uint encoding) + { + InstRdb8w4Rotateb4w2Rmb0w4 inst = new(encoding); + + InstEmitExtension.Uxth(context, inst.Rd, inst.Rm, inst.Rotate); + } + + public static void VabaA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vaba(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VabaT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vaba(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VabalA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vabal(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VabalT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vabal(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VabdlIA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vabdl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VabdlIT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vabdl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VabdFA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VabdF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VabdFT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VabdF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VabdIA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VabdI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VabdIT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VabdI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VabsA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vabs(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VabsA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VabsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VabsT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vabs(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VabsT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VabsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VacgeA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.Vacge(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VacgeT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.Vacge(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VacgtA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.Vacgt(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VacgtT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.Vacgt(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VaddhnA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vaddhn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VaddhnT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vaddhn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VaddlA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vaddl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VaddlT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vaddl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VaddwA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vaddw(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VaddwT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vaddw(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VaddFA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VaddF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VaddFA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VaddF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VaddFT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VaddF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VaddFT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VaddF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VaddIA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VaddI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VaddIT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VaddI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VandRA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VandR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VandRT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VandR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VbicIA1(CodeGenContext context, uint encoding) + { + InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonLogical.VbicI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VbicIA2(CodeGenContext context, uint encoding) + { + InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonLogical.VbicI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VbicIT1(CodeGenContext context, uint encoding) + { + InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonLogical.VbicI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VbicIT2(CodeGenContext context, uint encoding) + { + InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonLogical.VbicI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VbicRA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VbicR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VbicRT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VbicR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VbifA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VbifR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VbifT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VbifR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VbitA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VbitR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VbitT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VbitR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VbslA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VbslR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VbslT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VbslR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VcaddA1(CodeGenContext context, uint encoding) + { + _ = new InstRotb24w1Db22w1Sb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VcaddT1(CodeGenContext context, uint encoding) + { + _ = new InstRotb24w1Db22w1Sb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VceqIA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VceqI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VceqIT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VceqI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VceqRA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VceqR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VceqRA2(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VceqFR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VceqRT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VceqR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VceqRT2(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VceqFR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VcgeIA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcgeI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VcgeIT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcgeI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VcgeRA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcgeR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VcgeRA2(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcgeFR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VcgeRT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcgeR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VcgeRT2(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcgeFR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VcgtIA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcgtI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VcgtIT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcgtI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VcgtRA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcgtR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VcgtRA2(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcgtFR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VcgtRT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcgtR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VcgtRT2(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcgtFR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VcleIA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcleI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VcleIT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcleI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VclsA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonBit.Vcls(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VclsT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonBit.Vcls(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VcltIA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcltI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VcltIT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.VcltI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VclzA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonBit.Vclz(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VclzT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonBit.Vclz(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VcmlaA1(CodeGenContext context, uint encoding) + { + _ = new InstRotb23w2Db22w1Sb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VcmlaT1(CodeGenContext context, uint encoding) + { + _ = new InstRotb23w2Db22w1Sb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VcmlaSA1(CodeGenContext context, uint encoding) + { + _ = new InstSb23w1Db22w1Rotb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VcmlaST1(CodeGenContext context, uint encoding) + { + _ = new InstSb23w1Db22w1Rotb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VcmpA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpCompare.VcmpR(context, inst.Cond, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VcmpA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2 inst = new(encoding); + + InstEmitVfpCompare.VcmpI(context, inst.Cond, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), inst.Size); + } + + public static void VcmpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpCompare.VcmpR(context, 0xe, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VcmpT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2 inst = new(encoding); + + InstEmitVfpCompare.VcmpI(context, 0xe, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), inst.Size); + } + + public static void VcmpeA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpCompare.VcmpeR(context, inst.Cond, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VcmpeA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2 inst = new(encoding); + + InstEmitVfpCompare.VcmpeI(context, inst.Cond, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), inst.Size); + } + + public static void VcmpeT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpCompare.VcmpeR(context, 0xe, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VcmpeT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2 inst = new(encoding); + + InstEmitVfpCompare.VcmpeI(context, 0xe, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), inst.Size); + } + + public static void VcntA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonBit.Vcnt(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VcntT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonBit.Vcnt(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VcvtaAsimdA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.Vcvta(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VcvtaAsimdT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.Vcvta(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VcvtaVfpA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.Vcvta(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Op != 0, inst.Size); + } + + public static void VcvtaVfpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.Vcvta(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Op != 0, inst.Size); + } + + public static void VcvtbA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Opb16w1Vdb12w4Szb8w1Mb5w1Vmb0w4 inst = new(encoding); + + uint dSize = inst.Sz == 1 && inst.Op == 0 ? 3u : 2u; + uint mSize = inst.Sz == 1 && inst.Op == 1 ? 3u : 2u; + + InstEmitVfpConvert.Vcvtb(context, InstEmitCommon.CombineV(inst.Vd, inst.D, dSize), InstEmitCommon.CombineV(inst.Vm, inst.M, mSize), inst.Sz, inst.Op); + } + + public static void VcvtbT1(CodeGenContext context, uint encoding) + { + InstDb22w1Opb16w1Vdb12w4Szb8w1Mb5w1Vmb0w4 inst = new(encoding); + + uint dSize = inst.Sz == 1 && inst.Op == 0 ? 3u : 2u; + uint mSize = inst.Sz == 1 && inst.Op == 1 ? 3u : 2u; + + InstEmitVfpConvert.Vcvtb(context, InstEmitCommon.CombineV(inst.Vd, inst.D, dSize), InstEmitCommon.CombineV(inst.Vm, inst.M, mSize), inst.Sz, inst.Op); + } + + public static void VcvtbBfsA1(CodeGenContext context, uint encoding) + { + _ = new InstCondb28w4Db22w1Vdb12w4Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VcvtbBfsT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vdb12w4Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VcvtmAsimdA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.Vcvtm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VcvtmAsimdT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.Vcvtm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VcvtmVfpA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.Vcvtm(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Op != 0, inst.Size); + } + + public static void VcvtmVfpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.Vcvtm(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Op != 0, inst.Size); + } + + public static void VcvtnAsimdA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.Vcvtn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VcvtnAsimdT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.Vcvtn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VcvtnVfpA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.Vcvtn(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Op != 0, inst.Size); + } + + public static void VcvtnVfpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.Vcvtn(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Op != 0, inst.Size); + } + + public static void VcvtpAsimdA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.Vcvtp(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VcvtpAsimdT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.Vcvtp(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VcvtpVfpA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.Vcvtp(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Op != 0, inst.Size); + } + + public static void VcvtpVfpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.Vcvtp(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Op != 0, inst.Size); + } + + public static void VcvtrIvA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.VcvtrIv(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), (encoding >> 16) & 7, inst.Size); + } + + public static void VcvtrIvT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.VcvtrIv(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), (encoding >> 16) & 7, inst.Size); + } + + public static void VcvttA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Opb16w1Vdb12w4Szb8w1Mb5w1Vmb0w4 inst = new(encoding); + + uint dSize = inst.Sz == 1 && inst.Op == 0 ? 3u : 2u; + uint mSize = inst.Sz == 1 && inst.Op == 1 ? 3u : 2u; + + InstEmitVfpConvert.Vcvtt(context, InstEmitCommon.CombineV(inst.Vd, inst.D, dSize), InstEmitCommon.CombineV(inst.Vm, inst.M, mSize), inst.Sz, inst.Op); + } + + public static void VcvttT1(CodeGenContext context, uint encoding) + { + InstDb22w1Opb16w1Vdb12w4Szb8w1Mb5w1Vmb0w4 inst = new(encoding); + + uint dSize = inst.Sz == 1 && inst.Op == 0 ? 3u : 2u; + uint mSize = inst.Sz == 1 && inst.Op == 1 ? 3u : 2u; + + InstEmitVfpConvert.Vcvtt(context, InstEmitCommon.CombineV(inst.Vd, inst.D, dSize), InstEmitCommon.CombineV(inst.Vm, inst.M, mSize), inst.Sz, inst.Op); + } + + public static void VcvttBfsA1(CodeGenContext context, uint encoding) + { + _ = new InstCondb28w4Db22w1Vdb12w4Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VcvttBfsT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vdb12w4Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VcvtBfsA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vdb12w4Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VcvtBfsT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vdb12w4Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VcvtDsA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + uint size = (encoding >> 8) & 3; + + InstEmitVfpConvert.VcvtDs(context, InstEmitCommon.CombineV(inst.Vd, inst.D, size ^ 1u), InstEmitCommon.CombineV(inst.Vm, inst.M, size), size); + } + + public static void VcvtDsT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + uint size = (encoding >> 8) & 3; + + InstEmitVfpConvert.VcvtDs(context, InstEmitCommon.CombineV(inst.Vd, inst.D, size ^ 1u), InstEmitCommon.CombineV(inst.Vm, inst.M, size), size); + } + + public static void VcvtHsA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb8w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.VcvtHs(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0); + } + + public static void VcvtHsT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb8w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.VcvtHs(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0); + } + + public static void VcvtIsA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w2Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.VcvtIs(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op, inst.Size, inst.Q); + } + + public static void VcvtIsT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w2Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.VcvtIs(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op, inst.Size, inst.Q); + } + + public static void VcvtIvA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.VcvtIv(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), (encoding & (1u << 16)) == 0, inst.Size); + } + + public static void VcvtIvT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.VcvtIv(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), (encoding & (1u << 16)) == 0, inst.Size); + } + + public static void VcvtViA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.VcvtVi(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineVF(inst.M, inst.Vm), inst.Op == 0, inst.Size); + } + + public static void VcvtViT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Opb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpConvert.VcvtVi(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineVF(inst.M, inst.Vm), inst.Op == 0, inst.Size); + } + + public static void VcvtXsA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Imm6b16w6Vdb12w4Opb8w2Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.VcvtXs(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Imm6, inst.Op, inst.U != 0, inst.Q); + } + + public static void VcvtXsT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Imm6b16w6Vdb12w4Opb8w2Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonConvert.VcvtXs(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Imm6, inst.Op, inst.U != 0, inst.Q); + } + + public static void VcvtXvA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Opb18w1Ub16w1Vdb12w4Sfb8w2Sxb7w1Ib5w1Imm4b0w4 inst = new(encoding); + + InstEmitVfpConvert.VcvtXv(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Sf), ImmUtils.CombineImmU5IImm4(inst.I, inst.Imm4), inst.Sx != 0, inst.Sf, inst.Op, inst.U != 0); + } + + public static void VcvtXvT1(CodeGenContext context, uint encoding) + { + InstDb22w1Opb18w1Ub16w1Vdb12w4Sfb8w2Sxb7w1Ib5w1Imm4b0w4 inst = new(encoding); + + InstEmitVfpConvert.VcvtXv(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Sf), ImmUtils.CombineImmU5IImm4(inst.I, inst.Imm4), inst.Sx != 0, inst.Sf, inst.Op, inst.U != 0); + } + + public static void VdivA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VdivF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VdivT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VdivF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VdotA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VdotT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VdotSA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VdotST1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VdupRA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Bb22w1Qb21w1Vdb16w4Rtb12w4Db7w1Eb5w1 inst = new(encoding); + + InstEmitNeonMove.VdupR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rt, inst.B, inst.E, inst.Q); + } + + public static void VdupRT1(CodeGenContext context, uint encoding) + { + InstBb22w1Qb21w1Vdb16w4Rtb12w4Db7w1Eb5w1 inst = new(encoding); + + InstEmitNeonMove.VdupR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rt, inst.B, inst.E, inst.Q); + } + + public static void VdupSA1(CodeGenContext context, uint encoding) + { + InstDb22w1Imm4b16w4Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.VdupS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Imm4, inst.Q); + } + + public static void VdupST1(CodeGenContext context, uint encoding) + { + InstDb22w1Imm4b16w4Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.VdupS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Imm4, inst.Q); + } + + public static void VeorA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VeorR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VeorT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VeorR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VextA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Imm4b8w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vext(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Imm4, inst.Q); + } + + public static void VextT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Imm4b8w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vext(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Imm4, inst.Q); + } + + public static void VfmaA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VfmaF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VfmaA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VfmaF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VfmaT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VfmaF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VfmaT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VfmaF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VfmalA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VfmalT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VfmalSA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VfmalST1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VfmaBfA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VfmaBfT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VfmaBfsA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VfmaBfsT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VfmsA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VfmsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VfmsA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VfmsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VfmsT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VfmsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VfmsT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VfmsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VfmslA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VfmslT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VfmslSA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VfmslST1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VfnmaA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VfnmaF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VfnmaT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VfnmaF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VfnmsA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VfnmsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VfnmsT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VfnmsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VhaddA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vhadd(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VhaddT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vhadd(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VhsubA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vhsub(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VhsubT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vhsub(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VinsA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vdb12w4Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VinsT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vdb12w4Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VjcvtA1(CodeGenContext context, uint encoding) + { + _ = new InstCondb28w4Db22w1Vdb12w4Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VjcvtT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vdb12w4Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void Vld11A1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld11(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vld11A2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld11(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vld11A3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld11(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vld11T1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld11(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vld11T2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld11(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vld11T3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld11(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vld1AA1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Tb5w1Ab4w1Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld1A(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.A, inst.T, inst.Size); + } + + public static void Vld1AT1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Tb5w1Ab4w1Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld1A(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.A, inst.T, inst.Size); + } + + public static void Vld1MA1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 1, inst.Align, inst.Size); + } + + public static void Vld1MA2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 2, inst.Align, inst.Size); + } + + public static void Vld1MA3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 3, inst.Align, inst.Size); + } + + public static void Vld1MA4(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 4, inst.Align, inst.Size); + } + + public static void Vld1MT1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 1, inst.Align, inst.Size); + } + + public static void Vld1MT2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 2, inst.Align, inst.Size); + } + + public static void Vld1MT3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 3, inst.Align, inst.Size); + } + + public static void Vld1MT4(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 4, inst.Align, inst.Size); + } + + public static void Vld21A1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld21(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vld21A2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld21(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vld21A3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld21(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vld21T1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld21(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vld21T2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld21(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vld21T3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld21(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vld2AA1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Tb5w1Ab4w1Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld2A(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.A, inst.T, inst.Size); + } + + public static void Vld2AT1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Tb5w1Ab4w1Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld2A(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.A, inst.T, inst.Size); + } + + public static void Vld2MA1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld2M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, (encoding >> 8) & 0xf, inst.Align, inst.Size); + } + + public static void Vld2MA2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld2M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.Align, inst.Size); + } + + public static void Vld2MT1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld2M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, (encoding >> 8) & 0xf, inst.Align, inst.Size); + } + + public static void Vld2MT2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld2M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.Align, inst.Size); + } + + public static void Vld31A1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld31(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vld31A2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld31(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vld31A3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld31(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vld31T1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld31(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vld31T2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld31(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vld31T3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld31(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vld3AA1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Tb5w1Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld3A(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 0, inst.T, inst.Size); + } + + public static void Vld3AT1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Tb5w1Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld3A(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 0, inst.T, inst.Size); + } + + public static void Vld3MA1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld3M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, (encoding >> 8) & 0xf, inst.Align, inst.Size); + } + + public static void Vld3MT1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld3M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, (encoding >> 8) & 0xf, inst.Align, inst.Size); + } + + public static void Vld41A1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld41(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vld41A2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld41(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vld41A3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld41(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vld41T1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld41(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vld41T2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld41(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vld41T3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld41(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vld4AA1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Tb5w1Ab4w1Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld4A(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.A, inst.T, inst.Size); + } + + public static void Vld4AT1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Tb5w1Ab4w1Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld4A(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.A, inst.T, inst.Size); + } + + public static void Vld4MA1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld4M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, (encoding >> 8) & 0xf, inst.Align, inst.Size); + } + + public static void Vld4MT1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vld4M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, (encoding >> 8) & 0xf, inst.Align, inst.Size); + } + + public static void VldmA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm871b1w7 inst = new(encoding); + + InstEmitNeonMemory.Vldm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Imm871, inst.U != 0, inst.W != 0, singleRegs: false); + } + + public static void VldmA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm8b0w8 inst = new(encoding); + + InstEmitNeonMemory.Vldm(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), inst.Rn, inst.Imm8, inst.U != 0, inst.W != 0, singleRegs: true); + } + + public static void VldmT1(CodeGenContext context, uint encoding) + { + InstPb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm871b1w7 inst = new(encoding); + + InstEmitNeonMemory.Vldm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Imm871, inst.U != 0, inst.W != 0, singleRegs: false); + } + + public static void VldmT2(CodeGenContext context, uint encoding) + { + InstPb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm8b0w8 inst = new(encoding); + + InstEmitNeonMemory.Vldm(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), inst.Rn, inst.Imm8, inst.U != 0, inst.W != 0, singleRegs: true); + } + + public static void VldrIA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Db22w1Rnb16w4Vdb12w4Sizeb8w2Imm8b0w8 inst = new(encoding); + + InstEmitNeonMemory.Vldr(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), inst.Rn, inst.Imm8, inst.U != 0, inst.Size); + } + + public static void VldrIT1(CodeGenContext context, uint encoding) + { + InstUb23w1Db22w1Rnb16w4Vdb12w4Sizeb8w2Imm8b0w8 inst = new(encoding); + + InstEmitNeonMemory.Vldr(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), inst.Rn, inst.Imm8, inst.U != 0, inst.Size); + } + + public static void VldrLA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Db22w1Vdb12w4Sizeb8w2Imm8b0w8 inst = new(encoding); + + InstEmitNeonMemory.Vldr(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), RegisterUtils.PcRegister, inst.Imm8, inst.U != 0, inst.Size); + } + + public static void VldrLT1(CodeGenContext context, uint encoding) + { + InstUb23w1Db22w1Vdb12w4Sizeb8w2Imm8b0w8 inst = new(encoding); + + InstEmitNeonMemory.Vldr(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), RegisterUtils.PcRegister, inst.Imm8, inst.U != 0, inst.Size); + } + + public static void VmaxnmA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vmaxnm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VmaxnmA2(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.Vmaxnm(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VmaxnmT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vmaxnm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VmaxnmT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.Vmaxnm(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VmaxFA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmaxF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VmaxFT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmaxF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VmaxIA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmaxI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VmaxIT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmaxI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VminnmA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vminnm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VminnmA2(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.Vminnm(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VminnmT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vminnm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VminnmT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.Vminnm(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VminFA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VminF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VminFT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VminF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VminIA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VminI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VminIT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VminI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VmlalIA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlalI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VmlalIT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlalI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VmlalSA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlalS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VmlalST1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlalS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VmlaFA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlaF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VmlaFA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VmlaF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VmlaFT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlaF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VmlaFT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VmlaF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VmlaIA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlaI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VmlaIT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlaI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VmlaSA1(CodeGenContext context, uint encoding) + { + InstQb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Fb8w1Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlaS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VmlaST1(CodeGenContext context, uint encoding) + { + InstQb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Fb8w1Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlaS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VmlslIA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlslI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VmlslIT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlslI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VmlslSA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlslS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VmlslST1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlslS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VmlsFA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VmlsFA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VmlsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VmlsFT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VmlsFT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VmlsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VmlsIA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlsI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VmlsIT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlsI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VmlsSA1(CodeGenContext context, uint encoding) + { + InstQb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Fb8w1Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlsS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VmlsST1(CodeGenContext context, uint encoding) + { + InstQb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Fb8w1Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmlsS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VmmlaA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VmmlaT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VmovlA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Imm3hb19w3Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vmovl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Imm3h); + } + + public static void VmovlT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Imm3hb19w3Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vmovl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Imm3h); + } + + public static void VmovnA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vmovn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VmovnT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vmovn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VmovxA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vmovx(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M)); + } + + public static void VmovxT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vmovx(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M)); + } + + public static void VmovDA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Opb20w1Rt2b16w4Rtb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.VmovD(context, inst.Rt, inst.Rt2, InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0); + } + + public static void VmovDT1(CodeGenContext context, uint encoding) + { + InstOpb20w1Rt2b16w4Rtb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.VmovD(context, inst.Rt, inst.Rt2, InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0); + } + + public static void VmovHA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Opb20w1Vnb16w4Rtb12w4Nb7w1 inst = new(encoding); + + InstEmitNeonMove.VmovH(context, inst.Rt, InstEmitCommon.CombineVF(inst.N, inst.Vn), inst.Op != 0); + } + + public static void VmovHT1(CodeGenContext context, uint encoding) + { + InstOpb20w1Vnb16w4Rtb12w4Nb7w1 inst = new(encoding); + + InstEmitNeonMove.VmovH(context, inst.Rt, InstEmitCommon.CombineVF(inst.N, inst.Vn), inst.Op != 0); + } + + public static void VmovIA1(CodeGenContext context, uint encoding) + { + InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmovI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), 0, (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmovIA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Imm4hb16w4Vdb12w4Sizeb8w2Imm4lb0w4 inst = new(encoding); + + InstEmitNeonMove.VmovFI(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), inst.Size); + } + + public static void VmovIA3(CodeGenContext context, uint encoding) + { + InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmovI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), 0, (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmovIA4(CodeGenContext context, uint encoding) + { + InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmovI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), 0, (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmovIA5(CodeGenContext context, uint encoding) + { + InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmovI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), 1, (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmovIT1(CodeGenContext context, uint encoding) + { + InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmovI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), 0, (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmovIT2(CodeGenContext context, uint encoding) + { + InstDb22w1Imm4hb16w4Vdb12w4Sizeb8w2Imm4lb0w4 inst = new(encoding); + + InstEmitNeonMove.VmovFI(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), ImmUtils.CombineImmU8(inst.Imm4l, inst.Imm4h), inst.Size); + } + + public static void VmovIT3(CodeGenContext context, uint encoding) + { + InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmovI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), 0, (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmovIT4(CodeGenContext context, uint encoding) + { + InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmovI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), 0, (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmovIT5(CodeGenContext context, uint encoding) + { + InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmovI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), 1, (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmovRA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + uint size = (encoding >> 8) & 3; + + InstEmitNeonMove.VmovR(context, InstEmitCommon.CombineV(inst.Vd, inst.D, size), InstEmitCommon.CombineV(inst.Vm, inst.M, size), size); + } + + public static void VmovRT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + uint size = (encoding >> 8) & 3; + + InstEmitNeonMove.VmovR(context, InstEmitCommon.CombineV(inst.Vd, inst.D, size), InstEmitCommon.CombineV(inst.Vm, inst.M, size), size); + } + + public static void VmovRsA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Opc1b21w2Vdb16w4Rtb12w4Db7w1Opc2b5w2 inst = new(encoding); + + InstEmitNeonMove.VmovRs(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rt, inst.Opc1, inst.Opc2); + } + + public static void VmovRsT1(CodeGenContext context, uint encoding) + { + InstOpc1b21w2Vdb16w4Rtb12w4Db7w1Opc2b5w2 inst = new(encoding); + + InstEmitNeonMove.VmovRs(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rt, inst.Opc1, inst.Opc2); + } + + public static void VmovSA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Opb20w1Vnb16w4Rtb12w4Nb7w1 inst = new(encoding); + + InstEmitNeonMove.VmovS(context, inst.Rt, InstEmitCommon.CombineVF(inst.N, inst.Vn), inst.Op != 0); + } + + public static void VmovST1(CodeGenContext context, uint encoding) + { + InstOpb20w1Vnb16w4Rtb12w4Nb7w1 inst = new(encoding); + + InstEmitNeonMove.VmovS(context, inst.Rt, InstEmitCommon.CombineVF(inst.N, inst.Vn), inst.Op != 0); + } + + public static void VmovSrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Opc1b21w2Vnb16w4Rtb12w4Nb7w1Opc2b5w2 inst = new(encoding); + + InstEmitNeonMove.VmovSr(context, inst.Rt, InstEmitCommon.CombineV(inst.Vn, inst.N), inst.U != 0, inst.Opc1, inst.Opc2); + } + + public static void VmovSrT1(CodeGenContext context, uint encoding) + { + InstUb23w1Opc1b21w2Vnb16w4Rtb12w4Nb7w1Opc2b5w2 inst = new(encoding); + + InstEmitNeonMove.VmovSr(context, inst.Rt, InstEmitCommon.CombineV(inst.Vn, inst.N), inst.U != 0, inst.Opc1, inst.Opc2); + } + + public static void VmovSsA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Opb20w1Rt2b16w4Rtb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.VmovSs(context, inst.Rt, inst.Rt2, InstEmitCommon.CombineVF(inst.M, inst.Vm), inst.Op != 0); + } + + public static void VmovSsT1(CodeGenContext context, uint encoding) + { + InstOpb20w1Rt2b16w4Rtb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.VmovSs(context, inst.Rt, inst.Rt2, InstEmitCommon.CombineVF(inst.M, inst.Vm), inst.Op != 0); + } + + public static void VmrsA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Regb16w4Rtb12w4 inst = new(encoding); + + InstEmitNeonSystem.Vmrs(context, inst.Rt, inst.Reg); + } + + public static void VmrsT1(CodeGenContext context, uint encoding) + { + InstRegb16w4Rtb12w4 inst = new(encoding); + + InstEmitNeonSystem.Vmrs(context, inst.Rt, inst.Reg); + } + + public static void VmsrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Regb16w4Rtb12w4 inst = new(encoding); + + InstEmitNeonSystem.Vmsr(context, inst.Rt, inst.Reg); + } + + public static void VmsrT1(CodeGenContext context, uint encoding) + { + InstRegb16w4Rtb12w4 inst = new(encoding); + + InstEmitNeonSystem.Vmsr(context, inst.Rt, inst.Reg); + } + + public static void VmullIA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Opb9w1Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmullI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.U != 0, inst.Size); + } + + public static void VmullIT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Opb9w1Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmullI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.U != 0, inst.Size); + } + + public static void VmullSA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmullS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VmullST1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmullS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VmulFA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmulF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VmulFA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VmulF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VmulFT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmulF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VmulFT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VmulF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VmulIA1(CodeGenContext context, uint encoding) + { + InstOpb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmulI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VmulIT1(CodeGenContext context, uint encoding) + { + InstOpb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmulI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VmulSA1(CodeGenContext context, uint encoding) + { + InstQb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Fb8w1Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmulS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VmulST1(CodeGenContext context, uint encoding) + { + InstQb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Fb8w1Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VmulS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VmvnIA1(CodeGenContext context, uint encoding) + { + InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmvnI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmvnIA2(CodeGenContext context, uint encoding) + { + InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmvnI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmvnIA3(CodeGenContext context, uint encoding) + { + InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmvnI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmvnIT1(CodeGenContext context, uint encoding) + { + InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmvnI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmvnIT2(CodeGenContext context, uint encoding) + { + InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmvnI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmvnIT3(CodeGenContext context, uint encoding) + { + InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonMove.VmvnI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VmvnRA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.VmvnR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VmvnRT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.VmvnR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VnegA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vneg(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VnegA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VnegF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VnegT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb10w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vneg(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VnegT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VnegF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VnmlaA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VnmlaF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VnmlaT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VnmlaF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VnmlsA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VnmlsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VnmlsT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VnmlsF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VnmulA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VnmulF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VnmulT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VnmulF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VornRA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VornR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VornRT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VornR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VorrIA1(CodeGenContext context, uint encoding) + { + InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonLogical.VorrI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VorrIA2(CodeGenContext context, uint encoding) + { + InstIb24w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonLogical.VorrI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VorrIT1(CodeGenContext context, uint encoding) + { + InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonLogical.VorrI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VorrIT2(CodeGenContext context, uint encoding) + { + InstIb28w1Db22w1Imm3b16w3Vdb12w4Qb6w1Imm4b0w4 inst = new(encoding); + + InstEmitNeonLogical.VorrI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), (encoding >> 8) & 0xf, ImmUtils.CombineImmU8(inst.Imm4, inst.Imm3, inst.I), inst.Q); + } + + public static void VorrRA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VorrR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VorrRT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonLogical.VorrR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VpadalA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vpadal(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VpadalT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vpadal(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VpaddlA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vpaddl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VpaddlT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vpaddl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Size, inst.Q); + } + + public static void VpaddFA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VpaddF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VpaddFT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VpaddF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VpaddIA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VpaddI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VpaddIT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VpaddI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VpmaxFA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VpmaxF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, 0); + } + + public static void VpmaxFT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VpmaxF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, 0); + } + + public static void VpmaxIA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VpmaxI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, 0); + } + + public static void VpmaxIT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VpmaxI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, 0); + } + + public static void VpminFA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VpminF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, 0); + } + + public static void VpminFT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VpminF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, 0); + } + + public static void VpminIA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VpminI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, 0); + } + + public static void VpminIT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VpminI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, 0); + } + + public static void VqabsA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqabs(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqabsT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqabs(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqaddA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqadd(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VqaddT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqadd(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VqdmlalA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqdmlal(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VqdmlalA2(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqdmlalS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VqdmlalT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqdmlal(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VqdmlalT2(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqdmlalS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VqdmlslA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqdmlsl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VqdmlslA2(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqdmlslS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VqdmlslT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqdmlsl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VqdmlslT2(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqdmlslS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VqdmulhA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqdmulh(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqdmulhA2(CodeGenContext context, uint encoding) + { + InstQb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqdmulhS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqdmulhT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqdmulh(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqdmulhT2(CodeGenContext context, uint encoding) + { + InstQb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqdmulhS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqdmullA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqdmull(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VqdmullA2(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqdmullS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VqdmullT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqdmull(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VqdmullT2(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqdmullS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VqmovnA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb6w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqmovn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op, inst.Size); + } + + public static void VqmovnT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Opb6w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqmovn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op, inst.Size); + } + + public static void VqnegA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqneg(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqnegT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqneg(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrdmlahA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqrdmlah(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrdmlahA2(CodeGenContext context, uint encoding) + { + InstQb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqrdmlahS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrdmlahT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqrdmlah(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrdmlahT2(CodeGenContext context, uint encoding) + { + InstQb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqrdmlahS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrdmlshA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqrdmlsh(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrdmlshA2(CodeGenContext context, uint encoding) + { + InstQb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqrdmlshS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrdmlshT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqrdmlsh(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrdmlshT2(CodeGenContext context, uint encoding) + { + InstQb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqrdmlshS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrdmulhA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqrdmulh(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrdmulhA2(CodeGenContext context, uint encoding) + { + InstQb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqrdmulhS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrdmulhT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqrdmulh(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrdmulhT2(CodeGenContext context, uint encoding) + { + InstQb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqrdmulhS(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrshlA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqrshl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrshlT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqrshl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VqrshrnA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Imm6b16w6Vdb12w4Opb8w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqrshrn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Op, inst.Imm6); + } + + public static void VqrshrnT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Imm6b16w6Vdb12w4Opb8w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqrshrn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Op, inst.Imm6); + } + + public static void VqshlIA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Imm6b16w6Vdb12w4Opb8w1Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqshlI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Op, inst.L, inst.Imm6, inst.Q); + } + + public static void VqshlIT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Imm6b16w6Vdb12w4Opb8w1Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqshlI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Op, inst.L, inst.Imm6, inst.Q); + } + + public static void VqshlRA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqshlR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VqshlRT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.VqshlR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VqshrnA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Imm6b16w6Vdb12w4Opb8w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqshrn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Op, inst.Imm6); + } + + public static void VqshrnT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Imm6b16w6Vdb12w4Opb8w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqshrn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Op, inst.Imm6); + } + + public static void VqsubA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqsub(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VqsubT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonSaturate.Vqsub(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VraddhnA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vraddhn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VraddhnT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vraddhn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VrecpeA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb8w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vrecpe(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VrecpeT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb8w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vrecpe(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VrecpsA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vrecps(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VrecpsT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vrecps(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void Vrev16A1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonBit.Vrev16(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void Vrev16T1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonBit.Vrev16(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void Vrev32A1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonBit.Vrev32(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void Vrev32T1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonBit.Vrev32(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void Vrev64A1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonBit.Vrev64(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void Vrev64T1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonBit.Vrev64(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrhaddA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrhadd(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VrhaddT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrhadd(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VrintaAsimdA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrinta(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrintaAsimdT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrinta(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrintaVfpA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrinta(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintaVfpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrinta(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintmAsimdA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrintm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrintmAsimdT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrintm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrintmVfpA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrintm(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintmVfpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrintm(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintnAsimdA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrintn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrintnAsimdT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrintn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrintnVfpA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrintn(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintnVfpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrintn(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintpAsimdA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrintp(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrintpAsimdT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrintp(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrintpVfpA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrintp(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintpVfpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrintp(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintrVfpA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrintr(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintrVfpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrintr(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintxAsimdA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrintx(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrintxAsimdT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrintx(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrintxVfpA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrintx(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintxVfpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrintx(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintzAsimdA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrintz(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrintzAsimdT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrintz(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VrintzVfpA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrintz(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrintzVfpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpRound.Vrintz(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VrshlA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrshl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VrshlT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrshl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VrshrA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrshr(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.L, inst.Imm6, inst.Q); + } + + public static void VrshrT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrshr(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.L, inst.Imm6, inst.Q); + } + + public static void VrshrnA1(CodeGenContext context, uint encoding) + { + InstDb22w1Imm6b16w6Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrshrn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Imm6); + } + + public static void VrshrnT1(CodeGenContext context, uint encoding) + { + InstDb22w1Imm6b16w6Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrshrn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Imm6); + } + + public static void VrsqrteA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb8w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vrsqrte(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VrsqrteT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Fb8w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vrsqrte(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.F != 0, inst.Size, inst.Q); + } + + public static void VrsqrtsA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vrsqrts(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VrsqrtsT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vrsqrts(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VrsraA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrsra(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.L, inst.Imm6, inst.Q); + } + + public static void VrsraT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrsra(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.L, inst.Imm6, inst.Q); + } + + public static void VrsubhnA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrsubhn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VrsubhnT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonRound.Vrsubhn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VsdotA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VsdotT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VsdotSA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VsdotST1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VselA1(CodeGenContext context, uint encoding) + { + InstDb22w1Ccb20w2Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpMove.Vsel(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Cc, inst.Size); + } + + public static void VselT1(CodeGenContext context, uint encoding) + { + InstDb22w1Ccb20w2Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpMove.Vsel(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Cc, inst.Size); + } + + public static void VshllA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Imm6b16w6Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vshll(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Imm6, inst.U != 0); + } + + public static void VshllA2(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vshll2(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VshllT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Imm6b16w6Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vshll(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Imm6, inst.U != 0); + } + + public static void VshllT2(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vshll2(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VshlIA1(CodeGenContext context, uint encoding) + { + InstDb22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.VshlI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.L, inst.Imm6, inst.Q); + } + + public static void VshlIT1(CodeGenContext context, uint encoding) + { + InstDb22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.VshlI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.L, inst.Imm6, inst.Q); + } + + public static void VshlRA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.VshlR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VshlRT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.VshlR(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size, inst.Q); + } + + public static void VshrA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vshr(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.L, inst.Imm6, inst.Q); + } + + public static void VshrT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vshr(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.L, inst.Imm6, inst.Q); + } + + public static void VshrnA1(CodeGenContext context, uint encoding) + { + InstDb22w1Imm6b16w6Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vshrn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Imm6); + } + + public static void VshrnT1(CodeGenContext context, uint encoding) + { + InstDb22w1Imm6b16w6Vdb12w4Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vshrn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Imm6); + } + + public static void VsliA1(CodeGenContext context, uint encoding) + { + InstDb22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vsli(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.L, inst.Imm6, inst.Q); + } + + public static void VsliT1(CodeGenContext context, uint encoding) + { + InstDb22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vsli(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.L, inst.Imm6, inst.Q); + } + + public static void VsmmlaA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VsmmlaT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VsqrtA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VsqrtF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VsqrtT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Sizeb8w2Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VsqrtF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VsraA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vsra(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.L, inst.Imm6, inst.Q); + } + + public static void VsraT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vsra(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.L, inst.Imm6, inst.Q); + } + + public static void VsriA1(CodeGenContext context, uint encoding) + { + InstDb22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vsri(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.L, inst.Imm6, inst.Q); + } + + public static void VsriT1(CodeGenContext context, uint encoding) + { + InstDb22w1Imm6b16w6Vdb12w4Lb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonShift.Vsri(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.L, inst.Imm6, inst.Q); + } + + public static void Vst11A1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst11(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vst11A2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst11(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vst11A3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst11(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vst11T1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst11(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vst11T2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst11(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vst11T3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst11(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vst1MA1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 1, inst.Align, inst.Size); + } + + public static void Vst1MA2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 2, inst.Align, inst.Size); + } + + public static void Vst1MA3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 3, inst.Align, inst.Size); + } + + public static void Vst1MA4(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 4, inst.Align, inst.Size); + } + + public static void Vst1MT1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 1, inst.Align, inst.Size); + } + + public static void Vst1MT2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 2, inst.Align, inst.Size); + } + + public static void Vst1MT3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 3, inst.Align, inst.Size); + } + + public static void Vst1MT4(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst1M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, 4, inst.Align, inst.Size); + } + + public static void Vst21A1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst21(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vst21A2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst21(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vst21A3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst21(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vst21T1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst21(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vst21T2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst21(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vst21T3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst21(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vst2MA1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst2M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, (encoding >> 8) & 0xf, inst.Align, inst.Size); + } + + public static void Vst2MA2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst2M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.Align, inst.Size); + } + + public static void Vst2MT1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst2M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, (encoding >> 8) & 0xf, inst.Align, inst.Size); + } + + public static void Vst2MT2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst2M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.Align, inst.Size); + } + + public static void Vst31A1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst31(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vst31A2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst31(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vst31A3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst31(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vst31T1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst31(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vst31T2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst31(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vst31T3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst31(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vst3MA1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst3M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, (encoding >> 8) & 0xf, inst.Align, inst.Size); + } + + public static void Vst3MT1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst3M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, (encoding >> 8) & 0xf, inst.Align, inst.Size); + } + + public static void Vst41A1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst41(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vst41A2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst41(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vst41A3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst41(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vst41T1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst41(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 0); + } + + public static void Vst41T2(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst41(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 1); + } + + public static void Vst41T3(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4IndexAlignb4w4Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst41(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, inst.IndexAlign, 2); + } + + public static void Vst4MA1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst4M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, (encoding >> 8) & 0xf, inst.Align, inst.Size); + } + + public static void Vst4MT1(CodeGenContext context, uint encoding) + { + InstDb22w1Rnb16w4Vdb12w4Sizeb6w2Alignb4w2Rmb0w4 inst = new(encoding); + + InstEmitNeonMemory.Vst4M(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Rm, (encoding >> 8) & 0xf, inst.Align, inst.Size); + } + + public static void VstmA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm871b1w7 inst = new(encoding); + + InstEmitNeonMemory.Vstm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Imm871, inst.U != 0, inst.W != 0, singleRegs: false); + } + + public static void VstmA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Pb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm8b0w8 inst = new(encoding); + + InstEmitNeonMemory.Vstm(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), inst.Rn, inst.Imm8, inst.U != 0, inst.W != 0, singleRegs: true); + } + + public static void VstmT1(CodeGenContext context, uint encoding) + { + InstPb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm871b1w7 inst = new(encoding); + + InstEmitNeonMemory.Vstm(context, InstEmitCommon.CombineV(inst.Vd, inst.D), inst.Rn, inst.Imm871, inst.U != 0, inst.W != 0, singleRegs: false); + } + + public static void VstmT2(CodeGenContext context, uint encoding) + { + InstPb24w1Ub23w1Db22w1Wb21w1Rnb16w4Vdb12w4Imm8b0w8 inst = new(encoding); + + InstEmitNeonMemory.Vstm(context, InstEmitCommon.CombineVF(inst.D, inst.Vd), inst.Rn, inst.Imm8, inst.U != 0, inst.W != 0, singleRegs: true); + } + + public static void VstrA1(CodeGenContext context, uint encoding) + { + InstCondb28w4Ub23w1Db22w1Rnb16w4Vdb12w4Sizeb8w2Imm8b0w8 inst = new(encoding); + + InstEmitNeonMemory.Vstr(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), inst.Rn, inst.Imm8, inst.U != 0, inst.Size); + } + + public static void VstrT1(CodeGenContext context, uint encoding) + { + InstUb23w1Db22w1Rnb16w4Vdb12w4Sizeb8w2Imm8b0w8 inst = new(encoding); + + InstEmitNeonMemory.Vstr(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), inst.Rn, inst.Imm8, inst.U != 0, inst.Size); + } + + public static void VsubhnA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vsubhn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VsubhnT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vsubhn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size); + } + + public static void VsublA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vsubl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VsublT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vsubl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VsubwA1(CodeGenContext context, uint encoding) + { + InstUb24w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vsubw(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VsubwT1(CodeGenContext context, uint encoding) + { + InstUb28w1Db22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.Vsubw(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.U != 0, inst.Size); + } + + public static void VsubFA1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VsubF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VsubFA2(CodeGenContext context, uint encoding) + { + InstCondb28w4Db22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VsubF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VsubFT1(CodeGenContext context, uint encoding) + { + InstDb22w1Szb20w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VsubF(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Sz, inst.Q); + } + + public static void VsubFT2(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Sizeb8w2Nb7w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitVfpArithmetic.VsubF(context, InstEmitCommon.CombineV(inst.Vd, inst.D, inst.Size), InstEmitCommon.CombineV(inst.Vn, inst.N, inst.Size), InstEmitCommon.CombineV(inst.Vm, inst.M, inst.Size), inst.Size); + } + + public static void VsubIA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VsubI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VsubIT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonArithmetic.VsubI(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VsudotSA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VsudotST1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VswpA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vswp(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VswpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vswp(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Q); + } + + public static void VtblA1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Lenb8w2Nb7w1Opb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vtbl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Len); + } + + public static void VtblT1(CodeGenContext context, uint encoding) + { + InstDb22w1Vnb16w4Vdb12w4Lenb8w2Nb7w1Opb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vtbl(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Op != 0, inst.Len); + } + + public static void VtrnA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vtrn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VtrnT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vtrn(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VtstA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.Vtst(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VtstT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb20w2Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonCompare.Vtst(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vn, inst.N), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VudotA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VudotT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VudotSA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VudotST1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VummlaA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VummlaT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VusdotA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VusdotT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VusdotSA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VusdotST1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Qb6w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VusmmlaA1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VusmmlaT1(CodeGenContext context, uint encoding) + { + _ = new InstDb22w1Vnb16w4Vdb12w4Nb7w1Mb5w1Vmb0w4(encoding); + + throw new NotImplementedException(); + } + + public static void VuzpA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vuzp(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VuzpT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vuzp(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VzipA1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vzip(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void VzipT1(CodeGenContext context, uint encoding) + { + InstDb22w1Sizeb18w2Vdb12w4Qb6w1Mb5w1Vmb0w4 inst = new(encoding); + + InstEmitNeonMove.Vzip(context, InstEmitCommon.CombineV(inst.Vd, inst.D), InstEmitCommon.CombineV(inst.Vm, inst.M), inst.Size, inst.Q); + } + + public static void WfeA1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Wfe(); + } + + public static void WfeT1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Wfe(); + } + + public static void WfeT2(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Wfe(); + } + + public static void WfiA1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Wfi(); + } + + public static void WfiT1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Wfi(); + } + + public static void WfiT2(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Wfi(); + } + + public static void YieldA1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Yield(); + } + + public static void YieldT1(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Yield(); + } + + public static void YieldT2(CodeGenContext context, uint encoding) + { + context.Arm64Assembler.Yield(); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAbsDiff.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAbsDiff.cs new file mode 100644 index 00000000..f8100503 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAbsDiff.cs @@ -0,0 +1,87 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitAbsDiff + { + public static void Usad8(CodeGenContext context, uint rd, uint rn, uint rm) + { + using ScopedRegister tempD = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempD2 = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + for (int b = 0; b < 4; b++) + { + context.Arm64Assembler.Ubfx(tempN.Operand, rnOperand, b * 8, 8); + context.Arm64Assembler.Ubfx(tempM.Operand, rmOperand, b * 8, 8); + + Operand dest = b == 0 ? tempD.Operand : tempD2.Operand; + + context.Arm64Assembler.Sub(dest, tempN.Operand, tempM.Operand); + + EmitAbs(context, dest); + + if (b > 0) + { + if (b < 3) + { + context.Arm64Assembler.Add(tempD.Operand, tempD.Operand, dest); + } + else + { + context.Arm64Assembler.Add(rdOperand, tempD.Operand, dest); + } + } + } + } + + public static void Usada8(CodeGenContext context, uint rd, uint rn, uint rm, uint ra) + { + using ScopedRegister tempD = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempD2 = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand raOperand = InstEmitCommon.GetInputGpr(context, ra); + + for (int b = 0; b < 4; b++) + { + context.Arm64Assembler.Ubfx(tempN.Operand, rnOperand, b * 8, 8); + context.Arm64Assembler.Ubfx(tempM.Operand, rmOperand, b * 8, 8); + + Operand dest = b == 0 ? tempD.Operand : tempD2.Operand; + + context.Arm64Assembler.Sub(dest, tempN.Operand, tempM.Operand); + + EmitAbs(context, dest); + + if (b > 0) + { + context.Arm64Assembler.Add(tempD.Operand, tempD.Operand, dest); + } + } + + context.Arm64Assembler.Add(rdOperand, tempD.Operand, raOperand); + } + + private static void EmitAbs(CodeGenContext context, Operand value) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + // r = (value + ((int)value >> 31)) ^ ((int)value >> 31). + // Subtracts 1 and then inverts the value if the sign bit is set, same as a conditional negation. + + context.Arm64Assembler.Add(tempRegister.Operand, value, value, ArmShiftType.Asr, 31); + context.Arm64Assembler.Eor(value, tempRegister.Operand, value, ArmShiftType.Asr, 31); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAlu.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAlu.cs new file mode 100644 index 00000000..c0762819 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAlu.cs @@ -0,0 +1,1105 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System; +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitAlu + { + private const uint Imm12Limit = 0x1000; + + public static void AdcI(CodeGenContext context, uint rd, uint rn, uint imm, bool s) + { + EmitI(context, s ? context.Arm64Assembler.Adcs : context.Arm64Assembler.Adc, rd, rn, imm, s); + } + + public static void AdcR(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s) + { + EmitR(context, s ? context.Arm64Assembler.Adcs : context.Arm64Assembler.Adc, rd, rn, rm, sType, imm5, s); + } + + public static void AdcRr(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint rs, bool s) + { + EmitRr(context, s ? context.Arm64Assembler.Adcs : context.Arm64Assembler.Adc, rd, rn, rm, sType, rs, s); + } + + public static void AddI(CodeGenContext context, uint rd, uint rn, uint imm, bool s) + { + EmitArithmeticI(context, s ? context.Arm64Assembler.Adds : context.Arm64Assembler.Add, rd, rn, imm, s); + } + + public static void AddR(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s) + { + EmitArithmeticR(context, s ? context.Arm64Assembler.Adds : context.Arm64Assembler.Add, rd, rn, rm, sType, imm5, s); + } + + public static void AddRr(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint rs, bool s) + { + EmitRr(context, s ? context.Arm64Assembler.Adds : context.Arm64Assembler.Add, rd, rn, rm, sType, rs, s); + } + + public static void Adr(CodeGenContext context, uint rd, uint imm, bool add) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + + uint pc = context.Pc & ~3u; + + if (add) + { + pc += imm; + } + else + { + pc -= imm; + } + + context.Arm64Assembler.Mov(rdOperand, pc); + } + + public static void AndI(CodeGenContext context, uint rd, uint rn, uint imm, bool immRotated, bool s) + { + EmitLogicalI(context, s ? context.Arm64Assembler.Ands : context.Arm64Assembler.And, rd, rn, imm, immRotated, s); + } + + public static void AndR(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s) + { + EmitLogicalR(context, s ? context.Arm64Assembler.Ands : context.Arm64Assembler.And, rd, rn, rm, sType, imm5, s); + } + + public static void AndRr(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint rs, bool s) + { + EmitLogicalRr(context, s ? context.Arm64Assembler.Ands : context.Arm64Assembler.And, rd, rn, rm, sType, rs, s); + } + + public static void BicI(CodeGenContext context, uint rd, uint rn, uint imm, bool immRotated, bool s) + { + if (!s && CodeGenCommon.TryEncodeBitMask(OperandType.I32, ~imm, out _, out _, out _)) + { + AndI(context, rd, rn, ~imm, immRotated, s); + } + else + { + EmitLogicalI(context, s ? context.Arm64Assembler.Bics : context.Arm64Assembler.Bic, rd, rn, imm, immRotated, s, immForm: false); + } + } + + public static void BicR(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s) + { + EmitLogicalR(context, s ? context.Arm64Assembler.Bics : context.Arm64Assembler.Bic, rd, rn, rm, sType, imm5, s); + } + + public static void BicRr(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint rs, bool s) + { + EmitLogicalRr(context, s ? context.Arm64Assembler.Bics : context.Arm64Assembler.Bic, rd, rn, rm, sType, rs, s); + } + + public static void CmnI(CodeGenContext context, uint rn, uint imm) + { + EmitCompareI(context, context.Arm64Assembler.Cmn, rn, imm); + } + + public static void CmnR(CodeGenContext context, uint rn, uint rm, uint sType, uint imm5) + { + EmitCompareR(context, context.Arm64Assembler.Cmn, rn, rm, sType, imm5); + } + + public static void CmnRr(CodeGenContext context, uint rn, uint rm, uint sType, uint rs) + { + EmitCompareRr(context, context.Arm64Assembler.Cmn, rn, rm, sType, rs); + } + + public static void CmpI(CodeGenContext context, uint rn, uint imm) + { + EmitCompareI(context, context.Arm64Assembler.Cmp, rn, imm); + } + + public static void CmpR(CodeGenContext context, uint rn, uint rm, uint sType, uint imm5) + { + EmitCompareR(context, context.Arm64Assembler.Cmp, rn, rm, sType, imm5); + } + + public static void CmpRr(CodeGenContext context, uint rn, uint rm, uint sType, uint rs) + { + EmitCompareRr(context, context.Arm64Assembler.Cmp, rn, rm, sType, rs); + } + + public static void EorI(CodeGenContext context, uint rd, uint rn, uint imm, bool immRotated, bool s) + { + EmitLogicalI(context, s ? context.Arm64Assembler.Eors : context.Arm64Assembler.Eor, rd, rn, imm, immRotated, s); + } + + public static void EorR(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s) + { + EmitLogicalR(context, s ? context.Arm64Assembler.Eors : context.Arm64Assembler.Eor, rd, rn, rm, sType, imm5, s); + } + + public static void EorRr(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint rs, bool s) + { + EmitLogicalRr(context, s ? context.Arm64Assembler.Eors : context.Arm64Assembler.Eor, rd, rn, rm, sType, rs, s); + } + + public static void OrnI(CodeGenContext context, uint rd, uint rn, uint imm, bool immRotated, bool s) + { + if (!s && CodeGenCommon.TryEncodeBitMask(OperandType.I32, ~imm, out _, out _, out _)) + { + OrrI(context, rd, rn, ~imm, immRotated, s); + } + else + { + EmitLogicalI(context, s ? context.Arm64Assembler.Orns : context.Arm64Assembler.Orn, rd, rn, imm, immRotated, s, immForm: false); + } + } + + public static void OrnR(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s) + { + EmitLogicalR(context, s ? context.Arm64Assembler.Orns : context.Arm64Assembler.Orn, rd, rn, rm, sType, imm5, s); + } + + public static void OrrI(CodeGenContext context, uint rd, uint rn, uint imm, bool immRotated, bool s) + { + EmitLogicalI(context, s ? context.Arm64Assembler.Orrs : context.Arm64Assembler.Orr, rd, rn, imm, immRotated, s); + } + + public static void OrrR(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s) + { + EmitLogicalR(context, s ? context.Arm64Assembler.Orrs : context.Arm64Assembler.Orr, rd, rn, rm, sType, imm5, s); + } + + public static void OrrRr(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint rs, bool s) + { + EmitLogicalRr(context, s ? context.Arm64Assembler.Orrs : context.Arm64Assembler.Orr, rd, rn, rm, sType, rs, s); + } + + public static void RsbI(CodeGenContext context, uint rd, uint rn, uint imm, bool s) + { + if (imm == 0) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + if (s) + { + context.Arm64Assembler.Negs(rdOperand, rnOperand); + context.SetNzcvModified(); + } + else + { + context.Arm64Assembler.Neg(rdOperand, rnOperand); + } + } + else + { + EmitI(context, s ? context.Arm64Assembler.Subs : context.Arm64Assembler.Sub, rd, rn, imm, s, reverse: true); + } + } + + public static void RsbR(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s) + { + EmitR(context, s ? context.Arm64Assembler.Subs : context.Arm64Assembler.Sub, rd, rn, rm, sType, imm5, s, reverse: true); + } + + public static void RsbRr(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint rs, bool s) + { + EmitRr(context, s ? context.Arm64Assembler.Subs : context.Arm64Assembler.Sub, rd, rn, rm, sType, rs, s, reverse: true); + } + + public static void RscI(CodeGenContext context, uint rd, uint rn, uint imm, bool s) + { + EmitI(context, s ? context.Arm64Assembler.Sbcs : context.Arm64Assembler.Sbc, rd, rn, imm, s, reverse: true); + } + + public static void RscR(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s) + { + EmitR(context, s ? context.Arm64Assembler.Sbcs : context.Arm64Assembler.Sbc, rd, rn, rm, sType, imm5, s, reverse: true); + } + + public static void RscRr(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint rs, bool s) + { + EmitRr(context, s ? context.Arm64Assembler.Sbcs : context.Arm64Assembler.Sbc, rd, rn, rm, sType, rs, s, reverse: true); + } + + public static void SbcI(CodeGenContext context, uint rd, uint rn, uint imm, bool s) + { + EmitI(context, s ? context.Arm64Assembler.Sbcs : context.Arm64Assembler.Sbc, rd, rn, imm, s); + } + + public static void SbcR(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s) + { + EmitR(context, s ? context.Arm64Assembler.Sbcs : context.Arm64Assembler.Sbc, rd, rn, rm, sType, imm5, s); + } + + public static void SbcRr(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint rs, bool s) + { + EmitRr(context, s ? context.Arm64Assembler.Sbcs : context.Arm64Assembler.Sbc, rd, rn, rm, sType, rs, s); + } + + public static void SubI(CodeGenContext context, uint rd, uint rn, uint imm, bool s) + { + EmitArithmeticI(context, s ? context.Arm64Assembler.Subs : context.Arm64Assembler.Sub, rd, rn, imm, s); + } + + public static void SubR(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s) + { + EmitArithmeticR(context, s ? context.Arm64Assembler.Subs : context.Arm64Assembler.Sub, rd, rn, rm, sType, imm5, s); + } + + public static void SubRr(CodeGenContext context, uint rd, uint rn, uint rm, uint sType, uint rs, bool s) + { + EmitRr(context, s ? context.Arm64Assembler.Subs : context.Arm64Assembler.Sub, rd, rn, rm, sType, rs, s); + } + + public static void TeqI(CodeGenContext context, uint rn, uint imm, bool immRotated) + { + EmitLogicalI(context, (rnOperand, rmOperand) => EmitTeq(context, rnOperand, rmOperand), rn, imm, immRotated); + } + + public static void TeqR(CodeGenContext context, uint rn, uint rm, uint sType, uint imm5) + { + EmitLogicalR(context, (rnOperand, rmOperand) => EmitTeq(context, rnOperand, rmOperand), rn, rm, sType, imm5); + } + + public static void TeqRr(CodeGenContext context, uint rn, uint rm, uint sType, uint rs) + { + EmitLogicalRr(context, (rnOperand, rmOperand) => EmitTeq(context, rnOperand, rmOperand), rn, rm, sType, rs); + } + + public static void TstI(CodeGenContext context, uint rn, uint imm, bool immRotated) + { + EmitLogicalI(context, context.Arm64Assembler.Tst, rn, imm, immRotated); + } + + public static void TstR(CodeGenContext context, uint rn, uint rm, uint sType, uint imm5) + { + EmitLogicalR(context, context.Arm64Assembler.Tst, rn, rm, sType, imm5); + } + + public static void TstRr(CodeGenContext context, uint rn, uint rm, uint sType, uint rs) + { + EmitLogicalRr(context, context.Arm64Assembler.Tst, rn, rm, sType, rs); + } + + private static void EmitArithmeticI(CodeGenContext context, Action<Operand, Operand, Operand> action, uint rd, uint rn, uint imm, bool s) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + if (imm < Imm12Limit) + { + Operand rmOperand = new(OperandKind.Constant, OperandType.I32, imm); + + action(rdOperand, rnOperand, rmOperand); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Mov(tempRegister.Operand, imm); + + action(rdOperand, rnOperand, tempRegister.Operand); + } + + if (s) + { + context.SetNzcvModified(); + } + } + + private static void EmitArithmeticR( + CodeGenContext context, + Action<Operand, Operand, Operand, ArmShiftType, int> action, + uint rd, + uint rn, + uint rm, + uint sType, + uint imm5, + bool s) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + if (CanShiftArithmetic(sType, imm5)) + { + action(rdOperand, rnOperand, rmOperand, (ArmShiftType)sType, (int)imm5); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + rmOperand = GetMShiftedByImmediate(context, tempRegister.Operand, rmOperand, imm5, sType); + + action(rdOperand, rnOperand, rmOperand, ArmShiftType.Lsl, 0); + } + + if (s) + { + context.SetNzcvModified(); + } + } + + private static void EmitCompareI(CodeGenContext context, Action<Operand, Operand> action, uint rn, uint imm) + { + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + if (imm < Imm12Limit) + { + Operand rmOperand = new(OperandKind.Constant, OperandType.I32, imm); + + action(rnOperand, rmOperand); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Mov(tempRegister.Operand, imm); + + action(rnOperand, tempRegister.Operand); + } + + context.SetNzcvModified(); + } + + private static void EmitCompareR( + CodeGenContext context, + Action<Operand, Operand, ArmShiftType, int> action, + uint rn, + uint rm, + uint sType, + uint imm5) + { + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + if (CanShiftArithmetic(sType, imm5)) + { + action(rnOperand, rmOperand, (ArmShiftType)sType, (int)imm5); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + rmOperand = GetMShiftedByImmediate(context, tempRegister.Operand, rmOperand, imm5, sType); + + action(rnOperand, rmOperand, ArmShiftType.Lsl, 0); + } + + context.SetNzcvModified(); + } + + private static void EmitCompareRr(CodeGenContext context, Action<Operand, Operand> action, uint rn, uint rm, uint sType, uint rs) + { + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand rsOperand = InstEmitCommon.GetInputGpr(context, rs); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + rmOperand = GetMShiftedByReg(context, tempRegister.Operand, rmOperand, rsOperand, sType); + + action(rnOperand, rmOperand); + + context.SetNzcvModified(); + } + + private static void EmitI(CodeGenContext context, Action<Operand, Operand, Operand> action, uint rd, uint rn, uint imm, bool s, bool reverse = false) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Mov(tempRegister.Operand, imm); + + if (reverse) + { + action(rdOperand, tempRegister.Operand, rnOperand); + } + else + { + action(rdOperand, rnOperand, tempRegister.Operand); + } + + if (s) + { + context.SetNzcvModified(); + } + } + + private static void EmitR(CodeGenContext context, Action<Operand, Operand, Operand> action, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s, bool reverse = false) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + rmOperand = GetMShiftedByImmediate(context, tempRegister.Operand, rmOperand, imm5, sType); + + if (reverse) + { + action(rdOperand, rmOperand, rnOperand); + } + else + { + action(rdOperand, rnOperand, rmOperand); + } + + if (s) + { + context.SetNzcvModified(); + } + } + + private static void EmitRr(CodeGenContext context, Action<Operand, Operand, Operand> action, uint rd, uint rn, uint rm, uint sType, uint rs, bool s, bool reverse = false) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand rsOperand = InstEmitCommon.GetInputGpr(context, rs); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + rmOperand = GetMShiftedByReg(context, tempRegister.Operand, rmOperand, rsOperand, sType); + + if (reverse) + { + action(rdOperand, rmOperand, rnOperand); + } + else + { + action(rdOperand, rnOperand, rmOperand); + } + + if (s) + { + context.SetNzcvModified(); + } + } + + private static void EmitLogicalI(CodeGenContext context, Action<Operand, Operand> action, uint rn, uint imm, bool immRotated) + { + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + if (immRotated) + { + if ((imm & (1u << 31)) != 0) + { + context.Arm64Assembler.Orr(flagsRegister.Operand, flagsRegister.Operand, InstEmitCommon.Const(2)); + } + else + { + context.Arm64Assembler.Bfc(flagsRegister.Operand, 1, 1); + } + } + + if (CodeGenCommon.TryEncodeBitMask(OperandType.I32, imm, out _, out _, out _)) + { + action(rnOperand, InstEmitCommon.Const((int)imm)); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Mov(tempRegister.Operand, imm); + + action(rnOperand, tempRegister.Operand); + } + + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + context.SetNzcvModified(); + } + + private static void EmitLogicalI( + CodeGenContext context, + Action<Operand, Operand, Operand> action, + uint rd, + uint rn, + uint imm, + bool immRotated, + bool s, + bool immForm = true) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + ScopedRegister flagsRegister = default; + + if (s) + { + flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + if (immRotated) + { + if ((imm & (1u << 31)) != 0) + { + context.Arm64Assembler.Orr(flagsRegister.Operand, flagsRegister.Operand, InstEmitCommon.Const(2)); + } + else + { + context.Arm64Assembler.Bfc(flagsRegister.Operand, 1, 1); + } + } + } + + if (imm == 0 || (immForm && CodeGenCommon.TryEncodeBitMask(OperandType.I32, imm, out _, out _, out _))) + { + action(rdOperand, rnOperand, InstEmitCommon.Const((int)imm)); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Mov(tempRegister.Operand, imm); + + action(rdOperand, rnOperand, tempRegister.Operand); + } + + if (s) + { + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + flagsRegister.Dispose(); + + context.SetNzcvModified(); + } + } + + private static void EmitLogicalR(CodeGenContext context, Action<Operand, Operand> action, uint rn, uint rm, uint sType, uint imm5) + { + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + rmOperand = GetMShiftedByImmediate(context, tempRegister.Operand, rmOperand, imm5, sType, flagsRegister.Operand); + + action(rnOperand, rmOperand); + + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + context.SetNzcvModified(); + } + + private static void EmitLogicalR(CodeGenContext context, Action<Operand, Operand, Operand, ArmShiftType, int> action, uint rd, uint rn, uint rm, uint sType, uint imm5, bool s) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + if (CanShift(sType, imm5) && !s) + { + action(rdOperand, rnOperand, rmOperand, (ArmShiftType)sType, (int)imm5); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + ScopedRegister flagsRegister = default; + + if (s) + { + flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + rmOperand = GetMShiftedByImmediate(context, tempRegister.Operand, rmOperand, imm5, sType, flagsRegister.Operand); + } + else + { + rmOperand = GetMShiftedByImmediate(context, tempRegister.Operand, rmOperand, imm5, sType, null); + } + + action(rdOperand, rnOperand, rmOperand, ArmShiftType.Lsl, 0); + + if (s) + { + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + flagsRegister.Dispose(); + + context.SetNzcvModified(); + } + } + } + + private static void EmitLogicalRr(CodeGenContext context, Action<Operand, Operand> action, uint rn, uint rm, uint sType, uint rs) + { + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand rsOperand = InstEmitCommon.GetInputGpr(context, rs); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + rmOperand = GetMShiftedByReg(context, tempRegister.Operand, rmOperand, rsOperand, sType, flagsRegister.Operand); + + action(rnOperand, rmOperand); + + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + context.SetNzcvModified(); + } + + private static void EmitLogicalRr(CodeGenContext context, Action<Operand, Operand, Operand> action, uint rd, uint rn, uint rm, uint sType, uint rs, bool s) + { + if (s) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand rsOperand = InstEmitCommon.GetInputGpr(context, rs); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + rmOperand = GetMShiftedByReg(context, tempRegister.Operand, rmOperand, rsOperand, sType, flagsRegister.Operand); + + action(rdOperand, rnOperand, rmOperand); + + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + context.SetNzcvModified(); + } + else + { + EmitRr(context, action, rd, rn, rm, sType, rs, s); + } + } + + public static bool CanShiftArithmetic(uint sType, uint imm5) + { + // We can't encode ROR or RRX. + + return sType != 3 && (sType == 0 || imm5 != 0); + } + + public static bool CanShift(uint sType, uint imm5) + { + // We can encode all shift types directly, except RRX. + + return imm5 != 0 || sType == 0; + } + + public static Operand GetMShiftedByImmediate(CodeGenContext context, Operand dest, Operand m, uint imm, uint sType, Operand? carryOut = null) + { + int shift = (int)imm; + + if (shift == 0) + { + switch ((ArmShiftType)sType) + { + case ArmShiftType.Lsr: + shift = 32; + break; + case ArmShiftType.Asr: + shift = 32; + break; + case ArmShiftType.Ror: + shift = 1; + break; + } + } + + if (shift != 0) + { + switch ((ArmShiftType)sType) + { + case ArmShiftType.Lsl: + m = GetLslC(context, dest, m, carryOut, shift); + break; + case ArmShiftType.Lsr: + m = GetLsrC(context, dest, m, carryOut, shift); + break; + case ArmShiftType.Asr: + m = GetAsrC(context, dest, m, carryOut, shift); + break; + case ArmShiftType.Ror: + if (imm != 0) + { + m = GetRorC(context, dest, m, carryOut, shift); + } + else + { + m = GetRrxC(context, dest, m, carryOut); + } + break; + } + } + + return m; + } + + public static Operand GetMShiftedByReg(CodeGenContext context, Operand dest, Operand m, Operand s, uint sType, Operand? carryOut = null) + { + Operand shiftResult = m; + + switch ((ArmShiftType)sType) + { + case ArmShiftType.Lsl: + shiftResult = EmitLslC(context, dest, m, carryOut, s); + break; + case ArmShiftType.Lsr: + shiftResult = EmitLsrC(context, dest, m, carryOut, s); + break; + case ArmShiftType.Asr: + shiftResult = EmitAsrC(context, dest, m, carryOut, s); + break; + case ArmShiftType.Ror: + shiftResult = EmitRorC(context, dest, m, carryOut, s); + break; + } + + return shiftResult; + } + + private static void EmitIfHelper(CodeGenContext context, Operand boolValue, Action action, bool expected = true) + { + Debug.Assert(boolValue.Type == OperandType.I32); + + int branchInstructionPointer = context.CodeWriter.InstructionPointer; + + if (expected) + { + context.Arm64Assembler.Cbnz(boolValue, 0); + } + else + { + context.Arm64Assembler.Cbz(boolValue, 0); + } + + action(); + + int offset = context.CodeWriter.InstructionPointer - branchInstructionPointer; + Debug.Assert(offset >= 0); + Debug.Assert((offset << 13) >> 13 == offset); + uint branchInst = context.CodeWriter.ReadInstructionAt(branchInstructionPointer); + context.CodeWriter.WriteInstructionAt(branchInstructionPointer, branchInst | (uint)(offset << 5)); + } + + private static Operand EmitLslC(CodeGenContext context, Operand dest, Operand m, Operand? carryOut, Operand shift) + { + Debug.Assert(m.Type == OperandType.I32 && shift.Type == OperandType.I32); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand mask = tempRegister.Operand; + context.Arm64Assembler.Uxtb(mask, shift); + context.Arm64Assembler.Sub(mask, mask, InstEmitCommon.Const(32)); + context.Arm64Assembler.Asr(mask, mask, InstEmitCommon.Const(31)); + + Operand dest64 = new(OperandKind.Register, OperandType.I64, dest.Value); + + if (carryOut.HasValue) + { + context.Arm64Assembler.Lslv(dest64, m, shift); + } + else + { + context.Arm64Assembler.Lslv(dest, m, shift); + } + + // If shift >= 32, force the result to 0. + context.Arm64Assembler.And(dest, dest, mask); + + if (carryOut.HasValue) + { + EmitIfHelper(context, shift, () => + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Uxtb(mask, shift); + context.Arm64Assembler.Sub(mask, mask, InstEmitCommon.Const(33)); + context.Arm64Assembler.Lsr(mask, mask, InstEmitCommon.Const(31)); + context.Arm64Assembler.Lsr(tempRegister.Operand, dest64, InstEmitCommon.Const(32)); + context.Arm64Assembler.And(tempRegister.Operand, tempRegister.Operand, mask); + + UpdateCarryFlag(context, tempRegister.Operand, carryOut.Value); + }, false); + } + + return dest; + } + + private static Operand GetLslC(CodeGenContext context, Operand dest, Operand m, Operand? carryOut, int shift) + { + Debug.Assert(m.Type == OperandType.I32); + + if ((uint)shift > 32) + { + return GetShiftByMoreThan32(context, carryOut); + } + else if (shift == 32) + { + if (carryOut.HasValue) + { + SetCarryMLsb(context, m, carryOut.Value); + } + + return InstEmitCommon.Const(0); + } + else + { + if (carryOut.HasValue) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Lsr(tempRegister.Operand, m, InstEmitCommon.Const(32 - shift)); + + UpdateCarryFlag(context, tempRegister.Operand, carryOut.Value); + } + + context.Arm64Assembler.Lsl(dest, m, InstEmitCommon.Const(shift)); + + return dest; + } + } + + private static Operand EmitLsrC(CodeGenContext context, Operand dest, Operand m, Operand? carryOut, Operand shift) + { + Debug.Assert(m.Type == OperandType.I32 && shift.Type == OperandType.I32); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand mask = tempRegister.Operand; + context.Arm64Assembler.Uxtb(mask, shift); + context.Arm64Assembler.Sub(mask, mask, InstEmitCommon.Const(32)); + context.Arm64Assembler.Asr(mask, mask, InstEmitCommon.Const(31)); + + context.Arm64Assembler.Lsrv(dest, m, shift); + + // If shift >= 32, force the result to 0. + context.Arm64Assembler.And(dest, dest, mask); + + if (carryOut.HasValue) + { + EmitIfHelper(context, shift, () => + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Uxtb(mask, shift); + context.Arm64Assembler.Sub(mask, mask, InstEmitCommon.Const(33)); + context.Arm64Assembler.Lsr(mask, mask, InstEmitCommon.Const(31)); + context.Arm64Assembler.Sub(tempRegister.Operand, shift, InstEmitCommon.Const(1)); + context.Arm64Assembler.Lsrv(tempRegister.Operand, m, tempRegister.Operand); + context.Arm64Assembler.And(tempRegister.Operand, tempRegister.Operand, mask); + + UpdateCarryFlag(context, tempRegister.Operand, carryOut.Value); + }, false); + } + + return dest; + } + + public static Operand GetLsrC(CodeGenContext context, Operand dest, Operand m, Operand? carryOut, int shift) + { + Debug.Assert(m.Type == OperandType.I32); + + if ((uint)shift > 32) + { + return GetShiftByMoreThan32(context, carryOut); + } + else if (shift == 32) + { + if (carryOut.HasValue) + { + SetCarryMMsb(context, m, carryOut.Value); + } + + return InstEmitCommon.Const(0); + } + else + { + if (carryOut.HasValue) + { + SetCarryMShrOut(context, m, shift, carryOut.Value); + } + + context.Arm64Assembler.Lsr(dest, m, InstEmitCommon.Const(shift)); + + return dest; + } + } + + private static Operand GetShiftByMoreThan32(CodeGenContext context, Operand? carryOut) + { + if (carryOut.HasValue) + { + // Clear carry flag. + + context.Arm64Assembler.Bfc(carryOut.Value, 1, 1); + } + + return InstEmitCommon.Const(0); + } + + private static Operand EmitAsrC(CodeGenContext context, Operand dest, Operand m, Operand? carryOut, Operand shift) + { + Debug.Assert(m.Type == OperandType.I32 && shift.Type == OperandType.I32); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand mask = tempRegister.Operand; + context.Arm64Assembler.Uxtb(mask, shift); + context.Arm64Assembler.Sub(mask, mask, InstEmitCommon.Const(31)); + context.Arm64Assembler.Orn(mask, shift, mask, ArmShiftType.Asr, 31); + + context.Arm64Assembler.Asrv(dest, m, mask); + + if (carryOut.HasValue) + { + EmitIfHelper(context, shift, () => + { + // If shift >= 32, carry should be equal to the MSB of Rm. + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Sub(tempRegister.Operand, mask, InstEmitCommon.Const(1)); + context.Arm64Assembler.Orr(tempRegister.Operand, tempRegister.Operand, mask, ArmShiftType.Asr, 31); + context.Arm64Assembler.Lsrv(tempRegister.Operand, m, tempRegister.Operand); + + UpdateCarryFlag(context, tempRegister.Operand, carryOut.Value); + }, false); + } + + return dest; + } + + private static Operand GetAsrC(CodeGenContext context, Operand dest, Operand m, Operand? carryOut, int shift) + { + Debug.Assert(m.Type == OperandType.I32); + + if ((uint)shift >= 32) + { + context.Arm64Assembler.Asr(dest, m, InstEmitCommon.Const(31)); + + if (carryOut.HasValue) + { + SetCarryMLsb(context, dest, carryOut.Value); + } + + return dest; + } + else + { + if (carryOut.HasValue) + { + SetCarryMShrOut(context, m, shift, carryOut.Value); + } + + context.Arm64Assembler.Asr(dest, m, InstEmitCommon.Const(shift)); + + return dest; + } + } + + private static Operand EmitRorC(CodeGenContext context, Operand dest, Operand m, Operand? carryOut, Operand shift) + { + Debug.Assert(m.Type == OperandType.I32 && shift.Type == OperandType.I32); + + context.Arm64Assembler.Rorv(dest, m, shift); + + if (carryOut.HasValue) + { + EmitIfHelper(context, shift, () => + { + SetCarryMMsb(context, m, carryOut.Value); + }, false); + } + + return dest; + } + + private static Operand GetRorC(CodeGenContext context, Operand dest, Operand m, Operand? carryOut, int shift) + { + Debug.Assert(m.Type == OperandType.I32); + + shift &= 0x1f; + + context.Arm64Assembler.Ror(dest, m, InstEmitCommon.Const(shift)); + + if (carryOut.HasValue) + { + SetCarryMMsb(context, dest, carryOut.Value); + } + + return dest; + } + + private static Operand GetRrxC(CodeGenContext context, Operand dest, Operand m, Operand? carryOut) + { + Debug.Assert(m.Type == OperandType.I32); + + // Rotate right by 1 with carry. + + if (carryOut.HasValue) + { + SetCarryMLsb(context, m, carryOut.Value); + } + + context.Arm64Assembler.Mov(dest, m); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.MrsNzcv(tempRegister.Operand); + context.Arm64Assembler.Bfxil(dest, tempRegister.Operand, 29, 1); + context.Arm64Assembler.Ror(dest, dest, InstEmitCommon.Const(1)); + + return dest; + } + + private static void SetCarryMLsb(CodeGenContext context, Operand m, Operand carryOut) + { + Debug.Assert(m.Type == OperandType.I32); + + UpdateCarryFlag(context, m, carryOut); + } + + private static void SetCarryMMsb(CodeGenContext context, Operand m, Operand carryOut) + { + Debug.Assert(m.Type == OperandType.I32); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Lsr(tempRegister.Operand, m, InstEmitCommon.Const(31)); + + UpdateCarryFlag(context, tempRegister.Operand, carryOut); + } + + private static void SetCarryMShrOut(CodeGenContext context, Operand m, int shift, Operand carryOut) + { + Debug.Assert(m.Type == OperandType.I32); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Lsr(tempRegister.Operand, m, InstEmitCommon.Const(shift - 1)); + + UpdateCarryFlag(context, tempRegister.Operand, carryOut); + } + + private static void UpdateCarryFlag(CodeGenContext context, Operand value, Operand carryOut) + { + context.Arm64Assembler.Bfi(carryOut, value, 1, 1); + } + + private static void EmitTeq(CodeGenContext context, Operand rnOperand, Operand rmOperand) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Eors(tempRegister.Operand, rnOperand, rmOperand); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitBit.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitBit.cs new file mode 100644 index 00000000..3f91d45f --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitBit.cs @@ -0,0 +1,103 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitBit + { + public static void Bfc(CodeGenContext context, uint rd, uint lsb, uint msb) + { + // This is documented as "unpredictable". + if (msb < lsb) + { + return; + } + + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + + context.Arm64Assembler.Bfc(rdOperand, (int)lsb, (int)(msb - lsb + 1)); + } + + public static void Bfi(CodeGenContext context, uint rd, uint rn, uint lsb, uint msb) + { + // This is documented as "unpredictable". + if (msb < lsb) + { + return; + } + + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + context.Arm64Assembler.Bfi(rdOperand, rnOperand, (int)lsb, (int)(msb - lsb + 1)); + } + + public static void Clz(CodeGenContext context, uint rd, uint rm) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + context.Arm64Assembler.Clz(rdOperand, rmOperand); + } + + public static void Rbit(CodeGenContext context, uint rd, uint rm) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + context.Arm64Assembler.Rbit(rdOperand, rmOperand); + } + + public static void Rev(CodeGenContext context, uint rd, uint rm) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + context.Arm64Assembler.Rev(rdOperand, rmOperand); + } + + public static void Rev16(CodeGenContext context, uint rd, uint rm) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + context.Arm64Assembler.Rev16(rdOperand, rmOperand); + } + + public static void Revsh(CodeGenContext context, uint rd, uint rm) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + context.Arm64Assembler.Rev16(rdOperand, rmOperand); + context.Arm64Assembler.Sxth(rdOperand, rdOperand); + } + + public static void Sbfx(CodeGenContext context, uint rd, uint rn, uint lsb, uint widthMinus1) + { + // This is documented as "unpredictable". + if (lsb + widthMinus1 > 31) + { + return; + } + + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + context.Arm64Assembler.Sbfx(rdOperand, rnOperand, (int)lsb, (int)widthMinus1 + 1); + } + + public static void Ubfx(CodeGenContext context, uint rd, uint rn, uint lsb, uint widthMinus1) + { + // This is documented as "unpredictable". + if (lsb + widthMinus1 > 31) + { + return; + } + + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + context.Arm64Assembler.Ubfx(rdOperand, rnOperand, (int)lsb, (int)widthMinus1 + 1); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitCommon.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitCommon.cs new file mode 100644 index 00000000..1ec4c807 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitCommon.cs @@ -0,0 +1,263 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitCommon + { + public static Operand Const(int value) + { + return new(OperandKind.Constant, OperandType.I32, (uint)value); + } + + public static Operand GetInputGpr(CodeGenContext context, uint register) + { + Operand operand = context.RegisterAllocator.RemapGprRegister((int)register); + + if (register == RegisterUtils.PcRegister) + { + context.Arm64Assembler.Mov(operand, context.Pc); + } + + return operand; + } + + public static Operand GetOutputGpr(CodeGenContext context, uint register) + { + return context.RegisterAllocator.RemapGprRegister((int)register); + } + + public static void GetCurrentFlags(CodeGenContext context, Operand flagsOut) + { + context.Arm64Assembler.MrsNzcv(flagsOut); + context.Arm64Assembler.Lsr(flagsOut, flagsOut, Const(28)); + } + + public static void RestoreNzcvFlags(CodeGenContext context, Operand nzcvFlags) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Lsl(tempRegister.Operand, nzcvFlags, Const(28)); + context.Arm64Assembler.MsrNzcv(tempRegister.Operand); + } + + public static void RestoreCvFlags(CodeGenContext context, Operand cvFlags) + { + // Arm64 zeros the carry and overflow flags for logical operations, but Arm32 keeps them unchanged. + // This will restore carry and overflow after a operation has zeroed them. + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.MrsNzcv(tempRegister.Operand); + context.Arm64Assembler.Bfi(tempRegister.Operand, cvFlags, 28, 2); + context.Arm64Assembler.MsrNzcv(tempRegister.Operand); + } + + public static void SetThumbFlag(CodeGenContext context) + { + Operand ctx = InstEmitSystem.Register(context.RegisterAllocator.FixedContextRegister); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.LdrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + context.Arm64Assembler.Orr(tempRegister.Operand, tempRegister.Operand, Const(1 << 5)); + context.Arm64Assembler.StrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + } + + public static void SetThumbFlag(CodeGenContext context, Operand value) + { + Operand ctx = InstEmitSystem.Register(context.RegisterAllocator.FixedContextRegister); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.LdrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + context.Arm64Assembler.Bfi(tempRegister.Operand, value, 5, 1); + context.Arm64Assembler.StrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + } + + public static void ClearThumbFlag(CodeGenContext context) + { + Operand ctx = InstEmitSystem.Register(context.RegisterAllocator.FixedContextRegister); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.LdrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + context.Arm64Assembler.Bfc(tempRegister.Operand, 5, 1); + context.Arm64Assembler.StrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + } + + public static void EmitSigned16BitPair(CodeGenContext context, uint rd, uint rn, Action<Operand, Operand> elementAction) + { + using ScopedRegister tempD = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempD2 = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand rdOperand = GetOutputGpr(context, rd); + Operand rnOperand = GetInputGpr(context, rn); + + context.Arm64Assembler.Sxth(tempN.Operand, rnOperand); + elementAction(tempD.Operand, tempN.Operand); + context.Arm64Assembler.Uxth(tempD2.Operand, tempD.Operand); + + context.Arm64Assembler.Asr(tempN.Operand, rnOperand, Const(16)); + elementAction(tempD.Operand, tempN.Operand); + context.Arm64Assembler.Orr(rdOperand, tempD2.Operand, tempD.Operand, ArmShiftType.Lsl, 16); + } + + public static void EmitSigned16BitPair(CodeGenContext context, uint rd, uint rn, uint rm, Action<Operand, Operand, Operand> elementAction) + { + using ScopedRegister tempD = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempD2 = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand rdOperand = GetOutputGpr(context, rd); + Operand rnOperand = GetInputGpr(context, rn); + Operand rmOperand = GetInputGpr(context, rm); + + context.Arm64Assembler.Sxth(tempN.Operand, rnOperand); + context.Arm64Assembler.Sxth(tempM.Operand, rmOperand); + elementAction(tempD.Operand, tempN.Operand, tempM.Operand); + context.Arm64Assembler.Uxth(tempD2.Operand, tempD.Operand); + + context.Arm64Assembler.Asr(tempN.Operand, rnOperand, Const(16)); + context.Arm64Assembler.Asr(tempM.Operand, rmOperand, Const(16)); + elementAction(tempD.Operand, tempN.Operand, tempM.Operand); + context.Arm64Assembler.Orr(rdOperand, tempD2.Operand, tempD.Operand, ArmShiftType.Lsl, 16); + } + + public static void EmitSigned16BitXPair(CodeGenContext context, uint rd, uint rn, uint rm, Action<Operand, Operand, Operand, int> elementAction) + { + using ScopedRegister tempD = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempD2 = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand rdOperand = GetOutputGpr(context, rd); + Operand rnOperand = GetInputGpr(context, rn); + Operand rmOperand = GetInputGpr(context, rm); + + context.Arm64Assembler.Sxth(tempN.Operand, rnOperand); + context.Arm64Assembler.Asr(tempM.Operand, rmOperand, Const(16)); + elementAction(tempD.Operand, tempN.Operand, tempM.Operand, 0); + context.Arm64Assembler.Uxth(tempD2.Operand, tempD.Operand); + + context.Arm64Assembler.Asr(tempN.Operand, rnOperand, Const(16)); + context.Arm64Assembler.Sxth(tempM.Operand, rmOperand); + elementAction(tempD.Operand, tempN.Operand, tempM.Operand, 1); + context.Arm64Assembler.Orr(rdOperand, tempD2.Operand, tempD.Operand, ArmShiftType.Lsl, 16); + } + + public static void EmitSigned8BitPair(CodeGenContext context, uint rd, uint rn, uint rm, Action<Operand, Operand, Operand> elementAction) + { + Emit8BitPair(context, rd, rn, rm, elementAction, unsigned: false); + } + + public static void EmitUnsigned16BitPair(CodeGenContext context, uint rd, uint rn, uint rm, Action<Operand, Operand, Operand> elementAction) + { + using ScopedRegister tempD = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempD2 = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand rdOperand = GetOutputGpr(context, rd); + Operand rnOperand = GetInputGpr(context, rn); + Operand rmOperand = GetInputGpr(context, rm); + + context.Arm64Assembler.Uxth(tempN.Operand, rnOperand); + context.Arm64Assembler.Uxth(tempM.Operand, rmOperand); + elementAction(tempD.Operand, tempN.Operand, tempM.Operand); + context.Arm64Assembler.Uxth(tempD2.Operand, tempD.Operand); + + context.Arm64Assembler.Lsr(tempN.Operand, rnOperand, Const(16)); + context.Arm64Assembler.Lsr(tempM.Operand, rmOperand, Const(16)); + elementAction(tempD.Operand, tempN.Operand, tempM.Operand); + context.Arm64Assembler.Orr(rdOperand, tempD2.Operand, tempD.Operand, ArmShiftType.Lsl, 16); + } + + public static void EmitUnsigned16BitXPair(CodeGenContext context, uint rd, uint rn, uint rm, Action<Operand, Operand, Operand, int> elementAction) + { + using ScopedRegister tempD = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempD2 = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand rdOperand = GetOutputGpr(context, rd); + Operand rnOperand = GetInputGpr(context, rn); + Operand rmOperand = GetInputGpr(context, rm); + + context.Arm64Assembler.Uxth(tempN.Operand, rnOperand); + context.Arm64Assembler.Lsr(tempM.Operand, rmOperand, Const(16)); + elementAction(tempD.Operand, tempN.Operand, tempM.Operand, 0); + context.Arm64Assembler.Uxth(tempD2.Operand, tempD.Operand); + + context.Arm64Assembler.Lsr(tempN.Operand, rnOperand, Const(16)); + context.Arm64Assembler.Uxth(tempM.Operand, rmOperand); + elementAction(tempD.Operand, tempN.Operand, tempM.Operand, 1); + context.Arm64Assembler.Orr(rdOperand, tempD2.Operand, tempD.Operand, ArmShiftType.Lsl, 16); + } + + public static void EmitUnsigned8BitPair(CodeGenContext context, uint rd, uint rn, uint rm, Action<Operand, Operand, Operand> elementAction) + { + Emit8BitPair(context, rd, rn, rm, elementAction, unsigned: true); + } + + private static void Emit8BitPair(CodeGenContext context, uint rd, uint rn, uint rm, Action<Operand, Operand, Operand> elementAction, bool unsigned) + { + using ScopedRegister tempD = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempD2 = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand rdOperand = GetOutputGpr(context, rd); + Operand rnOperand = GetInputGpr(context, rn); + Operand rmOperand = GetInputGpr(context, rm); + + for (int b = 0; b < 4; b++) + { + if (unsigned) + { + context.Arm64Assembler.Ubfx(tempN.Operand, rnOperand, b * 8, 8); + context.Arm64Assembler.Ubfx(tempM.Operand, rmOperand, b * 8, 8); + } + else + { + context.Arm64Assembler.Sbfx(tempN.Operand, rnOperand, b * 8, 8); + context.Arm64Assembler.Sbfx(tempM.Operand, rmOperand, b * 8, 8); + } + + elementAction(tempD.Operand, tempN.Operand, tempM.Operand); + + if (b == 0) + { + context.Arm64Assembler.Uxtb(tempD2.Operand, tempD.Operand); + } + else if (b < 3) + { + context.Arm64Assembler.Uxtb(tempD.Operand, tempD.Operand); + context.Arm64Assembler.Orr(tempD2.Operand, tempD2.Operand, tempD.Operand, ArmShiftType.Lsl, b * 8); + } + else + { + context.Arm64Assembler.Orr(rdOperand, tempD2.Operand, tempD.Operand, ArmShiftType.Lsl, 24); + } + } + } + + public static uint CombineV(uint low4, uint high1, uint size) + { + return size == 3 ? CombineV(low4, high1) : CombineVF(high1, low4); + } + + public static uint CombineV(uint low4, uint high1) + { + return low4 | (high1 << 4); + } + + public static uint CombineVF(uint low1, uint high4) + { + return low1 | (high4 << 1); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitCrc32.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitCrc32.cs new file mode 100644 index 00000000..ee634188 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitCrc32.cs @@ -0,0 +1,26 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using System; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitCrc32 + { + public static void Crc32(CodeGenContext context, uint rd, uint rn, uint rm, uint sz) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + context.Arm64Assembler.Crc32(rdOperand, rnOperand, rmOperand, Math.Min(2, sz)); + } + + public static void Crc32c(CodeGenContext context, uint rd, uint rn, uint rm, uint sz) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + context.Arm64Assembler.Crc32c(rdOperand, rnOperand, rmOperand, Math.Min(2, sz)); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitDivide.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitDivide.cs new file mode 100644 index 00000000..31c96dc8 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitDivide.cs @@ -0,0 +1,25 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitDivide + { + public static void Sdiv(CodeGenContext context, uint rd, uint rn, uint rm) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + context.Arm64Assembler.Sdiv(rdOperand, rnOperand, rmOperand); + } + + public static void Udiv(CodeGenContext context, uint rd, uint rn, uint rm) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + context.Arm64Assembler.Udiv(rdOperand, rnOperand, rmOperand); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitExtension.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitExtension.cs new file mode 100644 index 00000000..dafe2974 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitExtension.cs @@ -0,0 +1,191 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitExtension + { + public static void Sxtab(CodeGenContext context, uint rd, uint rn, uint rm, uint rotate) + { + EmitRotated(context, ArmExtensionType.Sxtb, rd, rn, rm, rotate); + } + + public static void Sxtab16(CodeGenContext context, uint rd, uint rn, uint rm, uint rotate) + { + EmitExtendAccumulate8(context, rd, rn, rm, rotate, unsigned: false); + } + + public static void Sxtah(CodeGenContext context, uint rd, uint rn, uint rm, uint rotate) + { + EmitRotated(context, ArmExtensionType.Sxth, rd, rn, rm, rotate); + } + + public static void Sxtb(CodeGenContext context, uint rd, uint rm, uint rotate) + { + EmitRotated(context, context.Arm64Assembler.Sxtb, rd, rm, rotate); + } + + public static void Sxtb16(CodeGenContext context, uint rd, uint rm, uint rotate) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempRegister2 = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + if (rotate != 0) + { + context.Arm64Assembler.Ror(tempRegister.Operand, rmOperand, InstEmitCommon.Const((int)rotate * 8)); + context.Arm64Assembler.And(rdOperand, tempRegister.Operand, InstEmitCommon.Const(0xff00ff)); + } + else + { + context.Arm64Assembler.And(rdOperand, rmOperand, InstEmitCommon.Const(0xff00ff)); + } + + // Sign-extend by broadcasting sign bits. + context.Arm64Assembler.And(tempRegister.Operand, rdOperand, InstEmitCommon.Const(0x800080)); + context.Arm64Assembler.Lsl(tempRegister2.Operand, tempRegister.Operand, InstEmitCommon.Const(9)); + context.Arm64Assembler.Sub(tempRegister.Operand, tempRegister2.Operand, tempRegister.Operand); + context.Arm64Assembler.Orr(rdOperand, rdOperand, tempRegister.Operand); + } + + public static void Sxth(CodeGenContext context, uint rd, uint rm, uint rotate) + { + EmitRotated(context, context.Arm64Assembler.Sxth, rd, rm, rotate); + } + + public static void Uxtab(CodeGenContext context, uint rd, uint rn, uint rm, uint rotate) + { + EmitRotated(context, ArmExtensionType.Uxtb, rd, rn, rm, rotate); + } + + public static void Uxtab16(CodeGenContext context, uint rd, uint rn, uint rm, uint rotate) + { + EmitExtendAccumulate8(context, rd, rn, rm, rotate, unsigned: true); + } + + public static void Uxtah(CodeGenContext context, uint rd, uint rn, uint rm, uint rotate) + { + EmitRotated(context, ArmExtensionType.Uxth, rd, rn, rm, rotate); + } + + public static void Uxtb(CodeGenContext context, uint rd, uint rm, uint rotate) + { + EmitRotated(context, context.Arm64Assembler.Uxtb, rd, rm, rotate); + } + + public static void Uxtb16(CodeGenContext context, uint rd, uint rm, uint rotate) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + if (rotate != 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Ror(tempRegister.Operand, rmOperand, InstEmitCommon.Const((int)rotate * 8)); + context.Arm64Assembler.And(rdOperand, tempRegister.Operand, InstEmitCommon.Const(0xff00ff)); + } + else + { + context.Arm64Assembler.And(rdOperand, rmOperand, InstEmitCommon.Const(0xff00ff)); + } + } + + public static void Uxth(CodeGenContext context, uint rd, uint rm, uint rotate) + { + EmitRotated(context, context.Arm64Assembler.Uxth, rd, rm, rotate); + } + + private static void EmitRotated(CodeGenContext context, Action<Operand, Operand> action, uint rd, uint rm, uint rotate) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + if (rotate != 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Ror(tempRegister.Operand, rmOperand, InstEmitCommon.Const((int)rotate * 8)); + action(rdOperand, tempRegister.Operand); + } + else + { + action(rdOperand, rmOperand); + } + } + + private static void EmitRotated(CodeGenContext context, ArmExtensionType extensionType, uint rd, uint rn, uint rm, uint rotate) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + if (rotate != 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Ror(tempRegister.Operand, rmOperand, InstEmitCommon.Const((int)rotate * 8)); + context.Arm64Assembler.Add(rdOperand, rnOperand, tempRegister.Operand, extensionType); + } + else + { + context.Arm64Assembler.Add(rdOperand, rnOperand, rmOperand, extensionType); + } + } + + private static void EmitExtendAccumulate8(CodeGenContext context, uint rd, uint rn, uint rm, uint rotate, bool unsigned) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + if (rotate != 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Ror(tempRegister.Operand, rmOperand, InstEmitCommon.Const((int)rotate * 8)); + + EmitExtendAccumulate8Core(context, rdOperand, rnOperand, tempRegister.Operand, unsigned); + } + else + { + EmitExtendAccumulate8Core(context, rdOperand, rnOperand, rmOperand, unsigned); + } + } + + private static void EmitExtendAccumulate8Core(CodeGenContext context, Operand rd, Operand rn, Operand rm, bool unsigned) + { + using ScopedRegister tempD = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempD2 = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + if (unsigned) + { + context.Arm64Assembler.Uxth(tempN.Operand, rn); + } + else + { + context.Arm64Assembler.Sxth(tempN.Operand, rn); + } + + context.Arm64Assembler.Add(tempD.Operand, tempN.Operand, rm, unsigned ? ArmExtensionType.Uxtb : ArmExtensionType.Sxtb); + context.Arm64Assembler.Uxth(tempD2.Operand, tempD.Operand); + + if (unsigned) + { + context.Arm64Assembler.Lsr(tempN.Operand, rn, InstEmitCommon.Const(16)); + } + else + { + context.Arm64Assembler.Asr(tempN.Operand, rn, InstEmitCommon.Const(16)); + } + + context.Arm64Assembler.Lsr(tempD.Operand, rm, InstEmitCommon.Const(16)); + context.Arm64Assembler.Add(tempD.Operand, tempN.Operand, tempD.Operand, unsigned ? ArmExtensionType.Uxtb : ArmExtensionType.Sxtb); + context.Arm64Assembler.Orr(rd, tempD2.Operand, tempD.Operand, ArmShiftType.Lsl, 16); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs new file mode 100644 index 00000000..81e44ba0 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs @@ -0,0 +1,256 @@ +using ARMeilleure.Common; +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System; +using System.Diagnostics; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitFlow + { + private const int SpIndex = 31; + + public static void B(CodeGenContext context, int imm, ArmCondition condition) + { + context.AddPendingBranch(InstName.B, imm); + + if (condition == ArmCondition.Al) + { + context.Arm64Assembler.B(0); + } + else + { + context.Arm64Assembler.B(condition, 0); + } + } + + public static void Bl(CodeGenContext context, int imm, bool sourceIsThumb, bool targetIsThumb) + { + uint nextAddress = sourceIsThumb ? context.Pc | 1u : context.Pc - 4; + uint targetAddress = targetIsThumb ? context.Pc + (uint)imm : (context.Pc & ~3u) + (uint)imm; + + if (sourceIsThumb != targetIsThumb) + { + if (targetIsThumb) + { + InstEmitCommon.SetThumbFlag(context); + } + else + { + InstEmitCommon.ClearThumbFlag(context); + } + } + + context.AddPendingCall(targetAddress, nextAddress); + + context.Arm64Assembler.B(0); + } + + public static void Blx(CodeGenContext context, uint rm, bool sourceIsThumb) + { + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + InstEmitCommon.SetThumbFlag(context, rmOperand); + + uint nextAddress = sourceIsThumb ? (context.Pc - 2) | 1u : context.Pc - 4; + + context.AddPendingIndirectCall(rm, nextAddress); + + context.Arm64Assembler.B(0); + } + + public static void Bx(CodeGenContext context, uint rm) + { + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + InstEmitCommon.SetThumbFlag(context, rmOperand); + + context.AddPendingIndirectBranch(InstName.Bx, rm); + + context.Arm64Assembler.B(0); + } + + public static void Cbnz(CodeGenContext context, uint rn, int imm, bool op) + { + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + context.AddPendingBranch(InstName.Cbnz, imm); + + if (op) + { + context.Arm64Assembler.Cbnz(rnOperand, 0); + } + else + { + context.Arm64Assembler.Cbz(rnOperand, 0); + } + } + + public static void It(CodeGenContext context, uint firstCond, uint mask) + { + Debug.Assert(mask != 0); + + int instCount = 4 - BitOperations.TrailingZeroCount(mask); + + Span<ArmCondition> conditions = stackalloc ArmCondition[instCount]; + + int i = 0; + + for (int index = 5 - instCount; index < 4; index++) + { + bool invert = (mask & (1u << index)) != 0; + + if (invert) + { + conditions[i++] = ((ArmCondition)firstCond).Invert(); + } + else + { + conditions[i++] = (ArmCondition)firstCond; + } + } + + conditions[i] = (ArmCondition)firstCond; + + context.SetItBlockStart(conditions); + } + + public static void Tbb(CodeGenContext context, uint rn, uint rm, bool h) + { + context.Arm64Assembler.Mov(context.RegisterAllocator.RemapGprRegister(RegisterUtils.PcRegister), context.Pc); + + context.AddPendingTableBranch(rn, rm, h); + + context.Arm64Assembler.B(0); + } + + public unsafe static void WriteCallWithGuestAddress( + CodeWriter writer, + ref Assembler asm, + RegisterAllocator regAlloc, + TailMerger tailMerger, + Action writeEpilogue, + AddressTable<ulong> funcTable, + IntPtr funcPtr, + int spillBaseOffset, + uint nextAddress, + Operand guestAddress, + bool isTail = false) + { + int tempRegister; + + if (guestAddress.Kind == OperandKind.Constant) + { + tempRegister = regAlloc.AllocateTempGprRegister(); + + asm.Mov(Register(tempRegister), guestAddress.Value); + asm.StrRiUn(Register(tempRegister), Register(regAlloc.FixedContextRegister), NativeContextOffsets.DispatchAddressOffset); + + regAlloc.FreeTempGprRegister(tempRegister); + } + else + { + asm.StrRiUn(guestAddress, Register(regAlloc.FixedContextRegister), NativeContextOffsets.DispatchAddressOffset); + } + + tempRegister = regAlloc.FixedContextRegister == 1 ? 2 : 1; + + if (!isTail) + { + WriteSpillSkipContext(ref asm, regAlloc, spillBaseOffset); + } + + Operand rn = Register(tempRegister); + + if (regAlloc.FixedContextRegister != 0) + { + asm.Mov(Register(0), Register(regAlloc.FixedContextRegister)); + } + + if (guestAddress.Kind == OperandKind.Constant && funcTable != null) + { + ulong funcPtrLoc = (ulong)Unsafe.AsPointer(ref funcTable.GetValue(guestAddress.Value)); + + asm.Mov(rn, funcPtrLoc & ~0xfffUL); + asm.LdrRiUn(rn, rn, (int)(funcPtrLoc & 0xfffUL)); + } + else + { + asm.Mov(rn, (ulong)funcPtr); + } + + if (isTail) + { + writeEpilogue(); + asm.Br(rn); + } + else + { + asm.Blr(rn); + + asm.Mov(rn, nextAddress); + asm.Cmp(Register(0), rn); + + tailMerger.AddConditionalReturn(writer, asm, ArmCondition.Ne); + + WriteFillSkipContext(ref asm, regAlloc, spillBaseOffset); + } + } + + private static void WriteSpillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset) + { + WriteSpillOrFillSkipContext(ref asm, regAlloc, spillOffset, spill: true); + } + + private static void WriteFillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset) + { + WriteSpillOrFillSkipContext(ref asm, regAlloc, spillOffset, spill: false); + } + + private static void WriteSpillOrFillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset, bool spill) + { + uint gprMask = regAlloc.UsedGprsMask & ((1u << regAlloc.FixedContextRegister) | (1u << regAlloc.FixedPageTableRegister)); + + while (gprMask != 0) + { + int reg = BitOperations.TrailingZeroCount(gprMask); + + if (reg < 31 && (gprMask & (2u << reg)) != 0 && spillOffset < RegisterSaveRestore.Encodable9BitsOffsetLimit) + { + if (spill) + { + asm.StpRiUn(Register(reg), Register(reg + 1), Register(SpIndex), spillOffset); + } + else + { + asm.LdpRiUn(Register(reg), Register(reg + 1), Register(SpIndex), spillOffset); + } + + gprMask &= ~(3u << reg); + spillOffset += 16; + } + else + { + if (spill) + { + asm.StrRiUn(Register(reg), Register(SpIndex), spillOffset); + } + else + { + asm.LdrRiUn(Register(reg), Register(SpIndex), spillOffset); + } + + gprMask &= ~(1u << reg); + spillOffset += 8; + } + } + } + + private static Operand Register(int register, OperandType type = OperandType.I64) + { + return new Operand(register, RegisterType.Integer, type); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitGE.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitGE.cs new file mode 100644 index 00000000..dffcc511 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitGE.cs @@ -0,0 +1,265 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitGE + { + public static void Sadd16(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAddSub(context, rd, rn, rm, is16Bit: true, add: true, unsigned: false); + } + + public static void Sadd8(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAddSub(context, rd, rn, rm, is16Bit: false, add: true, unsigned: false); + } + + public static void Sasx(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAsxSax(context, rd, rn, rm, isAsx: true, unsigned: false); + } + + public static void Sel(CodeGenContext context, uint rd, uint rn, uint rm) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + using ScopedRegister geFlags = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + ExtractGEFlags(context, geFlags.Operand); + + // Broadcast compact GE flags (one bit to one byte, 0b1111 -> 0x1010101). + context.Arm64Assembler.Mov(tempRegister.Operand, 0x204081u); + context.Arm64Assembler.Mul(geFlags.Operand, geFlags.Operand, tempRegister.Operand); + context.Arm64Assembler.And(geFlags.Operand, geFlags.Operand, InstEmitCommon.Const(0x1010101)); + + // Build mask from expanded flags (0x1010101 -> 0xFFFFFFFF). + context.Arm64Assembler.Lsl(tempRegister.Operand, geFlags.Operand, InstEmitCommon.Const(8)); + context.Arm64Assembler.Sub(geFlags.Operand, tempRegister.Operand, geFlags.Operand); + + // Result = (n & mask) | (m & ~mask). + context.Arm64Assembler.And(tempRegister.Operand, geFlags.Operand, rnOperand); + context.Arm64Assembler.Bic(rdOperand, rmOperand, geFlags.Operand); + context.Arm64Assembler.Orr(rdOperand, rdOperand, tempRegister.Operand); + } + + public static void Ssax(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAsxSax(context, rd, rn, rm, isAsx: false, unsigned: false); + } + + public static void Ssub16(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAddSub(context, rd, rn, rm, is16Bit: true, add: false, unsigned: false); + } + + public static void Ssub8(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAddSub(context, rd, rn, rm, is16Bit: false, add: false, unsigned: false); + } + + public static void Uadd16(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAddSub(context, rd, rn, rm, is16Bit: true, add: true, unsigned: true); + } + + public static void Uadd8(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAddSub(context, rd, rn, rm, is16Bit: false, add: true, unsigned: true); + } + + public static void Uasx(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAsxSax(context, rd, rn, rm, isAsx: true, unsigned: true); + } + + public static void Usax(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAsxSax(context, rd, rn, rm, isAsx: false, unsigned: true); + } + + public static void Usub16(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAddSub(context, rd, rn, rm, is16Bit: true, add: false, unsigned: true); + } + + public static void Usub8(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAddSub(context, rd, rn, rm, is16Bit: false, add: false, unsigned: true); + } + + private static void EmitAddSub(CodeGenContext context, uint rd, uint rn, uint rm, bool is16Bit, bool add, bool unsigned) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + using ScopedRegister geFlags = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + int e = 0; + + void Emit(Operand d, Operand n, Operand m) + { + if (add) + { + context.Arm64Assembler.Add(d, n, m); + } + else + { + context.Arm64Assembler.Sub(d, n, m); + } + + if (unsigned && add) + { + if (e == 0) + { + context.Arm64Assembler.Lsr(geFlags.Operand, d, InstEmitCommon.Const(is16Bit ? 16 : 8)); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Lsr(tempRegister.Operand, d, InstEmitCommon.Const(is16Bit ? 16 : 8)); + context.Arm64Assembler.Orr(geFlags.Operand, geFlags.Operand, tempRegister.Operand, ArmShiftType.Lsl, e); + } + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Mvn(tempRegister.Operand, d); + + if (e == 0) + { + context.Arm64Assembler.Lsr(geFlags.Operand, tempRegister.Operand, InstEmitCommon.Const(31)); + } + else + { + context.Arm64Assembler.Lsr(tempRegister.Operand, tempRegister.Operand, InstEmitCommon.Const(31)); + context.Arm64Assembler.Orr(geFlags.Operand, geFlags.Operand, tempRegister.Operand, ArmShiftType.Lsl, e); + } + } + + e += is16Bit ? 2 : 1; + } + + if (is16Bit) + { + if (unsigned) + { + InstEmitCommon.EmitUnsigned16BitPair(context, rd, rn, rm, Emit); + } + else + { + InstEmitCommon.EmitSigned16BitPair(context, rd, rn, rm, Emit); + } + + // Duplicate bits. + context.Arm64Assembler.Orr(geFlags.Operand, geFlags.Operand, geFlags.Operand, ArmShiftType.Lsl, 1); + } + else + { + if (unsigned) + { + InstEmitCommon.EmitUnsigned8BitPair(context, rd, rn, rm, Emit); + } + else + { + InstEmitCommon.EmitSigned8BitPair(context, rd, rn, rm, Emit); + } + } + + UpdateGEFlags(context, geFlags.Operand); + } + + private static void EmitAsxSax(CodeGenContext context, uint rd, uint rn, uint rm, bool isAsx, bool unsigned) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + using ScopedRegister geFlags = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + void Emit(Operand d, Operand n, Operand m, int e) + { + bool add = e == (isAsx ? 1 : 0); + + if (add) + { + context.Arm64Assembler.Add(d, n, m); + } + else + { + context.Arm64Assembler.Sub(d, n, m); + } + + if (unsigned && add) + { + if (e == 0) + { + context.Arm64Assembler.Lsr(geFlags.Operand, d, InstEmitCommon.Const(16)); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Lsr(tempRegister.Operand, d, InstEmitCommon.Const(16)); + context.Arm64Assembler.Orr(geFlags.Operand, geFlags.Operand, tempRegister.Operand, ArmShiftType.Lsl, e * 2); + } + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Mvn(tempRegister.Operand, d); + + if (e == 0) + { + context.Arm64Assembler.Lsr(geFlags.Operand, tempRegister.Operand, InstEmitCommon.Const(31)); + } + else + { + context.Arm64Assembler.Lsr(tempRegister.Operand, tempRegister.Operand, InstEmitCommon.Const(31)); + context.Arm64Assembler.Orr(geFlags.Operand, geFlags.Operand, tempRegister.Operand, ArmShiftType.Lsl, e * 2); + } + } + } + + if (unsigned) + { + InstEmitCommon.EmitUnsigned16BitXPair(context, rd, rn, rm, Emit); + } + else + { + InstEmitCommon.EmitSigned16BitXPair(context, rd, rn, rm, Emit); + } + + // Duplicate bits. + context.Arm64Assembler.Orr(geFlags.Operand, geFlags.Operand, geFlags.Operand, ArmShiftType.Lsl, 1); + + UpdateGEFlags(context, geFlags.Operand); + } + + public static void UpdateGEFlags(CodeGenContext context, Operand flags) + { + Operand ctx = InstEmitSystem.Register(context.RegisterAllocator.FixedContextRegister); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.LdrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + context.Arm64Assembler.Bfi(tempRegister.Operand, flags, 16, 4); + context.Arm64Assembler.StrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + } + + public static void ExtractGEFlags(CodeGenContext context, Operand flags) + { + Operand ctx = InstEmitSystem.Register(context.RegisterAllocator.FixedContextRegister); + + context.Arm64Assembler.LdrRiUn(flags, ctx, NativeContextOffsets.FlagsBaseOffset); + context.Arm64Assembler.Ubfx(flags, flags, 16, 4); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitHalve.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitHalve.cs new file mode 100644 index 00000000..567acfbf --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitHalve.cs @@ -0,0 +1,178 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitHalve + { + public static void Shadd16(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitHadd(context, rd, rn, rm, 0x7fff7fff, unsigned: false); + } + + public static void Shadd8(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitHadd(context, rd, rn, rm, 0x7f7f7f7f, unsigned: false); + } + + public static void Shsub16(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitHsub(context, rd, rn, rm, 0x7fff7fff, unsigned: false); + } + + public static void Shsub8(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitHsub(context, rd, rn, rm, 0x7f7f7f7f, unsigned: false); + } + + public static void Shasx(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitSigned16BitXPair(context, rd, rn, rm, (d, n, m, e) => + { + if (e == 0) + { + context.Arm64Assembler.Sub(d, n, m); + } + else + { + context.Arm64Assembler.Add(d, n, m); + } + + context.Arm64Assembler.Lsr(d, d, InstEmitCommon.Const(1)); + }); + } + + public static void Shsax(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitSigned16BitXPair(context, rd, rn, rm, (d, n, m, e) => + { + if (e == 0) + { + context.Arm64Assembler.Add(d, n, m); + } + else + { + context.Arm64Assembler.Sub(d, n, m); + } + + context.Arm64Assembler.Lsr(d, d, InstEmitCommon.Const(1)); + }); + } + + public static void Uhadd16(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitHadd(context, rd, rn, rm, 0x7fff7fff, unsigned: true); + } + + public static void Uhadd8(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitHadd(context, rd, rn, rm, 0x7f7f7f7f, unsigned: true); + } + + public static void Uhasx(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitUnsigned16BitXPair(context, rd, rn, rm, (d, n, m, e) => + { + if (e == 0) + { + context.Arm64Assembler.Sub(d, n, m); + } + else + { + context.Arm64Assembler.Add(d, n, m); + } + + context.Arm64Assembler.Lsr(d, d, InstEmitCommon.Const(1)); + }); + } + + public static void Uhsax(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitUnsigned16BitXPair(context, rd, rn, rm, (d, n, m, e) => + { + if (e == 0) + { + context.Arm64Assembler.Add(d, n, m); + } + else + { + context.Arm64Assembler.Sub(d, n, m); + } + + context.Arm64Assembler.Lsr(d, d, InstEmitCommon.Const(1)); + }); + } + + public static void Uhsub16(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitHsub(context, rd, rn, rm, 0x7fff7fff, unsigned: true); + } + + public static void Uhsub8(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitHsub(context, rd, rn, rm, 0x7f7f7f7f, unsigned: true); + } + + private static void EmitHadd(CodeGenContext context, uint rd, uint rn, uint rm, int mask, bool unsigned) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + using ScopedRegister res = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister carry = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + // This relies on the equality x+y == ((x&y) << 1) + (x^y). + // Note that x^y always contains the LSB of the result. + // Since we want to calculate (x+y)/2, we can instead calculate (x&y) + ((x^y)>>1). + // We mask by 0x7F/0x7FFF to remove the LSB so that it doesn't leak into the field below. + + context.Arm64Assembler.And(res.Operand, rmOperand, rnOperand); + context.Arm64Assembler.Eor(carry.Operand, rmOperand, rnOperand); + context.Arm64Assembler.Lsr(rdOperand, carry.Operand, InstEmitCommon.Const(1)); + context.Arm64Assembler.And(rdOperand, rdOperand, InstEmitCommon.Const(mask)); + context.Arm64Assembler.Add(rdOperand, rdOperand, res.Operand); + + if (!unsigned) + { + // Propagates the sign bit from (x^y)>>1 upwards by one. + context.Arm64Assembler.And(carry.Operand, carry.Operand, InstEmitCommon.Const(~mask)); + context.Arm64Assembler.Eor(rdOperand, rdOperand, carry.Operand); + } + } + + private static void EmitHsub(CodeGenContext context, uint rd, uint rn, uint rm, int mask, bool unsigned) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + using ScopedRegister carry = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister left = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister right = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + // This relies on the equality x-y == (x^y) - (((x^y)&y) << 1). + // Note that x^y always contains the LSB of the result. + // Since we want to calculate (x+y)/2, we can instead calculate ((x^y)>>1) - ((x^y)&y). + + context.Arm64Assembler.Eor(carry.Operand, rmOperand, rnOperand); + context.Arm64Assembler.Lsr(left.Operand, carry.Operand, InstEmitCommon.Const(1)); + context.Arm64Assembler.And(right.Operand, carry.Operand, rmOperand); + + // We must now perform a partitioned subtraction. + // We can do this because minuend contains 7/15 bit fields. + // We use the extra bit in minuend as a bit to borrow from; we set this bit. + // We invert this bit at the end as this tells us if that bit was borrowed from. + + context.Arm64Assembler.Orr(rdOperand, left.Operand, InstEmitCommon.Const(~mask)); + context.Arm64Assembler.Sub(rdOperand, rdOperand, right.Operand); + context.Arm64Assembler.Eor(rdOperand, rdOperand, InstEmitCommon.Const(~mask)); + + if (!unsigned) + { + // We then sign extend the result into this bit. + context.Arm64Assembler.And(carry.Operand, carry.Operand, InstEmitCommon.Const(~mask)); + context.Arm64Assembler.Eor(rdOperand, rdOperand, carry.Operand); + } + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMemory.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMemory.cs new file mode 100644 index 00000000..6ab4b949 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMemory.cs @@ -0,0 +1,1172 @@ +using ARMeilleure.Memory; +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System; +using System.Diagnostics; +using System.Numerics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitMemory + { + private enum PrefetchType : uint + { + Pld = 0, + Pli = 1, + Pst = 2, + } + + public static void Lda(CodeGenContext context, uint rt, uint rn) + { + EmitMemoryInstruction(context, rt, rn, isStore: false, context.Arm64Assembler.Ldar); + } + + public static void Ldab(CodeGenContext context, uint rt, uint rn) + { + EmitMemoryInstruction(context, rt, rn, isStore: false, context.Arm64Assembler.Ldarb); + } + + public static void Ldaex(CodeGenContext context, uint rt, uint rn) + { + EmitMemoryInstruction(context, rt, rn, isStore: false, context.Arm64Assembler.Ldaxr); + } + + public static void Ldaexb(CodeGenContext context, uint rt, uint rn) + { + EmitMemoryInstruction(context, rt, rn, isStore: false, context.Arm64Assembler.Ldaxrb); + } + + public static void Ldaexd(CodeGenContext context, uint rt, uint rt2, uint rn) + { + EmitMemoryDWordInstruction(context, rt, rt2, rn, isStore: false, context.Arm64Assembler.Ldaxp); + } + + public static void Ldaexh(CodeGenContext context, uint rt, uint rn) + { + EmitMemoryInstruction(context, rt, rn, isStore: false, context.Arm64Assembler.Ldaxrh); + } + + public static void Ldah(CodeGenContext context, uint rt, uint rn) + { + EmitMemoryInstruction(context, rt, rn, isStore: false, context.Arm64Assembler.Ldarh); + } + + public static void LdcI(CodeGenContext context, uint rn, int imm, bool p, bool u, bool w) + { + // TODO. + } + + public static void LdcL(CodeGenContext context, uint imm, bool p, bool u, bool w) + { + // TODO. + } + + public static void Ldm(CodeGenContext context, uint rn, uint registerList, bool w) + { + Operand baseAddress = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); + + EmitMemoryMultipleInstructionCore( + context, + tempRegister.Operand, + registerList, + isStore: false, + context.Arm64Assembler.LdrRiUn, + context.Arm64Assembler.LdpRiUn); + + if (w) + { + Operand offset = InstEmitCommon.Const(BitOperations.PopCount(registerList) * 4); + + WriteAddShiftOffset(context.Arm64Assembler, baseAddress, baseAddress, offset, true, ArmShiftType.Lsl, 0); + } + } + + public static void Ldmda(CodeGenContext context, uint rn, uint registerList, bool w) + { + EmitMemoryMultipleDaInstruction(context, rn, registerList, w, isStore: false, context.Arm64Assembler.LdrRiUn, context.Arm64Assembler.LdpRiUn); + } + + public static void Ldmdb(CodeGenContext context, uint rn, uint registerList, bool w) + { + EmitMemoryMultipleDbInstruction(context, rn, registerList, w, isStore: false, context.Arm64Assembler.LdrRiUn, context.Arm64Assembler.LdpRiUn); + } + + public static void Ldmib(CodeGenContext context, uint rn, uint registerList, bool w) + { + EmitMemoryMultipleIbInstruction(context, rn, registerList, w, isStore: false, context.Arm64Assembler.LdrRiUn, context.Arm64Assembler.LdpRiUn); + } + + public static void LdrI(CodeGenContext context, uint rt, uint rn, int imm, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, imm, 2, p, u, w, isStore: false, context.Arm64Assembler.LdrRiUn, context.Arm64Assembler.Ldur); + } + + public static void LdrL(CodeGenContext context, uint rt, uint imm, bool p, bool u, bool w) + { + EmitMemoryLiteralInstruction(context, rt, imm, 2, p, u, w, context.Arm64Assembler.LdrRiUn); + } + + public static void LdrR(CodeGenContext context, uint rt, uint rn, uint rm, uint sType, uint imm5, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, rm, sType, imm5, p, u, w, isStore: false, context.Arm64Assembler.LdrRiUn, context.Arm64Assembler.Ldur); + } + + public static void LdrbI(CodeGenContext context, uint rt, uint rn, int imm, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, imm, 0, p, u, w, isStore: false, context.Arm64Assembler.LdrbRiUn, context.Arm64Assembler.Ldurb); + } + + public static void LdrbL(CodeGenContext context, uint rt, uint imm, bool p, bool u, bool w) + { + EmitMemoryLiteralInstruction(context, rt, imm, 0, p, u, w, context.Arm64Assembler.LdrbRiUn); + } + + public static void LdrbR(CodeGenContext context, uint rt, uint rn, uint rm, uint sType, uint imm5, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, rm, sType, imm5, p, u, w, isStore: false, context.Arm64Assembler.LdrbRiUn, context.Arm64Assembler.Ldurb); + } + + public static void LdrbtI(CodeGenContext context, uint rt, uint rn, int imm, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, imm, 0, !postIndex, u, false, isStore: false, context.Arm64Assembler.LdrbRiUn, context.Arm64Assembler.Ldurb); + } + + public static void LdrbtR(CodeGenContext context, uint rt, uint rn, uint rm, uint sType, uint imm5, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, rm, sType, imm5, !postIndex, u, false, isStore: false, context.Arm64Assembler.LdrbRiUn, context.Arm64Assembler.Ldurb); + } + + public static void LdrdI(CodeGenContext context, uint rt, uint rt2, uint rn, uint imm, bool p, bool u, bool w) + { + EmitMemoryDWordInstructionI(context, rt, rt2, rn, imm, p, u, w, isStore: false, context.Arm64Assembler.LdpRiUn); + } + + public static void LdrdL(CodeGenContext context, uint rt, uint rt2, uint imm, bool p, bool u, bool w) + { + EmitMemoryDWordLiteralInstruction(context, rt, rt2, imm, p, u, w, context.Arm64Assembler.LdpRiUn); + } + + public static void LdrdR(CodeGenContext context, uint rt, uint rt2, uint rn, uint rm, bool p, bool u, bool w) + { + EmitMemoryDWordInstructionR(context, rt, rt2, rn, rm, p, u, w, isStore: false, context.Arm64Assembler.LdpRiUn); + } + + public static void Ldrex(CodeGenContext context, uint rt, uint rn) + { + EmitMemoryInstruction(context, rt, rn, isStore: false, context.Arm64Assembler.Ldaxr); + } + + public static void Ldrexb(CodeGenContext context, uint rt, uint rn) + { + EmitMemoryInstruction(context, rt, rn, isStore: false, context.Arm64Assembler.Ldaxrb); + } + + public static void Ldrexd(CodeGenContext context, uint rt, uint rt2, uint rn) + { + EmitMemoryDWordInstruction(context, rt, rt2, rn, isStore: false, context.Arm64Assembler.Ldaxp); + } + + public static void Ldrexh(CodeGenContext context, uint rt, uint rn) + { + EmitMemoryInstruction(context, rt, rn, isStore: false, context.Arm64Assembler.Ldaxrh); + } + + public static void LdrhI(CodeGenContext context, uint rt, uint rn, int imm, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, imm, 1, p, u, w, isStore: false, context.Arm64Assembler.LdrhRiUn, context.Arm64Assembler.Ldurh); + } + + public static void LdrhL(CodeGenContext context, uint rt, uint imm, bool p, bool u, bool w) + { + EmitMemoryLiteralInstruction(context, rt, imm, 1, p, u, w, context.Arm64Assembler.LdrhRiUn); + } + + public static void LdrhR(CodeGenContext context, uint rt, uint rn, uint rm, uint sType, uint imm5, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, rm, sType, imm5, p, u, w, isStore: false, context.Arm64Assembler.LdrhRiUn, context.Arm64Assembler.Ldurh); + } + + public static void LdrhtI(CodeGenContext context, uint rt, uint rn, int imm, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, imm, 1, !postIndex, u, false, isStore: false, context.Arm64Assembler.LdrhRiUn, context.Arm64Assembler.Ldurh); + } + + public static void LdrhtR(CodeGenContext context, uint rt, uint rn, uint rm, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, rm, 0, 0, !postIndex, u, false, isStore: false, context.Arm64Assembler.LdrhRiUn, context.Arm64Assembler.Ldurh); + } + + public static void LdrsbI(CodeGenContext context, uint rt, uint rn, int imm, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, imm, 0, p, u, w, isStore: false, context.Arm64Assembler.LdrsbRiUn, context.Arm64Assembler.Ldursb); + } + + public static void LdrsbL(CodeGenContext context, uint rt, uint imm, bool p, bool u, bool w) + { + EmitMemoryLiteralInstruction(context, rt, imm, 0, p, u, w, context.Arm64Assembler.LdrsbRiUn); + } + + public static void LdrsbR(CodeGenContext context, uint rt, uint rn, uint rm, uint sType, uint imm5, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, rm, sType, imm5, p, u, w, isStore: false, context.Arm64Assembler.LdrsbRiUn, context.Arm64Assembler.Ldursb); + } + + public static void LdrsbtI(CodeGenContext context, uint rt, uint rn, int imm, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, imm, 0, !postIndex, u, false, isStore: false, context.Arm64Assembler.LdrsbRiUn, context.Arm64Assembler.Ldursb); + } + + public static void LdrsbtR(CodeGenContext context, uint rt, uint rn, uint rm, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, rm, 0, 0, !postIndex, u, false, isStore: false, context.Arm64Assembler.LdrsbRiUn, context.Arm64Assembler.Ldursb); + } + + public static void LdrshI(CodeGenContext context, uint rt, uint rn, int imm, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, imm, 1, p, u, w, isStore: false, context.Arm64Assembler.LdrshRiUn, context.Arm64Assembler.Ldursh); + } + + public static void LdrshL(CodeGenContext context, uint rt, uint imm, bool p, bool u, bool w) + { + EmitMemoryLiteralInstruction(context, rt, imm, 1, p, u, w, context.Arm64Assembler.LdrshRiUn); + } + + public static void LdrshR(CodeGenContext context, uint rt, uint rn, uint rm, uint sType, uint imm5, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, rm, sType, imm5, p, u, w, isStore: false, context.Arm64Assembler.LdrshRiUn, context.Arm64Assembler.Ldursh); + } + + public static void LdrshtI(CodeGenContext context, uint rt, uint rn, int imm, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, imm, 1, !postIndex, u, false, isStore: false, context.Arm64Assembler.LdrshRiUn, context.Arm64Assembler.Ldursh); + } + + public static void LdrshtR(CodeGenContext context, uint rt, uint rn, uint rm, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, rm, 0, 0, !postIndex, u, false, isStore: false, context.Arm64Assembler.LdrshRiUn, context.Arm64Assembler.Ldursh); + } + + public static void LdrtI(CodeGenContext context, uint rt, uint rn, int imm, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, imm, 2, !postIndex, u, false, isStore: false, context.Arm64Assembler.LdrRiUn, context.Arm64Assembler.Ldur); + } + + public static void LdrtR(CodeGenContext context, uint rt, uint rn, uint rm, uint sType, uint imm5, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, rm, sType, imm5, !postIndex, u, false, isStore: false, context.Arm64Assembler.LdrRiUn, context.Arm64Assembler.Ldur); + } + + public static void PldI(CodeGenContext context, uint rn, uint imm, bool u, bool r) + { + EmitMemoryPrefetchInstruction(context, rn, imm, u, r ? PrefetchType.Pld : PrefetchType.Pst); + } + + public static void PldL(CodeGenContext context, uint imm, bool u) + { + EmitMemoryPrefetchLiteralInstruction(context, imm, u, PrefetchType.Pld); + } + + public static void PldR(CodeGenContext context, uint rn, uint rm, uint sType, uint imm5, bool u, bool r) + { + EmitMemoryPrefetchInstruction(context, rn, rm, u, sType, imm5, r ? PrefetchType.Pld : PrefetchType.Pst); + } + + public static void PliI(CodeGenContext context, uint rn, uint imm, bool u) + { + EmitMemoryPrefetchInstruction(context, rn, imm, u, PrefetchType.Pli); + } + + public static void PliL(CodeGenContext context, uint imm, bool u) + { + EmitMemoryPrefetchLiteralInstruction(context, imm, u, PrefetchType.Pli); + } + + public static void PliR(CodeGenContext context, uint rn, uint rm, uint sType, uint imm5, bool u) + { + EmitMemoryPrefetchInstruction(context, rn, rm, u, sType, imm5, PrefetchType.Pli); + } + + public static void Stc(CodeGenContext context, uint rn, int imm, bool p, bool u, bool w) + { + // TODO. + } + + public static void Stl(CodeGenContext context, uint rt, uint rn) + { + EmitMemoryInstruction(context, rt, rn, isStore: true, context.Arm64Assembler.Stlr); + } + + public static void Stlb(CodeGenContext context, uint rt, uint rn) + { + EmitMemoryInstruction(context, rt, rn, isStore: true, context.Arm64Assembler.Stlrb); + } + + public static void Stlex(CodeGenContext context, uint rd, uint rt, uint rn) + { + EmitMemoryStrexInstruction(context, rd, rt, rn, context.Arm64Assembler.Stlxr); + } + + public static void Stlexb(CodeGenContext context, uint rd, uint rt, uint rn) + { + EmitMemoryStrexInstruction(context, rd, rt, rn, context.Arm64Assembler.Stlxrb); + } + + public static void Stlexd(CodeGenContext context, uint rd, uint rt, uint rt2, uint rn) + { + EmitMemoryDWordStrexInstruction(context, rd, rt, rt2, rn, context.Arm64Assembler.Stlxp); + } + + public static void Stlexh(CodeGenContext context, uint rd, uint rt, uint rn) + { + EmitMemoryStrexInstruction(context, rd, rt, rn, context.Arm64Assembler.Stlxrh); + } + + public static void Stlh(CodeGenContext context, uint rt, uint rn) + { + EmitMemoryInstruction(context, rt, rn, isStore: true, context.Arm64Assembler.Stlrh); + } + + public static void Stm(CodeGenContext context, uint rn, uint registerList, bool w) + { + Operand baseAddress = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); + + EmitMemoryMultipleInstructionCore( + context, + tempRegister.Operand, + registerList, + isStore: true, + context.Arm64Assembler.StrRiUn, + context.Arm64Assembler.StpRiUn); + + if (w) + { + Operand offset = InstEmitCommon.Const(BitOperations.PopCount(registerList) * 4); + + WriteAddShiftOffset(context.Arm64Assembler, baseAddress, baseAddress, offset, true, ArmShiftType.Lsl, 0); + } + } + + public static void Stmda(CodeGenContext context, uint rn, uint registerList, bool w) + { + EmitMemoryMultipleDaInstruction(context, rn, registerList, w, isStore: true, context.Arm64Assembler.StrRiUn, context.Arm64Assembler.StpRiUn); + } + + public static void Stmdb(CodeGenContext context, uint rn, uint registerList, bool w) + { + EmitMemoryMultipleDbInstruction(context, rn, registerList, w, isStore: true, context.Arm64Assembler.StrRiUn, context.Arm64Assembler.StpRiUn); + } + + public static void Stmib(CodeGenContext context, uint rn, uint registerList, bool w) + { + EmitMemoryMultipleIbInstruction(context, rn, registerList, w, isStore: true, context.Arm64Assembler.StrRiUn, context.Arm64Assembler.StpRiUn); + } + + public static void StrI(CodeGenContext context, uint rt, uint rn, int imm, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, imm, 2, p, u, w, isStore: true, context.Arm64Assembler.StrRiUn, context.Arm64Assembler.Stur); + } + + public static void StrR(CodeGenContext context, uint rt, uint rn, uint rm, uint sType, uint imm5, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, rm, sType, imm5, p, u, w, isStore: true, context.Arm64Assembler.StrRiUn, context.Arm64Assembler.Stur); + } + + public static void StrbI(CodeGenContext context, uint rt, uint rn, int imm, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, imm, 0, p, u, w, isStore: true, context.Arm64Assembler.StrbRiUn, context.Arm64Assembler.Sturb); + } + + public static void StrbR(CodeGenContext context, uint rt, uint rn, uint rm, uint sType, uint imm5, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, rm, sType, imm5, p, u, w, isStore: true, context.Arm64Assembler.StrbRiUn, context.Arm64Assembler.Sturb); + } + + public static void StrbtI(CodeGenContext context, uint rt, uint rn, int imm, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, imm, 0, !postIndex, u, false, isStore: true, context.Arm64Assembler.StrbRiUn, context.Arm64Assembler.Sturb); + } + + public static void StrbtR(CodeGenContext context, uint rt, uint rn, uint rm, uint sType, uint imm5, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, rm, sType, imm5, !postIndex, u, false, isStore: true, context.Arm64Assembler.StrbRiUn, context.Arm64Assembler.Sturb); + } + + public static void StrdI(CodeGenContext context, uint rt, uint rt2, uint rn, uint imm, bool p, bool u, bool w) + { + EmitMemoryDWordInstructionI(context, rt, rt2, rn, imm, p, u, w, isStore: true, context.Arm64Assembler.StpRiUn); + } + + public static void StrdR(CodeGenContext context, uint rt, uint rt2, uint rn, uint rm, bool p, bool u, bool w) + { + EmitMemoryDWordInstructionR(context, rt, rt2, rn, rm, p, u, w, isStore: true, context.Arm64Assembler.StpRiUn); + } + + public static void Strex(CodeGenContext context, uint rd, uint rt, uint rn) + { + EmitMemoryStrexInstruction(context, rd, rt, rn, context.Arm64Assembler.Stlxr); + } + + public static void Strexb(CodeGenContext context, uint rd, uint rt, uint rn) + { + EmitMemoryStrexInstruction(context, rd, rt, rn, context.Arm64Assembler.Stlxrb); + } + + public static void Strexd(CodeGenContext context, uint rd, uint rt, uint rt2, uint rn) + { + EmitMemoryDWordStrexInstruction(context, rd, rt, rt2, rn, context.Arm64Assembler.Stlxp); + } + + public static void Strexh(CodeGenContext context, uint rd, uint rt, uint rn) + { + EmitMemoryStrexInstruction(context, rd, rt, rn, context.Arm64Assembler.Stlxrh); + } + + public static void StrhI(CodeGenContext context, uint rt, uint rn, int imm, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, imm, 1, p, u, w, isStore: true, context.Arm64Assembler.StrhRiUn, context.Arm64Assembler.Sturh); + } + + public static void StrhR(CodeGenContext context, uint rt, uint rn, uint rm, uint sType, uint imm5, bool p, bool u, bool w) + { + EmitMemoryInstruction(context, rt, rn, rm, sType, imm5, p, u, w, isStore: true, context.Arm64Assembler.StrhRiUn, context.Arm64Assembler.Sturh); + } + + public static void StrhtI(CodeGenContext context, uint rt, uint rn, int imm, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, imm, 1, !postIndex, u, false, isStore: true, context.Arm64Assembler.StrhRiUn, context.Arm64Assembler.Sturh); + } + + public static void StrhtR(CodeGenContext context, uint rt, uint rn, uint rm, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, rm, 0, 0, !postIndex, u, false, isStore: true, context.Arm64Assembler.StrhRiUn, context.Arm64Assembler.Sturh); + } + + public static void StrtI(CodeGenContext context, uint rt, uint rn, int imm, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, imm, 2, !postIndex, u, false, isStore: true, context.Arm64Assembler.StrRiUn, context.Arm64Assembler.Stur); + } + + public static void StrtR(CodeGenContext context, uint rt, uint rn, uint rm, uint sType, uint imm5, bool postIndex, bool u) + { + EmitMemoryInstruction(context, rt, rn, rm, sType, imm5, !postIndex, u, false, isStore: true, context.Arm64Assembler.StrRiUn, context.Arm64Assembler.Stur); + } + + private static void EmitMemoryMultipleDaInstruction( + CodeGenContext context, + uint rn, + uint registerList, + bool w, + bool isStore, + Action<Operand, Operand, int> writeInst, + Action<Operand, Operand, Operand, int> writeInstPair) + { + Operand baseAddress = InstEmitCommon.GetInputGpr(context, rn); + Operand offset; + + if (registerList != 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + offset = InstEmitCommon.Const(BitOperations.PopCount(registerList) * 4 - 4); + + WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, baseAddress, offset, false, ArmShiftType.Lsl, 0); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); + + EmitMemoryMultipleInstructionCore( + context, + tempRegister.Operand, + registerList, + isStore, + writeInst, + writeInstPair); + } + + if (w) + { + offset = InstEmitCommon.Const(BitOperations.PopCount(registerList) * 4); + + WriteAddShiftOffset(context.Arm64Assembler, baseAddress, baseAddress, offset, false, ArmShiftType.Lsl, 0); + } + } + + private static void EmitMemoryMultipleDbInstruction( + CodeGenContext context, + uint rn, + uint registerList, + bool w, + bool isStore, + Action<Operand, Operand, int> writeInst, + Action<Operand, Operand, Operand, int> writeInstPair) + { + Operand baseAddress = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand offset = InstEmitCommon.Const(BitOperations.PopCount(registerList) * 4); + + bool writesToRn = (registerList & (1u << (int)rn)) != 0; + + if (w && !writesToRn) + { + WriteAddShiftOffset(context.Arm64Assembler, baseAddress, baseAddress, offset, false, ArmShiftType.Lsl, 0); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); + } + else + { + WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, baseAddress, offset, false, ArmShiftType.Lsl, 0); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); + } + + EmitMemoryMultipleInstructionCore( + context, + tempRegister.Operand, + registerList, + isStore, + writeInst, + writeInstPair); + + if (w && writesToRn) + { + WriteAddShiftOffset(context.Arm64Assembler, baseAddress, baseAddress, offset, false, ArmShiftType.Lsl, 0); + } + } + + private static void EmitMemoryMultipleIbInstruction( + CodeGenContext context, + uint rn, + uint registerList, + bool w, + bool isStore, + Action<Operand, Operand, int> writeInst, + Action<Operand, Operand, Operand, int> writeInstPair) + { + Operand baseAddress = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand offset = InstEmitCommon.Const(4); + + WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, baseAddress, offset, true, ArmShiftType.Lsl, 0); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); + + EmitMemoryMultipleInstructionCore( + context, + tempRegister.Operand, + registerList, + isStore, + writeInst, + writeInstPair); + + if (w) + { + offset = InstEmitCommon.Const(BitOperations.PopCount(registerList) * 4); + + WriteAddShiftOffset(context.Arm64Assembler, baseAddress, baseAddress, offset, true, ArmShiftType.Lsl, 0); + } + } + + private static void EmitMemoryMultipleInstructionCore( + CodeGenContext context, + Operand baseAddress, + uint registerList, + bool isStore, + Action<Operand, Operand, int> writeInst, + Action<Operand, Operand, Operand, int> writeInstPair) + { + uint registers = registerList; + int offs = 0; + + while (registers != 0) + { + int regIndex = BitOperations.TrailingZeroCount(registers); + + registers &= ~(1u << regIndex); + + Operand rt = isStore + ? InstEmitCommon.GetInputGpr(context, (uint)regIndex) + : InstEmitCommon.GetOutputGpr(context, (uint)regIndex); + + int regIndex2 = BitOperations.TrailingZeroCount(registers); + if (regIndex2 < 32) + { + registers &= ~(1u << regIndex2); + + Operand rt2 = isStore + ? InstEmitCommon.GetInputGpr(context, (uint)regIndex2) + : InstEmitCommon.GetOutputGpr(context, (uint)regIndex2); + + writeInstPair(rt, rt2, baseAddress, offs); + + offs += 8; + } + else + { + writeInst(rt, baseAddress, offs); + + offs += 4; + } + } + } + + private static void EmitMemoryInstruction( + CodeGenContext context, + uint rt, + uint rn, + int imm, + int scale, + bool p, + bool u, + bool w, + bool isStore, + Action<Operand, Operand, int> writeInst, + Action<Operand, Operand, int> writeInstUnscaled) + { + Operand rtOperand = isStore ? InstEmitCommon.GetInputGpr(context, rt) : InstEmitCommon.GetOutputGpr(context, rt); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand offset = InstEmitCommon.Const(imm); + + EmitMemoryInstruction(context, writeInst, writeInstUnscaled, rtOperand, rnOperand, offset, scale, p, u, w); + } + + private static void EmitMemoryInstruction( + CodeGenContext context, + uint rt, + uint rn, + uint rm, + uint sType, + uint imm5, + bool p, + bool u, + bool w, + bool isStore, + Action<Operand, Operand, int> writeInst, + Action<Operand, Operand, int> writeInstUnscaled) + { + Operand rtOperand = isStore ? InstEmitCommon.GetInputGpr(context, rt) : InstEmitCommon.GetOutputGpr(context, rt); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + EmitMemoryInstruction(context, writeInst, writeInstUnscaled, rtOperand, rnOperand, rmOperand, 0, p, u, w, (ArmShiftType)sType, (int)imm5); + } + + private static void EmitMemoryInstruction(CodeGenContext context, uint rt, uint rn, bool isStore, Action<Operand, Operand> action) + { + Operand rtOperand = isStore ? InstEmitCommon.GetInputGpr(context, rt) : InstEmitCommon.GetOutputGpr(context, rt); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); + + action(rtOperand, tempRegister.Operand); + } + + private static void EmitMemoryDWordInstruction(CodeGenContext context, uint rt, uint rt2, uint rn, bool isStore, Action<Operand, Operand, Operand> action) + { + Operand rtOperand = isStore ? InstEmitCommon.GetInputGpr(context, rt) : InstEmitCommon.GetOutputGpr(context, rt); + Operand rt2Operand = isStore ? InstEmitCommon.GetInputGpr(context, rt2) : InstEmitCommon.GetOutputGpr(context, rt2); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); + + action(rtOperand, rt2Operand, tempRegister.Operand); + } + + private static void EmitMemoryDWordInstructionI( + CodeGenContext context, + uint rt, + uint rt2, + uint rn, + uint imm, + bool p, + bool u, + bool w, + bool isStore, + Action<Operand, Operand, Operand, int> action) + { + Operand rtOperand = isStore ? InstEmitCommon.GetInputGpr(context, rt) : InstEmitCommon.GetOutputGpr(context, rt); + Operand rt2Operand = isStore ? InstEmitCommon.GetInputGpr(context, rt2) : InstEmitCommon.GetOutputGpr(context, rt2); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand offset = InstEmitCommon.Const((int)imm); + + EmitMemoryDWordInstruction(context, rtOperand, rt2Operand, rnOperand, offset, p, u, w, action); + } + + private static void EmitMemoryDWordInstructionR( + CodeGenContext context, + uint rt, + uint rt2, + uint rn, + uint rm, + bool p, + bool u, + bool w, + bool isStore, + Action<Operand, Operand, Operand, int> action) + { + Operand rtOperand = isStore ? InstEmitCommon.GetInputGpr(context, rt) : InstEmitCommon.GetOutputGpr(context, rt); + Operand rt2Operand = isStore ? InstEmitCommon.GetInputGpr(context, rt2) : InstEmitCommon.GetOutputGpr(context, rt2); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + EmitMemoryDWordInstruction(context, rtOperand, rt2Operand, rnOperand, rmOperand, p, u, w, action); + } + + private static void EmitMemoryDWordInstruction( + CodeGenContext context, + Operand rt, + Operand rt2, + Operand baseAddress, + Operand offset, + bool index, + bool add, + bool wBack, + Action<Operand, Operand, Operand, int> action) + { + Assembler asm = context.Arm64Assembler; + RegisterAllocator regAlloc = context.RegisterAllocator; + + if (index && !wBack) + { + // Offset. + + using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped(); + + int signedOffs = add ? offset.AsInt32() : -offset.AsInt32(); + int offs = 0; + + if (offset.Kind == OperandKind.Constant && offset.Value == 0) + { + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); + } + else if (offset.Kind == OperandKind.Constant && CanFoldDWordOffset(context.MemoryManagerType, signedOffs)) + { + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); + offs = signedOffs; + } + else + { + WriteAddShiftOffset(asm, tempRegister.Operand, baseAddress, offset, add, ArmShiftType.Lsl, 0); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, tempRegister.Operand); + } + + action(rt, rt2, tempRegister.Operand, offs); + } + else if (context.IsThumb ? !index && wBack : !index && !wBack) + { + // Post-indexed. + + using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); + + action(rt, rt2, tempRegister.Operand, 0); + + WriteAddShiftOffset(asm, baseAddress, baseAddress, offset, add, ArmShiftType.Lsl, 0); + } + else if (index && wBack) + { + // Pre-indexed. + + using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped(); + + if (rt.Value == baseAddress.Value) + { + // If Rt and Rn are the same register, ensure we perform the write back after the read/write. + + WriteAddShiftOffset(asm, tempRegister.Operand, baseAddress, offset, add, ArmShiftType.Lsl, 0); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, tempRegister.Operand); + + action(rt, rt2, tempRegister.Operand, 0); + + context.Arm64Assembler.Mov(baseAddress, tempRegister.Operand); + } + else + { + WriteAddShiftOffset(asm, baseAddress, baseAddress, offset, add, ArmShiftType.Lsl, 0); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); + + action(rt, rt2, tempRegister.Operand, 0); + } + } + } + + private static void EmitMemoryStrexInstruction(CodeGenContext context, uint rd, uint rt, uint rn, Action<Operand, Operand, Operand> action) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rtOperand = InstEmitCommon.GetInputGpr(context, rt); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); + + action(rdOperand, rtOperand, tempRegister.Operand); + } + + private static void EmitMemoryDWordStrexInstruction(CodeGenContext context, uint rd, uint rt, uint rt2, uint rn, Action<Operand, Operand, Operand, Operand> action) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rtOperand = InstEmitCommon.GetInputGpr(context, rt); + Operand rt2Operand = InstEmitCommon.GetInputGpr(context, rt2); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); + + action(rdOperand, rtOperand, rt2Operand, tempRegister.Operand); + } + + private static void EmitMemoryInstruction( + CodeGenContext context, + Action<Operand, Operand, int> writeInst, + Action<Operand, Operand, int> writeInstUnscaled, + Operand rt, + Operand baseAddress, + Operand offset, + int scale, + bool index, + bool add, + bool wBack, + ArmShiftType shiftType = ArmShiftType.Lsl, + int shift = 0) + { + Assembler asm = context.Arm64Assembler; + RegisterAllocator regAlloc = context.RegisterAllocator; + + if (index && !wBack) + { + // Offset. + + using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped(); + + int signedOffs = add ? offset.AsInt32() : -offset.AsInt32(); + int offs = 0; + bool unscaled = false; + + if (offset.Kind == OperandKind.Constant && offset.Value == 0) + { + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); + } + else if (offset.Kind == OperandKind.Constant && shift == 0 && CanFoldOffset(context.MemoryManagerType, signedOffs, scale, writeInstUnscaled != null, out unscaled)) + { + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); + offs = signedOffs; + } + else + { + WriteAddShiftOffset(asm, tempRegister.Operand, baseAddress, offset, add, shiftType, shift); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, tempRegister.Operand); + } + + if (unscaled) + { + writeInstUnscaled(rt, tempRegister.Operand, offs); + } + else + { + writeInst(rt, tempRegister.Operand, offs); + } + } + else if (context.IsThumb ? !index && wBack : !index && !wBack) + { + // Post-indexed. + + if (rt.Type == offset.Type && rt.Value == offset.Value) + { + // If Rt and Rm are the same register, we must ensure we add the register offset (Rm) + // before the value is loaded, otherwise we will be adding the wrong value. + + if (rt.Type != baseAddress.Type || rt.Value != baseAddress.Value) + { + using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); + WriteAddShiftOffset(asm, baseAddress, baseAddress, offset, add, shiftType, shift); + + writeInst(rt, tempRegister.Operand, 0); + } + else + { + using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped(); + using ScopedRegister tempRegister2 = regAlloc.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); + WriteAddShiftOffset(asm, tempRegister2.Operand, baseAddress, offset, add, shiftType, shift); + + writeInst(rt, tempRegister.Operand, 0); + + asm.Mov(baseAddress, tempRegister2.Operand); + } + } + else + { + using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); + + writeInst(rt, tempRegister.Operand, 0); + + WriteAddShiftOffset(asm, baseAddress, baseAddress, offset, add, shiftType, shift); + } + } + else if (index && wBack) + { + // Pre-indexed. + + using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped(); + + if (rt.Value == baseAddress.Value) + { + // If Rt and Rn are the same register, ensure we perform the write back after the read/write. + + WriteAddShiftOffset(asm, tempRegister.Operand, baseAddress, offset, add, shiftType, shift); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, tempRegister.Operand); + + writeInst(rt, tempRegister.Operand, 0); + + context.Arm64Assembler.Mov(baseAddress, tempRegister.Operand); + } + else + { + WriteAddShiftOffset(asm, baseAddress, baseAddress, offset, add, shiftType, shift); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); + + writeInst(rt, tempRegister.Operand, 0); + } + } + else + { + Debug.Fail($"Invalid pre-index and write-back combination."); + } + } + + private static void EmitMemoryLiteralInstruction(CodeGenContext context, uint rt, uint imm, int scale, bool p, bool u, bool w, Action<Operand, Operand, int> action) + { + if (!p || w) + { + EmitMemoryInstruction(context, rt, RegisterUtils.PcRegister, (int)imm, scale, p, u, w, isStore: false, action, null); + + return; + } + + Operand rtOperand = InstEmitCommon.GetOutputGpr(context, rt); + uint targetAddress = context.Pc & ~3u; + + if (u) + { + targetAddress += imm; + } + else + { + targetAddress -= imm; + } + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress); + + action(rtOperand, tempRegister.Operand, 0); + } + + private static void EmitMemoryDWordLiteralInstruction(CodeGenContext context, uint rt, uint rt2, uint imm, bool p, bool u, bool w, Action<Operand, Operand, Operand, int> action) + { + if (!p || w) + { + EmitMemoryDWordInstructionI(context, rt, rt2, RegisterUtils.PcRegister, imm, p, u, w, isStore: false, action); + + return; + } + + Operand rtOperand = InstEmitCommon.GetOutputGpr(context, rt); + Operand rt2Operand = InstEmitCommon.GetOutputGpr(context, rt2); + uint targetAddress = context.Pc & ~3u; + + if (u) + { + targetAddress += imm; + } + else + { + targetAddress -= imm; + } + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress); + + action(rtOperand, rt2Operand, tempRegister.Operand, 0); + } + + private static void EmitMemoryPrefetchInstruction(CodeGenContext context, uint rn, uint imm, bool u, PrefetchType type) + { + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + int signedOffs = u ? (int)imm : -(int)imm; + int offs = 0; + bool unscaled = false; + + if (imm == 0) + { + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); + } + else if (CanFoldOffset(context.MemoryManagerType, signedOffs, 3, true, out unscaled)) + { + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); + offs = signedOffs; + } + else + { + WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, rnOperand, InstEmitCommon.Const((int)imm), u, ArmShiftType.Lsl, 0); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); + } + + if (unscaled) + { + context.Arm64Assembler.Prfum(tempRegister.Operand, offs, (uint)type, 0, 0); + } + else + { + context.Arm64Assembler.PrfmI(tempRegister.Operand, offs, (uint)type, 0, 0); + } + } + + private static void EmitMemoryPrefetchInstruction(CodeGenContext context, uint rn, uint rm, bool u, uint sType, uint shift, PrefetchType type) + { + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, rnOperand, rmOperand, u, (ArmShiftType)sType, (int)shift); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); + + context.Arm64Assembler.PrfmI(tempRegister.Operand, 0, (uint)type, 0, 0); + } + + private static void EmitMemoryPrefetchLiteralInstruction(CodeGenContext context, uint imm, bool u, PrefetchType type) + { + uint targetAddress = context.Pc & ~3u; + + if (u) + { + targetAddress += imm; + } + else + { + targetAddress -= imm; + } + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress); + + context.Arm64Assembler.PrfmI(tempRegister.Operand, 0, (uint)type, 0, 0); + } + + public static bool CanFoldOffset(MemoryManagerType mmType, int offset, int scale, bool hasUnscaled, out bool unscaled) + { + if (mmType != MemoryManagerType.HostMappedUnsafe) + { + unscaled = false; + + return false; + } + + int mask = (1 << scale) - 1; + + if ((offset & mask) == 0 && offset >= 0 && offset < 0x1000) + { + // We can use the unsigned, scaled encoding. + + unscaled = false; + + return true; + } + + // Check if we can use the signed, unscaled encoding. + + unscaled = hasUnscaled && offset >= -0x100 && offset < 0x100; + + return unscaled; + } + + private static bool CanFoldDWordOffset(MemoryManagerType mmType, int offset) + { + if (mmType != MemoryManagerType.HostMappedUnsafe) + { + return false; + } + + return offset >= 0 && offset < 0x40 && (offset & 3) == 0; + } + + private static void WriteAddressTranslation(MemoryManagerType mmType, RegisterAllocator regAlloc, in Assembler asm, Operand destination, uint guestAddress) + { + asm.Mov(destination, guestAddress); + + WriteAddressTranslation(mmType, regAlloc, asm, destination, destination); + } + + public static void WriteAddressTranslation(MemoryManagerType mmType, RegisterAllocator regAlloc, in Assembler asm, Operand destination, Operand guestAddress) + { + Operand destination64 = new(destination.Kind, OperandType.I64, destination.Value); + Operand basePointer = new(regAlloc.FixedPageTableRegister, RegisterType.Integer, OperandType.I64); + + if (mmType == MemoryManagerType.HostMapped || mmType == MemoryManagerType.HostMappedUnsafe) + { + // We don't need to mask the address for the safe mode, since it is already naturally limited to 32-bit + // and can never reach out of the guest address space. + + asm.Add(destination64, basePointer, guestAddress); + } + else + { + throw new NotImplementedException(mmType.ToString()); + } + } + + public static void WriteAddShiftOffset(in Assembler asm, Operand rd, Operand rn, Operand offset, bool add, ArmShiftType shiftType, int shift) + { + Debug.Assert(offset.Kind != OperandKind.Constant || offset.AsInt32() >= 0); + + if (shiftType == ArmShiftType.Ror) + { + asm.Ror(rd, rn, InstEmitCommon.Const(shift & 31)); + + if (add) + { + asm.Add(rd, rd, offset, ArmShiftType.Lsl, 0); + } + else + { + asm.Sub(rd, rd, offset, ArmShiftType.Lsl, 0); + } + } + else + { + if (add) + { + asm.Add(rd, rn, offset, shiftType, shift); + } + else + { + asm.Sub(rd, rn, offset, shiftType, shift); + } + } + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMove.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMove.cs new file mode 100644 index 00000000..88850cb3 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMove.cs @@ -0,0 +1,350 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitMove + { + public static void MvnI(CodeGenContext context, uint rd, uint imm, bool immRotated, bool s) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + + if (s) + { + using ScopedRegister flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + if (immRotated) + { + if ((imm & (1u << 31)) != 0) + { + context.Arm64Assembler.Orr(flagsRegister.Operand, flagsRegister.Operand, InstEmitCommon.Const(1 << 29)); + } + else + { + context.Arm64Assembler.Bfc(flagsRegister.Operand, 29, 1); + } + } + + context.Arm64Assembler.Mov(rdOperand, ~imm); + context.Arm64Assembler.Tst(rdOperand, rdOperand); + + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + context.SetNzcvModified(); + } + else + { + context.Arm64Assembler.Mov(rdOperand, ~imm); + } + } + + public static void MvnR(CodeGenContext context, uint rd, uint rm, uint sType, uint imm5, bool s) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + ScopedRegister flagsRegister = default; + + if (s) + { + flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + rmOperand = InstEmitAlu.GetMShiftedByImmediate(context, tempRegister.Operand, rmOperand, imm5, sType, flagsRegister.Operand); + } + else + { + rmOperand = InstEmitAlu.GetMShiftedByImmediate(context, tempRegister.Operand, rmOperand, imm5, sType); + } + + context.Arm64Assembler.Mvn(rdOperand, rmOperand); + + if (s) + { + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + flagsRegister.Dispose(); + + context.SetNzcvModified(); + } + } + + public static void MvnRr(CodeGenContext context, uint rd, uint rm, uint sType, uint rs, bool s) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand rsOperand = InstEmitCommon.GetInputGpr(context, rs); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + ScopedRegister flagsRegister = default; + + if (s) + { + flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + rmOperand = InstEmitAlu.GetMShiftedByReg(context, tempRegister.Operand, rmOperand, rsOperand, sType, flagsRegister.Operand); + } + else + { + rmOperand = InstEmitAlu.GetMShiftedByReg(context, tempRegister.Operand, rmOperand, rsOperand, sType); + } + + context.Arm64Assembler.Mvn(rdOperand, rmOperand); + + if (s) + { + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + flagsRegister.Dispose(); + + context.SetNzcvModified(); + } + } + + public static void MovI(CodeGenContext context, uint rd, uint imm, bool immRotated, bool s) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + + if (s) + { + using ScopedRegister flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + if (immRotated) + { + if ((imm & (1u << 31)) != 0) + { + context.Arm64Assembler.Orr(flagsRegister.Operand, flagsRegister.Operand, InstEmitCommon.Const(2)); + } + else + { + context.Arm64Assembler.Bfc(flagsRegister.Operand, 1, 1); + } + } + + context.Arm64Assembler.Mov(rdOperand, imm); + context.Arm64Assembler.Tst(rdOperand, rdOperand); + + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + context.SetNzcvModified(); + } + else + { + context.Arm64Assembler.Mov(rdOperand, imm); + } + } + + public static void MovR(CodeGenContext context, uint rd, uint rm, uint sType, uint imm5, bool s) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + if (InstEmitAlu.CanShift(sType, imm5) && !s) + { + if (imm5 != 0) + { + switch ((ArmShiftType)sType) + { + case ArmShiftType.Lsl: + context.Arm64Assembler.Lsl(rdOperand, rmOperand, InstEmitCommon.Const((int)imm5)); + break; + case ArmShiftType.Lsr: + context.Arm64Assembler.Lsr(rdOperand, rmOperand, InstEmitCommon.Const((int)imm5)); + break; + case ArmShiftType.Asr: + context.Arm64Assembler.Asr(rdOperand, rmOperand, InstEmitCommon.Const((int)imm5)); + break; + case ArmShiftType.Ror: + context.Arm64Assembler.Ror(rdOperand, rmOperand, InstEmitCommon.Const((int)imm5)); + break; + } + } + else + { + context.Arm64Assembler.Mov(rdOperand, rmOperand); + } + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + ScopedRegister flagsRegister = default; + + if (s) + { + flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + rmOperand = InstEmitAlu.GetMShiftedByImmediate(context, tempRegister.Operand, rmOperand, imm5, sType, flagsRegister.Operand); + } + else + { + rmOperand = InstEmitAlu.GetMShiftedByImmediate(context, tempRegister.Operand, rmOperand, imm5, sType, null); + } + + context.Arm64Assembler.Mov(rdOperand, rmOperand); + + if (s) + { + context.Arm64Assembler.Tst(rdOperand, rdOperand); + + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + flagsRegister.Dispose(); + + context.SetNzcvModified(); + } + } + } + + public static void MovR(CodeGenContext context, uint cond, uint rd, uint rm, uint sType, uint imm5, bool s) + { + if (context.ConsumeSkipNextInstruction()) + { + return; + } + + if ((ArmCondition)cond >= ArmCondition.Al || s) + { + MovR(context, rd, rm, sType, imm5, s); + + return; + } + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + if (InstEmitAlu.CanShift(sType, imm5)) + { + if (imm5 != 0) + { + switch ((ArmShiftType)sType) + { + case ArmShiftType.Lsl: + context.Arm64Assembler.Lsl(tempRegister.Operand, rmOperand, InstEmitCommon.Const((int)imm5)); + break; + case ArmShiftType.Lsr: + context.Arm64Assembler.Lsr(tempRegister.Operand, rmOperand, InstEmitCommon.Const((int)imm5)); + break; + case ArmShiftType.Asr: + context.Arm64Assembler.Asr(tempRegister.Operand, rmOperand, InstEmitCommon.Const((int)imm5)); + break; + case ArmShiftType.Ror: + context.Arm64Assembler.Ror(tempRegister.Operand, rmOperand, InstEmitCommon.Const((int)imm5)); + break; + } + + context.Arm64Assembler.Csel(rdOperand, tempRegister.Operand, rdOperand, (ArmCondition)cond); + } + else + { + Operand other = rdOperand; + + InstInfo nextInstruction = context.PeekNextInstruction(); + + if (nextInstruction.Name == InstName.MovR) + { + // If this instruction is followed by another move with the inverse condition, + // we can just put it into the second operand of the CSEL instruction and skip the next move. + + InstCondb28w4Sb20w1Rdb12w4Imm5b7w5Stypeb5w2Rmb0w4 nextInst = new(nextInstruction.Encoding); + + if (nextInst.Rd == rd && + nextInst.S == 0 && + nextInst.Stype == 0 && + nextInst.Imm5 == 0 && + nextInst.Cond == (cond ^ 1u) && + nextInst.Rm != RegisterUtils.PcRegister) + { + other = InstEmitCommon.GetInputGpr(context, nextInst.Rm); + context.SetSkipNextInstruction(); + } + } + + context.Arm64Assembler.Csel(rdOperand, rmOperand, other, (ArmCondition)cond); + } + } + else + { + rmOperand = InstEmitAlu.GetMShiftedByImmediate(context, tempRegister.Operand, rmOperand, imm5, sType, null); + + context.Arm64Assembler.Csel(rdOperand, rmOperand, rdOperand, (ArmCondition)cond); + } + } + + public static void MovRr(CodeGenContext context, uint rd, uint rm, uint sType, uint rs, bool s) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand rsOperand = InstEmitCommon.GetInputGpr(context, rs); + + if (!s) + { + InstEmitAlu.GetMShiftedByReg(context, rdOperand, rmOperand, rsOperand, sType); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + rmOperand = InstEmitAlu.GetMShiftedByReg(context, tempRegister.Operand, rmOperand, rsOperand, sType, flagsRegister.Operand); + + context.Arm64Assembler.Mov(rdOperand, rmOperand); + context.Arm64Assembler.Tst(rdOperand, rdOperand); + + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + context.SetNzcvModified(); + } + } + + public static void Movt(CodeGenContext context, uint rd, uint imm) + { + Operand rdOperand = InstEmitCommon.GetInputGpr(context, rd); + + context.Arm64Assembler.Movk(rdOperand, (int)imm, 1); + } + + public static void Pkh(CodeGenContext context, uint rd, uint rn, uint rm, bool tb, uint imm5) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + if (!tb && imm5 == 0) + { + context.Arm64Assembler.Extr(rdOperand, rnOperand, rmOperand, 16); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + if (tb) + { + context.Arm64Assembler.Asr(tempRegister.Operand, rmOperand, InstEmitCommon.Const(imm5 == 0 ? 31 : (int)imm5)); + context.Arm64Assembler.Extr(rdOperand, tempRegister.Operand, rnOperand, 16); + } + else + { + context.Arm64Assembler.Lsl(tempRegister.Operand, rmOperand, InstEmitCommon.Const((int)imm5)); + context.Arm64Assembler.Extr(rdOperand, rnOperand, tempRegister.Operand, 16); + } + } + + context.Arm64Assembler.Ror(rdOperand, rdOperand, InstEmitCommon.Const(16)); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMultiply.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMultiply.cs new file mode 100644 index 00000000..042ab815 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMultiply.cs @@ -0,0 +1,603 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using System; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitMultiply + { + public static void Mla(CodeGenContext context, uint rd, uint rn, uint rm, uint ra) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand raOperand = InstEmitCommon.GetInputGpr(context, ra); + + context.Arm64Assembler.Madd(rdOperand, rnOperand, rmOperand, raOperand); + } + + public static void Mls(CodeGenContext context, uint rd, uint rn, uint rm, uint ra) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand raOperand = InstEmitCommon.GetInputGpr(context, ra); + + context.Arm64Assembler.Msub(rdOperand, rnOperand, rmOperand, raOperand); + } + + public static void Mul(CodeGenContext context, uint rd, uint rn, uint rm, bool s) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + if (s) + { + using ScopedRegister flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + context.Arm64Assembler.Mul(rdOperand, rnOperand, rmOperand); + context.Arm64Assembler.Tst(rdOperand, rdOperand); + + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + context.SetNzcvModified(); + } + else + { + context.Arm64Assembler.Mul(rdOperand, rnOperand, rmOperand); + } + } + + public static void Smlabb(CodeGenContext context, uint rd, uint rn, uint rm, uint ra, bool nHigh, bool mHigh) + { + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempA = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand tempM64 = new(OperandKind.Register, OperandType.I64, tempM.Operand.Value); + Operand tempA64 = new(OperandKind.Register, OperandType.I64, tempA.Operand.Value); + + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand raOperand = InstEmitCommon.GetInputGpr(context, ra); + + SelectSignedHalfword(context, tempN.Operand, rnOperand, nHigh); + SelectSignedHalfword(context, tempM.Operand, rmOperand, mHigh); + + context.Arm64Assembler.Sxtw(tempA64, raOperand); + context.Arm64Assembler.Smaddl(tempN.Operand, tempN.Operand, tempM.Operand, tempA64); + + CheckResultOverflow(context, tempM64, tempN.Operand); + + context.Arm64Assembler.Mov(rdOperand, tempN.Operand); + } + + public static void Smlad(CodeGenContext context, uint rd, uint rn, uint rm, uint ra, bool x) + { + EmitSmladSmlsd(context, rd, rn, rm, ra, x, add: true); + } + + public static void Smlal(CodeGenContext context, uint rdLo, uint rdHi, uint rn, uint rm, bool s) + { + EmitMultiplyAddLong(context, context.Arm64Assembler.Smaddl, rdLo, rdHi, rn, rm, s); + } + + public static void Smlalbb(CodeGenContext context, uint rdLo, uint rdHi, uint rn, uint rm, bool nHigh, bool mHigh) + { + Operand rdLoOperand = InstEmitCommon.GetOutputGpr(context, rdLo); + Operand rdHiOperand = InstEmitCommon.GetOutputGpr(context, rdHi); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + Operand rdLoOperand64 = new(OperandKind.Register, OperandType.I64, rdLoOperand.Value); + Operand rdHiOperand64 = new(OperandKind.Register, OperandType.I64, rdHiOperand.Value); + + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempA = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + SelectSignedHalfword(context, tempN.Operand, rnOperand, nHigh); + SelectSignedHalfword(context, tempM.Operand, rmOperand, mHigh); + + Operand tempA64 = new(OperandKind.Register, OperandType.I64, tempA.Operand.Value); + + context.Arm64Assembler.Lsl(tempA64, rdHiOperand64, InstEmitCommon.Const(32)); + context.Arm64Assembler.Orr(tempA64, tempA64, rdLoOperand); + + context.Arm64Assembler.Smaddl(rdLoOperand64, tempN.Operand, tempM.Operand, tempA64); + + if (rdLo != rdHi) + { + context.Arm64Assembler.Lsr(rdHiOperand64, rdLoOperand64, InstEmitCommon.Const(32)); + } + + context.Arm64Assembler.Mov(rdLoOperand, rdLoOperand); // Zero-extend. + } + + public static void Smlald(CodeGenContext context, uint rdLo, uint rdHi, uint rn, uint rm, bool x) + { + EmitSmlaldSmlsld(context, rdLo, rdHi, rn, rm, x, add: true); + } + + public static void Smlawb(CodeGenContext context, uint rd, uint rn, uint rm, uint ra, bool mHigh) + { + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempA = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand tempN64 = new(OperandKind.Register, OperandType.I64, tempN.Operand.Value); + Operand tempM64 = new(OperandKind.Register, OperandType.I64, tempM.Operand.Value); + Operand tempA64 = new(OperandKind.Register, OperandType.I64, tempA.Operand.Value); + + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand raOperand = InstEmitCommon.GetInputGpr(context, ra); + + SelectSignedHalfword(context, tempM.Operand, rmOperand, mHigh); + + context.Arm64Assembler.Sxtw(tempA64, raOperand); + context.Arm64Assembler.Lsl(tempA64, tempA64, InstEmitCommon.Const(16)); + context.Arm64Assembler.Smaddl(tempN.Operand, rnOperand, tempM.Operand, tempA64); + context.Arm64Assembler.Asr(tempN64, tempN64, InstEmitCommon.Const(16)); + + CheckResultOverflow(context, tempM64, tempN.Operand); + + context.Arm64Assembler.Mov(rdOperand, tempN.Operand); + } + + public static void Smlsd(CodeGenContext context, uint rd, uint rn, uint rm, uint ra, bool x) + { + EmitSmladSmlsd(context, rd, rn, rm, ra, x, add: false); + } + + public static void Smlsld(CodeGenContext context, uint rdLo, uint rdHi, uint rn, uint rm, bool x) + { + EmitSmlaldSmlsld(context, rdLo, rdHi, rn, rm, x, add: false); + } + + public static void Smmla(CodeGenContext context, uint rd, uint rn, uint rm, uint ra, bool r) + { + EmitSmmlaSmmls(context, rd, rn, rm, ra, r, add: true); + } + + public static void Smmls(CodeGenContext context, uint rd, uint rn, uint rm, uint ra, bool r) + { + EmitSmmlaSmmls(context, rd, rn, rm, ra, r, add: false); + } + + public static void Smmul(CodeGenContext context, uint rd, uint rn, uint rm, bool r) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + Operand rdOperand64 = new(OperandKind.Register, OperandType.I64, rdOperand.Value); + + context.Arm64Assembler.Smull(rdOperand64, rnOperand, rmOperand); + + if (r) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Mov(tempRegister.Operand, 0x80000000u); + context.Arm64Assembler.Add(rdOperand64, rdOperand64, tempRegister.Operand); + } + + context.Arm64Assembler.Lsr(rdOperand64, rdOperand64, InstEmitCommon.Const(32)); + } + + public static void Smuad(CodeGenContext context, uint rd, uint rn, uint rm, bool x) + { + EmitSmuadSmusd(context, rd, rn, rm, x, add: true); + } + + public static void Smulbb(CodeGenContext context, uint rd, uint rn, uint rm, bool nHigh, bool mHigh) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + Operand rdOperand64 = new(OperandKind.Register, OperandType.I64, rdOperand.Value); + + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + SelectSignedHalfword(context, tempN.Operand, rnOperand, nHigh); + SelectSignedHalfword(context, tempM.Operand, rmOperand, mHigh); + + context.Arm64Assembler.Smull(rdOperand64, tempN.Operand, tempM.Operand); + + context.Arm64Assembler.Mov(rdOperand, rdOperand); // Zero-extend. + } + + public static void Smull(CodeGenContext context, uint rdLo, uint rdHi, uint rn, uint rm, bool s) + { + EmitMultiplyLong(context, context.Arm64Assembler.Smull, rdLo, rdHi, rn, rm, s); + } + + public static void Smulwb(CodeGenContext context, uint rd, uint rn, uint rm, bool mHigh) + { + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand tempN64 = new(OperandKind.Register, OperandType.I64, tempN.Operand.Value); + Operand tempM64 = new(OperandKind.Register, OperandType.I64, tempM.Operand.Value); + + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + SelectSignedHalfword(context, tempM.Operand, rmOperand, mHigh); + + context.Arm64Assembler.Smull(tempN.Operand, rnOperand, tempM.Operand); + context.Arm64Assembler.Asr(tempN64, tempN64, InstEmitCommon.Const(16)); + + CheckResultOverflow(context, tempM64, tempN.Operand); + + context.Arm64Assembler.Mov(rdOperand, tempN.Operand); + } + + public static void Smusd(CodeGenContext context, uint rd, uint rn, uint rm, bool x) + { + EmitSmuadSmusd(context, rd, rn, rm, x, add: false); + } + + public static void Umaal(CodeGenContext context, uint rdLo, uint rdHi, uint rn, uint rm) + { + Operand rdLoOperand = InstEmitCommon.GetOutputGpr(context, rdLo); + Operand rdHiOperand = InstEmitCommon.GetOutputGpr(context, rdHi); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + Operand rdLoOperand64 = new(OperandKind.Register, OperandType.I64, rdLoOperand.Value); + Operand rdHiOperand64 = new(OperandKind.Register, OperandType.I64, rdHiOperand.Value); + + if (rdLo == rdHi) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand tempRegister64 = new(OperandKind.Register, OperandType.I64, tempRegister.Operand.Value); + + context.Arm64Assembler.Umaddl(tempRegister64, rnOperand, rmOperand, rdLoOperand64); + context.Arm64Assembler.Add(rdLoOperand64, tempRegister64, rdHiOperand64); + } + else + { + context.Arm64Assembler.Umaddl(rdLoOperand64, rnOperand, rmOperand, rdLoOperand64); + context.Arm64Assembler.Add(rdLoOperand64, rdLoOperand64, rdHiOperand64); + } + + if (rdLo != rdHi) + { + context.Arm64Assembler.Lsr(rdHiOperand64, rdLoOperand64, InstEmitCommon.Const(32)); + } + + context.Arm64Assembler.Mov(rdLoOperand, rdLoOperand); // Zero-extend. + } + + public static void Umlal(CodeGenContext context, uint rdLo, uint rdHi, uint rn, uint rm, bool s) + { + EmitMultiplyAddLong(context, context.Arm64Assembler.Umaddl, rdLo, rdHi, rn, rm, s); + } + + public static void Umull(CodeGenContext context, uint rdLo, uint rdHi, uint rn, uint rm, bool s) + { + EmitMultiplyLong(context, context.Arm64Assembler.Umull, rdLo, rdHi, rn, rm, s); + } + + private static void EmitMultiplyLong(CodeGenContext context, Action<Operand, Operand, Operand> action, uint rdLo, uint rdHi, uint rn, uint rm, bool s) + { + Operand rdLoOperand = InstEmitCommon.GetOutputGpr(context, rdLo); + Operand rdHiOperand = InstEmitCommon.GetOutputGpr(context, rdHi); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + Operand rdLoOperand64 = new(OperandKind.Register, OperandType.I64, rdLoOperand.Value); + Operand rdHiOperand64 = new(OperandKind.Register, OperandType.I64, rdHiOperand.Value); + + if (s) + { + using ScopedRegister flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + action(rdLoOperand64, rnOperand, rmOperand); + context.Arm64Assembler.Tst(rdLoOperand64, rdLoOperand64); + + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + } + else + { + action(rdLoOperand64, rnOperand, rmOperand); + } + + if (rdLo != rdHi) + { + context.Arm64Assembler.Lsr(rdHiOperand64, rdLoOperand64, InstEmitCommon.Const(32)); + } + + context.Arm64Assembler.Mov(rdLoOperand, rdLoOperand); // Zero-extend. + } + + private static void EmitMultiplyAddLong(CodeGenContext context, Action<Operand, Operand, Operand, Operand> action, uint rdLo, uint rdHi, uint rn, uint rm, bool s) + { + Operand rdLoOperand = InstEmitCommon.GetOutputGpr(context, rdLo); + Operand rdHiOperand = InstEmitCommon.GetOutputGpr(context, rdHi); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + Operand rdLoOperand64 = new(OperandKind.Register, OperandType.I64, rdLoOperand.Value); + Operand rdHiOperand64 = new(OperandKind.Register, OperandType.I64, rdHiOperand.Value); + + using ScopedRegister raRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand raOperand64 = new(OperandKind.Register, OperandType.I64, raRegister.Operand.Value); + + context.Arm64Assembler.Lsl(raOperand64, rdHiOperand64, InstEmitCommon.Const(32)); + context.Arm64Assembler.Orr(raOperand64, raOperand64, rdLoOperand); + + if (s) + { + using ScopedRegister flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + action(rdLoOperand64, rnOperand, rmOperand, raOperand64); + context.Arm64Assembler.Tst(rdLoOperand64, rdLoOperand64); + + InstEmitCommon.RestoreCvFlags(context, flagsRegister.Operand); + + context.SetNzcvModified(); + } + else + { + action(rdLoOperand64, rnOperand, rmOperand, raOperand64); + } + + if (rdLo != rdHi) + { + context.Arm64Assembler.Lsr(rdHiOperand64, rdLoOperand64, InstEmitCommon.Const(32)); + } + + context.Arm64Assembler.Mov(rdLoOperand, rdLoOperand); // Zero-extend. + } + + private static void EmitSmladSmlsd(CodeGenContext context, uint rd, uint rn, uint rm, uint ra, bool x, bool add) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand raOperand = InstEmitCommon.GetInputGpr(context, ra); + + Operand rdOperand64 = new(OperandKind.Register, OperandType.I64, rdOperand.Value); + + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempA = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand tempN64 = new(OperandKind.Register, OperandType.I64, tempN.Operand.Value); + Operand tempM64 = new(OperandKind.Register, OperandType.I64, tempM.Operand.Value); + Operand tempA64 = new(OperandKind.Register, OperandType.I64, tempA.Operand.Value); + + ScopedRegister swapTemp = default; + + if (x) + { + swapTemp = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Ror(swapTemp.Operand, rmOperand, InstEmitCommon.Const(16)); + + rmOperand = swapTemp.Operand; + } + + context.Arm64Assembler.Sxth(tempN64, rnOperand); + context.Arm64Assembler.Sxth(tempM64, rmOperand); + context.Arm64Assembler.Sxtw(tempA64, raOperand); + + context.Arm64Assembler.Mul(rdOperand64, tempN64, tempM64); + + context.Arm64Assembler.Asr(tempN.Operand, rnOperand, InstEmitCommon.Const(16)); + context.Arm64Assembler.Asr(tempM.Operand, rmOperand, InstEmitCommon.Const(16)); + + if (add) + { + context.Arm64Assembler.Smaddl(rdOperand64, tempN.Operand, tempM.Operand, rdOperand64); + } + else + { + context.Arm64Assembler.Smsubl(rdOperand64, tempN.Operand, tempM.Operand, rdOperand64); + } + + context.Arm64Assembler.Add(rdOperand64, rdOperand64, tempA64); + + CheckResultOverflow(context, tempM64, rdOperand64); + + context.Arm64Assembler.Mov(rdOperand, rdOperand); // Zero-extend. + + if (x) + { + swapTemp.Dispose(); + } + } + + private static void EmitSmlaldSmlsld(CodeGenContext context, uint rdLo, uint rdHi, uint rn, uint rm, bool x, bool add) + { + Operand rdLoOperand = InstEmitCommon.GetOutputGpr(context, rdLo); + Operand rdHiOperand = InstEmitCommon.GetOutputGpr(context, rdHi); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + Operand rdLoOperand64 = new(OperandKind.Register, OperandType.I64, rdLoOperand.Value); + Operand rdHiOperand64 = new(OperandKind.Register, OperandType.I64, rdHiOperand.Value); + + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempA = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand tempN64 = new(OperandKind.Register, OperandType.I64, tempN.Operand.Value); + Operand tempM64 = new(OperandKind.Register, OperandType.I64, tempM.Operand.Value); + Operand tempA64 = new(OperandKind.Register, OperandType.I64, tempA.Operand.Value); + + ScopedRegister swapTemp = default; + + if (x) + { + swapTemp = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Ror(swapTemp.Operand, rmOperand, InstEmitCommon.Const(16)); + + rmOperand = swapTemp.Operand; + } + + context.Arm64Assembler.Sxth(tempN64, rnOperand); + context.Arm64Assembler.Sxth(tempM64, rmOperand); + + context.Arm64Assembler.Mul(rdLoOperand64, tempN64, tempM64); + + context.Arm64Assembler.Asr(tempN.Operand, rnOperand, InstEmitCommon.Const(16)); + context.Arm64Assembler.Asr(tempM.Operand, rmOperand, InstEmitCommon.Const(16)); + + if (add) + { + context.Arm64Assembler.Smaddl(rdLoOperand64, tempN.Operand, tempM.Operand, rdLoOperand64); + } + else + { + context.Arm64Assembler.Smsubl(rdLoOperand64, tempN.Operand, tempM.Operand, rdLoOperand64); + } + + context.Arm64Assembler.Lsl(tempA64, rdHiOperand64, InstEmitCommon.Const(32)); + context.Arm64Assembler.Orr(tempA64, tempA64, rdLoOperand); + + context.Arm64Assembler.Add(rdLoOperand64, rdLoOperand64, tempA64); + + if (rdLo != rdHi) + { + context.Arm64Assembler.Lsr(rdHiOperand64, rdLoOperand64, InstEmitCommon.Const(32)); + } + + context.Arm64Assembler.Mov(rdLoOperand, rdLoOperand); // Zero-extend. + + if (x) + { + swapTemp.Dispose(); + } + } + + private static void EmitSmmlaSmmls(CodeGenContext context, uint rd, uint rn, uint rm, uint ra, bool r, bool add) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + Operand raOperand = InstEmitCommon.GetInputGpr(context, ra); + + Operand rdOperand64 = new(OperandKind.Register, OperandType.I64, rdOperand.Value); + Operand raOperand64 = new(OperandKind.Register, OperandType.I64, raOperand.Value); + + using ScopedRegister tempA = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand tempA64 = new(OperandKind.Register, OperandType.I64, tempA.Operand.Value); + + context.Arm64Assembler.Lsl(tempA64, raOperand64, InstEmitCommon.Const(32)); + + if (add) + { + context.Arm64Assembler.Smaddl(rdOperand64, rnOperand, rmOperand, tempA64); + } + else + { + context.Arm64Assembler.Smsubl(rdOperand64, rnOperand, rmOperand, tempA64); + } + + if (r) + { + context.Arm64Assembler.Mov(tempA.Operand, 0x80000000u); + context.Arm64Assembler.Add(rdOperand64, rdOperand64, tempA64); + } + + context.Arm64Assembler.Lsr(rdOperand64, rdOperand64, InstEmitCommon.Const(32)); + } + + private static void EmitSmuadSmusd(CodeGenContext context, uint rd, uint rn, uint rm, bool x, bool add) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + Operand rdOperand64 = new(OperandKind.Register, OperandType.I64, rdOperand.Value); + + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand tempN64 = new(OperandKind.Register, OperandType.I64, tempN.Operand.Value); + Operand tempM64 = new(OperandKind.Register, OperandType.I64, tempM.Operand.Value); + + ScopedRegister swapTemp = default; + + if (x) + { + swapTemp = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Ror(swapTemp.Operand, rmOperand, InstEmitCommon.Const(16)); + + rmOperand = swapTemp.Operand; + } + + context.Arm64Assembler.Sxth(tempN64, rnOperand); + context.Arm64Assembler.Sxth(tempM64, rmOperand); + + context.Arm64Assembler.Mul(rdOperand64, tempN64, tempM64); + + context.Arm64Assembler.Asr(tempN.Operand, rnOperand, InstEmitCommon.Const(16)); + context.Arm64Assembler.Asr(tempM.Operand, rmOperand, InstEmitCommon.Const(16)); + + if (add) + { + context.Arm64Assembler.Smaddl(rdOperand64, tempN.Operand, tempM.Operand, rdOperand64); + } + else + { + context.Arm64Assembler.Smsubl(rdOperand64, tempN.Operand, tempM.Operand, rdOperand64); + } + + context.Arm64Assembler.Mov(rdOperand, rdOperand); // Zero-extend. + + if (x) + { + swapTemp.Dispose(); + } + } + + private static void SelectSignedHalfword(CodeGenContext context, Operand dest, Operand source, bool high) + { + if (high) + { + context.Arm64Assembler.Asr(dest, source, InstEmitCommon.Const(16)); + } + else + { + context.Arm64Assembler.Sxth(dest, source); + } + } + + private static void CheckResultOverflow(CodeGenContext context, Operand temp64, Operand result) + { + context.Arm64Assembler.Sxtw(temp64, result); + context.Arm64Assembler.Sub(temp64, temp64, result); + + int branchIndex = context.CodeWriter.InstructionPointer; + + context.Arm64Assembler.Cbz(temp64, 0); + + // Set Q flag if we had an overflow. + InstEmitSaturate.SetQFlag(context); + + int delta = context.CodeWriter.InstructionPointer - branchIndex; + context.CodeWriter.WriteInstructionAt(branchIndex, context.CodeWriter.ReadInstructionAt(branchIndex) | (uint)((delta & 0x7ffff) << 5)); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonArithmetic.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonArithmetic.cs new file mode 100644 index 00000000..a59f00fc --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonArithmetic.cs @@ -0,0 +1,344 @@ +using System; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonArithmetic + { + public static void Vaba(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, u ? context.Arm64Assembler.Uaba : context.Arm64Assembler.Saba, null); + } + + public static void Vabal(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryLong(context, rd, rn, rm, size, u ? context.Arm64Assembler.Uabal : context.Arm64Assembler.Sabal); + } + + public static void VabdF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FabdV, context.Arm64Assembler.FabdVH); + } + + public static void VabdI(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, u ? context.Arm64Assembler.Uabd : context.Arm64Assembler.Sabd, null); + } + + public static void Vabdl(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryLong(context, rd, rn, rm, size, u ? context.Arm64Assembler.Uabdl : context.Arm64Assembler.Sabdl); + } + + public static void Vabs(CodeGenContext context, uint rd, uint rm, bool f, uint size, uint q) + { + if (f) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FabsSingleAndDouble, context.Arm64Assembler.FabsHalf); + } + else + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.AbsV); + } + } + + public static void VaddF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FaddSingleAndDouble, context.Arm64Assembler.FaddHalf); + } + + public static void VaddI(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, context.Arm64Assembler.AddV, context.Arm64Assembler.AddS); + } + + public static void Vaddhn(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryNarrow(context, rd, rn, rm, size, context.Arm64Assembler.Addhn); + } + + public static void Vaddl(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryLong(context, rd, rn, rm, size, u ? context.Arm64Assembler.Uaddl : context.Arm64Assembler.Saddl); + } + + public static void Vaddw(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryWide(context, rd, rn, rm, size, u ? context.Arm64Assembler.Uaddw : context.Arm64Assembler.Saddw); + } + + public static void VfmaF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryRdF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FmlaVecSingleAndDouble, context.Arm64Assembler.FmlaVecHalf); + } + + public static void VfmsF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryRdF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FmlsVecSingleAndDouble, context.Arm64Assembler.FmlsVecHalf); + } + + public static void Vhadd(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, u ? context.Arm64Assembler.Uhadd : context.Arm64Assembler.Shadd, null); + } + + public static void Vhsub(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, u ? context.Arm64Assembler.Uhsub : context.Arm64Assembler.Shsub, null); + } + + public static void Vmaxnm(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FmaxnmSingleAndDouble, context.Arm64Assembler.FmaxnmHalf); + } + + public static void VmaxF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FmaxSingleAndDouble, context.Arm64Assembler.FmaxHalf); + } + + public static void VmaxI(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, u ? context.Arm64Assembler.Umax : context.Arm64Assembler.Smax, null); + } + + public static void Vminnm(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FminnmSingleAndDouble, context.Arm64Assembler.FminnmHalf); + } + + public static void VminF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FminSingleAndDouble, context.Arm64Assembler.FminHalf); + } + + public static void VminI(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, u ? context.Arm64Assembler.Umin : context.Arm64Assembler.Smin, null); + } + + public static void VmlaF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryMulNegRdF(context, rd, rn, rm, sz, q, negProduct: false); + } + + public static void VmlaI(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryRd(context, rd, rn, rm, size, q, context.Arm64Assembler.MlaVec); + } + + public static void VmlaS(CodeGenContext context, uint rd, uint rn, uint rm, bool f, uint size, uint q) + { + if (f) + { + InstEmitNeonCommon.EmitVectorTernaryMulNegRdByScalarAnyF(context, rd, rn, rm, size, q, negProduct: false); + } + else + { + InstEmitNeonCommon.EmitVectorTernaryRdByScalar(context, rd, rn, rm, size, q, context.Arm64Assembler.MlaElt); + } + } + + public static void VmlalI(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size) + { + InstEmitNeonCommon.EmitVectorTernaryRdLong(context, rd, rn, rm, size, u ? context.Arm64Assembler.UmlalVec : context.Arm64Assembler.SmlalVec); + } + + public static void VmlalS(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size) + { + InstEmitNeonCommon.EmitVectorTernaryRdLongByScalar(context, rd, rn, rm, size, u ? context.Arm64Assembler.UmlalElt : context.Arm64Assembler.SmlalElt); + } + + public static void VmlsF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryMulNegRdF(context, rd, rn, rm, sz, q, negProduct: true); + } + + public static void VmlsI(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryRd(context, rd, rn, rm, size, q, context.Arm64Assembler.MlsVec); + } + + public static void VmlsS(CodeGenContext context, uint rd, uint rn, uint rm, bool f, uint size, uint q) + { + if (f) + { + InstEmitNeonCommon.EmitVectorTernaryMulNegRdByScalarAnyF(context, rd, rn, rm, size, q, negProduct: true); + } + else + { + InstEmitNeonCommon.EmitVectorTernaryRdByScalar(context, rd, rn, rm, size, q, context.Arm64Assembler.MlsElt); + } + } + + public static void VmlslI(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size) + { + InstEmitNeonCommon.EmitVectorTernaryRdLong(context, rd, rn, rm, size, u ? context.Arm64Assembler.UmlslVec : context.Arm64Assembler.SmlslVec); + } + + public static void VmlslS(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size) + { + InstEmitNeonCommon.EmitVectorTernaryRdLongByScalar(context, rd, rn, rm, size, u ? context.Arm64Assembler.UmlslElt : context.Arm64Assembler.SmlslElt); + } + + public static void VmulF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FmulVecSingleAndDouble, context.Arm64Assembler.FmulVecHalf); + } + + public static void VmulI(CodeGenContext context, uint rd, uint rn, uint rm, bool op, uint size, uint q) + { + if (op) + { + // TODO: Feature check, emulation if not supported. + + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, context.Arm64Assembler.Pmul, null); + } + else + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, context.Arm64Assembler.MulVec, null); + } + } + + public static void VmulS(CodeGenContext context, uint rd, uint rn, uint rm, bool f, uint size, uint q) + { + if (f) + { + InstEmitNeonCommon.EmitVectorBinaryByScalarAnyF(context, rd, rn, rm, size, q, context.Arm64Assembler.FmulElt2regElementSingleAndDouble, context.Arm64Assembler.FmulElt2regElementHalf); + } + else + { + InstEmitNeonCommon.EmitVectorBinaryByScalar(context, rd, rn, rm, size, q, context.Arm64Assembler.MulElt); + } + } + + public static void VmullI(CodeGenContext context, uint rd, uint rn, uint rm, bool op, bool u, uint size) + { + if (op) + { + // TODO: Feature check, emulation if not supported. + + InstEmitNeonCommon.EmitVectorBinaryLong(context, rd, rn, rm, size == 2 ? 3 : size, context.Arm64Assembler.Pmull); + } + else + { + InstEmitNeonCommon.EmitVectorBinaryLong(context, rd, rn, rm, size, u ? context.Arm64Assembler.UmullVec : context.Arm64Assembler.SmullVec); + } + } + + public static void VmullS(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryLongByScalar(context, rd, rn, rm, size, u ? context.Arm64Assembler.UmullElt : context.Arm64Assembler.SmullElt); + } + + public static void Vneg(CodeGenContext context, uint rd, uint rm, bool f, uint size, uint q) + { + if (f) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FnegSingleAndDouble, context.Arm64Assembler.FnegHalf); + } + else + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.NegV); + } + } + + public static void Vpadal(CodeGenContext context, uint rd, uint rm, bool op, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryRd(context, rd, rm, size, q, op ? context.Arm64Assembler.Uadalp : context.Arm64Assembler.Sadalp); + } + + public static void VpaddF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FaddpVecSingleAndDouble, context.Arm64Assembler.FaddpVecHalf); + } + + public static void VpaddI(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, context.Arm64Assembler.AddpVec, null); + } + + public static void Vpaddl(CodeGenContext context, uint rd, uint rm, bool op, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, op ? context.Arm64Assembler.Uaddlp : context.Arm64Assembler.Saddlp); + } + + public static void VpmaxF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FmaxpVecSingleAndDouble, context.Arm64Assembler.FmaxpVecHalf); + } + + public static void VpmaxI(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, u ? context.Arm64Assembler.Umaxp : context.Arm64Assembler.Smaxp, null); + } + + public static void VpminF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FminpVecSingleAndDouble, context.Arm64Assembler.FminpVecHalf); + } + + public static void VpminI(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, u ? context.Arm64Assembler.Uminp : context.Arm64Assembler.Sminp, null); + } + + public static void Vrecpe(CodeGenContext context, uint rd, uint rm, bool f, uint size, uint q) + { + if (f) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FrecpeV, context.Arm64Assembler.FrecpeVH); + } + else + { + throw new NotImplementedException(); + } + } + + public static void Vrecps(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FrecpsV, context.Arm64Assembler.FrecpsVH); + } + + public static void Vrsqrte(CodeGenContext context, uint rd, uint rm, bool f, uint size, uint q) + { + if (f) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FrsqrteV, context.Arm64Assembler.FrsqrteVH); + } + else + { + throw new NotImplementedException(); + } + } + + public static void Vrsqrts(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FrsqrtsV, context.Arm64Assembler.FrsqrtsVH); + } + + public static void VsubF(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FsubSingleAndDouble, context.Arm64Assembler.FsubHalf); + } + + public static void VsubI(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, context.Arm64Assembler.SubV, context.Arm64Assembler.SubS); + } + + public static void Vsubhn(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryNarrow(context, rd, rn, rm, size, context.Arm64Assembler.Subhn); + } + + public static void Vsubl(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryLong(context, rd, rn, rm, size, u ? context.Arm64Assembler.Usubl : context.Arm64Assembler.Ssubl); + } + + public static void Vsubw(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryWide(context, rd, rn, rm, size, u ? context.Arm64Assembler.Usubw : context.Arm64Assembler.Ssubw); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonBit.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonBit.cs new file mode 100644 index 00000000..9601f4c2 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonBit.cs @@ -0,0 +1,35 @@ +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonBit + { + public static void Vcls(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.Cls); + } + + public static void Vclz(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.Clz); + } + + public static void Vcnt(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.Cnt); + } + + public static void Vrev16(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.Rev16); + } + + public static void Vrev32(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.Rev32); + } + + public static void Vrev64(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.Rev64); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCommon.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCommon.cs new file mode 100644 index 00000000..dce6556e --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCommon.cs @@ -0,0 +1,1513 @@ + +using Ryujinx.Cpu.LightningJit.CodeGen; +using System; +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonCommon + { + public static ScopedRegister MoveScalarToSide(CodeGenContext context, uint srcReg, bool isFP32, bool forceAllocation = false) + { + int shift = isFP32 ? 2 : 1; + uint mask = isFP32 ? 3u : 1u; + uint elt = srcReg & mask; + + if (elt == 0 && !forceAllocation) + { + return new ScopedRegister(context.RegisterAllocator, context.RegisterAllocator.RemapFpRegister((int)(srcReg >> shift), isFP32), false); + } + + Operand source = context.RegisterAllocator.RemapSimdRegister((int)(srcReg >> shift)); + ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempFpRegisterScoped(isFP32); + + uint imm5 = GetImm5ForElementIndex(elt, isFP32); + + context.Arm64Assembler.DupEltScalarFromElement(tempRegister.Operand, source, imm5); + + return tempRegister; + } + + public static ScopedRegister Move16BitScalarToSide(CodeGenContext context, uint srcReg, bool top = false) + { + uint elt = srcReg & 3; + + Operand source = context.RegisterAllocator.RemapSimdRegister((int)(srcReg >> 2)); + ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempFpRegisterScoped(true); + + uint imm5 = GetImm5ForElementIndex((elt << 1) | (top ? 1u : 0u), 1); + + context.Arm64Assembler.DupEltScalarFromElement(tempRegister.Operand, source, imm5); + + return tempRegister; + } + + public static void MoveScalarToSide(CodeGenContext context, Operand dest, uint srcReg, bool isFP32) + { + int shift = isFP32 ? 2 : 1; + uint mask = isFP32 ? 3u : 1u; + uint elt = srcReg & mask; + + Operand source = context.RegisterAllocator.RemapSimdRegister((int)(srcReg >> shift)); + + uint imm5 = GetImm5ForElementIndex(elt, isFP32); + + context.Arm64Assembler.DupEltScalarFromElement(dest, source, imm5); + } + + public static ScopedRegister MoveScalarToSideIntoGpr(CodeGenContext context, uint srcReg, bool isFP32) + { + int shift = isFP32 ? 2 : 1; + uint mask = isFP32 ? 3u : 1u; + uint elt = srcReg & mask; + + Operand source = context.RegisterAllocator.RemapSimdRegister((int)(srcReg >> shift)); + ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Umov(tempRegister.Operand, source, (int)elt, isFP32 ? 2 : 3); + + return tempRegister; + } + + public static void InsertResult(CodeGenContext context, Operand source, uint dstReg, bool isFP32) + { + int shift = isFP32 ? 2 : 1; + uint mask = isFP32 ? 3u : 1u; + uint elt = dstReg & mask; + + uint imm5 = GetImm5ForElementIndex(elt, isFP32); + + Operand dest = context.RegisterAllocator.RemapSimdRegister((int)(dstReg >> shift)); + + context.Arm64Assembler.InsElt(dest, source, 0, imm5); + } + + public static void Insert16BitResult(CodeGenContext context, Operand source, uint dstReg, bool top = false) + { + uint elt = dstReg & 3u; + + uint imm5 = GetImm5ForElementIndex((elt << 1) | (top ? 1u : 0u), 1); + + Operand dest = context.RegisterAllocator.RemapSimdRegister((int)(dstReg >> 2)); + + context.Arm64Assembler.InsElt(dest, source, 0, imm5); + } + + public static void InsertResultFromGpr(CodeGenContext context, Operand source, uint dstReg, bool isFP32) + { + int shift = isFP32 ? 2 : 1; + uint mask = isFP32 ? 3u : 1u; + uint elt = dstReg & mask; + + uint imm5 = GetImm5ForElementIndex(elt, isFP32); + + Operand dest = context.RegisterAllocator.RemapSimdRegister((int)(dstReg >> shift)); + + context.Arm64Assembler.InsGen(dest, source, imm5); + } + + public static uint GetImm5ForElementIndex(uint elt, bool isFP32) + { + return isFP32 ? (4u | (elt << 3)) : (8u | (elt << 4)); + } + + public static uint GetImm5ForElementIndex(uint elt, uint size) + { + return (1u << (int)size) | (elt << ((int)size + 1)); + } + + public static void EmitScalarUnaryF(CodeGenContext context, uint rd, uint rm, uint size, Action<Operand, Operand, uint> action) + { + Debug.Assert(size == 1 || size == 2 || size == 3); + + bool singleRegs = size != 3; + + using ScopedRegister rmReg = MoveScalarToSide(context, rm, singleRegs); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rmReg); + + action(tempRegister.Operand, rmReg.Operand, size ^ 2u); + + InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + + public static void EmitScalarUnaryF(CodeGenContext context, uint rd, uint rm, uint size, Action<Operand, Operand, uint> action, Action<Operand, Operand> actionHalf) + { + Debug.Assert(size == 1 || size == 2 || size == 3); + + bool singleRegs = size != 3; + + using ScopedRegister rmReg = MoveScalarToSide(context, rm, singleRegs); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rmReg); + + if (size == 1) + { + actionHalf(tempRegister.Operand, rmReg.Operand); + } + else + { + action(tempRegister.Operand, rmReg.Operand, size & 1); + } + + InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + + public static void EmitScalarUnaryToGprTempF( + CodeGenContext context, + uint rd, + uint rm, + uint size, + uint sf, + Action<Operand, Operand, uint, uint> action) + { + Debug.Assert(size == 1 || size == 2 || size == 3); + + bool singleRegs = size != 3; + + using ScopedRegister rmReg = MoveScalarToSide(context, rm, singleRegs); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + action(tempRegister.Operand, rmReg.Operand, size ^ 2u, sf); + + InsertResultFromGpr(context, tempRegister.Operand, rd, sf == 0); + } + + public static void EmitScalarUnaryFromGprTempF( + CodeGenContext context, + uint rd, + uint rm, + uint size, + uint sf, + Action<Operand, Operand, uint, uint> action) + { + Debug.Assert(size == 1 || size == 2 || size == 3); + + bool singleRegs = size != 3; + + using ScopedRegister rmReg = MoveScalarToSideIntoGpr(context, rm, sf == 0); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + action(tempRegister.Operand, rmReg.Operand, size ^ 2u, sf); + + InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + + public static void EmitScalarUnaryFixedF(CodeGenContext context, uint rd, uint rm, uint fbits, uint size, bool is16Bit, Action<Operand, Operand, uint, uint> action) + { + Debug.Assert(size == 1 || size == 2 || size == 3); + + bool singleRegs = size != 3; + + (uint immb, uint immh) = GetImmbImmh(fbits, size); + + using ScopedRegister rmReg = is16Bit ? Move16BitScalarToSide(context, rm) : MoveScalarToSide(context, rm, singleRegs); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rmReg); + + action(tempRegister.Operand, rmReg.Operand, immb, immh); + + InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + + public static void EmitScalarBinaryF(CodeGenContext context, uint rd, uint rn, uint rm, uint size, Action<Operand, Operand, Operand, uint> action) + { + Debug.Assert(size == 1 || size == 2 || size == 3); + + bool singleRegs = size != 3; + + using ScopedRegister rnReg = MoveScalarToSide(context, rn, singleRegs); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, singleRegs); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rnReg, rmReg); + + action(tempRegister.Operand, rnReg.Operand, rmReg.Operand, size ^ 2u); + + InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + + public static void EmitScalarBinaryShift( + CodeGenContext context, + uint rd, + uint rm, + uint shift, + uint size, + bool isShl, + Action<Operand, Operand, uint, uint> action) + { + bool singleRegs = size != 3; + + (uint immb, uint immh) = GetImmbImmhForShift(shift, size, isShl); + + using ScopedRegister rmReg = MoveScalarToSide(context, rm, singleRegs); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rmReg); + + action(tempRegister.Operand, rmReg.Operand, immb, immh); + + InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + + public static void EmitScalarTernaryRdF(CodeGenContext context, uint rd, uint rn, uint rm, uint size, Action<Operand, Operand, Operand, uint> action) + { + Debug.Assert(size == 1 || size == 2 || size == 3); + + bool singleRegs = size != 3; + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + MoveScalarToSide(context, tempRegister.Operand, rd, singleRegs); + + using ScopedRegister rnReg = MoveScalarToSide(context, rn, singleRegs); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, singleRegs); + + action(tempRegister.Operand, rnReg.Operand, rmReg.Operand, size ^ 2u); + + InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + + public static void EmitScalarTernaryRdF( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + Action<Operand, Operand, Operand, Operand, uint> action) + { + Debug.Assert(size == 1 || size == 2 || size == 3); + + bool singleRegs = size != 3; + + using ScopedRegister rdReg = MoveScalarToSide(context, rd, singleRegs); + using ScopedRegister rnReg = MoveScalarToSide(context, rn, singleRegs); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, singleRegs); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rdReg, rnReg, rmReg); + + action(tempRegister.Operand, rnReg.Operand, rmReg.Operand, rdReg.Operand, size ^ 2u); + + InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + + public static void EmitScalarTernaryMulNegRdF( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + bool negD, + bool negProduct) + { + Debug.Assert(size == 1 || size == 2 || size == 3); + + bool singleRegs = size != 3; + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + MoveScalarToSide(context, tempRegister.Operand, rd, singleRegs); + + using ScopedRegister rnReg = MoveScalarToSide(context, rn, singleRegs); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, singleRegs); + + using ScopedRegister productRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + uint ftype = size ^ 2u; + + context.Arm64Assembler.FmulFloat(productRegister.Operand, rnReg.Operand, rmReg.Operand, ftype); + + if (negD) + { + context.Arm64Assembler.FnegFloat(tempRegister.Operand, tempRegister.Operand, ftype); + } + + if (negProduct) + { + context.Arm64Assembler.FnegFloat(productRegister.Operand, productRegister.Operand, ftype); + } + + context.Arm64Assembler.FaddFloat(tempRegister.Operand, tempRegister.Operand, productRegister.Operand, ftype); + + InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + + public static void EmitVectorUnary(CodeGenContext context, uint rd, uint rm, Action<Operand, Operand> action) + { + Debug.Assert(((rd | rm) & 1) == 0); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + action(rdOperand, rmOperand); + } + + public static void EmitVectorUnary(CodeGenContext context, uint rd, uint rm, uint q, Action<Operand, Operand, uint> action) + { + if (q == 0) + { + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rmReg); + + action(tempRegister.Operand, rmReg.Operand, q); + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + action(rdOperand, rmOperand, q); + } + } + + public static void EmitVectorUnary(CodeGenContext context, uint rd, uint rm, uint size, uint q, Action<Operand, Operand, uint, uint> action) + { + Debug.Assert(size < 3); + + if (q == 0) + { + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rmReg); + + action(tempRegister.Operand, rmReg.Operand, size, q); + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + action(rdOperand, rmOperand, size, q); + } + } + + public static void EmitVectorUnaryLong(CodeGenContext context, uint rd, uint rm, uint size, Action<Operand, Operand, uint, uint> action) + { + Debug.Assert((rd & 1) == 0); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + uint q = rm & 1; + + action(rdOperand, rmOperand, size, q); + } + + public static void EmitVectorUnaryNarrow(CodeGenContext context, uint rd, uint rm, uint size, Action<Operand, Operand, uint, uint> action) + { + Debug.Assert((rm & 1) == 0); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + uint q = rd & 1; + + if (q == 0) + { + // Writing to the lower half would clear the higher bits, we don't want that, so use a temp register and move the element. + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + action(tempRegister.Operand, rmOperand, size, q); + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + action(rdOperand, rmOperand, size, q); + } + } + + public static void EmitVectorBinary(CodeGenContext context, uint rd, uint rn, uint rm, Action<Operand, Operand, Operand> action) + { + Debug.Assert(((rd | rn | rm) & 1) == 0); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + action(rdOperand, rnOperand, rmOperand); + } + + public static void EmitVectorBinary(CodeGenContext context, uint rd, uint rn, uint rm, uint q, Action<Operand, Operand, Operand, uint> action) + { + if (q == 0) + { + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rnReg, rmReg); + + action(tempRegister.Operand, rnReg.Operand, rmReg.Operand, q); + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + action(rdOperand, rnOperand, rmOperand, q); + } + } + + public static void EmitVectorBinary( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + uint q, + Action<Operand, Operand, Operand, uint, uint> action, + Action<Operand, Operand, Operand, uint> actionScalar) + { + Debug.Assert(size <= 3); + + if (q == 0) + { + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rnReg, rmReg); + + if (size == 3) + { + actionScalar(tempRegister.Operand, rnReg.Operand, rmReg.Operand, size); + } + else + { + action(tempRegister.Operand, rnReg.Operand, rmReg.Operand, size, q); + } + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + action(rdOperand, rnOperand, rmOperand, size, q); + } + } + + public static void EmitVectorBinaryRd(CodeGenContext context, uint rd, uint rm, uint size, uint q, Action<Operand, Operand, uint, uint> action) + { + Debug.Assert(size < 3); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + MoveScalarToSide(context, tempRegister.Operand, rd, false); + + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + action(tempRegister.Operand, rmReg.Operand, size, q); + + InsertResult(context, tempRegister.Operand, rd, false); + } + + public static void EmitVectorBinaryShift( + CodeGenContext context, + uint rd, + uint rm, + uint shift, + uint size, + uint q, + bool isShl, + Action<Operand, Operand, uint, uint, uint> action, + Action<Operand, Operand, uint, uint> actionScalar) + { + (uint immb, uint immh) = GetImmbImmhForShift(shift, size, isShl); + + if (q == 0) + { + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rmReg); + + if (size == 3) + { + actionScalar(tempRegister.Operand, rmReg.Operand, immb, immh); + } + else + { + action(tempRegister.Operand, rmReg.Operand, immb, immh, q); + } + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + action(rdOperand, rmOperand, immb, immh, q); + } + } + + public static void EmitVectorBinaryLong(CodeGenContext context, uint rd, uint rn, uint rm, uint size, Action<Operand, Operand, Operand, uint, uint> action) + { + Debug.Assert((rd & 1) == 0); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + + if ((rn & 1) == (rm & 1)) + { + // Both inputs are on the same side of the vector, so we can use the variant that selects the half. + + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + uint q = rn & 1; + + action(rdOperand, rnOperand, rmOperand, size, q); + } + else + { + // Inputs are on different sides of the vector, we have to move them. + + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + action(rdOperand, rnReg.Operand, rmReg.Operand, size, 0); + } + } + + public static void EmitVectorBinaryLongShift( + CodeGenContext context, + uint rd, + uint rn, + uint shift, + uint size, + bool isShl, + Action<Operand, Operand, uint, uint, uint> action) + { + (uint immb, uint immh) = GetImmbImmhForShift(shift, size, isShl); + + Debug.Assert((rd & 1) == 0); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + + uint q = rn & 1; + + action(rdOperand, rnOperand, immb, immh, q); + } + + public static void EmitVectorBinaryLongByScalar( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + Action<Operand, Operand, uint, Operand, uint, uint, uint, uint> action) + { + Debug.Assert((rd & 1) == 0); + + (uint h, uint l, uint m) = GetIndexForReg(ref rm, size); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + uint q = rn & 1; + + action(rdOperand, rnOperand, h, rmOperand, m, l, size, q); + } + + public static void EmitVectorBinaryNarrow( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + Action<Operand, Operand, Operand, uint, uint> action) + { + Debug.Assert((rn & 1) == 0); + Debug.Assert((rm & 1) == 0); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + uint q = rd & 1; + + if (q == 0) + { + // Writing to the lower half would clear the higher bits, we don't want that, so use a temp register and move the element. + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + action(tempRegister.Operand, rnOperand, rmOperand, size, q); + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + action(rdOperand, rnOperand, rmOperand, size, q); + } + } + + public static void EmitVectorBinaryNarrowShift( + CodeGenContext context, + uint rd, + uint rm, + uint shift, + uint size, + bool isShl, + Action<Operand, Operand, uint, uint, uint> action) + { + (uint immb, uint immh) = GetImmbImmhForShift(shift, size, isShl); + + Debug.Assert((rm & 1) == 0); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + uint q = rd & 1; + + if (q == 0) + { + // Writing to the lower half would clear the higher bits, we don't want that, so use a temp register and move the element. + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + action(tempRegister.Operand, rmOperand, immb, immh, q); + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + action(rdOperand, rmOperand, immb, immh, q); + } + } + + public static void EmitVectorBinaryWide(CodeGenContext context, uint rd, uint rn, uint rm, uint size, Action<Operand, Operand, Operand, uint, uint> action) + { + Debug.Assert(((rd | rn) & 1) == 0); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + uint q = rm & 1; + + action(rdOperand, rnOperand, rmOperand, size, q); + } + + public static void EmitVectorBinaryByScalar( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + uint q, + Action<Operand, Operand, uint, Operand, uint, uint, uint, uint> action) + { + EmitVectorByScalarCore(context, rd, rn, rm, size, q, action, isTernary: false); + } + + public static void EmitVectorTernaryRd(CodeGenContext context, uint rd, uint rn, uint rm, uint q, Action<Operand, Operand, Operand, uint> action) + { + if (q == 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + MoveScalarToSide(context, tempRegister.Operand, rd, false); + + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + action(tempRegister.Operand, rnReg.Operand, rmReg.Operand, q); + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + action(rdOperand, rnOperand, rmOperand, q); + } + } + + public static void EmitVectorTernaryRd(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q, Action<Operand, Operand, Operand, uint, uint> action) + { + if (q == 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + MoveScalarToSide(context, tempRegister.Operand, rd, false); + + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + action(tempRegister.Operand, rnReg.Operand, rmReg.Operand, size, q); + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + action(rdOperand, rnOperand, rmOperand, size, q); + } + } + + public static void EmitVectorTernaryRdLong(CodeGenContext context, uint rd, uint rn, uint rm, uint size, Action<Operand, Operand, Operand, uint, uint> action) + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + + if ((rn & 1) == (rm & 1)) + { + // Both inputs are on the same side of the vector, so we can use the variant that selects the half. + + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + uint q = rn & 1; + + action(rdOperand, rnOperand, rmOperand, size, q); + } + else + { + // Inputs are on different sides of the vector, we have to move them. + + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + action(rdOperand, rnReg.Operand, rmReg.Operand, size, 0); + } + } + + public static void EmitVectorTernaryRdLongByScalar( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + Action<Operand, Operand, uint, Operand, uint, uint, uint, uint> action) + { + (uint h, uint l, uint m) = GetIndexForReg(ref rm, size); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + uint q = rn & 1; + + action(rdOperand, rnOperand, h, rmOperand, m, l, size, q); + } + + public static void EmitVectorTernaryRdShift( + CodeGenContext context, + uint rd, + uint rm, + uint shift, + uint size, + uint q, + bool isShl, + Action<Operand, Operand, uint, uint, uint> action, + Action<Operand, Operand, uint, uint> actionScalar) + { + (uint immb, uint immh) = GetImmbImmhForShift(shift, size, isShl); + + if (q == 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + MoveScalarToSide(context, tempRegister.Operand, rd, false); + + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + if (size == 3) + { + actionScalar(tempRegister.Operand, rmReg.Operand, immb, immh); + } + else + { + action(tempRegister.Operand, rmReg.Operand, immb, immh, q); + } + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + action(rdOperand, rmOperand, immb, immh, q); + } + } + + public static void EmitVectorTernaryRdByScalar( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + uint q, + Action<Operand, Operand, uint, Operand, uint, uint, uint, uint> action) + { + EmitVectorByScalarCore(context, rd, rn, rm, size, q, action, isTernary: true); + } + + private static void EmitVectorByScalarCore( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + uint q, + Action<Operand, Operand, uint, Operand, uint, uint, uint, uint> action, + bool isTernary) + { + (uint h, uint l, uint m) = GetIndexForReg(ref rm, size); + + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + if (q == 0) + { + if (isTernary) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + MoveScalarToSide(context, tempRegister.Operand, rd, false); + + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + + action(tempRegister.Operand, rnReg.Operand, h, rmOperand, m, l, size, q); + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rnReg); + + action(tempRegister.Operand, rnReg.Operand, h, rmOperand, m, l, size, q); + + InsertResult(context, tempRegister.Operand, rd, false); + } + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + + action(rdOperand, rnOperand, h, rmOperand, m, l, size, q); + } + } + + public static void EmitVectorUnaryF( + CodeGenContext context, + uint rd, + uint rm, + uint sz, + uint q, + Action<Operand, Operand, uint, uint> action, + Action<Operand, Operand, uint> actionHalf) + { + Debug.Assert(sz == 0 || sz == 1); + + if (q == 0) + { + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rmReg); + + if (sz == 1) + { + actionHalf(tempRegister.Operand, rmReg.Operand, q); + } + else + { + action(tempRegister.Operand, rmReg.Operand, 0, q); + } + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + if (sz == 1) + { + actionHalf(rdOperand, rmOperand, q); + } + else + { + action(rdOperand, rmOperand, 0, q); + } + } + } + + public static void EmitVectorUnaryAnyF( + CodeGenContext context, + uint rd, + uint rm, + uint size, + uint q, + Action<Operand, Operand, uint, uint> action, + Action<Operand, Operand, uint> actionHalf) + { + Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size != 3 || q == 1); + + if (q == 0) + { + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rmReg); + + if (size == 1) + { + actionHalf(tempRegister.Operand, rmReg.Operand, q); + } + else + { + action(tempRegister.Operand, rmReg.Operand, size ^ 2u, q); + } + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + if (size == 1) + { + actionHalf(rdOperand, rmOperand, q); + } + else + { + action(rdOperand, rmOperand, size ^ 2u, q); + } + } + } + + public static void EmitVectorUnaryFixedAnyF( + CodeGenContext context, + uint rd, + uint rm, + uint fbits, + uint size, + uint q, + Action<Operand, Operand, uint, uint, uint> action) + { + Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size != 3 || q == 1); + + (uint immb, uint immh) = GetImmbImmh(fbits, size); + + if (q == 0) + { + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rmReg); + + action(tempRegister.Operand, rmReg.Operand, immb, immh, q); + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + action(rdOperand, rmOperand, immb, immh, q); + } + } + + public static void EmitVectorBinaryF( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint sz, + uint q, + Action<Operand, Operand, Operand, uint, uint> action, + Action<Operand, Operand, Operand, uint> actionHalf) + { + Debug.Assert(sz == 0 || sz == 1); + + if (q == 0) + { + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rnReg, rmReg); + + if (sz == 1) + { + actionHalf(tempRegister.Operand, rnReg.Operand, rmReg.Operand, q); + } + else + { + action(tempRegister.Operand, rnReg.Operand, rmReg.Operand, 0, q); + } + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + if (sz == 1) + { + actionHalf(rdOperand, rnOperand, rmOperand, q); + } + else + { + action(rdOperand, rnOperand, rmOperand, 0, q); + } + } + } + + public static void EmitVectorBinaryByScalarAnyF( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + uint q, + Action<Operand, Operand, uint, Operand, uint, uint, uint, uint> action, + Action<Operand, Operand, uint, Operand, uint, uint, uint> actionHalf) + { + EmitVectorByScalarAnyFCore(context, rd, rn, rm, size, q, action, actionHalf, isTernary: false); + } + + public static void EmitVectorTernaryRdF( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint sz, + uint q, + Action<Operand, Operand, Operand, uint, uint> action, + Action<Operand, Operand, Operand, uint> actionHalf) + { + Debug.Assert(sz == 0 || sz == 1); + + if (q == 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + MoveScalarToSide(context, tempRegister.Operand, rd, false); + + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + if (sz == 1) + { + actionHalf(tempRegister.Operand, rnReg.Operand, rmReg.Operand, q); + } + else + { + action(tempRegister.Operand, rnReg.Operand, rmReg.Operand, 0, q); + } + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + if (sz == 1) + { + actionHalf(rdOperand, rnOperand, rmOperand, q); + } + else + { + action(rdOperand, rnOperand, rmOperand, 0, q); + } + } + } + + public static void EmitVectorTernaryMulNegRdF( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint sz, + uint q, + bool negProduct) + { + Debug.Assert(sz == 0 || sz == 1); + + if (q == 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + MoveScalarToSide(context, tempRegister.Operand, rd, false); + + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + using ScopedRegister rmReg = MoveScalarToSide(context, rm, false); + + EmitMulNegVector(context, tempRegister.Operand, rnReg.Operand, rmReg.Operand, sz, q, negProduct); + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + EmitMulNegVector(context, rdOperand, rnOperand, rmOperand, sz, q, negProduct); + } + } + + private static void EmitMulNegVector( + CodeGenContext context, + Operand rd, + Operand rn, + Operand rm, + uint sz, + uint q, + bool negProduct) + { + using ScopedRegister productRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + if (sz == 1) + { + context.Arm64Assembler.FmulVecHalf(productRegister.Operand, rn, rm, q); + + if (negProduct) + { + context.Arm64Assembler.FnegHalf(productRegister.Operand, productRegister.Operand, q); + } + + context.Arm64Assembler.FaddHalf(rd, rd, productRegister.Operand, q); + } + else + { + context.Arm64Assembler.FmulVecSingleAndDouble(productRegister.Operand, rn, rm, 0, q); + + if (negProduct) + { + context.Arm64Assembler.FnegSingleAndDouble(productRegister.Operand, productRegister.Operand, 0, q); + } + + context.Arm64Assembler.FaddSingleAndDouble(rd, rd, productRegister.Operand, 0, q); + } + } + + public static void EmitVectorTernaryRdByScalarAnyF( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + uint q, + Action<Operand, Operand, uint, Operand, uint, uint, uint, uint> action, + Action<Operand, Operand, uint, Operand, uint, uint, uint> actionHalf) + { + EmitVectorByScalarAnyFCore(context, rd, rn, rm, size, q, action, actionHalf, isTernary: true); + } + + private static void EmitVectorByScalarAnyFCore( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + uint q, + Action<Operand, Operand, uint, Operand, uint, uint, uint, uint> action, + Action<Operand, Operand, uint, Operand, uint, uint, uint> actionHalf, + bool isTernary) + { + (uint h, uint l, uint m) = GetIndexForReg(ref rm, size); + + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + if (q == 0) + { + if (isTernary) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + MoveScalarToSide(context, tempRegister.Operand, rd, false); + + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + + if (size == 1) + { + actionHalf(tempRegister.Operand, rnReg.Operand, h, rmOperand, m, l, q); + } + else + { + action(tempRegister.Operand, rnReg.Operand, h, rmOperand, m, l, 0, q); + } + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + + using ScopedRegister tempRegister = PickSimdRegister(context.RegisterAllocator, rnReg); + + if (size == 1) + { + actionHalf(tempRegister.Operand, rnReg.Operand, h, rmOperand, m, l, q); + } + else + { + action(tempRegister.Operand, rnReg.Operand, h, rmOperand, m, l, 0, q); + } + + InsertResult(context, tempRegister.Operand, rd, false); + } + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + + if (size == 1) + { + actionHalf(rdOperand, rnOperand, h, rmOperand, m, l, q); + } + else + { + action(rdOperand, rnOperand, h, rmOperand, m, l, 0, q); + } + } + } + + public static void EmitVectorTernaryMulNegRdByScalarAnyF( + CodeGenContext context, + uint rd, + uint rn, + uint rm, + uint size, + uint q, + bool negProduct) + { + (uint h, uint l, uint m) = GetIndexForReg(ref rm, size); + + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + if (q == 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + MoveScalarToSide(context, tempRegister.Operand, rd, false); + + using ScopedRegister rnReg = MoveScalarToSide(context, rn, false); + + EmitMulNegVectorByScalar(context, tempRegister.Operand, rnReg.Operand, rmOperand, h, l, m, size, q, negProduct); + + InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + + EmitMulNegVectorByScalar(context, rdOperand, rnOperand, rmOperand, h, l, m, size, q, negProduct); + } + } + + private static void EmitMulNegVectorByScalar( + CodeGenContext context, + Operand rd, + Operand rn, + Operand rm, + uint h, + uint l, + uint m, + uint sz, + uint q, + bool negProduct) + { + using ScopedRegister productRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + if (sz == 1) + { + context.Arm64Assembler.FmulElt2regElementHalf(productRegister.Operand, rn, h, rm, m, l, q); + + if (negProduct) + { + context.Arm64Assembler.FnegHalf(productRegister.Operand, productRegister.Operand, q); + } + + context.Arm64Assembler.FaddHalf(rd, rd, productRegister.Operand, q); + } + else + { + context.Arm64Assembler.FmulElt2regElementSingleAndDouble(productRegister.Operand, rn, h, rm, m, l, 0, q); + + if (negProduct) + { + context.Arm64Assembler.FnegSingleAndDouble(productRegister.Operand, productRegister.Operand, 0, q); + } + + context.Arm64Assembler.FaddSingleAndDouble(rd, rd, productRegister.Operand, 0, q); + } + } + + private static (uint, uint, uint) GetIndexForReg(ref uint reg, uint size) + { + int shift = (int)(size + 2); + uint index = reg >> shift; + reg &= (1u << shift) - 1; + index |= (reg & 1) << (5 - shift); + + uint h, l, m; + + if (size == 1) + { + Debug.Assert((index >> 3) == 0); + + m = index & 1; + l = (index >> 1) & 1; + h = index >> 2; + } + else + { + Debug.Assert(size == 2); + Debug.Assert((index >> 2) == 0); + + m = 0; + l = index & 1; + h = (index >> 1) & 1; + } + + return (h, l, m); + } + + private static (uint, uint) GetImmbImmh(uint value, uint size) + { + Debug.Assert(value > 0 && value <= (8u << (int)size)); + + uint imm = (8u << (int)size) | ((8u << (int)size) - value); + + Debug.Assert((imm >> 7) == 0); + + uint immb = imm & 7; + uint immh = imm >> 3; + + return (immb, immh); + } + + public static (uint, uint) GetImmbImmhForShift(uint value, uint size, bool isShl) + { + if (isShl) + { + Debug.Assert(value >= 0 && value < (8u << (int)size)); + + uint imm = (8u << (int)size) | (value & (0x3fu >> (int)(3 - size))); + + Debug.Assert((imm >> 7) == 0); + + uint immb = imm & 7; + uint immh = imm >> 3; + + return (immb, immh); + } + else + { + return GetImmbImmh(value, size); + } + } + + public static uint GetSizeFromImm6(uint imm6) + { + if ((imm6 & 0b100000) != 0) + { + return 2; + } + else if ((imm6 & 0b10000) != 0) + { + return 1; + } + else + { + Debug.Assert((imm6 & 0b1000) != 0); + + return 0; + } + } + + public static uint GetSizeFromImm7(uint imm7) + { + if ((imm7 & 0b1000000) != 0) + { + return 3; + } + else if ((imm7 & 0b100000) != 0) + { + return 2; + } + else if ((imm7 & 0b10000) != 0) + { + return 1; + } + else + { + Debug.Assert((imm7 & 0b1000) != 0); + + return 0; + } + } + + public static ScopedRegister PickSimdRegister(RegisterAllocator registerAllocator, ScopedRegister option1) + { + if (option1.IsAllocated) + { + return option1; + } + + return registerAllocator.AllocateTempSimdRegisterScoped(); + } + + public static ScopedRegister PickSimdRegister(RegisterAllocator registerAllocator, ScopedRegister option1, ScopedRegister option2) + { + if (option1.IsAllocated) + { + return option1; + } + else if (option2.IsAllocated) + { + return option2; + } + + return registerAllocator.AllocateTempSimdRegisterScoped(); + } + + public static ScopedRegister PickSimdRegister(RegisterAllocator registerAllocator, ScopedRegister option1, ScopedRegister option2, ScopedRegister option3) + { + if (option1.IsAllocated) + { + return option1; + } + else if (option2.IsAllocated) + { + return option2; + } + else if (option3.IsAllocated) + { + return option3; + } + + return registerAllocator.AllocateTempSimdRegisterScoped(); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCompare.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCompare.cs new file mode 100644 index 00000000..8da99385 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCompare.cs @@ -0,0 +1,126 @@ +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonCompare + { + public static void Vacge(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FacgeV, context.Arm64Assembler.FacgeVH); + } + + public static void Vacgt(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FacgtV, context.Arm64Assembler.FacgtVH); + } + + public static void VceqI(CodeGenContext context, uint rd, uint rm, bool f, uint size, uint q) + { + if (f) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcmeqZeroV, context.Arm64Assembler.FcmeqZeroVH); + } + else + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.CmeqZeroV); + } + } + + public static void VceqR(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, context.Arm64Assembler.CmeqRegV, context.Arm64Assembler.CmeqRegS); + } + + public static void VceqFR(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FcmeqRegV, context.Arm64Assembler.FcmeqRegVH); + } + + public static void VcgeI(CodeGenContext context, uint rd, uint rm, bool f, uint size, uint q) + { + if (f) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcmgeZeroV, context.Arm64Assembler.FcmgeZeroVH); + } + else + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.CmgeZeroV); + } + } + + public static void VcgeR(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary( + context, + rd, + rn, + rm, + size, + q, + u ? context.Arm64Assembler.CmhsV : context.Arm64Assembler.CmgeRegV, + u ? context.Arm64Assembler.CmhsS : context.Arm64Assembler.CmgeRegS); + } + + public static void VcgeFR(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FcmgeRegV, context.Arm64Assembler.FcmgeRegVH); + } + + public static void VcgtI(CodeGenContext context, uint rd, uint rm, bool f, uint size, uint q) + { + if (f) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcmgtZeroV, context.Arm64Assembler.FcmgtZeroVH); + } + else + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.CmgtZeroV); + } + } + + public static void VcgtR(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary( + context, + rd, + rn, + rm, + size, + q, + u ? context.Arm64Assembler.CmhiV : context.Arm64Assembler.CmgtRegV, + u ? context.Arm64Assembler.CmhiS : context.Arm64Assembler.CmgtRegS); + } + + public static void VcgtFR(CodeGenContext context, uint rd, uint rn, uint rm, uint sz, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryF(context, rd, rn, rm, sz, q, context.Arm64Assembler.FcmgtRegV, context.Arm64Assembler.FcmgtRegVH); + } + + public static void VcleI(CodeGenContext context, uint rd, uint rm, bool f, uint size, uint q) + { + if (f) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcmleV, context.Arm64Assembler.FcmleVH); + } + else + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.CmleV); + } + } + + public static void VcltI(CodeGenContext context, uint rd, uint rm, bool f, uint size, uint q) + { + if (f) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcmltV, context.Arm64Assembler.FcmltVH); + } + else + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.CmltV); + } + } + + public static void Vtst(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, context.Arm64Assembler.CmtstV, context.Arm64Assembler.CmtstS); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonConvert.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonConvert.cs new file mode 100644 index 00000000..81fce678 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonConvert.cs @@ -0,0 +1,137 @@ +using System; +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonConvert + { + public static void Vcvta(CodeGenContext context, uint rd, uint rm, bool op, uint size, uint q) + { + if (op) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcvtauV, context.Arm64Assembler.FcvtauVH); + } + else + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcvtasV, context.Arm64Assembler.FcvtasVH); + } + } + + public static void Vcvtm(CodeGenContext context, uint rd, uint rm, bool op, uint size, uint q) + { + if (op) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcvtmuV, context.Arm64Assembler.FcvtmuVH); + } + else + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcvtmsV, context.Arm64Assembler.FcvtmsVH); + } + } + + public static void Vcvtn(CodeGenContext context, uint rd, uint rm, bool op, uint size, uint q) + { + if (op) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcvtnuV, context.Arm64Assembler.FcvtnuVH); + } + else + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcvtnsV, context.Arm64Assembler.FcvtnsVH); + } + } + + public static void Vcvtp(CodeGenContext context, uint rd, uint rm, bool op, uint size, uint q) + { + if (op) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcvtpuV, context.Arm64Assembler.FcvtpuVH); + } + else + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcvtpsV, context.Arm64Assembler.FcvtpsVH); + } + } + + public static void VcvtHs(CodeGenContext context, uint rd, uint rm, bool op) + { + bool halfToSingle = op; + if (halfToSingle) + { + // Half to single. + + InstEmitNeonCommon.EmitVectorUnaryLong(context, rd, rm, 0, context.Arm64Assembler.Fcvtl); + } + else + { + // Single to half. + + InstEmitNeonCommon.EmitVectorUnaryNarrow(context, rd, rm, 0, context.Arm64Assembler.Fcvtn); + } + } + + public static void VcvtIs(CodeGenContext context, uint rd, uint rm, uint op, uint size, uint q) + { + Debug.Assert(op >> 2 == 0); + + bool unsigned = (op & 1) != 0; + bool toInteger = (op >> 1) != 0; + + if (toInteger) + { + if (unsigned) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcvtzuIntV, context.Arm64Assembler.FcvtzuIntVH); + } + else + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FcvtzsIntV, context.Arm64Assembler.FcvtzsIntVH); + } + } + else + { + if (unsigned) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.UcvtfIntV, context.Arm64Assembler.UcvtfIntVH); + } + else + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.ScvtfIntV, context.Arm64Assembler.ScvtfIntVH); + } + } + } + + public static void VcvtXs(CodeGenContext context, uint rd, uint rm, uint imm6, uint op, bool u, uint q) + { + Debug.Assert(op >> 2 == 0); + + bool unsigned = u; + bool toFixed = (op & 1) != 0; + uint size = 1 + (op >> 1); + uint fbits = Math.Clamp(64u - imm6, 1, 8u << (int)size); + + if (toFixed) + { + if (unsigned) + { + InstEmitNeonCommon.EmitVectorUnaryFixedAnyF(context, rd, rm, fbits, size, q, context.Arm64Assembler.FcvtzuFixV); + } + else + { + InstEmitNeonCommon.EmitVectorUnaryFixedAnyF(context, rd, rm, fbits, size, q, context.Arm64Assembler.FcvtzsFixV); + } + } + else + { + if (unsigned) + { + InstEmitNeonCommon.EmitVectorUnaryFixedAnyF(context, rd, rm, fbits, size, q, context.Arm64Assembler.UcvtfFixV); + } + else + { + InstEmitNeonCommon.EmitVectorUnaryFixedAnyF(context, rd, rm, fbits, size, q, context.Arm64Assembler.ScvtfFixV); + } + } + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCrypto.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCrypto.cs new file mode 100644 index 00000000..a36ae82c --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCrypto.cs @@ -0,0 +1,43 @@ +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonCrypto + { + public static void Aesd(CodeGenContext context, uint rd, uint rm, uint size) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(size == 0); + + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, context.Arm64Assembler.Aesd); + } + + public static void Aese(CodeGenContext context, uint rd, uint rm, uint size) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(size == 0); + + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, context.Arm64Assembler.Aese); + } + + public static void Aesimc(CodeGenContext context, uint rd, uint rm, uint size) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(size == 0); + + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, context.Arm64Assembler.Aesimc); + } + + public static void Aesmc(CodeGenContext context, uint rd, uint rm, uint size) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(size == 0); + + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, context.Arm64Assembler.Aesmc); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonHash.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonHash.cs new file mode 100644 index 00000000..57090ac8 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonHash.cs @@ -0,0 +1,97 @@ +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonHash + { + public static void Sha1c(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(q == 1); + + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, context.Arm64Assembler.Sha1c); + } + + public static void Sha1h(CodeGenContext context, uint rd, uint rm, uint size) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(size == 2); + + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, context.Arm64Assembler.Sha1h); + } + + public static void Sha1m(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(q == 1); + + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, context.Arm64Assembler.Sha1m); + } + + public static void Sha1p(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(q == 1); + + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, context.Arm64Assembler.Sha1p); + } + + public static void Sha1su0(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(q == 1); + + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, context.Arm64Assembler.Sha1su0); + } + + public static void Sha1su1(CodeGenContext context, uint rd, uint rm, uint size) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(size == 2); + + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, context.Arm64Assembler.Sha1su1); + } + + public static void Sha256h(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(q == 1); + + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, context.Arm64Assembler.Sha256h); + } + + public static void Sha256h2(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(q == 1); + + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, context.Arm64Assembler.Sha256h2); + } + + public static void Sha256su0(CodeGenContext context, uint rd, uint rm, uint size) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(size == 2); + + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, context.Arm64Assembler.Sha256su0); + } + + public static void Sha256su1(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + // TODO: Feature check, emulation if not supported. + + Debug.Assert(q == 1); + + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, context.Arm64Assembler.Sha256su1); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonLogical.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonLogical.cs new file mode 100644 index 00000000..af2e54cc --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonLogical.cs @@ -0,0 +1,79 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonLogical + { + public static void VandR(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, q, context.Arm64Assembler.And); + } + + public static void VbicI(CodeGenContext context, uint rd, uint cmode, uint imm8, uint q) + { + EmitMovi(context, rd, cmode, imm8, 1, q); + } + + public static void VbicR(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, q, context.Arm64Assembler.BicReg); + } + + public static void VbifR(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryRd(context, rd, rn, rm, q, context.Arm64Assembler.Bif); + } + + public static void VbitR(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryRd(context, rd, rn, rm, q, context.Arm64Assembler.Bit); + } + + public static void VbslR(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryRd(context, rd, rn, rm, q, context.Arm64Assembler.Bsl); + } + + public static void VeorR(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, q, context.Arm64Assembler.Eor); + } + + public static void VornR(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, q, context.Arm64Assembler.Orn); + } + + public static void VorrI(CodeGenContext context, uint rd, uint cmode, uint imm8, uint q) + { + EmitMovi(context, rd, cmode, imm8, 0, q); + } + + public static void VorrR(CodeGenContext context, uint rd, uint rn, uint rm, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, q, context.Arm64Assembler.OrrReg); + } + + private static void EmitMovi(CodeGenContext context, uint rd, uint cmode, uint imm8, uint op, uint q) + { + (uint a, uint b, uint c, uint d, uint e, uint f, uint g, uint h) = InstEmitNeonMove.Split(imm8); + + if (q == 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + InstEmitNeonCommon.MoveScalarToSide(context, tempRegister.Operand, rd, false); + + context.Arm64Assembler.Movi(tempRegister.Operand, h, g, f, e, d, cmode, c, b, a, op, q); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + + context.Arm64Assembler.Movi(rdOperand, h, g, f, e, d, cmode, c, b, a, op, q); + } + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs new file mode 100644 index 00000000..e77dc0a2 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs @@ -0,0 +1,797 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System; +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonMemory + { + public static void Vld11(CodeGenContext context, uint rd, uint rn, uint rm, uint indexAlign, uint size) + { + uint index = indexAlign >> ((int)size + 1); + + EmitMemory1234InstructionCore(context, rn, rm, 1 << (int)size, (address) => + { + EmitMemoryLoad1234SingleInstruction(context, address, rd, index, size, 1, 1, context.Arm64Assembler.Ld1SnglAsNoPostIndex); + }); + } + + public static void Vld1A(CodeGenContext context, uint rd, uint rn, uint rm, uint a, uint t, uint size) + { + EmitMemory1234InstructionCore(context, rn, rm, 1 << (int)size, (address) => + { + EmitMemoryLoad1SingleReplicateInstruction(context, address, rd, size, t + 1, 1, context.Arm64Assembler.Ld1rAsNoPostIndex); + }); + } + + public static void Vld1M(CodeGenContext context, uint rd, uint rn, uint rm, uint registersCount, uint align, uint size) + { + EmitMemory1234InstructionCore(context, rn, rm, 8 * (int)registersCount, (address) => + { + EmitMemoryLoad1234MultipleInstruction(context, address, rd, size, registersCount, 1, context.Arm64Assembler.Ld1MultAsNoPostIndex); + }); + } + + public static void Vld21(CodeGenContext context, uint rd, uint rn, uint rm, uint indexAlign, uint size) + { + uint index = indexAlign >> ((int)size + 1); + uint step = size > 0 && (indexAlign & (1u << (int)size)) != 0 ? 2u : 1u; + + EmitMemory1234InstructionCore(context, rn, rm, 2 * (1 << (int)size), (address) => + { + EmitMemoryLoad1234SingleInstruction(context, address, rd, index, size, 2, step, context.Arm64Assembler.Ld2SnglAsNoPostIndex); + }); + } + + public static void Vld2A(CodeGenContext context, uint rd, uint rn, uint rm, uint a, uint t, uint size) + { + EmitMemory1234InstructionCore(context, rn, rm, 2 * (1 << (int)size), (address) => + { + EmitMemoryLoad234SingleReplicateInstruction(context, address, rd, size, 2, t + 1, context.Arm64Assembler.Ld2rAsNoPostIndex); + }); + } + + public static void Vld2M(CodeGenContext context, uint rd, uint rn, uint rm, uint type, uint align, uint size) + { + uint step = (type & 1) + 1; + + EmitMemory1234InstructionCore(context, rn, rm, 16, (address) => + { + EmitMemoryLoad1234MultipleInstruction(context, address, rd, size, 2, step, context.Arm64Assembler.Ld2MultAsNoPostIndex); + }); + } + + public static void Vld2M(CodeGenContext context, uint rd, uint rn, uint rm, uint align, uint size) + { + EmitMemory1234InstructionCore(context, rn, rm, 32, (address) => + { + EmitMemoryLoad1234Multiple2x2Instruction(context, address, rd, size, context.Arm64Assembler.Ld2MultAsNoPostIndex); + }); + } + + public static void Vld31(CodeGenContext context, uint rd, uint rn, uint rm, uint indexAlign, uint size) + { + uint index = indexAlign >> ((int)size + 1); + uint step = size > 0 && (indexAlign & (1u << (int)size)) != 0 ? 2u : 1u; + + EmitMemory1234InstructionCore(context, rn, rm, 3 * (1 << (int)size), (address) => + { + EmitMemoryLoad1234SingleInstruction(context, address, rd, index, size, 3, step, context.Arm64Assembler.Ld3SnglAsNoPostIndex); + }); + } + + public static void Vld3A(CodeGenContext context, uint rd, uint rn, uint rm, uint a, uint t, uint size) + { + EmitMemory1234InstructionCore(context, rn, rm, 3 * (1 << (int)size), (address) => + { + EmitMemoryLoad234SingleReplicateInstruction(context, address, rd, size, 3, t + 1, context.Arm64Assembler.Ld3rAsNoPostIndex); + }); + } + + public static void Vld3M(CodeGenContext context, uint rd, uint rn, uint rm, uint type, uint align, uint size) + { + uint step = (type & 1) + 1; + + EmitMemory1234InstructionCore(context, rn, rm, 24, (address) => + { + EmitMemoryLoad1234MultipleInstruction(context, address, rd, size, 3, step, context.Arm64Assembler.Ld3MultAsNoPostIndex); + }); + } + + public static void Vld41(CodeGenContext context, uint rd, uint rn, uint rm, uint indexAlign, uint size) + { + uint index = indexAlign >> ((int)size + 1); + uint step = size > 0 && (indexAlign & (1u << (int)size)) != 0 ? 2u : 1u; + + EmitMemory1234InstructionCore(context, rn, rm, 4 * (1 << (int)size), (address) => + { + EmitMemoryLoad1234SingleInstruction(context, address, rd, index, size, 4, step, context.Arm64Assembler.Ld4SnglAsNoPostIndex); + }); + } + + public static void Vld4A(CodeGenContext context, uint rd, uint rn, uint rm, uint a, uint t, uint size) + { + EmitMemory1234InstructionCore(context, rn, rm, 4 * (1 << (int)size), (address) => + { + EmitMemoryLoad234SingleReplicateInstruction(context, address, rd, size, 4, t + 1, context.Arm64Assembler.Ld4rAsNoPostIndex); + }); + } + + public static void Vld4M(CodeGenContext context, uint rd, uint rn, uint rm, uint type, uint align, uint size) + { + uint step = (type & 1) + 1; + + EmitMemory1234InstructionCore(context, rn, rm, 32, (address) => + { + EmitMemoryLoad1234MultipleInstruction(context, address, rd, size, 4, step, context.Arm64Assembler.Ld4MultAsNoPostIndex); + }); + } + + public static void Vldm(CodeGenContext context, uint rd, uint rn, uint registerCount, bool u, bool w, bool singleRegs) + { + EmitMemoryMultipleInstruction(context, rd, rn, registerCount, u, w, singleRegs, isStore: false); + } + + public static void Vldr(CodeGenContext context, uint rd, uint rn, uint imm8, bool u, uint size) + { + EmitMemoryInstruction(context, rd, rn, imm8, u, size, isStore: false); + } + + public static void Vst11(CodeGenContext context, uint rd, uint rn, uint rm, uint indexAlign, uint size) + { + uint index = indexAlign >> ((int)size + 1); + + EmitMemory1234InstructionCore(context, rn, rm, 1 << (int)size, (address) => + { + EmitMemoryStore1234SingleInstruction(context, address, rd, index, size, 1, 1, context.Arm64Assembler.St1SnglAsNoPostIndex); + }); + } + + public static void Vst1M(CodeGenContext context, uint rd, uint rn, uint rm, uint registersCount, uint align, uint size) + { + EmitMemory1234InstructionCore(context, rn, rm, 8 * (int)registersCount, (address) => + { + EmitMemoryStore1234MultipleInstruction(context, address, rd, size, registersCount, 1, context.Arm64Assembler.St1MultAsNoPostIndex); + }); + } + + public static void Vst21(CodeGenContext context, uint rd, uint rn, uint rm, uint indexAlign, uint size) + { + uint index = indexAlign >> ((int)size + 1); + uint step = size > 0 && (indexAlign & (1u << (int)size)) != 0 ? 2u : 1u; + + EmitMemory1234InstructionCore(context, rn, rm, 2 * (1 << (int)size), (address) => + { + EmitMemoryStore1234SingleInstruction(context, address, rd, index, size, 2, step, context.Arm64Assembler.St2SnglAsNoPostIndex); + }); + } + + public static void Vst2M(CodeGenContext context, uint rd, uint rn, uint rm, uint type, uint align, uint size) + { + uint step = (type & 1) + 1; + + EmitMemory1234InstructionCore(context, rn, rm, 16, (address) => + { + EmitMemoryStore1234MultipleInstruction(context, address, rd, size, 2, step, context.Arm64Assembler.St2MultAsNoPostIndex); + }); + } + + public static void Vst2M(CodeGenContext context, uint rd, uint rn, uint rm, uint align, uint size) + { + EmitMemory1234InstructionCore(context, rn, rm, 32, (address) => + { + EmitMemoryStore1234Multiple2x2Instruction(context, address, rd, size, context.Arm64Assembler.St2MultAsNoPostIndex); + }); + } + + public static void Vst31(CodeGenContext context, uint rd, uint rn, uint rm, uint indexAlign, uint size) + { + uint index = indexAlign >> ((int)size + 1); + uint step = size > 0 && (indexAlign & (1u << (int)size)) != 0 ? 2u : 1u; + + EmitMemory1234InstructionCore(context, rn, rm, 3 * (1 << (int)size), (address) => + { + EmitMemoryStore1234SingleInstruction(context, address, rd, index, size, 3, step, context.Arm64Assembler.St3SnglAsNoPostIndex); + }); + } + + public static void Vst3M(CodeGenContext context, uint rd, uint rn, uint rm, uint type, uint align, uint size) + { + uint step = (type & 1) + 1; + + EmitMemory1234InstructionCore(context, rn, rm, 24, (address) => + { + EmitMemoryStore1234MultipleInstruction(context, address, rd, size, 3, step, context.Arm64Assembler.St3MultAsNoPostIndex); + }); + } + + public static void Vst41(CodeGenContext context, uint rd, uint rn, uint rm, uint indexAlign, uint size) + { + uint index = indexAlign >> ((int)size + 1); + uint step = size > 0 && (indexAlign & (1u << (int)size)) != 0 ? 2u : 1u; + + EmitMemory1234InstructionCore(context, rn, rm, 4 * (1 << (int)size), (address) => + { + EmitMemoryStore1234SingleInstruction(context, address, rd, index, size, 4, step, context.Arm64Assembler.St4SnglAsNoPostIndex); + }); + } + + public static void Vst4M(CodeGenContext context, uint rd, uint rn, uint rm, uint type, uint align, uint size) + { + uint step = (type & 1) + 1; + + EmitMemory1234InstructionCore(context, rn, rm, 32, (address) => + { + EmitMemoryStore1234MultipleInstruction(context, address, rd, size, 4, step, context.Arm64Assembler.St4MultAsNoPostIndex); + }); + } + + public static void Vstm(CodeGenContext context, uint rd, uint rn, uint registerCount, bool u, bool w, bool singleRegs) + { + EmitMemoryMultipleInstruction(context, rd, rn, registerCount, u, w, singleRegs, isStore: true); + } + + public static void Vstr(CodeGenContext context, uint rd, uint rn, uint imm8, bool u, uint size) + { + EmitMemoryInstruction(context, rd, rn, imm8, u, size, isStore: true); + } + + private static void EmitMemoryMultipleInstruction( + CodeGenContext context, + uint rd, + uint rn, + uint registerCount, + bool add, + bool wBack, + bool singleRegs, + bool isStore) + { + Operand baseAddress = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand offset = InstEmitCommon.Const((int)registerCount * (singleRegs ? 4 : 8)); + + if (!add) + { + if (wBack) + { + InstEmitMemory.WriteAddShiftOffset(context.Arm64Assembler, baseAddress, baseAddress, offset, false, ArmShiftType.Lsl, 0); + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); + } + else + { + InstEmitMemory.WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, baseAddress, offset, false, ArmShiftType.Lsl, 0); + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); + } + } + else + { + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); + } + + EmitMemoryMultipleInstructionCore(context, tempRegister.Operand, rd, registerCount, singleRegs, isStore); + + if (add && wBack) + { + context.Arm64Assembler.Add(baseAddress, baseAddress, offset); + } + } + + private static void EmitMemoryMultipleInstructionCore(CodeGenContext context, Operand baseAddress, uint rd, uint registerCount, bool singleRegs, bool isStore) + { + int offs = 0; + uint r = rd; + uint upperBound = Math.Min(rd + registerCount, 32u); + uint regMask = singleRegs ? 3u : 1u; + + // Read/write misaligned elements first. + + for (; (r & regMask) != 0 && r < upperBound; r++) + { + EmitMemoryInstruction(context, baseAddress, r, offs, singleRegs, isStore); + + offs += singleRegs ? 4 : 8; + } + + // Read/write aligned, full vectors. + + while (upperBound - r >= (singleRegs ? 4 : 2)) + { + int qIndex = (int)(r >> (singleRegs ? 2 : 1)); + + Operand rtOperand = context.RegisterAllocator.RemapSimdRegister(qIndex); + + if (upperBound - r >= (singleRegs ? 8 : 4) && (offs & 0xf) == 0) + { + Operand rt2Operand = context.RegisterAllocator.RemapSimdRegister(qIndex + 1); + + if (isStore) + { + context.Arm64Assembler.StpRiUn(rtOperand, rt2Operand, baseAddress, offs); + } + else + { + context.Arm64Assembler.LdpRiUn(rtOperand, rt2Operand, baseAddress, offs); + } + + r += singleRegs ? 8u : 4u; + offs += 32; + } + else + { + if ((offs & 0xf) == 0) + { + if (isStore) + { + context.Arm64Assembler.StrRiUn(rtOperand, baseAddress, offs); + } + else + { + context.Arm64Assembler.LdrRiUn(rtOperand, baseAddress, offs); + } + } + else + { + if (isStore) + { + context.Arm64Assembler.Stur(rtOperand, baseAddress, offs); + } + else + { + context.Arm64Assembler.Ldur(rtOperand, baseAddress, offs); + } + } + + r += singleRegs ? 4u : 2u; + offs += 16; + } + } + + // Read/write last misaligned elements. + + for (; r < upperBound; r++) + { + EmitMemoryInstruction(context, baseAddress, r, offs, singleRegs, isStore); + + offs += singleRegs ? 4 : 8; + } + } + + private static void EmitMemoryInstruction(CodeGenContext context, Operand baseAddress, uint r, int offs, bool singleRegs, bool isStore) + { + if (isStore) + { + using ScopedRegister tempRegister = InstEmitNeonCommon.MoveScalarToSide(context, r, singleRegs); + + context.Arm64Assembler.StrRiUn(tempRegister.Operand, baseAddress, offs); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempFpRegisterScoped(singleRegs); + + context.Arm64Assembler.LdrRiUn(tempRegister.Operand, baseAddress, offs); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, r, singleRegs); + } + } + + private static void EmitMemoryInstruction(CodeGenContext context, uint rd, uint rn, uint imm8, bool add, uint size, bool isStore) + { + bool singleRegs = size != 3; + int offs = (int)imm8; + + if (size == 1) + { + offs <<= 1; + } + else + { + offs <<= 2; + } + + using ScopedRegister address = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + if (rn == RegisterUtils.PcRegister) + { + if (!add) + { + offs = -offs; + } + + context.Arm64Assembler.Mov(address.Operand, (context.Pc & ~3u) + (uint)offs); + + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, address.Operand, address.Operand); + + offs = 0; + } + else + { + Operand rnOperand = context.RegisterAllocator.RemapGprRegister((int)rn); + + if (InstEmitMemory.CanFoldOffset(context.MemoryManagerType, add ? offs : -offs, (int)size, true, out _)) + { + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, address.Operand, rnOperand); + + if (!add) + { + offs = -offs; + } + } + else + { + InstEmitMemory.WriteAddShiftOffset(context.Arm64Assembler, address.Operand, rnOperand, InstEmitCommon.Const(offs), add, ArmShiftType.Lsl, 0); + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, address.Operand, address.Operand); + + offs = 0; + } + } + + if ((size == 3 && (offs & 7) != 0) || offs < 0) + { + if (isStore) + { + using ScopedRegister tempRegister = InstEmitNeonCommon.MoveScalarToSide(context, rd, singleRegs); + + context.Arm64Assembler.Stur(tempRegister.Operand, address.Operand, offs, size); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempFpRegisterScoped(singleRegs); + + context.Arm64Assembler.Ldur(tempRegister.Operand, address.Operand, offs, size); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + } + else + { + if (isStore) + { + using ScopedRegister tempRegister = InstEmitNeonCommon.MoveScalarToSide(context, rd, singleRegs); + + context.Arm64Assembler.StrRiUn(tempRegister.Operand, address.Operand, offs, size); + } + else + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempFpRegisterScoped(singleRegs); + + context.Arm64Assembler.LdrRiUn(tempRegister.Operand, address.Operand, offs, size); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + } + } + + private static void EmitMemory1234InstructionCore(CodeGenContext context, uint rn, uint rm, int bytes, Action<Operand> callback) + { + bool wBack = rm != RegisterUtils.PcRegister; + bool registerIndex = rm != RegisterUtils.PcRegister && rm != RegisterUtils.SpRegister; + + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + using ScopedRegister address = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, address.Operand, rnOperand); + + callback(address.Operand); + + if (wBack) + { + if (registerIndex) + { + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + context.Arm64Assembler.Add(rnOperand, rnOperand, rmOperand); + } + else + { + context.Arm64Assembler.Add(rnOperand, rnOperand, InstEmitCommon.Const(bytes)); + } + } + } + + private static void EmitMemoryLoad1234SingleInstruction( + CodeGenContext context, + Operand baseAddress, + uint rd, + uint index, + uint size, + uint registerCount, + uint step, + Action<Operand, Operand, uint, uint> action) + { + ScopedRegister[] tempRegisters = AllocateSequentialRegisters(context, (int)registerCount); + + MoveDoublewordsToQuadwordsLower(context, rd, registerCount, step, tempRegisters); + + action(tempRegisters[0].Operand, baseAddress, index, size); + + MoveQuadwordsLowerToDoublewords(context, rd, registerCount, step, tempRegisters); + + FreeSequentialRegisters(tempRegisters); + } + + private static void EmitMemoryLoad1SingleReplicateInstruction( + CodeGenContext context, + Operand baseAddress, + uint rd, + uint size, + uint registerCount, + uint step, + Action<Operand, Operand, uint, uint> action) + { + if ((rd & 1) == 0 && registerCount == 2) + { + action(context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)), baseAddress, size, 1); + } + else + { + uint vecsCount = (registerCount + 1) >> 1; + + ScopedRegister[] tempRegisters = AllocateSequentialRegisters(context, (int)vecsCount); + + action(tempRegisters[0].Operand, baseAddress, size, registerCount > 1 ? 1u : 0u); + + MoveQuadwordsToDoublewords(context, rd, registerCount, step, tempRegisters); + + FreeSequentialRegisters(tempRegisters); + } + } + + private static void EmitMemoryLoad234SingleReplicateInstruction( + CodeGenContext context, + Operand baseAddress, + uint rd, + uint size, + uint registerCount, + uint step, + Action<Operand, Operand, uint, uint> action) + { + ScopedRegister[] tempRegisters = AllocateSequentialRegisters(context, (int)registerCount); + + action(tempRegisters[0].Operand, baseAddress, size, 0u); + + MoveQuadwordsLowerToDoublewords(context, rd, registerCount, step, tempRegisters); + + FreeSequentialRegisters(tempRegisters); + } + + private static void EmitMemoryLoad1234MultipleInstruction( + CodeGenContext context, + Operand baseAddress, + uint rd, + uint size, + uint registerCount, + uint step, + Action<Operand, Operand, uint, uint> action) + { + ScopedRegister[] tempRegisters = AllocateSequentialRegisters(context, (int)registerCount); + + action(tempRegisters[0].Operand, baseAddress, size, 0); + + MoveQuadwordsLowerToDoublewords(context, rd, registerCount, step, tempRegisters); + + FreeSequentialRegisters(tempRegisters); + } + + private static void EmitMemoryLoad1234MultipleInstruction( + CodeGenContext context, + Operand baseAddress, + uint rd, + uint size, + uint registerCount, + uint step, + Action<Operand, Operand, uint, uint, uint> action) + { + ScopedRegister[] tempRegisters = AllocateSequentialRegisters(context, (int)registerCount); + + action(tempRegisters[0].Operand, baseAddress, registerCount, size, 0); + + MoveQuadwordsLowerToDoublewords(context, rd, registerCount, step, tempRegisters); + + FreeSequentialRegisters(tempRegisters); + } + + private static void EmitMemoryLoad1234Multiple2x2Instruction( + CodeGenContext context, + Operand baseAddress, + uint rd, + uint size, + Action<Operand, Operand, uint, uint> action) + { + if ((rd & 1) == 0) + { + action(context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1), 2), baseAddress, size, 1); + } + else + { + ScopedRegister[] tempRegisters = AllocateSequentialRegisters(context, 2); + + action(tempRegisters[0].Operand, baseAddress, size, 1); + + MoveQuadwordsToDoublewords2x2(context, rd, tempRegisters); + + FreeSequentialRegisters(tempRegisters); + } + } + + private static void EmitMemoryStore1234SingleInstruction( + CodeGenContext context, + Operand baseAddress, + uint rd, + uint index, + uint size, + uint registerCount, + uint step, + Action<Operand, Operand, uint, uint> action) + { + ScopedRegister[] tempRegisters = AllocateSequentialRegisters(context, (int)registerCount); + + MoveDoublewordsToQuadwordsLower(context, rd, registerCount, step, tempRegisters); + + action(tempRegisters[0].Operand, baseAddress, index, size); + + FreeSequentialRegisters(tempRegisters); + } + + private static void EmitMemoryStore1234MultipleInstruction( + CodeGenContext context, + Operand baseAddress, + uint rd, + uint size, + uint registerCount, + uint step, + Action<Operand, Operand, uint, uint> action) + { + ScopedRegister[] tempRegisters = AllocateSequentialRegisters(context, (int)registerCount); + + MoveDoublewordsToQuadwordsLower(context, rd, registerCount, step, tempRegisters); + + action(tempRegisters[0].Operand, baseAddress, size, 0); + + FreeSequentialRegisters(tempRegisters); + } + + private static void EmitMemoryStore1234MultipleInstruction( + CodeGenContext context, + Operand baseAddress, + uint rd, + uint size, + uint registerCount, + uint step, + Action<Operand, Operand, uint, uint, uint> action) + { + ScopedRegister[] tempRegisters = AllocateSequentialRegisters(context, (int)registerCount); + + MoveDoublewordsToQuadwordsLower(context, rd, registerCount, step, tempRegisters); + + action(tempRegisters[0].Operand, baseAddress, registerCount, size, 0); + + FreeSequentialRegisters(tempRegisters); + } + + private static void EmitMemoryStore1234Multiple2x2Instruction( + CodeGenContext context, + Operand baseAddress, + uint rd, + uint size, + Action<Operand, Operand, uint, uint> action) + { + if ((rd & 1) == 0) + { + action(context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1), 2), baseAddress, size, 1); + } + else + { + ScopedRegister[] tempRegisters = AllocateSequentialRegisters(context, 2); + + MoveDoublewordsToQuadwords2x2(context, rd, tempRegisters); + + action(tempRegisters[0].Operand, baseAddress, size, 1); + + FreeSequentialRegisters(tempRegisters); + } + } + + private static ScopedRegister[] AllocateSequentialRegisters(CodeGenContext context, int count) + { + ScopedRegister[] registers = new ScopedRegister[count]; + + for (int index = 0; index < count; index++) + { + registers[index] = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + } + + AssertSequentialRegisters(registers); + + return registers; + } + + private static void FreeSequentialRegisters(ReadOnlySpan<ScopedRegister> registers) + { + for (int index = 0; index < registers.Length; index++) + { + registers[index].Dispose(); + } + } + + [Conditional("DEBUG")] + private static void AssertSequentialRegisters(ReadOnlySpan<ScopedRegister> registers) + { + for (int index = 1; index < registers.Length; index++) + { + Debug.Assert(registers[index].Operand.GetRegister().Index == registers[0].Operand.GetRegister().Index + index); + } + } + + private static void MoveQuadwordsLowerToDoublewords(CodeGenContext context, uint rd, uint registerCount, uint step, ReadOnlySpan<ScopedRegister> registers) + { + for (int index = 0; index < registerCount; index++) + { + uint r = rd + (uint)index * step; + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(r >> 1)); + uint imm5 = InstEmitNeonCommon.GetImm5ForElementIndex(r & 1u, false); + context.Arm64Assembler.InsElt(rdOperand, registers[index].Operand, 0, imm5); + } + } + + private static void MoveDoublewordsToQuadwordsLower(CodeGenContext context, uint rd, uint registerCount, uint step, ReadOnlySpan<ScopedRegister> registers) + { + for (int index = 0; index < registerCount; index++) + { + uint r = rd + (uint)index * step; + + InstEmitNeonCommon.MoveScalarToSide(context, registers[index].Operand, r, false); + } + } + + private static void MoveDoublewordsToQuadwords2x2(CodeGenContext context, uint rd, ReadOnlySpan<ScopedRegister> registers) + { + for (int index = 0; index < 2; index++) + { + uint r = rd + (uint)index * 2; + uint r2 = r + 1; + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(r >> 1)); + uint imm5 = InstEmitNeonCommon.GetImm5ForElementIndex(0, false); + context.Arm64Assembler.InsElt(registers[index].Operand, rdOperand, (r & 1u) << 3, imm5); + + rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(r2 >> 1)); + imm5 = InstEmitNeonCommon.GetImm5ForElementIndex(1, false); + context.Arm64Assembler.InsElt(registers[index].Operand, rdOperand, (r2 & 1u) << 3, imm5); + } + } + + private static void MoveQuadwordsToDoublewords(CodeGenContext context, uint rd, uint registerCount, uint step, ReadOnlySpan<ScopedRegister> registers) + { + for (int index = 0; index < registerCount; index++) + { + uint r = rd + (uint)index * step; + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(r >> 1)); + uint imm5 = InstEmitNeonCommon.GetImm5ForElementIndex(r & 1u, false); + context.Arm64Assembler.InsElt(rdOperand, registers[index >> 1].Operand, ((uint)index & 1u) << 3, imm5); + } + } + + private static void MoveQuadwordsToDoublewords2x2(CodeGenContext context, uint rd, ReadOnlySpan<ScopedRegister> registers) + { + for (int index = 0; index < 2; index++) + { + uint r = rd + (uint)index * 2; + uint r2 = r + 1; + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(r >> 1)); + uint imm5 = InstEmitNeonCommon.GetImm5ForElementIndex(r & 1u, false); + context.Arm64Assembler.InsElt(rdOperand, registers[index].Operand, 0, imm5); + + rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(r2 >> 1)); + imm5 = InstEmitNeonCommon.GetImm5ForElementIndex(r2 & 1u, false); + context.Arm64Assembler.InsElt(rdOperand, registers[index].Operand, 1u << 3, imm5); + } + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMove.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMove.cs new file mode 100644 index 00000000..08a0673a --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMove.cs @@ -0,0 +1,665 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using System; +using System.Diagnostics; +using System.Numerics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonMove + { + public static void VdupR(CodeGenContext context, uint rd, uint rt, uint b, uint e, uint q) + { + uint size = 2 - (e | (b << 1)); + + Debug.Assert(size < 3); + + Operand rtOperand = InstEmitCommon.GetInputGpr(context, rt); + + uint imm5 = InstEmitNeonCommon.GetImm5ForElementIndex(0, size); + + if (q == 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + context.Arm64Assembler.DupGen(tempRegister.Operand, rtOperand, imm5, q); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Debug.Assert((rd & 1) == 0); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + + context.Arm64Assembler.DupGen(rdOperand, rtOperand, imm5, q); + } + } + + public static void VdupS(CodeGenContext context, uint rd, uint rm, uint imm4, uint q) + { + uint size = (uint)BitOperations.TrailingZeroCount(imm4); + + Debug.Assert(size < 3); + + uint index = imm4 >> (int)(size + 1); + + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + uint imm5 = InstEmitNeonCommon.GetImm5ForElementIndex(index | ((rm & 1) << (int)(3 - size)), size); + + if (q == 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + context.Arm64Assembler.DupEltVectorFromElement(tempRegister.Operand, rmOperand, imm5, q); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Debug.Assert((rd & 1) == 0); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + + context.Arm64Assembler.DupEltVectorFromElement(rdOperand, rmOperand, imm5, q); + } + } + + public static void Vext(CodeGenContext context, uint rd, uint rn, uint rm, uint imm4, uint q) + { + if (q == 0) + { + using ScopedRegister rnReg = InstEmitNeonCommon.MoveScalarToSide(context, rn, false); + using ScopedRegister rmReg = InstEmitNeonCommon.MoveScalarToSide(context, rm, false); + + using ScopedRegister tempRegister = InstEmitNeonCommon.PickSimdRegister(context.RegisterAllocator, rnReg, rmReg); + + context.Arm64Assembler.Ext(tempRegister.Operand, rnReg.Operand, imm4, rmReg.Operand, q); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Debug.Assert(((rd | rn | rm) & 1) == 0); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rnOperand = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + context.Arm64Assembler.Ext(rdOperand, rnOperand, imm4, rmOperand, q); + } + } + + public static void Vmovl(CodeGenContext context, uint rd, uint rm, bool u, uint imm3h) + { + uint size = (uint)BitOperations.TrailingZeroCount(imm3h); + Debug.Assert(size < 3); + + InstEmitNeonCommon.EmitVectorBinaryLongShift( + context, + rd, + rm, + 0, + size, + isShl: true, + u ? context.Arm64Assembler.Ushll : context.Arm64Assembler.Sshll); + } + + public static void Vmovn(CodeGenContext context, uint rd, uint rm, uint size) + { + Debug.Assert(size < 3); + + InstEmitNeonCommon.EmitVectorUnaryNarrow(context, rd, rm, size, context.Arm64Assembler.Xtn); + } + + public static void Vmovx(CodeGenContext context, uint rd, uint rm) + { + InstEmitNeonCommon.EmitScalarBinaryShift(context, rd, rm, 16, 2, isShl: false, context.Arm64Assembler.UshrS); + } + + public static void VmovD(CodeGenContext context, uint rt, uint rt2, uint rm, bool op) + { + Operand rmReg = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + uint top = rm & 1; + uint ftype = top + 1; + + if (op) + { + Operand rtOperand = InstEmitCommon.GetOutputGpr(context, rt); + Operand rt2Operand = InstEmitCommon.GetOutputGpr(context, rt2); + + Operand rtOperand64 = new(OperandKind.Register, OperandType.I64, rtOperand.Value); + Operand rt2Operand64 = new(OperandKind.Register, OperandType.I64, rt2Operand.Value); + + context.Arm64Assembler.FmovFloatGen(rtOperand64, rmReg, ftype, 1, 0, top); + + context.Arm64Assembler.Lsr(rt2Operand64, rtOperand64, InstEmitCommon.Const(32)); + context.Arm64Assembler.Mov(rtOperand, rtOperand); // Zero-extend. + } + else + { + Operand rtOperand = InstEmitCommon.GetInputGpr(context, rt); + Operand rt2Operand = InstEmitCommon.GetInputGpr(context, rt2); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand tempRegister64 = new(OperandKind.Register, OperandType.I64, tempRegister.Operand.Value); + + context.Arm64Assembler.Lsl(tempRegister64, rt2Operand, InstEmitCommon.Const(32)); + context.Arm64Assembler.Orr(tempRegister64, tempRegister64, rtOperand); + + if (top == 0) + { + // Doing FMOV on Rm directly would clear the high bits if we are moving to the bottom. + + using ScopedRegister tempRegister2 = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + context.Arm64Assembler.FmovFloatGen(tempRegister2.Operand, tempRegister64, ftype, 1, 1, top); + + InstEmitNeonCommon.InsertResult(context, tempRegister2.Operand, rm, false); + } + else + { + context.Arm64Assembler.FmovFloatGen(rmReg, tempRegister64, ftype, 1, 1, top); + } + } + } + + public static void VmovH(CodeGenContext context, uint rt, uint rn, bool op) + { + if (op) + { + Operand rtOperand = InstEmitCommon.GetOutputGpr(context, rt); + + using ScopedRegister tempRegister = InstEmitNeonCommon.MoveScalarToSide(context, rn, true); + + context.Arm64Assembler.FmovFloatGen(rtOperand, tempRegister.Operand, 3, 0, 0, 0); + } + else + { + Operand rtOperand = InstEmitCommon.GetInputGpr(context, rt); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + context.Arm64Assembler.FmovFloatGen(tempRegister.Operand, rtOperand, 3, 0, 1, 0); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rn, true); + } + } + + public static void VmovI(CodeGenContext context, uint rd, uint op, uint cmode, uint imm8, uint q) + { + (uint a, uint b, uint c, uint d, uint e, uint f, uint g, uint h) = Split(imm8); + + if (q == 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + context.Arm64Assembler.Movi(tempRegister.Operand, h, g, f, e, d, cmode, c, b, a, op, q); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + + context.Arm64Assembler.Movi(rdOperand, h, g, f, e, d, cmode, c, b, a, op, q); + } + } + + public static void VmovFI(CodeGenContext context, uint rd, uint imm8, uint size) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + context.Arm64Assembler.FmovFloatImm(tempRegister.Operand, imm8, size ^ 2u); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, size != 3); + } + + public static void VmovR(CodeGenContext context, uint rd, uint rm, uint size) + { + bool singleRegister = size == 2; + + int shift = singleRegister ? 2 : 1; + uint mask = singleRegister ? 3u : 1u; + uint dstElt = rd & mask; + uint srcElt = rm & mask; + + uint imm4 = srcElt << (singleRegister ? 2 : 3); + uint imm5 = InstEmitNeonCommon.GetImm5ForElementIndex(dstElt, singleRegister); + + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> shift)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> shift)); + + context.Arm64Assembler.InsElt(rdOperand, rmOperand, imm4, imm5); + } + + public static void VmovRs(CodeGenContext context, uint rd, uint rt, uint opc1, uint opc2) + { + uint index; + uint size; + + if ((opc1 & 2u) != 0) + { + index = opc2 | ((opc1 & 1u) << 2); + size = 0; + } + else if ((opc2 & 1u) != 0) + { + index = (opc2 >> 1) | ((opc1 & 1u) << 1); + size = 1; + } + else + { + Debug.Assert(opc1 == 0 || opc1 == 1); + Debug.Assert(opc2 == 0); + + index = opc1 & 1u; + size = 2; + } + + index |= (rd & 1u) << (int)(3 - size); + + Operand rtOperand = InstEmitCommon.GetInputGpr(context, rt); + + Operand rdReg = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + + context.Arm64Assembler.InsGen(rdReg, rtOperand, InstEmitNeonCommon.GetImm5ForElementIndex(index, size)); + } + + public static void VmovS(CodeGenContext context, uint rt, uint rn, bool op) + { + if (op) + { + Operand rtOperand = InstEmitCommon.GetOutputGpr(context, rt); + + using ScopedRegister tempRegister = InstEmitNeonCommon.MoveScalarToSide(context, rn, true); + + context.Arm64Assembler.FmovFloatGen(rtOperand, tempRegister.Operand, 0, 0, 0, 0); + } + else + { + Operand rtOperand = InstEmitCommon.GetInputGpr(context, rt); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + context.Arm64Assembler.FmovFloatGen(tempRegister.Operand, rtOperand, 0, 0, 1, 0); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rn, true); + } + } + + public static void VmovSr(CodeGenContext context, uint rt, uint rn, bool u, uint opc1, uint opc2) + { + uint index; + uint size; + + if ((opc1 & 2u) != 0) + { + index = opc2 | ((opc1 & 1u) << 2); + size = 0; + } + else if ((opc2 & 1u) != 0) + { + index = (opc2 >> 1) | ((opc1 & 1u) << 1); + size = 1; + } + else + { + Debug.Assert(opc1 == 0 || opc1 == 1); + Debug.Assert(opc2 == 0); + Debug.Assert(!u); + + index = opc1 & 1u; + size = 2; + } + + index |= (rn & 1u) << (int)(3 - size); + + Operand rtOperand = InstEmitCommon.GetOutputGpr(context, rt); + + Operand rnReg = context.RegisterAllocator.RemapSimdRegister((int)(rn >> 1)); + + if (u || size > 1) + { + context.Arm64Assembler.Umov(rtOperand, rnReg, (int)index, (int)size); + } + else + { + context.Arm64Assembler.Smov(rtOperand, rnReg, (int)index, (int)size); + } + } + + public static void VmovSs(CodeGenContext context, uint rt, uint rt2, uint rm, bool op) + { + if ((rm & 1) == 0) + { + // If we are moving an aligned pair of single-precision registers, + // we can just move a single double-precision register. + + VmovD(context, rt, rt2, rm >> 1, op); + + return; + } + + if (op) + { + Operand rtOperand = InstEmitCommon.GetOutputGpr(context, rt); + Operand rt2Operand = InstEmitCommon.GetOutputGpr(context, rt2); + + using ScopedRegister rmReg = InstEmitNeonCommon.MoveScalarToSide(context, rm, true); + using ScopedRegister rmReg2 = InstEmitNeonCommon.MoveScalarToSide(context, rm + 1, true); + + context.Arm64Assembler.FmovFloatGen(rtOperand, rmReg.Operand, 0, 0, 0, 0); + context.Arm64Assembler.FmovFloatGen(rt2Operand, rmReg2.Operand, 0, 0, 0, 0); + } + else + { + Operand rtOperand = InstEmitCommon.GetInputGpr(context, rt); + Operand rt2Operand = InstEmitCommon.GetInputGpr(context, rt2); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + context.Arm64Assembler.FmovFloatGen(tempRegister.Operand, rtOperand, 0, 0, 1, 0); + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rm, true); + + context.Arm64Assembler.FmovFloatGen(tempRegister.Operand, rt2Operand, 0, 0, 1, 0); + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rm + 1, true); + } + } + + public static void VmvnI(CodeGenContext context, uint rd, uint cmode, uint imm8, uint q) + { + (uint a, uint b, uint c, uint d, uint e, uint f, uint g, uint h) = Split(imm8); + + if (q == 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + context.Arm64Assembler.Mvni(tempRegister.Operand, h, g, f, e, d, cmode, c, b, a, q); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + + context.Arm64Assembler.Mvni(rdOperand, h, g, f, e, d, cmode, c, b, a, q); + } + } + + public static void VmvnR(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, q, context.Arm64Assembler.Not); + } + + public static void Vswp(CodeGenContext context, uint rd, uint rm, uint q) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + if (q == 0) + { + InstEmitNeonCommon.MoveScalarToSide(context, tempRegister.Operand, rd, false); + using ScopedRegister rmReg = InstEmitNeonCommon.MoveScalarToSide(context, rm, false); + + InstEmitNeonCommon.InsertResult(context, rmReg.Operand, rd, false); + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rm, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + context.Arm64Assembler.Orr(tempRegister.Operand, rdOperand, rdOperand); // Temp = Rd + context.Arm64Assembler.Orr(rdOperand, rmOperand, rmOperand); // Rd = Rm + context.Arm64Assembler.Orr(rmOperand, tempRegister.Operand, tempRegister.Operand); // Rm = Temp + } + } + + public static void Vtbl(CodeGenContext context, uint rd, uint rn, uint rm, bool op, uint len) + { + // On AArch64, TBL/TBX works with 128-bit vectors, while on AArch32 it works with 64-bit vectors. + // We must combine the 64-bit vectors into a larger 128-bit one in some cases. + + // TODO: Peephole optimization to combine adjacent TBL instructions? + + Debug.Assert(len <= 3); + + bool isTbl = !op; + + len = Math.Min(len, 31 - rn); + + bool rangeMismatch = !isTbl && (len & 1) == 0; + + using ScopedRegister indicesReg = InstEmitNeonCommon.MoveScalarToSide(context, rm, false, rangeMismatch); + + if (rangeMismatch) + { + // Force any index >= 8 * regs to be the maximum value, since on AArch64 we are working with a full vector, + // and the out of range value is 16 * regs, not 8 * regs. + + Debug.Assert(indicesReg.IsAllocated); + + using ScopedRegister tempRegister2 = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + if (len == 0) + { + (uint immb, uint immh) = InstEmitNeonCommon.GetImmbImmhForShift(3, 0, isShl: false); + + context.Arm64Assembler.UshrV(tempRegister2.Operand, indicesReg.Operand, immb, immh, 0); + context.Arm64Assembler.CmeqZeroV(tempRegister2.Operand, tempRegister2.Operand, 0, 0); + context.Arm64Assembler.Orn(indicesReg.Operand, indicesReg.Operand, tempRegister2.Operand, 0); + } + else + { + (uint a, uint b, uint c, uint d, uint e, uint f, uint g, uint h) = Split(8u * (len + 1)); + + context.Arm64Assembler.Movi(tempRegister2.Operand, h, g, f, e, d, 0xe, c, b, a, 0, 0); + context.Arm64Assembler.CmgeRegV(tempRegister2.Operand, indicesReg.Operand, tempRegister2.Operand, 0, 0); + context.Arm64Assembler.OrrReg(indicesReg.Operand, indicesReg.Operand, tempRegister2.Operand, 0); + } + } + + ScopedRegister tableReg1 = default; + ScopedRegister tableReg2 = default; + + switch (len) + { + case 0: + tableReg1 = MoveHalfToSideZeroUpper(context, rn); + break; + case 1: + tableReg1 = MoveDoublewords(context, rn, rn + 1); + break; + case 2: + tableReg1 = MoveDoublewords(context, rn, rn + 1, isOdd: true); + tableReg2 = MoveHalfToSideZeroUpper(context, rn + 2); + break; + case 3: + tableReg1 = MoveDoublewords(context, rn, rn + 1); + tableReg2 = MoveDoublewords(context, rn + 2, rn + 3); + break; + } + + // TBL works with consecutive registers, it is assumed that two consecutive calls to the register allocator + // will return consecutive registers. + + Debug.Assert(len < 2 || tableReg1.Operand.GetRegister().Index + 1 == tableReg2.Operand.GetRegister().Index); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + if (isTbl) + { + context.Arm64Assembler.Tbl(tempRegister.Operand, tableReg1.Operand, len >> 1, indicesReg.Operand, 0); + } + else + { + InstEmitNeonCommon.MoveScalarToSide(context, tempRegister.Operand, rd, false); + + context.Arm64Assembler.Tbx(tempRegister.Operand, tableReg1.Operand, len >> 1, indicesReg.Operand, 0); + } + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, false); + + tableReg1.Dispose(); + + if (len > 1) + { + tableReg2.Dispose(); + } + } + + public static void Vtrn(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + EmitVectorBinaryInterleavedTrn(context, rd, rm, size, q, context.Arm64Assembler.Trn1, context.Arm64Assembler.Trn2); + } + + public static void Vuzp(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + EmitVectorBinaryInterleaved(context, rd, rm, size, q, context.Arm64Assembler.Uzp1, context.Arm64Assembler.Uzp2); + } + + public static void Vzip(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + EmitVectorBinaryInterleaved(context, rd, rm, size, q, context.Arm64Assembler.Zip1, context.Arm64Assembler.Zip2); + } + + public static (uint, uint, uint, uint, uint, uint, uint, uint) Split(uint imm8) + { + uint a = (imm8 >> 7) & 1; + uint b = (imm8 >> 6) & 1; + uint c = (imm8 >> 5) & 1; + uint d = (imm8 >> 4) & 1; + uint e = (imm8 >> 3) & 1; + uint f = (imm8 >> 2) & 1; + uint g = (imm8 >> 1) & 1; + uint h = imm8 & 1; + + return (a, b, c, d, e, f, g, h); + } + + private static ScopedRegister MoveHalfToSideZeroUpper(CodeGenContext context, uint srcReg) + { + uint elt = srcReg & 1u; + + Operand source = context.RegisterAllocator.RemapSimdRegister((int)(srcReg >> 1)); + ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempFpRegisterScoped(false); + + uint imm5 = InstEmitNeonCommon.GetImm5ForElementIndex(elt, false); + + context.Arm64Assembler.DupEltScalarFromElement(tempRegister.Operand, source, imm5); + + return tempRegister; + } + + private static ScopedRegister MoveDoublewords(CodeGenContext context, uint lowerReg, uint upperReg, bool isOdd = false) + { + if ((lowerReg & 1) == 0 && upperReg == lowerReg + 1 && !isOdd) + { + return new ScopedRegister(context.RegisterAllocator, context.RegisterAllocator.RemapSimdRegister((int)(lowerReg >> 1)), false); + } + + Operand lowerSrc = context.RegisterAllocator.RemapSimdRegister((int)(lowerReg >> 1)); + Operand upperSrc = context.RegisterAllocator.RemapSimdRegister((int)(upperReg >> 1)); + ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempFpRegisterScoped(false); + + uint imm5 = InstEmitNeonCommon.GetImm5ForElementIndex(lowerReg & 1u, false); + + context.Arm64Assembler.DupEltScalarFromElement(tempRegister.Operand, lowerSrc, imm5); + + imm5 = InstEmitNeonCommon.GetImm5ForElementIndex(1, false); + + context.Arm64Assembler.InsElt(tempRegister.Operand, upperSrc, (upperReg & 1u) << 3, imm5); + + return tempRegister; + } + + private static void EmitVectorBinaryInterleavedTrn( + CodeGenContext context, + uint rd, + uint rm, + uint size, + uint q, + Action<Operand, Operand, Operand, uint, uint> action1, + Action<Operand, Operand, Operand, uint, uint> action2) + { + if (rd == rm) + { + // The behaviour when the registers are the same is "unpredictable" according to the manual. + + if (q == 0) + { + using ScopedRegister rdReg = InstEmitNeonCommon.MoveScalarToSide(context, rd, false); + using ScopedRegister rmReg = InstEmitNeonCommon.MoveScalarToSide(context, rm, false); + + using ScopedRegister tempRegister1 = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + using ScopedRegister tempRegister2 = InstEmitNeonCommon.PickSimdRegister(context.RegisterAllocator, rdReg, rmReg); + + action1(tempRegister1.Operand, rdReg.Operand, rmReg.Operand, size, q); + action2(tempRegister2.Operand, rdReg.Operand, tempRegister1.Operand, size, q); + + InstEmitNeonCommon.InsertResult(context, tempRegister2.Operand, rd, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + action1(tempRegister.Operand, rdOperand, rmOperand, size, q); + action2(rmOperand, rdOperand, tempRegister.Operand, size, q); + } + } + else + { + EmitVectorBinaryInterleaved(context, rd, rm, size, q, action1, action2); + } + } + + private static void EmitVectorBinaryInterleaved( + CodeGenContext context, + uint rd, + uint rm, + uint size, + uint q, + Action<Operand, Operand, Operand, uint, uint> action1, + Action<Operand, Operand, Operand, uint, uint> action2) + { + if (q == 0) + { + using ScopedRegister rdReg = InstEmitNeonCommon.MoveScalarToSide(context, rd, false); + using ScopedRegister rmReg = InstEmitNeonCommon.MoveScalarToSide(context, rm, false); + + using ScopedRegister tempRegister1 = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + using ScopedRegister tempRegister2 = InstEmitNeonCommon.PickSimdRegister(context.RegisterAllocator, rdReg, rmReg); + + action1(tempRegister1.Operand, rdReg.Operand, rmReg.Operand, size, q); + action2(tempRegister2.Operand, rdReg.Operand, rmReg.Operand, size, q); + + if (rd != rm) + { + InstEmitNeonCommon.InsertResult(context, tempRegister1.Operand, rd, false); + } + + InstEmitNeonCommon.InsertResult(context, tempRegister2.Operand, rm, false); + } + else + { + Operand rdOperand = context.RegisterAllocator.RemapSimdRegister((int)(rd >> 1)); + Operand rmOperand = context.RegisterAllocator.RemapSimdRegister((int)(rm >> 1)); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + action1(tempRegister.Operand, rdOperand, rmOperand, size, q); + action2(rmOperand, rdOperand, rmOperand, size, q); + + if (rd != rm) + { + context.Arm64Assembler.OrrReg(rdOperand, tempRegister.Operand, tempRegister.Operand, 1); + } + } + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonRound.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonRound.cs new file mode 100644 index 00000000..3c6ca65d --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonRound.cs @@ -0,0 +1,105 @@ +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonRound + { + public static void Vraddhn(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryNarrow(context, rd, rn, rm, size, context.Arm64Assembler.Raddhn); + } + + public static void Vrhadd(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, u ? context.Arm64Assembler.Urhadd : context.Arm64Assembler.Srhadd, null); + } + + public static void Vrshl(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary( + context, + rd, + rm, + rn, + size, + q, + u ? context.Arm64Assembler.UrshlV : context.Arm64Assembler.SrshlV, + u ? context.Arm64Assembler.UrshlS : context.Arm64Assembler.SrshlS); + } + + public static void Vrshr(CodeGenContext context, uint rd, uint rm, bool u, uint l, uint imm6, uint q) + { + uint size = InstEmitNeonCommon.GetSizeFromImm7(imm6 | (l << 6)); + uint shift = InstEmitNeonShift.GetShiftRight(imm6, size); + + InstEmitNeonCommon.EmitVectorBinaryShift( + context, + rd, + rm, + shift, + size, + q, + isShl: false, + u ? context.Arm64Assembler.UrshrV : context.Arm64Assembler.SrshrV, + u ? context.Arm64Assembler.UrshrS : context.Arm64Assembler.SrshrS); + } + + public static void Vrshrn(CodeGenContext context, uint rd, uint rm, uint imm6) + { + uint size = InstEmitNeonCommon.GetSizeFromImm6(imm6); + uint shift = InstEmitNeonShift.GetShiftRight(imm6, size); + + InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.Rshrn); + } + + public static void Vrsra(CodeGenContext context, uint rd, uint rm, bool u, uint l, uint imm6, uint q) + { + uint size = InstEmitNeonCommon.GetSizeFromImm7(imm6 | (l << 6)); + uint shift = InstEmitNeonShift.GetShiftRight(imm6, size); + + InstEmitNeonCommon.EmitVectorTernaryRdShift( + context, + rd, + rm, + shift, + size, + q, + isShl: false, + u ? context.Arm64Assembler.UrsraV : context.Arm64Assembler.SrsraV, + u ? context.Arm64Assembler.UrsraS : context.Arm64Assembler.SrsraS); + } + + public static void Vrsubhn(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryNarrow(context, rd, rn, rm, size, context.Arm64Assembler.Rsubhn); + } + + public static void Vrinta(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FrintaSingleAndDouble, context.Arm64Assembler.FrintaHalf); + } + + public static void Vrintm(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FrintmSingleAndDouble, context.Arm64Assembler.FrintmHalf); + } + + public static void Vrintn(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FrintnSingleAndDouble, context.Arm64Assembler.FrintnHalf); + } + + public static void Vrintp(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FrintpSingleAndDouble, context.Arm64Assembler.FrintpHalf); + } + + public static void Vrintx(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FrintxSingleAndDouble, context.Arm64Assembler.FrintxHalf); + } + + public static void Vrintz(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnaryAnyF(context, rd, rm, size, q, context.Arm64Assembler.FrintzSingleAndDouble, context.Arm64Assembler.FrintzHalf); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonSaturate.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonSaturate.cs new file mode 100644 index 00000000..aeab726a --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonSaturate.cs @@ -0,0 +1,205 @@ +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonSaturate + { + public static void Vqabs(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.SqabsV); + } + + public static void Vqadd(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary( + context, + rd, + rn, + rm, + size, + q, + u ? context.Arm64Assembler.UqaddV : context.Arm64Assembler.SqaddV, + u ? context.Arm64Assembler.UqaddS : context.Arm64Assembler.SqaddS); + } + + public static void Vqdmlal(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryLong(context, rd, rn, rm, size, context.Arm64Assembler.SqdmlalVecV); + } + + public static void VqdmlalS(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryLongByScalar(context, rd, rn, rm, size, context.Arm64Assembler.SqdmlalElt2regElement); + } + + public static void Vqdmlsl(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryLong(context, rd, rn, rm, size, context.Arm64Assembler.SqdmlslVecV); + } + + public static void VqdmlslS(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryLongByScalar(context, rd, rn, rm, size, context.Arm64Assembler.SqdmlslElt2regElement); + } + + public static void Vqdmulh(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, context.Arm64Assembler.SqdmulhVecV, context.Arm64Assembler.SqdmulhVecS); + } + + public static void VqdmulhS(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryByScalar(context, rd, rn, rm, size, q, context.Arm64Assembler.SqdmulhElt2regElement); + } + + public static void Vqdmull(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryLong(context, rd, rn, rm, size, context.Arm64Assembler.SqdmullVecV); + } + + public static void VqdmullS(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitVectorBinaryLongByScalar(context, rd, rn, rm, size, context.Arm64Assembler.SqdmullElt2regElement); + } + + public static void Vqmovn(CodeGenContext context, uint rd, uint rm, uint op, uint size) + { + if (op == 3) + { + InstEmitNeonCommon.EmitVectorUnaryNarrow(context, rd, rm, size, context.Arm64Assembler.UqxtnV); + } + else + { + InstEmitNeonCommon.EmitVectorUnaryNarrow(context, rd, rm, size, op == 1 ? context.Arm64Assembler.SqxtunV : context.Arm64Assembler.SqxtnV); + } + } + + public static void Vqneg(CodeGenContext context, uint rd, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.SqnegV); + } + + public static void Vqrdmlah(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryRd(context, rd, rn, rm, size, q, context.Arm64Assembler.SqrdmlahVecV); + } + + public static void VqrdmlahS(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryRdByScalar(context, rd, rn, rm, size, q, context.Arm64Assembler.SqrdmlahElt2regElement); + } + + public static void Vqrdmlsh(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryRd(context, rd, rn, rm, size, q, context.Arm64Assembler.SqrdmlshVecV); + } + + public static void VqrdmlshS(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorTernaryRdByScalar(context, rd, rn, rm, size, q, context.Arm64Assembler.SqrdmlshElt2regElement); + } + + public static void Vqrdmulh(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, context.Arm64Assembler.SqrdmulhVecV, context.Arm64Assembler.SqrdmulhVecS); + } + + public static void VqrdmulhS(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinaryByScalar(context, rd, rn, rm, size, q, context.Arm64Assembler.SqrdmulhElt2regElement); + } + + public static void Vqrshl(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rm, rn, size, q, context.Arm64Assembler.SqrshlV, context.Arm64Assembler.SqrshlS); + } + + public static void Vqrshrn(CodeGenContext context, uint rd, uint rm, bool u, uint op, uint imm6) + { + uint size = InstEmitNeonCommon.GetSizeFromImm6(imm6); + uint shift = InstEmitNeonShift.GetShiftRight(imm6, size); + + if (u && op == 0) + { + InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.SqrshrunV); + } + else if (!u && op == 1) + { + InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.SqrshrnV); + } + else + { + Debug.Assert(u && op == 1); // !u && op == 0 is the encoding for another instruction. + + InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.UqrshrnV); + } + } + + public static void VqshlI(CodeGenContext context, uint rd, uint rm, bool u, uint op, uint l, uint imm6, uint q) + { + uint size = InstEmitNeonCommon.GetSizeFromImm7(imm6 | (l << 6)); + uint shift = InstEmitNeonShift.GetShiftLeft(imm6, size); + + if (u && op == 0) + { + InstEmitNeonCommon.EmitVectorBinaryShift(context, rd, rm, shift, size, q, isShl: true, context.Arm64Assembler.SqshluV, context.Arm64Assembler.SqshluS); + } + else if (!u && op == 1) + { + InstEmitNeonCommon.EmitVectorBinaryShift(context, rd, rm, shift, size, q, isShl: true, context.Arm64Assembler.SqshlImmV, context.Arm64Assembler.SqshlImmS); + } + else + { + Debug.Assert(u && op == 1); // !u && op == 0 is the encoding for another instruction. + + InstEmitNeonCommon.EmitVectorBinaryShift(context, rd, rm, shift, size, q, isShl: true, context.Arm64Assembler.UqshlImmV, context.Arm64Assembler.UqshlImmS); + } + } + + public static void VqshlR(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + if (u) + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rm, rn, size, q, context.Arm64Assembler.UqshlRegV, context.Arm64Assembler.UqshlRegS); + } + else + { + InstEmitNeonCommon.EmitVectorBinary(context, rd, rm, rn, size, q, context.Arm64Assembler.SqshlRegV, context.Arm64Assembler.SqshlRegS); + } + } + + public static void Vqshrn(CodeGenContext context, uint rd, uint rm, bool u, uint op, uint imm6) + { + uint size = InstEmitNeonCommon.GetSizeFromImm6(imm6); + uint shift = InstEmitNeonShift.GetShiftRight(imm6, size); + + if (u && op == 0) + { + InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.SqshrunV); + } + else if (!u && op == 1) + { + InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.SqshrnV); + } + else + { + Debug.Assert(u && op == 1); // !u && op == 0 is the encoding for another instruction. + + InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.UqshrnV); + } + } + + public static void Vqsub(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary( + context, + rd, + rn, + rm, + size, + q, + u ? context.Arm64Assembler.UqsubV : context.Arm64Assembler.SqsubV, + u ? context.Arm64Assembler.UqsubS : context.Arm64Assembler.SqsubS); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonShift.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonShift.cs new file mode 100644 index 00000000..9f8d0bde --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonShift.cs @@ -0,0 +1,123 @@ +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonShift + { + public static void Vshll(CodeGenContext context, uint rd, uint rm, uint imm6, bool u) + { + uint size = InstEmitNeonCommon.GetSizeFromImm7(imm6); + uint shift = GetShiftLeft(imm6, size); + + InstEmitNeonCommon.EmitVectorBinaryLongShift(context, rd, rm, shift, size, isShl: true, u ? context.Arm64Assembler.Ushll : context.Arm64Assembler.Sshll); + } + + public static void Vshll2(CodeGenContext context, uint rd, uint rm, uint size) + { + // Shift can't be encoded, so shift by value - 1 first, then first again by 1. + // Doesn't matter if we do a signed or unsigned shift in this case since all sign bits will be shifted out. + + uint shift = 8u << (int)size; + + InstEmitNeonCommon.EmitVectorBinaryLongShift(context, rd, rm, shift - 1, size, isShl: true, context.Arm64Assembler.Sshll); + InstEmitNeonCommon.EmitVectorBinaryLongShift(context, rd, rd, 1, size, isShl: true, context.Arm64Assembler.Sshll); + } + + public static void VshlI(CodeGenContext context, uint rd, uint rm, uint l, uint imm6, uint q) + { + uint size = InstEmitNeonCommon.GetSizeFromImm7(imm6 | (l << 6)); + uint shift = GetShiftLeft(imm6, size); + + InstEmitNeonCommon.EmitVectorBinaryShift(context, rd, rm, shift, size, q, isShl: true, context.Arm64Assembler.ShlV, context.Arm64Assembler.ShlS); + } + + public static void VshlR(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q) + { + InstEmitNeonCommon.EmitVectorBinary( + context, + rd, + rm, + rn, + size, + q, + u ? context.Arm64Assembler.UshlV : context.Arm64Assembler.SshlV, + u ? context.Arm64Assembler.UshlS : context.Arm64Assembler.SshlS); + } + + public static void Vshr(CodeGenContext context, uint rd, uint rm, bool u, uint l, uint imm6, uint q) + { + uint size = InstEmitNeonCommon.GetSizeFromImm7(imm6 | (l << 6)); + uint shift = GetShiftRight(imm6, size); + + InstEmitNeonCommon.EmitVectorBinaryShift( + context, + rd, + rm, + shift, + size, + q, + isShl: false, + u ? context.Arm64Assembler.UshrV : context.Arm64Assembler.SshrV, + u ? context.Arm64Assembler.UshrS : context.Arm64Assembler.SshrS); + } + + public static void Vshrn(CodeGenContext context, uint rd, uint rm, uint imm6) + { + uint size = InstEmitNeonCommon.GetSizeFromImm6(imm6); + uint shift = GetShiftRight(imm6, size); + + InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.Shrn); + } + + public static void Vsli(CodeGenContext context, uint rd, uint rm, uint l, uint imm6, uint q) + { + uint size = InstEmitNeonCommon.GetSizeFromImm7(imm6 | (l << 6)); + uint shift = GetShiftLeft(imm6, size); + + InstEmitNeonCommon.EmitVectorBinaryShift( + context, + rd, + rm, + shift, + size, + q, + isShl: true, + context.Arm64Assembler.SliV, + context.Arm64Assembler.SliS); + } + + public static void Vsra(CodeGenContext context, uint rd, uint rm, bool u, uint l, uint imm6, uint q) + { + uint size = InstEmitNeonCommon.GetSizeFromImm7(imm6 | (l << 6)); + uint shift = GetShiftRight(imm6, size); + + InstEmitNeonCommon.EmitVectorTernaryRdShift( + context, + rd, + rm, + shift, + size, + q, + isShl: false, + u ? context.Arm64Assembler.UsraV : context.Arm64Assembler.SsraV, + u ? context.Arm64Assembler.UsraS : context.Arm64Assembler.SsraS); + } + + public static void Vsri(CodeGenContext context, uint rd, uint rm, uint l, uint imm6, uint q) + { + uint size = InstEmitNeonCommon.GetSizeFromImm7(imm6 | (l << 6)); + uint shift = GetShiftRight(imm6, size); + + InstEmitNeonCommon.EmitVectorBinaryShift(context, rd, rm, shift, size, q, isShl: false, context.Arm64Assembler.SriV, context.Arm64Assembler.SriS); + } + + public static uint GetShiftLeft(uint imm6, uint size) + { + return size < 3 ? imm6 - (8u << (int)size) : imm6; + } + + public static uint GetShiftRight(uint imm6, uint size) + { + return (size == 3 ? 64u : (16u << (int)size)) - imm6; + ; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonSystem.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonSystem.cs new file mode 100644 index 00000000..8c7bf91d --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonSystem.cs @@ -0,0 +1,77 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitNeonSystem + { + public static void Vmrs(CodeGenContext context, uint rt, uint reg) + { + if (context.ConsumeSkipNextInstruction()) + { + // This case means that we managed to combine a VCMP and VMRS instruction, + // so we have nothing to do here as FCMP/FCMPE already set PSTATE.NZCV. + context.SetNzcvModified(); + + return; + } + + if (reg == 1) + { + // FPSCR + + Operand ctx = InstEmitSystem.Register(context.RegisterAllocator.FixedContextRegister); + + if (rt == RegisterUtils.PcRegister) + { + using ScopedRegister fpsrRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.LdrRiUn(fpsrRegister.Operand, ctx, NativeContextOffsets.FpFlagsBaseOffset); + context.Arm64Assembler.Lsr(fpsrRegister.Operand, fpsrRegister.Operand, InstEmitCommon.Const(28)); + + InstEmitCommon.RestoreNzcvFlags(context, fpsrRegister.Operand); + + context.SetNzcvModified(); + } + else + { + // FPSCR is a combination of the FPCR and FPSR registers. + // We also need to set the FPSR NZCV bits that no longer exist on AArch64. + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand rtOperand = InstEmitCommon.GetOutputGpr(context, rt); + + context.Arm64Assembler.MrsFpsr(rtOperand); + context.Arm64Assembler.MrsFpcr(tempRegister.Operand); + context.Arm64Assembler.Orr(rtOperand, rtOperand, tempRegister.Operand); + context.Arm64Assembler.LdrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FpFlagsBaseOffset); + context.Arm64Assembler.Bfc(tempRegister.Operand, 0, 28); + context.Arm64Assembler.Orr(rtOperand, rtOperand, tempRegister.Operand); + } + } + else + { + Operand rtOperand = InstEmitCommon.GetOutputGpr(context, rt); + + context.Arm64Assembler.Mov(rtOperand, 0u); + } + } + + public static void Vmsr(CodeGenContext context, uint rt, uint reg) + { + if (reg == 1) + { + // FPSCR + + // TODO: Do not set bits related to features that are not supported (like FP16)? + + Operand ctx = InstEmitSystem.Register(context.RegisterAllocator.FixedContextRegister); + Operand rtOperand = InstEmitCommon.GetInputGpr(context, rt); + + context.Arm64Assembler.MsrFpcr(rtOperand); + context.Arm64Assembler.MsrFpsr(rtOperand); + context.Arm64Assembler.StrRiUn(rtOperand, ctx, NativeContextOffsets.FpFlagsBaseOffset); + } + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSaturate.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSaturate.cs new file mode 100644 index 00000000..e2354f44 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSaturate.cs @@ -0,0 +1,452 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitSaturate + { + public static void Qadd(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAddSubSaturate(context, rd, rn, rm, doubling: false, add: true); + } + + public static void Qadd16(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitSigned16BitPair(context, rd, rn, rm, (d, n, m) => + { + context.Arm64Assembler.Add(d, n, m); + EmitSaturateRange(context, d, d, 16, unsigned: false, setQ: false); + }); + } + + public static void Qadd8(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitSigned8BitPair(context, rd, rn, rm, (d, n, m) => + { + context.Arm64Assembler.Add(d, n, m); + EmitSaturateRange(context, d, d, 8, unsigned: false, setQ: false); + }); + } + + public static void Qasx(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitSigned16BitXPair(context, rd, rn, rm, (d, n, m, e) => + { + if (e == 0) + { + context.Arm64Assembler.Sub(d, n, m); + } + else + { + context.Arm64Assembler.Add(d, n, m); + } + + EmitSaturateRange(context, d, d, 16, unsigned: false, setQ: false); + }); + } + + public static void Qdadd(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAddSubSaturate(context, rd, rn, rm, doubling: true, add: true); + } + + public static void Qdsub(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAddSubSaturate(context, rd, rn, rm, doubling: true, add: false); + } + + public static void Qsax(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitSigned16BitXPair(context, rd, rn, rm, (d, n, m, e) => + { + if (e == 0) + { + context.Arm64Assembler.Add(d, n, m); + } + else + { + context.Arm64Assembler.Sub(d, n, m); + } + + EmitSaturateRange(context, d, d, 16, unsigned: false, setQ: false); + }); + } + + public static void Qsub(CodeGenContext context, uint rd, uint rn, uint rm) + { + EmitAddSubSaturate(context, rd, rn, rm, doubling: false, add: false); + } + + public static void Qsub16(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitSigned16BitPair(context, rd, rn, rm, (d, n, m) => + { + context.Arm64Assembler.Sub(d, n, m); + EmitSaturateRange(context, d, d, 16, unsigned: false, setQ: false); + }); + } + + public static void Qsub8(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitSigned8BitPair(context, rd, rn, rm, (d, n, m) => + { + context.Arm64Assembler.Sub(d, n, m); + EmitSaturateRange(context, d, d, 8, unsigned: false, setQ: false); + }); + } + + public static void Ssat(CodeGenContext context, uint rd, uint imm, uint rn, bool sh, uint shift) + { + EmitSaturate(context, rd, imm + 1, rn, sh, shift, unsigned: false); + } + + public static void Ssat16(CodeGenContext context, uint rd, uint imm, uint rn) + { + InstEmitCommon.EmitSigned16BitPair(context, rd, rn, (d, n) => + { + EmitSaturateRange(context, d, n, imm + 1, unsigned: false); + }); + } + + public static void Uqadd16(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitUnsigned16BitPair(context, rd, rn, rm, (d, n, m) => + { + context.Arm64Assembler.Add(d, n, m); + EmitSaturateUnsignedRange(context, d, 16); + }); + } + + public static void Uqadd8(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitUnsigned8BitPair(context, rd, rn, rm, (d, n, m) => + { + context.Arm64Assembler.Add(d, n, m); + EmitSaturateUnsignedRange(context, d, 8); + }); + } + + public static void Uqasx(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitUnsigned16BitXPair(context, rd, rn, rm, (d, n, m, e) => + { + if (e == 0) + { + context.Arm64Assembler.Sub(d, n, m); + } + else + { + context.Arm64Assembler.Add(d, n, m); + } + + EmitSaturateUnsignedRange(context, d, 16); + }); + } + + public static void Uqsax(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitUnsigned16BitXPair(context, rd, rn, rm, (d, n, m, e) => + { + if (e == 0) + { + context.Arm64Assembler.Add(d, n, m); + } + else + { + context.Arm64Assembler.Sub(d, n, m); + } + + EmitSaturateUnsignedRange(context, d, 16); + }); + } + + public static void Uqsub16(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitSigned16BitPair(context, rd, rn, rm, (d, n, m) => + { + context.Arm64Assembler.Sub(d, n, m); + EmitSaturateUnsignedRange(context, d, 16); + }); + } + + public static void Uqsub8(CodeGenContext context, uint rd, uint rn, uint rm) + { + InstEmitCommon.EmitSigned8BitPair(context, rd, rn, rm, (d, n, m) => + { + context.Arm64Assembler.Sub(d, n, m); + EmitSaturateUnsignedRange(context, d, 8); + }); + } + + public static void Usat(CodeGenContext context, uint rd, uint imm, uint rn, bool sh, uint shift) + { + EmitSaturate(context, rd, imm, rn, sh, shift, unsigned: true); + } + + public static void Usat16(CodeGenContext context, uint rd, uint imm, uint rn) + { + InstEmitCommon.EmitSigned16BitPair(context, rd, rn, (d, n) => + { + EmitSaturateRange(context, d, n, imm, unsigned: true); + }); + } + + private static void EmitAddSubSaturate(CodeGenContext context, uint rd, uint rn, uint rm, bool doubling, bool add) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + Operand rmOperand = InstEmitCommon.GetInputGpr(context, rm); + + using ScopedRegister tempN = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempM = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand tempN64 = new(OperandKind.Register, OperandType.I64, tempN.Operand.Value); + Operand tempM64 = new(OperandKind.Register, OperandType.I64, tempM.Operand.Value); + + context.Arm64Assembler.Sxtw(tempN64, rnOperand); + context.Arm64Assembler.Sxtw(tempM64, rmOperand); + + if (doubling) + { + context.Arm64Assembler.Lsl(tempN64, tempN64, InstEmitCommon.Const(1)); + + EmitSaturateLongToInt(context, tempN64, tempN64); + } + + if (add) + { + context.Arm64Assembler.Add(tempN64, tempN64, tempM64); + } + else + { + context.Arm64Assembler.Sub(tempN64, tempN64, tempM64); + } + + EmitSaturateLongToInt(context, rdOperand, tempN64); + } + + private static void EmitSaturate(CodeGenContext context, uint rd, uint imm, uint rn, bool sh, uint shift, bool unsigned) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + if (sh && shift == 0) + { + shift = 31; + } + + if (shift != 0) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + if (sh) + { + context.Arm64Assembler.Asr(tempRegister.Operand, rnOperand, InstEmitCommon.Const((int)shift)); + } + else + { + context.Arm64Assembler.Lsl(tempRegister.Operand, rnOperand, InstEmitCommon.Const((int)shift)); + } + + EmitSaturateRange(context, rdOperand, tempRegister.Operand, imm, unsigned); + } + else + { + EmitSaturateRange(context, rdOperand, rnOperand, imm, unsigned); + } + } + + private static void EmitSaturateRange(CodeGenContext context, Operand result, Operand value, uint saturateTo, bool unsigned, bool setQ = true) + { + Debug.Assert(saturateTo <= 32); + Debug.Assert(!unsigned || saturateTo < 32); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + ScopedRegister tempValue = default; + + bool resultValueOverlap = result.Value == value.Value; + + if (!unsigned && saturateTo == 32) + { + // No saturation possible for this case. + + if (!resultValueOverlap) + { + context.Arm64Assembler.Mov(result, value); + } + + return; + } + else if (saturateTo == 0) + { + // Result is always zero if we saturate 0 bits. + + context.Arm64Assembler.Mov(result, 0u); + + return; + } + + if (resultValueOverlap) + { + tempValue = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.Mov(tempValue.Operand, value); + value = tempValue.Operand; + } + + if (unsigned) + { + // Negative values always saturate (to zero). + // So we must always ignore the sign bit when masking, so that the truncated value will differ from the original one. + + context.Arm64Assembler.And(result, value, InstEmitCommon.Const((int)(uint.MaxValue >> (32 - (int)saturateTo)))); + } + else + { + context.Arm64Assembler.Sbfx(result, value, 0, (int)saturateTo); + } + + context.Arm64Assembler.Sub(tempRegister.Operand, value, result); + + int branchIndex = context.CodeWriter.InstructionPointer; + + // If the result is 0, the values are equal and we don't need saturation. + context.Arm64Assembler.Cbz(tempRegister.Operand, 0); + + // Saturate and set Q flag. + if (unsigned) + { + if (saturateTo == 31) + { + // Only saturation case possible when going from 32 bits signed to 32 or 31 bits unsigned + // is when the signed input is negative, as all positive values are representable on a 31 bits range. + + context.Arm64Assembler.Mov(result, 0u); + } + else + { + context.Arm64Assembler.Asr(result, value, InstEmitCommon.Const(31)); + context.Arm64Assembler.Mvn(result, result); + context.Arm64Assembler.Lsr(result, result, InstEmitCommon.Const(32 - (int)saturateTo)); + } + } + else + { + if (saturateTo == 1) + { + context.Arm64Assembler.Asr(result, value, InstEmitCommon.Const(31)); + } + else + { + context.Arm64Assembler.Mov(result, uint.MaxValue >> (33 - (int)saturateTo)); + context.Arm64Assembler.Eor(result, result, value, ArmShiftType.Asr, 31); + } + } + + if (setQ) + { + SetQFlag(context); + } + + int delta = context.CodeWriter.InstructionPointer - branchIndex; + context.CodeWriter.WriteInstructionAt(branchIndex, context.CodeWriter.ReadInstructionAt(branchIndex) | (uint)((delta & 0x7ffff) << 5)); + + if (resultValueOverlap) + { + tempValue.Dispose(); + } + } + + private static void EmitSaturateUnsignedRange(CodeGenContext context, Operand value, uint saturateTo) + { + Debug.Assert(saturateTo <= 32); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + if (saturateTo == 32) + { + // No saturation possible for this case. + + return; + } + else if (saturateTo == 0) + { + // Result is always zero if we saturate 0 bits. + + context.Arm64Assembler.Mov(value, 0u); + + return; + } + + context.Arm64Assembler.Lsr(tempRegister.Operand, value, InstEmitCommon.Const(32 - (int)saturateTo)); + + int branchIndex = context.CodeWriter.InstructionPointer; + + // If the result is 0, the values are equal and we don't need saturation. + context.Arm64Assembler.Cbz(tempRegister.Operand, 0); + + // Saturate. + context.Arm64Assembler.Mov(value, uint.MaxValue >> (32 - (int)saturateTo)); + + int delta = context.CodeWriter.InstructionPointer - branchIndex; + context.CodeWriter.WriteInstructionAt(branchIndex, context.CodeWriter.ReadInstructionAt(branchIndex) | (uint)((delta & 0x7ffff) << 5)); + } + + private static void EmitSaturateLongToInt(CodeGenContext context, Operand result, Operand value) + { + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + ScopedRegister tempValue = default; + + bool resultValueOverlap = result.Value == value.Value; + + if (resultValueOverlap) + { + tempValue = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand tempValue64 = new(OperandKind.Register, OperandType.I64, tempValue.Operand.Value); + + context.Arm64Assembler.Mov(tempValue64, value); + value = tempValue64; + } + + Operand temp64 = new(OperandKind.Register, OperandType.I64, tempRegister.Operand.Value); + Operand result64 = new(OperandKind.Register, OperandType.I64, result.Value); + + context.Arm64Assembler.Sxtw(result64, value); + context.Arm64Assembler.Sub(temp64, value, result64); + + int branchIndex = context.CodeWriter.InstructionPointer; + + // If the result is 0, the values are equal and we don't need saturation. + context.Arm64Assembler.Cbz(temp64, 0); + + // Saturate and set Q flag. + context.Arm64Assembler.Mov(result, uint.MaxValue >> 1); + context.Arm64Assembler.Eor(result64, result64, value, ArmShiftType.Asr, 63); + + SetQFlag(context); + + int delta = context.CodeWriter.InstructionPointer - branchIndex; + context.CodeWriter.WriteInstructionAt(branchIndex, context.CodeWriter.ReadInstructionAt(branchIndex) | (uint)((delta & 0x7ffff) << 5)); + + context.Arm64Assembler.Mov(result, result); // Zero-extend. + + if (resultValueOverlap) + { + tempValue.Dispose(); + } + } + + public static void SetQFlag(CodeGenContext context) + { + Operand ctx = InstEmitSystem.Register(context.RegisterAllocator.FixedContextRegister); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.LdrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + context.Arm64Assembler.Orr(tempRegister.Operand, tempRegister.Operand, InstEmitCommon.Const(1 << 27)); + context.Arm64Assembler.StrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs new file mode 100644 index 00000000..be0976fd --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs @@ -0,0 +1,648 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; +using System; +using System.Diagnostics; +using System.Numerics; +using System.Runtime.InteropServices; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitSystem + { + private delegate void SoftwareInterruptHandler(ulong address, int imm); + private delegate ulong Get64(); + private delegate bool GetBool(); + + private const int SpIndex = 31; + + public static void Bkpt(CodeGenContext context, uint imm) + { + context.AddPendingBkpt(imm); + + context.Arm64Assembler.B(0); + } + + public static void Cps(CodeGenContext context, uint imod, uint m, uint a, uint i, uint f, uint mode) + { + // NOP in user mode. + } + + public static void Dbg(CodeGenContext context, uint option) + { + // NOP in ARMv8. + } + + public static void Hlt(CodeGenContext context, uint imm) + { + } + + public static void Mcr(CodeGenContext context, uint encoding, uint coproc, uint opc1, uint rt, uint crn, uint crm, uint opc2) + { + if (coproc != 15 || opc1 != 0) + { + Udf(context, encoding, 0); + + return; + } + + Operand ctx = Register(context.RegisterAllocator.FixedContextRegister); + Operand rtOperand = InstEmitCommon.GetInputGpr(context, rt); + + switch (crn) + { + case 13: // Process and Thread Info. + if (crm == 0) + { + switch (opc2) + { + case 2: + context.Arm64Assembler.StrRiUn(rtOperand, ctx, NativeContextOffsets.TpidrEl0Offset); + return; + } + } + break; + } + } + + public static void Mcrr(CodeGenContext context, uint encoding, uint coproc, uint opc1, uint rt, uint crm) + { + if (coproc != 15 || opc1 != 0) + { + Udf(context, encoding, 0); + + return; + } + + // We don't have any system register that needs to be modified using a 64-bit value. + } + + public static void Mrc(CodeGenContext context, uint encoding, uint coproc, uint opc1, uint rt, uint crn, uint crm, uint opc2) + { + if (coproc != 15 || opc1 != 0) + { + Udf(context, encoding, 0); + + return; + } + + Operand ctx = Register(context.RegisterAllocator.FixedContextRegister); + Operand rtOperand = InstEmitCommon.GetInputGpr(context, rt); + bool hasValue = false; + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + Operand dest = rt == RegisterUtils.PcRegister ? tempRegister.Operand : rtOperand; + + switch (crn) + { + case 13: // Process and Thread Info. + if (crm == 0) + { + switch (opc2) + { + case 2: + context.Arm64Assembler.LdrRiUn(dest, ctx, NativeContextOffsets.TpidrEl0Offset); + hasValue = true; + break; + case 3: + context.Arm64Assembler.LdrRiUn(dest, ctx, NativeContextOffsets.TpidrroEl0Offset); + hasValue = true; + break; + } + } + break; + } + + if (rt == RegisterUtils.PcRegister) + { + context.Arm64Assembler.MsrNzcv(dest); + context.SetNzcvModified(); + } + else if (!hasValue) + { + context.Arm64Assembler.Mov(dest, 0u); + } + } + + public static void Mrrc(CodeGenContext context, uint encoding, uint coproc, uint opc1, uint rt, uint rt2, uint crm) + { + if (coproc != 15) + { + Udf(context, encoding, 0); + + return; + } + + switch (crm) + { + case 14: + switch (opc1) + { + case 0: + context.AddPendingReadCntpct(rt, rt2); + context.Arm64Assembler.B(0); + return; + } + break; + } + + // Unsupported system register. + context.Arm64Assembler.Mov(InstEmitCommon.GetOutputGpr(context, rt), 0u); + context.Arm64Assembler.Mov(InstEmitCommon.GetOutputGpr(context, rt2), 0u); + } + + public static void Mrs(CodeGenContext context, uint rd, bool r) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + + if (r) + { + // Reads SPSR, unpredictable in user mode. + + context.Arm64Assembler.Mov(rdOperand, 0u); + } + else + { + Operand ctx = Register(context.RegisterAllocator.FixedContextRegister); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.LdrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + + // Copy GE flags to destination register. + context.Arm64Assembler.Ubfx(rdOperand, tempRegister.Operand, 16, 4); + + // Insert Q flag. + context.Arm64Assembler.And(tempRegister.Operand, tempRegister.Operand, InstEmitCommon.Const(1 << 27)); + context.Arm64Assembler.Orr(rdOperand, rdOperand, tempRegister.Operand); + + // Insert NZCV flags. + context.Arm64Assembler.MrsNzcv(tempRegister.Operand); + context.Arm64Assembler.Orr(rdOperand, rdOperand, tempRegister.Operand); + + // All other flags can't be accessed in user mode or have "unknown" values. + } + } + + public static void MrsBr(CodeGenContext context, uint rd, uint m1, bool r) + { + Operand rdOperand = InstEmitCommon.GetOutputGpr(context, rd); + + // Reads banked register, unpredictable in user mode. + + context.Arm64Assembler.Mov(rdOperand, 0u); + } + + public static void MsrBr(CodeGenContext context, uint rn, uint m1, bool r) + { + // Writes banked register, unpredictable in user mode. + } + + public static void MsrI(CodeGenContext context, uint imm, uint mask, bool r) + { + if (r) + { + // Writes SPSR, unpredictable in user mode. + } + else + { + Operand ctx = Register(context.RegisterAllocator.FixedContextRegister); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempRegister2 = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.LdrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + + if ((mask & 2) != 0) + { + // Endian flag. + + context.Arm64Assembler.Mov(tempRegister2.Operand, (imm >> 9) & 1); + context.Arm64Assembler.Bfi(tempRegister.Operand, tempRegister2.Operand, 9, 1); + } + + if ((mask & 4) != 0) + { + // GE flags. + + context.Arm64Assembler.Mov(tempRegister2.Operand, (imm >> 16) & 0xf); + context.Arm64Assembler.Bfi(tempRegister.Operand, tempRegister2.Operand, 16, 4); + } + + if ((mask & 8) != 0) + { + // NZCVQ flags. + + context.Arm64Assembler.Mov(tempRegister2.Operand, (imm >> 27) & 0x1f); + context.Arm64Assembler.Bfi(tempRegister.Operand, tempRegister2.Operand, 27, 5); + context.Arm64Assembler.Mov(tempRegister2.Operand, (imm >> 28) & 0xf); + InstEmitCommon.RestoreNzcvFlags(context, tempRegister2.Operand); + context.SetNzcvModified(); + } + } + } + + public static void MsrR(CodeGenContext context, uint rn, uint mask, bool r) + { + Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); + + if (r) + { + // Writes SPSR, unpredictable in user mode. + } + else + { + Operand ctx = Register(context.RegisterAllocator.FixedContextRegister); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister tempRegister2 = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.LdrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + + if ((mask & 2) != 0) + { + // Endian flag. + + context.Arm64Assembler.Lsr(tempRegister2.Operand, rnOperand, InstEmitCommon.Const(9)); + context.Arm64Assembler.Bfi(tempRegister.Operand, tempRegister2.Operand, 9, 1); + } + + if ((mask & 4) != 0) + { + // GE flags. + + context.Arm64Assembler.Lsr(tempRegister2.Operand, rnOperand, InstEmitCommon.Const(16)); + context.Arm64Assembler.Bfi(tempRegister.Operand, tempRegister2.Operand, 16, 4); + } + + if ((mask & 8) != 0) + { + // NZCVQ flags. + + context.Arm64Assembler.Lsr(tempRegister2.Operand, rnOperand, InstEmitCommon.Const(27)); + context.Arm64Assembler.Bfi(tempRegister.Operand, tempRegister2.Operand, 27, 5); + context.Arm64Assembler.Lsr(tempRegister2.Operand, rnOperand, InstEmitCommon.Const(28)); + InstEmitCommon.RestoreNzcvFlags(context, tempRegister2.Operand); + context.SetNzcvModified(); + } + } + } + + public static void Setend(CodeGenContext context, bool e) + { + Operand ctx = Register(context.RegisterAllocator.FixedContextRegister); + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + context.Arm64Assembler.LdrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + + if (e) + { + context.Arm64Assembler.Orr(tempRegister.Operand, tempRegister.Operand, InstEmitCommon.Const(1 << 9)); + } + else + { + context.Arm64Assembler.Bfc(tempRegister.Operand, 9, 1); + } + + context.Arm64Assembler.StrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FlagsBaseOffset); + } + + public static void Svc(CodeGenContext context, uint imm) + { + context.AddPendingSvc(imm); + context.Arm64Assembler.B(0); + } + + public static void Udf(CodeGenContext context, uint encoding, uint imm) + { + context.AddPendingUdf(encoding); + context.Arm64Assembler.B(0); + } + + public static void PrivilegedInstruction(CodeGenContext context, uint encoding) + { + Udf(context, encoding, 0); + } + + private static IntPtr GetBkptHandlerPtr() + { + return Marshal.GetFunctionPointerForDelegate<SoftwareInterruptHandler>(NativeInterface.Break); + } + + private static IntPtr GetSvcHandlerPtr() + { + return Marshal.GetFunctionPointerForDelegate<SoftwareInterruptHandler>(NativeInterface.SupervisorCall); + } + + private static IntPtr GetUdfHandlerPtr() + { + return Marshal.GetFunctionPointerForDelegate<SoftwareInterruptHandler>(NativeInterface.Undefined); + } + + private static IntPtr GetCntpctEl0Ptr() + { + return Marshal.GetFunctionPointerForDelegate<Get64>(NativeInterface.GetCntpctEl0); + } + + private static IntPtr CheckSynchronizationPtr() + { + return Marshal.GetFunctionPointerForDelegate<GetBool>(NativeInterface.CheckSynchronization); + } + + public static bool NeedsCall(InstName name) + { + // All instructions that might do a host call should be included here. + // That is required to reserve space on the stack for caller saved registers. + + switch (name) + { + case InstName.Mcr: + case InstName.Mrc: + case InstName.Mrrc: + case InstName.Svc: + case InstName.Udf: + return true; + } + + return false; + } + + public static void WriteBkpt(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset, uint pc, uint imm) + { + Assembler asm = new(writer); + + WriteCall(ref asm, regAlloc, GetBkptHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, imm); + WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: true, spillBaseOffset); + } + + public static void WriteSvc(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset, uint pc, uint svcId) + { + Assembler asm = new(writer); + + WriteCall(ref asm, regAlloc, GetSvcHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, svcId); + WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: true, spillBaseOffset); + } + + public static void WriteUdf(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset, uint pc, uint imm) + { + Assembler asm = new(writer); + + WriteCall(ref asm, regAlloc, GetUdfHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, imm); + WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: true, spillBaseOffset); + } + + public static void WriteReadCntpct(CodeWriter writer, RegisterAllocator regAlloc, int spillBaseOffset, int rt, int rt2) + { + Assembler asm = new(writer); + + uint resultMask = (1u << rt) | (1u << rt2); + int tempRegister = 0; + + while ((resultMask & (1u << tempRegister)) != 0 && tempRegister < 32) + { + tempRegister++; + } + + Debug.Assert(tempRegister < 32); + + WriteSpill(ref asm, regAlloc, resultMask, skipContext: false, spillBaseOffset, tempRegister); + + Operand rn = Register(tempRegister); + + asm.Mov(rn, (ulong)GetCntpctEl0Ptr()); + asm.Blr(rn); + + if (rt != rt2) + { + asm.Lsr(Register(rt2), Register(0), InstEmitCommon.Const(32)); + } + + asm.Mov(Register(rt, OperandType.I32), Register(0, OperandType.I32)); // Zero-extend. + + WriteFill(ref asm, regAlloc, resultMask, skipContext: false, spillBaseOffset, tempRegister); + } + + public static void WriteSyncPoint(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset) + { + Assembler asm = new(writer); + + WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: false, spillBaseOffset); + } + + private static void WriteSyncPoint(CodeWriter writer, ref Assembler asm, RegisterAllocator regAlloc, TailMerger tailMerger, bool skipContext, int spillBaseOffset) + { + int tempRegister = regAlloc.AllocateTempGprRegister(); + + Operand rt = Register(tempRegister, OperandType.I32); + + asm.LdrRiUn(rt, Register(regAlloc.FixedContextRegister), NativeContextOffsets.CounterOffset); + + int branchIndex = writer.InstructionPointer; + asm.Cbnz(rt, 0); + + WriteSpill(ref asm, regAlloc, 1u << tempRegister, skipContext, spillBaseOffset, tempRegister); + + Operand rn = Register(tempRegister == 0 ? 1 : 0); + + asm.Mov(rn, (ulong)CheckSynchronizationPtr()); + asm.Blr(rn); + + tailMerger.AddConditionalZeroReturn(writer, asm, Register(0, OperandType.I32)); + + WriteFill(ref asm, regAlloc, 1u << tempRegister, skipContext, spillBaseOffset, tempRegister); + + asm.LdrRiUn(rt, Register(regAlloc.FixedContextRegister), NativeContextOffsets.CounterOffset); + + uint branchInst = writer.ReadInstructionAt(branchIndex); + writer.WriteInstructionAt(branchIndex, branchInst | (((uint)(writer.InstructionPointer - branchIndex) & 0x7ffff) << 5)); + + asm.Sub(rt, rt, new Operand(OperandKind.Constant, OperandType.I32, 1)); + asm.StrRiUn(rt, Register(regAlloc.FixedContextRegister), NativeContextOffsets.CounterOffset); + + regAlloc.FreeTempGprRegister(tempRegister); + } + + private static void WriteCall( + ref Assembler asm, + RegisterAllocator regAlloc, + IntPtr funcPtr, + bool skipContext, + int spillBaseOffset, + int? resultRegister, + params ulong[] callArgs) + { + uint resultMask = 0u; + + if (resultRegister.HasValue) + { + resultMask = 1u << resultRegister.Value; + } + + int tempRegister = callArgs.Length; + + if (resultRegister.HasValue && tempRegister == resultRegister.Value) + { + tempRegister++; + } + + WriteSpill(ref asm, regAlloc, resultMask, skipContext, spillBaseOffset, tempRegister); + + // We only support up to 7 arguments right now. + // ABI defines the first 8 integer arguments to be passed on registers X0-X7. + // We need at least one register to put the function address on, so that reduces the number of + // registers we can use for that by one. + + Debug.Assert(callArgs.Length < 8); + + for (int index = 0; index < callArgs.Length; index++) + { + asm.Mov(Register(index), callArgs[index]); + } + + Operand rn = Register(tempRegister); + + asm.Mov(rn, (ulong)funcPtr); + asm.Blr(rn); + + if (resultRegister.HasValue && resultRegister.Value != 0) + { + asm.Mov(Register(resultRegister.Value), Register(0)); + } + + WriteFill(ref asm, regAlloc, resultMask, skipContext, spillBaseOffset, tempRegister); + } + + private static void WriteSpill(ref Assembler asm, RegisterAllocator regAlloc, uint exceptMask, bool skipContext, int spillOffset, int tempRegister) + { + WriteSpillOrFill(ref asm, regAlloc, skipContext, exceptMask, spillOffset, tempRegister, spill: true); + } + + private static void WriteFill(ref Assembler asm, RegisterAllocator regAlloc, uint exceptMask, bool skipContext, int spillOffset, int tempRegister) + { + WriteSpillOrFill(ref asm, regAlloc, skipContext, exceptMask, spillOffset, tempRegister, spill: false); + } + + private static void WriteSpillOrFill( + ref Assembler asm, + RegisterAllocator regAlloc, + bool skipContext, + uint exceptMask, + int spillOffset, + int tempRegister, + bool spill) + { + uint gprMask = regAlloc.UsedGprsMask & ~(AbiConstants.GprCalleeSavedRegsMask | exceptMask); + + if (skipContext) + { + gprMask &= ~Compiler.UsableGprsMask; + } + + if (!spill) + { + // We must reload the status register before reloading the GPRs, + // since we might otherwise trash one of them by using it as temp register. + + Operand rt = Register(tempRegister, OperandType.I32); + + asm.LdrRiUn(rt, Register(SpIndex), spillOffset + BitOperations.PopCount(gprMask) * 8); + asm.MsrNzcv(rt); + } + + while (gprMask != 0) + { + int reg = BitOperations.TrailingZeroCount(gprMask); + + if (reg < 31 && (gprMask & (2u << reg)) != 0 && spillOffset < RegisterSaveRestore.Encodable9BitsOffsetLimit) + { + if (spill) + { + asm.StpRiUn(Register(reg), Register(reg + 1), Register(SpIndex), spillOffset); + } + else + { + asm.LdpRiUn(Register(reg), Register(reg + 1), Register(SpIndex), spillOffset); + } + + gprMask &= ~(3u << reg); + spillOffset += 16; + } + else + { + if (spill) + { + asm.StrRiUn(Register(reg), Register(SpIndex), spillOffset); + } + else + { + asm.LdrRiUn(Register(reg), Register(SpIndex), spillOffset); + } + + gprMask &= ~(1u << reg); + spillOffset += 8; + } + } + + if (spill) + { + Operand rt = Register(tempRegister, OperandType.I32); + + asm.MrsNzcv(rt); + asm.StrRiUn(rt, Register(SpIndex), spillOffset); + } + + spillOffset += 8; + + if ((spillOffset & 8) != 0) + { + spillOffset += 8; + } + + uint fpSimdMask = regAlloc.UsedFpSimdMask; + + if (skipContext) + { + fpSimdMask &= ~Compiler.UsableFpSimdMask; + } + + while (fpSimdMask != 0) + { + int reg = BitOperations.TrailingZeroCount(fpSimdMask); + + if (reg < 31 && (fpSimdMask & (2u << reg)) != 0 && spillOffset < RegisterSaveRestore.Encodable9BitsOffsetLimit) + { + if (spill) + { + asm.StpRiUn(Register(reg, OperandType.V128), Register(reg + 1, OperandType.V128), Register(SpIndex), spillOffset); + } + else + { + asm.LdpRiUn(Register(reg, OperandType.V128), Register(reg + 1, OperandType.V128), Register(SpIndex), spillOffset); + } + + fpSimdMask &= ~(3u << reg); + spillOffset += 32; + } + else + { + if (spill) + { + asm.StrRiUn(Register(reg, OperandType.V128), Register(SpIndex), spillOffset); + } + else + { + asm.LdrRiUn(Register(reg, OperandType.V128), Register(SpIndex), spillOffset); + } + + fpSimdMask &= ~(1u << reg); + spillOffset += 16; + } + } + } + + public static Operand Register(int register, OperandType type = OperandType.I64) + { + return new Operand(register, RegisterType.Integer, type); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpArithmetic.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpArithmetic.cs new file mode 100644 index 00000000..efb2fc6b --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpArithmetic.cs @@ -0,0 +1,95 @@ +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitVfpArithmetic + { + public static void VabsF(CodeGenContext context, uint rd, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FabsFloat); + } + + public static void VaddF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarBinaryF(context, rd, rn, rm, size, context.Arm64Assembler.FaddFloat); + } + + public static void VdivF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarBinaryF(context, rd, rn, rm, size, context.Arm64Assembler.FdivFloat); + } + + public static void VfmaF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarTernaryRdF(context, rd, rn, rm, size, context.Arm64Assembler.FmaddFloat); + } + + public static void VfmsF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarTernaryRdF(context, rd, rn, rm, size, context.Arm64Assembler.FmsubFloat); + } + + public static void VfnmaF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarTernaryRdF(context, rd, rn, rm, size, context.Arm64Assembler.FnmaddFloat); + } + + public static void VfnmsF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarTernaryRdF(context, rd, rn, rm, size, context.Arm64Assembler.FnmsubFloat); + } + + public static void Vmaxnm(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarBinaryF(context, rd, rn, rm, size, context.Arm64Assembler.FmaxnmFloat); + } + + public static void Vminnm(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarBinaryF(context, rd, rn, rm, size, context.Arm64Assembler.FminnmFloat); + } + + public static void VmlaF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarTernaryMulNegRdF(context, rd, rn, rm, size, negD: false, negProduct: false); + } + + public static void VmlsF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarTernaryMulNegRdF(context, rd, rn, rm, size, negD: false, negProduct: true); + } + + public static void VmulF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarBinaryF(context, rd, rn, rm, size, context.Arm64Assembler.FmulFloat); + } + + public static void VnegF(CodeGenContext context, uint rd, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FnegFloat); + } + + public static void VnmlaF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarTernaryMulNegRdF(context, rd, rn, rm, size, negD: true, negProduct: true); + } + + public static void VnmlsF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarTernaryMulNegRdF(context, rd, rn, rm, size, negD: true, negProduct: false); + } + + public static void VnmulF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarBinaryF(context, rd, rn, rm, size, context.Arm64Assembler.FnmulFloat); + } + + public static void VsqrtF(CodeGenContext context, uint rd, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FsqrtFloat); + } + + public static void VsubF(CodeGenContext context, uint rd, uint rn, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarBinaryF(context, rd, rn, rm, size, context.Arm64Assembler.FsubFloat); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpCompare.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpCompare.cs new file mode 100644 index 00000000..f5f30609 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpCompare.cs @@ -0,0 +1,133 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; +using System; +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitVfpCompare + { + public static void VcmpI(CodeGenContext context, uint cond, uint rd, uint size) + { + EmitVcmpVcmpe(context, cond, rd, 0, size, zero: true, e: false); + } + + public static void VcmpR(CodeGenContext context, uint cond, uint rd, uint rm, uint size) + { + EmitVcmpVcmpe(context, cond, rd, rm, size, zero: false, e: false); + } + + public static void VcmpeI(CodeGenContext context, uint cond, uint rd, uint size) + { + EmitVcmpVcmpe(context, cond, rd, 0, size, zero: true, e: true); + } + + public static void VcmpeR(CodeGenContext context, uint cond, uint rd, uint rm, uint size) + { + EmitVcmpVcmpe(context, cond, rd, rm, size, zero: false, e: true); + } + + private static void EmitVcmpVcmpe(CodeGenContext context, uint cond, uint rd, uint rm, uint size, bool zero, bool e) + { + Debug.Assert(size == 1 || size == 2 || size == 3); + + bool singleRegs = size != 3; + uint ftype = size ^ 2u; + uint opc = zero ? 1u : 0u; + + using ScopedRegister rdReg = InstEmitNeonCommon.MoveScalarToSide(context, rd, singleRegs); + ScopedRegister rmReg; + Operand rmOrZero; + + if (zero) + { + rmReg = default; + rmOrZero = new Operand(0, RegisterType.Vector, OperandType.V128); + } + else + { + rmReg = InstEmitNeonCommon.MoveScalarToSide(context, rm, singleRegs); + rmOrZero = rmReg.Operand; + } + + using ScopedRegister oldFlags = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + bool canPeepholeOptimize = CanFuseVcmpVmrs(context, cond); + if (!canPeepholeOptimize) + { + InstEmitCommon.GetCurrentFlags(context, oldFlags.Operand); + } + + if (e) + { + context.Arm64Assembler.FcmpeFloat(rdReg.Operand, rmOrZero, opc, ftype); + } + else + { + context.Arm64Assembler.FcmpFloat(rdReg.Operand, rmOrZero, opc, ftype); + } + + // Save result flags from the FCMP operation on FPSCR register, then restore the old flags if needed. + + WriteUpdateFpsrNzcv(context); + + if (!canPeepholeOptimize) + { + InstEmitCommon.RestoreNzcvFlags(context, oldFlags.Operand); + } + + if (!zero) + { + rmReg.Dispose(); + } + } + + private static void WriteUpdateFpsrNzcv(CodeGenContext context) + { + using ScopedRegister fpsrRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + using ScopedRegister flagsRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); + + Operand ctx = InstEmitSystem.Register(context.RegisterAllocator.FixedContextRegister); + + context.Arm64Assembler.LdrRiUn(fpsrRegister.Operand, ctx, NativeContextOffsets.FpFlagsBaseOffset); + + InstEmitCommon.GetCurrentFlags(context, flagsRegister.Operand); + + context.Arm64Assembler.Bfi(fpsrRegister.Operand, flagsRegister.Operand, 28, 4); + context.Arm64Assembler.StrRiUn(fpsrRegister.Operand, ctx, NativeContextOffsets.FpFlagsBaseOffset); + } + + private static bool CanFuseVcmpVmrs(CodeGenContext context, uint vcmpCond) + { + // Conditions might be different for the VCMP and VMRS instructions if they are inside a IT block, + // we don't bother to check right now, so just always skip if inside an IT block. + if (context.InITBlock) + { + return false; + } + + InstInfo nextInfo = context.PeekNextInstruction(); + + // We're looking for a VMRS instructions. + if (nextInfo.Name != InstName.Vmrs) + { + return false; + } + + // Conditions must match. + if (vcmpCond != (nextInfo.Encoding >> 28)) + { + return false; + } + + // Reg must be 1, Rt must be PC indicating VMRS to PSTATE.NZCV. + if (((nextInfo.Encoding >> 16) & 0xf) != 1 || ((nextInfo.Encoding >> 12) & 0xf) != RegisterUtils.PcRegister) + { + return false; + } + + context.SetSkipNextInstruction(); + + return true; + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpConvert.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpConvert.cs new file mode 100644 index 00000000..8e488695 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpConvert.cs @@ -0,0 +1,305 @@ +using System; +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitVfpConvert + { + public static void Vcvta(CodeGenContext context, uint rd, uint rm, bool op, uint size) + { + if (size == 3) + { + // F64 -> S32/U32 conversion on SIMD is not supported, so we convert it to a GPR, then insert it back into the SIMD register. + + if (op) + { + InstEmitNeonCommon.EmitScalarUnaryToGprTempF(context, rd, rm, size, 0, context.Arm64Assembler.FcvtasFloat); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryToGprTempF(context, rd, rm, size, 0, context.Arm64Assembler.FcvtauFloat); + } + } + else if (op) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FcvtasS, context.Arm64Assembler.FcvtasSH); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FcvtauS, context.Arm64Assembler.FcvtauSH); + } + } + + public static void Vcvtb(CodeGenContext context, uint rd, uint rm, uint sz, uint op) + { + EmitVcvtbVcvtt(context, rd, rm, sz, op, top: false); + } + + public static void Vcvtm(CodeGenContext context, uint rd, uint rm, bool op, uint size) + { + if (size == 3) + { + // F64 -> S32/U32 conversion on SIMD is not supported, so we convert it to a GPR, then insert it back into the SIMD register. + + if (op) + { + InstEmitNeonCommon.EmitScalarUnaryToGprTempF(context, rd, rm, size, 0, context.Arm64Assembler.FcvtmsFloat); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryToGprTempF(context, rd, rm, size, 0, context.Arm64Assembler.FcvtmuFloat); + } + } + else if (op) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FcvtmsS, context.Arm64Assembler.FcvtmsSH); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FcvtmuS, context.Arm64Assembler.FcvtmuSH); + } + } + + public static void Vcvtn(CodeGenContext context, uint rd, uint rm, bool op, uint size) + { + if (size == 3) + { + // F64 -> S32/U32 conversion on SIMD is not supported, so we convert it to a GPR, then insert it back into the SIMD register. + + if (op) + { + InstEmitNeonCommon.EmitScalarUnaryToGprTempF(context, rd, rm, size, 0, context.Arm64Assembler.FcvtnsFloat); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryToGprTempF(context, rd, rm, size, 0, context.Arm64Assembler.FcvtnuFloat); + } + } + else if (op) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FcvtnsS, context.Arm64Assembler.FcvtnsSH); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FcvtnuS, context.Arm64Assembler.FcvtnuSH); + } + } + + public static void Vcvtp(CodeGenContext context, uint rd, uint rm, bool op, uint size) + { + if (size == 3) + { + // F64 -> S32/U32 conversion on SIMD is not supported, so we convert it to a GPR, then insert it back into the SIMD register. + + if (op) + { + InstEmitNeonCommon.EmitScalarUnaryToGprTempF(context, rd, rm, size, 0, context.Arm64Assembler.FcvtpsFloat); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryToGprTempF(context, rd, rm, size, 0, context.Arm64Assembler.FcvtpuFloat); + } + } + else if (op) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FcvtpsS, context.Arm64Assembler.FcvtpsSH); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FcvtpuS, context.Arm64Assembler.FcvtpuSH); + } + } + + public static void VcvtDs(CodeGenContext context, uint rd, uint rm, uint size) + { + bool doubleToSingle = size == 3; + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + if (doubleToSingle) + { + // Double to single. + + using ScopedRegister rmReg = InstEmitNeonCommon.MoveScalarToSide(context, rm, false); + + context.Arm64Assembler.FcvtFloat(tempRegister.Operand, rmReg.Operand, 0, 1); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, true); + } + else + { + // Single to double. + + using ScopedRegister rmReg = InstEmitNeonCommon.MoveScalarToSide(context, rm, true); + + context.Arm64Assembler.FcvtFloat(tempRegister.Operand, rmReg.Operand, 1, 0); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, false); + } + } + + public static void VcvtIv(CodeGenContext context, uint rd, uint rm, bool unsigned, uint size) + { + if (size == 3) + { + // F64 -> S32/U32 conversion on SIMD is not supported, so we convert it to a GPR, then insert it back into the SIMD register. + + if (unsigned) + { + InstEmitNeonCommon.EmitScalarUnaryToGprTempF(context, rd, rm, size, 0, context.Arm64Assembler.FcvtzuFloatInt); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryToGprTempF(context, rd, rm, size, 0, context.Arm64Assembler.FcvtzsFloatInt); + } + } + else + { + if (unsigned) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FcvtzuIntS, context.Arm64Assembler.FcvtzuIntSH); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FcvtzsIntS, context.Arm64Assembler.FcvtzsIntSH); + } + } + } + + public static void VcvtVi(CodeGenContext context, uint rd, uint rm, bool unsigned, uint size) + { + if (size == 3) + { + // S32/U32 -> F64 conversion on SIMD is not supported, so we convert it to a GPR, then insert it back into the SIMD register. + + if (unsigned) + { + InstEmitNeonCommon.EmitScalarUnaryFromGprTempF(context, rd, rm, size, 0, context.Arm64Assembler.UcvtfFloatInt); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryFromGprTempF(context, rd, rm, size, 0, context.Arm64Assembler.ScvtfFloatInt); + } + } + else + { + if (unsigned) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.UcvtfIntS, context.Arm64Assembler.UcvtfIntSH); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.ScvtfIntS, context.Arm64Assembler.ScvtfIntSH); + } + } + } + + public static void VcvtXv(CodeGenContext context, uint rd, uint imm5, bool sx, uint sf, uint op, bool u) + { + Debug.Assert(op >> 1 == 0); + + bool unsigned = u; + bool toFixed = op == 1; + uint size = sf; + uint fbits = Math.Clamp((sx ? 32u : 16u) - imm5, 1, 8u << (int)size); + + if (toFixed) + { + if (unsigned) + { + InstEmitNeonCommon.EmitScalarUnaryFixedF(context, rd, rd, fbits, size, is16Bit: false, context.Arm64Assembler.FcvtzuFixS); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryFixedF(context, rd, rd, fbits, size, is16Bit: false, context.Arm64Assembler.FcvtzsFixS); + } + } + else + { + if (unsigned) + { + InstEmitNeonCommon.EmitScalarUnaryFixedF(context, rd, rd, fbits, size, is16Bit: !sx, context.Arm64Assembler.UcvtfFixS); + } + else + { + InstEmitNeonCommon.EmitScalarUnaryFixedF(context, rd, rd, fbits, size, is16Bit: !sx, context.Arm64Assembler.ScvtfFixS); + } + } + } + + public static void VcvtrIv(CodeGenContext context, uint rd, uint rm, uint op, uint size) + { + bool unsigned = (op & 1) == 0; + + Debug.Assert(size == 1 || size == 2 || size == 3); + + bool singleRegs = size != 3; + + using ScopedRegister rmReg = InstEmitNeonCommon.MoveScalarToSide(context, rm, singleRegs); + + using ScopedRegister tempRegister = InstEmitNeonCommon.PickSimdRegister(context.RegisterAllocator, rmReg); + + // Round using the FPCR rounding mode first, since the FCVTZ instructions will use the round to zero mode. + context.Arm64Assembler.FrintiFloat(tempRegister.Operand, rmReg.Operand, size ^ 2u); + + if (unsigned) + { + if (size == 1) + { + context.Arm64Assembler.FcvtzuIntSH(tempRegister.Operand, tempRegister.Operand); + } + else + { + context.Arm64Assembler.FcvtzuIntS(tempRegister.Operand, tempRegister.Operand, size & 1); + } + } + else + { + if (size == 1) + { + context.Arm64Assembler.FcvtzsIntSH(tempRegister.Operand, tempRegister.Operand); + } + else + { + context.Arm64Assembler.FcvtzsIntS(tempRegister.Operand, tempRegister.Operand, size & 1); + } + } + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + + public static void Vcvtt(CodeGenContext context, uint rd, uint rm, uint sz, uint op) + { + EmitVcvtbVcvtt(context, rd, rm, sz, op, top: true); + } + + public static void EmitVcvtbVcvtt(CodeGenContext context, uint rd, uint rm, uint sz, uint op, bool top) + { + bool usesDouble = sz == 1; + bool convertFromHalf = op == 0; + + using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempSimdRegisterScoped(); + + if (convertFromHalf) + { + // Half to single/double. + + using ScopedRegister rmReg = InstEmitNeonCommon.Move16BitScalarToSide(context, rm, top); + + context.Arm64Assembler.FcvtFloat(tempRegister.Operand, rmReg.Operand, usesDouble ? 1u : 0u, 3u); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, !usesDouble); + } + else + { + // Single/double to half. + + using ScopedRegister rmReg = InstEmitNeonCommon.MoveScalarToSide(context, rm, !usesDouble); + + context.Arm64Assembler.FcvtFloat(tempRegister.Operand, rmReg.Operand, 3u, usesDouble ? 1u : 0u); + + InstEmitNeonCommon.Insert16BitResult(context, tempRegister.Operand, rd, top); + } + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpMove.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpMove.cs new file mode 100644 index 00000000..5c1eefac --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpMove.cs @@ -0,0 +1,22 @@ +using Ryujinx.Cpu.LightningJit.CodeGen; + +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitVfpMove + { + public static void Vsel(CodeGenContext context, uint rd, uint rn, uint rm, uint cc, uint size) + { + bool singleRegs = size != 3; + uint cond = (cc << 2) | ((cc & 2) ^ ((cc << 1) & 2)); + + using ScopedRegister rnReg = InstEmitNeonCommon.MoveScalarToSide(context, rn, singleRegs); + using ScopedRegister rmReg = InstEmitNeonCommon.MoveScalarToSide(context, rm, singleRegs); + + using ScopedRegister tempRegister = InstEmitNeonCommon.PickSimdRegister(context.RegisterAllocator, rnReg, rmReg); + + context.Arm64Assembler.FcselFloat(tempRegister.Operand, rnReg.Operand, cond, rmReg.Operand, size ^ 2u); + + InstEmitNeonCommon.InsertResult(context, tempRegister.Operand, rd, singleRegs); + } + } +} diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpRound.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpRound.cs new file mode 100644 index 00000000..2826fa64 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpRound.cs @@ -0,0 +1,40 @@ +namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 +{ + static class InstEmitVfpRound + { + public static void Vrinta(CodeGenContext context, uint rd, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FrintaFloat); + } + + public static void Vrintm(CodeGenContext context, uint rd, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FrintmFloat); + } + + public static void Vrintn(CodeGenContext context, uint rd, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FrintnFloat); + } + + public static void Vrintp(CodeGenContext context, uint rd, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FrintpFloat); + } + + public static void Vrintr(CodeGenContext context, uint rd, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FrintiFloat); + } + + public static void Vrintx(CodeGenContext context, uint rd, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FrintxFloat); + } + + public static void Vrintz(CodeGenContext context, uint rd, uint rm, uint size) + { + InstEmitNeonCommon.EmitScalarUnaryF(context, rd, rm, size, context.Arm64Assembler.FrintzFloat); + } + } +} |