diff options
Diffstat (limited to 'ChocolArm64')
161 files changed, 0 insertions, 27032 deletions
diff --git a/ChocolArm64/ChocolArm64.csproj b/ChocolArm64/ChocolArm64.csproj deleted file mode 100644 index cccdd94d..00000000 --- a/ChocolArm64/ChocolArm64.csproj +++ /dev/null @@ -1,39 +0,0 @@ -<Project Sdk="Microsoft.NET.Sdk"> - - <PropertyGroup> - <TargetFramework>netcoreapp2.1</TargetFramework> - <RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers> - <Configurations>Debug;Release;Profile Debug;Profile Release</Configurations> - </PropertyGroup> - - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - </PropertyGroup> - - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Debug|AnyCPU'"> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - <DefineConstants>TRACE;USE_PROFILING</DefineConstants> - <Optimize>false</Optimize> - </PropertyGroup> - - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - </PropertyGroup> - - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Release|AnyCPU'"> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - <DefineConstants>TRACE;USE_PROFILING</DefineConstants> - <Optimize>true</Optimize> - </PropertyGroup> - - <ItemGroup> - <PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" /> - <PackageReference Include="System.Runtime.Intrinsics.Experimental" Version="4.5.0-rc1" /> - </ItemGroup> - - <ItemGroup> - <ProjectReference Include="..\Ryujinx.Profiler\Ryujinx.Profiler.csproj" /> - <ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" /> - </ItemGroup> - -</Project> diff --git a/ChocolArm64/Decoders/BitUtils.cs b/ChocolArm64/Decoders/BitUtils.cs deleted file mode 100644 index 8b9fb5e3..00000000 --- a/ChocolArm64/Decoders/BitUtils.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace ChocolArm64.Decoders -{ - static class BitUtils - { - public static int HighestBitSet32(int value) - { - for (int bit = 31; bit >= 0; bit--) - { - if (((value >> bit) & 1) != 0) - { - return bit; - } - } - - return -1; - } - - private static readonly sbyte[] HbsNibbleTbl = { -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 }; - - public static int HighestBitSetNibble(int value) => HbsNibbleTbl[value & 0b1111]; - - public static long Replicate(long bits, int size) - { - long output = 0; - - for (int bit = 0; bit < 64; bit += size) - { - output |= bits << bit; - } - - return output; - } - - public static long FillWithOnes(int bits) - { - return bits == 64 ? -1L : (1L << bits) - 1; - } - - public static int RotateRight(int bits, int shift, int size) - { - return (int)RotateRight((uint)bits, shift, size); - } - - public static uint RotateRight(uint bits, int shift, int size) - { - return (bits >> shift) | (bits << (size - shift)); - } - - public static long RotateRight(long bits, int shift, int size) - { - return (long)RotateRight((ulong)bits, shift, size); - } - - public static ulong RotateRight(ulong bits, int shift, int size) - { - return (bits >> shift) | (bits << (size - shift)); - } - } -} diff --git a/ChocolArm64/Decoders/Block.cs b/ChocolArm64/Decoders/Block.cs deleted file mode 100644 index fc87fd18..00000000 --- a/ChocolArm64/Decoders/Block.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace ChocolArm64.Decoders -{ - class Block - { - public ulong Address { get; set; } - public ulong EndAddress { get; set; } - - public Block Next { get; set; } - public Block Branch { get; set; } - - public List<OpCode64> OpCodes { get; private set; } - - public Block() - { - OpCodes = new List<OpCode64>(); - } - - public Block(ulong address) : this() - { - Address = address; - } - - public void Split(Block rightBlock) - { - int splitIndex = BinarySearch(OpCodes, rightBlock.Address); - - if ((ulong)OpCodes[splitIndex].Position < rightBlock.Address) - { - splitIndex++; - } - - int splitCount = OpCodes.Count - splitIndex; - - if (splitCount <= 0) - { - throw new ArgumentException("Can't split at right block address."); - } - - rightBlock.EndAddress = EndAddress; - - rightBlock.Next = Next; - rightBlock.Branch = Branch; - - rightBlock.OpCodes.AddRange(OpCodes.GetRange(splitIndex, splitCount)); - - EndAddress = rightBlock.Address; - - Next = rightBlock; - Branch = null; - - OpCodes.RemoveRange(splitIndex, splitCount); - } - - private static int BinarySearch(List<OpCode64> opCodes, ulong address) - { - int left = 0; - int middle = 0; - int right = opCodes.Count - 1; - - while (left <= right) - { - int size = right - left; - - middle = left + (size >> 1); - - OpCode64 opCode = opCodes[middle]; - - if (address == (ulong)opCode.Position) - { - break; - } - - if (address < (ulong)opCode.Position) - { - right = middle - 1; - } - else - { - left = middle + 1; - } - } - - return middle; - } - - public OpCode64 GetLastOp() - { - if (OpCodes.Count > 0) - { - return OpCodes[OpCodes.Count - 1]; - } - - return null; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/Condition.cs b/ChocolArm64/Decoders/Condition.cs deleted file mode 100644 index ef4b2959..00000000 --- a/ChocolArm64/Decoders/Condition.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace ChocolArm64.Decoders -{ - enum Condition - { - Eq = 0, - Ne = 1, - GeUn = 2, - LtUn = 3, - Mi = 4, - Pl = 5, - Vs = 6, - Vc = 7, - GtUn = 8, - LeUn = 9, - Ge = 10, - Lt = 11, - Gt = 12, - Le = 13, - Al = 14, - Nv = 15 - } - - static class ConditionExtensions - { - public static Condition Invert(this Condition cond) - { - // Bit 0 of all conditions is basically a negation bit, so - // inverting this bit has the effect of inverting the condition. - return (Condition)((int)cond ^ 1); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/DataOp.cs b/ChocolArm64/Decoders/DataOp.cs deleted file mode 100644 index b7768bb4..00000000 --- a/ChocolArm64/Decoders/DataOp.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ChocolArm64.Decoders -{ - enum DataOp - { - Adr = 0, - Arithmetic = 1, - Logical = 2, - BitField = 3 - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/Decoder.cs b/ChocolArm64/Decoders/Decoder.cs deleted file mode 100644 index a1eeee15..00000000 --- a/ChocolArm64/Decoders/Decoder.cs +++ /dev/null @@ -1,379 +0,0 @@ -using ChocolArm64.Instructions; -using ChocolArm64.Memory; -using ChocolArm64.State; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Reflection.Emit; - -namespace ChocolArm64.Decoders -{ - static class Decoder - { - private delegate object OpActivator(Inst inst, long position, int opCode); - - private static ConcurrentDictionary<Type, OpActivator> _opActivators; - - static Decoder() - { - _opActivators = new ConcurrentDictionary<Type, OpActivator>(); - } - - public static Block[] DecodeBasicBlock(MemoryManager memory, ulong address, ExecutionMode mode) - { - Block block = new Block(address); - - FillBlock(memory, mode, block, ulong.MaxValue); - - OpCode64 lastOp = block.GetLastOp(); - - if (IsBranch(lastOp) && !IsCall(lastOp) && lastOp is IOpCodeBImm op) - { - // It's possible that the branch on this block lands on the middle of the block. - // This is more common on tight loops. In this case, we can improve the codegen - // a bit by changing the CFG and either making the branch point to the same block - // (which indicates that the block is a loop that jumps back to the start), and the - // other possible case is a jump somewhere on the middle of the block, which is - // also a loop, but in this case we need to split the block in half. - if ((ulong)op.Imm == address) - { - block.Branch = block; - } - else if ((ulong)op.Imm > address && - (ulong)op.Imm < block.EndAddress) - { - Block rightBlock = new Block((ulong)op.Imm); - - block.Split(rightBlock); - - return new Block[] { block, rightBlock }; - } - } - - return new Block[] { block }; - } - - public static Block[] DecodeSubroutine(MemoryManager memory, ulong address, ExecutionMode mode) - { - List<Block> blocks = new List<Block>(); - - Queue<Block> workQueue = new Queue<Block>(); - - Dictionary<ulong, Block> visited = new Dictionary<ulong, Block>(); - - Block GetBlock(ulong blkAddress) - { - if (!visited.TryGetValue(blkAddress, out Block block)) - { - block = new Block(blkAddress); - - workQueue.Enqueue(block); - - visited.Add(blkAddress, block); - } - - return block; - } - - GetBlock(address); - - while (workQueue.TryDequeue(out Block currBlock)) - { - // Check if the current block is inside another block. - if (BinarySearch(blocks, currBlock.Address, out int nBlkIndex)) - { - Block nBlock = blocks[nBlkIndex]; - - if (nBlock.Address == currBlock.Address) - { - throw new InvalidOperationException("Found duplicate block address on the list."); - } - - nBlock.Split(currBlock); - - blocks.Insert(nBlkIndex + 1, currBlock); - - continue; - } - - // If we have a block after the current one, set the limit address. - ulong limitAddress = ulong.MaxValue; - - if (nBlkIndex != blocks.Count) - { - Block nBlock = blocks[nBlkIndex]; - - int nextIndex = nBlkIndex + 1; - - if (nBlock.Address < currBlock.Address && nextIndex < blocks.Count) - { - limitAddress = blocks[nextIndex].Address; - } - else if (nBlock.Address > currBlock.Address) - { - limitAddress = blocks[nBlkIndex].Address; - } - } - - FillBlock(memory, mode, currBlock, limitAddress); - - if (currBlock.OpCodes.Count != 0) - { - // Set child blocks. "Branch" is the block the branch instruction - // points to (when taken), "Next" is the block at the next address, - // executed when the branch is not taken. For Unconditional Branches - // (except BL/BLR that are sub calls) or end of executable, Next is null. - OpCode64 lastOp = currBlock.GetLastOp(); - - bool isCall = IsCall(lastOp); - - if (lastOp is IOpCodeBImm op && !isCall) - { - currBlock.Branch = GetBlock((ulong)op.Imm); - } - - if (!IsUnconditionalBranch(lastOp) || isCall) - { - currBlock.Next = GetBlock(currBlock.EndAddress); - } - } - - // Insert the new block on the list (sorted by address). - if (blocks.Count != 0) - { - Block nBlock = blocks[nBlkIndex]; - - blocks.Insert(nBlkIndex + (nBlock.Address < currBlock.Address ? 1 : 0), currBlock); - } - else - { - blocks.Add(currBlock); - } - } - - return blocks.ToArray(); - } - - private static bool BinarySearch(List<Block> blocks, ulong address, out int index) - { - index = 0; - - int left = 0; - int right = blocks.Count - 1; - - while (left <= right) - { - int size = right - left; - - int middle = left + (size >> 1); - - Block block = blocks[middle]; - - index = middle; - - if (address >= block.Address && address < block.EndAddress) - { - return true; - } - - if (address < block.Address) - { - right = middle - 1; - } - else - { - left = middle + 1; - } - } - - return false; - } - - private static void FillBlock( - MemoryManager memory, - ExecutionMode mode, - Block block, - ulong limitAddress) - { - ulong address = block.Address; - - OpCode64 opCode; - - do - { - if (address >= limitAddress) - { - break; - } - - opCode = DecodeOpCode(memory, address, mode); - - block.OpCodes.Add(opCode); - - address += (ulong)opCode.OpCodeSizeInBytes; - } - while (!(IsBranch(opCode) || IsException(opCode))); - - block.EndAddress = address; - } - - private static bool IsBranch(OpCode64 opCode) - { - return opCode is OpCodeBImm64 || - opCode is OpCodeBReg64 || IsAarch32Branch(opCode); - } - - private static bool IsUnconditionalBranch(OpCode64 opCode) - { - return opCode is OpCodeBImmAl64 || - opCode is OpCodeBReg64 || IsAarch32UnconditionalBranch(opCode); - } - - private static bool IsAarch32UnconditionalBranch(OpCode64 opCode) - { - if (!(opCode is OpCode32 op)) - { - return false; - } - - // Note: On ARM32, most instructions have conditional execution, - // so there's no "Always" (unconditional) branch like on ARM64. - // We need to check if the condition is "Always" instead. - return IsAarch32Branch(op) && op.Cond >= Condition.Al; - } - - private static bool IsAarch32Branch(OpCode64 opCode) - { - // Note: On ARM32, most ALU operations can write to R15 (PC), - // so we must consider such operations as a branch in potential as well. - if (opCode is IOpCode32Alu opAlu && opAlu.Rd == RegisterAlias.Aarch32Pc) - { - return true; - } - - // Same thing for memory operations. We have the cases where PC is a target - // register (Rt == 15 or (mask & (1 << 15)) != 0), and cases where there is - // a write back to PC (wback == true && Rn == 15), however the later may - // be "undefined" depending on the CPU, so compilers should not produce that. - if (opCode is IOpCode32Mem || opCode is IOpCode32MemMult) - { - int rt, rn; - - bool wBack, isLoad; - - if (opCode is IOpCode32Mem opMem) - { - rt = opMem.Rt; - rn = opMem.Rn; - wBack = opMem.WBack; - isLoad = opMem.IsLoad; - - // For the dual load, we also need to take into account the - // case were Rt2 == 15 (PC). - if (rt == 14 && opMem.Emitter == InstEmit32.Ldrd) - { - rt = RegisterAlias.Aarch32Pc; - } - } - else if (opCode is IOpCode32MemMult opMemMult) - { - const int pcMask = 1 << RegisterAlias.Aarch32Pc; - - rt = (opMemMult.RegisterMask & pcMask) != 0 ? RegisterAlias.Aarch32Pc : 0; - rn = opMemMult.Rn; - wBack = opMemMult.PostOffset != 0; - isLoad = opMemMult.IsLoad; - } - else - { - throw new NotImplementedException($"The type \"{opCode.GetType().Name}\" is not implemented on the decoder."); - } - - if ((rt == RegisterAlias.Aarch32Pc && isLoad) || - (rn == RegisterAlias.Aarch32Pc && wBack)) - { - return true; - } - } - - // Explicit branch instructions. - return opCode is IOpCode32BImm || - opCode is IOpCode32BReg; - } - - private static bool IsCall(OpCode64 opCode) - { - // TODO (CQ): ARM32 support. - return opCode.Emitter == InstEmit.Bl || - opCode.Emitter == InstEmit.Blr; - } - - private static bool IsException(OpCode64 opCode) - { - return opCode.Emitter == InstEmit.Brk || - opCode.Emitter == InstEmit.Svc || - opCode.Emitter == InstEmit.Und; - } - - public static OpCode64 DecodeOpCode(MemoryManager memory, ulong address, ExecutionMode mode) - { - int opCode = memory.ReadInt32((long)address); - - Inst inst; - - if (mode == ExecutionMode.Aarch64) - { - inst = OpCodeTable.GetInstA64(opCode); - } - else - { - if (mode == ExecutionMode.Aarch32Arm) - { - inst = OpCodeTable.GetInstA32(opCode); - } - else /* if (mode == ExecutionMode.Aarch32Thumb) */ - { - inst = OpCodeTable.GetInstT32(opCode); - } - } - - OpCode64 decodedOpCode = new OpCode64(Inst.Undefined, (long)address, opCode); - - if (inst.Type != null) - { - decodedOpCode = MakeOpCode(inst.Type, inst, (long)address, opCode); - } - - return decodedOpCode; - } - - private static OpCode64 MakeOpCode(Type type, Inst inst, long position, int opCode) - { - if (type == null) - { - throw new ArgumentNullException(nameof(type)); - } - - OpActivator createInstance = _opActivators.GetOrAdd(type, CacheOpActivator); - - return (OpCode64)createInstance(inst, position, opCode); - } - - private static OpActivator CacheOpActivator(Type type) - { - Type[] argTypes = new Type[] { typeof(Inst), typeof(long), typeof(int) }; - - DynamicMethod mthd = new DynamicMethod($"Make{type.Name}", type, argTypes); - - ILGenerator generator = mthd.GetILGenerator(); - - generator.Emit(OpCodes.Ldarg_0); - generator.Emit(OpCodes.Ldarg_1); - generator.Emit(OpCodes.Ldarg_2); - generator.Emit(OpCodes.Newobj, type.GetConstructor(argTypes)); - generator.Emit(OpCodes.Ret); - - return (OpActivator)mthd.CreateDelegate(typeof(OpActivator)); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/DecoderHelper.cs b/ChocolArm64/Decoders/DecoderHelper.cs deleted file mode 100644 index 2209472b..00000000 --- a/ChocolArm64/Decoders/DecoderHelper.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; - -namespace ChocolArm64.Decoders -{ - static class DecoderHelper - { - public struct BitMask - { - public long WMask; - public long TMask; - public int Pos; - public int Shift; - public bool IsUndefined; - - public static BitMask Invalid => new BitMask { IsUndefined = true }; - } - - public static BitMask DecodeBitMask(int opCode, bool immediate) - { - int immS = (opCode >> 10) & 0x3f; - int immR = (opCode >> 16) & 0x3f; - - int n = (opCode >> 22) & 1; - int sf = (opCode >> 31) & 1; - - int length = BitUtils.HighestBitSet32((~immS & 0x3f) | (n << 6)); - - if (length < 1 || (sf == 0 && n != 0)) - { - return BitMask.Invalid; - } - - int size = 1 << length; - - int levels = size - 1; - - int s = immS & levels; - int r = immR & levels; - - if (immediate && s == levels) - { - return BitMask.Invalid; - } - - long wMask = BitUtils.FillWithOnes(s + 1); - long tMask = BitUtils.FillWithOnes(((s - r) & levels) + 1); - - if (r > 0) - { - wMask = BitUtils.RotateRight(wMask, r, size); - wMask &= BitUtils.FillWithOnes(size); - } - - return new BitMask() - { - WMask = BitUtils.Replicate(wMask, size), - TMask = BitUtils.Replicate(tMask, size), - - Pos = immS, - Shift = immR - }; - } - - public static long DecodeImm8Float(long imm, int size) - { - int e = 0, f = 0; - - switch (size) - { - case 0: e = 8; f = 23; break; - case 1: e = 11; f = 52; break; - - default: throw new ArgumentOutOfRangeException(nameof(size)); - } - - long value = (imm & 0x3f) << f - 4; - - long eBit = (imm >> 6) & 1; - long sBit = (imm >> 7) & 1; - - if (eBit != 0) - { - value |= (1L << e - 3) - 1 << f + 2; - } - - value |= (eBit ^ 1) << f + e - 1; - value |= sBit << f + e; - - return value; - } - - public static long DecodeImm24_2(int opCode) - { - return ((long)opCode << 40) >> 38; - } - - public static long DecodeImm26_2(int opCode) - { - return ((long)opCode << 38) >> 36; - } - - public static long DecodeImmS19_2(int opCode) - { - return (((long)opCode << 40) >> 43) & ~3; - } - - public static long DecodeImmS14_2(int opCode) - { - return (((long)opCode << 45) >> 48) & ~3; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCode32.cs b/ChocolArm64/Decoders/IOpCode32.cs deleted file mode 100644 index 3353ffe8..00000000 --- a/ChocolArm64/Decoders/IOpCode32.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCode32 : IOpCode64 - { - Condition Cond { get; } - - uint GetPc(); - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCode32Alu.cs b/ChocolArm64/Decoders/IOpCode32Alu.cs deleted file mode 100644 index d6f6d82a..00000000 --- a/ChocolArm64/Decoders/IOpCode32Alu.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCode32Alu : IOpCode32 - { - int Rd { get; } - int Rn { get; } - - bool SetFlags { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCode32BImm.cs b/ChocolArm64/Decoders/IOpCode32BImm.cs deleted file mode 100644 index b69c1e36..00000000 --- a/ChocolArm64/Decoders/IOpCode32BImm.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCode32BImm : IOpCode32, IOpCodeBImm { } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCode32BReg.cs b/ChocolArm64/Decoders/IOpCode32BReg.cs deleted file mode 100644 index a498b02d..00000000 --- a/ChocolArm64/Decoders/IOpCode32BReg.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCode32BReg : IOpCode32 - { - int Rm { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCode32Mem.cs b/ChocolArm64/Decoders/IOpCode32Mem.cs deleted file mode 100644 index 8ed25add..00000000 --- a/ChocolArm64/Decoders/IOpCode32Mem.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCode32Mem : IOpCode32 - { - int Rt { get; } - int Rn { get; } - - bool WBack { get; } - - bool IsLoad { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCode32MemMult.cs b/ChocolArm64/Decoders/IOpCode32MemMult.cs deleted file mode 100644 index d611c53b..00000000 --- a/ChocolArm64/Decoders/IOpCode32MemMult.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCode32MemMult : IOpCode32 - { - int Rn { get; } - - int RegisterMask { get; } - - int PostOffset { get; } - - bool IsLoad { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCode64.cs b/ChocolArm64/Decoders/IOpCode64.cs deleted file mode 100644 index e9407123..00000000 --- a/ChocolArm64/Decoders/IOpCode64.cs +++ /dev/null @@ -1,13 +0,0 @@ -using ChocolArm64.Instructions; -using ChocolArm64.State; - -namespace ChocolArm64.Decoders -{ - interface IOpCode64 - { - long Position { get; } - - InstEmitter Emitter { get; } - RegisterSize RegisterSize { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCodeAlu64.cs b/ChocolArm64/Decoders/IOpCodeAlu64.cs deleted file mode 100644 index b9a5fe9e..00000000 --- a/ChocolArm64/Decoders/IOpCodeAlu64.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCodeAlu64 : IOpCode64 - { - int Rd { get; } - int Rn { get; } - - DataOp DataOp { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCodeAluImm64.cs b/ChocolArm64/Decoders/IOpCodeAluImm64.cs deleted file mode 100644 index 4b305e27..00000000 --- a/ChocolArm64/Decoders/IOpCodeAluImm64.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCodeAluImm64 : IOpCodeAlu64 - { - long Imm { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCodeAluRs64.cs b/ChocolArm64/Decoders/IOpCodeAluRs64.cs deleted file mode 100644 index df503ae9..00000000 --- a/ChocolArm64/Decoders/IOpCodeAluRs64.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCodeAluRs64 : IOpCodeAlu64 - { - int Shift { get; } - int Rm { get; } - - ShiftType ShiftType { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCodeAluRx64.cs b/ChocolArm64/Decoders/IOpCodeAluRx64.cs deleted file mode 100644 index f41fc4d2..00000000 --- a/ChocolArm64/Decoders/IOpCodeAluRx64.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCodeAluRx64 : IOpCodeAlu64 - { - int Shift { get; } - int Rm { get; } - - IntType IntType { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCodeBImm.cs b/ChocolArm64/Decoders/IOpCodeBImm.cs deleted file mode 100644 index f0c6a832..00000000 --- a/ChocolArm64/Decoders/IOpCodeBImm.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCodeBImm : IOpCode64 - { - long Imm { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCodeCond64.cs b/ChocolArm64/Decoders/IOpCodeCond64.cs deleted file mode 100644 index 2c465406..00000000 --- a/ChocolArm64/Decoders/IOpCodeCond64.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCodeCond64 : IOpCode64 - { - Condition Cond { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCodeLit64.cs b/ChocolArm64/Decoders/IOpCodeLit64.cs deleted file mode 100644 index c6dc2c7f..00000000 --- a/ChocolArm64/Decoders/IOpCodeLit64.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCodeLit64 : IOpCode64 - { - int Rt { get; } - long Imm { get; } - int Size { get; } - bool Signed { get; } - bool Prefetch { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IOpCodeSimd64.cs b/ChocolArm64/Decoders/IOpCodeSimd64.cs deleted file mode 100644 index fc8f54d6..00000000 --- a/ChocolArm64/Decoders/IOpCodeSimd64.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ChocolArm64.Decoders -{ - interface IOpCodeSimd64 : IOpCode64 - { - int Size { get; } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/IntType.cs b/ChocolArm64/Decoders/IntType.cs deleted file mode 100644 index 70f833ec..00000000 --- a/ChocolArm64/Decoders/IntType.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace ChocolArm64.Decoders -{ - enum IntType - { - UInt8 = 0, - UInt16 = 1, - UInt32 = 2, - UInt64 = 3, - Int8 = 4, - Int16 = 5, - Int32 = 6, - Int64 = 7 - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCode32.cs b/ChocolArm64/Decoders/OpCode32.cs deleted file mode 100644 index 1909757c..00000000 --- a/ChocolArm64/Decoders/OpCode32.cs +++ /dev/null @@ -1,24 +0,0 @@ -using ChocolArm64.Instructions; -using ChocolArm64.State; - -namespace ChocolArm64.Decoders -{ - class OpCode32 : OpCode64 - { - public Condition Cond { get; protected set; } - - public OpCode32(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - RegisterSize = RegisterSize.Int32; - - Cond = (Condition)((uint)opCode >> 28); - } - - public uint GetPc() - { - // Due to backwards compatibility and legacy behavior of ARMv4 CPUs pipeline, - // the PC actually points 2 instructions ahead. - return (uint)Position + (uint)OpCodeSizeInBytes * 2; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCode32Alu.cs b/ChocolArm64/Decoders/OpCode32Alu.cs deleted file mode 100644 index 0cf06696..00000000 --- a/ChocolArm64/Decoders/OpCode32Alu.cs +++ /dev/null @@ -1,20 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCode32Alu : OpCode32, IOpCode32Alu - { - public int Rd { get; private set; } - public int Rn { get; private set; } - - public bool SetFlags { get; private set; } - - public OpCode32Alu(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rd = (opCode >> 12) & 0xf; - Rn = (opCode >> 16) & 0xf; - - SetFlags = ((opCode >> 20) & 1) != 0; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCode32AluImm.cs b/ChocolArm64/Decoders/OpCode32AluImm.cs deleted file mode 100644 index 4302f117..00000000 --- a/ChocolArm64/Decoders/OpCode32AluImm.cs +++ /dev/null @@ -1,21 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCode32AluImm : OpCode32Alu - { - public int Imm { get; private set; } - - public bool IsRotated { get; private set; } - - public OpCode32AluImm(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - int value = (opCode >> 0) & 0xff; - int shift = (opCode >> 8) & 0xf; - - Imm = BitUtils.RotateRight(value, shift * 2, 32); - - IsRotated = shift != 0; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCode32AluRsImm.cs b/ChocolArm64/Decoders/OpCode32AluRsImm.cs deleted file mode 100644 index f23916be..00000000 --- a/ChocolArm64/Decoders/OpCode32AluRsImm.cs +++ /dev/null @@ -1,20 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCode32AluRsImm : OpCode32Alu - { - public int Rm { get; private set; } - public int Imm { get; private set; } - - public ShiftType ShiftType { get; private set; } - - public OpCode32AluRsImm(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rm = (opCode >> 0) & 0xf; - Imm = (opCode >> 7) & 0x1f; - - ShiftType = (ShiftType)((opCode >> 5) & 3); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCode32BImm.cs b/ChocolArm64/Decoders/OpCode32BImm.cs deleted file mode 100644 index 7f3c29a6..00000000 --- a/ChocolArm64/Decoders/OpCode32BImm.cs +++ /dev/null @@ -1,29 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCode32BImm : OpCode32, IOpCode32BImm - { - public long Imm { get; private set; } - - public OpCode32BImm(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - uint pc = GetPc(); - - // When the condition is never, the instruction is BLX to Thumb mode. - if (Cond != Condition.Nv) - { - pc &= ~3u; - } - - Imm = pc + DecoderHelper.DecodeImm24_2(opCode); - - if (Cond == Condition.Nv) - { - long H = (opCode >> 23) & 2; - - Imm |= H; - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCode32BReg.cs b/ChocolArm64/Decoders/OpCode32BReg.cs deleted file mode 100644 index 4a0fa537..00000000 --- a/ChocolArm64/Decoders/OpCode32BReg.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCode32BReg : OpCode32, IOpCode32BReg - { - public int Rm { get; private set; } - - public OpCode32BReg(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rm = opCode & 0xf; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCode32Mem.cs b/ChocolArm64/Decoders/OpCode32Mem.cs deleted file mode 100644 index ed648a5f..00000000 --- a/ChocolArm64/Decoders/OpCode32Mem.cs +++ /dev/null @@ -1,37 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCode32Mem : OpCode32, IOpCode32Mem - { - public int Rt { get; private set; } - public int Rn { get; private set; } - - public int Imm { get; protected set; } - - public bool Index { get; private set; } - public bool Add { get; private set; } - public bool WBack { get; private set; } - public bool Unprivileged { get; private set; } - - public bool IsLoad { get; private set; } - - public OpCode32Mem(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rt = (opCode >> 12) & 0xf; - Rn = (opCode >> 16) & 0xf; - - bool isLoad = (opCode & (1 << 20)) != 0; - bool w = (opCode & (1 << 21)) != 0; - bool u = (opCode & (1 << 23)) != 0; - bool p = (opCode & (1 << 24)) != 0; - - Index = p; - Add = u; - WBack = !p || w; - Unprivileged = !p && w; - - IsLoad = isLoad || inst.Emitter == InstEmit32.Ldrd; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCode32MemImm.cs b/ChocolArm64/Decoders/OpCode32MemImm.cs deleted file mode 100644 index ca46e08f..00000000 --- a/ChocolArm64/Decoders/OpCode32MemImm.cs +++ /dev/null @@ -1,12 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCode32MemImm : OpCode32Mem - { - public OpCode32MemImm(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Imm = opCode & 0xfff; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCode32MemImm8.cs b/ChocolArm64/Decoders/OpCode32MemImm8.cs deleted file mode 100644 index 02e446e8..00000000 --- a/ChocolArm64/Decoders/OpCode32MemImm8.cs +++ /dev/null @@ -1,15 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCode32MemImm8 : OpCode32Mem - { - public OpCode32MemImm8(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - int imm4L = (opCode >> 0) & 0xf; - int imm4H = (opCode >> 8) & 0xf; - - Imm = imm4L | (imm4H << 4); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCode32MemMult.cs b/ChocolArm64/Decoders/OpCode32MemMult.cs deleted file mode 100644 index 652da8a5..00000000 --- a/ChocolArm64/Decoders/OpCode32MemMult.cs +++ /dev/null @@ -1,57 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCode32MemMult : OpCode32, IOpCode32MemMult - { - public int Rn { get; private set; } - - public int RegisterMask { get; private set; } - public int Offset { get; private set; } - public int PostOffset { get; private set; } - - public bool IsLoad { get; private set; } - - public OpCode32MemMult(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rn = (opCode >> 16) & 0xf; - - bool isLoad = (opCode & (1 << 20)) != 0; - bool w = (opCode & (1 << 21)) != 0; - bool u = (opCode & (1 << 23)) != 0; - bool p = (opCode & (1 << 24)) != 0; - - RegisterMask = opCode & 0xffff; - - int regsSize = 0; - - for (int index = 0; index < 16; index++) - { - regsSize += (RegisterMask >> index) & 1; - } - - regsSize *= 4; - - if (!u) - { - Offset -= regsSize; - } - - if (u == p) - { - Offset += 4; - } - - if (w) - { - PostOffset = u ? regsSize : -regsSize; - } - else - { - PostOffset = 0; - } - - IsLoad = isLoad; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCode64.cs b/ChocolArm64/Decoders/OpCode64.cs deleted file mode 100644 index 1072228e..00000000 --- a/ChocolArm64/Decoders/OpCode64.cs +++ /dev/null @@ -1,40 +0,0 @@ -using ChocolArm64.Instructions; -using ChocolArm64.State; -using System; - -namespace ChocolArm64.Decoders -{ - class OpCode64 : IOpCode64 - { - public long Position { get; private set; } - public int RawOpCode { get; private set; } - - public int OpCodeSizeInBytes { get; protected set; } = 4; - - public InstEmitter Emitter { get; protected set; } - public RegisterSize RegisterSize { get; protected set; } - - public OpCode64(Inst inst, long position, int opCode) - { - Position = position; - RawOpCode = opCode; - - RegisterSize = RegisterSize.Int64; - - Emitter = inst.Emitter; - } - - public int GetBitsCount() - { - switch (RegisterSize) - { - case RegisterSize.Int32: return 32; - case RegisterSize.Int64: return 64; - case RegisterSize.Simd64: return 64; - case RegisterSize.Simd128: return 128; - } - - throw new InvalidOperationException(); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeAdr64.cs b/ChocolArm64/Decoders/OpCodeAdr64.cs deleted file mode 100644 index 98b2f07b..00000000 --- a/ChocolArm64/Decoders/OpCodeAdr64.cs +++ /dev/null @@ -1,18 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeAdr64 : OpCode64 - { - public int Rd { get; private set; } - public long Imm { get; private set; } - - public OpCodeAdr64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rd = opCode & 0x1f; - - Imm = DecoderHelper.DecodeImmS19_2(opCode); - Imm |= ((long)opCode >> 29) & 3; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeAlu64.cs b/ChocolArm64/Decoders/OpCodeAlu64.cs deleted file mode 100644 index b46fef4f..00000000 --- a/ChocolArm64/Decoders/OpCodeAlu64.cs +++ /dev/null @@ -1,23 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeAlu64 : OpCode64, IOpCodeAlu64 - { - public int Rd { get; protected set; } - public int Rn { get; private set; } - - public DataOp DataOp { get; private set; } - - public OpCodeAlu64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rd = (opCode >> 0) & 0x1f; - Rn = (opCode >> 5) & 0x1f; - DataOp = (DataOp)((opCode >> 24) & 0x3); - - RegisterSize = (opCode >> 31) != 0 - ? State.RegisterSize.Int64 - : State.RegisterSize.Int32; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeAluImm64.cs b/ChocolArm64/Decoders/OpCodeAluImm64.cs deleted file mode 100644 index 64ac08a7..00000000 --- a/ChocolArm64/Decoders/OpCodeAluImm64.cs +++ /dev/null @@ -1,39 +0,0 @@ -using ChocolArm64.Instructions; -using System; - -namespace ChocolArm64.Decoders -{ - class OpCodeAluImm64 : OpCodeAlu64, IOpCodeAluImm64 - { - public long Imm { get; private set; } - - public OpCodeAluImm64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - if (DataOp == DataOp.Arithmetic) - { - Imm = (opCode >> 10) & 0xfff; - - int shift = (opCode >> 22) & 3; - - Imm <<= shift * 12; - } - else if (DataOp == DataOp.Logical) - { - var bm = DecoderHelper.DecodeBitMask(opCode, true); - - if (bm.IsUndefined) - { - Emitter = InstEmit.Und; - - return; - } - - Imm = bm.WMask; - } - else - { - throw new ArgumentException(nameof(opCode)); - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeAluRs64.cs b/ChocolArm64/Decoders/OpCodeAluRs64.cs deleted file mode 100644 index bed840b8..00000000 --- a/ChocolArm64/Decoders/OpCodeAluRs64.cs +++ /dev/null @@ -1,29 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeAluRs64 : OpCodeAlu64, IOpCodeAluRs64 - { - public int Shift { get; private set; } - public int Rm { get; private set; } - - public ShiftType ShiftType { get; private set; } - - public OpCodeAluRs64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - int shift = (opCode >> 10) & 0x3f; - - if (shift >= GetBitsCount()) - { - Emitter = InstEmit.Und; - - return; - } - - Shift = shift; - - Rm = (opCode >> 16) & 0x1f; - ShiftType = (ShiftType)((opCode >> 22) & 0x3); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeAluRx64.cs b/ChocolArm64/Decoders/OpCodeAluRx64.cs deleted file mode 100644 index 24cee056..00000000 --- a/ChocolArm64/Decoders/OpCodeAluRx64.cs +++ /dev/null @@ -1,19 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeAluRx64 : OpCodeAlu64, IOpCodeAluRx64 - { - public int Shift { get; private set; } - public int Rm { get; private set; } - - public IntType IntType { get; private set; } - - public OpCodeAluRx64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Shift = (opCode >> 10) & 0x7; - IntType = (IntType)((opCode >> 13) & 0x7); - Rm = (opCode >> 16) & 0x1f; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeBImm64.cs b/ChocolArm64/Decoders/OpCodeBImm64.cs deleted file mode 100644 index bb5326ce..00000000 --- a/ChocolArm64/Decoders/OpCodeBImm64.cs +++ /dev/null @@ -1,11 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeBImm64 : OpCode64, IOpCodeBImm - { - public long Imm { get; protected set; } - - public OpCodeBImm64(Inst inst, long position, int opCode) : base(inst, position, opCode) { } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeBImmAl64.cs b/ChocolArm64/Decoders/OpCodeBImmAl64.cs deleted file mode 100644 index f419ffa0..00000000 --- a/ChocolArm64/Decoders/OpCodeBImmAl64.cs +++ /dev/null @@ -1,12 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeBImmAl64 : OpCodeBImm64 - { - public OpCodeBImmAl64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Imm = position + DecoderHelper.DecodeImm26_2(opCode); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeBImmCmp64.cs b/ChocolArm64/Decoders/OpCodeBImmCmp64.cs deleted file mode 100644 index 2e674a54..00000000 --- a/ChocolArm64/Decoders/OpCodeBImmCmp64.cs +++ /dev/null @@ -1,20 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeBImmCmp64 : OpCodeBImm64 - { - public int Rt { get; private set; } - - public OpCodeBImmCmp64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rt = opCode & 0x1f; - - Imm = position + DecoderHelper.DecodeImmS19_2(opCode); - - RegisterSize = (opCode >> 31) != 0 - ? State.RegisterSize.Int64 - : State.RegisterSize.Int32; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeBImmCond64.cs b/ChocolArm64/Decoders/OpCodeBImmCond64.cs deleted file mode 100644 index ca7df554..00000000 --- a/ChocolArm64/Decoders/OpCodeBImmCond64.cs +++ /dev/null @@ -1,25 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeBImmCond64 : OpCodeBImm64, IOpCodeCond64 - { - public Condition Cond { get; private set; } - - public OpCodeBImmCond64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - int o0 = (opCode >> 4) & 1; - - if (o0 != 0) - { - Emitter = InstEmit.Und; - - return; - } - - Cond = (Condition)(opCode & 0xf); - - Imm = position + DecoderHelper.DecodeImmS19_2(opCode); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeBImmTest64.cs b/ChocolArm64/Decoders/OpCodeBImmTest64.cs deleted file mode 100644 index a2e8baea..00000000 --- a/ChocolArm64/Decoders/OpCodeBImmTest64.cs +++ /dev/null @@ -1,20 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeBImmTest64 : OpCodeBImm64 - { - public int Rt { get; private set; } - public int Pos { get; private set; } - - public OpCodeBImmTest64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rt = opCode & 0x1f; - - Imm = position + DecoderHelper.DecodeImmS14_2(opCode); - - Pos = (opCode >> 19) & 0x1f; - Pos |= (opCode >> 26) & 0x20; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeBReg64.cs b/ChocolArm64/Decoders/OpCodeBReg64.cs deleted file mode 100644 index 74dbff58..00000000 --- a/ChocolArm64/Decoders/OpCodeBReg64.cs +++ /dev/null @@ -1,24 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeBReg64 : OpCode64 - { - public int Rn { get; private set; } - - public OpCodeBReg64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - int op4 = (opCode >> 0) & 0x1f; - int op2 = (opCode >> 16) & 0x1f; - - if (op2 != 0b11111 || op4 != 0b00000) - { - Emitter = InstEmit.Und; - - return; - } - - Rn = (opCode >> 5) & 0x1f; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeBfm64.cs b/ChocolArm64/Decoders/OpCodeBfm64.cs deleted file mode 100644 index 6891a8f4..00000000 --- a/ChocolArm64/Decoders/OpCodeBfm64.cs +++ /dev/null @@ -1,29 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeBfm64 : OpCodeAlu64 - { - public long WMask { get; private set; } - public long TMask { get; private set; } - public int Pos { get; private set; } - public int Shift { get; private set; } - - public OpCodeBfm64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - var bm = DecoderHelper.DecodeBitMask(opCode, false); - - if (bm.IsUndefined) - { - Emitter = InstEmit.Und; - - return; - } - - WMask = bm.WMask; - TMask = bm.TMask; - Pos = bm.Pos; - Shift = bm.Shift; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeCcmp64.cs b/ChocolArm64/Decoders/OpCodeCcmp64.cs deleted file mode 100644 index d65a24a4..00000000 --- a/ChocolArm64/Decoders/OpCodeCcmp64.cs +++ /dev/null @@ -1,31 +0,0 @@ -using ChocolArm64.Instructions; -using ChocolArm64.State; - -namespace ChocolArm64.Decoders -{ - class OpCodeCcmp64 : OpCodeAlu64, IOpCodeCond64 - { - public int Nzcv { get; private set; } - protected int RmImm; - - public Condition Cond { get; private set; } - - public OpCodeCcmp64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - int o3 = (opCode >> 4) & 1; - - if (o3 != 0) - { - Emitter = InstEmit.Und; - - return; - } - - Nzcv = (opCode >> 0) & 0xf; - Cond = (Condition)((opCode >> 12) & 0xf); - RmImm = (opCode >> 16) & 0x1f; - - Rd = RegisterAlias.Zr; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeCcmpImm64.cs b/ChocolArm64/Decoders/OpCodeCcmpImm64.cs deleted file mode 100644 index 78d5de55..00000000 --- a/ChocolArm64/Decoders/OpCodeCcmpImm64.cs +++ /dev/null @@ -1,11 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeCcmpImm64 : OpCodeCcmp64, IOpCodeAluImm64 - { - public long Imm => RmImm; - - public OpCodeCcmpImm64(Inst inst, long position, int opCode) : base(inst, position, opCode) { } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeCcmpReg64.cs b/ChocolArm64/Decoders/OpCodeCcmpReg64.cs deleted file mode 100644 index a0544d98..00000000 --- a/ChocolArm64/Decoders/OpCodeCcmpReg64.cs +++ /dev/null @@ -1,15 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeCcmpReg64 : OpCodeCcmp64, IOpCodeAluRs64 - { - public int Rm => RmImm; - - public int Shift => 0; - - public ShiftType ShiftType => ShiftType.Lsl; - - public OpCodeCcmpReg64(Inst inst, long position, int opCode) : base(inst, position, opCode) { } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeCsel64.cs b/ChocolArm64/Decoders/OpCodeCsel64.cs deleted file mode 100644 index 108a2798..00000000 --- a/ChocolArm64/Decoders/OpCodeCsel64.cs +++ /dev/null @@ -1,17 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeCsel64 : OpCodeAlu64, IOpCodeCond64 - { - public int Rm { get; private set; } - - public Condition Cond { get; private set; } - - public OpCodeCsel64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rm = (opCode >> 16) & 0x1f; - Cond = (Condition)((opCode >> 12) & 0xf); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeException64.cs b/ChocolArm64/Decoders/OpCodeException64.cs deleted file mode 100644 index 2554124c..00000000 --- a/ChocolArm64/Decoders/OpCodeException64.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeException64 : OpCode64 - { - public int Id { get; private set; } - - public OpCodeException64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Id = (opCode >> 5) & 0xffff; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeMem64.cs b/ChocolArm64/Decoders/OpCodeMem64.cs deleted file mode 100644 index 36e67583..00000000 --- a/ChocolArm64/Decoders/OpCodeMem64.cs +++ /dev/null @@ -1,19 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeMem64 : OpCode64 - { - public int Rt { get; protected set; } - public int Rn { get; protected set; } - public int Size { get; protected set; } - public bool Extend64 { get; protected set; } - - public OpCodeMem64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rt = (opCode >> 0) & 0x1f; - Rn = (opCode >> 5) & 0x1f; - Size = (opCode >> 30) & 0x3; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeMemEx64.cs b/ChocolArm64/Decoders/OpCodeMemEx64.cs deleted file mode 100644 index 39935eb3..00000000 --- a/ChocolArm64/Decoders/OpCodeMemEx64.cs +++ /dev/null @@ -1,16 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeMemEx64 : OpCodeMem64 - { - public int Rt2 { get; private set; } - public int Rs { get; private set; } - - public OpCodeMemEx64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rt2 = (opCode >> 10) & 0x1f; - Rs = (opCode >> 16) & 0x1f; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeMemImm64.cs b/ChocolArm64/Decoders/OpCodeMemImm64.cs deleted file mode 100644 index 01a62ef5..00000000 --- a/ChocolArm64/Decoders/OpCodeMemImm64.cs +++ /dev/null @@ -1,53 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeMemImm64 : OpCodeMem64 - { - public long Imm { get; protected set; } - public bool WBack { get; protected set; } - public bool PostIdx { get; protected set; } - protected bool Unscaled { get; private set; } - - private enum MemOp - { - Unscaled = 0, - PostIndexed = 1, - Unprivileged = 2, - PreIndexed = 3, - Unsigned - } - - public OpCodeMemImm64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Extend64 = ((opCode >> 22) & 3) == 2; - WBack = ((opCode >> 24) & 1) == 0; - - // The type is not valid for the Unsigned Immediate 12-bits encoding, - // because the bits 11:10 are used for the larger Immediate offset. - MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned; - - PostIdx = type == MemOp.PostIndexed; - Unscaled = type == MemOp.Unscaled || - type == MemOp.Unprivileged; - - // Unscaled and Unprivileged doesn't write back, - // but they do use the 9-bits Signed Immediate. - if (Unscaled) - { - WBack = false; - } - - if (WBack || Unscaled) - { - // 9-bits Signed Immediate. - Imm = (opCode << 11) >> 23; - } - else - { - // 12-bits Unsigned Immediate. - Imm = ((opCode >> 10) & 0xfff) << Size; - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeMemLit64.cs b/ChocolArm64/Decoders/OpCodeMemLit64.cs deleted file mode 100644 index 29bfeee3..00000000 --- a/ChocolArm64/Decoders/OpCodeMemLit64.cs +++ /dev/null @@ -1,28 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeMemLit64 : OpCode64, IOpCodeLit64 - { - public int Rt { get; private set; } - public long Imm { get; private set; } - public int Size { get; private set; } - public bool Signed { get; private set; } - public bool Prefetch { get; private set; } - - public OpCodeMemLit64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rt = opCode & 0x1f; - - Imm = position + DecoderHelper.DecodeImmS19_2(opCode); - - switch ((opCode >> 30) & 3) - { - case 0: Size = 2; Signed = false; Prefetch = false; break; - case 1: Size = 3; Signed = false; Prefetch = false; break; - case 2: Size = 2; Signed = true; Prefetch = false; break; - case 3: Size = 0; Signed = false; Prefetch = true; break; - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeMemPair64.cs b/ChocolArm64/Decoders/OpCodeMemPair64.cs deleted file mode 100644 index 5b81c755..00000000 --- a/ChocolArm64/Decoders/OpCodeMemPair64.cs +++ /dev/null @@ -1,25 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeMemPair64 : OpCodeMemImm64 - { - public int Rt2 { get; private set; } - - public OpCodeMemPair64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rt2 = (opCode >> 10) & 0x1f; - WBack = ((opCode >> 23) & 0x1) != 0; - PostIdx = ((opCode >> 23) & 0x3) == 1; - Extend64 = ((opCode >> 30) & 0x3) == 1; - Size = ((opCode >> 31) & 0x1) | 2; - - DecodeImm(opCode); - } - - protected void DecodeImm(int opCode) - { - Imm = ((long)(opCode >> 15) << 57) >> (57 - Size); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeMemReg64.cs b/ChocolArm64/Decoders/OpCodeMemReg64.cs deleted file mode 100644 index 2eb734aa..00000000 --- a/ChocolArm64/Decoders/OpCodeMemReg64.cs +++ /dev/null @@ -1,20 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeMemReg64 : OpCodeMem64 - { - public bool Shift { get; private set; } - public int Rm { get; private set; } - - public IntType IntType { get; private set; } - - public OpCodeMemReg64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Shift = ((opCode >> 12) & 0x1) != 0; - IntType = (IntType)((opCode >> 13) & 0x7); - Rm = (opCode >> 16) & 0x1f; - Extend64 = ((opCode >> 22) & 0x3) == 2; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeMov64.cs b/ChocolArm64/Decoders/OpCodeMov64.cs deleted file mode 100644 index 7dbd9247..00000000 --- a/ChocolArm64/Decoders/OpCodeMov64.cs +++ /dev/null @@ -1,35 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeMov64 : OpCode64 - { - public int Rd { get; private set; } - public long Imm { get; private set; } - public int Pos { get; private set; } - - public OpCodeMov64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - int p1 = (opCode >> 22) & 1; - int sf = (opCode >> 31) & 1; - - if (sf == 0 && p1 != 0) - { - Emitter = InstEmit.Und; - - return; - } - - Rd = (opCode >> 0) & 0x1f; - Imm = (opCode >> 5) & 0xffff; - Pos = (opCode >> 21) & 0x3; - - Pos <<= 4; - Imm <<= Pos; - - RegisterSize = (opCode >> 31) != 0 - ? State.RegisterSize.Int64 - : State.RegisterSize.Int32; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeMul64.cs b/ChocolArm64/Decoders/OpCodeMul64.cs deleted file mode 100644 index 176b7b93..00000000 --- a/ChocolArm64/Decoders/OpCodeMul64.cs +++ /dev/null @@ -1,16 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeMul64 : OpCodeAlu64 - { - public int Rm { get; private set; } - public int Ra { get; private set; } - - public OpCodeMul64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Ra = (opCode >> 10) & 0x1f; - Rm = (opCode >> 16) & 0x1f; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimd64.cs b/ChocolArm64/Decoders/OpCodeSimd64.cs deleted file mode 100644 index a705e489..00000000 --- a/ChocolArm64/Decoders/OpCodeSimd64.cs +++ /dev/null @@ -1,25 +0,0 @@ -using ChocolArm64.Instructions; -using ChocolArm64.State; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimd64 : OpCode64, IOpCodeSimd64 - { - public int Rd { get; private set; } - public int Rn { get; private set; } - public int Opc { get; private set; } - public int Size { get; protected set; } - - public OpCodeSimd64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rd = (opCode >> 0) & 0x1f; - Rn = (opCode >> 5) & 0x1f; - Opc = (opCode >> 15) & 0x3; - Size = (opCode >> 22) & 0x3; - - RegisterSize = ((opCode >> 30) & 1) != 0 - ? RegisterSize.Simd128 - : RegisterSize.Simd64; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdCvt64.cs b/ChocolArm64/Decoders/OpCodeSimdCvt64.cs deleted file mode 100644 index 3181a85a..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdCvt64.cs +++ /dev/null @@ -1,21 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdCvt64 : OpCodeSimd64 - { - public int FBits { get; private set; } - - public OpCodeSimdCvt64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - int scale = (opCode >> 10) & 0x3f; - int sf = (opCode >> 31) & 0x1; - - FBits = 64 - scale; - - RegisterSize = sf != 0 - ? State.RegisterSize.Int64 - : State.RegisterSize.Int32; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdExt64.cs b/ChocolArm64/Decoders/OpCodeSimdExt64.cs deleted file mode 100644 index 1c57f19c..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdExt64.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdExt64 : OpCodeSimdReg64 - { - public int Imm4 { get; private set; } - - public OpCodeSimdExt64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Imm4 = (opCode >> 11) & 0xf; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdFcond64.cs b/ChocolArm64/Decoders/OpCodeSimdFcond64.cs deleted file mode 100644 index 47de231c..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdFcond64.cs +++ /dev/null @@ -1,17 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdFcond64 : OpCodeSimdReg64, IOpCodeCond64 - { - public int Nzcv { get; private set; } - - public Condition Cond { get; private set; } - - public OpCodeSimdFcond64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Nzcv = (opCode >> 0) & 0xf; - Cond = (Condition)((opCode >> 12) & 0xf); - } - } -} diff --git a/ChocolArm64/Decoders/OpCodeSimdFmov64.cs b/ChocolArm64/Decoders/OpCodeSimdFmov64.cs deleted file mode 100644 index 6752e185..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdFmov64.cs +++ /dev/null @@ -1,33 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdFmov64 : OpCode64, IOpCodeSimd64 - { - public int Rd { get; private set; } - public long Imm { get; private set; } - public int Size { get; private set; } - - public OpCodeSimdFmov64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - int imm5 = (opCode >> 5) & 0x1f; - int type = (opCode >> 22) & 0x3; - - if (imm5 != 0b00000 || type > 1) - { - Emitter = InstEmit.Und; - - return; - } - - Size = type; - - long imm; - - Rd = (opCode >> 0) & 0x1f; - imm = (opCode >> 13) & 0xff; - - Imm = DecoderHelper.DecodeImm8Float(imm, type); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdImm64.cs b/ChocolArm64/Decoders/OpCodeSimdImm64.cs deleted file mode 100644 index 27f586f1..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdImm64.cs +++ /dev/null @@ -1,100 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdImm64 : OpCode64, IOpCodeSimd64 - { - public int Rd { get; private set; } - public long Imm { get; private set; } - public int Size { get; private set; } - - public OpCodeSimdImm64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rd = opCode & 0x1f; - - int cMode = (opCode >> 12) & 0xf; - int op = (opCode >> 29) & 0x1; - - int modeLow = cMode & 1; - int modeHigh = cMode >> 1; - - long imm; - - imm = ((uint)opCode >> 5) & 0x1f; - imm |= ((uint)opCode >> 11) & 0xe0; - - if (modeHigh == 0b111) - { - Size = modeLow != 0 ? op : 3; - - switch (op | (modeLow << 1)) - { - case 0: - // 64-bits Immediate. - // Transform abcd efgh into abcd efgh abcd efgh ... - imm = (long)((ulong)imm * 0x0101010101010101); - break; - - case 1: - // 64-bits Immediate. - // Transform abcd efgh into aaaa aaaa bbbb bbbb ... - imm = (imm & 0xf0) >> 4 | (imm & 0x0f) << 4; - imm = (imm & 0xcc) >> 2 | (imm & 0x33) << 2; - imm = (imm & 0xaa) >> 1 | (imm & 0x55) << 1; - - imm = (long)((ulong)imm * 0x8040201008040201); - imm = (long)((ulong)imm & 0x8080808080808080); - - imm |= imm >> 4; - imm |= imm >> 2; - imm |= imm >> 1; - break; - - case 2: - case 3: - // Floating point Immediate. - imm = DecoderHelper.DecodeImm8Float(imm, Size); - break; - } - } - else if ((modeHigh & 0b110) == 0b100) - { - // 16-bits shifted Immediate. - Size = 1; imm <<= (modeHigh & 1) << 3; - } - else if ((modeHigh & 0b100) == 0b000) - { - // 32-bits shifted Immediate. - Size = 2; imm <<= modeHigh << 3; - } - else if ((modeHigh & 0b111) == 0b110) - { - // 32-bits shifted Immediate (fill with ones). - Size = 2; imm = ShlOnes(imm, 8 << modeLow); - } - else - { - // 8 bits without shift. - Size = 0; - } - - Imm = imm; - - RegisterSize = ((opCode >> 30) & 1) != 0 - ? State.RegisterSize.Simd128 - : State.RegisterSize.Simd64; - } - - private static long ShlOnes(long value, int shift) - { - if (shift != 0) - { - return value << shift | (long)(ulong.MaxValue >> (64 - shift)); - } - else - { - return value; - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdIns64.cs b/ChocolArm64/Decoders/OpCodeSimdIns64.cs deleted file mode 100644 index 3b25faeb..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdIns64.cs +++ /dev/null @@ -1,36 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdIns64 : OpCodeSimd64 - { - public int SrcIndex { get; private set; } - public int DstIndex { get; private set; } - - public OpCodeSimdIns64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - int imm4 = (opCode >> 11) & 0xf; - int imm5 = (opCode >> 16) & 0x1f; - - if (imm5 == 0b10000) - { - Emitter = InstEmit.Und; - - return; - } - - Size = imm5 & -imm5; - - switch (Size) - { - case 1: Size = 0; break; - case 2: Size = 1; break; - case 4: Size = 2; break; - case 8: Size = 3; break; - } - - SrcIndex = imm4 >> Size; - DstIndex = imm5 >> (Size + 1); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdMemImm64.cs b/ChocolArm64/Decoders/OpCodeSimdMemImm64.cs deleted file mode 100644 index 9fbab567..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdMemImm64.cs +++ /dev/null @@ -1,19 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdMemImm64 : OpCodeMemImm64, IOpCodeSimd64 - { - public OpCodeSimdMemImm64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Size |= (opCode >> 21) & 4; - - if (!WBack && !Unscaled && Size >= 4) - { - Imm <<= 4; - } - - Extend64 = false; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdMemLit64.cs b/ChocolArm64/Decoders/OpCodeSimdMemLit64.cs deleted file mode 100644 index c98ffd03..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdMemLit64.cs +++ /dev/null @@ -1,31 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdMemLit64 : OpCode64, IOpCodeSimd64, IOpCodeLit64 - { - public int Rt { get; private set; } - public long Imm { get; private set; } - public int Size { get; private set; } - public bool Signed => false; - public bool Prefetch => false; - - public OpCodeSimdMemLit64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - int opc = (opCode >> 30) & 3; - - if (opc == 3) - { - Emitter = InstEmit.Und; - - return; - } - - Rt = opCode & 0x1f; - - Imm = position + DecoderHelper.DecodeImmS19_2(opCode); - - Size = opc + 2; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdMemMs64.cs b/ChocolArm64/Decoders/OpCodeSimdMemMs64.cs deleted file mode 100644 index 83297c41..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdMemMs64.cs +++ /dev/null @@ -1,48 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdMemMs64 : OpCodeMemReg64, IOpCodeSimd64 - { - public int Reps { get; private set; } - public int SElems { get; private set; } - public int Elems { get; private set; } - public bool WBack { get; private set; } - - public OpCodeSimdMemMs64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - switch ((opCode >> 12) & 0xf) - { - case 0b0000: Reps = 1; SElems = 4; break; - case 0b0010: Reps = 4; SElems = 1; break; - case 0b0100: Reps = 1; SElems = 3; break; - case 0b0110: Reps = 3; SElems = 1; break; - case 0b0111: Reps = 1; SElems = 1; break; - case 0b1000: Reps = 1; SElems = 2; break; - case 0b1010: Reps = 2; SElems = 1; break; - - default: inst = Inst.Undefined; return; - } - - Size = (opCode >> 10) & 3; - WBack = ((opCode >> 23) & 1) != 0; - - bool q = ((opCode >> 30) & 1) != 0; - - if (!q && Size == 3 && SElems != 1) - { - inst = Inst.Undefined; - - return; - } - - Extend64 = false; - - RegisterSize = q - ? State.RegisterSize.Simd128 - : State.RegisterSize.Simd64; - - Elems = (GetBitsCount() >> 3) >> Size; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdMemPair64.cs b/ChocolArm64/Decoders/OpCodeSimdMemPair64.cs deleted file mode 100644 index 1b796742..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdMemPair64.cs +++ /dev/null @@ -1,16 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdMemPair64 : OpCodeMemPair64, IOpCodeSimd64 - { - public OpCodeSimdMemPair64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Size = ((opCode >> 30) & 3) + 2; - - Extend64 = false; - - DecodeImm(opCode); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdMemReg64.cs b/ChocolArm64/Decoders/OpCodeSimdMemReg64.cs deleted file mode 100644 index 4ccbbed2..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdMemReg64.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdMemReg64 : OpCodeMemReg64, IOpCodeSimd64 - { - public OpCodeSimdMemReg64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Size |= (opCode >> 21) & 4; - - Extend64 = false; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdMemSs64.cs b/ChocolArm64/Decoders/OpCodeSimdMemSs64.cs deleted file mode 100644 index 1b0ead33..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdMemSs64.cs +++ /dev/null @@ -1,97 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdMemSs64 : OpCodeMemReg64, IOpCodeSimd64 - { - public int SElems { get; private set; } - public int Index { get; private set; } - public bool Replicate { get; private set; } - public bool WBack { get; private set; } - - public OpCodeSimdMemSs64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - int size = (opCode >> 10) & 3; - int s = (opCode >> 12) & 1; - int sElems = (opCode >> 12) & 2; - int scale = (opCode >> 14) & 3; - int l = (opCode >> 22) & 1; - int q = (opCode >> 30) & 1; - - sElems |= (opCode >> 21) & 1; - - sElems++; - - int index = (q << 3) | (s << 2) | size; - - switch (scale) - { - case 1: - { - if ((size & 1) != 0) - { - inst = Inst.Undefined; - - return; - } - - index >>= 1; - - break; - } - - case 2: - { - if ((size & 2) != 0 || - ((size & 1) != 0 && s != 0)) - { - inst = Inst.Undefined; - - return; - } - - if ((size & 1) != 0) - { - index >>= 3; - - scale = 3; - } - else - { - index >>= 2; - } - - break; - } - - case 3: - { - if (l == 0 || s != 0) - { - inst = Inst.Undefined; - - return; - } - - scale = size; - - Replicate = true; - - break; - } - } - - Index = index; - SElems = sElems; - Size = scale; - - Extend64 = false; - - WBack = ((opCode >> 23) & 1) != 0; - - RegisterSize = q != 0 - ? State.RegisterSize.Simd128 - : State.RegisterSize.Simd64; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdReg64.cs b/ChocolArm64/Decoders/OpCodeSimdReg64.cs deleted file mode 100644 index 4bf462de..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdReg64.cs +++ /dev/null @@ -1,18 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdReg64 : OpCodeSimd64 - { - public bool Bit3 { get; private set; } - public int Ra { get; private set; } - public int Rm { get; protected set; } - - public OpCodeSimdReg64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Bit3 = ((opCode >> 3) & 0x1) != 0; - Ra = (opCode >> 10) & 0x1f; - Rm = (opCode >> 16) & 0x1f; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdRegElem64.cs b/ChocolArm64/Decoders/OpCodeSimdRegElem64.cs deleted file mode 100644 index 04e95861..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdRegElem64.cs +++ /dev/null @@ -1,31 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdRegElem64 : OpCodeSimdReg64 - { - public int Index { get; private set; } - - public OpCodeSimdRegElem64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - switch (Size) - { - case 1: - Index = (opCode >> 20) & 3 | - (opCode >> 9) & 4; - - Rm &= 0xf; - - break; - - case 2: - Index = (opCode >> 21) & 1 | - (opCode >> 10) & 2; - - break; - - default: Emitter = InstEmit.Und; return; - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs b/ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs deleted file mode 100644 index b5db7345..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs +++ /dev/null @@ -1,33 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdRegElemF64 : OpCodeSimdReg64 - { - public int Index { get; private set; } - - public OpCodeSimdRegElemF64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - switch ((opCode >> 21) & 3) // sz:L - { - case 0: // H:0 - Index = (opCode >> 10) & 2; // 0, 2 - - break; - - case 1: // H:1 - Index = (opCode >> 10) & 2; - Index++; // 1, 3 - - break; - - case 2: // H - Index = (opCode >> 11) & 1; // 0, 1 - - break; - - default: Emitter = InstEmit.Und; return; - } - } - } -} diff --git a/ChocolArm64/Decoders/OpCodeSimdShImm64.cs b/ChocolArm64/Decoders/OpCodeSimdShImm64.cs deleted file mode 100644 index d4cd88d1..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdShImm64.cs +++ /dev/null @@ -1,16 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdShImm64 : OpCodeSimd64 - { - public int Imm { get; private set; } - - public OpCodeSimdShImm64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Imm = (opCode >> 16) & 0x7f; - - Size = BitUtils.HighestBitSetNibble(Imm >> 3); - } - } -} diff --git a/ChocolArm64/Decoders/OpCodeSimdTbl64.cs b/ChocolArm64/Decoders/OpCodeSimdTbl64.cs deleted file mode 100644 index 13cc9090..00000000 --- a/ChocolArm64/Decoders/OpCodeSimdTbl64.cs +++ /dev/null @@ -1,12 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSimdTbl64 : OpCodeSimdReg64 - { - public OpCodeSimdTbl64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Size = ((opCode >> 13) & 3) + 1; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeSystem64.cs b/ChocolArm64/Decoders/OpCodeSystem64.cs deleted file mode 100644 index 41c51565..00000000 --- a/ChocolArm64/Decoders/OpCodeSystem64.cs +++ /dev/null @@ -1,24 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeSystem64 : OpCode64 - { - public int Rt { get; private set; } - public int Op2 { get; private set; } - public int CRm { get; private set; } - public int CRn { get; private set; } - public int Op1 { get; private set; } - public int Op0 { get; private set; } - - public OpCodeSystem64(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rt = (opCode >> 0) & 0x1f; - Op2 = (opCode >> 5) & 0x7; - CRm = (opCode >> 8) & 0xf; - CRn = (opCode >> 12) & 0xf; - Op1 = (opCode >> 16) & 0x7; - Op0 = ((opCode >> 19) & 0x1) | 2; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeT16.cs b/ChocolArm64/Decoders/OpCodeT16.cs deleted file mode 100644 index 005c470d..00000000 --- a/ChocolArm64/Decoders/OpCodeT16.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeT16 : OpCode32 - { - public OpCodeT16(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Cond = Condition.Al; - - OpCodeSizeInBytes = 2; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeT16AluImm8.cs b/ChocolArm64/Decoders/OpCodeT16AluImm8.cs deleted file mode 100644 index 52c059f4..00000000 --- a/ChocolArm64/Decoders/OpCodeT16AluImm8.cs +++ /dev/null @@ -1,22 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeT16AluImm8 : OpCodeT16, IOpCode32Alu - { - private int _rdn; - - public int Rd => _rdn; - public int Rn => _rdn; - - public bool SetFlags => false; - - public int Imm { get; private set; } - - public OpCodeT16AluImm8(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Imm = (opCode >> 0) & 0xff; - _rdn = (opCode >> 8) & 0x7; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/OpCodeT16BReg.cs b/ChocolArm64/Decoders/OpCodeT16BReg.cs deleted file mode 100644 index 29514700..00000000 --- a/ChocolArm64/Decoders/OpCodeT16BReg.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ChocolArm64.Instructions; - -namespace ChocolArm64.Decoders -{ - class OpCodeT16BReg : OpCodeT16, IOpCode32BReg - { - public int Rm { get; private set; } - - public OpCodeT16BReg(Inst inst, long position, int opCode) : base(inst, position, opCode) - { - Rm = (opCode >> 3) & 0xf; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Decoders/ShiftType.cs b/ChocolArm64/Decoders/ShiftType.cs deleted file mode 100644 index cad43103..00000000 --- a/ChocolArm64/Decoders/ShiftType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ChocolArm64.Decoders -{ - enum ShiftType - { - Lsl = 0, - Lsr = 1, - Asr = 2, - Ror = 3 - } -}
\ No newline at end of file diff --git a/ChocolArm64/Events/CpuTraceEventArgs.cs b/ChocolArm64/Events/CpuTraceEventArgs.cs deleted file mode 100644 index c12781ed..00000000 --- a/ChocolArm64/Events/CpuTraceEventArgs.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace ChocolArm64.Events -{ - public class CpuTraceEventArgs : EventArgs - { - public long Position { get; private set; } - - public CpuTraceEventArgs(long position) - { - Position = position; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Events/InstExceptionEventArgs.cs b/ChocolArm64/Events/InstExceptionEventArgs.cs deleted file mode 100644 index e3cc0ba0..00000000 --- a/ChocolArm64/Events/InstExceptionEventArgs.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace ChocolArm64.Events -{ - public class InstExceptionEventArgs : EventArgs - { - public long Position { get; private set; } - public int Id { get; private set; } - - public InstExceptionEventArgs(long position, int id) - { - Position = position; - Id = id; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Events/InstUndefinedEventArgs.cs b/ChocolArm64/Events/InstUndefinedEventArgs.cs deleted file mode 100644 index 3ad7ea8b..00000000 --- a/ChocolArm64/Events/InstUndefinedEventArgs.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace ChocolArm64.Events -{ - public class InstUndefinedEventArgs : EventArgs - { - public long Position { get; private set; } - public int RawOpCode { get; private set; } - - public InstUndefinedEventArgs(long position, int rawOpCode) - { - Position = position; - RawOpCode = rawOpCode; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/CryptoHelper.cs b/ChocolArm64/Instructions/CryptoHelper.cs deleted file mode 100644 index e9b6ed5f..00000000 --- a/ChocolArm64/Instructions/CryptoHelper.cs +++ /dev/null @@ -1,331 +0,0 @@ -// https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf - -using System; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -namespace ChocolArm64.Instructions -{ - static class CryptoHelper - { -#region "LookUp Tables" - private static readonly byte[] _sBox = new byte[] - { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 - }; - - private static readonly byte[] _invSBox = new byte[] - { - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d - }; - - private static readonly byte[] _gfMul02 = new byte[] - { - 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, - 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, - 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, - 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, - 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, - 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, - 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, - 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, - 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, - 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, - 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, - 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, - 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, - 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, - 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, - 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5 - }; - - private static readonly byte[] _gfMul03 = new byte[] - { - 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, - 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, - 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, - 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, - 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, - 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, - 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, - 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, - 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, - 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, - 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, - 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, - 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, - 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, - 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, - 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a - }; - - private static readonly byte[] _gfMul09 = new byte[] - { - 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, - 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, - 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, - 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, - 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, - 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, - 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, - 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, - 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, - 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, - 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, - 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, - 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, - 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, - 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, - 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46 - }; - - private static readonly byte[] _gfMul0B = new byte[] - { - 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, - 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, - 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, - 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, - 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, - 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, - 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, - 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, - 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, - 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, - 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, - 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, - 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, - 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, - 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, - 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3 - }; - - private static readonly byte[] _gfMul0D = new byte[] - { - 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, - 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, - 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, - 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, - 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, - 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, - 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, - 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, - 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, - 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, - 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, - 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, - 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, - 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, - 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, - 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97 - }; - - private static readonly byte[] _gfMul0E = new byte[] - { - 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, - 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, - 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, - 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, - 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, - 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, - 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, - 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, - 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, - 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, - 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, - 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, - 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, - 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, - 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, - 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d - }; - - private static readonly byte[] _srPerm = new byte[] - { - 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3 - }; - - private static readonly byte[] _isrPerm = new byte[] - { - 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11 - }; -#endregion - - public static Vector128<float> AesInvMixColumns(Vector128<float> op) - { - byte[] inState = new byte[16]; - byte[] outState = new byte[16]; - - FromVectorToByteArray(op, inState); - - for (int columns = 0; columns <= 3; columns++) - { - int idx = columns << 2; - - byte row0 = inState[idx + 0]; // A, E, I, M: [row0, col0-col3] - byte row1 = inState[idx + 1]; // B, F, J, N: [row1, col0-col3] - byte row2 = inState[idx + 2]; // C, G, K, O: [row2, col0-col3] - byte row3 = inState[idx + 3]; // D, H, L, P: [row3, col0-col3] - - outState[idx + 0] = (byte)((uint)_gfMul0E[row0] ^ _gfMul0B[row1] ^ _gfMul0D[row2] ^ _gfMul09[row3]); - outState[idx + 1] = (byte)((uint)_gfMul09[row0] ^ _gfMul0E[row1] ^ _gfMul0B[row2] ^ _gfMul0D[row3]); - outState[idx + 2] = (byte)((uint)_gfMul0D[row0] ^ _gfMul09[row1] ^ _gfMul0E[row2] ^ _gfMul0B[row3]); - outState[idx + 3] = (byte)((uint)_gfMul0B[row0] ^ _gfMul0D[row1] ^ _gfMul09[row2] ^ _gfMul0E[row3]); - } - - FromByteArrayToVector(outState, ref op); - - return op; - } - - public static Vector128<float> AesInvShiftRows(Vector128<float> op) - { - byte[] inState = new byte[16]; - byte[] outState = new byte[16]; - - FromVectorToByteArray(op, inState); - - for (int idx = 0; idx <= 15; idx++) - { - outState[_isrPerm[idx]] = inState[idx]; - } - - FromByteArrayToVector(outState, ref op); - - return op; - } - - public static Vector128<float> AesInvSubBytes(Vector128<float> op) - { - byte[] inState = new byte[16]; - byte[] outState = new byte[16]; - - FromVectorToByteArray(op, inState); - - for (int idx = 0; idx <= 15; idx++) - { - outState[idx] = _invSBox[inState[idx]]; - } - - FromByteArrayToVector(outState, ref op); - - return op; - } - - public static Vector128<float> AesMixColumns(Vector128<float> op) - { - byte[] inState = new byte[16]; - byte[] outState = new byte[16]; - - FromVectorToByteArray(op, inState); - - for (int columns = 0; columns <= 3; columns++) - { - int idx = columns << 2; - - byte row0 = inState[idx + 0]; // A, E, I, M: [row0, col0-col3] - byte row1 = inState[idx + 1]; // B, F, J, N: [row1, col0-col3] - byte row2 = inState[idx + 2]; // C, G, K, O: [row2, col0-col3] - byte row3 = inState[idx + 3]; // D, H, L, P: [row3, col0-col3] - - outState[idx + 0] = (byte)((uint)_gfMul02[row0] ^ _gfMul03[row1] ^ row2 ^ row3); - outState[idx + 1] = (byte)((uint)row0 ^ _gfMul02[row1] ^ _gfMul03[row2] ^ row3); - outState[idx + 2] = (byte)((uint)row0 ^ row1 ^ _gfMul02[row2] ^ _gfMul03[row3]); - outState[idx + 3] = (byte)((uint)_gfMul03[row0] ^ row1 ^ row2 ^ _gfMul02[row3]); - } - - FromByteArrayToVector(outState, ref op); - - return op; - } - - public static Vector128<float> AesShiftRows(Vector128<float> op) - { - byte[] inState = new byte[16]; - byte[] outState = new byte[16]; - - FromVectorToByteArray(op, inState); - - for (int idx = 0; idx <= 15; idx++) - { - outState[_srPerm[idx]] = inState[idx]; - } - - FromByteArrayToVector(outState, ref op); - - return op; - } - - public static Vector128<float> AesSubBytes(Vector128<float> op) - { - byte[] inState = new byte[16]; - byte[] outState = new byte[16]; - - FromVectorToByteArray(op, inState); - - for (int idx = 0; idx <= 15; idx++) - { - outState[idx] = _sBox[inState[idx]]; - } - - FromByteArrayToVector(outState, ref op); - - return op; - } - - private unsafe static void FromVectorToByteArray(Vector128<float> op, byte[] state) - { - if (!Sse2.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - fixed (byte* ptr = &state[0]) - { - Sse2.Store(ptr, Sse.StaticCast<float, byte>(op)); - } - } - - private unsafe static void FromByteArrayToVector(byte[] state, ref Vector128<float> op) - { - if (!Sse2.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - fixed (byte* ptr = &state[0]) - { - op = Sse.StaticCast<byte, float>(Sse2.LoadVector128(ptr)); - } - } - } -} diff --git a/ChocolArm64/Instructions/Inst.cs b/ChocolArm64/Instructions/Inst.cs deleted file mode 100644 index de9ec18b..00000000 --- a/ChocolArm64/Instructions/Inst.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace ChocolArm64.Instructions -{ - struct Inst - { - public InstEmitter Emitter { get; } - public Type Type { get; } - - public static Inst Undefined => new Inst(InstEmit.Und, null); - - public Inst(InstEmitter emitter, Type type) - { - Emitter = emitter; - Type = type; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmit32Helper.cs b/ChocolArm64/Instructions/InstEmit32Helper.cs deleted file mode 100644 index c5d08b8a..00000000 --- a/ChocolArm64/Instructions/InstEmit32Helper.cs +++ /dev/null @@ -1,146 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; - -namespace ChocolArm64.Instructions -{ - static class InstEmit32Helper - { - public static bool IsThumb(OpCode64 op) - { - return op is OpCodeT16; - } - - public static void EmitLoadFromRegister(ILEmitterCtx context, int register) - { - if (register == RegisterAlias.Aarch32Pc) - { - OpCode32 op = (OpCode32)context.CurrOp; - - context.EmitLdc_I4((int)op.GetPc()); - } - else - { - context.EmitLdint(GetRegisterAlias(context.Mode, register)); - } - } - - public static void EmitStoreToRegister(ILEmitterCtx context, int register) - { - if (register == RegisterAlias.Aarch32Pc) - { - context.EmitStoreContext(); - - EmitBxWritePc(context); - } - else - { - context.EmitStint(GetRegisterAlias(context.Mode, register)); - } - } - - public static void EmitBxWritePc(ILEmitterCtx context) - { - context.Emit(OpCodes.Dup); - - context.EmitLdc_I4(1); - - context.Emit(OpCodes.And); - context.Emit(OpCodes.Dup); - - context.EmitStflg((int)PState.TBit); - - ILLabel lblArmMode = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.Emit(OpCodes.Brtrue_S, lblArmMode); - - context.EmitLdc_I4(~1); - - context.Emit(OpCodes.Br_S, lblEnd); - - context.MarkLabel(lblArmMode); - - context.EmitLdc_I4(~3); - - context.MarkLabel(lblEnd); - - context.Emit(OpCodes.And); - context.Emit(OpCodes.Conv_U8); - context.Emit(OpCodes.Ret); - } - - public static int GetRegisterAlias(Aarch32Mode mode, int register) - { - //Only registers >= 8 are banked, with registers in the range [8, 12] being - //banked for the FIQ mode, and registers 13 and 14 being banked for all modes. - if ((uint)register < 8) - { - return register; - } - - return GetBankedRegisterAlias(mode, register); - } - - public static int GetBankedRegisterAlias(Aarch32Mode mode, int register) - { - switch (register) - { - case 8: return mode == Aarch32Mode.Fiq - ? RegisterAlias.R8Fiq - : RegisterAlias.R8Usr; - - case 9: return mode == Aarch32Mode.Fiq - ? RegisterAlias.R9Fiq - : RegisterAlias.R9Usr; - - case 10: return mode == Aarch32Mode.Fiq - ? RegisterAlias.R10Fiq - : RegisterAlias.R10Usr; - - case 11: return mode == Aarch32Mode.Fiq - ? RegisterAlias.R11Fiq - : RegisterAlias.R11Usr; - - case 12: return mode == Aarch32Mode.Fiq - ? RegisterAlias.R12Fiq - : RegisterAlias.R12Usr; - - case 13: - switch (mode) - { - case Aarch32Mode.User: - case Aarch32Mode.System: return RegisterAlias.SpUsr; - case Aarch32Mode.Fiq: return RegisterAlias.SpFiq; - case Aarch32Mode.Irq: return RegisterAlias.SpIrq; - case Aarch32Mode.Supervisor: return RegisterAlias.SpSvc; - case Aarch32Mode.Abort: return RegisterAlias.SpAbt; - case Aarch32Mode.Hypervisor: return RegisterAlias.SpHyp; - case Aarch32Mode.Undefined: return RegisterAlias.SpUnd; - - default: throw new ArgumentException(nameof(mode)); - } - - case 14: - switch (mode) - { - case Aarch32Mode.User: - case Aarch32Mode.Hypervisor: - case Aarch32Mode.System: return RegisterAlias.LrUsr; - case Aarch32Mode.Fiq: return RegisterAlias.LrFiq; - case Aarch32Mode.Irq: return RegisterAlias.LrIrq; - case Aarch32Mode.Supervisor: return RegisterAlias.LrSvc; - case Aarch32Mode.Abort: return RegisterAlias.LrAbt; - case Aarch32Mode.Undefined: return RegisterAlias.LrUnd; - - default: throw new ArgumentException(nameof(mode)); - } - - default: throw new ArgumentOutOfRangeException(nameof(register)); - } - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitAlu.cs b/ChocolArm64/Instructions/InstEmitAlu.cs deleted file mode 100644 index 25bd8e64..00000000 --- a/ChocolArm64/Instructions/InstEmitAlu.cs +++ /dev/null @@ -1,422 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.Intrinsics.X86; - -using static ChocolArm64.Instructions.InstEmitAluHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Adc(ILEmitterCtx context) => EmitAdc(context, false); - public static void Adcs(ILEmitterCtx context) => EmitAdc(context, true); - - private static void EmitAdc(ILEmitterCtx context, bool setFlags) - { - EmitAluLoadOpers(context); - - context.Emit(OpCodes.Add); - - context.EmitLdflg((int)PState.CBit); - - Type[] mthdTypes = new Type[] { typeof(bool) }; - - MethodInfo mthdInfo = typeof(Convert).GetMethod(nameof(Convert.ToInt32), mthdTypes); - - context.EmitCall(mthdInfo); - - if (context.CurrOp.RegisterSize != RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U8); - } - - context.Emit(OpCodes.Add); - - if (setFlags) - { - context.EmitZnFlagCheck(); - - EmitAdcsCCheck(context); - EmitAddsVCheck(context); - } - - EmitAluStore(context); - } - - public static void Add(ILEmitterCtx context) => EmitAluOp(context, OpCodes.Add); - - public static void Adds(ILEmitterCtx context) - { - context.TryOptMarkCondWithoutCmp(); - - EmitAluLoadOpers(context); - - context.Emit(OpCodes.Add); - - context.EmitZnFlagCheck(); - - EmitAddsCCheck(context); - EmitAddsVCheck(context); - EmitAluStoreS(context); - } - - public static void And(ILEmitterCtx context) => EmitAluOp(context, OpCodes.And); - - public static void Ands(ILEmitterCtx context) - { - EmitAluLoadOpers(context); - - context.Emit(OpCodes.And); - - EmitZeroCvFlags(context); - - context.EmitZnFlagCheck(); - - EmitAluStoreS(context); - } - - public static void Asrv(ILEmitterCtx context) => EmitAluOpShift(context, OpCodes.Shr); - - public static void Bic(ILEmitterCtx context) => EmitBic(context, false); - public static void Bics(ILEmitterCtx context) => EmitBic(context, true); - - private static void EmitBic(ILEmitterCtx context, bool setFlags) - { - EmitAluLoadOpers(context); - - context.Emit(OpCodes.Not); - context.Emit(OpCodes.And); - - if (setFlags) - { - EmitZeroCvFlags(context); - - context.EmitZnFlagCheck(); - } - - EmitAluStore(context, setFlags); - } - - public static void Cls(ILEmitterCtx context) - { - OpCodeAlu64 op = (OpCodeAlu64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - context.EmitLdc_I4(op.RegisterSize == RegisterSize.Int32 ? 32 : 64); - - SoftFallback.EmitCall(context, nameof(SoftFallback.CountLeadingSigns)); - - context.EmitStintzr(op.Rd); - } - - public static void Clz(ILEmitterCtx context) - { - OpCodeAlu64 op = (OpCodeAlu64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - if (Lzcnt.IsSupported) - { - Type tValue = op.RegisterSize == RegisterSize.Int32 ? typeof(uint) : typeof(ulong); - - context.EmitCall(typeof(Lzcnt).GetMethod(nameof(Lzcnt.LeadingZeroCount), new Type[] { tValue })); - } - else - { - context.EmitLdc_I4(op.RegisterSize == RegisterSize.Int32 ? 32 : 64); - - SoftFallback.EmitCall(context, nameof(SoftFallback.CountLeadingZeros)); - } - - context.EmitStintzr(op.Rd); - } - - public static void Eon(ILEmitterCtx context) - { - EmitAluLoadOpers(context); - - context.Emit(OpCodes.Not); - context.Emit(OpCodes.Xor); - - EmitAluStore(context); - } - - public static void Eor(ILEmitterCtx context) => EmitAluOp(context, OpCodes.Xor); - - public static void Extr(ILEmitterCtx context) - { - // TODO: Ensure that the Shift is valid for the Is64Bits. - OpCodeAluRs64 op = (OpCodeAluRs64)context.CurrOp; - - context.EmitLdintzr(op.Rm); - - if (op.Shift > 0) - { - context.EmitLdc_I4(op.Shift); - - context.Emit(OpCodes.Shr_Un); - - context.EmitLdintzr(op.Rn); - context.EmitLdc_I4(op.GetBitsCount() - op.Shift); - - context.Emit(OpCodes.Shl); - context.Emit(OpCodes.Or); - } - - EmitAluStore(context); - } - - public static void Lslv(ILEmitterCtx context) => EmitAluOpShift(context, OpCodes.Shl); - public static void Lsrv(ILEmitterCtx context) => EmitAluOpShift(context, OpCodes.Shr_Un); - - public static void Sbc(ILEmitterCtx context) => EmitSbc(context, false); - public static void Sbcs(ILEmitterCtx context) => EmitSbc(context, true); - - private static void EmitSbc(ILEmitterCtx context, bool setFlags) - { - EmitAluLoadOpers(context); - - context.Emit(OpCodes.Sub); - - context.EmitLdflg((int)PState.CBit); - - Type[] mthdTypes = new Type[] { typeof(bool) }; - - MethodInfo mthdInfo = typeof(Convert).GetMethod(nameof(Convert.ToInt32), mthdTypes); - - context.EmitCall(mthdInfo); - - context.EmitLdc_I4(1); - - context.Emit(OpCodes.Xor); - - if (context.CurrOp.RegisterSize != RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U8); - } - - context.Emit(OpCodes.Sub); - - if (setFlags) - { - context.EmitZnFlagCheck(); - - EmitSbcsCCheck(context); - EmitSubsVCheck(context); - } - - EmitAluStore(context); - } - - public static void Sub(ILEmitterCtx context) => EmitAluOp(context, OpCodes.Sub); - - public static void Subs(ILEmitterCtx context) - { - context.TryOptMarkCondWithoutCmp(); - - EmitAluLoadOpers(context); - - context.Emit(OpCodes.Sub); - - context.EmitZnFlagCheck(); - - EmitSubsCCheck(context); - EmitSubsVCheck(context); - EmitAluStoreS(context); - } - - public static void Orn(ILEmitterCtx context) - { - EmitAluLoadOpers(context); - - context.Emit(OpCodes.Not); - context.Emit(OpCodes.Or); - - EmitAluStore(context); - } - - public static void Orr(ILEmitterCtx context) => EmitAluOp(context, OpCodes.Or); - - public static void Rbit(ILEmitterCtx context) => EmitFallback32_64(context, - nameof(SoftFallback.ReverseBits32), - nameof(SoftFallback.ReverseBits64)); - - public static void Rev16(ILEmitterCtx context) => EmitFallback32_64(context, - nameof(SoftFallback.ReverseBytes16_32), - nameof(SoftFallback.ReverseBytes16_64)); - - public static void Rev32(ILEmitterCtx context) => EmitFallback32_64(context, - nameof(SoftFallback.ReverseBytes32_32), - nameof(SoftFallback.ReverseBytes32_64)); - - private static void EmitFallback32_64(ILEmitterCtx context, string name32, string name64) - { - OpCodeAlu64 op = (OpCodeAlu64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - if (op.RegisterSize == RegisterSize.Int32) - { - SoftFallback.EmitCall(context, name32); - } - else - { - SoftFallback.EmitCall(context, name64); - } - - context.EmitStintzr(op.Rd); - } - - public static void Rev64(ILEmitterCtx context) - { - OpCodeAlu64 op = (OpCodeAlu64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - SoftFallback.EmitCall(context, nameof(SoftFallback.ReverseBytes64)); - - context.EmitStintzr(op.Rd); - } - - public static void Rorv(ILEmitterCtx context) - { - EmitAluLoadRn(context); - EmitAluLoadShift(context); - - context.Emit(OpCodes.Shr_Un); - - EmitAluLoadRn(context); - - context.EmitLdc_I4(context.CurrOp.GetBitsCount()); - - EmitAluLoadShift(context); - - context.Emit(OpCodes.Sub); - context.Emit(OpCodes.Shl); - context.Emit(OpCodes.Or); - - EmitAluStore(context); - } - - public static void Sdiv(ILEmitterCtx context) => EmitDiv(context, OpCodes.Div); - public static void Udiv(ILEmitterCtx context) => EmitDiv(context, OpCodes.Div_Un); - - private static void EmitDiv(ILEmitterCtx context, OpCode ilOp) - { - // If Rm == 0, Rd = 0 (division by zero). - context.EmitLdc_I(0); - - EmitAluLoadRm(context); - - context.EmitLdc_I(0); - - ILLabel badDiv = new ILLabel(); - - context.Emit(OpCodes.Beq_S, badDiv); - context.Emit(OpCodes.Pop); - - if (ilOp == OpCodes.Div) - { - // If Rn == INT_MIN && Rm == -1, Rd = INT_MIN (overflow). - long intMin = 1L << (context.CurrOp.GetBitsCount() - 1); - - context.EmitLdc_I(intMin); - - EmitAluLoadRn(context); - - context.EmitLdc_I(intMin); - - context.Emit(OpCodes.Ceq); - - EmitAluLoadRm(context); - - context.EmitLdc_I(-1); - - context.Emit(OpCodes.Ceq); - context.Emit(OpCodes.And); - context.Emit(OpCodes.Brtrue_S, badDiv); - context.Emit(OpCodes.Pop); - } - - EmitAluLoadRn(context); - EmitAluLoadRm(context); - - context.Emit(ilOp); - - context.MarkLabel(badDiv); - - EmitAluStore(context); - } - - private static void EmitAluOp(ILEmitterCtx context, OpCode ilOp) - { - EmitAluLoadOpers(context); - - context.Emit(ilOp); - - EmitAluStore(context); - } - - private static void EmitAluOpShift(ILEmitterCtx context, OpCode ilOp) - { - EmitAluLoadRn(context); - EmitAluLoadShift(context); - - context.Emit(ilOp); - - EmitAluStore(context); - } - - private static void EmitAluLoadShift(ILEmitterCtx context) - { - EmitAluLoadRm(context); - - context.EmitLdc_I(context.CurrOp.GetBitsCount() - 1); - - context.Emit(OpCodes.And); - - // Note: Only 32-bits shift values are valid, so when the value is 64-bits - // we need to cast it to a 32-bits integer. This is fine because we - // AND the value and only keep the lower 5 or 6 bits anyway -- it - // could very well fit on a byte. - if (context.CurrOp.RegisterSize != RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_I4); - } - } - - private static void EmitZeroCvFlags(ILEmitterCtx context) - { - context.EmitLdc_I4(0); - - context.EmitStflg((int)PState.VBit); - - context.EmitLdc_I4(0); - - context.EmitStflg((int)PState.CBit); - } - - public static void EmitAluStore(ILEmitterCtx context) => EmitAluStore(context, false); - public static void EmitAluStoreS(ILEmitterCtx context) => EmitAluStore(context, true); - - public static void EmitAluStore(ILEmitterCtx context, bool setFlags) - { - IOpCodeAlu64 op = (IOpCodeAlu64)context.CurrOp; - - if (setFlags || op is IOpCodeAluRs64) - { - context.EmitStintzr(op.Rd); - } - else - { - context.EmitStint(op.Rd); - } - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitAlu32.cs b/ChocolArm64/Instructions/InstEmitAlu32.cs deleted file mode 100644 index 94a8c750..00000000 --- a/ChocolArm64/Instructions/InstEmitAlu32.cs +++ /dev/null @@ -1,142 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System.Reflection.Emit; - -using static ChocolArm64.Instructions.InstEmit32Helper; -using static ChocolArm64.Instructions.InstEmitAluHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit32 - { - public static void Add(ILEmitterCtx context) - { - IOpCode32Alu op = (IOpCode32Alu)context.CurrOp; - - EmitAluLoadOpers(context, setCarry: false); - - context.Emit(OpCodes.Add); - - if (op.SetFlags) - { - context.EmitZnFlagCheck(); - - EmitAddsCCheck(context); - EmitAddsVCheck(context); - } - - EmitAluStore(context); - } - - public static void Cmp(ILEmitterCtx context) - { - IOpCode32Alu op = (IOpCode32Alu)context.CurrOp; - - EmitAluLoadOpers(context, setCarry: false); - - context.Emit(OpCodes.Sub); - - context.EmitZnFlagCheck(); - - EmitSubsCCheck(context); - EmitSubsVCheck(context); - - context.Emit(OpCodes.Pop); - } - - public static void Mov(ILEmitterCtx context) - { - IOpCode32Alu op = (IOpCode32Alu)context.CurrOp; - - EmitAluLoadOper2(context); - - if (op.SetFlags) - { - context.EmitZnFlagCheck(); - } - - EmitAluStore(context); - } - - public static void Sub(ILEmitterCtx context) - { - IOpCode32Alu op = (IOpCode32Alu)context.CurrOp; - - EmitAluLoadOpers(context, setCarry: false); - - context.Emit(OpCodes.Sub); - - if (op.SetFlags) - { - context.EmitZnFlagCheck(); - - EmitSubsCCheck(context); - EmitSubsVCheck(context); - } - - EmitAluStore(context); - } - - private static void EmitAluStore(ILEmitterCtx context) - { - IOpCode32Alu op = (IOpCode32Alu)context.CurrOp; - - if (op.Rd == RegisterAlias.Aarch32Pc) - { - if (op.SetFlags) - { - // TODO: Load SPSR etc. - - context.EmitLdflg((int)PState.TBit); - - ILLabel lblThumb = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.Emit(OpCodes.Brtrue_S, lblThumb); - - context.EmitLdc_I4(~3); - - context.Emit(OpCodes.Br_S, lblEnd); - - context.MarkLabel(lblThumb); - - context.EmitLdc_I4(~1); - - context.MarkLabel(lblEnd); - - context.Emit(OpCodes.And); - context.Emit(OpCodes.Conv_U8); - context.Emit(OpCodes.Ret); - } - else - { - EmitAluWritePc(context); - } - } - else - { - context.EmitStint(GetRegisterAlias(context.Mode, op.Rd)); - } - } - - private static void EmitAluWritePc(ILEmitterCtx context) - { - context.EmitStoreContext(); - - if (IsThumb(context.CurrOp)) - { - context.EmitLdc_I4(~1); - - context.Emit(OpCodes.And); - context.Emit(OpCodes.Conv_U8); - context.Emit(OpCodes.Ret); - } - else - { - EmitBxWritePc(context); - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitAluHelper.cs b/ChocolArm64/Instructions/InstEmitAluHelper.cs deleted file mode 100644 index 64822088..00000000 --- a/ChocolArm64/Instructions/InstEmitAluHelper.cs +++ /dev/null @@ -1,462 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; - -namespace ChocolArm64.Instructions -{ - static class InstEmitAluHelper - { - public static void EmitAdcsCCheck(ILEmitterCtx context) - { - // C = (Rd == Rn && CIn) || Rd < Rn - context.EmitSttmp(); - context.EmitLdtmp(); - context.EmitLdtmp(); - - EmitAluLoadRn(context); - - context.Emit(OpCodes.Ceq); - - context.EmitLdflg((int)PState.CBit); - - context.Emit(OpCodes.And); - - context.EmitLdtmp(); - - EmitAluLoadRn(context); - - context.Emit(OpCodes.Clt_Un); - context.Emit(OpCodes.Or); - - context.EmitStflg((int)PState.CBit); - } - - public static void EmitAddsCCheck(ILEmitterCtx context) - { - // C = Rd < Rn - context.Emit(OpCodes.Dup); - - EmitAluLoadRn(context); - - context.Emit(OpCodes.Clt_Un); - - context.EmitStflg((int)PState.CBit); - } - - public static void EmitAddsVCheck(ILEmitterCtx context) - { - // V = (Rd ^ Rn) & ~(Rn ^ Rm) < 0 - context.Emit(OpCodes.Dup); - - EmitAluLoadRn(context); - - context.Emit(OpCodes.Xor); - - EmitAluLoadOpers(context); - - context.Emit(OpCodes.Xor); - context.Emit(OpCodes.Not); - context.Emit(OpCodes.And); - - context.EmitLdc_I(0); - - context.Emit(OpCodes.Clt); - - context.EmitStflg((int)PState.VBit); - } - - public static void EmitSbcsCCheck(ILEmitterCtx context) - { - // C = (Rn == Rm && CIn) || Rn > Rm - EmitAluLoadOpers(context); - - context.Emit(OpCodes.Ceq); - - context.EmitLdflg((int)PState.CBit); - - context.Emit(OpCodes.And); - - EmitAluLoadOpers(context); - - context.Emit(OpCodes.Cgt_Un); - context.Emit(OpCodes.Or); - - context.EmitStflg((int)PState.CBit); - } - - public static void EmitSubsCCheck(ILEmitterCtx context) - { - // C = Rn == Rm || Rn > Rm = !(Rn < Rm) - EmitAluLoadOpers(context); - - context.Emit(OpCodes.Clt_Un); - - context.EmitLdc_I4(1); - - context.Emit(OpCodes.Xor); - - context.EmitStflg((int)PState.CBit); - } - - public static void EmitSubsVCheck(ILEmitterCtx context) - { - // V = (Rd ^ Rn) & (Rn ^ Rm) < 0 - context.Emit(OpCodes.Dup); - - EmitAluLoadRn(context); - - context.Emit(OpCodes.Xor); - - EmitAluLoadOpers(context); - - context.Emit(OpCodes.Xor); - context.Emit(OpCodes.And); - - context.EmitLdc_I(0); - - context.Emit(OpCodes.Clt); - - context.EmitStflg((int)PState.VBit); - } - - public static void EmitAluLoadRm(ILEmitterCtx context) - { - if (context.CurrOp is IOpCodeAluRs64 op) - { - context.EmitLdintzr(op.Rm); - } - else if (context.CurrOp is OpCode32AluRsImm op32) - { - InstEmit32Helper.EmitLoadFromRegister(context, op32.Rm); - } - else - { - throw new InvalidOperationException(); - } - } - - public static void EmitAluLoadOpers(ILEmitterCtx context, bool setCarry = true) - { - EmitAluLoadRn(context); - EmitAluLoadOper2(context, setCarry); - } - - public static void EmitAluLoadRn(ILEmitterCtx context) - { - if (context.CurrOp is IOpCodeAlu64 op) - { - if (op.DataOp == DataOp.Logical || op is IOpCodeAluRs64) - { - context.EmitLdintzr(op.Rn); - } - else - { - context.EmitLdint(op.Rn); - } - } - else if (context.CurrOp is IOpCode32Alu op32) - { - InstEmit32Helper.EmitLoadFromRegister(context, op32.Rn); - } - else - { - throw new InvalidOperationException(); - } - } - - public static void EmitAluLoadOper2(ILEmitterCtx context, bool setCarry = true) - { - switch (context.CurrOp) - { - // ARM32. - case OpCode32AluImm op: - context.EmitLdc_I4(op.Imm); - - if (op.SetFlags && op.IsRotated) - { - context.EmitLdc_I4((int)((uint)op.Imm >> 31)); - - context.EmitStflg((int)PState.CBit); - } - break; - - case OpCode32AluRsImm op: - EmitLoadRmShiftedByImmediate(context, op, setCarry); - break; - - case OpCodeT16AluImm8 op: - context.EmitLdc_I4(op.Imm); - break; - - // ARM64. - case IOpCodeAluImm64 op: - context.EmitLdc_I(op.Imm); - break; - - case IOpCodeAluRs64 op: - context.EmitLdintzr(op.Rm); - - switch (op.ShiftType) - { - case ShiftType.Lsl: context.EmitLsl(op.Shift); break; - case ShiftType.Lsr: context.EmitLsr(op.Shift); break; - case ShiftType.Asr: context.EmitAsr(op.Shift); break; - case ShiftType.Ror: context.EmitRor(op.Shift); break; - } - break; - - case IOpCodeAluRx64 op: - context.EmitLdintzr(op.Rm); - context.EmitCast(op.IntType); - context.EmitLsl(op.Shift); - break; - - default: throw new InvalidOperationException(); - } - } - - public static void EmitSetNzcv(ILEmitterCtx context) - { - context.Emit(OpCodes.Dup); - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.And); - context.EmitStflg((int)PState.VBit); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr); - context.Emit(OpCodes.Dup); - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.And); - context.EmitStflg((int)PState.CBit); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr); - context.Emit(OpCodes.Dup); - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.And); - context.EmitStflg((int)PState.ZBit); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr); - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.And); - context.EmitStflg((int)PState.NBit); - } - - // ARM32 helpers. - private static void EmitLoadRmShiftedByImmediate(ILEmitterCtx context, OpCode32AluRsImm op, bool setCarry) - { - int shift = op.Imm; - - if (shift == 0) - { - switch (op.ShiftType) - { - case ShiftType.Lsr: shift = 32; break; - case ShiftType.Asr: shift = 32; break; - case ShiftType.Ror: shift = 1; break; - } - } - - context.EmitLdint(op.Rm); - - if (shift != 0) - { - setCarry &= op.SetFlags; - - switch (op.ShiftType) - { - case ShiftType.Lsl: EmitLslC(context, setCarry, shift); break; - case ShiftType.Lsr: EmitLsrC(context, setCarry, shift); break; - case ShiftType.Asr: EmitAsrC(context, setCarry, shift); break; - case ShiftType.Ror: - if (op.Imm != 0) - { - EmitRorC(context, setCarry, shift); - } - else - { - EmitRrxC(context, setCarry); - } - break; - } - } - } - - private static void EmitLslC(ILEmitterCtx context, bool setCarry, int shift) - { - if ((uint)shift > 32) - { - EmitShiftByMoreThan32(context, setCarry); - } - else if (shift == 32) - { - if (setCarry) - { - context.EmitLdc_I4(1); - - context.Emit(OpCodes.And); - - context.EmitStflg((int)PState.CBit); - } - else - { - context.Emit(OpCodes.Pop); - } - - context.EmitLdc_I4(0); - } - else - { - if (setCarry) - { - context.Emit(OpCodes.Dup); - - context.EmitLsr(32 - shift); - - context.EmitLdc_I4(1); - - context.Emit(OpCodes.And); - - context.EmitStflg((int)PState.CBit); - } - - context.EmitLsl(shift); - } - } - - private static void EmitLsrC(ILEmitterCtx context, bool setCarry, int shift) - { - if ((uint)shift > 32) - { - EmitShiftByMoreThan32(context, setCarry); - } - else if (shift == 32) - { - if (setCarry) - { - context.EmitLsr(31); - - context.EmitStflg((int)PState.CBit); - } - else - { - context.Emit(OpCodes.Pop); - } - - context.EmitLdc_I4(0); - } - else - { - context.Emit(OpCodes.Dup); - - context.EmitLsr(shift - 1); - - context.EmitLdc_I4(1); - - context.Emit(OpCodes.And); - - context.EmitStflg((int)PState.CBit); - - context.EmitLsr(shift); - } - } - - private static void EmitShiftByMoreThan32(ILEmitterCtx context, bool setCarry) - { - context.Emit(OpCodes.Pop); - - context.EmitLdc_I4(0); - - if (setCarry) - { - context.Emit(OpCodes.Dup); - - context.EmitStflg((int)PState.CBit); - } - } - - private static void EmitAsrC(ILEmitterCtx context, bool setCarry, int shift) - { - if ((uint)shift >= 32) - { - context.EmitAsr(31); - - if (setCarry) - { - context.Emit(OpCodes.Dup); - - context.EmitLdc_I4(1); - - context.Emit(OpCodes.And); - - context.EmitStflg((int)PState.CBit); - } - } - else - { - if (setCarry) - { - context.Emit(OpCodes.Dup); - - context.EmitLsr(shift - 1); - - context.EmitLdc_I4(1); - - context.Emit(OpCodes.And); - - context.EmitStflg((int)PState.CBit); - } - - context.EmitAsr(shift); - } - } - - private static void EmitRorC(ILEmitterCtx context, bool setCarry, int shift) - { - shift &= 0x1f; - - context.EmitRor(shift); - - if (setCarry) - { - context.Emit(OpCodes.Dup); - - context.EmitLsr(31); - - context.EmitStflg((int)PState.CBit); - } - } - - private static void EmitRrxC(ILEmitterCtx context, bool setCarry) - { - // Rotate right by 1 with carry. - if (setCarry) - { - context.Emit(OpCodes.Dup); - - context.EmitLdc_I4(1); - - context.Emit(OpCodes.And); - - context.EmitSttmp(); - } - - context.EmitLsr(1); - - context.EmitLdflg((int)PState.CBit); - - context.EmitLsl(31); - - context.Emit(OpCodes.Or); - - if (setCarry) - { - context.EmitLdtmp(); - context.EmitStflg((int)PState.CBit); - } - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitBfm.cs b/ChocolArm64/Instructions/InstEmitBfm.cs deleted file mode 100644 index 75e259c1..00000000 --- a/ChocolArm64/Instructions/InstEmitBfm.cs +++ /dev/null @@ -1,243 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System.Reflection.Emit; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Bfm(ILEmitterCtx context) - { - OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp; - - if (op.Pos < op.Shift) - { - // BFI. - context.EmitLdintzr(op.Rn); - - int shift = op.GetBitsCount() - op.Shift; - - int width = op.Pos + 1; - - long mask = (long)(ulong.MaxValue >> (64 - width)); - - context.EmitLdc_I(mask); - - context.Emit(OpCodes.And); - - context.EmitLsl(shift); - - context.EmitLdintzr(op.Rd); - - context.EmitLdc_I(~(mask << shift)); - - context.Emit(OpCodes.And); - context.Emit(OpCodes.Or); - - context.EmitStintzr(op.Rd); - } - else - { - // BFXIL. - context.EmitLdintzr(op.Rn); - - context.EmitLsr(op.Shift); - - int width = op.Pos - op.Shift + 1; - - long mask = (long)(ulong.MaxValue >> (64 - width)); - - context.EmitLdc_I(mask); - - context.Emit(OpCodes.And); - - context.EmitLdintzr(op.Rd); - - context.EmitLdc_I(~mask); - - context.Emit(OpCodes.And); - context.Emit(OpCodes.Or); - - context.EmitStintzr(op.Rd); - } - } - - public static void Sbfm(ILEmitterCtx context) - { - OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp; - - int bitsCount = op.GetBitsCount(); - - if (op.Pos + 1 == bitsCount) - { - EmitSbfmShift(context); - } - else if (op.Pos < op.Shift) - { - EmitSbfiz(context); - } - else if (op.Pos == 7 && op.Shift == 0) - { - EmitSbfmCast(context, OpCodes.Conv_I1); - } - else if (op.Pos == 15 && op.Shift == 0) - { - EmitSbfmCast(context, OpCodes.Conv_I2); - } - else if (op.Pos == 31 && op.Shift == 0) - { - EmitSbfmCast(context, OpCodes.Conv_I4); - } - else - { - EmitBfmLoadRn(context); - - context.EmitLdintzr(op.Rn); - - context.EmitLsl(bitsCount - 1 - op.Pos); - context.EmitAsr(bitsCount - 1); - - context.EmitLdc_I(~op.TMask); - - context.Emit(OpCodes.And); - context.Emit(OpCodes.Or); - - context.EmitStintzr(op.Rd); - } - } - - public static void Ubfm(ILEmitterCtx context) - { - OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp; - - if (op.Pos + 1 == op.GetBitsCount()) - { - EmitUbfmShift(context); - } - else if (op.Pos < op.Shift) - { - EmitUbfiz(context); - } - else if (op.Pos + 1 == op.Shift) - { - EmitBfmLsl(context); - } - else if (op.Pos == 7 && op.Shift == 0) - { - EmitUbfmCast(context, OpCodes.Conv_U1); - } - else if (op.Pos == 15 && op.Shift == 0) - { - EmitUbfmCast(context, OpCodes.Conv_U2); - } - else - { - EmitBfmLoadRn(context); - - context.EmitStintzr(op.Rd); - } - } - - private static void EmitSbfiz(ILEmitterCtx context) => EmitBfiz(context, true); - private static void EmitUbfiz(ILEmitterCtx context) => EmitBfiz(context, false); - - private static void EmitBfiz(ILEmitterCtx context, bool signed) - { - OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp; - - int width = op.Pos + 1; - - context.EmitLdintzr(op.Rn); - - context.EmitLsl(op.GetBitsCount() - width); - - if (signed) - { - context.EmitAsr(op.Shift - width); - } - else - { - context.EmitLsr(op.Shift - width); - } - - context.EmitStintzr(op.Rd); - } - - private static void EmitSbfmCast(ILEmitterCtx context, OpCode ilOp) - { - EmitBfmCast(context, ilOp, true); - } - - private static void EmitUbfmCast(ILEmitterCtx context, OpCode ilOp) - { - EmitBfmCast(context, ilOp, false); - } - - private static void EmitBfmCast(ILEmitterCtx context, OpCode ilOp, bool signed) - { - OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - context.Emit(ilOp); - - if (op.RegisterSize != RegisterSize.Int32) - { - context.Emit(signed - ? OpCodes.Conv_I8 - : OpCodes.Conv_U8); - } - - context.EmitStintzr(op.Rd); - } - - private static void EmitSbfmShift(ILEmitterCtx context) - { - EmitBfmShift(context, true); - } - - private static void EmitUbfmShift(ILEmitterCtx context) - { - EmitBfmShift(context, false); - } - - private static void EmitBfmShift(ILEmitterCtx context, bool signed) - { - OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - context.EmitLdc_I4(op.Shift); - - context.Emit(signed - ? OpCodes.Shr - : OpCodes.Shr_Un); - - context.EmitStintzr(op.Rd); - } - - private static void EmitBfmLsl(ILEmitterCtx context) - { - OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - context.EmitLsl(op.GetBitsCount() - op.Shift); - - context.EmitStintzr(op.Rd); - } - - private static void EmitBfmLoadRn(ILEmitterCtx context) - { - OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - context.EmitRor(op.Shift); - - context.EmitLdc_I(op.WMask & op.TMask); - - context.Emit(OpCodes.And); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitCcmp.cs b/ChocolArm64/Instructions/InstEmitCcmp.cs deleted file mode 100644 index e21dc696..00000000 --- a/ChocolArm64/Instructions/InstEmitCcmp.cs +++ /dev/null @@ -1,82 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; - -using static ChocolArm64.Instructions.InstEmitAluHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - private enum CcmpOp - { - Cmp, - Cmn - } - - public static void Ccmn(ILEmitterCtx context) => EmitCcmp(context, CcmpOp.Cmn); - public static void Ccmp(ILEmitterCtx context) => EmitCcmp(context, CcmpOp.Cmp); - - private static void EmitCcmp(ILEmitterCtx context, CcmpOp cmpOp) - { - OpCodeCcmp64 op = (OpCodeCcmp64)context.CurrOp; - - ILLabel lblTrue = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.EmitCondBranch(lblTrue, op.Cond); - - context.EmitLdc_I4((op.Nzcv >> 0) & 1); - - context.EmitStflg((int)PState.VBit); - - context.EmitLdc_I4((op.Nzcv >> 1) & 1); - - context.EmitStflg((int)PState.CBit); - - context.EmitLdc_I4((op.Nzcv >> 2) & 1); - - context.EmitStflg((int)PState.ZBit); - - context.EmitLdc_I4((op.Nzcv >> 3) & 1); - - context.EmitStflg((int)PState.NBit); - - context.Emit(OpCodes.Br_S, lblEnd); - - context.MarkLabel(lblTrue); - - EmitAluLoadOpers(context); - - if (cmpOp == CcmpOp.Cmp) - { - context.Emit(OpCodes.Sub); - - context.EmitZnFlagCheck(); - - EmitSubsCCheck(context); - EmitSubsVCheck(context); - } - else if (cmpOp == CcmpOp.Cmn) - { - context.Emit(OpCodes.Add); - - context.EmitZnFlagCheck(); - - EmitAddsCCheck(context); - EmitAddsVCheck(context); - } - else - { - throw new ArgumentException(nameof(cmpOp)); - } - - context.Emit(OpCodes.Pop); - - context.MarkLabel(lblEnd); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitCsel.cs b/ChocolArm64/Instructions/InstEmitCsel.cs deleted file mode 100644 index 7008a8c7..00000000 --- a/ChocolArm64/Instructions/InstEmitCsel.cs +++ /dev/null @@ -1,59 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.Translation; -using System.Reflection.Emit; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - private enum CselOperation - { - None, - Increment, - Invert, - Negate - } - - public static void Csel(ILEmitterCtx context) => EmitCsel(context, CselOperation.None); - public static void Csinc(ILEmitterCtx context) => EmitCsel(context, CselOperation.Increment); - public static void Csinv(ILEmitterCtx context) => EmitCsel(context, CselOperation.Invert); - public static void Csneg(ILEmitterCtx context) => EmitCsel(context, CselOperation.Negate); - - private static void EmitCsel(ILEmitterCtx context, CselOperation cselOp) - { - OpCodeCsel64 op = (OpCodeCsel64)context.CurrOp; - - ILLabel lblTrue = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.EmitCondBranch(lblTrue, op.Cond); - context.EmitLdintzr(op.Rm); - - if (cselOp == CselOperation.Increment) - { - context.EmitLdc_I(1); - - context.Emit(OpCodes.Add); - } - else if (cselOp == CselOperation.Invert) - { - context.Emit(OpCodes.Not); - } - else if (cselOp == CselOperation.Negate) - { - context.Emit(OpCodes.Neg); - } - - context.Emit(OpCodes.Br_S, lblEnd); - - context.MarkLabel(lblTrue); - - context.EmitLdintzr(op.Rn); - - context.MarkLabel(lblEnd); - - context.EmitStintzr(op.Rd); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitException.cs b/ChocolArm64/Instructions/InstEmitException.cs deleted file mode 100644 index c835fb0d..00000000 --- a/ChocolArm64/Instructions/InstEmitException.cs +++ /dev/null @@ -1,87 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System.Reflection.Emit; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Brk(ILEmitterCtx context) - { - EmitExceptionCall(context, nameof(CpuThreadState.OnBreak)); - } - - public static void Svc(ILEmitterCtx context) - { - EmitExceptionCall(context, nameof(CpuThreadState.OnSvcCall)); - } - - private static void EmitExceptionCall(ILEmitterCtx context, string mthdName) - { - OpCodeException64 op = (OpCodeException64)context.CurrOp; - - context.EmitStoreContext(); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitLdc_I8(op.Position); - context.EmitLdc_I4(op.Id); - - context.EmitPrivateCall(typeof(CpuThreadState), mthdName); - - // Check if the thread should still be running, if it isn't then we return 0 - // to force a return to the dispatcher and then exit the thread. - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitCallPropGet(typeof(CpuThreadState), nameof(CpuThreadState.Running)); - - ILLabel lblEnd = new ILLabel(); - - context.Emit(OpCodes.Brtrue_S, lblEnd); - - context.EmitLdc_I8(0); - - context.Emit(OpCodes.Ret); - - context.MarkLabel(lblEnd); - - if (context.CurrBlock.Next != null) - { - context.EmitLoadContext(); - } - else - { - context.EmitLdc_I8(op.Position + 4); - - context.Emit(OpCodes.Ret); - } - } - - public static void Und(ILEmitterCtx context) - { - OpCode64 op = context.CurrOp; - - context.EmitStoreContext(); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitLdc_I8(op.Position); - context.EmitLdc_I4(op.RawOpCode); - - context.EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.OnUndefined)); - - if (context.CurrBlock.Next != null) - { - context.EmitLoadContext(); - } - else - { - context.EmitLdc_I8(op.Position + 4); - - context.Emit(OpCodes.Ret); - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitFlow.cs b/ChocolArm64/Instructions/InstEmitFlow.cs deleted file mode 100644 index 6355b8b4..00000000 --- a/ChocolArm64/Instructions/InstEmitFlow.cs +++ /dev/null @@ -1,181 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System.Reflection.Emit; - -using static ChocolArm64.Instructions.InstEmitFlowHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void B(ILEmitterCtx context) - { - OpCodeBImmAl64 op = (OpCodeBImmAl64)context.CurrOp; - - if (context.CurrBlock.Branch != null) - { - context.Emit(OpCodes.Br, context.GetLabel(op.Imm)); - } - else - { - context.EmitStoreContext(); - context.EmitLdc_I8(op.Imm); - - context.Emit(OpCodes.Ret); - } - } - - public static void B_Cond(ILEmitterCtx context) - { - OpCodeBImmCond64 op = (OpCodeBImmCond64)context.CurrOp; - - EmitBranch(context, op.Cond); - } - - public static void Bl(ILEmitterCtx context) - { - OpCodeBImmAl64 op = (OpCodeBImmAl64)context.CurrOp; - - context.EmitLdc_I(op.Position + 4); - context.EmitStint(RegisterAlias.Lr); - - EmitCall(context, op.Imm); - } - - public static void Blr(ILEmitterCtx context) - { - OpCodeBReg64 op = (OpCodeBReg64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - context.EmitLdc_I(op.Position + 4); - context.EmitStint(RegisterAlias.Lr); - context.EmitStoreContext(); - - EmitVirtualCall(context); - } - - public static void Br(ILEmitterCtx context) - { - OpCodeBReg64 op = (OpCodeBReg64)context.CurrOp; - - context.HasIndirectJump = true; - - context.EmitStoreContext(); - context.EmitLdintzr(op.Rn); - - EmitVirtualJump(context); - } - - public static void Cbnz(ILEmitterCtx context) => EmitCb(context, OpCodes.Bne_Un); - public static void Cbz(ILEmitterCtx context) => EmitCb(context, OpCodes.Beq); - - private static void EmitCb(ILEmitterCtx context, OpCode ilOp) - { - OpCodeBImmCmp64 op = (OpCodeBImmCmp64)context.CurrOp; - - context.EmitLdintzr(op.Rt); - context.EmitLdc_I(0); - - EmitBranch(context, ilOp); - } - - public static void Ret(ILEmitterCtx context) - { - context.EmitStoreContext(); - context.EmitLdint(RegisterAlias.Lr); - - context.Emit(OpCodes.Ret); - } - - public static void Tbnz(ILEmitterCtx context) => EmitTb(context, OpCodes.Bne_Un); - public static void Tbz(ILEmitterCtx context) => EmitTb(context, OpCodes.Beq); - - private static void EmitTb(ILEmitterCtx context, OpCode ilOp) - { - OpCodeBImmTest64 op = (OpCodeBImmTest64)context.CurrOp; - - context.EmitLdintzr(op.Rt); - context.EmitLdc_I(1L << op.Pos); - - context.Emit(OpCodes.And); - - context.EmitLdc_I(0); - - EmitBranch(context, ilOp); - } - - private static void EmitBranch(ILEmitterCtx context, Condition cond) - { - OpCodeBImm64 op = (OpCodeBImm64)context.CurrOp; - - if (context.CurrBlock.Branch != null) - { - context.EmitCondBranch(context.GetLabel(op.Imm), cond); - - if (context.CurrBlock.Next == null) - { - context.EmitStoreContext(); - context.EmitLdc_I8(op.Position + 4); - - context.Emit(OpCodes.Ret); - } - } - else - { - context.EmitStoreContext(); - - ILLabel lblTaken = new ILLabel(); - - context.EmitCondBranch(lblTaken, cond); - - context.EmitLdc_I8(op.Position + 4); - - context.Emit(OpCodes.Ret); - - context.MarkLabel(lblTaken); - - context.EmitLdc_I8(op.Imm); - - context.Emit(OpCodes.Ret); - } - } - - private static void EmitBranch(ILEmitterCtx context, OpCode ilOp) - { - OpCodeBImm64 op = (OpCodeBImm64)context.CurrOp; - - if (context.CurrBlock.Branch != null) - { - context.Emit(ilOp, context.GetLabel(op.Imm)); - - if (context.CurrBlock.Next == null) - { - context.EmitStoreContext(); - context.EmitLdc_I8(op.Position + 4); - - context.Emit(OpCodes.Ret); - } - } - else - { - context.EmitStoreContext(); - - ILLabel lblTaken = new ILLabel(); - - context.Emit(ilOp, lblTaken); - - context.EmitLdc_I8(op.Position + 4); - - context.Emit(OpCodes.Ret); - - context.MarkLabel(lblTaken); - - context.EmitLdc_I8(op.Imm); - - context.Emit(OpCodes.Ret); - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitFlow32.cs b/ChocolArm64/Instructions/InstEmitFlow32.cs deleted file mode 100644 index 133e2784..00000000 --- a/ChocolArm64/Instructions/InstEmitFlow32.cs +++ /dev/null @@ -1,81 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System.Reflection.Emit; - -using static ChocolArm64.Instructions.InstEmit32Helper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit32 - { - public static void B(ILEmitterCtx context) - { - IOpCode32BImm op = (IOpCode32BImm)context.CurrOp; - - if (context.CurrBlock.Branch != null) - { - context.Emit(OpCodes.Br, context.GetLabel(op.Imm)); - } - else - { - context.EmitStoreContext(); - context.EmitLdc_I8(op.Imm); - - context.Emit(OpCodes.Ret); - } - } - - public static void Bl(ILEmitterCtx context) - { - Blx(context, x: false); - } - - public static void Blx(ILEmitterCtx context) - { - Blx(context, x: true); - } - - public static void Bx(ILEmitterCtx context) - { - IOpCode32BReg op = (IOpCode32BReg)context.CurrOp; - - context.EmitStoreContext(); - - EmitLoadFromRegister(context, op.Rm); - - EmitBxWritePc(context); - } - - private static void Blx(ILEmitterCtx context, bool x) - { - IOpCode32BImm op = (IOpCode32BImm)context.CurrOp; - - uint pc = op.GetPc(); - - bool isThumb = IsThumb(context.CurrOp); - - if (!isThumb) - { - context.EmitLdc_I(op.GetPc() - 4); - } - else - { - context.EmitLdc_I(op.GetPc() | 1); - } - - context.EmitStint(GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr)); - - // If x is true, then this is a branch with link and exchange. - // In this case we need to swap the mode between Arm <-> Thumb. - if (x) - { - context.EmitLdc_I4(isThumb ? 0 : 1); - - context.EmitStflg((int)PState.TBit); - } - - InstEmitFlowHelper.EmitCall(context, op.Imm); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitFlowHelper.cs b/ChocolArm64/Instructions/InstEmitFlowHelper.cs deleted file mode 100644 index f36fe5a1..00000000 --- a/ChocolArm64/Instructions/InstEmitFlowHelper.cs +++ /dev/null @@ -1,144 +0,0 @@ -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System.Reflection; -using System.Reflection.Emit; - -namespace ChocolArm64.Instructions -{ - static class InstEmitFlowHelper - { - public static void EmitCall(ILEmitterCtx context, long imm) - { - if (context.Tier == TranslationTier.Tier0) - { - context.EmitStoreContext(); - - context.TranslateAhead(imm); - - context.EmitLdc_I8(imm); - - context.Emit(OpCodes.Ret); - - return; - } - - if (!context.TryOptEmitSubroutineCall()) - { - context.HasSlowCall = true; - - context.EmitStoreContext(); - - context.TranslateAhead(imm); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitLdfld(typeof(CpuThreadState).GetField(nameof(CpuThreadState.CurrentTranslator), - BindingFlags.Instance | - BindingFlags.NonPublic)); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - context.EmitLdc_I8(imm); - context.EmitLdc_I4((int)CallType.Call); - - context.EmitPrivateCall(typeof(Translator), nameof(Translator.GetOrTranslateSubroutine)); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - context.EmitLdarg(TranslatedSub.MemoryArgIdx); - - context.EmitCall(typeof(TranslatedSub), nameof(TranslatedSub.Execute)); - } - - EmitContinueOrReturnCheck(context); - } - - public static void EmitVirtualCall(ILEmitterCtx context) - { - EmitVirtualCallOrJump(context, isJump: false); - } - - public static void EmitVirtualJump(ILEmitterCtx context) - { - EmitVirtualCallOrJump(context, isJump: true); - } - - private static void EmitVirtualCallOrJump(ILEmitterCtx context, bool isJump) - { - if (context.Tier == TranslationTier.Tier0) - { - context.Emit(OpCodes.Ret); - } - else - { - context.EmitSttmp(); - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitLdfld(typeof(CpuThreadState).GetField(nameof(CpuThreadState.CurrentTranslator), - BindingFlags.Instance | - BindingFlags.NonPublic)); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - context.EmitLdtmp(); - context.EmitLdc_I4(isJump - ? (int)CallType.VirtualJump - : (int)CallType.VirtualCall); - - context.EmitPrivateCall(typeof(Translator), nameof(Translator.GetOrTranslateSubroutine)); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - context.EmitLdarg(TranslatedSub.MemoryArgIdx); - - if (isJump) - { - // The tail prefix allows the JIT to jump to the next function, - // while releasing the stack space used by the current one. - // This is ideal for BR ARM instructions, which are - // basically indirect tail calls. - context.Emit(OpCodes.Tailcall); - } - - MethodInfo mthdInfo = typeof(ArmSubroutine).GetMethod("Invoke"); - - context.EmitCall(mthdInfo, isVirtual: true); - - if (!isJump) - { - EmitContinueOrReturnCheck(context); - } - else - { - context.Emit(OpCodes.Ret); - } - } - } - - private static void EmitContinueOrReturnCheck(ILEmitterCtx context) - { - // Note: The return value of the called method will be placed - // at the Stack, the return value is always a Int64 with the - // return address of the function. We check if the address is - // correct, if it isn't we keep returning until we reach the dispatcher. - if (context.CurrBlock.Next != null) - { - context.Emit(OpCodes.Dup); - - context.EmitLdc_I8(context.CurrOp.Position + 4); - - ILLabel lblContinue = new ILLabel(); - - context.Emit(OpCodes.Beq_S, lblContinue); - context.Emit(OpCodes.Ret); - - context.MarkLabel(lblContinue); - - context.Emit(OpCodes.Pop); - - context.EmitLoadContext(); - } - else - { - context.Emit(OpCodes.Ret); - } - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitHash.cs b/ChocolArm64/Instructions/InstEmitHash.cs deleted file mode 100644 index 7e21a886..00000000 --- a/ChocolArm64/Instructions/InstEmitHash.cs +++ /dev/null @@ -1,115 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; -using System.Runtime.Intrinsics.X86; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Crc32b(ILEmitterCtx context) - { - EmitCrc32(context, nameof(SoftFallback.Crc32B)); - } - - public static void Crc32h(ILEmitterCtx context) - { - EmitCrc32(context, nameof(SoftFallback.Crc32H)); - } - - public static void Crc32w(ILEmitterCtx context) - { - EmitCrc32(context, nameof(SoftFallback.Crc32W)); - } - - public static void Crc32x(ILEmitterCtx context) - { - EmitCrc32(context, nameof(SoftFallback.Crc32X)); - } - - public static void Crc32cb(ILEmitterCtx context) - { - if (Optimizations.UseSse42) - { - EmitSse42Crc32(context, typeof(uint), typeof(byte)); - } - else - { - EmitCrc32(context, nameof(SoftFallback.Crc32Cb)); - } - } - - public static void Crc32ch(ILEmitterCtx context) - { - if (Optimizations.UseSse42) - { - EmitSse42Crc32(context, typeof(uint), typeof(ushort)); - } - else - { - EmitCrc32(context, nameof(SoftFallback.Crc32Ch)); - } - } - - public static void Crc32cw(ILEmitterCtx context) - { - if (Optimizations.UseSse42) - { - EmitSse42Crc32(context, typeof(uint), typeof(uint)); - } - else - { - EmitCrc32(context, nameof(SoftFallback.Crc32Cw)); - } - } - - public static void Crc32cx(ILEmitterCtx context) - { - if (Optimizations.UseSse42) - { - EmitSse42Crc32(context, typeof(ulong), typeof(ulong)); - } - else - { - EmitCrc32(context, nameof(SoftFallback.Crc32Cx)); - } - } - - private static void EmitSse42Crc32(ILEmitterCtx context, Type tCrc, Type tData) - { - OpCodeAluRs64 op = (OpCodeAluRs64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - context.EmitLdintzr(op.Rm); - - context.EmitCall(typeof(Sse42).GetMethod(nameof(Sse42.Crc32), new Type[] { tCrc, tData })); - - context.EmitStintzr(op.Rd); - } - - private static void EmitCrc32(ILEmitterCtx context, string name) - { - OpCodeAluRs64 op = (OpCodeAluRs64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - if (op.RegisterSize != RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U4); - } - - context.EmitLdintzr(op.Rm); - - SoftFallback.EmitCall(context, name); - - if (op.RegisterSize != RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U8); - } - - context.EmitStintzr(op.Rd); - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitMemory.cs b/ChocolArm64/Instructions/InstEmitMemory.cs deleted file mode 100644 index 1328f393..00000000 --- a/ChocolArm64/Instructions/InstEmitMemory.cs +++ /dev/null @@ -1,241 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.Translation; -using System.Reflection.Emit; - -using static ChocolArm64.Instructions.InstEmitMemoryHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Adr(ILEmitterCtx context) - { - OpCodeAdr64 op = (OpCodeAdr64)context.CurrOp; - - context.EmitLdc_I(op.Position + op.Imm); - context.EmitStintzr(op.Rd); - } - - public static void Adrp(ILEmitterCtx context) - { - OpCodeAdr64 op = (OpCodeAdr64)context.CurrOp; - - context.EmitLdc_I((op.Position & ~0xfffL) + (op.Imm << 12)); - context.EmitStintzr(op.Rd); - } - - public static void Ldr(ILEmitterCtx context) => EmitLdr(context, false); - public static void Ldrs(ILEmitterCtx context) => EmitLdr(context, true); - - private static void EmitLdr(ILEmitterCtx context, bool signed) - { - OpCodeMem64 op = (OpCodeMem64)context.CurrOp; - - EmitLoadAddress(context); - - if (signed && op.Extend64) - { - EmitReadSx64Call(context, op.Size); - } - else if (signed) - { - EmitReadSx32Call(context, op.Size); - } - else - { - EmitReadZxCall(context, op.Size); - } - - if (op is IOpCodeSimd64) - { - context.EmitStvec(op.Rt); - } - else - { - context.EmitStintzr(op.Rt); - } - - EmitWBackIfNeeded(context); - } - - public static void Ldr_Literal(ILEmitterCtx context) - { - IOpCodeLit64 op = (IOpCodeLit64)context.CurrOp; - - if (op.Prefetch) - { - return; - } - - context.EmitLdc_I8(op.Imm); - - if (op.Signed) - { - EmitReadSx64Call(context, op.Size); - } - else - { - EmitReadZxCall(context, op.Size); - } - - if (op is IOpCodeSimd64) - { - context.EmitStvec(op.Rt); - } - else - { - context.EmitStint(op.Rt); - } - } - - public static void Ldp(ILEmitterCtx context) - { - OpCodeMemPair64 op = (OpCodeMemPair64)context.CurrOp; - - void EmitReadAndStore(int rt) - { - if (op.Extend64) - { - EmitReadSx64Call(context, op.Size); - } - else - { - EmitReadZxCall(context, op.Size); - } - - if (op is IOpCodeSimd64) - { - context.EmitStvec(rt); - } - else - { - context.EmitStintzr(rt); - } - } - - EmitLoadAddress(context); - - EmitReadAndStore(op.Rt); - - context.EmitLdtmp(); - context.EmitLdc_I8(1 << op.Size); - - context.Emit(OpCodes.Add); - - EmitReadAndStore(op.Rt2); - - EmitWBackIfNeeded(context); - } - - public static void Str(ILEmitterCtx context) - { - OpCodeMem64 op = (OpCodeMem64)context.CurrOp; - - EmitLoadAddress(context); - - if (op is IOpCodeSimd64) - { - context.EmitLdvec(op.Rt); - } - else - { - context.EmitLdintzr(op.Rt); - } - - EmitWriteCall(context, op.Size); - - EmitWBackIfNeeded(context); - } - - public static void Stp(ILEmitterCtx context) - { - OpCodeMemPair64 op = (OpCodeMemPair64)context.CurrOp; - - EmitLoadAddress(context); - - if (op is IOpCodeSimd64) - { - context.EmitLdvec(op.Rt); - } - else - { - context.EmitLdintzr(op.Rt); - } - - EmitWriteCall(context, op.Size); - - context.EmitLdtmp(); - context.EmitLdc_I8(1 << op.Size); - - context.Emit(OpCodes.Add); - - if (op is IOpCodeSimd64) - { - context.EmitLdvec(op.Rt2); - } - else - { - context.EmitLdintzr(op.Rt2); - } - - EmitWriteCall(context, op.Size); - - EmitWBackIfNeeded(context); - } - - private static void EmitLoadAddress(ILEmitterCtx context) - { - switch (context.CurrOp) - { - case OpCodeMemImm64 op: - context.EmitLdint(op.Rn); - - if (!op.PostIdx) - { - // Pre-indexing. - context.EmitLdc_I(op.Imm); - - context.Emit(OpCodes.Add); - } - break; - - case OpCodeMemReg64 op: - context.EmitLdint(op.Rn); - context.EmitLdintzr(op.Rm); - context.EmitCast(op.IntType); - - if (op.Shift) - { - context.EmitLsl(op.Size); - } - - context.Emit(OpCodes.Add); - break; - } - - // Save address to Scratch var since the register value may change. - context.Emit(OpCodes.Dup); - - context.EmitSttmp(); - } - - private static void EmitWBackIfNeeded(ILEmitterCtx context) - { - // Check whenever the current OpCode has post-indexed write back, if so write it. - // Note: AOpCodeMemPair inherits from AOpCodeMemImm, so this works for both. - if (context.CurrOp is OpCodeMemImm64 op && op.WBack) - { - context.EmitLdtmp(); - - if (op.PostIdx) - { - context.EmitLdc_I(op.Imm); - - context.Emit(OpCodes.Add); - } - - context.EmitStint(op.Rn); - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitMemory32.cs b/ChocolArm64/Instructions/InstEmitMemory32.cs deleted file mode 100644 index 807a65fe..00000000 --- a/ChocolArm64/Instructions/InstEmitMemory32.cs +++ /dev/null @@ -1,320 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; - -using static ChocolArm64.Instructions.InstEmit32Helper; -using static ChocolArm64.Instructions.InstEmitMemoryHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit32 - { - private const int ByteSizeLog2 = 0; - private const int HWordSizeLog2 = 1; - private const int WordSizeLog2 = 2; - private const int DWordSizeLog2 = 3; - - [Flags] - enum AccessType - { - Store = 0, - Signed = 1, - Load = 2, - - LoadZx = Load, - LoadSx = Load | Signed, - } - - public static void Ldm(ILEmitterCtx context) - { - OpCode32MemMult op = (OpCode32MemMult)context.CurrOp; - - EmitLoadFromRegister(context, op.Rn); - - bool writesToPc = (op.RegisterMask & (1 << RegisterAlias.Aarch32Pc)) != 0; - - bool writeBack = op.PostOffset != 0 && (op.Rn != RegisterAlias.Aarch32Pc || !writesToPc); - - if (writeBack) - { - context.Emit(OpCodes.Dup); - } - - context.EmitLdc_I4(op.Offset); - - context.Emit(OpCodes.Add); - - context.EmitSttmp(); - - if (writeBack) - { - context.EmitLdc_I4(op.PostOffset); - - context.Emit(OpCodes.Add); - - EmitStoreToRegister(context, op.Rn); - } - - int mask = op.RegisterMask; - int offset = 0; - - for (int register = 0; mask != 0; mask >>= 1, register++) - { - if ((mask & 1) != 0) - { - context.EmitLdtmp(); - context.EmitLdc_I4(offset); - - context.Emit(OpCodes.Add); - - EmitReadZxCall(context, WordSizeLog2); - - EmitStoreToRegister(context, register); - - offset += 4; - } - } - } - - public static void Ldr(ILEmitterCtx context) - { - EmitLoadOrStore(context, WordSizeLog2, AccessType.LoadZx); - } - - public static void Ldrb(ILEmitterCtx context) - { - EmitLoadOrStore(context, ByteSizeLog2, AccessType.LoadZx); - } - - public static void Ldrd(ILEmitterCtx context) - { - EmitLoadOrStore(context, DWordSizeLog2, AccessType.LoadZx); - } - - public static void Ldrh(ILEmitterCtx context) - { - EmitLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx); - } - - public static void Ldrsb(ILEmitterCtx context) - { - EmitLoadOrStore(context, ByteSizeLog2, AccessType.LoadSx); - } - - public static void Ldrsh(ILEmitterCtx context) - { - EmitLoadOrStore(context, HWordSizeLog2, AccessType.LoadSx); - } - - public static void Stm(ILEmitterCtx context) - { - OpCode32MemMult op = (OpCode32MemMult)context.CurrOp; - - EmitLoadFromRegister(context, op.Rn); - - context.EmitLdc_I4(op.Offset); - - context.Emit(OpCodes.Add); - - context.EmitSttmp(); - - int mask = op.RegisterMask; - int offset = 0; - - for (int register = 0; mask != 0; mask >>= 1, register++) - { - if ((mask & 1) != 0) - { - context.EmitLdtmp(); - context.EmitLdc_I4(offset); - - context.Emit(OpCodes.Add); - - EmitLoadFromRegister(context, register); - - EmitWriteCall(context, WordSizeLog2); - - // Note: If Rn is also specified on the register list, - // and Rn is the first register on this list, then the - // value that is written to memory is the unmodified value, - // before the write back. If it is on the list, but it's - // not the first one, then the value written to memory - // varies between CPUs. - if (offset == 0 && op.PostOffset != 0) - { - // Emit write back after the first write. - EmitLoadFromRegister(context, op.Rn); - - context.EmitLdc_I4(op.PostOffset); - - context.Emit(OpCodes.Add); - - EmitStoreToRegister(context, op.Rn); - } - - offset += 4; - } - } - } - - public static void Str(ILEmitterCtx context) - { - EmitLoadOrStore(context, WordSizeLog2, AccessType.Store); - } - - public static void Strb(ILEmitterCtx context) - { - EmitLoadOrStore(context, ByteSizeLog2, AccessType.Store); - } - - public static void Strd(ILEmitterCtx context) - { - EmitLoadOrStore(context, DWordSizeLog2, AccessType.Store); - } - - public static void Strh(ILEmitterCtx context) - { - EmitLoadOrStore(context, HWordSizeLog2, AccessType.Store); - } - - private static void EmitLoadOrStore(ILEmitterCtx context, int size, AccessType accType) - { - OpCode32Mem op = (OpCode32Mem)context.CurrOp; - - if (op.Index || op.WBack) - { - EmitLoadFromRegister(context, op.Rn); - - context.EmitLdc_I4(op.Imm); - - context.Emit(op.Add ? OpCodes.Add : OpCodes.Sub); - - context.EmitSttmp(); - } - - if (op.Index) - { - context.EmitLdtmp(); - } - else - { - EmitLoadFromRegister(context, op.Rn); - } - - if ((accType & AccessType.Load) != 0) - { - if ((accType & AccessType.Signed) != 0) - { - EmitReadSx32Call(context, size); - } - else - { - EmitReadZxCall(context, size); - } - - if (op.WBack) - { - context.EmitLdtmp(); - - EmitStoreToRegister(context, op.Rn); - } - - if (size == DWordSizeLog2) - { - context.Emit(OpCodes.Dup); - - context.EmitLdflg((int)PState.EBit); - - ILLabel lblBigEndian = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.Emit(OpCodes.Brtrue_S, lblBigEndian); - - // Little endian mode. - context.Emit(OpCodes.Conv_U4); - - EmitStoreToRegister(context, op.Rt); - - context.EmitLsr(32); - - context.Emit(OpCodes.Conv_U4); - - EmitStoreToRegister(context, op.Rt | 1); - - context.Emit(OpCodes.Br_S, lblEnd); - - // Big endian mode. - context.MarkLabel(lblBigEndian); - - context.EmitLsr(32); - - context.Emit(OpCodes.Conv_U4); - - EmitStoreToRegister(context, op.Rt); - - context.Emit(OpCodes.Conv_U4); - - EmitStoreToRegister(context, op.Rt | 1); - - context.MarkLabel(lblEnd); - } - else - { - EmitStoreToRegister(context, op.Rt); - } - } - else - { - if (op.WBack) - { - context.EmitLdtmp(); - - EmitStoreToRegister(context, op.Rn); - } - - EmitLoadFromRegister(context, op.Rt); - - if (size == DWordSizeLog2) - { - context.Emit(OpCodes.Conv_U8); - - context.EmitLdflg((int)PState.EBit); - - ILLabel lblBigEndian = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.Emit(OpCodes.Brtrue_S, lblBigEndian); - - // Little endian mode. - EmitLoadFromRegister(context, op.Rt | 1); - - context.Emit(OpCodes.Conv_U8); - - context.EmitLsl(32); - - context.Emit(OpCodes.Or); - - context.Emit(OpCodes.Br_S, lblEnd); - - // Big endian mode. - context.MarkLabel(lblBigEndian); - - context.EmitLsl(32); - - EmitLoadFromRegister(context, op.Rt | 1); - - context.Emit(OpCodes.Conv_U8); - - context.Emit(OpCodes.Or); - - context.MarkLabel(lblEnd); - } - - EmitWriteCall(context, size); - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitMemoryEx.cs b/ChocolArm64/Instructions/InstEmitMemoryEx.cs deleted file mode 100644 index 5deb035d..00000000 --- a/ChocolArm64/Instructions/InstEmitMemoryEx.cs +++ /dev/null @@ -1,350 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.Memory; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; -using System.Threading; - -using static ChocolArm64.Instructions.InstEmitMemoryHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - [Flags] - private enum AccessType - { - None = 0, - Ordered = 1, - Exclusive = 2, - OrderedEx = Ordered | Exclusive - } - - public static void Clrex(ILEmitterCtx context) - { - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.ClearExclusiveAddress)); - } - - public static void Dmb(ILEmitterCtx context) => EmitBarrier(context); - public static void Dsb(ILEmitterCtx context) => EmitBarrier(context); - - public static void Ldar(ILEmitterCtx context) => EmitLdr(context, AccessType.Ordered); - public static void Ldaxr(ILEmitterCtx context) => EmitLdr(context, AccessType.OrderedEx); - public static void Ldxr(ILEmitterCtx context) => EmitLdr(context, AccessType.Exclusive); - public static void Ldxp(ILEmitterCtx context) => EmitLdp(context, AccessType.Exclusive); - public static void Ldaxp(ILEmitterCtx context) => EmitLdp(context, AccessType.OrderedEx); - - private static void EmitLdr(ILEmitterCtx context, AccessType accType) - { - EmitLoad(context, accType, pair: false); - } - - private static void EmitLdp(ILEmitterCtx context, AccessType accType) - { - EmitLoad(context, accType, pair: true); - } - - private static void EmitLoad(ILEmitterCtx context, AccessType accType, bool pair) - { - OpCodeMemEx64 op = (OpCodeMemEx64)context.CurrOp; - - bool ordered = (accType & AccessType.Ordered) != 0; - bool exclusive = (accType & AccessType.Exclusive) != 0; - - if (ordered) - { - EmitBarrier(context); - } - - context.EmitLdint(op.Rn); - context.EmitSttmp(); - - if (exclusive) - { - context.EmitLdarg(TranslatedSub.StateArgIdx); - context.EmitLdtmp(); - - context.EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.SetExclusiveAddress)); - } - - void WriteExclusiveValue(string propName) - { - context.Emit(OpCodes.Dup); - - if (op.Size < 3) - { - context.Emit(OpCodes.Conv_U8); - } - - context.EmitSttmp2(); - context.EmitLdarg(TranslatedSub.StateArgIdx); - context.EmitLdtmp2(); - - context.EmitCallPrivatePropSet(typeof(CpuThreadState), propName); - } - - if (pair) - { - // Exclusive loads should be atomic. For pairwise loads, we need to - // read all the data at once. For a 32-bits pairwise load, we do a - // simple 64-bits load, for a 128-bits load, we need to call a special - // method to read 128-bits atomically. - if (op.Size == 2) - { - context.EmitLdtmp(); - - EmitReadZxCall(context, 3); - - context.Emit(OpCodes.Dup); - - // Mask low half. - context.Emit(OpCodes.Conv_U4); - - if (exclusive) - { - WriteExclusiveValue(nameof(CpuThreadState.ExclusiveValueLow)); - } - - context.EmitStintzr(op.Rt); - - // Shift high half. - context.EmitLsr(32); - context.Emit(OpCodes.Conv_U4); - - if (exclusive) - { - WriteExclusiveValue(nameof(CpuThreadState.ExclusiveValueHigh)); - } - - context.EmitStintzr(op.Rt2); - } - else if (op.Size == 3) - { - context.EmitLdarg(TranslatedSub.MemoryArgIdx); - context.EmitLdtmp(); - - context.EmitPrivateCall(typeof(MemoryManager), nameof(MemoryManager.AtomicReadInt128)); - - context.Emit(OpCodes.Dup); - - // Load low part of the vector. - context.EmitLdc_I4(0); - context.EmitLdc_I4(3); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorExtractIntZx)); - - if (exclusive) - { - WriteExclusiveValue(nameof(CpuThreadState.ExclusiveValueLow)); - } - - context.EmitStintzr(op.Rt); - - // Load high part of the vector. - context.EmitLdc_I4(1); - context.EmitLdc_I4(3); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorExtractIntZx)); - - if (exclusive) - { - WriteExclusiveValue(nameof(CpuThreadState.ExclusiveValueHigh)); - } - - context.EmitStintzr(op.Rt2); - } - else - { - throw new InvalidOperationException($"Invalid load size of {1 << op.Size} bytes."); - } - } - else - { - // 8, 16, 32 or 64-bits (non-pairwise) load. - context.EmitLdtmp(); - - EmitReadZxCall(context, op.Size); - - if (exclusive) - { - WriteExclusiveValue(nameof(CpuThreadState.ExclusiveValueLow)); - } - - context.EmitStintzr(op.Rt); - } - } - - public static void Pfrm(ILEmitterCtx context) - { - // Memory Prefetch, execute as no-op. - } - - public static void Stlr(ILEmitterCtx context) => EmitStr(context, AccessType.Ordered); - public static void Stlxr(ILEmitterCtx context) => EmitStr(context, AccessType.OrderedEx); - public static void Stxr(ILEmitterCtx context) => EmitStr(context, AccessType.Exclusive); - public static void Stxp(ILEmitterCtx context) => EmitStp(context, AccessType.Exclusive); - public static void Stlxp(ILEmitterCtx context) => EmitStp(context, AccessType.OrderedEx); - - private static void EmitStr(ILEmitterCtx context, AccessType accType) - { - EmitStore(context, accType, pair: false); - } - - private static void EmitStp(ILEmitterCtx context, AccessType accType) - { - EmitStore(context, accType, pair: true); - } - - private static void EmitStore(ILEmitterCtx context, AccessType accType, bool pair) - { - OpCodeMemEx64 op = (OpCodeMemEx64)context.CurrOp; - - bool ordered = (accType & AccessType.Ordered) != 0; - bool exclusive = (accType & AccessType.Exclusive) != 0; - - if (ordered) - { - EmitBarrier(context); - } - - if (exclusive) - { - ILLabel lblEx = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - context.EmitLdint(op.Rn); - - context.EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.CheckExclusiveAddress)); - - context.Emit(OpCodes.Brtrue_S, lblEx); - - // Address check failed, set error right away and do not store anything. - context.EmitLdc_I4(1); - context.EmitStintzr(op.Rs); - - context.Emit(OpCodes.Br, lblEnd); - - // Address check passed. - context.MarkLabel(lblEx); - - context.EmitLdarg(TranslatedSub.MemoryArgIdx); - context.EmitLdint(op.Rn); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitCallPrivatePropGet(typeof(CpuThreadState), nameof(CpuThreadState.ExclusiveValueLow)); - - void EmitCast() - { - // The input should be always int64. - switch (op.Size) - { - case 0: context.Emit(OpCodes.Conv_U1); break; - case 1: context.Emit(OpCodes.Conv_U2); break; - case 2: context.Emit(OpCodes.Conv_U4); break; - } - } - - EmitCast(); - - if (pair) - { - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitCallPrivatePropGet(typeof(CpuThreadState), nameof(CpuThreadState.ExclusiveValueHigh)); - - EmitCast(); - - context.EmitLdintzr(op.Rt); - - EmitCast(); - - context.EmitLdintzr(op.Rt2); - - EmitCast(); - - switch (op.Size) - { - case 2: context.EmitPrivateCall(typeof(MemoryManager), nameof(MemoryManager.AtomicCompareExchange2xInt32)); break; - case 3: context.EmitPrivateCall(typeof(MemoryManager), nameof(MemoryManager.AtomicCompareExchangeInt128)); break; - - default: throw new InvalidOperationException($"Invalid store size of {1 << op.Size} bytes."); - } - } - else - { - context.EmitLdintzr(op.Rt); - - EmitCast(); - - switch (op.Size) - { - case 0: context.EmitCall(typeof(MemoryManager), nameof(MemoryManager.AtomicCompareExchangeByte)); break; - case 1: context.EmitCall(typeof(MemoryManager), nameof(MemoryManager.AtomicCompareExchangeInt16)); break; - case 2: context.EmitCall(typeof(MemoryManager), nameof(MemoryManager.AtomicCompareExchangeInt32)); break; - case 3: context.EmitCall(typeof(MemoryManager), nameof(MemoryManager.AtomicCompareExchangeInt64)); break; - - default: throw new InvalidOperationException($"Invalid store size of {1 << op.Size} bytes."); - } - } - - // The value returned is a bool, true if the values compared - // were equal and the new value was written, false otherwise. - // We need to invert this result, as on ARM 1 indicates failure, - // and 0 success on those instructions. - context.EmitLdc_I4(1); - - context.Emit(OpCodes.Xor); - context.Emit(OpCodes.Dup); - context.Emit(OpCodes.Conv_U8); - - context.EmitStintzr(op.Rs); - - // Only clear the exclusive monitor if the store was successful (Rs = false). - context.Emit(OpCodes.Brtrue_S, lblEnd); - - Clrex(context); - - context.MarkLabel(lblEnd); - } - else - { - void EmitWriteCall(int rt, long offset) - { - context.EmitLdint(op.Rn); - - if (offset != 0) - { - context.EmitLdc_I8(offset); - - context.Emit(OpCodes.Add); - } - - context.EmitLdintzr(rt); - - InstEmitMemoryHelper.EmitWriteCall(context, op.Size); - } - - EmitWriteCall(op.Rt, 0); - - if (pair) - { - EmitWriteCall(op.Rt2, 1 << op.Size); - } - } - } - - private static void EmitBarrier(ILEmitterCtx context) - { - // Note: This barrier is most likely not necessary, and probably - // doesn't make any difference since we need to do a ton of stuff - // (software MMU emulation) to read or write anything anyway. - context.EmitCall(typeof(Thread), nameof(Thread.MemoryBarrier)); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitMemoryHelper.cs b/ChocolArm64/Instructions/InstEmitMemoryHelper.cs deleted file mode 100644 index 08c8265b..00000000 --- a/ChocolArm64/Instructions/InstEmitMemoryHelper.cs +++ /dev/null @@ -1,475 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.Memory; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; -using System.Runtime.Intrinsics.X86; - -namespace ChocolArm64.Instructions -{ - static class InstEmitMemoryHelper - { - private static int _tempIntAddress = ILEmitterCtx.GetIntTempIndex(); - private static int _tempIntValue = ILEmitterCtx.GetIntTempIndex(); - private static int _tempIntPtAddr = ILEmitterCtx.GetIntTempIndex(); - private static int _tempVecValue = ILEmitterCtx.GetVecTempIndex(); - - private enum Extension - { - Zx, - Sx32, - Sx64 - } - - public static void EmitReadZxCall(ILEmitterCtx context, int size) - { - EmitReadCall(context, Extension.Zx, size); - } - - public static void EmitReadSx32Call(ILEmitterCtx context, int size) - { - EmitReadCall(context, Extension.Sx32, size); - } - - public static void EmitReadSx64Call(ILEmitterCtx context, int size) - { - EmitReadCall(context, Extension.Sx64, size); - } - - private static void EmitReadCall(ILEmitterCtx context, Extension ext, int size) - { - // Save the address into a temp. - context.EmitStint(_tempIntAddress); - - bool isSimd = IsSimd(context); - - if (size < 0 || size > (isSimd ? 4 : 3)) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - if (isSimd) - { - if (context.Tier == TranslationTier.Tier0 || !Sse2.IsSupported || size < 2) - { - EmitReadVectorFallback(context, size); - } - else - { - EmitReadVector(context, size); - } - } - else - { - if (context.Tier == TranslationTier.Tier0) - { - EmitReadIntFallback(context, size); - } - else - { - EmitReadInt(context, size); - } - } - - if (!isSimd) - { - if (ext == Extension.Sx32 || - ext == Extension.Sx64) - { - switch (size) - { - case 0: context.Emit(OpCodes.Conv_I1); break; - case 1: context.Emit(OpCodes.Conv_I2); break; - case 2: context.Emit(OpCodes.Conv_I4); break; - } - } - - if (size < 3) - { - context.Emit(ext == Extension.Sx64 - ? OpCodes.Conv_I8 - : OpCodes.Conv_U8); - } - } - } - - public static void EmitWriteCall(ILEmitterCtx context, int size) - { - bool isSimd = IsSimd(context); - - // Save the value into a temp. - if (isSimd) - { - context.EmitStvec(_tempVecValue); - } - else - { - context.EmitStint(_tempIntValue); - } - - // Save the address into a temp. - context.EmitStint(_tempIntAddress); - - if (size < 0 || size > (isSimd ? 4 : 3)) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - if (isSimd) - { - if (context.Tier == TranslationTier.Tier0 || !Sse2.IsSupported || size < 2) - { - EmitWriteVectorFallback(context, size); - } - else - { - EmitWriteVector(context, size); - } - } - else - { - if (context.Tier == TranslationTier.Tier0) - { - EmitWriteIntFallback(context, size); - } - else - { - EmitWriteInt(context, size); - } - } - } - - private static bool IsSimd(ILEmitterCtx context) - { - return context.CurrOp is IOpCodeSimd64 && - !(context.CurrOp is OpCodeSimdMemMs64 || - context.CurrOp is OpCodeSimdMemSs64); - } - - private static void EmitReadInt(ILEmitterCtx context, int size) - { - EmitAddressCheck(context, size); - - ILLabel lblFastPath = new ILLabel(); - ILLabel lblSlowPath = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.Emit(OpCodes.Brfalse_S, lblFastPath); - - context.MarkLabel(lblSlowPath); - - EmitReadIntFallback(context, size); - - context.Emit(OpCodes.Br, lblEnd); - - context.MarkLabel(lblFastPath); - - EmitPtPointerLoad(context, lblSlowPath); - - switch (size) - { - case 0: context.Emit(OpCodes.Ldind_U1); break; - case 1: context.Emit(OpCodes.Ldind_U2); break; - case 2: context.Emit(OpCodes.Ldind_U4); break; - case 3: context.Emit(OpCodes.Ldind_I8); break; - } - - context.MarkLabel(lblEnd); - } - - private static void EmitReadVector(ILEmitterCtx context, int size) - { - EmitAddressCheck(context, size); - - ILLabel lblFastPath = new ILLabel(); - ILLabel lblSlowPath = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.Emit(OpCodes.Brfalse_S, lblFastPath); - - context.MarkLabel(lblSlowPath); - - EmitReadVectorFallback(context, size); - - context.Emit(OpCodes.Br, lblEnd); - - context.MarkLabel(lblFastPath); - - EmitPtPointerLoad(context, lblSlowPath); - - switch (size) - { - case 2: context.EmitCall(typeof(Sse), nameof(Sse.LoadScalarVector128)); break; - - case 3: - { - Type[] types = new Type[] { typeof(double*) }; - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.LoadScalarVector128), types)); - - break; - } - - case 4: context.EmitCall(typeof(Sse), nameof(Sse.LoadAlignedVector128)); break; - - throw new InvalidOperationException($"Invalid vector load size of {1 << size} bytes."); - } - - context.MarkLabel(lblEnd); - } - - private static void EmitWriteInt(ILEmitterCtx context, int size) - { - EmitAddressCheck(context, size); - - ILLabel lblFastPath = new ILLabel(); - ILLabel lblSlowPath = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.Emit(OpCodes.Brfalse_S, lblFastPath); - - context.MarkLabel(lblSlowPath); - - EmitWriteIntFallback(context, size); - - context.Emit(OpCodes.Br, lblEnd); - - context.MarkLabel(lblFastPath); - - EmitPtPointerLoad(context, lblSlowPath); - - context.EmitLdint(_tempIntValue); - - if (size < 3) - { - context.Emit(OpCodes.Conv_U4); - } - - switch (size) - { - case 0: context.Emit(OpCodes.Stind_I1); break; - case 1: context.Emit(OpCodes.Stind_I2); break; - case 2: context.Emit(OpCodes.Stind_I4); break; - case 3: context.Emit(OpCodes.Stind_I8); break; - } - - context.MarkLabel(lblEnd); - } - - private static void EmitWriteVector(ILEmitterCtx context, int size) - { - EmitAddressCheck(context, size); - - ILLabel lblFastPath = new ILLabel(); - ILLabel lblSlowPath = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.Emit(OpCodes.Brfalse_S, lblFastPath); - - context.MarkLabel(lblSlowPath); - - EmitWriteVectorFallback(context, size); - - context.Emit(OpCodes.Br, lblEnd); - - context.MarkLabel(lblFastPath); - - EmitPtPointerLoad(context, lblSlowPath); - - context.EmitLdvec(_tempVecValue); - - switch (size) - { - case 2: context.EmitCall(typeof(Sse), nameof(Sse.StoreScalar)); break; - case 3: context.EmitCall(typeof(Sse2), nameof(Sse2.StoreScalar)); break; - case 4: context.EmitCall(typeof(Sse), nameof(Sse.StoreAligned)); break; - - default: throw new InvalidOperationException($"Invalid vector store size of {1 << size} bytes."); - } - - context.MarkLabel(lblEnd); - } - - private static void EmitAddressCheck(ILEmitterCtx context, int size) - { - long addressCheckMask = ~(context.Memory.AddressSpaceSize - 1); - - addressCheckMask |= (1u << size) - 1; - - context.EmitLdint(_tempIntAddress); - - context.EmitLdc_I(addressCheckMask); - - context.Emit(OpCodes.And); - } - - private static void EmitPtPointerLoad(ILEmitterCtx context, ILLabel lblFallbackPath) - { - context.EmitLdc_I8(context.Memory.PageTable.ToInt64()); - - context.Emit(OpCodes.Conv_I); - - int bit = MemoryManager.PageBits; - - do - { - context.EmitLdint(_tempIntAddress); - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U8); - } - - context.EmitLsr(bit); - - bit += context.Memory.PtLevelBits; - - if (bit < context.Memory.AddressSpaceBits) - { - context.EmitLdc_I8(context.Memory.PtLevelMask); - - context.Emit(OpCodes.And); - } - - context.EmitLdc_I8(IntPtr.Size); - - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Conv_I); - context.Emit(OpCodes.Add); - context.Emit(OpCodes.Ldind_I); - } - while (bit < context.Memory.AddressSpaceBits); - - if (!context.Memory.HasWriteWatchSupport) - { - context.Emit(OpCodes.Conv_U8); - - context.EmitStint(_tempIntPtAddr); - context.EmitLdint(_tempIntPtAddr); - - context.EmitLdc_I8(MemoryManager.PteFlagsMask); - - context.Emit(OpCodes.And); - - context.Emit(OpCodes.Brtrue, lblFallbackPath); - - context.EmitLdint(_tempIntPtAddr); - - context.Emit(OpCodes.Conv_I); - } - - context.EmitLdint(_tempIntAddress); - - context.EmitLdc_I(MemoryManager.PageMask); - - context.Emit(OpCodes.And); - context.Emit(OpCodes.Conv_I); - context.Emit(OpCodes.Add); - } - - private static void EmitReadIntFallback(ILEmitterCtx context, int size) - { - context.EmitLdarg(TranslatedSub.MemoryArgIdx); - context.EmitLdint(_tempIntAddress); - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U8); - } - - string fallbackMethodName = null; - - switch (size) - { - case 0: fallbackMethodName = nameof(MemoryManager.ReadByte); break; - case 1: fallbackMethodName = nameof(MemoryManager.ReadUInt16); break; - case 2: fallbackMethodName = nameof(MemoryManager.ReadUInt32); break; - case 3: fallbackMethodName = nameof(MemoryManager.ReadUInt64); break; - } - - context.EmitCall(typeof(MemoryManager), fallbackMethodName); - } - - private static void EmitReadVectorFallback(ILEmitterCtx context, int size) - { - context.EmitLdarg(TranslatedSub.MemoryArgIdx); - context.EmitLdint(_tempIntAddress); - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U8); - } - - string fallbackMethodName = null; - - switch (size) - { - case 0: fallbackMethodName = nameof(MemoryManager.ReadVector8); break; - case 1: fallbackMethodName = nameof(MemoryManager.ReadVector16); break; - case 2: fallbackMethodName = nameof(MemoryManager.ReadVector32); break; - case 3: fallbackMethodName = nameof(MemoryManager.ReadVector64); break; - case 4: fallbackMethodName = nameof(MemoryManager.ReadVector128); break; - } - - context.EmitCall(typeof(MemoryManager), fallbackMethodName); - } - - private static void EmitWriteIntFallback(ILEmitterCtx context, int size) - { - context.EmitLdarg(TranslatedSub.MemoryArgIdx); - context.EmitLdint(_tempIntAddress); - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U8); - } - - context.EmitLdint(_tempIntValue); - - if (size < 3) - { - context.Emit(OpCodes.Conv_U4); - } - - string fallbackMethodName = null; - - switch (size) - { - case 0: fallbackMethodName = nameof(MemoryManager.WriteByte); break; - case 1: fallbackMethodName = nameof(MemoryManager.WriteUInt16); break; - case 2: fallbackMethodName = nameof(MemoryManager.WriteUInt32); break; - case 3: fallbackMethodName = nameof(MemoryManager.WriteUInt64); break; - } - - context.EmitCall(typeof(MemoryManager), fallbackMethodName); - } - - private static void EmitWriteVectorFallback(ILEmitterCtx context, int size) - { - context.EmitLdarg(TranslatedSub.MemoryArgIdx); - context.EmitLdint(_tempIntAddress); - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U8); - } - - context.EmitLdvec(_tempVecValue); - - string fallbackMethodName = null; - - switch (size) - { - case 0: fallbackMethodName = nameof(MemoryManager.WriteVector8); break; - case 1: fallbackMethodName = nameof(MemoryManager.WriteVector16); break; - case 2: fallbackMethodName = nameof(MemoryManager.WriteVector32); break; - case 3: fallbackMethodName = nameof(MemoryManager.WriteVector64); break; - case 4: fallbackMethodName = nameof(MemoryManager.WriteVector128Internal); break; - } - - context.EmitCall(typeof(MemoryManager), fallbackMethodName); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitMove.cs b/ChocolArm64/Instructions/InstEmitMove.cs deleted file mode 100644 index be3e8e2d..00000000 --- a/ChocolArm64/Instructions/InstEmitMove.cs +++ /dev/null @@ -1,41 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.Translation; -using System.Reflection.Emit; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Movk(ILEmitterCtx context) - { - OpCodeMov64 op = (OpCodeMov64)context.CurrOp; - - context.EmitLdintzr(op.Rd); - context.EmitLdc_I(~(0xffffL << op.Pos)); - - context.Emit(OpCodes.And); - - context.EmitLdc_I(op.Imm); - - context.Emit(OpCodes.Or); - - context.EmitStintzr(op.Rd); - } - - public static void Movn(ILEmitterCtx context) - { - OpCodeMov64 op = (OpCodeMov64)context.CurrOp; - - context.EmitLdc_I(~op.Imm); - context.EmitStintzr(op.Rd); - } - - public static void Movz(ILEmitterCtx context) - { - OpCodeMov64 op = (OpCodeMov64)context.CurrOp; - - context.EmitLdc_I(op.Imm); - context.EmitStintzr(op.Rd); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitMul.cs b/ChocolArm64/Instructions/InstEmitMul.cs deleted file mode 100644 index b7418e69..00000000 --- a/ChocolArm64/Instructions/InstEmitMul.cs +++ /dev/null @@ -1,80 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.Translation; -using System.Reflection.Emit; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Madd(ILEmitterCtx context) => EmitMul(context, OpCodes.Add); - public static void Msub(ILEmitterCtx context) => EmitMul(context, OpCodes.Sub); - - private static void EmitMul(ILEmitterCtx context, OpCode ilOp) - { - OpCodeMul64 op = (OpCodeMul64)context.CurrOp; - - context.EmitLdintzr(op.Ra); - context.EmitLdintzr(op.Rn); - context.EmitLdintzr(op.Rm); - - context.Emit(OpCodes.Mul); - context.Emit(ilOp); - - context.EmitStintzr(op.Rd); - } - - public static void Smaddl(ILEmitterCtx context) => EmitMull(context, OpCodes.Add, true); - public static void Smsubl(ILEmitterCtx context) => EmitMull(context, OpCodes.Sub, true); - public static void Umaddl(ILEmitterCtx context) => EmitMull(context, OpCodes.Add, false); - public static void Umsubl(ILEmitterCtx context) => EmitMull(context, OpCodes.Sub, false); - - private static void EmitMull(ILEmitterCtx context, OpCode addSubOp, bool signed) - { - OpCodeMul64 op = (OpCodeMul64)context.CurrOp; - - OpCode castOp = signed - ? OpCodes.Conv_I8 - : OpCodes.Conv_U8; - - context.EmitLdintzr(op.Ra); - context.EmitLdintzr(op.Rn); - - context.Emit(OpCodes.Conv_I4); - context.Emit(castOp); - - context.EmitLdintzr(op.Rm); - - context.Emit(OpCodes.Conv_I4); - context.Emit(castOp); - context.Emit(OpCodes.Mul); - - context.Emit(addSubOp); - - context.EmitStintzr(op.Rd); - } - - public static void Smulh(ILEmitterCtx context) - { - OpCodeMul64 op = (OpCodeMul64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - context.EmitLdintzr(op.Rm); - - SoftFallback.EmitCall(context, nameof(SoftFallback.SMulHi128)); - - context.EmitStintzr(op.Rd); - } - - public static void Umulh(ILEmitterCtx context) - { - OpCodeMul64 op = (OpCodeMul64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - context.EmitLdintzr(op.Rm); - - SoftFallback.EmitCall(context, nameof(SoftFallback.UMulHi128)); - - context.EmitStintzr(op.Rd); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitSimdArithmetic.cs b/ChocolArm64/Instructions/InstEmitSimdArithmetic.cs deleted file mode 100644 index fa9666eb..00000000 --- a/ChocolArm64/Instructions/InstEmitSimdArithmetic.cs +++ /dev/null @@ -1,3797 +0,0 @@ -// https://github.com/intel/ARM_NEON_2_x86_SSE/blob/master/NEON_2_SSE.h -// https://www.agner.org/optimize/#vectorclass @ vectori128.h - -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -using static ChocolArm64.Instructions.InstEmitSimdHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Abs_S(ILEmitterCtx context) - { - EmitScalarUnaryOpSx(context, () => EmitAbs(context)); - } - - public static void Abs_V(ILEmitterCtx context) - { - EmitVectorUnaryOpSx(context, () => EmitAbs(context)); - } - - public static void Add_S(ILEmitterCtx context) - { - EmitScalarBinaryOpZx(context, () => context.Emit(OpCodes.Add)); - } - - public static void Add_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - EmitSse2Op(context, nameof(Sse2.Add)); - } - else - { - EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.Add)); - } - } - - public static void Addhn_V(ILEmitterCtx context) - { - EmitHighNarrow(context, () => context.Emit(OpCodes.Add), round: false); - } - - public static void Addp_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - EmitVectorExtractZx(context, op.Rn, 0, op.Size); - EmitVectorExtractZx(context, op.Rn, 1, op.Size); - - context.Emit(OpCodes.Add); - - EmitScalarSet(context, op.Rd, op.Size); - } - - public static void Addp_V(ILEmitterCtx context) - { - EmitVectorPairwiseOpZx(context, () => context.Emit(OpCodes.Add)); - } - - public static void Addv_V(ILEmitterCtx context) - { - EmitVectorAcrossVectorOpZx(context, () => context.Emit(OpCodes.Add)); - } - - public static void Cls_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - int eSize = 8 << op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size); - - context.EmitLdc_I4(eSize); - - SoftFallback.EmitCall(context, nameof(SoftFallback.CountLeadingSigns)); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Clz_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - int eSize = 8 << op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size); - - if (Lzcnt.IsSupported && eSize == 32) - { - context.Emit(OpCodes.Conv_U4); - - context.EmitCall(typeof(Lzcnt).GetMethod(nameof(Lzcnt.LeadingZeroCount), new Type[] { typeof(uint) })); - - context.Emit(OpCodes.Conv_U8); - } - else - { - context.EmitLdc_I4(eSize); - - SoftFallback.EmitCall(context, nameof(SoftFallback.CountLeadingZeros)); - } - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Cnt_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int elems = op.RegisterSize == RegisterSize.Simd128 ? 16 : 8; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, 0); - - if (Popcnt.IsSupported) - { - context.EmitCall(typeof(Popcnt).GetMethod(nameof(Popcnt.PopCount), new Type[] { typeof(ulong) })); - } - else - { - SoftFallback.EmitCall(context, nameof(SoftFallback.CountSetBits8)); - } - - EmitVectorInsert(context, op.Rd, index, 0); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Fabd_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSsv = new Type[] { typeof(float) }; - Type[] typesSubAnt = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(-0f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), typesSubAnt)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AndNot), typesSubAnt)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (sizeF == 1) */ - { - Type[] typesSsv = new Type[] { typeof(double) }; - Type[] typesSubAnt = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(-0d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), typesSubAnt)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesSubAnt)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub)); - - EmitUnaryMathCall(context, nameof(Math.Abs)); - }); - } - } - - public static void Fabd_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSav = new Type[] { typeof(float) }; - Type[] typesSubAnt = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(-0f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), typesSubAnt)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AndNot), typesSubAnt)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSav = new Type[] { typeof(double) }; - Type[] typesSubAnt = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(-0d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSubAnt)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesSubAnt)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub)); - - EmitUnaryMathCall(context, nameof(Math.Abs)); - }); - } - } - - public static void Fabs_S(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - if (op.Size == 0) - { - Type[] typesSsv = new Type[] { typeof(float) }; - Type[] typesAnt = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(-0f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (op.Size == 1) */ - { - Type[] typesSsv = new Type[] { typeof(double) }; - Type[] typesAnt = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(-0d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Abs)); - }); - } - } - - public static void Fabs_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSav = new Type[] { typeof(float) }; - Type[] typesAnt = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(-0f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSav = new Type[] { typeof(double) }; - Type[] typesAnt = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(-0d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Abs)); - }); - } - } - - public static void Fadd_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.AddScalar)); - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd)); - }); - } - } - - public static void Fadd_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Add)); - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd)); - }); - } - } - - public static void Faddp_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.FastFP && Optimizations.UseSse3) - { - if (sizeF == 0) - { - Type[] typesAddH = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse3).GetMethod(nameof(Sse3.HorizontalAdd), typesAddH)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (sizeF == 1) */ - { - Type[] typesAddH = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse3).GetMethod(nameof(Sse3.HorizontalAdd), typesAddH)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorExtractF(context, op.Rn, 0, sizeF); - EmitVectorExtractF(context, op.Rn, 1, sizeF); - - EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd)); - - EmitScalarSetF(context, op.Rd, sizeF); - } - } - - public static void Faddp_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorPairwiseSseOrSse2OpF(context, nameof(Sse.Add)); - } - else - { - EmitVectorPairwiseOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd)); - }); - } - } - - public static void Fdiv_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.DivideScalar)); - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPDiv)); - }); - } - } - - public static void Fdiv_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Divide)); - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPDiv)); - }); - } - } - - public static void Fmadd_S(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (op.Size == 0) - { - Type[] typesMulAdd = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Ra); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulAdd)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AddScalar), typesMulAdd)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (op.Size == 1) */ - { - Type[] typesMulAdd = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Ra); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulAdd)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AddScalar), typesMulAdd)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarTernaryRaOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulAdd)); - }); - } - } - - public static void Fmax_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.MaxScalar)); - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax)); - }); - } - } - - public static void Fmax_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Max)); - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax)); - }); - } - } - - public static void Fmaxnm_S(ILEmitterCtx context) - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMaxNum)); - }); - } - - public static void Fmaxnm_V(ILEmitterCtx context) - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMaxNum)); - }); - } - - public static void Fmaxp_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorPairwiseSseOrSse2OpF(context, nameof(Sse.Max)); - } - else - { - EmitVectorPairwiseOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax)); - }); - } - } - - public static void Fmin_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.MinScalar)); - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin)); - }); - } - } - - public static void Fmin_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Min)); - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin)); - }); - } - } - - public static void Fminnm_S(ILEmitterCtx context) - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMinNum)); - }); - } - - public static void Fminnm_V(ILEmitterCtx context) - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMinNum)); - }); - } - - public static void Fminp_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorPairwiseSseOrSse2OpF(context, nameof(Sse.Min)); - } - else - { - EmitVectorPairwiseOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin)); - }); - } - } - - public static void Fmla_Se(ILEmitterCtx context) - { - EmitScalarTernaryOpByElemF(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - - public static void Fmla_V(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesMulAdd = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulAdd)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Add), typesMulAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesMulAdd = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulAdd)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesMulAdd)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorTernaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulAdd)); - }); - } - } - - public static void Fmla_Ve(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSfl = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>), typeof(byte) }; - Type[] typesMulAdd = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(op.Index | op.Index << 2 | op.Index << 4 | op.Index << 6); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulAdd)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Add), typesMulAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSfl = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>), typeof(byte) }; - Type[] typesMulAdd = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(op.Index | op.Index << 1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulAdd)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesMulAdd)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorTernaryOpByElemF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulAdd)); - }); - } - } - - public static void Fmls_Se(ILEmitterCtx context) - { - EmitScalarTernaryOpByElemF(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - - public static void Fmls_V(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorTernaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulSub)); - }); - } - } - - public static void Fmls_Ve(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSfl = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>), typeof(byte) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(op.Index | op.Index << 2 | op.Index << 4 | op.Index << 6); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSfl = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>), typeof(byte) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(op.Index | op.Index << 1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorTernaryOpByElemF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulSub)); - }); - } - } - - public static void Fmsub_S(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (op.Size == 0) - { - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Ra); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), typesMulSub)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (op.Size == 1) */ - { - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Ra); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), typesMulSub)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarTernaryRaOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulSub)); - }); - } - } - - public static void Fmul_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.MultiplyScalar)); - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMul)); - }); - } - } - - public static void Fmul_Se(ILEmitterCtx context) - { - EmitScalarBinaryOpByElemF(context, () => context.Emit(OpCodes.Mul)); - } - - public static void Fmul_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Multiply)); - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMul)); - }); - } - } - - public static void Fmul_Ve(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSfl = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>), typeof(byte) }; - Type[] typesMul = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rn); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(op.Index | op.Index << 2 | op.Index << 4 | op.Index << 6); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMul)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSfl = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>), typeof(byte) }; - Type[] typesMul = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rn); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(op.Index | op.Index << 1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMul)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorBinaryOpByElemF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMul)); - }); - } - } - - public static void Fmulx_S(ILEmitterCtx context) - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulX)); - }); - } - - public static void Fmulx_Se(ILEmitterCtx context) - { - EmitScalarBinaryOpByElemF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulX)); - }); - } - - public static void Fmulx_V(ILEmitterCtx context) - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulX)); - }); - } - - public static void Fmulx_Ve(ILEmitterCtx context) - { - EmitVectorBinaryOpByElemF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulX)); - }); - } - - public static void Fneg_S(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - if (op.Size == 0) - { - Type[] typesSsv = new Type[] { typeof(float) }; - Type[] typesXor = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(-0f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Xor), typesXor)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (op.Size == 1) */ - { - Type[] typesSsv = new Type[] { typeof(double) }; - Type[] typesXor = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(-0d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesXor)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarUnaryOpF(context, () => context.Emit(OpCodes.Neg)); - } - } - - public static void Fneg_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSav = new Type[] { typeof(float) }; - Type[] typesXor = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(-0f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Xor), typesXor)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSav = new Type[] { typeof(double) }; - Type[] typesXor = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(-0d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesXor)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorUnaryOpF(context, () => context.Emit(OpCodes.Neg)); - } - } - - public static void Fnmadd_S(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - EmitVectorExtractF(context, op.Rn, 0, sizeF); - - context.Emit(OpCodes.Neg); - - EmitVectorExtractF(context, op.Rm, 0, sizeF); - - context.Emit(OpCodes.Mul); - - EmitVectorExtractF(context, op.Ra, 0, sizeF); - - context.Emit(OpCodes.Sub); - - EmitScalarSetF(context, op.Rd, sizeF); - } - - public static void Fnmsub_S(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - EmitVectorExtractF(context, op.Rn, 0, sizeF); - EmitVectorExtractF(context, op.Rm, 0, sizeF); - - context.Emit(OpCodes.Mul); - - EmitVectorExtractF(context, op.Ra, 0, sizeF); - - context.Emit(OpCodes.Sub); - - EmitScalarSetF(context, op.Rd, sizeF); - } - - public static void Fnmul_S(ILEmitterCtx context) - { - EmitScalarBinaryOpF(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Neg); - }); - } - - public static void Frecpe_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.FastFP && Optimizations.UseSse && sizeF == 0) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.ReciprocalScalar)); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipEstimate)); - }); - } - } - - public static void Frecpe_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.FastFP && Optimizations.UseSse && sizeF == 0) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Reciprocal)); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipEstimate)); - }); - } - } - - public static void Frecps_S(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSsv = new Type[] { typeof(float) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(2f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), typesMulSub)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (sizeF == 1) */ - { - Type[] typesSsv = new Type[] { typeof(double) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(2d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), typesMulSub)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipStepFused)); - }); - } - } - - public static void Frecps_V(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSav = new Type[] { typeof(float) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(2f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSav = new Type[] { typeof(double) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(2d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipStepFused)); - }); - } - } - - public static void Frecpx_S(ILEmitterCtx context) - { - EmitScalarUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecpX)); - }); - } - - public static void Frinta_S(ILEmitterCtx context) - { - EmitScalarUnaryOpF(context, () => - { - EmitRoundMathCall(context, MidpointRounding.AwayFromZero); - }); - } - - public static void Frinta_V(ILEmitterCtx context) - { - EmitVectorUnaryOpF(context, () => - { - EmitRoundMathCall(context, MidpointRounding.AwayFromZero); - }); - } - - public static void Frinti_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - if (Optimizations.UseSse41) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - context.EmitLdvec(op.Rn); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (op.Size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41ScalarRoundF)); - } - else /* if (op.Size == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41ScalarRound)); - } - - context.EmitStvec(op.Rd); - } - else - { - EmitScalarUnaryOpF(context, () => - { - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (op.Size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.RoundF)); - } - else /* if (op.Size == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Round)); - } - }); - } - } - - public static void Frinti_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.UseSse41) - { - context.EmitLdvec(op.Rn); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (sizeF == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41VectorRoundF)); - } - else /* if (sizeF == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41VectorRound)); - } - - context.EmitStvec(op.Rd); - - if (sizeF == 0 && op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorUnaryOpF(context, () => - { - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (sizeF == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.RoundF)); - } - else /* if (sizeF == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Round)); - } - }); - } - } - - public static void Frintm_S(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.TowardsMinusInfinity, scalar: true); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Floor)); - }); - } - } - - public static void Frintm_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.TowardsMinusInfinity, scalar: false); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Floor)); - }); - } - } - - public static void Frintn_S(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.ToNearest, scalar: true); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitRoundMathCall(context, MidpointRounding.ToEven); - }); - } - } - - public static void Frintn_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.ToNearest, scalar: false); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitRoundMathCall(context, MidpointRounding.ToEven); - }); - } - } - - public static void Frintp_S(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.TowardsPlusInfinity, scalar: true); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Ceiling)); - }); - } - } - - public static void Frintp_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.TowardsPlusInfinity, scalar: false); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Ceiling)); - }); - } - } - - public static void Frintx_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - if (Optimizations.UseSse41) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - context.EmitLdvec(op.Rn); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (op.Size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41ScalarRoundF)); - } - else /* if (op.Size == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41ScalarRound)); - } - - context.EmitStvec(op.Rd); - } - else - { - EmitScalarUnaryOpF(context, () => - { - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (op.Size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.RoundF)); - } - else /* if (op.Size == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Round)); - } - }); - } - } - - public static void Frintx_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.UseSse41) - { - context.EmitLdvec(op.Rn); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (sizeF == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41VectorRoundF)); - } - else /* if (sizeF == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41VectorRound)); - } - - context.EmitStvec(op.Rd); - - if (sizeF == 0 && op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorUnaryOpF(context, () => - { - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (sizeF == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.RoundF)); - } - else /* if (sizeF == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Round)); - } - }); - } - } - - public static void Frintz_S(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.TowardsZero, scalar: true); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Truncate)); - }); - } - } - - public static void Frintz_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.TowardsZero, scalar: false); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Truncate)); - }); - } - } - - public static void Frsqrte_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.FastFP && Optimizations.UseSse && sizeF == 0) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.ReciprocalSqrtScalar)); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtEstimate)); - }); - } - } - - public static void Frsqrte_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.FastFP && Optimizations.UseSse && sizeF == 0) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.ReciprocalSqrt)); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtEstimate)); - }); - } - } - - public static void Frsqrts_S(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSsv = new Type[] { typeof(float) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(0.5f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv)); - - context.EmitLdc_R4(3f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulSub)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (sizeF == 1) */ - { - Type[] typesSsv = new Type[] { typeof(double) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(0.5d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv)); - - context.EmitLdc_R8(3d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulSub)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtStepFused)); - }); - } - } - - public static void Frsqrts_V(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSav = new Type[] { typeof(float) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(0.5f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav)); - - context.EmitLdc_R4(3f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSav = new Type[] { typeof(double) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(0.5d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitLdc_R8(3d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulSub)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtStepFused)); - }); - } - } - - public static void Fsqrt_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.SqrtScalar)); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPSqrt)); - }); - } - } - - public static void Fsqrt_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Sqrt)); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPSqrt)); - }); - } - } - - public static void Fsub_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.SubtractScalar)); - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub)); - }); - } - } - - public static void Fsub_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Subtract)); - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub)); - }); - } - } - - public static void Mla_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Mul_AddSub(context, nameof(Sse2.Add)); - } - else - { - EmitVectorTernaryOpZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - } - - public static void Mla_Ve(ILEmitterCtx context) - { - EmitVectorTernaryOpByElemZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - - public static void Mls_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Mul_AddSub(context, nameof(Sse2.Subtract)); - } - else - { - EmitVectorTernaryOpZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - } - - public static void Mls_Ve(ILEmitterCtx context) - { - EmitVectorTernaryOpByElemZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - - public static void Mul_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Mul_AddSub(context); - } - else - { - EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.Mul)); - } - } - - public static void Mul_Ve(ILEmitterCtx context) - { - EmitVectorBinaryOpByElemZx(context, () => context.Emit(OpCodes.Mul)); - } - - public static void Neg_S(ILEmitterCtx context) - { - EmitScalarUnaryOpSx(context, () => context.Emit(OpCodes.Neg)); - } - - public static void Neg_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorUnaryOpSx(context, () => context.Emit(OpCodes.Neg)); - } - } - - public static void Raddhn_V(ILEmitterCtx context) - { - EmitHighNarrow(context, () => context.Emit(OpCodes.Add), round: true); - } - - public static void Rsubhn_V(ILEmitterCtx context) - { - EmitHighNarrow(context, () => context.Emit(OpCodes.Sub), round: true); - } - - public static void Saba_V(ILEmitterCtx context) - { - EmitVectorTernaryOpSx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - - context.Emit(OpCodes.Add); - }); - } - - public static void Sabal_V(ILEmitterCtx context) - { - EmitVectorWidenRnRmTernaryOpSx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - - context.Emit(OpCodes.Add); - }); - } - - public static void Sabd_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesCmpSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesAndOr = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThan), typesCmpSub)); - - context.EmitStvectmp(); // Cmp mask - context.EmitLdvectmp(); // Cmp mask - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndOr)); - - context.EmitLdvectmp(); // Cmp mask - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rn); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndOr)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesAndOr)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpSx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - }); - } - } - - public static void Sabdl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse41 && op.Size < 2) - { - Type[] typesCmpSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAndOr = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - - string nameCvt = op.Size == 0 - ? nameof(Sse41.ConvertToVector128Int16) - : nameof(Sse41.ConvertToVector128Int32); - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitStvectmp2(); // Long Rm - context.EmitStvectmp(); // Long Rn - - context.EmitLdvectmp(); // Long Rn - context.EmitLdvectmp2(); // Long Rm - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThan), typesCmpSub)); - - context.EmitStvectmp3(); // Cmp mask - context.EmitLdvectmp3(); // Cmp mask - - context.EmitLdvectmp(); // Long Rn - context.EmitLdvectmp2(); // Long Rm - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndOr)); - - context.EmitLdvectmp3(); // Cmp mask - - context.EmitLdvectmp2(); // Long Rm - context.EmitLdvectmp(); // Long Rn - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndOr)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesAndOr)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmBinaryOpSx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - }); - } - } - - public static void Sadalp_V(ILEmitterCtx context) - { - EmitAddLongPairwise(context, signed: true, accumulate: true); - } - - public static void Saddl_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesAdd = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmBinaryOpSx(context, () => context.Emit(OpCodes.Add)); - } - } - - public static void Saddlp_V(ILEmitterCtx context) - { - EmitAddLongPairwise(context, signed: true, accumulate: false); - } - - public static void Saddlv_V(ILEmitterCtx context) - { - EmitVectorLongAcrossVectorOpSx(context, () => context.Emit(OpCodes.Add)); - } - - public static void Saddw_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesAdd = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRmBinaryOpSx(context, () => context.Emit(OpCodes.Add)); - } - } - - public static void Shadd_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size > 0) - { - Type[] typesSra = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAndXorAdd = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndXorAdd)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesAndXorAdd)); - - context.Emit(OpCodes.Ldc_I4_1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), typesSra)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAndXorAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpSx(context, () => - { - context.Emit(OpCodes.Add); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr); - }); - } - } - - public static void Shsub_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size < 2) - { - Type[] typesSav = new Type[] { IntTypesPerSizeLog2[op.Size] }; - Type[] typesAddSub = new Type[] { VectorIntTypesPerSizeLog2 [op.Size], VectorIntTypesPerSizeLog2 [op.Size] }; - Type[] typesAvg = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdc_I4(op.Size == 0 ? sbyte.MinValue : short.MinValue); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitStvectmp(); - - context.EmitLdvec(op.Rn); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAddSub)); - - context.Emit(OpCodes.Dup); - - context.EmitLdvec(op.Rm); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAddSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), typesAvg)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesAddSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpSx(context, () => - { - context.Emit(OpCodes.Sub); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr); - }); - } - } - - public static void Smax_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesMax = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - Type typeSse = op.Size == 1 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.Max), typesMax)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - Type[] types = new Type[] { typeof(long), typeof(long) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Max), types); - - EmitVectorBinaryOpSx(context, () => context.EmitCall(mthdInfo)); - } - } - - public static void Smaxp_V(ILEmitterCtx context) - { - Type[] types = new Type[] { typeof(long), typeof(long) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Max), types); - - EmitVectorPairwiseOpSx(context, () => context.EmitCall(mthdInfo)); - } - - public static void Smaxv_V(ILEmitterCtx context) - { - Type[] types = new Type[] { typeof(long), typeof(long) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Max), types); - - EmitVectorAcrossVectorOpSx(context, () => context.EmitCall(mthdInfo)); - } - - public static void Smin_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesMin = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - Type typeSse = op.Size == 1 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.Min), typesMin)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - Type[] types = new Type[] { typeof(long), typeof(long) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Min), types); - - EmitVectorBinaryOpSx(context, () => context.EmitCall(mthdInfo)); - } - } - - public static void Sminp_V(ILEmitterCtx context) - { - Type[] types = new Type[] { typeof(long), typeof(long) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Min), types); - - EmitVectorPairwiseOpSx(context, () => context.EmitCall(mthdInfo)); - } - - public static void Sminv_V(ILEmitterCtx context) - { - Type[] types = new Type[] { typeof(long), typeof(long) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Min), types); - - EmitVectorAcrossVectorOpSx(context, () => context.EmitCall(mthdInfo)); - } - - public static void Smlal_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse41 && op.Size < 2) - { - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesMulAdd = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - string nameCvt = op.Size == 0 - ? nameof(Sse41.ConvertToVector128Int16) - : nameof(Sse41.ConvertToVector128Int32); - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.MultiplyLow), typesMulAdd)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesMulAdd)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmTernaryOpSx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - } - - public static void Smlal_Ve(ILEmitterCtx context) - { - EmitVectorWidenTernaryOpByElemSx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - - public static void Smlsl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse41 && op.Size < 2) - { - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesMulSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - string nameCvt = op.Size == 0 - ? nameof(Sse41.ConvertToVector128Int16) - : nameof(Sse41.ConvertToVector128Int32); - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.MultiplyLow), typesMulSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmTernaryOpSx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - } - - public static void Smlsl_Ve(ILEmitterCtx context) - { - EmitVectorWidenTernaryOpByElemSx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - - public static void Smull_V(ILEmitterCtx context) - { - EmitVectorWidenRnRmBinaryOpSx(context, () => context.Emit(OpCodes.Mul)); - } - - public static void Smull_Ve(ILEmitterCtx context) - { - EmitVectorWidenBinaryOpByElemSx(context, () => context.Emit(OpCodes.Mul)); - } - - public static void Sqabs_S(ILEmitterCtx context) - { - EmitScalarSaturatingUnaryOpSx(context, () => EmitAbs(context)); - } - - public static void Sqabs_V(ILEmitterCtx context) - { - EmitVectorSaturatingUnaryOpSx(context, () => EmitAbs(context)); - } - - public static void Sqadd_S(ILEmitterCtx context) - { - EmitScalarSaturatingBinaryOpSx(context, SaturatingFlags.Add); - } - - public static void Sqadd_V(ILEmitterCtx context) - { - EmitVectorSaturatingBinaryOpSx(context, SaturatingFlags.Add); - } - - public static void Sqdmulh_S(ILEmitterCtx context) - { - EmitSaturatingBinaryOp(context, () => EmitDoublingMultiplyHighHalf(context, round: false), SaturatingFlags.ScalarSx); - } - - public static void Sqdmulh_V(ILEmitterCtx context) - { - EmitSaturatingBinaryOp(context, () => EmitDoublingMultiplyHighHalf(context, round: false), SaturatingFlags.VectorSx); - } - - public static void Sqneg_S(ILEmitterCtx context) - { - EmitScalarSaturatingUnaryOpSx(context, () => context.Emit(OpCodes.Neg)); - } - - public static void Sqneg_V(ILEmitterCtx context) - { - EmitVectorSaturatingUnaryOpSx(context, () => context.Emit(OpCodes.Neg)); - } - - public static void Sqrdmulh_S(ILEmitterCtx context) - { - EmitSaturatingBinaryOp(context, () => EmitDoublingMultiplyHighHalf(context, round: true), SaturatingFlags.ScalarSx); - } - - public static void Sqrdmulh_V(ILEmitterCtx context) - { - EmitSaturatingBinaryOp(context, () => EmitDoublingMultiplyHighHalf(context, round: true), SaturatingFlags.VectorSx); - } - - public static void Sqsub_S(ILEmitterCtx context) - { - EmitScalarSaturatingBinaryOpSx(context, SaturatingFlags.Sub); - } - - public static void Sqsub_V(ILEmitterCtx context) - { - EmitVectorSaturatingBinaryOpSx(context, SaturatingFlags.Sub); - } - - public static void Sqxtn_S(ILEmitterCtx context) - { - EmitSaturatingNarrowOp(context, SaturatingNarrowFlags.ScalarSxSx); - } - - public static void Sqxtn_V(ILEmitterCtx context) - { - EmitSaturatingNarrowOp(context, SaturatingNarrowFlags.VectorSxSx); - } - - public static void Sqxtun_S(ILEmitterCtx context) - { - EmitSaturatingNarrowOp(context, SaturatingNarrowFlags.ScalarSxZx); - } - - public static void Sqxtun_V(ILEmitterCtx context) - { - EmitSaturatingNarrowOp(context, SaturatingNarrowFlags.VectorSxZx); - } - - public static void Srhadd_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size < 2) - { - Type[] typesSav = new Type[] { IntTypesPerSizeLog2[op.Size] }; - Type[] typesSubAdd = new Type[] { VectorIntTypesPerSizeLog2 [op.Size], VectorIntTypesPerSizeLog2 [op.Size] }; - Type[] typesAvg = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdc_I4(op.Size == 0 ? sbyte.MinValue : short.MinValue); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitStvectmp(); - context.EmitLdvectmp(); - - context.EmitLdvec(op.Rn); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSubAdd)); - - context.EmitLdvec(op.Rm); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSubAdd)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), typesAvg)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesSubAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpSx(context, () => - { - context.Emit(OpCodes.Add); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Add); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr); - }); - } - } - - public static void Ssubl_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSub)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmBinaryOpSx(context, () => context.Emit(OpCodes.Sub)); - } - } - - public static void Ssubw_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSub)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRmBinaryOpSx(context, () => context.Emit(OpCodes.Sub)); - } - } - - public static void Sub_S(ILEmitterCtx context) - { - EmitScalarBinaryOpZx(context, () => context.Emit(OpCodes.Sub)); - } - - public static void Sub_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - EmitSse2Op(context, nameof(Sse2.Subtract)); - } - else - { - EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.Sub)); - } - } - - public static void Subhn_V(ILEmitterCtx context) - { - EmitHighNarrow(context, () => context.Emit(OpCodes.Sub), round: false); - } - - public static void Suqadd_S(ILEmitterCtx context) - { - EmitScalarSaturatingBinaryOpSx(context, SaturatingFlags.Accumulate); - } - - public static void Suqadd_V(ILEmitterCtx context) - { - EmitVectorSaturatingBinaryOpSx(context, SaturatingFlags.Accumulate); - } - - public static void Uaba_V(ILEmitterCtx context) - { - EmitVectorTernaryOpZx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - - context.Emit(OpCodes.Add); - }); - } - - public static void Uabal_V(ILEmitterCtx context) - { - EmitVectorWidenRnRmTernaryOpZx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - - context.Emit(OpCodes.Add); - }); - } - - public static void Uabd_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesMax = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesCmpSub = new Type[] { VectorIntTypesPerSizeLog2 [op.Size], VectorIntTypesPerSizeLog2 [op.Size] }; - Type[] typesAndOr = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - Type[] typesSav = new Type[] { typeof(long) }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.Max), typesMax)); - - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqual), typesCmpSub)); - - context.EmitLdc_I8(-1L); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndOr)); - - context.EmitStvectmp(); // Cmp mask - context.EmitLdvectmp(); // Cmp mask - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndOr)); - - context.EmitLdvectmp(); // Cmp mask - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rn); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndOr)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesAndOr)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpZx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - }); - } - } - - public static void Uabdl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse41 && op.Size < 2) - { - Type[] typesMax = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], - VectorUIntTypesPerSizeLog2[op.Size + 1] }; - Type[] typesCmpSub = new Type[] { VectorIntTypesPerSizeLog2 [op.Size + 1], - VectorIntTypesPerSizeLog2 [op.Size + 1] }; - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAndOr = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesSav = new Type[] { typeof(long) }; - - string nameCvt = op.Size == 0 - ? nameof(Sse41.ConvertToVector128Int16) - : nameof(Sse41.ConvertToVector128Int32); - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitStvectmp2(); // Long Rm - context.EmitStvectmp(); // Long Rn - - context.EmitLdvectmp2(); // Long Rm - context.EmitLdvectmp(); // Long Rn - - context.EmitCall(typeof(Sse41).GetMethod(nameof(Sse41.Max), typesMax)); - - context.EmitLdvectmp2(); // Long Rm - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqual), typesCmpSub)); - - context.EmitLdc_I8(-1L); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndOr)); - - context.EmitStvectmp3(); // Cmp mask - context.EmitLdvectmp3(); // Cmp mask - - context.EmitLdvectmp(); // Long Rn - context.EmitLdvectmp2(); // Long Rm - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndOr)); - - context.EmitLdvectmp3(); // Cmp mask - - context.EmitLdvectmp2(); // Long Rm - context.EmitLdvectmp(); // Long Rn - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndOr)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesAndOr)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmBinaryOpZx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - }); - } - } - - public static void Uadalp_V(ILEmitterCtx context) - { - EmitAddLongPairwise(context, signed: false, accumulate: true); - } - - public static void Uaddl_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], - VectorUIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmBinaryOpZx(context, () => context.Emit(OpCodes.Add)); - } - } - - public static void Uaddlp_V(ILEmitterCtx context) - { - EmitAddLongPairwise(context, signed: false, accumulate: false); - } - - public static void Uaddlv_V(ILEmitterCtx context) - { - EmitVectorLongAcrossVectorOpZx(context, () => context.Emit(OpCodes.Add)); - } - - public static void Uaddw_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], - VectorUIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRmBinaryOpZx(context, () => context.Emit(OpCodes.Add)); - } - } - - public static void Uhadd_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size > 0) - { - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAndXorAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndXorAdd)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesAndXorAdd)); - - context.Emit(OpCodes.Ldc_I4_1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrl)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAndXorAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpZx(context, () => - { - context.Emit(OpCodes.Add); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr_Un); - }); - } - } - - public static void Uhsub_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size < 2) - { - Type[] typesAvgSub = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), typesAvgSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesAvgSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpZx(context, () => - { - context.Emit(OpCodes.Sub); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr_Un); - }); - } - } - - public static void Umax_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesMax = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.Max), typesMax)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - Type[] types = new Type[] { typeof(ulong), typeof(ulong) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Max), types); - - EmitVectorBinaryOpZx(context, () => context.EmitCall(mthdInfo)); - } - } - - public static void Umaxp_V(ILEmitterCtx context) - { - Type[] types = new Type[] { typeof(ulong), typeof(ulong) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Max), types); - - EmitVectorPairwiseOpZx(context, () => context.EmitCall(mthdInfo)); - } - - public static void Umaxv_V(ILEmitterCtx context) - { - Type[] types = new Type[] { typeof(ulong), typeof(ulong) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Max), types); - - EmitVectorAcrossVectorOpZx(context, () => context.EmitCall(mthdInfo)); - } - - public static void Umin_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesMin = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.Min), typesMin)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - Type[] types = new Type[] { typeof(ulong), typeof(ulong) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Min), types); - - EmitVectorBinaryOpZx(context, () => context.EmitCall(mthdInfo)); - } - } - - public static void Uminp_V(ILEmitterCtx context) - { - Type[] types = new Type[] { typeof(ulong), typeof(ulong) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Min), types); - - EmitVectorPairwiseOpZx(context, () => context.EmitCall(mthdInfo)); - } - - public static void Uminv_V(ILEmitterCtx context) - { - Type[] types = new Type[] { typeof(ulong), typeof(ulong) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Min), types); - - EmitVectorAcrossVectorOpZx(context, () => context.EmitCall(mthdInfo)); - } - - public static void Umlal_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse41 && op.Size < 2) - { - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesMulAdd = new Type[] { VectorIntTypesPerSizeLog2 [op.Size + 1], - VectorIntTypesPerSizeLog2 [op.Size + 1] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - string nameCvt = op.Size == 0 - ? nameof(Sse41.ConvertToVector128Int16) - : nameof(Sse41.ConvertToVector128Int32); - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.MultiplyLow), typesMulAdd)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesMulAdd)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmTernaryOpZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - } - - public static void Umlal_Ve(ILEmitterCtx context) - { - EmitVectorWidenTernaryOpByElemZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - - public static void Umlsl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse41 && op.Size < 2) - { - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesMulSub = new Type[] { VectorIntTypesPerSizeLog2 [op.Size + 1], - VectorIntTypesPerSizeLog2 [op.Size + 1] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - string nameCvt = op.Size == 0 - ? nameof(Sse41.ConvertToVector128Int16) - : nameof(Sse41.ConvertToVector128Int32); - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.MultiplyLow), typesMulSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmTernaryOpZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - } - - public static void Umlsl_Ve(ILEmitterCtx context) - { - EmitVectorWidenTernaryOpByElemZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - - public static void Umull_V(ILEmitterCtx context) - { - EmitVectorWidenRnRmBinaryOpZx(context, () => context.Emit(OpCodes.Mul)); - } - - public static void Umull_Ve(ILEmitterCtx context) - { - EmitVectorWidenBinaryOpByElemZx(context, () => context.Emit(OpCodes.Mul)); - } - - public static void Uqadd_S(ILEmitterCtx context) - { - EmitScalarSaturatingBinaryOpZx(context, SaturatingFlags.Add); - } - - public static void Uqadd_V(ILEmitterCtx context) - { - EmitVectorSaturatingBinaryOpZx(context, SaturatingFlags.Add); - } - - public static void Uqsub_S(ILEmitterCtx context) - { - EmitScalarSaturatingBinaryOpZx(context, SaturatingFlags.Sub); - } - - public static void Uqsub_V(ILEmitterCtx context) - { - EmitVectorSaturatingBinaryOpZx(context, SaturatingFlags.Sub); - } - - public static void Uqxtn_S(ILEmitterCtx context) - { - EmitSaturatingNarrowOp(context, SaturatingNarrowFlags.ScalarZxZx); - } - - public static void Uqxtn_V(ILEmitterCtx context) - { - EmitSaturatingNarrowOp(context, SaturatingNarrowFlags.VectorZxZx); - } - - public static void Urhadd_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size < 2) - { - Type[] typesAvg = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), typesAvg)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpZx(context, () => - { - context.Emit(OpCodes.Add); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Add); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr_Un); - }); - } - } - - public static void Usqadd_S(ILEmitterCtx context) - { - EmitScalarSaturatingBinaryOpZx(context, SaturatingFlags.Accumulate); - } - - public static void Usqadd_V(ILEmitterCtx context) - { - EmitVectorSaturatingBinaryOpZx(context, SaturatingFlags.Accumulate); - } - - public static void Usubl_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesSub = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], - VectorUIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSub)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmBinaryOpZx(context, () => context.Emit(OpCodes.Sub)); - } - } - - public static void Usubw_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesSub = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], - VectorUIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSub)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRmBinaryOpZx(context, () => context.Emit(OpCodes.Sub)); - } - } - - private static void EmitAbs(ILEmitterCtx context) - { - ILLabel lblTrue = new ILLabel(); - - context.Emit(OpCodes.Dup); - context.Emit(OpCodes.Ldc_I4_0); - context.Emit(OpCodes.Bge_S, lblTrue); - - context.Emit(OpCodes.Neg); - - context.MarkLabel(lblTrue); - } - - private static void EmitAddLongPairwise(ILEmitterCtx context, bool signed, bool accumulate) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int words = op.GetBitsCount() >> 4; - int pairs = words >> op.Size; - - for (int index = 0; index < pairs; index++) - { - int idx = index << 1; - - EmitVectorExtract(context, op.Rn, idx, op.Size, signed); - EmitVectorExtract(context, op.Rn, idx + 1, op.Size, signed); - - context.Emit(OpCodes.Add); - - if (accumulate) - { - EmitVectorExtract(context, op.Rd, index, op.Size + 1, signed); - - context.Emit(OpCodes.Add); - } - - EmitVectorInsertTmp(context, index, op.Size + 1); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static void EmitDoublingMultiplyHighHalf(ILEmitterCtx context, bool round) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int eSize = 8 << op.Size; - - context.Emit(OpCodes.Mul); - - if (!round) - { - context.EmitAsr(eSize - 1); - } - else - { - long roundConst = 1L << (eSize - 1); - - ILLabel lblTrue = new ILLabel(); - - context.EmitLsl(1); - - context.EmitLdc_I8(roundConst); - - context.Emit(OpCodes.Add); - - context.EmitAsr(eSize); - - context.Emit(OpCodes.Dup); - context.EmitLdc_I8((long)int.MinValue); - context.Emit(OpCodes.Bne_Un_S, lblTrue); - - context.Emit(OpCodes.Neg); - - context.MarkLabel(lblTrue); - } - } - - private static void EmitHighNarrow(ILEmitterCtx context, Action emit, bool round) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int elems = 8 >> op.Size; - - int eSize = 8 << op.Size; - - int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; - - long roundConst = 1L << (eSize - 1); - - if (part != 0) - { - context.EmitLdvec(op.Rd); - context.EmitStvectmp(); - } - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size + 1); - EmitVectorExtractZx(context, op.Rm, index, op.Size + 1); - - emit(); - - if (round) - { - context.EmitLdc_I8(roundConst); - - context.Emit(OpCodes.Add); - } - - context.EmitLsr(eSize); - - EmitVectorInsertTmp(context, part + index, op.Size); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (part == 0) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static void EmitSse41Frint(ILEmitterCtx context, RoundMode roundMode, bool scalar) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - if (scalar) - { - Type[] typesRnd = op.Size == 0 - ? new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) } - : new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse41).GetMethod(GetScalarSse41NameRnd(roundMode), typesRnd)); - - context.EmitStvec(op.Rd); - } - else - { - int sizeF = op.Size & 1; - - Type[] typesRnd = sizeF == 0 - ? new Type[] { typeof(Vector128<float>) } - : new Type[] { typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse41).GetMethod(GetVectorSse41NameRnd(roundMode), typesRnd)); - - context.EmitStvec(op.Rd); - - if (sizeF == 0 && op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } - - private static void EmitSse41Mul_AddSub(ILEmitterCtx context, string nameAddSub = null) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (nameAddSub != null) - { - context.EmitLdvec(op.Rd); - } - - if (op.Size == 0) - { - Type[] typesBle = new Type[] { typeof(Vector128<sbyte>), typeof(Vector128<sbyte>), typeof(Vector128<sbyte>) }; - Type[] typesMul = new Type[] { typeof(Vector128<short>), typeof(Vector128<short>) }; - Type[] typesShs = new Type[] { typeof(Vector128<short>), typeof(byte) }; - Type[] typesSav = new Type[] { typeof(int) }; - - context.EmitLdvec(op.Rn); - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesShs)); - - context.EmitLdvec(op.Rm); - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesShs)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyLow), typesMul)); - - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesShs)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyLow), typesMul)); - - context.EmitLdc_I4(0x00FF00FF); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse41).GetMethod(nameof(Sse41.BlendVariable), typesBle)); - } - else if (op.Size == 1) - { - Type[] typesMul = new Type[] { typeof(Vector128<short>), typeof(Vector128<short>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyLow), typesMul)); - } - else /* if (op.Size == 2) */ - { - Type[] typesMul = new Type[] { typeof(Vector128<int>), typeof(Vector128<int>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse41).GetMethod(nameof(Sse41.MultiplyLow), typesMul)); - } - - if (nameAddSub != null) - { - Type[] typesAddSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - context.EmitCall(typeof(Sse2).GetMethod(nameAddSub, typesAddSub)); - } - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitSimdCmp.cs b/ChocolArm64/Instructions/InstEmitSimdCmp.cs deleted file mode 100644 index b2925006..00000000 --- a/ChocolArm64/Instructions/InstEmitSimdCmp.cs +++ /dev/null @@ -1,862 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -using static ChocolArm64.Instructions.InstEmitAluHelper; -using static ChocolArm64.Instructions.InstEmitSimdHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Cmeq_S(ILEmitterCtx context) - { - EmitCmpOp(context, OpCodes.Beq_S, scalar: true); - } - - public static void Cmeq_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesCmp = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - Type typeSse = op.Size != 3 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rn); - - if (op is OpCodeSimdReg64 binOp) - { - context.EmitLdvec(binOp.Rm); - } - else - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - } - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.CompareEqual), typesCmp)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitCmpOp(context, OpCodes.Beq_S, scalar: false); - } - } - - public static void Cmge_S(ILEmitterCtx context) - { - EmitCmpOp(context, OpCodes.Bge_S, scalar: true); - } - - public static void Cmge_V(ILEmitterCtx context) - { - if (Optimizations.UseSse42) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesCmp = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesAnt = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - Type[] typesSav = new Type[] { typeof(long) }; - - Type typeSse = op.Size != 3 ? typeof(Sse2) : typeof(Sse42); - - if (op is OpCodeSimdReg64 binOp) - { - context.EmitLdvec(binOp.Rm); - } - else - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - } - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.CompareGreaterThan), typesCmp)); - - context.EmitLdc_I8(-1L); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitCmpOp(context, OpCodes.Bge_S, scalar: false); - } - } - - public static void Cmgt_S(ILEmitterCtx context) - { - EmitCmpOp(context, OpCodes.Bgt_S, scalar: true); - } - - public static void Cmgt_V(ILEmitterCtx context) - { - if (Optimizations.UseSse42) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesCmp = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - Type typeSse = op.Size != 3 ? typeof(Sse2) : typeof(Sse42); - - context.EmitLdvec(op.Rn); - - if (op is OpCodeSimdReg64 binOp) - { - context.EmitLdvec(binOp.Rm); - } - else - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - } - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.CompareGreaterThan), typesCmp)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitCmpOp(context, OpCodes.Bgt_S, scalar: false); - } - } - - public static void Cmhi_S(ILEmitterCtx context) - { - EmitCmpOp(context, OpCodes.Bgt_Un_S, scalar: true); - } - - public static void Cmhi_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse41 && op.Size < 3) - { - Type[] typesMax = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesCmp = new Type[] { VectorIntTypesPerSizeLog2 [op.Size], VectorIntTypesPerSizeLog2 [op.Size] }; - Type[] typesAnt = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - Type[] typesSav = new Type[] { typeof(long) }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.Max), typesMax)); - - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqual), typesCmp)); - - context.EmitLdc_I8(-1L); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitCmpOp(context, OpCodes.Bgt_Un_S, scalar: false); - } - } - - public static void Cmhs_S(ILEmitterCtx context) - { - EmitCmpOp(context, OpCodes.Bge_Un_S, scalar: true); - } - - public static void Cmhs_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse41 && op.Size < 3) - { - Type[] typesMax = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesCmp = new Type[] { VectorIntTypesPerSizeLog2 [op.Size], VectorIntTypesPerSizeLog2 [op.Size] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.Max), typesMax)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqual), typesCmp)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitCmpOp(context, OpCodes.Bge_Un_S, scalar: false); - } - } - - public static void Cmle_S(ILEmitterCtx context) - { - EmitCmpOp(context, OpCodes.Ble_S, scalar: true); - } - - public static void Cmle_V(ILEmitterCtx context) - { - if (Optimizations.UseSse42) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesCmp = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesAnt = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - Type[] typesSav = new Type[] { typeof(long) }; - - Type typeSse = op.Size != 3 ? typeof(Sse2) : typeof(Sse42); - - context.EmitLdvec(op.Rn); - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.CompareGreaterThan), typesCmp)); - - context.EmitLdc_I8(-1L); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitCmpOp(context, OpCodes.Ble_S, scalar: false); - } - } - - public static void Cmlt_S(ILEmitterCtx context) - { - EmitCmpOp(context, OpCodes.Blt_S, scalar: true); - } - - public static void Cmlt_V(ILEmitterCtx context) - { - if (Optimizations.UseSse42) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesCmp = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - Type typeSse = op.Size != 3 ? typeof(Sse2) : typeof(Sse42); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.CompareGreaterThan), typesCmp)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitCmpOp(context, OpCodes.Blt_S, scalar: false); - } - } - - public static void Cmtst_S(ILEmitterCtx context) - { - EmitCmtstOp(context, scalar: true); - } - - public static void Cmtst_V(ILEmitterCtx context) - { - EmitCmtstOp(context, scalar: false); - } - - public static void Fccmp_S(ILEmitterCtx context) - { - OpCodeSimdFcond64 op = (OpCodeSimdFcond64)context.CurrOp; - - ILLabel lblTrue = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.EmitCondBranch(lblTrue, op.Cond); - - context.EmitLdc_I4(op.Nzcv); - EmitSetNzcv(context); - - context.Emit(OpCodes.Br, lblEnd); - - context.MarkLabel(lblTrue); - - EmitFcmpOrFcmpe(context, signalNaNs: false); - - context.MarkLabel(lblEnd); - } - - public static void Fccmpe_S(ILEmitterCtx context) - { - OpCodeSimdFcond64 op = (OpCodeSimdFcond64)context.CurrOp; - - ILLabel lblTrue = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.EmitCondBranch(lblTrue, op.Cond); - - context.EmitLdc_I4(op.Nzcv); - EmitSetNzcv(context); - - context.Emit(OpCodes.Br, lblEnd); - - context.MarkLabel(lblTrue); - - EmitFcmpOrFcmpe(context, signalNaNs: true); - - context.MarkLabel(lblEnd); - } - - public static void Fcmeq_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitCmpSseOrSse2OpF(context, nameof(Sse.CompareEqualScalar), scalar: true); - } - else - { - EmitCmpOpF(context, nameof(SoftFloat32.FPCompareEQ), scalar: true); - } - } - - public static void Fcmeq_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitCmpSseOrSse2OpF(context, nameof(Sse.CompareEqual), scalar: false); - } - else - { - EmitCmpOpF(context, nameof(SoftFloat32.FPCompareEQ), scalar: false); - } - } - - public static void Fcmge_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitCmpSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanOrEqualScalar), scalar: true); - } - else - { - EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: true); - } - } - - public static void Fcmge_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitCmpSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanOrEqual), scalar: false); - } - else - { - EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: false); - } - } - - public static void Fcmgt_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitCmpSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanScalar), scalar: true); - } - else - { - EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: true); - } - } - - public static void Fcmgt_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitCmpSseOrSse2OpF(context, nameof(Sse.CompareGreaterThan), scalar: false); - } - else - { - EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: false); - } - } - - public static void Fcmle_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitCmpSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanOrEqualScalar), scalar: true, isLeOrLt: true); - } - else - { - EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLE), scalar: true); - } - } - - public static void Fcmle_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitCmpSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanOrEqual), scalar: false, isLeOrLt: true); - } - else - { - EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLE), scalar: false); - } - } - - public static void Fcmlt_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitCmpSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanScalar), scalar: true, isLeOrLt: true); - } - else - { - EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLT), scalar: true); - } - } - - public static void Fcmlt_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitCmpSseOrSse2OpF(context, nameof(Sse.CompareGreaterThan), scalar: false, isLeOrLt: true); - } - else - { - EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLT), scalar: false); - } - } - - public static void Fcmp_S(ILEmitterCtx context) - { - EmitFcmpOrFcmpe(context, signalNaNs: false); - } - - public static void Fcmpe_S(ILEmitterCtx context) - { - EmitFcmpOrFcmpe(context, signalNaNs: true); - } - - private static void EmitFcmpOrFcmpe(ILEmitterCtx context, bool signalNaNs) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - bool cmpWithZero = !(op is OpCodeSimdFcond64) ? op.Bit3 : false; - - if (Optimizations.FastFP && Optimizations.UseSse2) - { - if (op.Size == 0) - { - Type[] typesCmp = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - ILLabel lblNaN = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.EmitLdvec(op.Rn); - - if (cmpWithZero) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - } - else - { - context.EmitLdvec(op.Rm); - } - - context.EmitStvectmp(); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareOrderedScalar), typesCmp)); - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareEqualOrderedScalar), typesCmp)); - - context.Emit(OpCodes.Brtrue_S, lblNaN); - - context.Emit(OpCodes.Ldc_I4_0); - - context.EmitLdvec(op.Rn); - context.EmitLdvectmp(); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqualOrderedScalar), typesCmp)); - - context.EmitLdvec(op.Rn); - context.EmitLdvectmp(); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareEqualOrderedScalar), typesCmp)); - - context.EmitLdvec(op.Rn); - context.EmitLdvectmp(); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrderedScalar), typesCmp)); - - context.EmitStflg((int)PState.NBit); - context.EmitStflg((int)PState.ZBit); - context.EmitStflg((int)PState.CBit); - context.EmitStflg((int)PState.VBit); - - context.Emit(OpCodes.Br_S, lblEnd); - - context.MarkLabel(lblNaN); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Ldc_I4_0); - context.Emit(OpCodes.Ldc_I4_0); - - context.EmitStflg((int)PState.NBit); - context.EmitStflg((int)PState.ZBit); - context.EmitStflg((int)PState.CBit); - context.EmitStflg((int)PState.VBit); - - context.MarkLabel(lblEnd); - } - else /* if (op.Size == 1) */ - { - Type[] typesCmp = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - ILLabel lblNaN = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.EmitLdvec(op.Rn); - - if (cmpWithZero) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - } - else - { - context.EmitLdvec(op.Rm); - } - - context.EmitStvectmp(); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareOrderedScalar), typesCmp)); - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualOrderedScalar), typesCmp)); - - context.Emit(OpCodes.Brtrue_S, lblNaN); - - context.Emit(OpCodes.Ldc_I4_0); - - context.EmitLdvec(op.Rn); - context.EmitLdvectmp(); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqualOrderedScalar), typesCmp)); - - context.EmitLdvec(op.Rn); - context.EmitLdvectmp(); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualOrderedScalar), typesCmp)); - - context.EmitLdvec(op.Rn); - context.EmitLdvectmp(); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrderedScalar), typesCmp)); - - context.EmitStflg((int)PState.NBit); - context.EmitStflg((int)PState.ZBit); - context.EmitStflg((int)PState.CBit); - context.EmitStflg((int)PState.VBit); - - context.Emit(OpCodes.Br_S, lblEnd); - - context.MarkLabel(lblNaN); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Ldc_I4_0); - context.Emit(OpCodes.Ldc_I4_0); - - context.EmitStflg((int)PState.NBit); - context.EmitStflg((int)PState.ZBit); - context.EmitStflg((int)PState.CBit); - context.EmitStflg((int)PState.VBit); - - context.MarkLabel(lblEnd); - } - } - else - { - EmitVectorExtractF(context, op.Rn, 0, op.Size); - - if (cmpWithZero) - { - if (op.Size == 0) - { - context.EmitLdc_R4(0f); - } - else /* if (op.Size == 1) */ - { - context.EmitLdc_R8(0d); - } - } - else - { - EmitVectorExtractF(context, op.Rm, 0, op.Size); - } - - context.EmitLdc_I4(!signalNaNs ? 0 : 1); - - EmitSoftFloatCall(context, nameof(SoftFloat32.FPCompare)); - - EmitSetNzcv(context); - } - } - - private static void EmitCmpOp(ILEmitterCtx context, OpCode ilOp, bool scalar) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = !scalar ? bytes >> op.Size : 1; - - ulong szMask = ulong.MaxValue >> (64 - (8 << op.Size)); - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractSx(context, op.Rn, index, op.Size); - - if (op is OpCodeSimdReg64 binOp) - { - EmitVectorExtractSx(context, binOp.Rm, index, op.Size); - } - else - { - context.EmitLdc_I8(0L); - } - - ILLabel lblTrue = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.Emit(ilOp, lblTrue); - - EmitVectorInsert(context, op.Rd, index, op.Size, 0); - - context.Emit(OpCodes.Br_S, lblEnd); - - context.MarkLabel(lblTrue); - - EmitVectorInsert(context, op.Rd, index, op.Size, (long)szMask); - - context.MarkLabel(lblEnd); - } - - if ((op.RegisterSize == RegisterSize.Simd64) || scalar) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static void EmitCmtstOp(ILEmitterCtx context, bool scalar) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = !scalar ? bytes >> op.Size : 1; - - ulong szMask = ulong.MaxValue >> (64 - (8 << op.Size)); - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size); - EmitVectorExtractZx(context, op.Rm, index, op.Size); - - ILLabel lblTrue = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.Emit(OpCodes.And); - - context.EmitLdc_I8(0L); - - context.Emit(OpCodes.Bne_Un_S, lblTrue); - - EmitVectorInsert(context, op.Rd, index, op.Size, 0); - - context.Emit(OpCodes.Br_S, lblEnd); - - context.MarkLabel(lblTrue); - - EmitVectorInsert(context, op.Rd, index, op.Size, (long)szMask); - - context.MarkLabel(lblEnd); - } - - if ((op.RegisterSize == RegisterSize.Simd64) || scalar) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static void EmitCmpOpF(ILEmitterCtx context, string name, bool scalar) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - int bytes = op.GetBitsCount() >> 3; - int elems = !scalar ? bytes >> sizeF + 2 : 1; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractF(context, op.Rn, index, sizeF); - - if (op is OpCodeSimdReg64 binOp) - { - EmitVectorExtractF(context, binOp.Rm, index, sizeF); - } - else - { - if (sizeF == 0) - { - context.EmitLdc_R4(0f); - } - else /* if (sizeF == 1) */ - { - context.EmitLdc_R8(0d); - } - } - - EmitSoftFloatCall(context, name); - - EmitVectorInsertF(context, op.Rd, index, sizeF); - } - - if (!scalar) - { - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - if (sizeF == 0) - { - EmitVectorZero32_128(context, op.Rd); - } - else /* if (sizeF == 1) */ - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } - - private static void EmitCmpSseOrSse2OpF(ILEmitterCtx context, string name, bool scalar, bool isLeOrLt = false) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - if (!isLeOrLt) - { - context.EmitLdvec(op.Rn); - } - - if (op is OpCodeSimdReg64 binOp) - { - context.EmitLdvec(binOp.Rm); - } - else - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - } - - if (isLeOrLt) - { - context.EmitLdvec(op.Rn); - } - - context.EmitCall(typeof(Sse).GetMethod(name, types)); - - context.EmitStvec(op.Rd); - - if (scalar) - { - EmitVectorZero32_128(context, op.Rd); - } - else if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] types = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - if (!isLeOrLt) - { - context.EmitLdvec(op.Rn); - } - - if (op is OpCodeSimdReg64 binOp) - { - context.EmitLdvec(binOp.Rm); - } - else - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - } - - if (isLeOrLt) - { - context.EmitLdvec(op.Rn); - } - - context.EmitCall(typeof(Sse2).GetMethod(name, types)); - - context.EmitStvec(op.Rd); - - if (scalar) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitSimdCrypto.cs b/ChocolArm64/Instructions/InstEmitSimdCrypto.cs deleted file mode 100644 index 33c81aab..00000000 --- a/ChocolArm64/Instructions/InstEmitSimdCrypto.cs +++ /dev/null @@ -1,54 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.Translation; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Aesd_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - SoftFallback.EmitCall(context, nameof(SoftFallback.Decrypt)); - - context.EmitStvec(op.Rd); - } - - public static void Aese_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - SoftFallback.EmitCall(context, nameof(SoftFallback.Encrypt)); - - context.EmitStvec(op.Rd); - } - - public static void Aesimc_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - context.EmitLdvec(op.Rn); - - SoftFallback.EmitCall(context, nameof(SoftFallback.InverseMixColumns)); - - context.EmitStvec(op.Rd); - } - - public static void Aesmc_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - context.EmitLdvec(op.Rn); - - SoftFallback.EmitCall(context, nameof(SoftFallback.MixColumns)); - - context.EmitStvec(op.Rd); - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitSimdCvt.cs b/ChocolArm64/Instructions/InstEmitSimdCvt.cs deleted file mode 100644 index 2b3deb98..00000000 --- a/ChocolArm64/Instructions/InstEmitSimdCvt.cs +++ /dev/null @@ -1,1382 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -using static ChocolArm64.Instructions.InstEmitSimdHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Fcvt_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - if (op.Size == 0 && op.Opc == 1) // Single -> Double. - { - if (Optimizations.UseSse2) - { - Type[] typesCvt = new Type[] { typeof(Vector128<double>), typeof(Vector128<float>) }; - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Double), typesCvt)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorExtractF(context, op.Rn, 0, 0); - - EmitFloatCast(context, 1); - - EmitScalarSetF(context, op.Rd, 1); - } - } - else if (op.Size == 1 && op.Opc == 0) // Double -> Single. - { - if (Optimizations.UseSse2) - { - Type[] typesCvt = new Type[] { typeof(Vector128<float>), typeof(Vector128<double>) }; - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Single), typesCvt)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorExtractF(context, op.Rn, 0, 1); - - EmitFloatCast(context, 0); - - EmitScalarSetF(context, op.Rd, 0); - } - } - else if (op.Size == 0 && op.Opc == 3) // Single -> Half. - { - EmitVectorExtractF(context, op.Rn, 0, 0); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitCall(typeof(SoftFloat32_16), nameof(SoftFloat32_16.FPConvert)); - - context.Emit(OpCodes.Conv_U8); - EmitScalarSet(context, op.Rd, 1); - } - else if (op.Size == 3 && op.Opc == 0) // Half -> Single. - { - EmitVectorExtractZx(context, op.Rn, 0, 1); - context.Emit(OpCodes.Conv_U2); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitCall(typeof(SoftFloat16_32), nameof(SoftFloat16_32.FPConvert)); - - EmitScalarSetF(context, op.Rd, 0); - } - else if (op.Size == 1 && op.Opc == 3) // Double -> Half. - { - throw new NotImplementedException("Double-precision to half-precision."); - } - else if (op.Size == 3 && op.Opc == 1) // Double -> Half. - { - throw new NotImplementedException("Half-precision to double-precision."); - } - else // Invalid encoding. - { - throw new InvalidOperationException($"type == {op.Size} && opc == {op.Opc}"); - } - } - - public static void Fcvtas_Gp(ILEmitterCtx context) - { - EmitFcvt_s_Gp(context, () => EmitRoundMathCall(context, MidpointRounding.AwayFromZero)); - } - - public static void Fcvtau_Gp(ILEmitterCtx context) - { - EmitFcvt_u_Gp(context, () => EmitRoundMathCall(context, MidpointRounding.AwayFromZero)); - } - - public static void Fcvtl_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.UseSse2 && sizeF == 1) - { - Type[] typesCvt = new Type[] { typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveHighToLow))); - } - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Double), typesCvt)); - - context.EmitStvec(op.Rd); - } - else - { - int elems = 4 >> sizeF; - - int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; - - for (int index = 0; index < elems; index++) - { - if (sizeF == 0) - { - EmitVectorExtractZx(context, op.Rn, part + index, 1); - context.Emit(OpCodes.Conv_U2); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitCall(typeof(SoftFloat16_32), nameof(SoftFloat16_32.FPConvert)); - } - else /* if (sizeF == 1) */ - { - EmitVectorExtractF(context, op.Rn, part + index, 0); - - context.Emit(OpCodes.Conv_R8); - } - - EmitVectorInsertTmpF(context, index, sizeF); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - } - } - - public static void Fcvtms_Gp(ILEmitterCtx context) - { - EmitFcvt_s_Gp(context, () => EmitUnaryMathCall(context, nameof(Math.Floor))); - } - - public static void Fcvtmu_Gp(ILEmitterCtx context) - { - EmitFcvt_u_Gp(context, () => EmitUnaryMathCall(context, nameof(Math.Floor))); - } - - public static void Fcvtn_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.UseSse2 && sizeF == 1) - { - Type[] typesCvt = new Type[] { typeof(Vector128<double>) }; - - string nameMov = op.RegisterSize == RegisterSize.Simd128 - ? nameof(Sse.MoveLowToHigh) - : nameof(Sse.MoveHighToLow); - - context.EmitLdvec(op.Rd); - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh))); - - context.EmitLdvec(op.Rn); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Single), typesCvt)); - context.Emit(OpCodes.Dup); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh))); - - context.EmitCall(typeof(Sse).GetMethod(nameMov)); - - context.EmitStvec(op.Rd); - } - else - { - int elems = 4 >> sizeF; - - int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; - - if (part != 0) - { - context.EmitLdvec(op.Rd); - context.EmitStvectmp(); - } - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractF(context, op.Rn, index, sizeF); - - if (sizeF == 0) - { - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitCall(typeof(SoftFloat32_16), nameof(SoftFloat32_16.FPConvert)); - - context.Emit(OpCodes.Conv_U8); - EmitVectorInsertTmp(context, part + index, 1); - } - else /* if (sizeF == 1) */ - { - context.Emit(OpCodes.Conv_R4); - - EmitVectorInsertTmpF(context, part + index, 0); - } - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (part == 0) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } - - public static void Fcvtns_S(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Fcvt_Signed(context, RoundMode.ToNearest, scalar: true); - } - else - { - EmitFcvtn(context, signed: true, scalar: true); - } - } - - public static void Fcvtns_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Fcvt_Signed(context, RoundMode.ToNearest, scalar: false); - } - else - { - EmitFcvtn(context, signed: true, scalar: false); - } - } - - public static void Fcvtnu_S(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Fcvt_Unsigned(context, RoundMode.ToNearest, scalar: true); - } - else - { - EmitFcvtn(context, signed: false, scalar: true); - } - } - - public static void Fcvtnu_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Fcvt_Unsigned(context, RoundMode.ToNearest, scalar: false); - } - else - { - EmitFcvtn(context, signed: false, scalar: false); - } - } - - public static void Fcvtps_Gp(ILEmitterCtx context) - { - EmitFcvt_s_Gp(context, () => EmitUnaryMathCall(context, nameof(Math.Ceiling))); - } - - public static void Fcvtpu_Gp(ILEmitterCtx context) - { - EmitFcvt_u_Gp(context, () => EmitUnaryMathCall(context, nameof(Math.Ceiling))); - } - - public static void Fcvtzs_Gp(ILEmitterCtx context) - { - EmitFcvt_s_Gp(context, () => { }); - } - - public static void Fcvtzs_Gp_Fixed(ILEmitterCtx context) - { - EmitFcvtzs_Gp_Fixed(context); - } - - public static void Fcvtzs_S(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Fcvt_Signed(context, RoundMode.TowardsZero, scalar: true); - } - else - { - EmitFcvtz(context, signed: true, scalar: true); - } - } - - public static void Fcvtzs_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Fcvt_Signed(context, RoundMode.TowardsZero, scalar: false); - } - else - { - EmitFcvtz(context, signed: true, scalar: false); - } - } - - public static void Fcvtzs_V_Fixed(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Fcvt_Signed(context, RoundMode.TowardsZero, scalar: false); - } - else - { - EmitFcvtz(context, signed: true, scalar: false); - } - } - - public static void Fcvtzu_Gp(ILEmitterCtx context) - { - EmitFcvt_u_Gp(context, () => { }); - } - - public static void Fcvtzu_Gp_Fixed(ILEmitterCtx context) - { - EmitFcvtzu_Gp_Fixed(context); - } - - public static void Fcvtzu_S(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Fcvt_Unsigned(context, RoundMode.TowardsZero, scalar: true); - } - else - { - EmitFcvtz(context, signed: false, scalar: true); - } - } - - public static void Fcvtzu_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Fcvt_Unsigned(context, RoundMode.TowardsZero, scalar: false); - } - else - { - EmitFcvtz(context, signed: false, scalar: false); - } - } - - public static void Fcvtzu_V_Fixed(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Fcvt_Unsigned(context, RoundMode.TowardsZero, scalar: false); - } - else - { - EmitFcvtz(context, signed: false, scalar: false); - } - } - - public static void Scvtf_Gp(ILEmitterCtx context) - { - OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_I4); - } - - EmitFloatCast(context, op.Size); - - EmitScalarSetF(context, op.Rd, op.Size); - } - - public static void Scvtf_Gp_Fixed(ILEmitterCtx context) - { - OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_I4); - } - - EmitFloatCast(context, op.Size); - - EmitI2fFBitsMul(context, op.Size, op.FBits); - - EmitScalarSetF(context, op.Rd, op.Size); - } - - public static void Scvtf_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.UseSse2 && sizeF == 0) - { - EmitSse2cvtF_Signed(context, scalar: true); - } - else - { - EmitVectorExtractSx(context, op.Rn, 0, sizeF + 2); - - EmitFloatCast(context, sizeF); - - EmitScalarSetF(context, op.Rd, sizeF); - } - } - - public static void Scvtf_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.UseSse2 && sizeF == 0) - { - EmitSse2cvtF_Signed(context, scalar: false); - } - else - { - EmitVectorCvtf(context, signed: true); - } - } - - public static void Scvtf_V_Fixed(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - // sizeF == ((OpCodeSimdShImm64)op).Size - 2 - int sizeF = op.Size & 1; - - if (Optimizations.UseSse2 && sizeF == 0) - { - EmitSse2cvtF_Signed(context, scalar: false); - } - else - { - EmitVectorCvtf(context, signed: true); - } - } - - public static void Ucvtf_Gp(ILEmitterCtx context) - { - OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U4); - } - - context.Emit(OpCodes.Conv_R_Un); - - EmitFloatCast(context, op.Size); - - EmitScalarSetF(context, op.Rd, op.Size); - } - - public static void Ucvtf_Gp_Fixed(ILEmitterCtx context) - { - OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U4); - } - - context.Emit(OpCodes.Conv_R_Un); - - EmitFloatCast(context, op.Size); - - EmitI2fFBitsMul(context, op.Size, op.FBits); - - EmitScalarSetF(context, op.Rd, op.Size); - } - - public static void Ucvtf_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.UseSse2 && sizeF == 0) - { - EmitSse2cvtF_Unsigned(context, scalar: true); - } - else - { - EmitVectorExtractZx(context, op.Rn, 0, sizeF + 2); - - context.Emit(OpCodes.Conv_R_Un); - - EmitFloatCast(context, sizeF); - - EmitScalarSetF(context, op.Rd, sizeF); - } - } - - public static void Ucvtf_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.UseSse2 && sizeF == 0) - { - EmitSse2cvtF_Unsigned(context, scalar: false); - } - else - { - EmitVectorCvtf(context, signed: false); - } - } - - public static void Ucvtf_V_Fixed(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - // sizeF == ((OpCodeSimdShImm64)op).Size - 2 - int sizeF = op.Size & 1; - - if (Optimizations.UseSse2 && sizeF == 0) - { - EmitSse2cvtF_Unsigned(context, scalar: false); - } - else - { - EmitVectorCvtf(context, signed: false); - } - } - - private static void EmitFcvtn(ILEmitterCtx context, bool signed, bool scalar) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - int sizeI = sizeF + 2; - - int bytes = op.GetBitsCount() >> 3; - int elems = !scalar ? bytes >> sizeI : 1; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractF(context, op.Rn, index, sizeF); - - EmitRoundMathCall(context, MidpointRounding.ToEven); - - if (sizeF == 0) - { - VectorHelper.EmitCall(context, signed - ? nameof(VectorHelper.SatF32ToS32) - : nameof(VectorHelper.SatF32ToU32)); - - context.Emit(OpCodes.Conv_U8); - } - else /* if (sizeF == 1) */ - { - VectorHelper.EmitCall(context, signed - ? nameof(VectorHelper.SatF64ToS64) - : nameof(VectorHelper.SatF64ToU64)); - } - - if (scalar) - { - EmitVectorZeroAll(context, op.Rd); - } - - EmitVectorInsert(context, op.Rd, index, sizeI); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static void EmitFcvtz(ILEmitterCtx context, bool signed, bool scalar) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - int sizeI = sizeF + 2; - - int fBits = GetFBits(context); - - int bytes = op.GetBitsCount() >> 3; - int elems = !scalar ? bytes >> sizeI : 1; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractF(context, op.Rn, index, sizeF); - - EmitF2iFBitsMul(context, sizeF, fBits); - - if (sizeF == 0) - { - VectorHelper.EmitCall(context, signed - ? nameof(VectorHelper.SatF32ToS32) - : nameof(VectorHelper.SatF32ToU32)); - - context.Emit(OpCodes.Conv_U8); - } - else /* if (sizeF == 1) */ - { - VectorHelper.EmitCall(context, signed - ? nameof(VectorHelper.SatF64ToS64) - : nameof(VectorHelper.SatF64ToU64)); - } - - if (scalar) - { - EmitVectorZeroAll(context, op.Rd); - } - - EmitVectorInsert(context, op.Rd, index, sizeI); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static void EmitFcvt_s_Gp(ILEmitterCtx context, Action emit) - { - EmitFcvt___Gp(context, emit, true); - } - - private static void EmitFcvt_u_Gp(ILEmitterCtx context, Action emit) - { - EmitFcvt___Gp(context, emit, false); - } - - private static void EmitFcvt___Gp(ILEmitterCtx context, Action emit, bool signed) - { - OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp; - - EmitVectorExtractF(context, op.Rn, 0, op.Size); - - emit(); - - if (signed) - { - EmitScalarFcvts(context, op.Size, 0); - } - else - { - EmitScalarFcvtu(context, op.Size, 0); - } - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U8); - } - - context.EmitStintzr(op.Rd); - } - - private static void EmitFcvtzs_Gp_Fixed(ILEmitterCtx context) - { - EmitFcvtz__Gp_Fixed(context, true); - } - - private static void EmitFcvtzu_Gp_Fixed(ILEmitterCtx context) - { - EmitFcvtz__Gp_Fixed(context, false); - } - - private static void EmitFcvtz__Gp_Fixed(ILEmitterCtx context, bool signed) - { - OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp; - - EmitVectorExtractF(context, op.Rn, 0, op.Size); - - if (signed) - { - EmitScalarFcvts(context, op.Size, op.FBits); - } - else - { - EmitScalarFcvtu(context, op.Size, op.FBits); - } - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U8); - } - - context.EmitStintzr(op.Rd); - } - - private static void EmitVectorCvtf(ILEmitterCtx context, bool signed) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - int sizeI = sizeF + 2; - - int fBits = GetFBits(context); - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> sizeI; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtract(context, op.Rn, index, sizeI, signed); - - if (!signed) - { - context.Emit(OpCodes.Conv_R_Un); - } - - EmitFloatCast(context, sizeF); - - EmitI2fFBitsMul(context, sizeF, fBits); - - EmitVectorInsertF(context, op.Rd, index, sizeF); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static int GetFBits(ILEmitterCtx context) - { - if (context.CurrOp is OpCodeSimdShImm64 op) - { - return GetImmShr(op); - } - - return 0; - } - - private static void EmitFloatCast(ILEmitterCtx context, int size) - { - if (size == 0) - { - context.Emit(OpCodes.Conv_R4); - } - else if (size == 1) - { - context.Emit(OpCodes.Conv_R8); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - } - - private static void EmitScalarFcvts(ILEmitterCtx context, int size, int fBits) - { - if (size < 0 || size > 1) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - EmitF2iFBitsMul(context, size, fBits); - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - if (size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.SatF32ToS32)); - } - else /* if (size == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.SatF64ToS32)); - } - } - else - { - if (size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.SatF32ToS64)); - } - else /* if (size == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.SatF64ToS64)); - } - } - } - - private static void EmitScalarFcvtu(ILEmitterCtx context, int size, int fBits) - { - if (size < 0 || size > 1) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - EmitF2iFBitsMul(context, size, fBits); - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - if (size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.SatF32ToU32)); - } - else /* if (size == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.SatF64ToU32)); - } - } - else - { - if (size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.SatF32ToU64)); - } - else /* if (size == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.SatF64ToU64)); - } - } - } - - private static void EmitF2iFBitsMul(ILEmitterCtx context, int size, int fBits) - { - if (fBits != 0) - { - if (size == 0) - { - context.EmitLdc_R4(MathF.Pow(2f, fBits)); - } - else if (size == 1) - { - context.EmitLdc_R8(Math.Pow(2d, fBits)); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - context.Emit(OpCodes.Mul); - } - } - - private static void EmitI2fFBitsMul(ILEmitterCtx context, int size, int fBits) - { - if (fBits != 0) - { - if (size == 0) - { - context.EmitLdc_R4(1f / MathF.Pow(2f, fBits)); - } - else if (size == 1) - { - context.EmitLdc_R8(1d / Math.Pow(2d, fBits)); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - context.Emit(OpCodes.Mul); - } - } - - private static void EmitSse41Fcvt_Signed(ILEmitterCtx context, RoundMode roundMode, bool scalar) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - // sizeF == ((OpCodeSimdShImm64)op).Size - 2 - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - Type[] typesRndCvt = new Type[] { typeof(Vector128<float>) }; - Type[] typesSav = new Type[] { typeof(int) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareOrdered), types)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.And), types)); - - if (op is OpCodeSimdShImm64 fixedOp) - { - int fBits = GetImmShr(fixedOp); - - // BitConverter.Int32BitsToSingle(fpScaled) == MathF.Pow(2f, fBits) - int fpScaled = 0x3F800000 + fBits * 0x800000; - - context.EmitLdc_I4(fpScaled); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), types)); - } - - context.EmitCall(typeof(Sse41).GetMethod(GetVectorSse41NameRnd(roundMode), typesRndCvt)); - - context.EmitStvectmp(); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Int32), typesRndCvt)); - - context.EmitLdvectmp(); - - context.EmitLdc_I4(0x4F000000); // 2.14748365E9f (2147483648) - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqual), types)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Xor), types)); - - context.EmitStvec(op.Rd); - - if (scalar) - { - EmitVectorZero32_128(context, op.Rd); - } - else if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] types = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - Type[] typesRndCvt = new Type[] { typeof(Vector128<double>) }; - Type[] typesSv = new Type[] { typeof(long), typeof(long) }; - Type[] typesSav = new Type[] { typeof(long) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareOrdered), types)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), types)); - - if (op is OpCodeSimdShImm64 fixedOp) - { - int fBits = GetImmShr(fixedOp); - - // BitConverter.Int64BitsToDouble(fpScaled) == Math.Pow(2d, fBits) - long fpScaled = 0x3FF0000000000000L + fBits * 0x10000000000000L; - - context.EmitLdc_I8(fpScaled); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), types)); - } - - context.EmitCall(typeof(Sse41).GetMethod(GetVectorSse41NameRnd(roundMode), typesRndCvt)); - - context.EmitStvectmp(); - - if (!scalar) - { - context.EmitLdvectmp(); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), types)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToInt64), typesRndCvt)); - } - else - { - context.EmitLdc_I8(0L); - } - - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToInt64), typesRndCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSv)); - - context.EmitLdvectmp(); - - context.EmitLdc_I8(0x43E0000000000000L); // 9.2233720368547760E18d (9223372036854775808) - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqual), types)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), types)); - - context.EmitStvec(op.Rd); - - if (scalar) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } - - private static void EmitSse41Fcvt_Unsigned(ILEmitterCtx context, RoundMode roundMode, bool scalar) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - // sizeF == ((OpCodeSimdShImm64)op).Size - 2 - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - Type[] typesAdd = new Type[] { typeof(Vector128<int>), typeof(Vector128<int>) }; - Type[] typesRndCvt = new Type[] { typeof(Vector128<float>) }; - Type[] typesSav = new Type[] { typeof(int) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareOrdered), types)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.And), types)); - - if (op is OpCodeSimdShImm64 fixedOp) - { - int fBits = GetImmShr(fixedOp); - - // BitConverter.Int32BitsToSingle(fpScaled) == MathF.Pow(2f, fBits) - int fpScaled = 0x3F800000 + fBits * 0x800000; - - context.EmitLdc_I4(fpScaled); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), types)); - } - - context.EmitCall(typeof(Sse41).GetMethod(GetVectorSse41NameRnd(roundMode), typesRndCvt)); - - context.Emit(OpCodes.Dup); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThan), types)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.And), types)); - - context.EmitStvectmp(); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Int32), typesRndCvt)); - - context.EmitLdvectmp(); - - context.EmitLdc_I4(0x4F000000); // 2.14748365E9f (2147483648) - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitStvectmp2(); - context.EmitLdvectmp2(); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), types)); - - context.Emit(OpCodes.Dup); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThan), types)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.And), types)); - - context.EmitStvectmp(); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Int32), typesRndCvt)); - - context.EmitLdvectmp(); - context.EmitLdvectmp2(); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqual), types)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Xor), types)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - - if (scalar) - { - EmitVectorZero32_128(context, op.Rd); - } - else if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] types = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - Type[] typesAdd = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - Type[] typesRndCvt = new Type[] { typeof(Vector128<double>) }; - Type[] typesSv = new Type[] { typeof(long), typeof(long) }; - Type[] typesSav = new Type[] { typeof(long) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareOrdered), types)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), types)); - - if (op is OpCodeSimdShImm64 fixedOp) - { - int fBits = GetImmShr(fixedOp); - - // BitConverter.Int64BitsToDouble(fpScaled) == Math.Pow(2d, fBits) - long fpScaled = 0x3FF0000000000000L + fBits * 0x10000000000000L; - - context.EmitLdc_I8(fpScaled); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), types)); - } - - context.EmitCall(typeof(Sse41).GetMethod(GetVectorSse41NameRnd(roundMode), typesRndCvt)); - - context.Emit(OpCodes.Dup); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThan), types)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), types)); - - context.EmitStvectmp(); - - if (!scalar) - { - context.EmitLdvectmp(); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), types)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToInt64), typesRndCvt)); - } - else - { - context.EmitLdc_I8(0L); - } - - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToInt64), typesRndCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSv)); - - context.EmitLdvectmp(); - - context.EmitLdc_I8(0x43E0000000000000L); // 9.2233720368547760E18d (9223372036854775808) - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitStvectmp2(); - context.EmitLdvectmp2(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), types)); - - context.Emit(OpCodes.Dup); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThan), types)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), types)); - - context.EmitStvectmp(); - - if (!scalar) - { - context.EmitLdvectmp(); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), types)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToInt64), typesRndCvt)); - } - else - { - context.EmitLdc_I8(0L); - } - - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToInt64), typesRndCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSv)); - - context.EmitLdvectmp(); - context.EmitLdvectmp2(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqual), types)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), types)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - - if (scalar) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } - - private static void EmitSse2cvtF_Signed(ILEmitterCtx context, bool scalar) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesMul = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - Type[] typesCvt = new Type[] { typeof(Vector128<int>) }; - Type[] typesSav = new Type[] { typeof(int) }; - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Single), typesCvt)); - - if (op is OpCodeSimdShImm64 fixedOp) - { - int fBits = GetImmShr(fixedOp); - - // BitConverter.Int32BitsToSingle(fpScaled) == 1f / MathF.Pow(2f, fBits) - int fpScaled = 0x3F800000 - fBits * 0x800000; - - context.EmitLdc_I4(fpScaled); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMul)); - } - - context.EmitStvec(op.Rd); - - if (scalar) - { - EmitVectorZero32_128(context, op.Rd); - } - else if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static void EmitSse2cvtF_Unsigned(ILEmitterCtx context, bool scalar) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesMulAdd = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - Type[] typesSrlSll = new Type[] { typeof(Vector128<int>), typeof(byte) }; - Type[] typesCvt = new Type[] { typeof(Vector128<int>) }; - Type[] typesSav = new Type[] { typeof(int) }; - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(16); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrlSll)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Single), typesCvt)); - - context.EmitLdc_I4(0x47800000); // 65536.0f (1 << 16) - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulAdd)); - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(16); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesSrlSll)); - - context.EmitLdc_I4(16); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrlSll)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Single), typesCvt)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Add), typesMulAdd)); - - if (op is OpCodeSimdShImm64 fixedOp) - { - int fBits = GetImmShr(fixedOp); - - // BitConverter.Int32BitsToSingle(fpScaled) == 1f / MathF.Pow(2f, fBits) - int fpScaled = 0x3F800000 - fBits * 0x800000; - - context.EmitLdc_I4(fpScaled); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulAdd)); - } - - context.EmitStvec(op.Rd); - - if (scalar) - { - EmitVectorZero32_128(context, op.Rd); - } - else if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static string GetScalarSse41NameRnd(RoundMode roundMode) - { - switch (roundMode) - { - case RoundMode.ToNearest: - return nameof(Sse41.RoundToNearestIntegerScalar); // even - - case RoundMode.TowardsPlusInfinity: - return nameof(Sse41.RoundToPositiveInfinityScalar); - - case RoundMode.TowardsMinusInfinity: - return nameof(Sse41.RoundToNegativeInfinityScalar); - - default: /* case RoundMode.TowardsZero: */ - return nameof(Sse41.RoundToZeroScalar); - } - } - - private static string GetVectorSse41NameRnd(RoundMode roundMode) - { - switch (roundMode) - { - case RoundMode.ToNearest: - return nameof(Sse41.RoundToNearestInteger); // even - - case RoundMode.TowardsPlusInfinity: - return nameof(Sse41.RoundToPositiveInfinity); - - case RoundMode.TowardsMinusInfinity: - return nameof(Sse41.RoundToNegativeInfinity); - - default: /* case RoundMode.TowardsZero: */ - return nameof(Sse41.RoundToZero); - } - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitSimdHash.cs b/ChocolArm64/Instructions/InstEmitSimdHash.cs deleted file mode 100644 index bb767fec..00000000 --- a/ChocolArm64/Instructions/InstEmitSimdHash.cs +++ /dev/null @@ -1,140 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.Translation; - -using static ChocolArm64.Instructions.InstEmitSimdHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { -#region "Sha1" - public static void Sha1c_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - context.EmitLdvec(op.Rd); - EmitVectorExtractZx(context, op.Rn, 0, 2); - context.EmitLdvec(op.Rm); - - SoftFallback.EmitCall(context, nameof(SoftFallback.HashChoose)); - - context.EmitStvec(op.Rd); - } - - public static void Sha1h_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - EmitVectorExtractZx(context, op.Rn, 0, 2); - - SoftFallback.EmitCall(context, nameof(SoftFallback.FixedRotate)); - - EmitScalarSet(context, op.Rd, 2); - } - - public static void Sha1m_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - context.EmitLdvec(op.Rd); - EmitVectorExtractZx(context, op.Rn, 0, 2); - context.EmitLdvec(op.Rm); - - SoftFallback.EmitCall(context, nameof(SoftFallback.HashMajority)); - - context.EmitStvec(op.Rd); - } - - public static void Sha1p_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - context.EmitLdvec(op.Rd); - EmitVectorExtractZx(context, op.Rn, 0, 2); - context.EmitLdvec(op.Rm); - - SoftFallback.EmitCall(context, nameof(SoftFallback.HashParity)); - - context.EmitStvec(op.Rd); - } - - public static void Sha1su0_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - SoftFallback.EmitCall(context, nameof(SoftFallback.Sha1SchedulePart1)); - - context.EmitStvec(op.Rd); - } - - public static void Sha1su1_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - SoftFallback.EmitCall(context, nameof(SoftFallback.Sha1SchedulePart2)); - - context.EmitStvec(op.Rd); - } -#endregion - -#region "Sha256" - public static void Sha256h_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - SoftFallback.EmitCall(context, nameof(SoftFallback.HashLower)); - - context.EmitStvec(op.Rd); - } - - public static void Sha256h2_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - SoftFallback.EmitCall(context, nameof(SoftFallback.HashUpper)); - - context.EmitStvec(op.Rd); - } - - public static void Sha256su0_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - SoftFallback.EmitCall(context, nameof(SoftFallback.Sha256SchedulePart1)); - - context.EmitStvec(op.Rd); - } - - public static void Sha256su1_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - SoftFallback.EmitCall(context, nameof(SoftFallback.Sha256SchedulePart2)); - - context.EmitStvec(op.Rd); - } -#endregion - } -} diff --git a/ChocolArm64/Instructions/InstEmitSimdHelper.cs b/ChocolArm64/Instructions/InstEmitSimdHelper.cs deleted file mode 100644 index c8c8df74..00000000 --- a/ChocolArm64/Instructions/InstEmitSimdHelper.cs +++ /dev/null @@ -1,1580 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -namespace ChocolArm64.Instructions -{ - static class InstEmitSimdHelper - { - public static readonly Type[] IntTypesPerSizeLog2 = new Type[] - { - typeof(sbyte), - typeof(short), - typeof(int), - typeof(long) - }; - - public static readonly Type[] UIntTypesPerSizeLog2 = new Type[] - { - typeof(byte), - typeof(ushort), - typeof(uint), - typeof(ulong) - }; - - public static readonly Type[] VectorIntTypesPerSizeLog2 = new Type[] - { - typeof(Vector128<sbyte>), - typeof(Vector128<short>), - typeof(Vector128<int>), - typeof(Vector128<long>) - }; - - public static readonly Type[] VectorUIntTypesPerSizeLog2 = new Type[] - { - typeof(Vector128<byte>), - typeof(Vector128<ushort>), - typeof(Vector128<uint>), - typeof(Vector128<ulong>) - }; - - [Flags] - public enum OperFlags - { - Rd = 1 << 0, - Rn = 1 << 1, - Rm = 1 << 2, - Ra = 1 << 3, - - RnRm = Rn | Rm, - RdRn = Rd | Rn, - RaRnRm = Ra | Rn | Rm, - RdRnRm = Rd | Rn | Rm - } - - public static int GetImmShl(OpCodeSimdShImm64 op) - { - return op.Imm - (8 << op.Size); - } - - public static int GetImmShr(OpCodeSimdShImm64 op) - { - return (8 << (op.Size + 1)) - op.Imm; - } - - public static void EmitSse2Op(ILEmitterCtx context, string name) - { - EmitSseOp(context, name, typeof(Sse2)); - } - - public static void EmitSse41Op(ILEmitterCtx context, string name) - { - EmitSseOp(context, name, typeof(Sse41)); - } - - public static void EmitSse42Op(ILEmitterCtx context, string name) - { - EmitSseOp(context, name, typeof(Sse42)); - } - - private static void EmitSseOp(ILEmitterCtx context, string name, Type type) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - context.EmitLdvec(op.Rn); - - Type baseType = VectorIntTypesPerSizeLog2[op.Size]; - - if (op is OpCodeSimdReg64 binOp) - { - context.EmitLdvec(binOp.Rm); - - context.EmitCall(type.GetMethod(name, new Type[] { baseType, baseType })); - } - else - { - context.EmitCall(type.GetMethod(name, new Type[] { baseType })); - } - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void EmitScalarSseOrSse2OpF(ILEmitterCtx context, string name) - { - EmitSseOrSse2OpF(context, name, true); - } - - public static void EmitVectorSseOrSse2OpF(ILEmitterCtx context, string name) - { - EmitSseOrSse2OpF(context, name, false); - } - - public static void EmitSseOrSse2OpF(ILEmitterCtx context, string name, bool scalar) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - context.EmitLdvec(op.Rn); - - Type type; - Type baseType; - - if (sizeF == 0) - { - type = typeof(Sse); - baseType = typeof(Vector128<float>); - } - else /* if (sizeF == 1) */ - { - type = typeof(Sse2); - baseType = typeof(Vector128<double>); - } - - if (op is OpCodeSimdReg64 binOp) - { - context.EmitLdvec(binOp.Rm); - - context.EmitCall(type.GetMethod(name, new Type[] { baseType, baseType })); - } - else - { - context.EmitCall(type.GetMethod(name, new Type[] { baseType })); - } - - context.EmitStvec(op.Rd); - - if (scalar) - { - if (sizeF == 0) - { - EmitVectorZero32_128(context, op.Rd); - } - else /* if (sizeF == 1) */ - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void EmitUnaryMathCall(ILEmitterCtx context, string name) - { - IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - MethodInfo mthdInfo; - - if (sizeF == 0) - { - mthdInfo = typeof(MathF).GetMethod(name, new Type[] { typeof(float) }); - } - else /* if (sizeF == 1) */ - { - mthdInfo = typeof(Math).GetMethod(name, new Type[] { typeof(double) }); - } - - context.EmitCall(mthdInfo); - } - - public static void EmitBinaryMathCall(ILEmitterCtx context, string name) - { - IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - MethodInfo mthdInfo; - - if (sizeF == 0) - { - mthdInfo = typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(float) }); - } - else /* if (sizeF == 1) */ - { - mthdInfo = typeof(Math).GetMethod(name, new Type[] { typeof(double), typeof(double) }); - } - - context.EmitCall(mthdInfo); - } - - public static void EmitRoundMathCall(ILEmitterCtx context, MidpointRounding roundMode) - { - IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - MethodInfo mthdInfo; - - if (sizeF == 0) - { - mthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), new Type[] { typeof(float), typeof(MidpointRounding) }); - } - else /* if (sizeF == 1) */ - { - mthdInfo = typeof(Math).GetMethod(nameof(Math.Round), new Type[] { typeof(double), typeof(MidpointRounding) }); - } - - context.EmitLdc_I4((int)roundMode); - - context.EmitCall(mthdInfo); - } - - public static void EmitSoftFloatCall(ILEmitterCtx context, string name) - { - IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - Type type = sizeF == 0 - ? typeof(SoftFloat32) - : typeof(SoftFloat64); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - context.EmitCall(type, name); - } - - public static void EmitScalarBinaryOpByElemF(ILEmitterCtx context, Action emit) - { - OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp; - - EmitScalarOpByElemF(context, emit, op.Index, ternary: false); - } - - public static void EmitScalarTernaryOpByElemF(ILEmitterCtx context, Action emit) - { - OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp; - - EmitScalarOpByElemF(context, emit, op.Index, ternary: true); - } - - public static void EmitScalarOpByElemF(ILEmitterCtx context, Action emit, int elem, bool ternary) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (ternary) - { - EmitVectorExtractF(context, op.Rd, 0, sizeF); - } - - EmitVectorExtractF(context, op.Rn, 0, sizeF); - EmitVectorExtractF(context, op.Rm, elem, sizeF); - - emit(); - - EmitScalarSetF(context, op.Rd, sizeF); - } - - public static void EmitScalarUnaryOpSx(ILEmitterCtx context, Action emit) - { - EmitScalarOp(context, emit, OperFlags.Rn, true); - } - - public static void EmitScalarBinaryOpSx(ILEmitterCtx context, Action emit) - { - EmitScalarOp(context, emit, OperFlags.RnRm, true); - } - - public static void EmitScalarUnaryOpZx(ILEmitterCtx context, Action emit) - { - EmitScalarOp(context, emit, OperFlags.Rn, false); - } - - public static void EmitScalarBinaryOpZx(ILEmitterCtx context, Action emit) - { - EmitScalarOp(context, emit, OperFlags.RnRm, false); - } - - public static void EmitScalarTernaryOpZx(ILEmitterCtx context, Action emit) - { - EmitScalarOp(context, emit, OperFlags.RdRnRm, false); - } - - public static void EmitScalarOp(ILEmitterCtx context, Action emit, OperFlags opers, bool signed) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - bool rd = (opers & OperFlags.Rd) != 0; - bool rn = (opers & OperFlags.Rn) != 0; - bool rm = (opers & OperFlags.Rm) != 0; - - if (rd) - { - EmitVectorExtract(context, op.Rd, 0, op.Size, signed); - } - - if (rn) - { - EmitVectorExtract(context, op.Rn, 0, op.Size, signed); - } - - if (rm) - { - EmitVectorExtract(context, ((OpCodeSimdReg64)op).Rm, 0, op.Size, signed); - } - - emit(); - - EmitScalarSet(context, op.Rd, op.Size); - } - - public static void EmitScalarUnaryOpF(ILEmitterCtx context, Action emit) - { - EmitScalarOpF(context, emit, OperFlags.Rn); - } - - public static void EmitScalarBinaryOpF(ILEmitterCtx context, Action emit) - { - EmitScalarOpF(context, emit, OperFlags.RnRm); - } - - public static void EmitScalarTernaryRaOpF(ILEmitterCtx context, Action emit) - { - EmitScalarOpF(context, emit, OperFlags.RaRnRm); - } - - public static void EmitScalarOpF(ILEmitterCtx context, Action emit, OperFlags opers) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - bool ra = (opers & OperFlags.Ra) != 0; - bool rn = (opers & OperFlags.Rn) != 0; - bool rm = (opers & OperFlags.Rm) != 0; - - if (ra) - { - EmitVectorExtractF(context, ((OpCodeSimdReg64)op).Ra, 0, sizeF); - } - - if (rn) - { - EmitVectorExtractF(context, op.Rn, 0, sizeF); - } - - if (rm) - { - EmitVectorExtractF(context, ((OpCodeSimdReg64)op).Rm, 0, sizeF); - } - - emit(); - - EmitScalarSetF(context, op.Rd, sizeF); - } - - public static void EmitVectorUnaryOpF(ILEmitterCtx context, Action emit) - { - EmitVectorOpF(context, emit, OperFlags.Rn); - } - - public static void EmitVectorBinaryOpF(ILEmitterCtx context, Action emit) - { - EmitVectorOpF(context, emit, OperFlags.RnRm); - } - - public static void EmitVectorTernaryOpF(ILEmitterCtx context, Action emit) - { - EmitVectorOpF(context, emit, OperFlags.RdRnRm); - } - - public static void EmitVectorOpF(ILEmitterCtx context, Action emit, OperFlags opers) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> sizeF + 2; - - bool rd = (opers & OperFlags.Rd) != 0; - bool rn = (opers & OperFlags.Rn) != 0; - bool rm = (opers & OperFlags.Rm) != 0; - - for (int index = 0; index < elems; index++) - { - if (rd) - { - EmitVectorExtractF(context, op.Rd, index, sizeF); - } - - if (rn) - { - EmitVectorExtractF(context, op.Rn, index, sizeF); - } - - if (rm) - { - EmitVectorExtractF(context, ((OpCodeSimdReg64)op).Rm, index, sizeF); - } - - emit(); - - EmitVectorInsertF(context, op.Rd, index, sizeF); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void EmitVectorBinaryOpByElemF(ILEmitterCtx context, Action emit) - { - OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp; - - EmitVectorOpByElemF(context, emit, op.Index, ternary: false); - } - - public static void EmitVectorTernaryOpByElemF(ILEmitterCtx context, Action emit) - { - OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp; - - EmitVectorOpByElemF(context, emit, op.Index, ternary: true); - } - - public static void EmitVectorOpByElemF(ILEmitterCtx context, Action emit, int elem, bool ternary) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> sizeF + 2; - - for (int index = 0; index < elems; index++) - { - if (ternary) - { - EmitVectorExtractF(context, op.Rd, index, sizeF); - } - - EmitVectorExtractF(context, op.Rn, index, sizeF); - EmitVectorExtractF(context, op.Rm, elem, sizeF); - - emit(); - - EmitVectorInsertTmpF(context, index, sizeF); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void EmitVectorUnaryOpSx(ILEmitterCtx context, Action emit) - { - EmitVectorOp(context, emit, OperFlags.Rn, true); - } - - public static void EmitVectorBinaryOpSx(ILEmitterCtx context, Action emit) - { - EmitVectorOp(context, emit, OperFlags.RnRm, true); - } - - public static void EmitVectorTernaryOpSx(ILEmitterCtx context, Action emit) - { - EmitVectorOp(context, emit, OperFlags.RdRnRm, true); - } - - public static void EmitVectorUnaryOpZx(ILEmitterCtx context, Action emit) - { - EmitVectorOp(context, emit, OperFlags.Rn, false); - } - - public static void EmitVectorBinaryOpZx(ILEmitterCtx context, Action emit) - { - EmitVectorOp(context, emit, OperFlags.RnRm, false); - } - - public static void EmitVectorTernaryOpZx(ILEmitterCtx context, Action emit) - { - EmitVectorOp(context, emit, OperFlags.RdRnRm, false); - } - - public static void EmitVectorOp(ILEmitterCtx context, Action emit, OperFlags opers, bool signed) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - bool rd = (opers & OperFlags.Rd) != 0; - bool rn = (opers & OperFlags.Rn) != 0; - bool rm = (opers & OperFlags.Rm) != 0; - - for (int index = 0; index < elems; index++) - { - if (rd) - { - EmitVectorExtract(context, op.Rd, index, op.Size, signed); - } - - if (rn) - { - EmitVectorExtract(context, op.Rn, index, op.Size, signed); - } - - if (rm) - { - EmitVectorExtract(context, ((OpCodeSimdReg64)op).Rm, index, op.Size, signed); - } - - emit(); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void EmitVectorBinaryOpByElemSx(ILEmitterCtx context, Action emit) - { - OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp; - - EmitVectorOpByElem(context, emit, op.Index, ternary: false, signed: true); - } - - public static void EmitVectorBinaryOpByElemZx(ILEmitterCtx context, Action emit) - { - OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp; - - EmitVectorOpByElem(context, emit, op.Index, ternary: false, signed: false); - } - - public static void EmitVectorTernaryOpByElemZx(ILEmitterCtx context, Action emit) - { - OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp; - - EmitVectorOpByElem(context, emit, op.Index, ternary: true, signed: false); - } - - public static void EmitVectorOpByElem(ILEmitterCtx context, Action emit, int elem, bool ternary, bool signed) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - EmitVectorExtract(context, op.Rm, elem, op.Size, signed); - context.EmitSttmp(); - - for (int index = 0; index < elems; index++) - { - if (ternary) - { - EmitVectorExtract(context, op.Rd, index, op.Size, signed); - } - - EmitVectorExtract(context, op.Rn, index, op.Size, signed); - context.EmitLdtmp(); - - emit(); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void EmitVectorImmUnaryOp(ILEmitterCtx context, Action emit) - { - EmitVectorImmOp(context, emit, false); - } - - public static void EmitVectorImmBinaryOp(ILEmitterCtx context, Action emit) - { - EmitVectorImmOp(context, emit, true); - } - - public static void EmitVectorImmOp(ILEmitterCtx context, Action emit, bool binary) - { - OpCodeSimdImm64 op = (OpCodeSimdImm64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - for (int index = 0; index < elems; index++) - { - if (binary) - { - EmitVectorExtractZx(context, op.Rd, index, op.Size); - } - - context.EmitLdc_I8(op.Imm); - - emit(); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void EmitVectorWidenRmBinaryOpSx(ILEmitterCtx context, Action emit) - { - EmitVectorWidenRmBinaryOp(context, emit, true); - } - - public static void EmitVectorWidenRmBinaryOpZx(ILEmitterCtx context, Action emit) - { - EmitVectorWidenRmBinaryOp(context, emit, false); - } - - public static void EmitVectorWidenRmBinaryOp(ILEmitterCtx context, Action emit, bool signed) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int elems = 8 >> op.Size; - - int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtract(context, op.Rn, index, op.Size + 1, signed); - EmitVectorExtract(context, op.Rm, part + index, op.Size, signed); - - emit(); - - EmitVectorInsertTmp(context, index, op.Size + 1); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - } - - public static void EmitVectorWidenRnRmBinaryOpSx(ILEmitterCtx context, Action emit) - { - EmitVectorWidenRnRmOp(context, emit, false, true); - } - - public static void EmitVectorWidenRnRmBinaryOpZx(ILEmitterCtx context, Action emit) - { - EmitVectorWidenRnRmOp(context, emit, false, false); - } - - public static void EmitVectorWidenRnRmTernaryOpSx(ILEmitterCtx context, Action emit) - { - EmitVectorWidenRnRmOp(context, emit, true, true); - } - - public static void EmitVectorWidenRnRmTernaryOpZx(ILEmitterCtx context, Action emit) - { - EmitVectorWidenRnRmOp(context, emit, true, false); - } - - public static void EmitVectorWidenRnRmOp(ILEmitterCtx context, Action emit, bool ternary, bool signed) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int elems = 8 >> op.Size; - - int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; - - for (int index = 0; index < elems; index++) - { - if (ternary) - { - EmitVectorExtract(context, op.Rd, index, op.Size + 1, signed); - } - - EmitVectorExtract(context, op.Rn, part + index, op.Size, signed); - EmitVectorExtract(context, op.Rm, part + index, op.Size, signed); - - emit(); - - EmitVectorInsertTmp(context, index, op.Size + 1); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - } - - public static void EmitVectorWidenBinaryOpByElemSx(ILEmitterCtx context, Action emit) - { - OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp; - - EmitVectorWidenOpByElem(context, emit, op.Index, ternary: false, signed: true); - } - - public static void EmitVectorWidenBinaryOpByElemZx(ILEmitterCtx context, Action emit) - { - OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp; - - EmitVectorWidenOpByElem(context, emit, op.Index, ternary: false, signed: false); - } - - public static void EmitVectorWidenTernaryOpByElemSx(ILEmitterCtx context, Action emit) - { - OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp; - - EmitVectorWidenOpByElem(context, emit, op.Index, ternary: true, signed: true); - } - - public static void EmitVectorWidenTernaryOpByElemZx(ILEmitterCtx context, Action emit) - { - OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp; - - EmitVectorWidenOpByElem(context, emit, op.Index, ternary: true, signed: false); - } - - public static void EmitVectorWidenOpByElem(ILEmitterCtx context, Action emit, int elem, bool ternary, bool signed) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int elems = 8 >> op.Size; - - int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; - - EmitVectorExtract(context, op.Rm, elem, op.Size, signed); - context.EmitSttmp(); - - for (int index = 0; index < elems; index++) - { - if (ternary) - { - EmitVectorExtract(context, op.Rd, index, op.Size + 1, signed); - } - - EmitVectorExtract(context, op.Rn, part + index, op.Size, signed); - context.EmitLdtmp(); - - emit(); - - EmitVectorInsertTmp(context, index, op.Size + 1); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - } - - public static void EmitVectorPairwiseOpSx(ILEmitterCtx context, Action emit) - { - EmitVectorPairwiseOp(context, emit, true); - } - - public static void EmitVectorPairwiseOpZx(ILEmitterCtx context, Action emit) - { - EmitVectorPairwiseOp(context, emit, false); - } - - public static void EmitVectorPairwiseOp(ILEmitterCtx context, Action emit, bool signed) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int words = op.GetBitsCount() >> 4; - int pairs = words >> op.Size; - - for (int index = 0; index < pairs; index++) - { - int idx = index << 1; - - EmitVectorExtract(context, op.Rn, idx, op.Size, signed); - EmitVectorExtract(context, op.Rn, idx + 1, op.Size, signed); - - emit(); - - EmitVectorExtract(context, op.Rm, idx, op.Size, signed); - EmitVectorExtract(context, op.Rm, idx + 1, op.Size, signed); - - emit(); - - EmitVectorInsertTmp(context, pairs + index, op.Size); - EmitVectorInsertTmp(context, index, op.Size); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void EmitVectorAcrossVectorOpSx(ILEmitterCtx context, Action emit) - { - EmitVectorAcrossVectorOp(context, emit, signed: true, isLong: false); - } - - public static void EmitVectorAcrossVectorOpZx(ILEmitterCtx context, Action emit) - { - EmitVectorAcrossVectorOp(context, emit, signed: false, isLong: false); - } - - public static void EmitVectorLongAcrossVectorOpSx(ILEmitterCtx context, Action emit) - { - EmitVectorAcrossVectorOp(context, emit, signed: true, isLong: true); - } - - public static void EmitVectorLongAcrossVectorOpZx(ILEmitterCtx context, Action emit) - { - EmitVectorAcrossVectorOp(context, emit, signed: false, isLong: true); - } - - public static void EmitVectorAcrossVectorOp( - ILEmitterCtx context, - Action emit, - bool signed, - bool isLong) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - EmitVectorExtract(context, op.Rn, 0, op.Size, signed); - - for (int index = 1; index < elems; index++) - { - EmitVectorExtract(context, op.Rn, index, op.Size, signed); - - emit(); - } - - EmitScalarSet(context, op.Rd, isLong ? op.Size + 1 : op.Size); - } - - public static void EmitVectorPairwiseOpF(ILEmitterCtx context, Action emit) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - int words = op.GetBitsCount() >> 4; - int pairs = words >> sizeF + 2; - - for (int index = 0; index < pairs; index++) - { - int idx = index << 1; - - EmitVectorExtractF(context, op.Rn, idx, sizeF); - EmitVectorExtractF(context, op.Rn, idx + 1, sizeF); - - emit(); - - EmitVectorExtractF(context, op.Rm, idx, sizeF); - EmitVectorExtractF(context, op.Rm, idx + 1, sizeF); - - emit(); - - EmitVectorInsertTmpF(context, pairs + index, sizeF); - EmitVectorInsertTmpF(context, index, sizeF); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void EmitVectorPairwiseSseOrSse2OpF(ILEmitterCtx context, string name) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - if (op.RegisterSize == RegisterSize.Simd64) - { - Type[] types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.UnpackLow), types)); - - context.EmitStvectmp(); - context.EmitLdvectmp(); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh), types)); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveHighToLow), types)); - - context.EmitCall(typeof(Sse).GetMethod(name, types)); - - context.EmitStvec(op.Rd); - } - else /* if (op.RegisterSize == RegisterSize.Simd128) */ - { - Type[] typesSfl = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>), typeof(byte) }; - Type[] types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(2 << 6 | 0 << 4 | 2 << 2 | 0 << 0); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Shuffle), typesSfl)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(3 << 6 | 1 << 4 | 3 << 2 | 1 << 0); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse).GetMethod(name, types)); - - context.EmitStvec(op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] types = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), types)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), types)); - - context.EmitCall(typeof(Sse2).GetMethod(name, types)); - - context.EmitStvec(op.Rd); - } - } - - [Flags] - public enum SaturatingFlags - { - Scalar = 1 << 0, - Signed = 1 << 1, - - Add = 1 << 2, - Sub = 1 << 3, - - Accumulate = 1 << 4, - - ScalarSx = Scalar | Signed, - ScalarZx = Scalar, - - VectorSx = Signed, - VectorZx = 0 - } - - public static void EmitScalarSaturatingUnaryOpSx(ILEmitterCtx context, Action emit) - { - EmitSaturatingUnaryOpSx(context, emit, SaturatingFlags.ScalarSx); - } - - public static void EmitVectorSaturatingUnaryOpSx(ILEmitterCtx context, Action emit) - { - EmitSaturatingUnaryOpSx(context, emit, SaturatingFlags.VectorSx); - } - - public static void EmitSaturatingUnaryOpSx(ILEmitterCtx context, Action emit, SaturatingFlags flags) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - bool scalar = (flags & SaturatingFlags.Scalar) != 0; - - int bytes = op.GetBitsCount() >> 3; - int elems = !scalar ? bytes >> op.Size : 1; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractSx(context, op.Rn, index, op.Size); - - emit(); - - if (op.Size <= 2) - { - EmitSatQ(context, op.Size, true, true); - } - else /* if (op.Size == 3) */ - { - EmitUnarySignedSatQAbsOrNeg(context); - } - - if (scalar) - { - EmitVectorZeroAll(context, op.Rd); - } - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void EmitScalarSaturatingBinaryOpSx(ILEmitterCtx context, SaturatingFlags flags) - { - EmitSaturatingBinaryOp(context, () => { }, SaturatingFlags.ScalarSx | flags); - } - - public static void EmitScalarSaturatingBinaryOpZx(ILEmitterCtx context, SaturatingFlags flags) - { - EmitSaturatingBinaryOp(context, () => { }, SaturatingFlags.ScalarZx | flags); - } - - public static void EmitVectorSaturatingBinaryOpSx(ILEmitterCtx context, SaturatingFlags flags) - { - EmitSaturatingBinaryOp(context, () => { }, SaturatingFlags.VectorSx | flags); - } - - public static void EmitVectorSaturatingBinaryOpZx(ILEmitterCtx context, SaturatingFlags flags) - { - EmitSaturatingBinaryOp(context, () => { }, SaturatingFlags.VectorZx | flags); - } - - public static void EmitSaturatingBinaryOp(ILEmitterCtx context, Action emit, SaturatingFlags flags) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - bool scalar = (flags & SaturatingFlags.Scalar) != 0; - bool signed = (flags & SaturatingFlags.Signed) != 0; - - bool add = (flags & SaturatingFlags.Add) != 0; - bool sub = (flags & SaturatingFlags.Sub) != 0; - - bool accumulate = (flags & SaturatingFlags.Accumulate) != 0; - - int bytes = op.GetBitsCount() >> 3; - int elems = !scalar ? bytes >> op.Size : 1; - - if (add || sub) - { - for (int index = 0; index < elems; index++) - { - EmitVectorExtract(context, op.Rn, index, op.Size, signed); - EmitVectorExtract(context, ((OpCodeSimdReg64)op).Rm, index, op.Size, signed); - - if (op.Size <= 2) - { - context.Emit(add ? OpCodes.Add : OpCodes.Sub); - - EmitSatQ(context, op.Size, true, signed); - } - else /* if (op.Size == 3) */ - { - if (add) - { - EmitBinarySatQAdd(context, signed); - } - else /* if (sub) */ - { - EmitBinarySatQSub(context, signed); - } - } - - if (scalar) - { - EmitVectorZeroAll(context, op.Rd); - } - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - } - else if (accumulate) - { - for (int index = 0; index < elems; index++) - { - EmitVectorExtract(context, op.Rn, index, op.Size, !signed); - EmitVectorExtract(context, op.Rd, index, op.Size, signed); - - if (op.Size <= 2) - { - context.Emit(OpCodes.Add); - - EmitSatQ(context, op.Size, true, signed); - } - else /* if (op.Size == 3) */ - { - EmitBinarySatQAccumulate(context, signed); - } - - if (scalar) - { - EmitVectorZeroAll(context, op.Rd); - } - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - } - else - { - for (int index = 0; index < elems; index++) - { - EmitVectorExtract(context, op.Rn, index, op.Size, signed); - EmitVectorExtract(context, ((OpCodeSimdReg64)op).Rm, index, op.Size, signed); - - emit(); - - EmitSatQ(context, op.Size, true, signed); - - if (scalar) - { - EmitVectorZeroAll(context, op.Rd); - } - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - [Flags] - public enum SaturatingNarrowFlags - { - Scalar = 1 << 0, - SignedSrc = 1 << 1, - SignedDst = 1 << 2, - - ScalarSxSx = Scalar | SignedSrc | SignedDst, - ScalarSxZx = Scalar | SignedSrc, - ScalarZxZx = Scalar, - - VectorSxSx = SignedSrc | SignedDst, - VectorSxZx = SignedSrc, - VectorZxZx = 0 - } - - public static void EmitSaturatingNarrowOp(ILEmitterCtx context, SaturatingNarrowFlags flags) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - bool scalar = (flags & SaturatingNarrowFlags.Scalar) != 0; - bool signedSrc = (flags & SaturatingNarrowFlags.SignedSrc) != 0; - bool signedDst = (flags & SaturatingNarrowFlags.SignedDst) != 0; - - int elems = !scalar ? 8 >> op.Size : 1; - - int part = !scalar && (op.RegisterSize == RegisterSize.Simd128) ? elems : 0; - - if (scalar) - { - EmitVectorZeroLowerTmp(context); - } - - if (part != 0) - { - context.EmitLdvec(op.Rd); - context.EmitStvectmp(); - } - - for (int index = 0; index < elems; index++) - { - EmitVectorExtract(context, op.Rn, index, op.Size + 1, signedSrc); - - EmitSatQ(context, op.Size, signedSrc, signedDst); - - EmitVectorInsertTmp(context, part + index, op.Size); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (part == 0) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - // TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned). - public static void EmitSatQ(ILEmitterCtx context, int sizeDst, bool signedSrc, bool signedDst) - { - if ((uint)sizeDst > 2u) - { - throw new ArgumentOutOfRangeException(nameof(sizeDst)); - } - - context.EmitLdc_I4(sizeDst); - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (signedSrc) - { - SoftFallback.EmitCall(context, signedDst - ? nameof(SoftFallback.SignedSrcSignedDstSatQ) - : nameof(SoftFallback.SignedSrcUnsignedDstSatQ)); - } - else - { - SoftFallback.EmitCall(context, signedDst - ? nameof(SoftFallback.UnsignedSrcSignedDstSatQ) - : nameof(SoftFallback.UnsignedSrcUnsignedDstSatQ)); - } - } - - // TSrc (64bit) == TDst (64bit); signed. - public static void EmitUnarySignedSatQAbsOrNeg(ILEmitterCtx context) - { - if (((OpCodeSimd64)context.CurrOp).Size < 3) - { - throw new InvalidOperationException(); - } - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - SoftFallback.EmitCall(context, nameof(SoftFallback.UnarySignedSatQAbsOrNeg)); - } - - // TSrcs (64bit) == TDst (64bit); signed, unsigned. - public static void EmitBinarySatQAdd(ILEmitterCtx context, bool signed) - { - if (((OpCodeSimdReg64)context.CurrOp).Size < 3) - { - throw new InvalidOperationException(); - } - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - SoftFallback.EmitCall(context, signed - ? nameof(SoftFallback.BinarySignedSatQAdd) - : nameof(SoftFallback.BinaryUnsignedSatQAdd)); - } - - // TSrcs (64bit) == TDst (64bit); signed, unsigned. - public static void EmitBinarySatQSub(ILEmitterCtx context, bool signed) - { - if (((OpCodeSimdReg64)context.CurrOp).Size < 3) - { - throw new InvalidOperationException(); - } - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - SoftFallback.EmitCall(context, signed - ? nameof(SoftFallback.BinarySignedSatQSub) - : nameof(SoftFallback.BinaryUnsignedSatQSub)); - } - - // TSrcs (64bit) == TDst (64bit); signed, unsigned. - public static void EmitBinarySatQAccumulate(ILEmitterCtx context, bool signed) - { - if (((OpCodeSimd64)context.CurrOp).Size < 3) - { - throw new InvalidOperationException(); - } - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - SoftFallback.EmitCall(context, signed - ? nameof(SoftFallback.BinarySignedSatQAcc) - : nameof(SoftFallback.BinaryUnsignedSatQAcc)); - } - - public static void EmitScalarSet(ILEmitterCtx context, int reg, int size) - { - EmitVectorZeroAll(context, reg); - EmitVectorInsert(context, reg, 0, size); - } - - public static void EmitScalarSetF(ILEmitterCtx context, int reg, int size) - { - if (Optimizations.UseSse41 && size == 0) - { - // If the type is float, we can perform insertion and - // zero the upper bits with a single instruction (INSERTPS); - context.EmitLdvec(reg); - - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41VectorInsertScalarSingle)); - - context.EmitStvec(reg); - } - else - { - EmitVectorZeroAll(context, reg); - EmitVectorInsertF(context, reg, 0, size); - } - } - - public static void EmitVectorExtractSx(ILEmitterCtx context, int reg, int index, int size) - { - EmitVectorExtract(context, reg, index, size, true); - } - - public static void EmitVectorExtractZx(ILEmitterCtx context, int reg, int index, int size) - { - EmitVectorExtract(context, reg, index, size, false); - } - - public static void EmitVectorExtract(ILEmitterCtx context, int reg, int index, int size, bool signed) - { - ThrowIfInvalid(index, size); - - context.EmitLdvec(reg); - context.EmitLdc_I4(index); - context.EmitLdc_I4(size); - - VectorHelper.EmitCall(context, signed - ? nameof(VectorHelper.VectorExtractIntSx) - : nameof(VectorHelper.VectorExtractIntZx)); - } - - public static void EmitVectorExtractF(ILEmitterCtx context, int reg, int index, int size) - { - ThrowIfInvalidF(index, size); - - context.EmitLdvec(reg); - context.EmitLdc_I4(index); - - if (size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorExtractSingle)); - } - else if (size == 1) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorExtractDouble)); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - } - - public static void EmitVectorZeroAll(ILEmitterCtx context, int reg) - { - if (Optimizations.UseSse) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitStvec(reg); - } - else - { - EmitVectorZeroLower(context, reg); - EmitVectorZeroUpper(context, reg); - } - } - - public static void EmitVectorZeroLower(ILEmitterCtx context, int reg) - { - EmitVectorInsert(context, reg, 0, 3, 0); - } - - public static void EmitVectorZeroLowerTmp(ILEmitterCtx context) - { - if (Optimizations.UseSse) - { - context.EmitLdvectmp(); - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveHighToLow))); - - context.EmitStvectmp(); - } - else - { - EmitVectorInsertTmp(context, 0, 3, 0); - } - } - - public static void EmitVectorZeroUpper(ILEmitterCtx context, int reg) - { - if (Optimizations.UseSse) - { - // TODO: Use Sse2.MoveScalar once it is fixed (in .NET Core 3.0), - // as of the time of writing it just crashes the JIT. - - /*Type[] typesMov = new Type[] { typeof(Vector128<ulong>) }; - - context.EmitLdvec(reg); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MoveScalar), typesMov)); - - context.EmitStvec(reg);*/ - - context.EmitLdvec(reg); - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh))); - - context.EmitStvec(reg); - } - else - { - EmitVectorInsert(context, reg, 1, 3, 0); - } - } - - public static void EmitVectorZero32_128(ILEmitterCtx context, int reg) - { - if (!Sse.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - context.EmitLdvec(reg); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveScalar))); - - context.EmitStvec(reg); - } - - public static void EmitVectorInsert(ILEmitterCtx context, int reg, int index, int size) - { - ThrowIfInvalid(index, size); - - context.EmitLdvec(reg); - context.EmitLdc_I4(index); - context.EmitLdc_I4(size); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertInt)); - - context.EmitStvec(reg); - } - - public static void EmitVectorInsertTmp(ILEmitterCtx context, int index, int size) - { - ThrowIfInvalid(index, size); - - context.EmitLdvectmp(); - context.EmitLdc_I4(index); - context.EmitLdc_I4(size); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertInt)); - - context.EmitStvectmp(); - } - - public static void EmitVectorInsert(ILEmitterCtx context, int reg, int index, int size, long value) - { - ThrowIfInvalid(index, size); - - context.EmitLdc_I8(value); - context.EmitLdvec(reg); - context.EmitLdc_I4(index); - context.EmitLdc_I4(size); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertInt)); - - context.EmitStvec(reg); - } - - public static void EmitVectorInsertTmp(ILEmitterCtx context, int index, int size, long value) - { - ThrowIfInvalid(index, size); - - context.EmitLdc_I8(value); - context.EmitLdvectmp(); - context.EmitLdc_I4(index); - context.EmitLdc_I4(size); - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertInt)); - - context.EmitStvectmp(); - } - - public static void EmitVectorInsertF(ILEmitterCtx context, int reg, int index, int size) - { - ThrowIfInvalidF(index, size); - - context.EmitLdvec(reg); - context.EmitLdc_I4(index); - - if (size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertSingle)); - } - else if (size == 1) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertDouble)); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - context.EmitStvec(reg); - } - - public static void EmitVectorInsertTmpF(ILEmitterCtx context, int index, int size) - { - ThrowIfInvalidF(index, size); - - context.EmitLdvectmp(); - context.EmitLdc_I4(index); - - if (size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertSingle)); - } - else if (size == 1) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertDouble)); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - context.EmitStvectmp(); - } - - private static void ThrowIfInvalid(int index, int size) - { - if ((uint)size > 3u) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - if ((uint)index >= 16u >> size) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - } - - private static void ThrowIfInvalidF(int index, int size) - { - if ((uint)size > 1u) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - if ((uint)index >= 4u >> size) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitSimdLogical.cs b/ChocolArm64/Instructions/InstEmitSimdLogical.cs deleted file mode 100644 index a5a92274..00000000 --- a/ChocolArm64/Instructions/InstEmitSimdLogical.cs +++ /dev/null @@ -1,437 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -using static ChocolArm64.Instructions.InstEmitSimdHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void And_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - EmitSse2Op(context, nameof(Sse2.And)); - } - else - { - EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.And)); - } - } - - public static void Bic_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesAnt = new Type[] { typeof(Vector128<byte>), typeof(Vector128<byte>) }; - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpZx(context, () => - { - context.Emit(OpCodes.Not); - context.Emit(OpCodes.And); - }); - } - } - - public static void Bic_Vi(ILEmitterCtx context) - { - EmitVectorImmBinaryOp(context, () => - { - context.Emit(OpCodes.Not); - context.Emit(OpCodes.And); - }); - } - - public static void Bif_V(ILEmitterCtx context) - { - EmitBifBit(context, notRm: true); - } - - public static void Bit_V(ILEmitterCtx context) - { - EmitBifBit(context, notRm: false); - } - - private static void EmitBifBit(ILEmitterCtx context, bool notRm) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2) - { - Type[] typesXorAnd = new Type[] { typeof(Vector128<byte>), typeof(Vector128<byte>) }; - - string nameAnd = notRm ? nameof(Sse2.AndNot) : nameof(Sse2.And); - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rd); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesXorAnd)); - context.EmitCall(typeof(Sse2).GetMethod(nameAnd, typesXorAnd)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesXorAnd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - int elems = op.RegisterSize == RegisterSize.Simd128 ? 2 : 1; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rd, index, 3); - context.Emit(OpCodes.Dup); - - EmitVectorExtractZx(context, op.Rn, index, 3); - - context.Emit(OpCodes.Xor); - - EmitVectorExtractZx(context, op.Rm, index, 3); - - if (notRm) - { - context.Emit(OpCodes.Not); - } - - context.Emit(OpCodes.And); - context.Emit(OpCodes.Xor); - - EmitVectorInsert(context, op.Rd, index, 3); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } - - public static void Bsl_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesXorAnd = new Type[] { typeof(Vector128<byte>), typeof(Vector128<byte>) }; - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesXorAnd)); - - context.EmitLdvec(op.Rd); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesXorAnd)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesXorAnd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorTernaryOpZx(context, () => - { - context.EmitSttmp(); - context.EmitLdtmp(); - - context.Emit(OpCodes.Xor); - context.Emit(OpCodes.And); - - context.EmitLdtmp(); - - context.Emit(OpCodes.Xor); - }); - } - } - - public static void Eor_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - EmitSse2Op(context, nameof(Sse2.Xor)); - } - else - { - EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.Xor)); - } - } - - public static void Not_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesSav = new Type[] { typeof(long) }; - Type[] typesAnt = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I8(-1L); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorUnaryOpZx(context, () => context.Emit(OpCodes.Not)); - } - } - - public static void Orn_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSav = new Type[] { typeof(long) }; - Type[] typesAntOr = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I8(-1L); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAntOr)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesAntOr)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpZx(context, () => - { - context.Emit(OpCodes.Not); - context.Emit(OpCodes.Or); - }); - } - } - - public static void Orr_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - EmitSse2Op(context, nameof(Sse2.Or)); - } - else - { - EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.Or)); - } - } - - public static void Orr_Vi(ILEmitterCtx context) - { - EmitVectorImmBinaryOp(context, () => context.Emit(OpCodes.Or)); - } - - public static void Rbit_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int elems = op.RegisterSize == RegisterSize.Simd128 ? 16 : 8; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, 0); - - context.Emit(OpCodes.Conv_U4); - - SoftFallback.EmitCall(context, nameof(SoftFallback.ReverseBits8)); - - context.Emit(OpCodes.Conv_U8); - - EmitVectorInsert(context, op.Rd, index, 0); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Rev16_V(ILEmitterCtx context) - { - if (Optimizations.UseSsse3) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesSve = new Type[] { typeof(long), typeof(long) }; - Type[] typesSfl = new Type[] { typeof(Vector128<sbyte>), typeof(Vector128<sbyte>) }; - - context.EmitLdvec(op.Rn); // value - - context.EmitLdc_I8(14L << 56 | 15L << 48 | 12L << 40 | 13L << 32 | 10L << 24 | 11L << 16 | 08L << 8 | 09L << 0); // maskE1 - context.EmitLdc_I8(06L << 56 | 07L << 48 | 04L << 40 | 05L << 32 | 02L << 24 | 03L << 16 | 00L << 8 | 01L << 0); // maskE0 - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), typesSfl)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitRev_V(context, containerSize: 1); - } - } - - public static void Rev32_V(ILEmitterCtx context) - { - if (Optimizations.UseSsse3) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesSve = new Type[] { typeof(long), typeof(long) }; - Type[] typesSfl = new Type[] { typeof(Vector128<sbyte>), typeof(Vector128<sbyte>) }; - - context.EmitLdvec(op.Rn); // value - - if (op.Size == 0) - { - context.EmitLdc_I8(12L << 56 | 13L << 48 | 14L << 40 | 15L << 32 | 08L << 24 | 09L << 16 | 10L << 8 | 11L << 0); // maskE1 - context.EmitLdc_I8(04L << 56 | 05L << 48 | 06L << 40 | 07L << 32 | 00L << 24 | 01L << 16 | 02L << 8 | 03L << 0); // maskE0 - } - else /* if (op.Size == 1) */ - { - context.EmitLdc_I8(13L << 56 | 12L << 48 | 15L << 40 | 14L << 32 | 09L << 24 | 08L << 16 | 11L << 8 | 10L << 0); // maskE1 - context.EmitLdc_I8(05L << 56 | 04L << 48 | 07L << 40 | 06L << 32 | 01L << 24 | 00L << 16 | 03L << 8 | 02L << 0); // maskE0 - } - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), typesSfl)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitRev_V(context, containerSize: 2); - } - } - - public static void Rev64_V(ILEmitterCtx context) - { - if (Optimizations.UseSsse3) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesSve = new Type[] { typeof(long), typeof(long) }; - Type[] typesSfl = new Type[] { typeof(Vector128<sbyte>), typeof(Vector128<sbyte>) }; - - context.EmitLdvec(op.Rn); // value - - if (op.Size == 0) - { - context.EmitLdc_I8(08L << 56 | 09L << 48 | 10L << 40 | 11L << 32 | 12L << 24 | 13L << 16 | 14L << 8 | 15L << 0); // maskE1 - context.EmitLdc_I8(00L << 56 | 01L << 48 | 02L << 40 | 03L << 32 | 04L << 24 | 05L << 16 | 06L << 8 | 07L << 0); // maskE0 - } - else if (op.Size == 1) - { - context.EmitLdc_I8(09L << 56 | 08L << 48 | 11L << 40 | 10L << 32 | 13L << 24 | 12L << 16 | 15L << 8 | 14L << 0); // maskE1 - context.EmitLdc_I8(01L << 56 | 00L << 48 | 03L << 40 | 02L << 32 | 05L << 24 | 04L << 16 | 07L << 8 | 06L << 0); // maskE0 - } - else /* if (op.Size == 2) */ - { - context.EmitLdc_I8(11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 15L << 24 | 14L << 16 | 13L << 8 | 12L << 0); // maskE1 - context.EmitLdc_I8(03L << 56 | 02L << 48 | 01L << 40 | 00L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0); // maskE0 - } - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), typesSfl)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitRev_V(context, containerSize: 3); - } - } - - private static void EmitRev_V(ILEmitterCtx context, int containerSize) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - int containerMask = (1 << (containerSize - op.Size)) - 1; - - for (int index = 0; index < elems; index++) - { - int revIndex = index ^ containerMask; - - EmitVectorExtractZx(context, op.Rn, revIndex, op.Size); - - EmitVectorInsertTmp(context, index, op.Size); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitSimdMemory.cs b/ChocolArm64/Instructions/InstEmitSimdMemory.cs deleted file mode 100644 index 073b0f0a..00000000 --- a/ChocolArm64/Instructions/InstEmitSimdMemory.cs +++ /dev/null @@ -1,182 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; - -using static ChocolArm64.Instructions.InstEmitMemoryHelper; -using static ChocolArm64.Instructions.InstEmitSimdHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Ld__Vms(ILEmitterCtx context) - { - EmitSimdMemMs(context, isLoad: true); - } - - public static void Ld__Vss(ILEmitterCtx context) - { - EmitSimdMemSs(context, isLoad: true); - } - - public static void St__Vms(ILEmitterCtx context) - { - EmitSimdMemMs(context, isLoad: false); - } - - public static void St__Vss(ILEmitterCtx context) - { - EmitSimdMemSs(context, isLoad: false); - } - - private static void EmitSimdMemMs(ILEmitterCtx context, bool isLoad) - { - OpCodeSimdMemMs64 op = (OpCodeSimdMemMs64)context.CurrOp; - - int offset = 0; - - for (int rep = 0; rep < op.Reps; rep++) - for (int elem = 0; elem < op.Elems; elem++) - for (int sElem = 0; sElem < op.SElems; sElem++) - { - int rtt = (op.Rt + rep + sElem) & 0x1f; - - if (isLoad) - { - context.EmitLdint(op.Rn); - context.EmitLdc_I8(offset); - - context.Emit(OpCodes.Add); - - EmitReadZxCall(context, op.Size); - - EmitVectorInsert(context, rtt, elem, op.Size); - - if (op.RegisterSize == RegisterSize.Simd64 && elem == op.Elems - 1) - { - EmitVectorZeroUpper(context, rtt); - } - } - else - { - context.EmitLdint(op.Rn); - context.EmitLdc_I8(offset); - - context.Emit(OpCodes.Add); - - EmitVectorExtractZx(context, rtt, elem, op.Size); - - EmitWriteCall(context, op.Size); - } - - offset += 1 << op.Size; - } - - if (op.WBack) - { - EmitSimdMemWBack(context, offset); - } - } - - private static void EmitSimdMemSs(ILEmitterCtx context, bool isLoad) - { - OpCodeSimdMemSs64 op = (OpCodeSimdMemSs64)context.CurrOp; - - int offset = 0; - - void EmitMemAddress() - { - context.EmitLdint(op.Rn); - context.EmitLdc_I8(offset); - - context.Emit(OpCodes.Add); - } - - if (op.Replicate) - { - // Only loads uses the replicate mode. - if (!isLoad) - { - throw new InvalidOperationException(); - } - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - for (int sElem = 0; sElem < op.SElems; sElem++) - { - int rt = (op.Rt + sElem) & 0x1f; - - for (int index = 0; index < elems; index++) - { - EmitMemAddress(); - - EmitReadZxCall(context, op.Size); - - EmitVectorInsert(context, rt, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, rt); - } - - offset += 1 << op.Size; - } - } - else - { - for (int sElem = 0; sElem < op.SElems; sElem++) - { - int rt = (op.Rt + sElem) & 0x1f; - - if (isLoad) - { - EmitMemAddress(); - - EmitReadZxCall(context, op.Size); - - EmitVectorInsert(context, rt, op.Index, op.Size); - } - else - { - EmitMemAddress(); - - EmitVectorExtractZx(context, rt, op.Index, op.Size); - - EmitWriteCall(context, op.Size); - } - - offset += 1 << op.Size; - } - } - - if (op.WBack) - { - EmitSimdMemWBack(context, offset); - } - } - - private static void EmitSimdMemWBack(ILEmitterCtx context, int offset) - { - OpCodeMemReg64 op = (OpCodeMemReg64)context.CurrOp; - - context.EmitLdint(op.Rn); - - if (op.Rm != RegisterAlias.Zr) - { - context.EmitLdint(op.Rm); - } - else - { - context.EmitLdc_I8(offset); - } - - context.Emit(OpCodes.Add); - - context.EmitStint(op.Rn); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/InstEmitSimdMove.cs b/ChocolArm64/Instructions/InstEmitSimdMove.cs deleted file mode 100644 index 647a2238..00000000 --- a/ChocolArm64/Instructions/InstEmitSimdMove.cs +++ /dev/null @@ -1,793 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -using static ChocolArm64.Instructions.InstEmitSimdHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { -#region "Masks" - private static readonly long[] _masksE0_TrnUzpXtn = new long[] - { - 14L << 56 | 12L << 48 | 10L << 40 | 08L << 32 | 06L << 24 | 04L << 16 | 02L << 8 | 00L << 0, - 13L << 56 | 12L << 48 | 09L << 40 | 08L << 32 | 05L << 24 | 04L << 16 | 01L << 8 | 00L << 0, - 11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 03L << 24 | 02L << 16 | 01L << 8 | 00L << 0 - }; - - private static readonly long[] _masksE1_TrnUzp = new long[] - { - 15L << 56 | 13L << 48 | 11L << 40 | 09L << 32 | 07L << 24 | 05L << 16 | 03L << 8 | 01L << 0, - 15L << 56 | 14L << 48 | 11L << 40 | 10L << 32 | 07L << 24 | 06L << 16 | 03L << 8 | 02L << 0, - 15L << 56 | 14L << 48 | 13L << 40 | 12L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0 - }; - - private static readonly long[] _masksE0_Uzp = new long[] - { - 13L << 56 | 09L << 48 | 05L << 40 | 01L << 32 | 12L << 24 | 08L << 16 | 04L << 8 | 00L << 0, - 11L << 56 | 10L << 48 | 03L << 40 | 02L << 32 | 09L << 24 | 08L << 16 | 01L << 8 | 00L << 0 - }; - - private static readonly long[] _masksE1_Uzp = new long[] - { - 15L << 56 | 11L << 48 | 07L << 40 | 03L << 32 | 14L << 24 | 10L << 16 | 06L << 8 | 02L << 0, - 15L << 56 | 14L << 48 | 07L << 40 | 06L << 32 | 13L << 24 | 12L << 16 | 05L << 8 | 04L << 0 - }; -#endregion - - public static void Dup_Gp(ILEmitterCtx context) - { - OpCodeSimdIns64 op = (OpCodeSimdIns64)context.CurrOp; - - if (Optimizations.UseSse2) - { - Type[] typesSav = new Type[] { UIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdintzr(op.Rn); - - switch (op.Size) - { - case 0: context.Emit(OpCodes.Conv_U1); break; - case 1: context.Emit(OpCodes.Conv_U2); break; - case 2: context.Emit(OpCodes.Conv_U4); break; - } - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitStvec(op.Rd); - } - else - { - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - for (int index = 0; index < elems; index++) - { - context.EmitLdintzr(op.Rn); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Dup_S(ILEmitterCtx context) - { - OpCodeSimdIns64 op = (OpCodeSimdIns64)context.CurrOp; - - EmitVectorExtractZx(context, op.Rn, op.DstIndex, op.Size); - - EmitScalarSet(context, op.Rd, op.Size); - } - - public static void Dup_V(ILEmitterCtx context) - { - OpCodeSimdIns64 op = (OpCodeSimdIns64)context.CurrOp; - - if (Optimizations.UseSse2) - { - Type[] typesSav = new Type[] { UIntTypesPerSizeLog2[op.Size] }; - - EmitVectorExtractZx(context, op.Rn, op.DstIndex, op.Size); - - switch (op.Size) - { - case 0: context.Emit(OpCodes.Conv_U1); break; - case 1: context.Emit(OpCodes.Conv_U2); break; - case 2: context.Emit(OpCodes.Conv_U4); break; - } - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitStvec(op.Rd); - } - else - { - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, op.DstIndex, op.Size); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Ext_V(ILEmitterCtx context) - { - OpCodeSimdExt64 op = (OpCodeSimdExt64)context.CurrOp; - - if (Optimizations.UseSse2) - { - Type[] typesShs = new Type[] { typeof(Vector128<byte>), typeof(byte) }; - Type[] typesOr = new Type[] { typeof(Vector128<byte>), typeof(Vector128<byte>) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd64) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh))); - } - - context.EmitLdc_I4(op.Imm4); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesShs)); - - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4((op.RegisterSize == RegisterSize.Simd64 ? 8 : 16) - op.Imm4); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical128BitLane), typesShs)); - - if (op.RegisterSize == RegisterSize.Simd64) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh))); - } - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesOr)); - - context.EmitStvec(op.Rd); - } - else - { - int bytes = op.GetBitsCount() >> 3; - - int position = op.Imm4; - - for (int index = 0; index < bytes; index++) - { - int reg = op.Imm4 + index < bytes ? op.Rn : op.Rm; - - if (position == bytes) - { - position = 0; - } - - EmitVectorExtractZx(context, reg, position++, 0); - EmitVectorInsertTmp(context, index, 0); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } - - public static void Fcsel_S(ILEmitterCtx context) - { - OpCodeSimdFcond64 op = (OpCodeSimdFcond64)context.CurrOp; - - ILLabel lblTrue = new ILLabel(); - ILLabel lblEnd = new ILLabel(); - - context.EmitCondBranch(lblTrue, op.Cond); - - EmitVectorExtractF(context, op.Rm, 0, op.Size); - - context.Emit(OpCodes.Br_S, lblEnd); - - context.MarkLabel(lblTrue); - - EmitVectorExtractF(context, op.Rn, 0, op.Size); - - context.MarkLabel(lblEnd); - - EmitScalarSetF(context, op.Rd, op.Size); - } - - public static void Fmov_Ftoi(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - EmitVectorExtractZx(context, op.Rn, 0, op.Size + 2); - - context.EmitStintzr(op.Rd); - } - - public static void Fmov_Ftoi1(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - EmitVectorExtractZx(context, op.Rn, 1, 3); - - context.EmitStintzr(op.Rd); - } - - public static void Fmov_Itof(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - EmitScalarSet(context, op.Rd, op.Size + 2); - } - - public static void Fmov_Itof1(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - EmitVectorInsert(context, op.Rd, 1, 3); - } - - public static void Fmov_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - EmitVectorExtractF(context, op.Rn, 0, op.Size); - - EmitScalarSetF(context, op.Rd, op.Size); - } - - public static void Fmov_Si(ILEmitterCtx context) - { - OpCodeSimdFmov64 op = (OpCodeSimdFmov64)context.CurrOp; - - context.EmitLdc_I8(op.Imm); - - EmitScalarSet(context, op.Rd, op.Size + 2); - } - - public static void Fmov_Vi(ILEmitterCtx context) - { - OpCodeSimdImm64 op = (OpCodeSimdImm64)context.CurrOp; - - int elems = op.RegisterSize == RegisterSize.Simd128 ? 4 : 2; - - for (int index = 0; index < (elems >> op.Size); index++) - { - context.EmitLdc_I8(op.Imm); - - EmitVectorInsert(context, op.Rd, index, op.Size + 2); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Ins_Gp(ILEmitterCtx context) - { - OpCodeSimdIns64 op = (OpCodeSimdIns64)context.CurrOp; - - context.EmitLdintzr(op.Rn); - - EmitVectorInsert(context, op.Rd, op.DstIndex, op.Size); - } - - public static void Ins_V(ILEmitterCtx context) - { - OpCodeSimdIns64 op = (OpCodeSimdIns64)context.CurrOp; - - EmitVectorExtractZx(context, op.Rn, op.SrcIndex, op.Size); - - EmitVectorInsert(context, op.Rd, op.DstIndex, op.Size); - } - - public static void Movi_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - EmitMoviMvni(context, not: false); - } - else - { - EmitVectorImmUnaryOp(context, () => { }); - } - } - - public static void Mvni_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - EmitMoviMvni(context, not: true); - } - else - { - EmitVectorImmUnaryOp(context, () => context.Emit(OpCodes.Not)); - } - } - - public static void Smov_S(ILEmitterCtx context) - { - OpCodeSimdIns64 op = (OpCodeSimdIns64)context.CurrOp; - - EmitVectorExtractSx(context, op.Rn, op.DstIndex, op.Size); - - if (op.RegisterSize == RegisterSize.Simd64) - { - context.Emit(OpCodes.Conv_U4); - context.Emit(OpCodes.Conv_U8); - } - - context.EmitStintzr(op.Rd); - } - - public static void Tbl_V(ILEmitterCtx context) - { - OpCodeSimdTbl64 op = (OpCodeSimdTbl64)context.CurrOp; - - if (Optimizations.UseSsse3) - { - Type[] typesCmpSflSub = new Type[] { typeof(Vector128<sbyte>), typeof(Vector128<sbyte>) }; - Type[] typesOr = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - Type[] typesSav = new Type[] { typeof(long) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I8(0x0F0F0F0F0F0F0F0FL); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitStvectmp2(); - context.EmitLdvectmp2(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThan), typesCmpSflSub)); - - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesOr)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), typesCmpSflSub)); - - for (int index = 1; index < op.Size; index++) - { - context.EmitLdvec((op.Rn + index) & 0x1F); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I8(0x1010101010101010L * index); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSflSub)); - - context.EmitStvectmp(); - context.EmitLdvectmp(); - - context.EmitLdvectmp2(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThan), typesCmpSflSub)); - - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesOr)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), typesCmpSflSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesOr)); - } - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - context.EmitLdvec(op.Rm); - - for (int index = 0; index < op.Size; index++) - { - context.EmitLdvec((op.Rn + index) & 0x1F); - } - - switch (op.Size) - { - case 1: VectorHelper.EmitCall(context, - nameof(VectorHelper.Tbl1_V64), - nameof(VectorHelper.Tbl1_V128)); break; - - case 2: VectorHelper.EmitCall(context, - nameof(VectorHelper.Tbl2_V64), - nameof(VectorHelper.Tbl2_V128)); break; - - case 3: VectorHelper.EmitCall(context, - nameof(VectorHelper.Tbl3_V64), - nameof(VectorHelper.Tbl3_V128)); break; - - case 4: VectorHelper.EmitCall(context, - nameof(VectorHelper.Tbl4_V64), - nameof(VectorHelper.Tbl4_V128)); break; - - default: throw new InvalidOperationException(); - } - - context.EmitStvec(op.Rd); - } - } - - public static void Trn1_V(ILEmitterCtx context) - { - EmitVectorTranspose(context, part: 0); - } - - public static void Trn2_V(ILEmitterCtx context) - { - EmitVectorTranspose(context, part: 1); - } - - public static void Umov_S(ILEmitterCtx context) - { - OpCodeSimdIns64 op = (OpCodeSimdIns64)context.CurrOp; - - EmitVectorExtractZx(context, op.Rn, op.DstIndex, op.Size); - - context.EmitStintzr(op.Rd); - } - - public static void Uzp1_V(ILEmitterCtx context) - { - EmitVectorUnzip(context, part: 0); - } - - public static void Uzp2_V(ILEmitterCtx context) - { - EmitVectorUnzip(context, part: 1); - } - - public static void Xtn_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - if (Optimizations.UseSsse3) - { - Type[] typesSve = new Type[] { typeof(long), typeof(long) }; - - string nameMov = op.RegisterSize == RegisterSize.Simd128 - ? nameof(Sse.MoveLowToHigh) - : nameof(Sse.MoveHighToLow); - - context.EmitLdvec(op.Rd); - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh))); - - context.EmitLdvec(op.Rn); // value - - context.EmitLdc_I8(_masksE0_TrnUzpXtn[op.Size]); // mask - context.Emit(OpCodes.Dup); // mask - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), GetTypesSflUpk(0))); - - context.EmitCall(typeof(Sse).GetMethod(nameMov)); - - context.EmitStvec(op.Rd); - } - else - { - int elems = 8 >> op.Size; - - int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; - - if (part != 0) - { - context.EmitLdvec(op.Rd); - context.EmitStvectmp(); - } - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size + 1); - - EmitVectorInsertTmp(context, part + index, op.Size); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (part == 0) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } - - public static void Zip1_V(ILEmitterCtx context) - { - EmitVectorZip(context, part: 0); - } - - public static void Zip2_V(ILEmitterCtx context) - { - EmitVectorZip(context, part: 1); - } - - private static void EmitMoviMvni(ILEmitterCtx context, bool not) - { - OpCodeSimdImm64 op = (OpCodeSimdImm64)context.CurrOp; - - Type[] typesSav = new Type[] { UIntTypesPerSizeLog2[op.Size] }; - - long imm = op.Imm; - - if (not) - { - imm = ~imm; - } - - if (op.Size < 3) - { - context.EmitLdc_I4((int)imm); - } - else - { - context.EmitLdc_I8(imm); - } - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static void EmitVectorTranspose(ILEmitterCtx context, int part) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSsse3) - { - Type[] typesSve = new Type[] { typeof(long), typeof(long) }; - - string nameUpk = part == 0 - ? nameof(Sse2.UnpackLow) - : nameof(Sse2.UnpackHigh); - - context.EmitLdvec(op.Rn); // value - - if (op.Size < 3) - { - context.EmitLdc_I8(_masksE1_TrnUzp [op.Size]); // maskE1 - context.EmitLdc_I8(_masksE0_TrnUzpXtn[op.Size]); // maskE0 - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), GetTypesSflUpk(0))); - } - - context.EmitLdvec(op.Rm); // value - - if (op.Size < 3) - { - context.EmitLdc_I8(_masksE1_TrnUzp [op.Size]); // maskE1 - context.EmitLdc_I8(_masksE0_TrnUzpXtn[op.Size]); // maskE0 - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), GetTypesSflUpk(0))); - } - - context.EmitCall(typeof(Sse2).GetMethod(nameUpk, GetTypesSflUpk(op.Size))); - - context.EmitStvec(op.Rd); - } - else - { - int words = op.GetBitsCount() >> 4; - int pairs = words >> op.Size; - - for (int index = 0; index < pairs; index++) - { - int idx = index << 1; - - EmitVectorExtractZx(context, op.Rn, idx + part, op.Size); - EmitVectorExtractZx(context, op.Rm, idx + part, op.Size); - - EmitVectorInsertTmp(context, idx + 1, op.Size); - EmitVectorInsertTmp(context, idx, op.Size); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static void EmitVectorUnzip(ILEmitterCtx context, int part) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSsse3) - { - Type[] typesSve = new Type[] { typeof(long), typeof(long) }; - - string nameUpk = part == 0 - ? nameof(Sse2.UnpackLow) - : nameof(Sse2.UnpackHigh); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.EmitLdvec(op.Rn); // value - - if (op.Size < 3) - { - context.EmitLdc_I8(_masksE1_TrnUzp [op.Size]); // maskE1 - context.EmitLdc_I8(_masksE0_TrnUzpXtn[op.Size]); // maskE0 - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), GetTypesSflUpk(0))); - } - - context.EmitLdvec(op.Rm); // value - - if (op.Size < 3) - { - context.EmitLdc_I8(_masksE1_TrnUzp [op.Size]); // maskE1 - context.EmitLdc_I8(_masksE0_TrnUzpXtn[op.Size]); // maskE0 - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), GetTypesSflUpk(0))); - } - - context.EmitCall(typeof(Sse2).GetMethod(nameUpk, GetTypesSflUpk(3))); - - context.EmitStvec(op.Rd); - } - else - { - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), GetTypesSflUpk(op.Size))); // value - - if (op.Size < 2) - { - context.EmitLdc_I8(_masksE1_Uzp[op.Size]); // maskE1 - context.EmitLdc_I8(_masksE0_Uzp[op.Size]); // maskE0 - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), GetTypesSflUpk(0))); - } - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse2).GetMethod(nameUpk, GetTypesSflUpk(3))); - - context.EmitStvec(op.Rd); - } - } - else - { - int words = op.GetBitsCount() >> 4; - int pairs = words >> op.Size; - - for (int index = 0; index < pairs; index++) - { - int idx = index << 1; - - EmitVectorExtractZx(context, op.Rn, idx + part, op.Size); - EmitVectorExtractZx(context, op.Rm, idx + part, op.Size); - - EmitVectorInsertTmp(context, pairs + index, op.Size); - EmitVectorInsertTmp(context, index, op.Size); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } - - private static void EmitVectorZip(ILEmitterCtx context, int part) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2) - { - string nameUpk = part == 0 - ? nameof(Sse2.UnpackLow) - : nameof(Sse2.UnpackHigh); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.EmitCall(typeof(Sse2).GetMethod(nameUpk, GetTypesSflUpk(op.Size))); - } - else - { - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), GetTypesSflUpk(op.Size))); - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse2).GetMethod(nameUpk, GetTypesSflUpk(3))); - } - - context.EmitStvec(op.Rd); - } - else - { - int words = op.GetBitsCount() >> 4; - int pairs = words >> op.Size; - - int Base = part != 0 ? pairs : 0; - - for (int index = 0; index < pairs; index++) - { - int idx = index << 1; - - EmitVectorExtractZx(context, op.Rn, Base + index, op.Size); - EmitVectorExtractZx(context, op.Rm, Base + index, op.Size); - - EmitVectorInsertTmp(context, idx + 1, op.Size); - EmitVectorInsertTmp(context, idx, op.Size); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } - - private static Type[] GetTypesSflUpk(int size) - { - return new Type[] { VectorIntTypesPerSizeLog2[size], VectorIntTypesPerSizeLog2[size] }; - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitSimdShift.cs b/ChocolArm64/Instructions/InstEmitSimdShift.cs deleted file mode 100644 index 6865948a..00000000 --- a/ChocolArm64/Instructions/InstEmitSimdShift.cs +++ /dev/null @@ -1,1175 +0,0 @@ -// https://github.com/intel/ARM_NEON_2_x86_SSE/blob/master/NEON_2_SSE.h - -using ChocolArm64.Decoders; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -using static ChocolArm64.Instructions.InstEmitSimdHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { -#region "Masks" - private static readonly long[] _masks_RshrnShrn = new long[] - { - 14L << 56 | 12L << 48 | 10L << 40 | 08L << 32 | 06L << 24 | 04L << 16 | 02L << 8 | 00L << 0, - 13L << 56 | 12L << 48 | 09L << 40 | 08L << 32 | 05L << 24 | 04L << 16 | 01L << 8 | 00L << 0, - 11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 03L << 24 | 02L << 16 | 01L << 8 | 00L << 0 - }; -#endregion - - public static void Rshrn_V(ILEmitterCtx context) - { - if (Optimizations.UseSsse3) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - Type[] typesAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], VectorUIntTypesPerSizeLog2[op.Size + 1] }; - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], typeof(byte) }; - Type[] typesSfl = new Type[] { typeof(Vector128<sbyte>), typeof(Vector128<sbyte>) }; - Type[] typesSav = new Type[] { UIntTypesPerSizeLog2[op.Size + 1] }; - Type[] typesSve = new Type[] { typeof(long), typeof(long) }; - - string nameMov = op.RegisterSize == RegisterSize.Simd128 - ? nameof(Sse.MoveLowToHigh) - : nameof(Sse.MoveHighToLow); - - int shift = GetImmShr(op); - - long roundConst = 1L << (shift - 1); - - context.EmitLdvec(op.Rd); - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh))); - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I8(roundConst); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitLdc_I4(shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrl)); // value - - context.EmitLdc_I8(_masks_RshrnShrn[op.Size]); // mask - context.Emit(OpCodes.Dup); // mask - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse).GetMethod(nameMov)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorShrImmNarrowOpZx(context, round: true); - } - } - - public static void Shl_S(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - int shift = GetImmShl(op); - - EmitScalarUnaryOpZx(context, () => - { - context.EmitLdc_I4(shift); - - context.Emit(OpCodes.Shl); - }); - } - - public static void Shl_V(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - int shift = GetImmShl(op); - - if (Optimizations.UseSse2 && op.Size > 0) - { - Type[] typesSll = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesSll)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorUnaryOpZx(context, () => - { - context.EmitLdc_I4(shift); - - context.Emit(OpCodes.Shl); - }); - } - } - - public static void Shll_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int shift = 8 << op.Size; - - if (Optimizations.UseSse41) - { - Type[] typesSll = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSll)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitLdc_I4(shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesSll)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorShImmWidenBinaryZx(context, () => context.Emit(OpCodes.Shl), shift); - } - } - - public static void Shrn_V(ILEmitterCtx context) - { - if (Optimizations.UseSsse3) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], typeof(byte) }; - Type[] typesSfl = new Type[] { typeof(Vector128<sbyte>), typeof(Vector128<sbyte>) }; - Type[] typesSve = new Type[] { typeof(long), typeof(long) }; - - string nameMov = op.RegisterSize == RegisterSize.Simd128 - ? nameof(Sse.MoveLowToHigh) - : nameof(Sse.MoveHighToLow); - - int shift = GetImmShr(op); - - context.EmitLdvec(op.Rd); - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh))); - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrl)); // value - - context.EmitLdc_I8(_masks_RshrnShrn[op.Size]); // mask - context.Emit(OpCodes.Dup); // mask - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); - - context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse).GetMethod(nameMov)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorShrImmNarrowOpZx(context, round: false); - } - } - - public static void Sli_V(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - int shift = GetImmShl(op); - - ulong mask = shift != 0 ? ulong.MaxValue >> (64 - shift) : 0; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size); - - context.EmitLdc_I4(shift); - - context.Emit(OpCodes.Shl); - - EmitVectorExtractZx(context, op.Rd, index, op.Size); - - context.EmitLdc_I8((long)mask); - - context.Emit(OpCodes.And); - context.Emit(OpCodes.Or); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Sqrshl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractSx(context, op.Rn, index, op.Size); - EmitVectorExtractSx(context, op.Rm, index, op.Size); - - context.Emit(OpCodes.Ldc_I4_1); - context.EmitLdc_I4(op.Size); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - SoftFallback.EmitCall(context, nameof(SoftFallback.SignedShlRegSatQ)); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Sqrshrn_S(ILEmitterCtx context) - { - EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxSx); - } - - public static void Sqrshrn_V(ILEmitterCtx context) - { - EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxSx); - } - - public static void Sqrshrun_S(ILEmitterCtx context) - { - EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxZx); - } - - public static void Sqrshrun_V(ILEmitterCtx context) - { - EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx); - } - - public static void Sqshl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractSx(context, op.Rn, index, op.Size); - EmitVectorExtractSx(context, op.Rm, index, op.Size); - - context.Emit(OpCodes.Ldc_I4_0); - context.EmitLdc_I4(op.Size); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - SoftFallback.EmitCall(context, nameof(SoftFallback.SignedShlRegSatQ)); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Sqshrn_S(ILEmitterCtx context) - { - EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxSx); - } - - public static void Sqshrn_V(ILEmitterCtx context) - { - EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxSx); - } - - public static void Sqshrun_S(ILEmitterCtx context) - { - EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxZx); - } - - public static void Sqshrun_V(ILEmitterCtx context) - { - EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx); - } - - public static void Srshl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractSx(context, op.Rn, index, op.Size); - EmitVectorExtractSx(context, op.Rm, index, op.Size); - - context.Emit(OpCodes.Ldc_I4_1); - context.EmitLdc_I4(op.Size); - - SoftFallback.EmitCall(context, nameof(SoftFallback.SignedShlReg)); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Srshr_S(ILEmitterCtx context) - { - EmitScalarShrImmOpSx(context, ShrImmFlags.Round); - } - - public static void Srshr_V(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3) - { - Type[] typesShs = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAdd = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - int shift = GetImmShr(op); - int eSize = 8 << op.Size; - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(eSize - shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesShs)); - - context.EmitLdc_I4(eSize - 1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesShs)); - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), typesShs)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorShrImmOpSx(context, ShrImmFlags.Round); - } - } - - public static void Srsra_S(ILEmitterCtx context) - { - EmitScalarShrImmOpSx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate); - } - - public static void Srsra_V(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3) - { - Type[] typesShs = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAdd = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - int shift = GetImmShr(op); - int eSize = 8 << op.Size; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(eSize - shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesShs)); - - context.EmitLdc_I4(eSize - 1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesShs)); - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), typesShs)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorShrImmOpSx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate); - } - } - - public static void Sshl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractSx(context, op.Rn, index, op.Size); - EmitVectorExtractSx(context, op.Rm, index, op.Size); - - context.Emit(OpCodes.Ldc_I4_0); - context.EmitLdc_I4(op.Size); - - SoftFallback.EmitCall(context, nameof(SoftFallback.SignedShlReg)); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Sshll_V(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - int shift = GetImmShl(op); - - if (Optimizations.UseSse41) - { - Type[] typesSll = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSll)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - if (shift != 0) - { - context.EmitLdc_I4(shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesSll)); - } - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorShImmWidenBinarySx(context, () => context.Emit(OpCodes.Shl), shift); - } - } - - public static void Sshr_S(ILEmitterCtx context) - { - EmitShrImmOp(context, ShrImmFlags.ScalarSx); - } - - public static void Sshr_V(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3) - { - Type[] typesSra = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(GetImmShr(op)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), typesSra)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitShrImmOp(context, ShrImmFlags.VectorSx); - } - } - - public static void Ssra_S(ILEmitterCtx context) - { - EmitScalarShrImmOpSx(context, ShrImmFlags.Accumulate); - } - - public static void Ssra_V(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3) - { - Type[] typesSra = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAdd = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(GetImmShr(op)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), typesSra)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorShrImmOpSx(context, ShrImmFlags.Accumulate); - } - } - - public static void Uqrshl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size); - EmitVectorExtractZx(context, op.Rm, index, op.Size); - - context.Emit(OpCodes.Ldc_I4_1); - context.EmitLdc_I4(op.Size); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - SoftFallback.EmitCall(context, nameof(SoftFallback.UnsignedShlRegSatQ)); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Uqrshrn_S(ILEmitterCtx context) - { - EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx); - } - - public static void Uqrshrn_V(ILEmitterCtx context) - { - EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx); - } - - public static void Uqshl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size); - EmitVectorExtractZx(context, op.Rm, index, op.Size); - - context.Emit(OpCodes.Ldc_I4_0); - context.EmitLdc_I4(op.Size); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - SoftFallback.EmitCall(context, nameof(SoftFallback.UnsignedShlRegSatQ)); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Uqshrn_S(ILEmitterCtx context) - { - EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx); - } - - public static void Uqshrn_V(ILEmitterCtx context) - { - EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx); - } - - public static void Urshl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size); - EmitVectorExtractZx(context, op.Rm, index, op.Size); - - context.Emit(OpCodes.Ldc_I4_1); - context.EmitLdc_I4(op.Size); - - SoftFallback.EmitCall(context, nameof(SoftFallback.UnsignedShlReg)); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Urshr_S(ILEmitterCtx context) - { - EmitScalarShrImmOpZx(context, ShrImmFlags.Round); - } - - public static void Urshr_V(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size > 0) - { - Type[] typesShs = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - int shift = GetImmShr(op); - int eSize = 8 << op.Size; - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(eSize - shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesShs)); - - context.EmitLdc_I4(eSize - 1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesShs)); - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesShs)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorShrImmOpZx(context, ShrImmFlags.Round); - } - } - - public static void Ursra_S(ILEmitterCtx context) - { - EmitScalarShrImmOpZx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate); - } - - public static void Ursra_V(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size > 0) - { - Type[] typesShs = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - int shift = GetImmShr(op); - int eSize = 8 << op.Size; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(eSize - shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesShs)); - - context.EmitLdc_I4(eSize - 1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesShs)); - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesShs)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorShrImmOpZx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate); - } - } - - public static void Ushl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size); - EmitVectorExtractZx(context, op.Rm, index, op.Size); - - context.Emit(OpCodes.Ldc_I4_0); - context.EmitLdc_I4(op.Size); - - SoftFallback.EmitCall(context, nameof(SoftFallback.UnsignedShlReg)); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Ushll_V(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - int shift = GetImmShl(op); - - if (Optimizations.UseSse41) - { - Type[] typesSll = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSll)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - if (shift != 0) - { - context.EmitLdc_I4(shift); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesSll)); - } - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorShImmWidenBinaryZx(context, () => context.Emit(OpCodes.Shl), shift); - } - } - - public static void Ushr_S(ILEmitterCtx context) - { - EmitShrImmOp(context, ShrImmFlags.ScalarZx); - } - - public static void Ushr_V(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size > 0) - { - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(GetImmShr(op)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrl)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitShrImmOp(context, ShrImmFlags.VectorZx); - } - } - - public static void Usra_S(ILEmitterCtx context) - { - EmitScalarShrImmOpZx(context, ShrImmFlags.Accumulate); - } - - public static void Usra_V(ILEmitterCtx context) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size > 0) - { - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - context.EmitLdc_I4(GetImmShr(op)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrl)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorShrImmOpZx(context, ShrImmFlags.Accumulate); - } - } - - [Flags] - private enum ShrImmFlags - { - Scalar = 1 << 0, - Signed = 1 << 1, - - Round = 1 << 2, - Accumulate = 1 << 3, - - ScalarSx = Scalar | Signed, - ScalarZx = Scalar, - - VectorSx = Signed, - VectorZx = 0 - } - - private static void EmitScalarShrImmOpSx(ILEmitterCtx context, ShrImmFlags flags) - { - EmitShrImmOp(context, ShrImmFlags.ScalarSx | flags); - } - - private static void EmitScalarShrImmOpZx(ILEmitterCtx context, ShrImmFlags flags) - { - EmitShrImmOp(context, ShrImmFlags.ScalarZx | flags); - } - - private static void EmitVectorShrImmOpSx(ILEmitterCtx context, ShrImmFlags flags) - { - EmitShrImmOp(context, ShrImmFlags.VectorSx | flags); - } - - private static void EmitVectorShrImmOpZx(ILEmitterCtx context, ShrImmFlags flags) - { - EmitShrImmOp(context, ShrImmFlags.VectorZx | flags); - } - - private static void EmitShrImmOp(ILEmitterCtx context, ShrImmFlags flags) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - bool scalar = (flags & ShrImmFlags.Scalar) != 0; - bool signed = (flags & ShrImmFlags.Signed) != 0; - bool round = (flags & ShrImmFlags.Round) != 0; - bool accumulate = (flags & ShrImmFlags.Accumulate) != 0; - - int shift = GetImmShr(op); - - long roundConst = 1L << (shift - 1); - - int bytes = op.GetBitsCount() >> 3; - int elems = !scalar ? bytes >> op.Size : 1; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtract(context, op.Rn, index, op.Size, signed); - - if (op.Size <= 2) - { - if (round) - { - context.EmitLdc_I8(roundConst); - - context.Emit(OpCodes.Add); - } - - context.EmitLdc_I4(shift); - - context.Emit(signed ? OpCodes.Shr : OpCodes.Shr_Un); - } - else /* if (op.Size == 3) */ - { - EmitShrImm64(context, signed, round ? roundConst : 0L, shift); - } - - if (accumulate) - { - EmitVectorExtract(context, op.Rd, index, op.Size, signed); - - context.Emit(OpCodes.Add); - } - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if ((op.RegisterSize == RegisterSize.Simd64) || scalar) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static void EmitVectorShrImmNarrowOpZx(ILEmitterCtx context, bool round) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - int shift = GetImmShr(op); - - long roundConst = 1L << (shift - 1); - - int elems = 8 >> op.Size; - - int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; - - if (part != 0) - { - context.EmitLdvec(op.Rd); - context.EmitStvectmp(); - } - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size + 1); - - if (round) - { - context.EmitLdc_I8(roundConst); - - context.Emit(OpCodes.Add); - } - - context.EmitLdc_I4(shift); - - context.Emit(OpCodes.Shr_Un); - - EmitVectorInsertTmp(context, part + index, op.Size); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (part == 0) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - [Flags] - private enum ShrImmSaturatingNarrowFlags - { - Scalar = 1 << 0, - SignedSrc = 1 << 1, - SignedDst = 1 << 2, - - Round = 1 << 3, - - ScalarSxSx = Scalar | SignedSrc | SignedDst, - ScalarSxZx = Scalar | SignedSrc, - ScalarZxZx = Scalar, - - VectorSxSx = SignedSrc | SignedDst, - VectorSxZx = SignedSrc, - VectorZxZx = 0 - } - - private static void EmitRoundShrImmSaturatingNarrowOp(ILEmitterCtx context, ShrImmSaturatingNarrowFlags flags) - { - EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.Round | flags); - } - - private static void EmitShrImmSaturatingNarrowOp(ILEmitterCtx context, ShrImmSaturatingNarrowFlags flags) - { - OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; - - bool scalar = (flags & ShrImmSaturatingNarrowFlags.Scalar) != 0; - bool signedSrc = (flags & ShrImmSaturatingNarrowFlags.SignedSrc) != 0; - bool signedDst = (flags & ShrImmSaturatingNarrowFlags.SignedDst) != 0; - bool round = (flags & ShrImmSaturatingNarrowFlags.Round) != 0; - - int shift = GetImmShr(op); - - long roundConst = 1L << (shift - 1); - - int elems = !scalar ? 8 >> op.Size : 1; - - int part = !scalar && (op.RegisterSize == RegisterSize.Simd128) ? elems : 0; - - if (scalar) - { - EmitVectorZeroLowerTmp(context); - } - - if (part != 0) - { - context.EmitLdvec(op.Rd); - context.EmitStvectmp(); - } - - for (int index = 0; index < elems; index++) - { - EmitVectorExtract(context, op.Rn, index, op.Size + 1, signedSrc); - - if (op.Size <= 1 || !round) - { - if (round) - { - context.EmitLdc_I8(roundConst); - - context.Emit(OpCodes.Add); - } - - context.EmitLdc_I4(shift); - - context.Emit(signedSrc ? OpCodes.Shr : OpCodes.Shr_Un); - } - else /* if (op.Size == 2 && round) */ - { - EmitShrImm64(context, signedSrc, roundConst, shift); // shift <= 32 - } - - EmitSatQ(context, op.Size, signedSrc, signedDst); - - EmitVectorInsertTmp(context, part + index, op.Size); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (part == 0) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - // dst64 = (Int(src64, signed) + roundConst) >> shift; - private static void EmitShrImm64(ILEmitterCtx context, bool signed, long roundConst, int shift) - { - context.EmitLdc_I8(roundConst); - context.EmitLdc_I4(shift); - - SoftFallback.EmitCall(context, signed - ? nameof(SoftFallback.SignedShrImm64) - : nameof(SoftFallback.UnsignedShrImm64)); - } - - private static void EmitVectorShImmWidenBinarySx(ILEmitterCtx context, Action emit, int imm) - { - EmitVectorShImmWidenBinaryOp(context, emit, imm, true); - } - - private static void EmitVectorShImmWidenBinaryZx(ILEmitterCtx context, Action emit, int imm) - { - EmitVectorShImmWidenBinaryOp(context, emit, imm, false); - } - - private static void EmitVectorShImmWidenBinaryOp(ILEmitterCtx context, Action emit, int imm, bool signed) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int elems = 8 >> op.Size; - - int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtract(context, op.Rn, part + index, op.Size, signed); - - context.EmitLdc_I4(imm); - - emit(); - - EmitVectorInsertTmp(context, index, op.Size + 1); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitSystem.cs b/ChocolArm64/Instructions/InstEmitSystem.cs deleted file mode 100644 index ac264de9..00000000 --- a/ChocolArm64/Instructions/InstEmitSystem.cs +++ /dev/null @@ -1,137 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection; -using System.Reflection.Emit; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Hint(ILEmitterCtx context) - { - // Execute as no-op. - } - - public static void Isb(ILEmitterCtx context) - { - // Execute as no-op. - } - - public static void Mrs(ILEmitterCtx context) - { - OpCodeSystem64 op = (OpCodeSystem64)context.CurrOp; - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - string propName; - - switch (GetPackedId(op)) - { - case 0b11_011_0000_0000_001: propName = nameof(CpuThreadState.CtrEl0); break; - case 0b11_011_0000_0000_111: propName = nameof(CpuThreadState.DczidEl0); break; - case 0b11_011_0100_0100_000: propName = nameof(CpuThreadState.CFpcr); break; - case 0b11_011_0100_0100_001: propName = nameof(CpuThreadState.CFpsr); break; - case 0b11_011_1101_0000_010: propName = nameof(CpuThreadState.TpidrEl0); break; - case 0b11_011_1101_0000_011: propName = nameof(CpuThreadState.Tpidr); break; - case 0b11_011_1110_0000_000: propName = nameof(CpuThreadState.CntfrqEl0); break; - case 0b11_011_1110_0000_001: propName = nameof(CpuThreadState.CntpctEl0); break; - - default: throw new NotImplementedException($"Unknown MRS at {op.Position:x16}"); - } - - context.EmitCallPropGet(typeof(CpuThreadState), propName); - - PropertyInfo propInfo = typeof(CpuThreadState).GetProperty(propName); - - if (propInfo.PropertyType != typeof(long) && - propInfo.PropertyType != typeof(ulong)) - { - context.Emit(OpCodes.Conv_U8); - } - - context.EmitStintzr(op.Rt); - } - - public static void Msr(ILEmitterCtx context) - { - OpCodeSystem64 op = (OpCodeSystem64)context.CurrOp; - - context.EmitLdarg(TranslatedSub.StateArgIdx); - context.EmitLdintzr(op.Rt); - - string propName; - - switch (GetPackedId(op)) - { - case 0b11_011_0100_0100_000: propName = nameof(CpuThreadState.CFpcr); break; - case 0b11_011_0100_0100_001: propName = nameof(CpuThreadState.CFpsr); break; - case 0b11_011_1101_0000_010: propName = nameof(CpuThreadState.TpidrEl0); break; - - default: throw new NotImplementedException($"Unknown MSR at {op.Position:x16}"); - } - - PropertyInfo propInfo = typeof(CpuThreadState).GetProperty(propName); - - if (propInfo.PropertyType != typeof(long) && - propInfo.PropertyType != typeof(ulong)) - { - context.Emit(OpCodes.Conv_U4); - } - - context.EmitCallPropSet(typeof(CpuThreadState), propName); - } - - public static void Nop(ILEmitterCtx context) - { - // Do nothing. - } - - public static void Sys(ILEmitterCtx context) - { - // This instruction is used to do some operations on the CPU like cache invalidation, - // address translation and the like. - // We treat it as no-op here since we don't have any cache being emulated anyway. - OpCodeSystem64 op = (OpCodeSystem64)context.CurrOp; - - switch (GetPackedId(op)) - { - case 0b11_011_0111_0100_001: - { - // DC ZVA - for (int offs = 0; offs < (4 << CpuThreadState.DczSizeLog2); offs += 8) - { - context.EmitLdintzr(op.Rt); - context.EmitLdc_I(offs); - - context.Emit(OpCodes.Add); - - context.EmitLdc_I8(0); - - InstEmitMemoryHelper.EmitWriteCall(context, 3); - } - - break; - } - - // No-op - case 0b11_011_0111_1110_001: //DC CIVAC - break; - } - } - - private static int GetPackedId(OpCodeSystem64 op) - { - int id; - - id = op.Op2 << 0; - id |= op.CRm << 3; - id |= op.CRn << 7; - id |= op.Op1 << 11; - id |= op.Op0 << 14; - - return id; - } - } -} diff --git a/ChocolArm64/Instructions/InstEmitter.cs b/ChocolArm64/Instructions/InstEmitter.cs deleted file mode 100644 index db6e8604..00000000 --- a/ChocolArm64/Instructions/InstEmitter.cs +++ /dev/null @@ -1,6 +0,0 @@ -using ChocolArm64.Translation; - -namespace ChocolArm64.Instructions -{ - delegate void InstEmitter(ILEmitterCtx context); -}
\ No newline at end of file diff --git a/ChocolArm64/Instructions/SoftFallback.cs b/ChocolArm64/Instructions/SoftFallback.cs deleted file mode 100644 index 16638894..00000000 --- a/ChocolArm64/Instructions/SoftFallback.cs +++ /dev/null @@ -1,1194 +0,0 @@ -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Runtime.CompilerServices; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -namespace ChocolArm64.Instructions -{ - using static VectorHelper; - - static class SoftFallback - { - public static void EmitCall(ILEmitterCtx context, string mthdName) - { - context.EmitCall(typeof(SoftFallback), mthdName); - } - -#region "ShlReg" - public static long SignedShlReg(long value, long shift, bool round, int size) - { - int eSize = 8 << size; - - int shiftLsB = (sbyte)shift; - - if (shiftLsB < 0) - { - return SignedShrReg(value, -shiftLsB, round, eSize); - } - else if (shiftLsB > 0) - { - if (shiftLsB >= eSize) - { - return 0L; - } - - return value << shiftLsB; - } - else /* if (shiftLsB == 0) */ - { - return value; - } - } - - public static ulong UnsignedShlReg(ulong value, ulong shift, bool round, int size) - { - int eSize = 8 << size; - - int shiftLsB = (sbyte)shift; - - if (shiftLsB < 0) - { - return UnsignedShrReg(value, -shiftLsB, round, eSize); - } - else if (shiftLsB > 0) - { - if (shiftLsB >= eSize) - { - return 0UL; - } - - return value << shiftLsB; - } - else /* if (shiftLsB == 0) */ - { - return value; - } - } - - public static long SignedShlRegSatQ(long value, long shift, bool round, int size, CpuThreadState state) - { - int eSize = 8 << size; - - int shiftLsB = (sbyte)shift; - - if (shiftLsB < 0) - { - return SignedShrReg(value, -shiftLsB, round, eSize); - } - else if (shiftLsB > 0) - { - if (shiftLsB >= eSize) - { - return SignedSignSatQ(value, eSize, state); - } - - if (eSize == 64) - { - long shl = value << shiftLsB; - long shr = shl >> shiftLsB; - - if (shr != value) - { - return SignedSignSatQ(value, eSize, state); - } - else /* if (shr == value) */ - { - return shl; - } - } - else /* if (eSize != 64) */ - { - return SignedSrcSignedDstSatQ(value << shiftLsB, size, state); - } - } - else /* if (shiftLsB == 0) */ - { - return value; - } - } - - public static ulong UnsignedShlRegSatQ(ulong value, ulong shift, bool round, int size, CpuThreadState state) - { - int eSize = 8 << size; - - int shiftLsB = (sbyte)shift; - - if (shiftLsB < 0) - { - return UnsignedShrReg(value, -shiftLsB, round, eSize); - } - else if (shiftLsB > 0) - { - if (shiftLsB >= eSize) - { - return UnsignedSignSatQ(value, eSize, state); - } - - if (eSize == 64) - { - ulong shl = value << shiftLsB; - ulong shr = shl >> shiftLsB; - - if (shr != value) - { - return UnsignedSignSatQ(value, eSize, state); - } - else /* if (shr == value) */ - { - return shl; - } - } - else /* if (eSize != 64) */ - { - return UnsignedSrcUnsignedDstSatQ(value << shiftLsB, size, state); - } - } - else /* if (shiftLsB == 0) */ - { - return value; - } - } - - private static long SignedShrReg(long value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}. - { - if (round) - { - if (shift >= eSize) - { - return 0L; - } - - long roundConst = 1L << (shift - 1); - - long add = value + roundConst; - - if (eSize == 64) - { - if ((~value & (value ^ add)) < 0L) - { - return (long)((ulong)add >> shift); - } - else - { - return add >> shift; - } - } - else /* if (eSize != 64) */ - { - return add >> shift; - } - } - else /* if (!round) */ - { - if (shift >= eSize) - { - if (value < 0L) - { - return -1L; - } - else /* if (value >= 0L) */ - { - return 0L; - } - } - - return value >> shift; - } - } - - private static ulong UnsignedShrReg(ulong value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}. - { - if (round) - { - if (shift > 64) - { - return 0UL; - } - - ulong roundConst = 1UL << (shift - 1); - - ulong add = value + roundConst; - - if (eSize == 64) - { - if ((add < value) && (add < roundConst)) - { - if (shift == 64) - { - return 1UL; - } - - return (add >> shift) | (0x8000000000000000UL >> (shift - 1)); - } - else - { - if (shift == 64) - { - return 0UL; - } - - return add >> shift; - } - } - else /* if (eSize != 64) */ - { - if (shift == 64) - { - return 0UL; - } - - return add >> shift; - } - } - else /* if (!round) */ - { - if (shift >= eSize) - { - return 0UL; - } - - return value >> shift; - } - } - - private static long SignedSignSatQ(long op, int eSize, CpuThreadState state) // eSize := {8, 16, 32, 64}. - { - long tMaxValue = (1L << (eSize - 1)) - 1L; - long tMinValue = -(1L << (eSize - 1)); - - if (op > 0L) - { - state.SetFpsrFlag(Fpsr.Qc); - - return tMaxValue; - } - else if (op < 0L) - { - state.SetFpsrFlag(Fpsr.Qc); - - return tMinValue; - } - else - { - return 0L; - } - } - - private static ulong UnsignedSignSatQ(ulong op, int eSize, CpuThreadState state) // eSize := {8, 16, 32, 64}. - { - ulong tMaxValue = ulong.MaxValue >> (64 - eSize); - - if (op > 0UL) - { - state.SetFpsrFlag(Fpsr.Qc); - - return tMaxValue; - } - else - { - return 0UL; - } - } -#endregion - -#region "ShrImm64" - public static long SignedShrImm64(long value, long roundConst, int shift) - { - if (roundConst == 0L) - { - if (shift <= 63) - { - return value >> shift; - } - else /* if (shift == 64) */ - { - if (value < 0L) - { - return -1L; - } - else /* if (value >= 0L) */ - { - return 0L; - } - } - } - else /* if (roundConst == 1L << (shift - 1)) */ - { - if (shift <= 63) - { - long add = value + roundConst; - - if ((~value & (value ^ add)) < 0L) - { - return (long)((ulong)add >> shift); - } - else - { - return add >> shift; - } - } - else /* if (shift == 64) */ - { - return 0L; - } - } - } - - public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift) - { - if (roundConst == 0L) - { - if (shift <= 63) - { - return value >> shift; - } - else /* if (shift == 64) */ - { - return 0UL; - } - } - else /* if (roundConst == 1L << (shift - 1)) */ - { - ulong add = value + (ulong)roundConst; - - if ((add < value) && (add < (ulong)roundConst)) - { - if (shift <= 63) - { - return (add >> shift) | (0x8000000000000000UL >> (shift - 1)); - } - else /* if (shift == 64) */ - { - return 1UL; - } - } - else - { - if (shift <= 63) - { - return add >> shift; - } - else /* if (shift == 64) */ - { - return 0UL; - } - } - } - } -#endregion - -#region "Saturating" - public static long SignedSrcSignedDstSatQ(long op, int size, CpuThreadState state) - { - int eSize = 8 << size; - - long tMaxValue = (1L << (eSize - 1)) - 1L; - long tMinValue = -(1L << (eSize - 1)); - - if (op > tMaxValue) - { - state.SetFpsrFlag(Fpsr.Qc); - - return tMaxValue; - } - else if (op < tMinValue) - { - state.SetFpsrFlag(Fpsr.Qc); - - return tMinValue; - } - else - { - return op; - } - } - - public static ulong SignedSrcUnsignedDstSatQ(long op, int size, CpuThreadState state) - { - int eSize = 8 << size; - - ulong tMaxValue = (1UL << eSize) - 1UL; - ulong tMinValue = 0UL; - - if (op > (long)tMaxValue) - { - state.SetFpsrFlag(Fpsr.Qc); - - return tMaxValue; - } - else if (op < (long)tMinValue) - { - state.SetFpsrFlag(Fpsr.Qc); - - return tMinValue; - } - else - { - return (ulong)op; - } - } - - public static long UnsignedSrcSignedDstSatQ(ulong op, int size, CpuThreadState state) - { - int eSize = 8 << size; - - long tMaxValue = (1L << (eSize - 1)) - 1L; - - if (op > (ulong)tMaxValue) - { - state.SetFpsrFlag(Fpsr.Qc); - - return tMaxValue; - } - else - { - return (long)op; - } - } - - public static ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size, CpuThreadState state) - { - int eSize = 8 << size; - - ulong tMaxValue = (1UL << eSize) - 1UL; - - if (op > tMaxValue) - { - state.SetFpsrFlag(Fpsr.Qc); - - return tMaxValue; - } - else - { - return op; - } - } - - public static long UnarySignedSatQAbsOrNeg(long op, CpuThreadState state) - { - if (op == long.MinValue) - { - state.SetFpsrFlag(Fpsr.Qc); - - return long.MaxValue; - } - else - { - return op; - } - } - - public static long BinarySignedSatQAdd(long op1, long op2, CpuThreadState state) - { - long add = op1 + op2; - - if ((~(op1 ^ op2) & (op1 ^ add)) < 0L) - { - state.SetFpsrFlag(Fpsr.Qc); - - if (op1 < 0L) - { - return long.MinValue; - } - else - { - return long.MaxValue; - } - } - else - { - return add; - } - } - - public static ulong BinaryUnsignedSatQAdd(ulong op1, ulong op2, CpuThreadState state) - { - ulong add = op1 + op2; - - if ((add < op1) && (add < op2)) - { - state.SetFpsrFlag(Fpsr.Qc); - - return ulong.MaxValue; - } - else - { - return add; - } - } - - public static long BinarySignedSatQSub(long op1, long op2, CpuThreadState state) - { - long sub = op1 - op2; - - if (((op1 ^ op2) & (op1 ^ sub)) < 0L) - { - state.SetFpsrFlag(Fpsr.Qc); - - if (op1 < 0L) - { - return long.MinValue; - } - else - { - return long.MaxValue; - } - } - else - { - return sub; - } - } - - public static ulong BinaryUnsignedSatQSub(ulong op1, ulong op2, CpuThreadState state) - { - ulong sub = op1 - op2; - - if (op1 < op2) - { - state.SetFpsrFlag(Fpsr.Qc); - - return ulong.MinValue; - } - else - { - return sub; - } - } - - public static long BinarySignedSatQAcc(ulong op1, long op2, CpuThreadState state) - { - if (op1 <= (ulong)long.MaxValue) - { - // op1 from ulong.MinValue to (ulong)long.MaxValue - // op2 from long.MinValue to long.MaxValue - - long add = (long)op1 + op2; - - if ((~op2 & add) < 0L) - { - state.SetFpsrFlag(Fpsr.Qc); - - return long.MaxValue; - } - else - { - return add; - } - } - else if (op2 >= 0L) - { - // op1 from (ulong)long.MaxValue + 1UL to ulong.MaxValue - // op2 from (long)ulong.MinValue to long.MaxValue - - state.SetFpsrFlag(Fpsr.Qc); - - return long.MaxValue; - } - else - { - // op1 from (ulong)long.MaxValue + 1UL to ulong.MaxValue - // op2 from long.MinValue to (long)ulong.MinValue - 1L - - ulong add = op1 + (ulong)op2; - - if (add > (ulong)long.MaxValue) - { - state.SetFpsrFlag(Fpsr.Qc); - - return long.MaxValue; - } - else - { - return (long)add; - } - } - } - - public static ulong BinaryUnsignedSatQAcc(long op1, ulong op2, CpuThreadState state) - { - if (op1 >= 0L) - { - // op1 from (long)ulong.MinValue to long.MaxValue - // op2 from ulong.MinValue to ulong.MaxValue - - ulong add = (ulong)op1 + op2; - - if ((add < (ulong)op1) && (add < op2)) - { - state.SetFpsrFlag(Fpsr.Qc); - - return ulong.MaxValue; - } - else - { - return add; - } - } - else if (op2 > (ulong)long.MaxValue) - { - // op1 from long.MinValue to (long)ulong.MinValue - 1L - // op2 from (ulong)long.MaxValue + 1UL to ulong.MaxValue - - return (ulong)op1 + op2; - } - else - { - // op1 from long.MinValue to (long)ulong.MinValue - 1L - // op2 from ulong.MinValue to (ulong)long.MaxValue - - long add = op1 + (long)op2; - - if (add < (long)ulong.MinValue) - { - state.SetFpsrFlag(Fpsr.Qc); - - return ulong.MinValue; - } - else - { - return (ulong)add; - } - } - } -#endregion - -#region "Count" - public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.). - { - value ^= value >> 1; - - int highBit = size - 2; - - for (int bit = highBit; bit >= 0; bit--) - { - if (((int)(value >> bit) & 0b1) != 0) - { - return (ulong)(highBit - bit); - } - } - - return (ulong)(size - 1); - } - - private static readonly byte[] ClzNibbleTbl = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; - - public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.). - { - if (value == 0ul) - { - return (ulong)size; - } - - int nibbleIdx = size; - int preCount, count = 0; - - do - { - nibbleIdx -= 4; - preCount = ClzNibbleTbl[(int)(value >> nibbleIdx) & 0b1111]; - count += preCount; - } - while (preCount == 4); - - return (ulong)count; - } - - public static ulong CountSetBits8(ulong value) // "size" is 8 (SIMD&FP Inst.). - { - value = ((value >> 1) & 0x55ul) + (value & 0x55ul); - value = ((value >> 2) & 0x33ul) + (value & 0x33ul); - - return (value >> 4) + (value & 0x0ful); - } -#endregion - -#region "Crc32" - private const uint Crc32RevPoly = 0xedb88320; - private const uint Crc32CRevPoly = 0x82f63b78; - - public static uint Crc32B(uint crc, byte val) => Crc32 (crc, Crc32RevPoly, val); - public static uint Crc32H(uint crc, ushort val) => Crc32H(crc, Crc32RevPoly, val); - public static uint Crc32W(uint crc, uint val) => Crc32W(crc, Crc32RevPoly, val); - public static uint Crc32X(uint crc, ulong val) => Crc32X(crc, Crc32RevPoly, val); - - public static uint Crc32Cb(uint crc, byte val) => Crc32 (crc, Crc32CRevPoly, val); - public static uint Crc32Ch(uint crc, ushort val) => Crc32H(crc, Crc32CRevPoly, val); - public static uint Crc32Cw(uint crc, uint val) => Crc32W(crc, Crc32CRevPoly, val); - public static uint Crc32Cx(uint crc, ulong val) => Crc32X(crc, Crc32CRevPoly, val); - - private static uint Crc32H(uint crc, uint poly, ushort val) - { - crc = Crc32(crc, poly, (byte)(val >> 0)); - crc = Crc32(crc, poly, (byte)(val >> 8)); - - return crc; - } - - private static uint Crc32W(uint crc, uint poly, uint val) - { - crc = Crc32(crc, poly, (byte)(val >> 0 )); - crc = Crc32(crc, poly, (byte)(val >> 8 )); - crc = Crc32(crc, poly, (byte)(val >> 16)); - crc = Crc32(crc, poly, (byte)(val >> 24)); - - return crc; - } - - private static uint Crc32X(uint crc, uint poly, ulong val) - { - crc = Crc32(crc, poly, (byte)(val >> 0 )); - crc = Crc32(crc, poly, (byte)(val >> 8 )); - crc = Crc32(crc, poly, (byte)(val >> 16)); - crc = Crc32(crc, poly, (byte)(val >> 24)); - crc = Crc32(crc, poly, (byte)(val >> 32)); - crc = Crc32(crc, poly, (byte)(val >> 40)); - crc = Crc32(crc, poly, (byte)(val >> 48)); - crc = Crc32(crc, poly, (byte)(val >> 56)); - - return crc; - } - - private static uint Crc32(uint crc, uint poly, byte val) - { - crc ^= val; - - for (int bit = 7; bit >= 0; bit--) - { - uint mask = (uint)(-(int)(crc & 1)); - - crc = (crc >> 1) ^ (poly & mask); - } - - return crc; - } -#endregion - -#region "Aes" - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> Decrypt(Vector128<float> value, Vector128<float> roundKey) - { - if (!Sse.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(Sse.Xor(value, roundKey))); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> Encrypt(Vector128<float> value, Vector128<float> roundKey) - { - if (!Sse.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(Sse.Xor(value, roundKey))); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> InverseMixColumns(Vector128<float> value) - { - return CryptoHelper.AesInvMixColumns(value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> MixColumns(Vector128<float> value) - { - return CryptoHelper.AesMixColumns(value); - } -#endregion - -#region "Sha1" - public static Vector128<float> HashChoose(Vector128<float> hash_abcd, uint hash_e, Vector128<float> wk) - { - for (int e = 0; e <= 3; e++) - { - uint t = ShaChoose((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2), - (uint)VectorExtractIntZx(hash_abcd, (byte)2, 2), - (uint)VectorExtractIntZx(hash_abcd, (byte)3, 2)); - - hash_e += Rol((uint)VectorExtractIntZx(hash_abcd, (byte)0, 2), 5) + t; - hash_e += (uint)VectorExtractIntZx(wk, (byte)e, 2); - - t = Rol((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2), 30); - hash_abcd = VectorInsertInt((ulong)t, hash_abcd, (byte)1, 2); - - Rol32_160(ref hash_e, ref hash_abcd); - } - - return hash_abcd; - } - - public static uint FixedRotate(uint hash_e) - { - return hash_e.Rol(30); - } - - public static Vector128<float> HashMajority(Vector128<float> hash_abcd, uint hash_e, Vector128<float> wk) - { - for (int e = 0; e <= 3; e++) - { - uint t = ShaMajority((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2), - (uint)VectorExtractIntZx(hash_abcd, (byte)2, 2), - (uint)VectorExtractIntZx(hash_abcd, (byte)3, 2)); - - hash_e += Rol((uint)VectorExtractIntZx(hash_abcd, (byte)0, 2), 5) + t; - hash_e += (uint)VectorExtractIntZx(wk, (byte)e, 2); - - t = Rol((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2), 30); - hash_abcd = VectorInsertInt((ulong)t, hash_abcd, (byte)1, 2); - - Rol32_160(ref hash_e, ref hash_abcd); - } - - return hash_abcd; - } - - public static Vector128<float> HashParity(Vector128<float> hash_abcd, uint hash_e, Vector128<float> wk) - { - for (int e = 0; e <= 3; e++) - { - uint t = ShaParity((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2), - (uint)VectorExtractIntZx(hash_abcd, (byte)2, 2), - (uint)VectorExtractIntZx(hash_abcd, (byte)3, 2)); - - hash_e += Rol((uint)VectorExtractIntZx(hash_abcd, (byte)0, 2), 5) + t; - hash_e += (uint)VectorExtractIntZx(wk, (byte)e, 2); - - t = Rol((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2), 30); - hash_abcd = VectorInsertInt((ulong)t, hash_abcd, (byte)1, 2); - - Rol32_160(ref hash_e, ref hash_abcd); - } - - return hash_abcd; - } - - public static Vector128<float> Sha1SchedulePart1(Vector128<float> w0_3, Vector128<float> w4_7, Vector128<float> w8_11) - { - if (!Sse.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - Vector128<float> result = new Vector128<float>(); - - ulong t2 = VectorExtractIntZx(w4_7, (byte)0, 3); - ulong t1 = VectorExtractIntZx(w0_3, (byte)1, 3); - - result = VectorInsertInt((ulong)t1, result, (byte)0, 3); - result = VectorInsertInt((ulong)t2, result, (byte)1, 3); - - return Sse.Xor(result, Sse.Xor(w0_3, w8_11)); - } - - public static Vector128<float> Sha1SchedulePart2(Vector128<float> tw0_3, Vector128<float> w12_15) - { - if (!Sse2.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - Vector128<float> result = new Vector128<float>(); - - Vector128<float> t = Sse.Xor(tw0_3, Sse.StaticCast<uint, float>( - Sse2.ShiftRightLogical128BitLane(Sse.StaticCast<float, uint>(w12_15), (byte)4))); - - uint tE0 = (uint)VectorExtractIntZx(t, (byte)0, 2); - uint tE1 = (uint)VectorExtractIntZx(t, (byte)1, 2); - uint tE2 = (uint)VectorExtractIntZx(t, (byte)2, 2); - uint tE3 = (uint)VectorExtractIntZx(t, (byte)3, 2); - - result = VectorInsertInt((ulong)tE0.Rol(1), result, (byte)0, 2); - result = VectorInsertInt((ulong)tE1.Rol(1), result, (byte)1, 2); - result = VectorInsertInt((ulong)tE2.Rol(1), result, (byte)2, 2); - - return VectorInsertInt((ulong)(tE3.Rol(1) ^ tE0.Rol(2)), result, (byte)3, 2); - } - - private static void Rol32_160(ref uint y, ref Vector128<float> x) - { - if (!Sse2.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - uint xE3 = (uint)VectorExtractIntZx(x, (byte)3, 2); - - x = Sse.StaticCast<uint, float>(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast<float, uint>(x), (byte)4)); - x = VectorInsertInt((ulong)y, x, (byte)0, 2); - - y = xE3; - } - - private static uint ShaChoose(uint x, uint y, uint z) - { - return ((y ^ z) & x) ^ z; - } - - private static uint ShaMajority(uint x, uint y, uint z) - { - return (x & y) | ((x | y) & z); - } - - private static uint ShaParity(uint x, uint y, uint z) - { - return x ^ y ^ z; - } - - private static uint Rol(this uint value, int count) - { - return (value << count) | (value >> (32 - count)); - } -#endregion - -#region "Sha256" - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> HashLower(Vector128<float> hash_abcd, Vector128<float> hash_efgh, Vector128<float> wk) - { - return Sha256Hash(hash_abcd, hash_efgh, wk, true); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> HashUpper(Vector128<float> hash_efgh, Vector128<float> hash_abcd, Vector128<float> wk) - { - return Sha256Hash(hash_abcd, hash_efgh, wk, false); - } - - public static Vector128<float> Sha256SchedulePart1(Vector128<float> w0_3, Vector128<float> w4_7) - { - Vector128<float> result = new Vector128<float>(); - - for (int e = 0; e <= 3; e++) - { - uint elt = (uint)VectorExtractIntZx(e <= 2 ? w0_3 : w4_7, (byte)(e <= 2 ? e + 1 : 0), 2); - - elt = elt.Ror(7) ^ elt.Ror(18) ^ elt.Lsr(3); - - elt += (uint)VectorExtractIntZx(w0_3, (byte)e, 2); - - result = VectorInsertInt((ulong)elt, result, (byte)e, 2); - } - - return result; - } - - public static Vector128<float> Sha256SchedulePart2(Vector128<float> w0_3, Vector128<float> w8_11, Vector128<float> w12_15) - { - Vector128<float> result = new Vector128<float>(); - - ulong t1 = VectorExtractIntZx(w12_15, (byte)1, 3); - - for (int e = 0; e <= 1; e++) - { - uint elt = t1.ULongPart(e); - - elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10); - - elt += (uint)VectorExtractIntZx(w0_3, (byte)e, 2); - elt += (uint)VectorExtractIntZx(w8_11, (byte)(e + 1), 2); - - result = VectorInsertInt((ulong)elt, result, (byte)e, 2); - } - - t1 = VectorExtractIntZx(result, (byte)0, 3); - - for (int e = 2; e <= 3; e++) - { - uint elt = t1.ULongPart(e - 2); - - elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10); - - elt += (uint)VectorExtractIntZx(w0_3, (byte)e, 2); - elt += (uint)VectorExtractIntZx(e == 2 ? w8_11 : w12_15, (byte)(e == 2 ? 3 : 0), 2); - - result = VectorInsertInt((ulong)elt, result, (byte)e, 2); - } - - return result; - } - - private static Vector128<float> Sha256Hash(Vector128<float> x, Vector128<float> y, Vector128<float> w, bool part1) - { - for (int e = 0; e <= 3; e++) - { - uint chs = ShaChoose((uint)VectorExtractIntZx(y, (byte)0, 2), - (uint)VectorExtractIntZx(y, (byte)1, 2), - (uint)VectorExtractIntZx(y, (byte)2, 2)); - - uint maj = ShaMajority((uint)VectorExtractIntZx(x, (byte)0, 2), - (uint)VectorExtractIntZx(x, (byte)1, 2), - (uint)VectorExtractIntZx(x, (byte)2, 2)); - - uint t1 = (uint)VectorExtractIntZx(y, (byte)3, 2); - t1 += ShaHashSigma1((uint)VectorExtractIntZx(y, (byte)0, 2)) + chs; - t1 += (uint)VectorExtractIntZx(w, (byte)e, 2); - - uint t2 = t1 + (uint)VectorExtractIntZx(x, (byte)3, 2); - x = VectorInsertInt((ulong)t2, x, (byte)3, 2); - t2 = t1 + ShaHashSigma0((uint)VectorExtractIntZx(x, (byte)0, 2)) + maj; - y = VectorInsertInt((ulong)t2, y, (byte)3, 2); - - Rol32_256(ref y, ref x); - } - - return part1 ? x : y; - } - - private static void Rol32_256(ref Vector128<float> y, ref Vector128<float> x) - { - if (!Sse2.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - uint yE3 = (uint)VectorExtractIntZx(y, (byte)3, 2); - uint xE3 = (uint)VectorExtractIntZx(x, (byte)3, 2); - - y = Sse.StaticCast<uint, float>(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast<float, uint>(y), (byte)4)); - x = Sse.StaticCast<uint, float>(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast<float, uint>(x), (byte)4)); - - y = VectorInsertInt((ulong)xE3, y, (byte)0, 2); - x = VectorInsertInt((ulong)yE3, x, (byte)0, 2); - } - - private static uint ShaHashSigma0(uint x) - { - return x.Ror(2) ^ x.Ror(13) ^ x.Ror(22); - } - - private static uint ShaHashSigma1(uint x) - { - return x.Ror(6) ^ x.Ror(11) ^ x.Ror(25); - } - - private static uint Ror(this uint value, int count) - { - return (value >> count) | (value << (32 - count)); - } - - private static uint Lsr(this uint value, int count) - { - return value >> count; - } - - private static uint ULongPart(this ulong value, int part) - { - return part == 0 - ? (uint)(value & 0xFFFFFFFFUL) - : (uint)(value >> 32); - } -#endregion - -#region "Reverse" - public static uint ReverseBits8(uint value) - { - value = ((value & 0xaa) >> 1) | ((value & 0x55) << 1); - value = ((value & 0xcc) >> 2) | ((value & 0x33) << 2); - - return (value >> 4) | ((value & 0x0f) << 4); - } - - public static uint ReverseBits32(uint value) - { - value = ((value & 0xaaaaaaaa) >> 1) | ((value & 0x55555555) << 1); - value = ((value & 0xcccccccc) >> 2) | ((value & 0x33333333) << 2); - value = ((value & 0xf0f0f0f0) >> 4) | ((value & 0x0f0f0f0f) << 4); - value = ((value & 0xff00ff00) >> 8) | ((value & 0x00ff00ff) << 8); - - return (value >> 16) | (value << 16); - } - - public static ulong ReverseBits64(ulong value) - { - value = ((value & 0xaaaaaaaaaaaaaaaa) >> 1 ) | ((value & 0x5555555555555555) << 1 ); - value = ((value & 0xcccccccccccccccc) >> 2 ) | ((value & 0x3333333333333333) << 2 ); - value = ((value & 0xf0f0f0f0f0f0f0f0) >> 4 ) | ((value & 0x0f0f0f0f0f0f0f0f) << 4 ); - value = ((value & 0xff00ff00ff00ff00) >> 8 ) | ((value & 0x00ff00ff00ff00ff) << 8 ); - value = ((value & 0xffff0000ffff0000) >> 16) | ((value & 0x0000ffff0000ffff) << 16); - - return (value >> 32) | (value << 32); - } - - public static uint ReverseBytes16_32(uint value) => (uint)ReverseBytes16_64(value); - public static uint ReverseBytes32_32(uint value) => (uint)ReverseBytes32_64(value); - - public static ulong ReverseBytes16_64(ulong value) => ReverseBytes(value, RevSize.Rev16); - public static ulong ReverseBytes32_64(ulong value) => ReverseBytes(value, RevSize.Rev32); - public static ulong ReverseBytes64(ulong value) => ReverseBytes(value, RevSize.Rev64); - - private enum RevSize - { - Rev16, - Rev32, - Rev64 - } - - private static ulong ReverseBytes(ulong value, RevSize size) - { - value = ((value & 0xff00ff00ff00ff00) >> 8) | ((value & 0x00ff00ff00ff00ff) << 8); - - if (size == RevSize.Rev16) - { - return value; - } - - value = ((value & 0xffff0000ffff0000) >> 16) | ((value & 0x0000ffff0000ffff) << 16); - - if (size == RevSize.Rev32) - { - return value; - } - - value = ((value & 0xffffffff00000000) >> 32) | ((value & 0x00000000ffffffff) << 32); - - if (size == RevSize.Rev64) - { - return value; - } - - throw new ArgumentException(nameof(size)); - } -#endregion - -#region "MultiplyHigh" - public static long SMulHi128(long left, long right) - { - long result = (long)UMulHi128((ulong)left, (ulong)right); - - if (left < 0) - { - result -= right; - } - - if (right < 0) - { - result -= left; - } - - return result; - } - - public static ulong UMulHi128(ulong left, ulong right) - { - ulong lHigh = left >> 32; - ulong lLow = left & 0xFFFFFFFF; - ulong rHigh = right >> 32; - ulong rLow = right & 0xFFFFFFFF; - - ulong z2 = lLow * rLow; - ulong t = lHigh * rLow + (z2 >> 32); - ulong z1 = t & 0xFFFFFFFF; - ulong z0 = t >> 32; - - z1 += lLow * rHigh; - - return lHigh * rHigh + z0 + (z1 >> 32); - } -#endregion - } -} diff --git a/ChocolArm64/Instructions/SoftFloat.cs b/ChocolArm64/Instructions/SoftFloat.cs deleted file mode 100644 index e78932cc..00000000 --- a/ChocolArm64/Instructions/SoftFloat.cs +++ /dev/null @@ -1,2790 +0,0 @@ -using ChocolArm64.State; -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace ChocolArm64.Instructions -{ - static class SoftFloat - { - static SoftFloat() - { - RecipEstimateTable = BuildRecipEstimateTable(); - RecipSqrtEstimateTable = BuildRecipSqrtEstimateTable(); - } - - internal static readonly byte[] RecipEstimateTable; - internal static readonly byte[] RecipSqrtEstimateTable; - - private static byte[] BuildRecipEstimateTable() - { - byte[] tbl = new byte[256]; - - for (int idx = 0; idx < 256; idx++) - { - uint src = (uint)idx + 256u; - - Debug.Assert(256u <= src && src < 512u); - - src = (src << 1) + 1u; - - uint aux = (1u << 19) / src; - - uint dst = (aux + 1u) >> 1; - - Debug.Assert(256u <= dst && dst < 512u); - - tbl[idx] = (byte)(dst - 256u); - } - - return tbl; - } - - private static byte[] BuildRecipSqrtEstimateTable() - { - byte[] tbl = new byte[384]; - - for (int idx = 0; idx < 384; idx++) - { - uint src = (uint)idx + 128u; - - Debug.Assert(128u <= src && src < 512u); - - if (src < 256u) - { - src = (src << 1) + 1u; - } - else - { - src = (src >> 1) << 1; - src = (src + 1u) << 1; - } - - uint aux = 512u; - - while (src * (aux + 1u) * (aux + 1u) < (1u << 28)) - { - aux = aux + 1u; - } - - uint dst = (aux + 1u) >> 1; - - Debug.Assert(256u <= dst && dst < 512u); - - tbl[idx] = (byte)(dst - 256u); - } - - return tbl; - } - } - - static class SoftFloat16_32 - { - public static float FPConvert(ushort valueBits, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat16_32.FPConvert: state.Fpcr = 0x{state.CFpcr:X8}"); - - double real = valueBits.FPUnpackCv(out FpType type, out bool sign, state); - - float result; - - if (type == FpType.SNaN || type == FpType.QNaN) - { - if (state.GetFpcrFlag(Fpcr.Dn)) - { - result = FPDefaultNaN(); - } - else - { - result = FPConvertNaN(valueBits); - } - - if (type == FpType.SNaN) - { - FPProcessException(FpExc.InvalidOp, state); - } - } - else if (type == FpType.Infinity) - { - result = FPInfinity(sign); - } - else if (type == FpType.Zero) - { - result = FPZero(sign); - } - else - { - result = FPRoundCv(real, state); - } - - return result; - } - - private static float FPDefaultNaN() - { - return -float.NaN; - } - - private static float FPInfinity(bool sign) - { - return sign ? float.NegativeInfinity : float.PositiveInfinity; - } - - private static float FPZero(bool sign) - { - return sign ? -0f : +0f; - } - - private static float FPMaxNormal(bool sign) - { - return sign ? float.MinValue : float.MaxValue; - } - - private static double FPUnpackCv( - this ushort valueBits, - out FpType type, - out bool sign, - CpuThreadState state) - { - sign = (~(uint)valueBits & 0x8000u) == 0u; - - uint exp16 = ((uint)valueBits & 0x7C00u) >> 10; - uint frac16 = (uint)valueBits & 0x03FFu; - - double real; - - if (exp16 == 0u) - { - if (frac16 == 0u) - { - type = FpType.Zero; - real = 0d; - } - else - { - type = FpType.Nonzero; // Subnormal. - real = Math.Pow(2d, -14) * ((double)frac16 * Math.Pow(2d, -10)); - } - } - else if (exp16 == 0x1Fu && !state.GetFpcrFlag(Fpcr.Ahp)) - { - if (frac16 == 0u) - { - type = FpType.Infinity; - real = Math.Pow(2d, 1000); - } - else - { - type = (~frac16 & 0x0200u) == 0u ? FpType.QNaN : FpType.SNaN; - real = 0d; - } - } - else - { - type = FpType.Nonzero; // Normal. - real = Math.Pow(2d, (int)exp16 - 15) * (1d + (double)frac16 * Math.Pow(2d, -10)); - } - - return sign ? -real : real; - } - - private static float FPRoundCv(double real, CpuThreadState state) - { - const int minimumExp = -126; - - const int e = 8; - const int f = 23; - - bool sign; - double mantissa; - - if (real < 0d) - { - sign = true; - mantissa = -real; - } - else - { - sign = false; - mantissa = real; - } - - int exponent = 0; - - while (mantissa < 1d) - { - mantissa *= 2d; - exponent--; - } - - while (mantissa >= 2d) - { - mantissa /= 2d; - exponent++; - } - - if (state.GetFpcrFlag(Fpcr.Fz) && exponent < minimumExp) - { - state.SetFpsrFlag(Fpsr.Ufc); - - return FPZero(sign); - } - - uint biasedExp = (uint)Math.Max(exponent - minimumExp + 1, 0); - - if (biasedExp == 0u) - { - mantissa /= Math.Pow(2d, minimumExp - exponent); - } - - uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, f)); - double error = mantissa * Math.Pow(2d, f) - (double)intMant; - - if (biasedExp == 0u && (error != 0d || state.GetFpcrFlag(Fpcr.Ufe))) - { - FPProcessException(FpExc.Underflow, state); - } - - bool overflowToInf; - bool roundUp; - - switch (state.FPRoundingMode()) - { - default: - case RoundMode.ToNearest: - roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u)); - overflowToInf = true; - break; - - case RoundMode.TowardsPlusInfinity: - roundUp = (error != 0d && !sign); - overflowToInf = !sign; - break; - - case RoundMode.TowardsMinusInfinity: - roundUp = (error != 0d && sign); - overflowToInf = sign; - break; - - case RoundMode.TowardsZero: - roundUp = false; - overflowToInf = false; - break; - } - - if (roundUp) - { - intMant++; - - if (intMant == 1u << f) - { - biasedExp = 1u; - } - - if (intMant == 1u << (f + 1)) - { - biasedExp++; - intMant >>= 1; - } - } - - float result; - - if (biasedExp >= (1u << e) - 1u) - { - result = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign); - - FPProcessException(FpExc.Overflow, state); - - error = 1d; - } - else - { - result = BitConverter.Int32BitsToSingle( - (int)((sign ? 1u : 0u) << 31 | (biasedExp & 0xFFu) << 23 | (intMant & 0x007FFFFFu))); - } - - if (error != 0d) - { - FPProcessException(FpExc.Inexact, state); - } - - return result; - } - - private static float FPConvertNaN(ushort valueBits) - { - return BitConverter.Int32BitsToSingle( - (int)(((uint)valueBits & 0x8000u) << 16 | 0x7FC00000u | ((uint)valueBits & 0x01FFu) << 13)); - } - - private static void FPProcessException(FpExc exc, CpuThreadState state) - { - int enable = (int)exc + 8; - - if ((state.CFpcr & (1 << enable)) != 0) - { - throw new NotImplementedException("Floating-point trap handling."); - } - else - { - state.CFpsr |= 1 << (int)exc; - } - } - } - - static class SoftFloat32_16 - { - public static ushort FPConvert(float value, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32_16.FPConvert: state.Fpcr = 0x{state.CFpcr:X8}"); - - double real = value.FPUnpackCv(out FpType type, out bool sign, out uint valueBits, state); - - bool altHp = state.GetFpcrFlag(Fpcr.Ahp); - - ushort resultBits; - - if (type == FpType.SNaN || type == FpType.QNaN) - { - if (altHp) - { - resultBits = FPZero(sign); - } - else if (state.GetFpcrFlag(Fpcr.Dn)) - { - resultBits = FPDefaultNaN(); - } - else - { - resultBits = FPConvertNaN(valueBits); - } - - if (type == FpType.SNaN || altHp) - { - FPProcessException(FpExc.InvalidOp, state); - } - } - else if (type == FpType.Infinity) - { - if (altHp) - { - resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu); - - FPProcessException(FpExc.InvalidOp, state); - } - else - { - resultBits = FPInfinity(sign); - } - } - else if (type == FpType.Zero) - { - resultBits = FPZero(sign); - } - else - { - resultBits = FPRoundCv(real, state); - } - - return resultBits; - } - - private static ushort FPDefaultNaN() - { - return (ushort)0x7E00u; - } - - private static ushort FPInfinity(bool sign) - { - return sign ? (ushort)0xFC00u : (ushort)0x7C00u; - } - - private static ushort FPZero(bool sign) - { - return sign ? (ushort)0x8000u : (ushort)0x0000u; - } - - private static ushort FPMaxNormal(bool sign) - { - return sign ? (ushort)0xFBFFu : (ushort)0x7BFFu; - } - - private static double FPUnpackCv( - this float value, - out FpType type, - out bool sign, - out uint valueBits, - CpuThreadState state) - { - valueBits = (uint)BitConverter.SingleToInt32Bits(value); - - sign = (~valueBits & 0x80000000u) == 0u; - - uint exp32 = (valueBits & 0x7F800000u) >> 23; - uint frac32 = valueBits & 0x007FFFFFu; - - double real; - - if (exp32 == 0u) - { - if (frac32 == 0u || state.GetFpcrFlag(Fpcr.Fz)) - { - type = FpType.Zero; - real = 0d; - - if (frac32 != 0u) - { - FPProcessException(FpExc.InputDenorm, state); - } - } - else - { - type = FpType.Nonzero; // Subnormal. - real = Math.Pow(2d, -126) * ((double)frac32 * Math.Pow(2d, -23)); - } - } - else if (exp32 == 0xFFu) - { - if (frac32 == 0u) - { - type = FpType.Infinity; - real = Math.Pow(2d, 1000); - } - else - { - type = (~frac32 & 0x00400000u) == 0u ? FpType.QNaN : FpType.SNaN; - real = 0d; - } - } - else - { - type = FpType.Nonzero; // Normal. - real = Math.Pow(2d, (int)exp32 - 127) * (1d + (double)frac32 * Math.Pow(2d, -23)); - } - - return sign ? -real : real; - } - - private static ushort FPRoundCv(double real, CpuThreadState state) - { - const int minimumExp = -14; - - const int e = 5; - const int f = 10; - - bool sign; - double mantissa; - - if (real < 0d) - { - sign = true; - mantissa = -real; - } - else - { - sign = false; - mantissa = real; - } - - int exponent = 0; - - while (mantissa < 1d) - { - mantissa *= 2d; - exponent--; - } - - while (mantissa >= 2d) - { - mantissa /= 2d; - exponent++; - } - - uint biasedExp = (uint)Math.Max(exponent - minimumExp + 1, 0); - - if (biasedExp == 0u) - { - mantissa /= Math.Pow(2d, minimumExp - exponent); - } - - uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, f)); - double error = mantissa * Math.Pow(2d, f) - (double)intMant; - - if (biasedExp == 0u && (error != 0d || state.GetFpcrFlag(Fpcr.Ufe))) - { - FPProcessException(FpExc.Underflow, state); - } - - bool overflowToInf; - bool roundUp; - - switch (state.FPRoundingMode()) - { - default: - case RoundMode.ToNearest: - roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u)); - overflowToInf = true; - break; - - case RoundMode.TowardsPlusInfinity: - roundUp = (error != 0d && !sign); - overflowToInf = !sign; - break; - - case RoundMode.TowardsMinusInfinity: - roundUp = (error != 0d && sign); - overflowToInf = sign; - break; - - case RoundMode.TowardsZero: - roundUp = false; - overflowToInf = false; - break; - } - - if (roundUp) - { - intMant++; - - if (intMant == 1u << f) - { - biasedExp = 1u; - } - - if (intMant == 1u << (f + 1)) - { - biasedExp++; - intMant >>= 1; - } - } - - ushort resultBits; - - if (!state.GetFpcrFlag(Fpcr.Ahp)) - { - if (biasedExp >= (1u << e) - 1u) - { - resultBits = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign); - - FPProcessException(FpExc.Overflow, state); - - error = 1d; - } - else - { - resultBits = (ushort)((sign ? 1u : 0u) << 15 | (biasedExp & 0x1Fu) << 10 | (intMant & 0x03FFu)); - } - } - else - { - if (biasedExp >= 1u << e) - { - resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu); - - FPProcessException(FpExc.InvalidOp, state); - - error = 0d; - } - else - { - resultBits = (ushort)((sign ? 1u : 0u) << 15 | (biasedExp & 0x1Fu) << 10 | (intMant & 0x03FFu)); - } - } - - if (error != 0d) - { - FPProcessException(FpExc.Inexact, state); - } - - return resultBits; - } - - private static ushort FPConvertNaN(uint valueBits) - { - return (ushort)((valueBits & 0x80000000u) >> 16 | 0x7E00u | (valueBits & 0x003FE000u) >> 13); - } - - private static void FPProcessException(FpExc exc, CpuThreadState state) - { - int enable = (int)exc + 8; - - if ((state.CFpcr & (1 << enable)) != 0) - { - throw new NotImplementedException("Floating-point trap handling."); - } - else - { - state.CFpsr |= 1 << (int)exc; - } - } - } - - static class SoftFloat32 - { - public static float FPAdd(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPAdd: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2, state); - - float result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if (inf1 && inf2 && sign1 == !sign2) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else if ((inf1 && !sign1) || (inf2 && !sign2)) - { - result = FPInfinity(false); - } - else if ((inf1 && sign1) || (inf2 && sign2)) - { - result = FPInfinity(true); - } - else if (zero1 && zero2 && sign1 == sign2) - { - result = FPZero(sign1); - } - else - { - result = value1 + value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && float.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0f); - } - } - } - - return result; - } - - public static int FPCompare(float value1, float value2, bool signalNaNs, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPCompare: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out _, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out _, state); - - int result; - - if (type1 == FpType.SNaN || type1 == FpType.QNaN || type2 == FpType.SNaN || type2 == FpType.QNaN) - { - result = 0b0011; - - if (type1 == FpType.SNaN || type2 == FpType.SNaN || signalNaNs) - { - FPProcessException(FpExc.InvalidOp, state); - } - } - else - { - if (value1 == value2) - { - result = 0b0110; - } - else if (value1 < value2) - { - result = 0b1000; - } - else - { - result = 0b0010; - } - } - - return result; - } - - public static float FPCompareEQ(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPCompareEQ: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out _, out _, state); - value2 = value2.FPUnpack(out FpType type2, out _, out _, state); - - float result; - - if (type1 == FpType.SNaN || type1 == FpType.QNaN || type2 == FpType.SNaN || type2 == FpType.QNaN) - { - result = ZerosOrOnes(false); - - if (type1 == FpType.SNaN || type2 == FpType.SNaN) - { - FPProcessException(FpExc.InvalidOp, state); - } - } - else - { - result = ZerosOrOnes(value1 == value2); - } - - return result; - } - - public static float FPCompareGE(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPCompareGE: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out _, out _, state); - value2 = value2.FPUnpack(out FpType type2, out _, out _, state); - - float result; - - if (type1 == FpType.SNaN || type1 == FpType.QNaN || type2 == FpType.SNaN || type2 == FpType.QNaN) - { - result = ZerosOrOnes(false); - - FPProcessException(FpExc.InvalidOp, state); - } - else - { - result = ZerosOrOnes(value1 >= value2); - } - - return result; - } - - public static float FPCompareGT(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPCompareGT: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out _, out _, state); - value2 = value2.FPUnpack(out FpType type2, out _, out _, state); - - float result; - - if (type1 == FpType.SNaN || type1 == FpType.QNaN || type2 == FpType.SNaN || type2 == FpType.QNaN) - { - result = ZerosOrOnes(false); - - FPProcessException(FpExc.InvalidOp, state); - } - else - { - result = ZerosOrOnes(value1 > value2); - } - - return result; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float FPCompareLE(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPCompareLE: state.Fpcr = 0x{state.CFpcr:X8}"); - - return FPCompareGE(value2, value1, state); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float FPCompareLT(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPCompareLT: state.Fpcr = 0x{state.CFpcr:X8}"); - - return FPCompareGT(value2, value1, state); - } - - public static float FPDiv(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPDiv: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2, state); - - float result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if ((inf1 && inf2) || (zero1 && zero2)) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else if (inf1 || zero2) - { - result = FPInfinity(sign1 ^ sign2); - - if (!inf1) - { - FPProcessException(FpExc.DivideByZero, state); - } - } - else if (zero1 || inf2) - { - result = FPZero(sign1 ^ sign2); - } - else - { - result = value1 / value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && float.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0f); - } - } - } - - return result; - } - - public static float FPMax(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPMax: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2, state); - - float result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - if (value1 > value2) - { - if (type1 == FpType.Infinity) - { - result = FPInfinity(sign1); - } - else if (type1 == FpType.Zero) - { - result = FPZero(sign1 && sign2); - } - else - { - result = value1; - } - } - else - { - if (type2 == FpType.Infinity) - { - result = FPInfinity(sign2); - } - else if (type2 == FpType.Zero) - { - result = FPZero(sign1 && sign2); - } - else - { - result = value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && float.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0f); - } - } - } - } - - return result; - } - - public static float FPMaxNum(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPMaxNum: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1.FPUnpack(out FpType type1, out _, out _, state); - value2.FPUnpack(out FpType type2, out _, out _, state); - - if (type1 == FpType.QNaN && type2 != FpType.QNaN) - { - value1 = FPInfinity(true); - } - else if (type1 != FpType.QNaN && type2 == FpType.QNaN) - { - value2 = FPInfinity(true); - } - - return FPMax(value1, value2, state); - } - - public static float FPMin(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPMin: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2, state); - - float result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - if (value1 < value2) - { - if (type1 == FpType.Infinity) - { - result = FPInfinity(sign1); - } - else if (type1 == FpType.Zero) - { - result = FPZero(sign1 || sign2); - } - else - { - result = value1; - } - } - else - { - if (type2 == FpType.Infinity) - { - result = FPInfinity(sign2); - } - else if (type2 == FpType.Zero) - { - result = FPZero(sign1 || sign2); - } - else - { - result = value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && float.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0f); - } - } - } - } - - return result; - } - - public static float FPMinNum(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPMinNum: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1.FPUnpack(out FpType type1, out _, out _, state); - value2.FPUnpack(out FpType type2, out _, out _, state); - - if (type1 == FpType.QNaN && type2 != FpType.QNaN) - { - value1 = FPInfinity(false); - } - else if (type1 != FpType.QNaN && type2 == FpType.QNaN) - { - value2 = FPInfinity(false); - } - - return FPMin(value1, value2, state); - } - - public static float FPMul(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPMul: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2, state); - - float result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if ((inf1 && zero2) || (zero1 && inf2)) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else if (inf1 || inf2) - { - result = FPInfinity(sign1 ^ sign2); - } - else if (zero1 || zero2) - { - result = FPZero(sign1 ^ sign2); - } - else - { - result = value1 * value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && float.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0f); - } - } - } - - return result; - } - - public static float FPMulAdd( - float valueA, - float value1, - float value2, - CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPMulAdd: state.Fpcr = 0x{state.CFpcr:X8}"); - - valueA = valueA.FPUnpack(out FpType typeA, out bool signA, out uint addend, state); - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2, state); - - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - float result = FPProcessNaNs3(typeA, type1, type2, addend, op1, op2, out bool done, state); - - if (typeA == FpType.QNaN && ((inf1 && zero2) || (zero1 && inf2))) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - - if (!done) - { - bool infA = typeA == FpType.Infinity; bool zeroA = typeA == FpType.Zero; - - bool signP = sign1 ^ sign2; - bool infP = inf1 || inf2; - bool zeroP = zero1 || zero2; - - if ((inf1 && zero2) || (zero1 && inf2) || (infA && infP && signA != signP)) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else if ((infA && !signA) || (infP && !signP)) - { - result = FPInfinity(false); - } - else if ((infA && signA) || (infP && signP)) - { - result = FPInfinity(true); - } - else if (zeroA && zeroP && signA == signP) - { - result = FPZero(signA); - } - else - { - // TODO: When available, use: T MathF.FusedMultiplyAdd(T, T, T); - // https://github.com/dotnet/corefx/issues/31903 - - result = valueA + (value1 * value2); - - if (state.GetFpcrFlag(Fpcr.Fz) && float.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0f); - } - } - } - - return result; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float FPMulSub( - float valueA, - float value1, - float value2, - CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPMulSub: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPNeg(); - - return FPMulAdd(valueA, value1, value2, state); - } - - public static float FPMulX(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPMulX: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2, state); - - float result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if ((inf1 && zero2) || (zero1 && inf2)) - { - result = FPTwo(sign1 ^ sign2); - } - else if (inf1 || inf2) - { - result = FPInfinity(sign1 ^ sign2); - } - else if (zero1 || zero2) - { - result = FPZero(sign1 ^ sign2); - } - else - { - result = value1 * value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && float.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0f); - } - } - } - - return result; - } - - public static float FPRecipEstimate(float value, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPRecipEstimate: state.Fpcr = 0x{state.CFpcr:X8}"); - - value.FPUnpack(out FpType type, out bool sign, out uint op, state); - - float result; - - if (type == FpType.SNaN || type == FpType.QNaN) - { - result = FPProcessNaN(type, op, state); - } - else if (type == FpType.Infinity) - { - result = FPZero(sign); - } - else if (type == FpType.Zero) - { - result = FPInfinity(sign); - - FPProcessException(FpExc.DivideByZero, state); - } - else if (MathF.Abs(value) < MathF.Pow(2f, -128)) - { - bool overflowToInf; - - switch (state.FPRoundingMode()) - { - default: - case RoundMode.ToNearest: overflowToInf = true; break; - case RoundMode.TowardsPlusInfinity: overflowToInf = !sign; break; - case RoundMode.TowardsMinusInfinity: overflowToInf = sign; break; - case RoundMode.TowardsZero: overflowToInf = false; break; - } - - result = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign); - - FPProcessException(FpExc.Overflow, state); - FPProcessException(FpExc.Inexact, state); - } - else if (state.GetFpcrFlag(Fpcr.Fz) && (MathF.Abs(value) >= MathF.Pow(2f, 126))) - { - result = FPZero(sign); - - state.SetFpsrFlag(Fpsr.Ufc); - } - else - { - ulong fraction = (ulong)(op & 0x007FFFFFu) << 29; - uint exp = (op & 0x7F800000u) >> 23; - - if (exp == 0u) - { - if ((fraction & 0x0008000000000000ul) == 0ul) - { - fraction = (fraction & 0x0003FFFFFFFFFFFFul) << 2; - exp -= 1u; - } - else - { - fraction = (fraction & 0x0007FFFFFFFFFFFFul) << 1; - } - } - - uint scaled = (uint)(((fraction & 0x000FF00000000000ul) | 0x0010000000000000ul) >> 44); - - uint resultExp = 253u - exp; - - uint estimate = (uint)SoftFloat.RecipEstimateTable[scaled - 256u] + 256u; - - fraction = (ulong)(estimate & 0xFFu) << 44; - - if (resultExp == 0u) - { - fraction = ((fraction & 0x000FFFFFFFFFFFFEul) | 0x0010000000000000ul) >> 1; - } - else if (resultExp + 1u == 0u) - { - fraction = ((fraction & 0x000FFFFFFFFFFFFCul) | 0x0010000000000000ul) >> 2; - resultExp = 0u; - } - - result = BitConverter.Int32BitsToSingle( - (int)((sign ? 1u : 0u) << 31 | (resultExp & 0xFFu) << 23 | (uint)(fraction >> 29) & 0x007FFFFFu)); - } - - return result; - } - - public static float FPRecipStepFused(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPRecipStepFused: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPNeg(); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2, state); - - float result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if ((inf1 && zero2) || (zero1 && inf2)) - { - result = FPTwo(false); - } - else if (inf1 || inf2) - { - result = FPInfinity(sign1 ^ sign2); - } - else - { - // TODO: When available, use: T MathF.FusedMultiplyAdd(T, T, T); - // https://github.com/dotnet/corefx/issues/31903 - - result = 2f + (value1 * value2); - - if (state.GetFpcrFlag(Fpcr.Fz) && float.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0f); - } - } - } - - return result; - } - - public static float FPRecpX(float value, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPRecpX: state.Fpcr = 0x{state.CFpcr:X8}"); - - value.FPUnpack(out FpType type, out bool sign, out uint op, state); - - float result; - - if (type == FpType.SNaN || type == FpType.QNaN) - { - result = FPProcessNaN(type, op, state); - } - else - { - uint notExp = (~op >> 23) & 0xFFu; - uint maxExp = 0xFEu; - - result = BitConverter.Int32BitsToSingle( - (int)((sign ? 1u : 0u) << 31 | (notExp == 0xFFu ? maxExp : notExp) << 23)); - } - - return result; - } - - public static float FPRSqrtEstimate(float value, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPRSqrtEstimate: state.Fpcr = 0x{state.CFpcr:X8}"); - - value.FPUnpack(out FpType type, out bool sign, out uint op, state); - - float result; - - if (type == FpType.SNaN || type == FpType.QNaN) - { - result = FPProcessNaN(type, op, state); - } - else if (type == FpType.Zero) - { - result = FPInfinity(sign); - - FPProcessException(FpExc.DivideByZero, state); - } - else if (sign) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else if (type == FpType.Infinity) - { - result = FPZero(false); - } - else - { - ulong fraction = (ulong)(op & 0x007FFFFFu) << 29; - uint exp = (op & 0x7F800000u) >> 23; - - if (exp == 0u) - { - while ((fraction & 0x0008000000000000ul) == 0ul) - { - fraction = (fraction & 0x0007FFFFFFFFFFFFul) << 1; - exp -= 1u; - } - - fraction = (fraction & 0x0007FFFFFFFFFFFFul) << 1; - } - - uint scaled; - - if ((exp & 1u) == 0u) - { - scaled = (uint)(((fraction & 0x000FF00000000000ul) | 0x0010000000000000ul) >> 44); - } - else - { - scaled = (uint)(((fraction & 0x000FE00000000000ul) | 0x0010000000000000ul) >> 45); - } - - uint resultExp = (380u - exp) >> 1; - - uint estimate = (uint)SoftFloat.RecipSqrtEstimateTable[scaled - 128u] + 256u; - - result = BitConverter.Int32BitsToSingle((int)((resultExp & 0xFFu) << 23 | (estimate & 0xFFu) << 15)); - } - - return result; - } - - public static float FPRSqrtStepFused(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPRSqrtStepFused: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPNeg(); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2, state); - - float result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if ((inf1 && zero2) || (zero1 && inf2)) - { - result = FPOnePointFive(false); - } - else if (inf1 || inf2) - { - result = FPInfinity(sign1 ^ sign2); - } - else - { - // TODO: When available, use: T MathF.FusedMultiplyAdd(T, T, T); - // https://github.com/dotnet/corefx/issues/31903 - - result = (3f + (value1 * value2)) / 2f; - - if (state.GetFpcrFlag(Fpcr.Fz) && float.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0f); - } - } - } - - return result; - } - - public static float FPSqrt(float value, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPSqrt: state.Fpcr = 0x{state.CFpcr:X8}"); - - value = value.FPUnpack(out FpType type, out bool sign, out uint op, state); - - float result; - - if (type == FpType.SNaN || type == FpType.QNaN) - { - result = FPProcessNaN(type, op, state); - } - else if (type == FpType.Zero) - { - result = FPZero(sign); - } - else if (type == FpType.Infinity && !sign) - { - result = FPInfinity(sign); - } - else if (sign) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else - { - result = MathF.Sqrt(value); - - if (state.GetFpcrFlag(Fpcr.Fz) && float.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0f); - } - } - - return result; - } - - public static float FPSub(float value1, float value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat32.FPSub: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2, state); - - float result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if (inf1 && inf2 && sign1 == sign2) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else if ((inf1 && !sign1) || (inf2 && sign2)) - { - result = FPInfinity(false); - } - else if ((inf1 && sign1) || (inf2 && !sign2)) - { - result = FPInfinity(true); - } - else if (zero1 && zero2 && sign1 == !sign2) - { - result = FPZero(sign1); - } - else - { - result = value1 - value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && float.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0f); - } - } - } - - return result; - } - - private static float FPDefaultNaN() - { - return -float.NaN; - } - - private static float FPInfinity(bool sign) - { - return sign ? float.NegativeInfinity : float.PositiveInfinity; - } - - private static float FPZero(bool sign) - { - return sign ? -0f : +0f; - } - - private static float FPMaxNormal(bool sign) - { - return sign ? float.MinValue : float.MaxValue; - } - - private static float FPTwo(bool sign) - { - return sign ? -2f : +2f; - } - - private static float FPOnePointFive(bool sign) - { - return sign ? -1.5f : +1.5f; - } - - private static float FPNeg(this float value) - { - return -value; - } - - private static float ZerosOrOnes(bool ones) - { - return BitConverter.Int32BitsToSingle(ones ? -1 : 0); - } - - private static float FPUnpack( - this float value, - out FpType type, - out bool sign, - out uint valueBits, - CpuThreadState state) - { - valueBits = (uint)BitConverter.SingleToInt32Bits(value); - - sign = (~valueBits & 0x80000000u) == 0u; - - if ((valueBits & 0x7F800000u) == 0u) - { - if ((valueBits & 0x007FFFFFu) == 0u || state.GetFpcrFlag(Fpcr.Fz)) - { - type = FpType.Zero; - value = FPZero(sign); - - if ((valueBits & 0x007FFFFFu) != 0u) - { - FPProcessException(FpExc.InputDenorm, state); - } - } - else - { - type = FpType.Nonzero; - } - } - else if ((~valueBits & 0x7F800000u) == 0u) - { - if ((valueBits & 0x007FFFFFu) == 0u) - { - type = FpType.Infinity; - } - else - { - type = (~valueBits & 0x00400000u) == 0u ? FpType.QNaN : FpType.SNaN; - value = FPZero(sign); - } - } - else - { - type = FpType.Nonzero; - } - - return value; - } - - private static float FPProcessNaNs( - FpType type1, - FpType type2, - uint op1, - uint op2, - out bool done, - CpuThreadState state) - { - done = true; - - if (type1 == FpType.SNaN) - { - return FPProcessNaN(type1, op1, state); - } - else if (type2 == FpType.SNaN) - { - return FPProcessNaN(type2, op2, state); - } - else if (type1 == FpType.QNaN) - { - return FPProcessNaN(type1, op1, state); - } - else if (type2 == FpType.QNaN) - { - return FPProcessNaN(type2, op2, state); - } - - done = false; - - return FPZero(false); - } - - private static float FPProcessNaNs3( - FpType type1, - FpType type2, - FpType type3, - uint op1, - uint op2, - uint op3, - out bool done, - CpuThreadState state) - { - done = true; - - if (type1 == FpType.SNaN) - { - return FPProcessNaN(type1, op1, state); - } - else if (type2 == FpType.SNaN) - { - return FPProcessNaN(type2, op2, state); - } - else if (type3 == FpType.SNaN) - { - return FPProcessNaN(type3, op3, state); - } - else if (type1 == FpType.QNaN) - { - return FPProcessNaN(type1, op1, state); - } - else if (type2 == FpType.QNaN) - { - return FPProcessNaN(type2, op2, state); - } - else if (type3 == FpType.QNaN) - { - return FPProcessNaN(type3, op3, state); - } - - done = false; - - return FPZero(false); - } - - private static float FPProcessNaN(FpType type, uint op, CpuThreadState state) - { - if (type == FpType.SNaN) - { - op |= 1u << 22; - - FPProcessException(FpExc.InvalidOp, state); - } - - if (state.GetFpcrFlag(Fpcr.Dn)) - { - return FPDefaultNaN(); - } - - return BitConverter.Int32BitsToSingle((int)op); - } - - private static void FPProcessException(FpExc exc, CpuThreadState state) - { - int enable = (int)exc + 8; - - if ((state.CFpcr & (1 << enable)) != 0) - { - throw new NotImplementedException("Floating-point trap handling."); - } - else - { - state.CFpsr |= 1 << (int)exc; - } - } - } - - static class SoftFloat64 - { - public static double FPAdd(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPAdd: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2, state); - - double result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if (inf1 && inf2 && sign1 == !sign2) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else if ((inf1 && !sign1) || (inf2 && !sign2)) - { - result = FPInfinity(false); - } - else if ((inf1 && sign1) || (inf2 && sign2)) - { - result = FPInfinity(true); - } - else if (zero1 && zero2 && sign1 == sign2) - { - result = FPZero(sign1); - } - else - { - result = value1 + value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && double.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0d); - } - } - } - - return result; - } - - public static int FPCompare(double value1, double value2, bool signalNaNs, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPCompare: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out _, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out _, state); - - int result; - - if (type1 == FpType.SNaN || type1 == FpType.QNaN || type2 == FpType.SNaN || type2 == FpType.QNaN) - { - result = 0b0011; - - if (type1 == FpType.SNaN || type2 == FpType.SNaN || signalNaNs) - { - FPProcessException(FpExc.InvalidOp, state); - } - } - else - { - if (value1 == value2) - { - result = 0b0110; - } - else if (value1 < value2) - { - result = 0b1000; - } - else - { - result = 0b0010; - } - } - - return result; - } - - public static double FPCompareEQ(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPCompareEQ: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out _, out _, state); - value2 = value2.FPUnpack(out FpType type2, out _, out _, state); - - double result; - - if (type1 == FpType.SNaN || type1 == FpType.QNaN || type2 == FpType.SNaN || type2 == FpType.QNaN) - { - result = ZerosOrOnes(false); - - if (type1 == FpType.SNaN || type2 == FpType.SNaN) - { - FPProcessException(FpExc.InvalidOp, state); - } - } - else - { - result = ZerosOrOnes(value1 == value2); - } - - return result; - } - - public static double FPCompareGE(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPCompareGE: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out _, out _, state); - value2 = value2.FPUnpack(out FpType type2, out _, out _, state); - - double result; - - if (type1 == FpType.SNaN || type1 == FpType.QNaN || type2 == FpType.SNaN || type2 == FpType.QNaN) - { - result = ZerosOrOnes(false); - - FPProcessException(FpExc.InvalidOp, state); - } - else - { - result = ZerosOrOnes(value1 >= value2); - } - - return result; - } - - public static double FPCompareGT(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPCompareGT: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out _, out _, state); - value2 = value2.FPUnpack(out FpType type2, out _, out _, state); - - double result; - - if (type1 == FpType.SNaN || type1 == FpType.QNaN || type2 == FpType.SNaN || type2 == FpType.QNaN) - { - result = ZerosOrOnes(false); - - FPProcessException(FpExc.InvalidOp, state); - } - else - { - result = ZerosOrOnes(value1 > value2); - } - - return result; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double FPCompareLE(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPCompareLE: state.Fpcr = 0x{state.CFpcr:X8}"); - - return FPCompareGE(value2, value1, state); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double FPCompareLT(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPCompareLT: state.Fpcr = 0x{state.CFpcr:X8}"); - - return FPCompareGT(value2, value1, state); - } - - public static double FPDiv(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPDiv: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2, state); - - double result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if ((inf1 && inf2) || (zero1 && zero2)) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else if (inf1 || zero2) - { - result = FPInfinity(sign1 ^ sign2); - - if (!inf1) - { - FPProcessException(FpExc.DivideByZero, state); - } - } - else if (zero1 || inf2) - { - result = FPZero(sign1 ^ sign2); - } - else - { - result = value1 / value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && double.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0d); - } - } - } - - return result; - } - - public static double FPMax(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPMax: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2, state); - - double result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - if (value1 > value2) - { - if (type1 == FpType.Infinity) - { - result = FPInfinity(sign1); - } - else if (type1 == FpType.Zero) - { - result = FPZero(sign1 && sign2); - } - else - { - result = value1; - } - } - else - { - if (type2 == FpType.Infinity) - { - result = FPInfinity(sign2); - } - else if (type2 == FpType.Zero) - { - result = FPZero(sign1 && sign2); - } - else - { - result = value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && double.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0d); - } - } - } - } - - return result; - } - - public static double FPMaxNum(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPMaxNum: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1.FPUnpack(out FpType type1, out _, out _, state); - value2.FPUnpack(out FpType type2, out _, out _, state); - - if (type1 == FpType.QNaN && type2 != FpType.QNaN) - { - value1 = FPInfinity(true); - } - else if (type1 != FpType.QNaN && type2 == FpType.QNaN) - { - value2 = FPInfinity(true); - } - - return FPMax(value1, value2, state); - } - - public static double FPMin(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPMin: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2, state); - - double result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - if (value1 < value2) - { - if (type1 == FpType.Infinity) - { - result = FPInfinity(sign1); - } - else if (type1 == FpType.Zero) - { - result = FPZero(sign1 || sign2); - } - else - { - result = value1; - } - } - else - { - if (type2 == FpType.Infinity) - { - result = FPInfinity(sign2); - } - else if (type2 == FpType.Zero) - { - result = FPZero(sign1 || sign2); - } - else - { - result = value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && double.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0d); - } - } - } - } - - return result; - } - - public static double FPMinNum(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPMinNum: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1.FPUnpack(out FpType type1, out _, out _, state); - value2.FPUnpack(out FpType type2, out _, out _, state); - - if (type1 == FpType.QNaN && type2 != FpType.QNaN) - { - value1 = FPInfinity(false); - } - else if (type1 != FpType.QNaN && type2 == FpType.QNaN) - { - value2 = FPInfinity(false); - } - - return FPMin(value1, value2, state); - } - - public static double FPMul(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPMul: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2, state); - - double result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if ((inf1 && zero2) || (zero1 && inf2)) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else if (inf1 || inf2) - { - result = FPInfinity(sign1 ^ sign2); - } - else if (zero1 || zero2) - { - result = FPZero(sign1 ^ sign2); - } - else - { - result = value1 * value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && double.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0d); - } - } - } - - return result; - } - - public static double FPMulAdd( - double valueA, - double value1, - double value2, - CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPMulAdd: state.Fpcr = 0x{state.CFpcr:X8}"); - - valueA = valueA.FPUnpack(out FpType typeA, out bool signA, out ulong addend, state); - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2, state); - - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - double result = FPProcessNaNs3(typeA, type1, type2, addend, op1, op2, out bool done, state); - - if (typeA == FpType.QNaN && ((inf1 && zero2) || (zero1 && inf2))) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - - if (!done) - { - bool infA = typeA == FpType.Infinity; bool zeroA = typeA == FpType.Zero; - - bool signP = sign1 ^ sign2; - bool infP = inf1 || inf2; - bool zeroP = zero1 || zero2; - - if ((inf1 && zero2) || (zero1 && inf2) || (infA && infP && signA != signP)) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else if ((infA && !signA) || (infP && !signP)) - { - result = FPInfinity(false); - } - else if ((infA && signA) || (infP && signP)) - { - result = FPInfinity(true); - } - else if (zeroA && zeroP && signA == signP) - { - result = FPZero(signA); - } - else - { - // TODO: When available, use: T Math.FusedMultiplyAdd(T, T, T); - // https://github.com/dotnet/corefx/issues/31903 - - result = valueA + (value1 * value2); - - if (state.GetFpcrFlag(Fpcr.Fz) && double.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0d); - } - } - } - - return result; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double FPMulSub( - double valueA, - double value1, - double value2, - CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPMulSub: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPNeg(); - - return FPMulAdd(valueA, value1, value2, state); - } - - public static double FPMulX(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPMulX: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2, state); - - double result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if ((inf1 && zero2) || (zero1 && inf2)) - { - result = FPTwo(sign1 ^ sign2); - } - else if (inf1 || inf2) - { - result = FPInfinity(sign1 ^ sign2); - } - else if (zero1 || zero2) - { - result = FPZero(sign1 ^ sign2); - } - else - { - result = value1 * value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && double.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0d); - } - } - } - - return result; - } - - public static double FPRecipEstimate(double value, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPRecipEstimate: state.Fpcr = 0x{state.CFpcr:X8}"); - - value.FPUnpack(out FpType type, out bool sign, out ulong op, state); - - double result; - - if (type == FpType.SNaN || type == FpType.QNaN) - { - result = FPProcessNaN(type, op, state); - } - else if (type == FpType.Infinity) - { - result = FPZero(sign); - } - else if (type == FpType.Zero) - { - result = FPInfinity(sign); - - FPProcessException(FpExc.DivideByZero, state); - } - else if (Math.Abs(value) < Math.Pow(2d, -1024)) - { - bool overflowToInf; - - switch (state.FPRoundingMode()) - { - default: - case RoundMode.ToNearest: overflowToInf = true; break; - case RoundMode.TowardsPlusInfinity: overflowToInf = !sign; break; - case RoundMode.TowardsMinusInfinity: overflowToInf = sign; break; - case RoundMode.TowardsZero: overflowToInf = false; break; - } - - result = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign); - - FPProcessException(FpExc.Overflow, state); - FPProcessException(FpExc.Inexact, state); - } - else if (state.GetFpcrFlag(Fpcr.Fz) && (Math.Abs(value) >= Math.Pow(2d, 1022))) - { - result = FPZero(sign); - - state.SetFpsrFlag(Fpsr.Ufc); - } - else - { - ulong fraction = op & 0x000FFFFFFFFFFFFFul; - uint exp = (uint)((op & 0x7FF0000000000000ul) >> 52); - - if (exp == 0u) - { - if ((fraction & 0x0008000000000000ul) == 0ul) - { - fraction = (fraction & 0x0003FFFFFFFFFFFFul) << 2; - exp -= 1u; - } - else - { - fraction = (fraction & 0x0007FFFFFFFFFFFFul) << 1; - } - } - - uint scaled = (uint)(((fraction & 0x000FF00000000000ul) | 0x0010000000000000ul) >> 44); - - uint resultExp = 2045u - exp; - - uint estimate = (uint)SoftFloat.RecipEstimateTable[scaled - 256u] + 256u; - - fraction = (ulong)(estimate & 0xFFu) << 44; - - if (resultExp == 0u) - { - fraction = ((fraction & 0x000FFFFFFFFFFFFEul) | 0x0010000000000000ul) >> 1; - } - else if (resultExp + 1u == 0u) - { - fraction = ((fraction & 0x000FFFFFFFFFFFFCul) | 0x0010000000000000ul) >> 2; - resultExp = 0u; - } - - result = BitConverter.Int64BitsToDouble( - (long)((sign ? 1ul : 0ul) << 63 | (resultExp & 0x7FFul) << 52 | (fraction & 0x000FFFFFFFFFFFFFul))); - } - - return result; - } - - public static double FPRecipStepFused(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPRecipStepFused: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPNeg(); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2, state); - - double result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if ((inf1 && zero2) || (zero1 && inf2)) - { - result = FPTwo(false); - } - else if (inf1 || inf2) - { - result = FPInfinity(sign1 ^ sign2); - } - else - { - // TODO: When available, use: T Math.FusedMultiplyAdd(T, T, T); - // https://github.com/dotnet/corefx/issues/31903 - - result = 2d + (value1 * value2); - - if (state.GetFpcrFlag(Fpcr.Fz) && double.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0d); - } - } - } - - return result; - } - - public static double FPRecpX(double value, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPRecpX: state.Fpcr = 0x{state.CFpcr:X8}"); - - value.FPUnpack(out FpType type, out bool sign, out ulong op, state); - - double result; - - if (type == FpType.SNaN || type == FpType.QNaN) - { - result = FPProcessNaN(type, op, state); - } - else - { - ulong notExp = (~op >> 52) & 0x7FFul; - ulong maxExp = 0x7FEul; - - result = BitConverter.Int64BitsToDouble( - (long)((sign ? 1ul : 0ul) << 63 | (notExp == 0x7FFul ? maxExp : notExp) << 52)); - } - - return result; - } - - public static double FPRSqrtEstimate(double value, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPRSqrtEstimate: state.Fpcr = 0x{state.CFpcr:X8}"); - - value.FPUnpack(out FpType type, out bool sign, out ulong op, state); - - double result; - - if (type == FpType.SNaN || type == FpType.QNaN) - { - result = FPProcessNaN(type, op, state); - } - else if (type == FpType.Zero) - { - result = FPInfinity(sign); - - FPProcessException(FpExc.DivideByZero, state); - } - else if (sign) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else if (type == FpType.Infinity) - { - result = FPZero(false); - } - else - { - ulong fraction = op & 0x000FFFFFFFFFFFFFul; - uint exp = (uint)((op & 0x7FF0000000000000ul) >> 52); - - if (exp == 0u) - { - while ((fraction & 0x0008000000000000ul) == 0ul) - { - fraction = (fraction & 0x0007FFFFFFFFFFFFul) << 1; - exp -= 1u; - } - - fraction = (fraction & 0x0007FFFFFFFFFFFFul) << 1; - } - - uint scaled; - - if ((exp & 1u) == 0u) - { - scaled = (uint)(((fraction & 0x000FF00000000000ul) | 0x0010000000000000ul) >> 44); - } - else - { - scaled = (uint)(((fraction & 0x000FE00000000000ul) | 0x0010000000000000ul) >> 45); - } - - uint resultExp = (3068u - exp) >> 1; - - uint estimate = (uint)SoftFloat.RecipSqrtEstimateTable[scaled - 128u] + 256u; - - result = BitConverter.Int64BitsToDouble((long)((resultExp & 0x7FFul) << 52 | (estimate & 0xFFul) << 44)); - } - - return result; - } - - public static double FPRSqrtStepFused(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPRSqrtStepFused: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPNeg(); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2, state); - - double result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if ((inf1 && zero2) || (zero1 && inf2)) - { - result = FPOnePointFive(false); - } - else if (inf1 || inf2) - { - result = FPInfinity(sign1 ^ sign2); - } - else - { - // TODO: When available, use: T Math.FusedMultiplyAdd(T, T, T); - // https://github.com/dotnet/corefx/issues/31903 - - result = (3d + (value1 * value2)) / 2d; - - if (state.GetFpcrFlag(Fpcr.Fz) && double.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0d); - } - } - } - - return result; - } - - public static double FPSqrt(double value, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPSqrt: state.Fpcr = 0x{state.CFpcr:X8}"); - - value = value.FPUnpack(out FpType type, out bool sign, out ulong op, state); - - double result; - - if (type == FpType.SNaN || type == FpType.QNaN) - { - result = FPProcessNaN(type, op, state); - } - else if (type == FpType.Zero) - { - result = FPZero(sign); - } - else if (type == FpType.Infinity && !sign) - { - result = FPInfinity(sign); - } - else if (sign) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else - { - result = Math.Sqrt(value); - - if (state.GetFpcrFlag(Fpcr.Fz) && double.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0d); - } - } - - return result; - } - - public static double FPSub(double value1, double value2, CpuThreadState state) - { - Debug.WriteLineIf(state.CFpcr != 0, $"SoftFloat64.FPSub: state.Fpcr = 0x{state.CFpcr:X8}"); - - value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1, state); - value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2, state); - - double result = FPProcessNaNs(type1, type2, op1, op2, out bool done, state); - - if (!done) - { - bool inf1 = type1 == FpType.Infinity; bool zero1 = type1 == FpType.Zero; - bool inf2 = type2 == FpType.Infinity; bool zero2 = type2 == FpType.Zero; - - if (inf1 && inf2 && sign1 == sign2) - { - result = FPDefaultNaN(); - - FPProcessException(FpExc.InvalidOp, state); - } - else if ((inf1 && !sign1) || (inf2 && sign2)) - { - result = FPInfinity(false); - } - else if ((inf1 && sign1) || (inf2 && !sign2)) - { - result = FPInfinity(true); - } - else if (zero1 && zero2 && sign1 == !sign2) - { - result = FPZero(sign1); - } - else - { - result = value1 - value2; - - if (state.GetFpcrFlag(Fpcr.Fz) && double.IsSubnormal(result)) - { - state.SetFpsrFlag(Fpsr.Ufc); - - result = FPZero(result < 0d); - } - } - } - - return result; - } - - private static double FPDefaultNaN() - { - return -double.NaN; - } - - private static double FPInfinity(bool sign) - { - return sign ? double.NegativeInfinity : double.PositiveInfinity; - } - - private static double FPZero(bool sign) - { - return sign ? -0d : +0d; - } - - private static double FPMaxNormal(bool sign) - { - return sign ? double.MinValue : double.MaxValue; - } - - private static double FPTwo(bool sign) - { - return sign ? -2d : +2d; - } - - private static double FPOnePointFive(bool sign) - { - return sign ? -1.5d : +1.5d; - } - - private static double FPNeg(this double value) - { - return -value; - } - - private static double ZerosOrOnes(bool ones) - { - return BitConverter.Int64BitsToDouble(ones ? -1L : 0L); - } - - private static double FPUnpack( - this double value, - out FpType type, - out bool sign, - out ulong valueBits, - CpuThreadState state) - { - valueBits = (ulong)BitConverter.DoubleToInt64Bits(value); - - sign = (~valueBits & 0x8000000000000000ul) == 0ul; - - if ((valueBits & 0x7FF0000000000000ul) == 0ul) - { - if ((valueBits & 0x000FFFFFFFFFFFFFul) == 0ul || state.GetFpcrFlag(Fpcr.Fz)) - { - type = FpType.Zero; - value = FPZero(sign); - - if ((valueBits & 0x000FFFFFFFFFFFFFul) != 0ul) - { - FPProcessException(FpExc.InputDenorm, state); - } - } - else - { - type = FpType.Nonzero; - } - } - else if ((~valueBits & 0x7FF0000000000000ul) == 0ul) - { - if ((valueBits & 0x000FFFFFFFFFFFFFul) == 0ul) - { - type = FpType.Infinity; - } - else - { - type = (~valueBits & 0x0008000000000000ul) == 0ul ? FpType.QNaN : FpType.SNaN; - value = FPZero(sign); - } - } - else - { - type = FpType.Nonzero; - } - - return value; - } - - private static double FPProcessNaNs( - FpType type1, - FpType type2, - ulong op1, - ulong op2, - out bool done, - CpuThreadState state) - { - done = true; - - if (type1 == FpType.SNaN) - { - return FPProcessNaN(type1, op1, state); - } - else if (type2 == FpType.SNaN) - { - return FPProcessNaN(type2, op2, state); - } - else if (type1 == FpType.QNaN) - { - return FPProcessNaN(type1, op1, state); - } - else if (type2 == FpType.QNaN) - { - return FPProcessNaN(type2, op2, state); - } - - done = false; - - return FPZero(false); - } - - private static double FPProcessNaNs3( - FpType type1, - FpType type2, - FpType type3, - ulong op1, - ulong op2, - ulong op3, - out bool done, - CpuThreadState state) - { - done = true; - - if (type1 == FpType.SNaN) - { - return FPProcessNaN(type1, op1, state); - } - else if (type2 == FpType.SNaN) - { - return FPProcessNaN(type2, op2, state); - } - else if (type3 == FpType.SNaN) - { - return FPProcessNaN(type3, op3, state); - } - else if (type1 == FpType.QNaN) - { - return FPProcessNaN(type1, op1, state); - } - else if (type2 == FpType.QNaN) - { - return FPProcessNaN(type2, op2, state); - } - else if (type3 == FpType.QNaN) - { - return FPProcessNaN(type3, op3, state); - } - - done = false; - - return FPZero(false); - } - - private static double FPProcessNaN(FpType type, ulong op, CpuThreadState state) - { - if (type == FpType.SNaN) - { - op |= 1ul << 51; - - FPProcessException(FpExc.InvalidOp, state); - } - - if (state.GetFpcrFlag(Fpcr.Dn)) - { - return FPDefaultNaN(); - } - - return BitConverter.Int64BitsToDouble((long)op); - } - - private static void FPProcessException(FpExc exc, CpuThreadState state) - { - int enable = (int)exc + 8; - - if ((state.CFpcr & (1 << enable)) != 0) - { - throw new NotImplementedException("Floating-point trap handling."); - } - else - { - state.CFpsr |= 1 << (int)exc; - } - } - } -} diff --git a/ChocolArm64/Instructions/VectorHelper.cs b/ChocolArm64/Instructions/VectorHelper.cs deleted file mode 100644 index 4d57e285..00000000 --- a/ChocolArm64/Instructions/VectorHelper.cs +++ /dev/null @@ -1,646 +0,0 @@ -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Runtime.CompilerServices; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -namespace ChocolArm64.Instructions -{ - static class VectorHelper - { - public static void EmitCall(ILEmitterCtx context, string name64, string name128) - { - bool isSimd64 = context.CurrOp.RegisterSize == RegisterSize.Simd64; - - context.EmitCall(typeof(VectorHelper), isSimd64 ? name64 : name128); - } - - public static void EmitCall(ILEmitterCtx context, string mthdName) - { - context.EmitCall(typeof(VectorHelper), mthdName); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int SatF32ToS32(float value) - { - if (float.IsNaN(value)) return 0; - - return value >= int.MaxValue ? int.MaxValue : - value <= int.MinValue ? int.MinValue : (int)value; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long SatF32ToS64(float value) - { - if (float.IsNaN(value)) return 0; - - return value >= long.MaxValue ? long.MaxValue : - value <= long.MinValue ? long.MinValue : (long)value; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint SatF32ToU32(float value) - { - if (float.IsNaN(value)) return 0; - - return value >= uint.MaxValue ? uint.MaxValue : - value <= uint.MinValue ? uint.MinValue : (uint)value; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong SatF32ToU64(float value) - { - if (float.IsNaN(value)) return 0; - - return value >= ulong.MaxValue ? ulong.MaxValue : - value <= ulong.MinValue ? ulong.MinValue : (ulong)value; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int SatF64ToS32(double value) - { - if (double.IsNaN(value)) return 0; - - return value >= int.MaxValue ? int.MaxValue : - value <= int.MinValue ? int.MinValue : (int)value; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long SatF64ToS64(double value) - { - if (double.IsNaN(value)) return 0; - - return value >= long.MaxValue ? long.MaxValue : - value <= long.MinValue ? long.MinValue : (long)value; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint SatF64ToU32(double value) - { - if (double.IsNaN(value)) return 0; - - return value >= uint.MaxValue ? uint.MaxValue : - value <= uint.MinValue ? uint.MinValue : (uint)value; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong SatF64ToU64(double value) - { - if (double.IsNaN(value)) return 0; - - return value >= ulong.MaxValue ? ulong.MaxValue : - value <= ulong.MinValue ? ulong.MinValue : (ulong)value; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Round(double value, CpuThreadState state) - { - RoundMode roundMode = state.FPRoundingMode(); - - if (roundMode == RoundMode.ToNearest) - { - return Math.Round(value); // even - } - else if (roundMode == RoundMode.TowardsPlusInfinity) - { - return Math.Ceiling(value); - } - else if (roundMode == RoundMode.TowardsMinusInfinity) - { - return Math.Floor(value); - } - else /* if (roundMode == RoundMode.TowardsZero) */ - { - return Math.Truncate(value); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float RoundF(float value, CpuThreadState state) - { - RoundMode roundMode = state.FPRoundingMode(); - - if (roundMode == RoundMode.ToNearest) - { - return MathF.Round(value); // even - } - else if (roundMode == RoundMode.TowardsPlusInfinity) - { - return MathF.Ceiling(value); - } - else if (roundMode == RoundMode.TowardsMinusInfinity) - { - return MathF.Floor(value); - } - else /* if (roundMode == RoundMode.TowardsZero) */ - { - return MathF.Truncate(value); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<double> Sse41ScalarRound(Vector128<double> upper, Vector128<double> value, CpuThreadState state) - { - if (!Sse41.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - RoundMode roundMode = state.FPRoundingMode(); - - if (roundMode == RoundMode.ToNearest) - { - return Sse41.RoundToNearestIntegerScalar(upper, value); // even - } - else if (roundMode == RoundMode.TowardsPlusInfinity) - { - return Sse41.RoundToPositiveInfinityScalar(upper, value); - } - else if (roundMode == RoundMode.TowardsMinusInfinity) - { - return Sse41.RoundToNegativeInfinityScalar(upper, value); - } - else /* if (roundMode == RoundMode.TowardsZero) */ - { - return Sse41.RoundToZeroScalar(upper, value); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> Sse41ScalarRoundF(Vector128<float> upper, Vector128<float> value, CpuThreadState state) - { - if (!Sse41.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - RoundMode roundMode = state.FPRoundingMode(); - - if (roundMode == RoundMode.ToNearest) - { - return Sse41.RoundToNearestIntegerScalar(upper, value); // even - } - else if (roundMode == RoundMode.TowardsPlusInfinity) - { - return Sse41.RoundToPositiveInfinityScalar(upper, value); - } - else if (roundMode == RoundMode.TowardsMinusInfinity) - { - return Sse41.RoundToNegativeInfinityScalar(upper, value); - } - else /* if (roundMode == RoundMode.TowardsZero) */ - { - return Sse41.RoundToZeroScalar(upper, value); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<double> Sse41VectorRound(Vector128<double> value, CpuThreadState state) - { - if (!Sse41.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - RoundMode roundMode = state.FPRoundingMode(); - - if (roundMode == RoundMode.ToNearest) - { - return Sse41.RoundToNearestInteger(value); // even - } - else if (roundMode == RoundMode.TowardsPlusInfinity) - { - return Sse41.RoundToPositiveInfinity(value); - } - else if (roundMode == RoundMode.TowardsMinusInfinity) - { - return Sse41.RoundToNegativeInfinity(value); - } - else /* if (roundMode == RoundMode.TowardsZero) */ - { - return Sse41.RoundToZero(value); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> Sse41VectorRoundF(Vector128<float> value, CpuThreadState state) - { - if (!Sse41.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - RoundMode roundMode = state.FPRoundingMode(); - - if (roundMode == RoundMode.ToNearest) - { - return Sse41.RoundToNearestInteger(value); // even - } - else if (roundMode == RoundMode.TowardsPlusInfinity) - { - return Sse41.RoundToPositiveInfinity(value); - } - else if (roundMode == RoundMode.TowardsMinusInfinity) - { - return Sse41.RoundToNegativeInfinity(value); - } - else /* if (roundMode == RoundMode.TowardsZero) */ - { - return Sse41.RoundToZero(value); - } - } - - public static Vector128<float> Tbl1_V64( - Vector128<float> vector, - Vector128<float> tb0) - { - return Tbl(vector, 8, tb0); - } - - public static Vector128<float> Tbl1_V128( - Vector128<float> vector, - Vector128<float> tb0) - { - return Tbl(vector, 16, tb0); - } - - public static Vector128<float> Tbl2_V64( - Vector128<float> vector, - Vector128<float> tb0, - Vector128<float> tb1) - { - return Tbl(vector, 8, tb0, tb1); - } - - public static Vector128<float> Tbl2_V128( - Vector128<float> vector, - Vector128<float> tb0, - Vector128<float> tb1) - { - return Tbl(vector, 16, tb0, tb1); - } - - public static Vector128<float> Tbl3_V64( - Vector128<float> vector, - Vector128<float> tb0, - Vector128<float> tb1, - Vector128<float> tb2) - { - return Tbl(vector, 8, tb0, tb1, tb2); - } - - public static Vector128<float> Tbl3_V128( - Vector128<float> vector, - Vector128<float> tb0, - Vector128<float> tb1, - Vector128<float> tb2) - { - return Tbl(vector, 16, tb0, tb1, tb2); - } - - public static Vector128<float> Tbl4_V64( - Vector128<float> vector, - Vector128<float> tb0, - Vector128<float> tb1, - Vector128<float> tb2, - Vector128<float> tb3) - { - return Tbl(vector, 8, tb0, tb1, tb2, tb3); - } - - public static Vector128<float> Tbl4_V128( - Vector128<float> vector, - Vector128<float> tb0, - Vector128<float> tb1, - Vector128<float> tb2, - Vector128<float> tb3) - { - return Tbl(vector, 16, tb0, tb1, tb2, tb3); - } - - private static Vector128<float> Tbl(Vector128<float> vector, int bytes, params Vector128<float>[] tb) - { - Vector128<float> res = new Vector128<float>(); - - byte[] table = new byte[tb.Length * 16]; - - for (byte index = 0; index < tb.Length; index++) - for (byte index2 = 0; index2 < 16; index2++) - { - table[index * 16 + index2] = (byte)VectorExtractIntZx(tb[index], index2, 0); - } - - for (byte index = 0; index < bytes; index++) - { - byte tblIdx = (byte)VectorExtractIntZx(vector, index, 0); - - if (tblIdx < table.Length) - { - res = VectorInsertInt(table[tblIdx], res, index, 0); - } - } - - return res; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double VectorExtractDouble(Vector128<float> vector, byte index) - { - if (Sse41.IsSupported) - { - return BitConverter.Int64BitsToDouble(Sse41.Extract(Sse.StaticCast<float, long>(vector), index)); - } - else if (Sse2.IsSupported) - { - return BitConverter.Int64BitsToDouble((long)VectorExtractIntZx(vector, index, 3)); - } - - throw new PlatformNotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long VectorExtractIntSx(Vector128<float> vector, byte index, int size) - { - if (Sse41.IsSupported) - { - if (size == 0) - { - return (sbyte)Sse41.Extract(Sse.StaticCast<float, byte>(vector), index); - } - else if (size == 1) - { - return (short)Sse2.Extract(Sse.StaticCast<float, ushort>(vector), index); - } - else if (size == 2) - { - return Sse41.Extract(Sse.StaticCast<float, int>(vector), index); - } - else if (size == 3) - { - return Sse41.Extract(Sse.StaticCast<float, long>(vector), index); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - } - else if (Sse2.IsSupported) - { - if (size == 0) - { - return (sbyte)VectorExtractIntZx(vector, index, size); - } - else if (size == 1) - { - return (short)VectorExtractIntZx(vector, index, size); - } - else if (size == 2) - { - return (int)VectorExtractIntZx(vector, index, size); - } - else if (size == 3) - { - return (long)VectorExtractIntZx(vector, index, size); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - } - - throw new PlatformNotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong VectorExtractIntZx(Vector128<float> vector, byte index, int size) - { - if (Sse41.IsSupported) - { - if (size == 0) - { - return Sse41.Extract(Sse.StaticCast<float, byte>(vector), index); - } - else if (size == 1) - { - return Sse2.Extract(Sse.StaticCast<float, ushort>(vector), index); - } - else if (size == 2) - { - return Sse41.Extract(Sse.StaticCast<float, uint>(vector), index); - } - else if (size == 3) - { - return Sse41.Extract(Sse.StaticCast<float, ulong>(vector), index); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - } - else if (Sse2.IsSupported) - { - int shortIdx = size == 0 - ? index >> 1 - : index << (size - 1); - - ushort value = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)shortIdx); - - if (size == 0) - { - return (byte)(value >> (index & 1) * 8); - } - else if (size == 1) - { - return value; - } - else if (size == 2 || size == 3) - { - ushort value1 = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)(shortIdx + 1)); - - if (size == 2) - { - return (uint)(value | (value1 << 16)); - } - - ushort value2 = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)(shortIdx + 2)); - ushort value3 = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)(shortIdx + 3)); - - return ((ulong)value << 0) | - ((ulong)value1 << 16) | - ((ulong)value2 << 32) | - ((ulong)value3 << 48); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - } - - throw new PlatformNotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float VectorExtractSingle(Vector128<float> vector, byte index) - { - if (Sse41.IsSupported) - { - return Sse41.Extract(vector, index); - } - else if (Sse2.IsSupported) - { - Vector128<ushort> shortVector = Sse.StaticCast<float, ushort>(vector); - - int low = Sse2.Extract(shortVector, (byte)(index * 2 + 0)); - int high = Sse2.Extract(shortVector, (byte)(index * 2 + 1)); - - return BitConverter.Int32BitsToSingle(low | (high << 16)); - } - - throw new PlatformNotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> VectorInsertDouble(double value, Vector128<float> vector, byte index) - { - return VectorInsertInt((ulong)BitConverter.DoubleToInt64Bits(value), vector, index, 3); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> VectorInsertInt(ulong value, Vector128<float> vector, byte index, int size) - { - if (Sse41.IsSupported) - { - if (size == 0) - { - return Sse.StaticCast<byte, float>(Sse41.Insert(Sse.StaticCast<float, byte>(vector), (byte)value, index)); - } - else if (size == 1) - { - return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse.StaticCast<float, ushort>(vector), (ushort)value, index)); - } - else if (size == 2) - { - return Sse.StaticCast<uint, float>(Sse41.Insert(Sse.StaticCast<float, uint>(vector), (uint)value, index)); - } - else if (size == 3) - { - return Sse.StaticCast<ulong, float>(Sse41.Insert(Sse.StaticCast<float, ulong>(vector), value, index)); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - } - else if (Sse2.IsSupported) - { - Vector128<ushort> shortVector = Sse.StaticCast<float, ushort>(vector); - - int shortIdx = size == 0 - ? index >> 1 - : index << (size - 1); - - if (size == 0) - { - ushort shortVal = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)shortIdx); - - int shift = (index & 1) * 8; - - shortVal &= (ushort)(0xff00 >> shift); - - shortVal |= (ushort)((byte)value << shift); - - return Sse.StaticCast<ushort, float>(Sse2.Insert(shortVector, shortVal, (byte)shortIdx)); - } - else if (size == 1) - { - return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse.StaticCast<float, ushort>(vector), (ushort)value, index)); - } - else if (size == 2 || size == 3) - { - shortVector = Sse2.Insert(shortVector, (ushort)(value >> 0), (byte)(shortIdx + 0)); - shortVector = Sse2.Insert(shortVector, (ushort)(value >> 16), (byte)(shortIdx + 1)); - - if (size == 3) - { - shortVector = Sse2.Insert(shortVector, (ushort)(value >> 32), (byte)(shortIdx + 2)); - shortVector = Sse2.Insert(shortVector, (ushort)(value >> 48), (byte)(shortIdx + 3)); - } - - return Sse.StaticCast<ushort, float>(shortVector); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - } - - throw new PlatformNotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> VectorInsertSingle(float value, Vector128<float> vector, byte index) - { - if (Sse41.IsSupported) - { - // Note: The if/else if is necessary to enable the JIT to - // produce a single INSERTPS instruction instead of the - // jump table fallback. - if (index == 0) - { - return Sse41.Insert(vector, value, 0x00); - } - else if (index == 1) - { - return Sse41.Insert(vector, value, 0x10); - } - else if (index == 2) - { - return Sse41.Insert(vector, value, 0x20); - } - else if (index == 3) - { - return Sse41.Insert(vector, value, 0x30); - } - else - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - } - else if (Sse2.IsSupported) - { - int intValue = BitConverter.SingleToInt32Bits(value); - - ushort low = (ushort)(intValue >> 0); - ushort high = (ushort)(intValue >> 16); - - Vector128<ushort> shortVector = Sse.StaticCast<float, ushort>(vector); - - shortVector = Sse2.Insert(shortVector, low, (byte)(index * 2 + 0)); - shortVector = Sse2.Insert(shortVector, high, (byte)(index * 2 + 1)); - - return Sse.StaticCast<ushort, float>(shortVector); - } - - throw new PlatformNotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> Sse41VectorInsertScalarSingle(float value, Vector128<float> vector) - { - // Note: 0b1110 is the mask to zero the upper bits. - return Sse41.Insert(vector, value, 0b1110); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128<float> VectorSingleZero() - { - if (Sse.IsSupported) - { - return Sse.SetZeroVector128(); - } - - throw new PlatformNotSupportedException(); - } - } -} diff --git a/ChocolArm64/IntermediateRepresentation/BasicBlock.cs b/ChocolArm64/IntermediateRepresentation/BasicBlock.cs deleted file mode 100644 index ce39fddb..00000000 --- a/ChocolArm64/IntermediateRepresentation/BasicBlock.cs +++ /dev/null @@ -1,122 +0,0 @@ -using ChocolArm64.State; -using System; -using System.Collections.Generic; - -using static ChocolArm64.State.RegisterConsts; - -namespace ChocolArm64.IntermediateRepresentation -{ - class BasicBlock - { - public int Index { get; set; } - - public RegisterMask RegInputs { get; private set; } - public RegisterMask RegOutputs { get; private set; } - - public bool HasStateLoad { get; private set; } - - private List<Operation> _operations; - - public int Count => _operations.Count; - - private BasicBlock _next; - private BasicBlock _branch; - - public BasicBlock Next - { - get => _next; - set => _next = AddSuccessor(_next, value); - } - - public BasicBlock Branch - { - get => _branch; - set => _branch = AddSuccessor(_branch, value); - } - - public List<BasicBlock> Predecessors { get; } - - public BasicBlock(int index = 0) - { - Index = index; - - _operations = new List<Operation>(); - - Predecessors = new List<BasicBlock>(); - } - - private BasicBlock AddSuccessor(BasicBlock oldBlock, BasicBlock newBlock) - { - oldBlock?.Predecessors.Remove(this); - newBlock?.Predecessors.Add(this); - - return newBlock; - } - - public void Add(Operation operation) - { - if (operation.Type == OperationType.LoadLocal || - operation.Type == OperationType.StoreLocal) - { - int index = operation.GetArg<int>(0); - - if (IsRegIndex(index)) - { - long intMask = 0; - long vecMask = 0; - - switch (operation.GetArg<RegisterType>(1)) - { - case RegisterType.Flag: intMask = (1L << RegsCount) << index; break; - case RegisterType.Int: intMask = 1L << index; break; - case RegisterType.Vector: vecMask = 1L << index; break; - } - - RegisterMask mask = new RegisterMask(intMask, vecMask); - - if (operation.Type == OperationType.LoadLocal) - { - RegInputs |= mask & ~RegOutputs; - } - else - { - RegOutputs |= mask; - } - } - } - else if (operation.Type == OperationType.LoadContext) - { - HasStateLoad = true; - } - - operation.Parent = this; - - _operations.Add(operation); - } - - public static bool IsRegIndex(int index) - { - return (uint)index < RegsCount; - } - - public Operation GetOperation(int index) - { - if ((uint)index >= _operations.Count) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - - return _operations[index]; - } - - public Operation GetLastOp() - { - if (Count == 0) - { - return null; - } - - return _operations[Count - 1]; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/IntermediateRepresentation/ILLabel.cs b/ChocolArm64/IntermediateRepresentation/ILLabel.cs deleted file mode 100644 index 70c576cd..00000000 --- a/ChocolArm64/IntermediateRepresentation/ILLabel.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace ChocolArm64.IntermediateRepresentation -{ - class ILLabel { } -}
\ No newline at end of file diff --git a/ChocolArm64/IntermediateRepresentation/Operation.cs b/ChocolArm64/IntermediateRepresentation/Operation.cs deleted file mode 100644 index dcd01bcd..00000000 --- a/ChocolArm64/IntermediateRepresentation/Operation.cs +++ /dev/null @@ -1,112 +0,0 @@ -using ChocolArm64.State; -using System; -using System.Reflection; -using System.Reflection.Emit; - -namespace ChocolArm64.IntermediateRepresentation -{ - class Operation - { - public BasicBlock Parent { get; set; } - - public OperationType Type { get; } - - private object[] _arguments { get; } - - private Operation(OperationType type, params object[] arguments) - { - Type = type; - _arguments = arguments; - } - - public T GetArg<T>(int index) - { - return (T)GetArg(index); - } - - public object GetArg(int index) - { - if ((uint)index >= _arguments.Length) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - - return _arguments[index]; - } - - public static Operation Call(MethodInfo info) - { - return new Operation(OperationType.Call, info); - } - - public static Operation CallVirtual(MethodInfo info) - { - return new Operation(OperationType.CallVirtual, info); - } - - public static Operation IL(OpCode ilOp) - { - return new Operation(OperationType.IL, ilOp); - } - - public static Operation ILBranch(OpCode ilOp, ILLabel target) - { - return new Operation(OperationType.ILBranch, ilOp, target); - } - - public static Operation LoadArgument(int index) - { - return new Operation(OperationType.LoadArgument, index); - } - - public static Operation LoadConstant(int value) - { - return new Operation(OperationType.LoadConstant, value); - } - - public static Operation LoadConstant(long value) - { - return new Operation(OperationType.LoadConstant, value); - } - - public static Operation LoadConstant(float value) - { - return new Operation(OperationType.LoadConstant, value); - } - - public static Operation LoadConstant(double value) - { - return new Operation(OperationType.LoadConstant, value); - } - - public static Operation LoadContext() - { - return new Operation(OperationType.LoadContext); - } - - public static Operation LoadField(FieldInfo info) - { - return new Operation(OperationType.LoadField, info); - } - - public static Operation LoadLocal(int index, RegisterType type, RegisterSize size) - { - return new Operation(OperationType.LoadLocal, index, type, size); - } - - public static Operation MarkLabel(ILLabel label) - { - return new Operation(OperationType.MarkLabel, label); - } - - public static Operation StoreContext() - { - return new Operation(OperationType.StoreContext); - } - - public static Operation StoreLocal(int index, RegisterType type, RegisterSize size) - { - return new Operation(OperationType.StoreLocal, index, type, size); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/IntermediateRepresentation/OperationType.cs b/ChocolArm64/IntermediateRepresentation/OperationType.cs deleted file mode 100644 index 644f1716..00000000 --- a/ChocolArm64/IntermediateRepresentation/OperationType.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace ChocolArm64.IntermediateRepresentation -{ - enum OperationType - { - Call, - CallVirtual, - IL, - ILBranch, - LoadArgument, - LoadConstant, - LoadContext, - LoadField, - LoadLocal, - MarkLabel, - StoreContext, - StoreLocal - } -}
\ No newline at end of file diff --git a/ChocolArm64/IntermediateRepresentation/RegisterMask.cs b/ChocolArm64/IntermediateRepresentation/RegisterMask.cs deleted file mode 100644 index aea6ab36..00000000 --- a/ChocolArm64/IntermediateRepresentation/RegisterMask.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; - -namespace ChocolArm64.IntermediateRepresentation -{ - struct RegisterMask : IEquatable<RegisterMask> - { - public long IntMask { get; set; } - public long VecMask { get; set; } - - public RegisterMask(long intMask, long vecMask) - { - IntMask = intMask; - VecMask = vecMask; - } - - public static RegisterMask operator &(RegisterMask x, RegisterMask y) - { - return new RegisterMask(x.IntMask & y.IntMask, x.VecMask & y.VecMask); - } - - public static RegisterMask operator |(RegisterMask x, RegisterMask y) - { - return new RegisterMask(x.IntMask | y.IntMask, x.VecMask | y.VecMask); - } - - public static RegisterMask operator ~(RegisterMask x) - { - return new RegisterMask(~x.IntMask, ~x.VecMask); - } - - public static bool operator ==(RegisterMask x, RegisterMask y) - { - return x.Equals(y); - } - - public static bool operator !=(RegisterMask x, RegisterMask y) - { - return !x.Equals(y); - } - - public override bool Equals(object obj) - { - return obj is RegisterMask regMask && Equals(regMask); - } - - public bool Equals(RegisterMask other) - { - return IntMask == other.IntMask && VecMask == other.VecMask; - } - - public override int GetHashCode() - { - return HashCode.Combine(IntMask, VecMask); - } - } -} diff --git a/ChocolArm64/Memory/CompareExchange128.cs b/ChocolArm64/Memory/CompareExchange128.cs deleted file mode 100644 index 1618ff0f..00000000 --- a/ChocolArm64/Memory/CompareExchange128.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace ChocolArm64.Memory -{ - static class CompareExchange128 - { - private struct Int128 - { - public ulong Low { get; } - public ulong High { get; } - - public Int128(ulong low, ulong high) - { - Low = low; - High = high; - } - } - - private delegate Int128 InterlockedCompareExchange(IntPtr address, Int128 expected, Int128 desired); - - private delegate int GetCpuId(); - - private static InterlockedCompareExchange _interlockedCompareExchange; - - static CompareExchange128() - { - if (RuntimeInformation.OSArchitecture != Architecture.X64 || !IsCmpxchg16bSupported()) - { - throw new PlatformNotSupportedException(); - } - - byte[] interlockedCompareExchange128Code; - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - interlockedCompareExchange128Code = new byte[] - { - 0x53, // push rbx - 0x49, 0x8b, 0x00, // mov rax, [r8] - 0x49, 0x8b, 0x19, // mov rbx, [r9] - 0x49, 0x89, 0xca, // mov r10, rcx - 0x49, 0x89, 0xd3, // mov r11, rdx - 0x49, 0x8b, 0x49, 0x08, // mov rcx, [r9+8] - 0x49, 0x8b, 0x50, 0x08, // mov rdx, [r8+8] - 0xf0, 0x49, 0x0f, 0xc7, 0x0b, // lock cmpxchg16b [r11] - 0x49, 0x89, 0x02, // mov [r10], rax - 0x4c, 0x89, 0xd0, // mov rax, r10 - 0x49, 0x89, 0x52, 0x08, // mov [r10+8], rdx - 0x5b, // pop rbx - 0xc3 // ret - }; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || - RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - interlockedCompareExchange128Code = new byte[] - { - 0x53, // push rbx - 0x49, 0x89, 0xd1, // mov r9, rdx - 0x48, 0x89, 0xcb, // mov rbx, rcx - 0x48, 0x89, 0xf0, // mov rax, rsi - 0x4c, 0x89, 0xca, // mov rdx, r9 - 0x4c, 0x89, 0xc1, // mov rcx, r8 - 0xf0, 0x48, 0x0f, 0xc7, 0x0f, // lock cmpxchg16b [rdi] - 0x5b, // pop rbx - 0xc3 // ret - }; - } - else - { - throw new PlatformNotSupportedException(); - } - - IntPtr funcPtr = MapCodeAsExecutable(interlockedCompareExchange128Code); - - _interlockedCompareExchange = Marshal.GetDelegateForFunctionPointer<InterlockedCompareExchange>(funcPtr); - } - - private static bool IsCmpxchg16bSupported() - { - byte[] getCpuIdCode = new byte[] - { - 0x53, // push rbx - 0xb8, 0x01, 0x00, 0x00, 0x00, // mov eax, 0x1 - 0x0f, 0xa2, // cpuid - 0x89, 0xc8, // mov eax, ecx - 0x5b, // pop rbx - 0xc3 // ret - }; - - IntPtr funcPtr = MapCodeAsExecutable(getCpuIdCode); - - GetCpuId getCpuId = Marshal.GetDelegateForFunctionPointer<GetCpuId>(funcPtr); - - int cpuId = getCpuId(); - - MemoryManagement.Free(funcPtr); - - return (cpuId & (1 << 13)) != 0; - } - - private static IntPtr MapCodeAsExecutable(byte[] code) - { - ulong codeLength = (ulong)code.Length; - - IntPtr funcPtr = MemoryManagement.Allocate(codeLength); - - unsafe - { - fixed (byte* codePtr = code) - { - byte* dest = (byte*)funcPtr; - - long size = (long)codeLength; - - Buffer.MemoryCopy(codePtr, dest, size, size); - } - } - - MemoryManagement.Reprotect(funcPtr, codeLength, MemoryProtection.Execute); - - return funcPtr; - } - - public static bool InterlockedCompareExchange128( - IntPtr address, - ulong expectedLow, - ulong expectedHigh, - ulong desiredLow, - ulong desiredHigh) - { - Int128 expected = new Int128(expectedLow, expectedHigh); - Int128 desired = new Int128(desiredLow, desiredHigh); - - Int128 old = _interlockedCompareExchange(address, expected, desired); - - return old.Low == expected.Low && old.High == expected.High; - } - - public static void InterlockedRead128(IntPtr address, out ulong low, out ulong high) - { - Int128 zero = new Int128(0, 0); - - Int128 old = _interlockedCompareExchange(address, zero, zero); - - low = old.Low; - high = old.High; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Memory/IMemory.cs b/ChocolArm64/Memory/IMemory.cs deleted file mode 100644 index dc582155..00000000 --- a/ChocolArm64/Memory/IMemory.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace ChocolArm64.Memory -{ - public interface IMemory - { - sbyte ReadSByte(long position); - - short ReadInt16(long position); - - int ReadInt32(long position); - - long ReadInt64(long position); - - byte ReadByte(long position); - - ushort ReadUInt16(long position); - - uint ReadUInt32(long position); - - ulong ReadUInt64(long position); - - void WriteSByte(long position, sbyte value); - - void WriteInt16(long position, short value); - - void WriteInt32(long position, int value); - - void WriteInt64(long position, long value); - - void WriteByte(long position, byte value); - - void WriteUInt16(long position, ushort value); - - void WriteUInt32(long position, uint value); - - void WriteUInt64(long position, ulong value); - } -}
\ No newline at end of file diff --git a/ChocolArm64/Memory/MemoryHelper.cs b/ChocolArm64/Memory/MemoryHelper.cs deleted file mode 100644 index 1c436dd8..00000000 --- a/ChocolArm64/Memory/MemoryHelper.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; - -namespace ChocolArm64.Memory -{ - public static class MemoryHelper - { - public static void FillWithZeros(MemoryManager memory, long position, int size) - { - int size8 = size & ~(8 - 1); - - for (int offs = 0; offs < size8; offs += 8) - { - memory.WriteInt64(position + offs, 0); - } - - for (int offs = size8; offs < (size - size8); offs++) - { - memory.WriteByte(position + offs, 0); - } - } - - public unsafe static T Read<T>(MemoryManager memory, long position) where T : struct - { - long size = Marshal.SizeOf<T>(); - - byte[] data = memory.ReadBytes(position, size); - - fixed (byte* ptr = data) - { - return Marshal.PtrToStructure<T>((IntPtr)ptr); - } - } - - public unsafe static void Write<T>(MemoryManager memory, long position, T value) where T : struct - { - long size = Marshal.SizeOf<T>(); - - byte[] data = new byte[size]; - - fixed (byte* ptr = data) - { - Marshal.StructureToPtr<T>(value, (IntPtr)ptr, false); - } - - memory.WriteBytes(position, data); - } - - public static string ReadAsciiString(MemoryManager memory, long position, long maxSize = -1) - { - using (MemoryStream ms = new MemoryStream()) - { - for (long offs = 0; offs < maxSize || maxSize == -1; offs++) - { - byte value = (byte)memory.ReadByte(position + offs); - - if (value == 0) - { - break; - } - - ms.WriteByte(value); - } - - return Encoding.ASCII.GetString(ms.ToArray()); - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Memory/MemoryManagement.cs b/ChocolArm64/Memory/MemoryManagement.cs deleted file mode 100644 index 80585791..00000000 --- a/ChocolArm64/Memory/MemoryManagement.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace ChocolArm64.Memory -{ - public static class MemoryManagement - { - public static bool HasWriteWatchSupport => RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - - public static IntPtr Allocate(ulong size) - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - IntPtr sizeNint = new IntPtr((long)size); - - return MemoryManagementWindows.Allocate(sizeNint); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || - RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return MemoryManagementUnix.Allocate(size); - } - else - { - throw new PlatformNotSupportedException(); - } - } - - public static IntPtr AllocateWriteTracked(ulong size) - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - IntPtr sizeNint = new IntPtr((long)size); - - return MemoryManagementWindows.AllocateWriteTracked(sizeNint); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || - RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return MemoryManagementUnix.Allocate(size); - } - else - { - throw new PlatformNotSupportedException(); - } - } - - public static void Reprotect(IntPtr address, ulong size, MemoryProtection permission) - { - bool result; - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - IntPtr sizeNint = new IntPtr((long)size); - - result = MemoryManagementWindows.Reprotect(address, sizeNint, permission); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || - RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - result = MemoryManagementUnix.Reprotect(address, size, permission); - } - else - { - throw new PlatformNotSupportedException(); - } - - if (!result) - { - throw new MemoryProtectionException(permission); - } - } - - public static bool Free(IntPtr address) - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return MemoryManagementWindows.Free(address); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || - RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return MemoryManagementUnix.Free(address); - } - else - { - throw new PlatformNotSupportedException(); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool GetModifiedPages( - IntPtr address, - IntPtr size, - IntPtr[] addresses, - out ulong count) - { - // This is only supported on windows, but returning - // false (failed) is also valid for platforms without - // write tracking support on the OS. - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return MemoryManagementWindows.GetModifiedPages(address, size, addresses, out count); - } - else - { - count = 0; - - return false; - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Memory/MemoryManagementUnix.cs b/ChocolArm64/Memory/MemoryManagementUnix.cs deleted file mode 100644 index fe3cfb7e..00000000 --- a/ChocolArm64/Memory/MemoryManagementUnix.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Mono.Unix.Native; -using System; - -namespace ChocolArm64.Memory -{ - static class MemoryManagementUnix - { - public static IntPtr Allocate(ulong size) - { - ulong pageSize = (ulong)Syscall.sysconf(SysconfName._SC_PAGESIZE); - - const MmapProts prot = MmapProts.PROT_READ | MmapProts.PROT_WRITE; - - const MmapFlags flags = MmapFlags.MAP_PRIVATE | MmapFlags.MAP_ANONYMOUS; - - IntPtr ptr = Syscall.mmap(IntPtr.Zero, size + pageSize, prot, flags, -1, 0); - - if (ptr == IntPtr.Zero) - { - throw new OutOfMemoryException(); - } - - unsafe - { - ptr = new IntPtr(ptr.ToInt64() + (long)pageSize); - - *((ulong*)ptr - 1) = size; - } - - return ptr; - } - - public static bool Reprotect(IntPtr address, ulong size, MemoryProtection protection) - { - MmapProts prot = GetProtection(protection); - - return Syscall.mprotect(address, size, prot) == 0; - } - - private static MmapProts GetProtection(MemoryProtection protection) - { - switch (protection) - { - case MemoryProtection.None: return MmapProts.PROT_NONE; - case MemoryProtection.Read: return MmapProts.PROT_READ; - case MemoryProtection.ReadAndWrite: return MmapProts.PROT_READ | MmapProts.PROT_WRITE; - case MemoryProtection.ReadAndExecute: return MmapProts.PROT_READ | MmapProts.PROT_EXEC; - case MemoryProtection.Execute: return MmapProts.PROT_EXEC; - - default: throw new ArgumentException($"Invalid permission \"{protection}\"."); - } - } - - public static bool Free(IntPtr address) - { - ulong pageSize = (ulong)Syscall.sysconf(SysconfName._SC_PAGESIZE); - - ulong size; - - unsafe - { - size = *((ulong*)address - 1); - - address = new IntPtr(address.ToInt64() - (long)pageSize); - } - - return Syscall.munmap(address, size + pageSize) == 0; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Memory/MemoryManagementWindows.cs b/ChocolArm64/Memory/MemoryManagementWindows.cs deleted file mode 100644 index 6cee1342..00000000 --- a/ChocolArm64/Memory/MemoryManagementWindows.cs +++ /dev/null @@ -1,155 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace ChocolArm64.Memory -{ - static class MemoryManagementWindows - { - [Flags] - private enum AllocationType : uint - { - Commit = 0x1000, - Reserve = 0x2000, - Decommit = 0x4000, - Release = 0x8000, - Reset = 0x80000, - Physical = 0x400000, - TopDown = 0x100000, - WriteWatch = 0x200000, - LargePages = 0x20000000 - } - - [Flags] - private enum MemoryProtection : uint - { - NoAccess = 0x01, - ReadOnly = 0x02, - ReadWrite = 0x04, - WriteCopy = 0x08, - Execute = 0x10, - ExecuteRead = 0x20, - ExecuteReadWrite = 0x40, - ExecuteWriteCopy = 0x80, - GuardModifierflag = 0x100, - NoCacheModifierflag = 0x200, - WriteCombineModifierflag = 0x400 - } - - private enum WriteWatchFlags : uint - { - None = 0, - Reset = 1 - } - - [DllImport("kernel32.dll")] - private static extern IntPtr VirtualAlloc( - IntPtr lpAddress, - IntPtr dwSize, - AllocationType flAllocationType, - MemoryProtection flProtect); - - [DllImport("kernel32.dll")] - private static extern bool VirtualProtect( - IntPtr lpAddress, - IntPtr dwSize, - MemoryProtection flNewProtect, - out MemoryProtection lpflOldProtect); - - [DllImport("kernel32.dll")] - private static extern bool VirtualFree( - IntPtr lpAddress, - IntPtr dwSize, - AllocationType dwFreeType); - - [DllImport("kernel32.dll")] - private static extern int GetWriteWatch( - WriteWatchFlags dwFlags, - IntPtr lpBaseAddress, - IntPtr dwRegionSize, - IntPtr[] lpAddresses, - ref ulong lpdwCount, - out uint lpdwGranularity); - - public static IntPtr Allocate(IntPtr size) - { - const AllocationType flags = - AllocationType.Reserve | - AllocationType.Commit; - - IntPtr ptr = VirtualAlloc(IntPtr.Zero, size, flags, MemoryProtection.ReadWrite); - - if (ptr == IntPtr.Zero) - { - throw new OutOfMemoryException(); - } - - return ptr; - } - - public static IntPtr AllocateWriteTracked(IntPtr size) - { - const AllocationType flags = - AllocationType.Reserve | - AllocationType.Commit | - AllocationType.WriteWatch; - - IntPtr ptr = VirtualAlloc(IntPtr.Zero, size, flags, MemoryProtection.ReadWrite); - - if (ptr == IntPtr.Zero) - { - throw new OutOfMemoryException(); - } - - return ptr; - } - - public static bool Reprotect(IntPtr address, IntPtr size, Memory.MemoryProtection protection) - { - MemoryProtection prot = GetProtection(protection); - - return VirtualProtect(address, size, prot, out _); - } - - private static MemoryProtection GetProtection(Memory.MemoryProtection protection) - { - switch (protection) - { - case Memory.MemoryProtection.None: return MemoryProtection.NoAccess; - case Memory.MemoryProtection.Read: return MemoryProtection.ReadOnly; - case Memory.MemoryProtection.ReadAndWrite: return MemoryProtection.ReadWrite; - case Memory.MemoryProtection.ReadAndExecute: return MemoryProtection.ExecuteRead; - case Memory.MemoryProtection.Execute: return MemoryProtection.Execute; - - default: throw new ArgumentException($"Invalid permission \"{protection}\"."); - } - } - - public static bool Free(IntPtr address) - { - return VirtualFree(address, IntPtr.Zero, AllocationType.Release); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool GetModifiedPages( - IntPtr address, - IntPtr size, - IntPtr[] addresses, - out ulong count) - { - ulong pagesCount = (ulong)addresses.Length; - - int result = GetWriteWatch( - WriteWatchFlags.Reset, - address, - size, - addresses, - ref pagesCount, - out uint granularity); - - count = pagesCount; - - return result == 0; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Memory/MemoryManager.cs b/ChocolArm64/Memory/MemoryManager.cs deleted file mode 100644 index 2347f1eb..00000000 --- a/ChocolArm64/Memory/MemoryManager.cs +++ /dev/null @@ -1,1017 +0,0 @@ -using ChocolArm64.Instructions; -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; -using System.Threading; - -using static ChocolArm64.Memory.CompareExchange128; -using static ChocolArm64.Memory.MemoryManagement; - -namespace ChocolArm64.Memory -{ - public unsafe class MemoryManager : ARMeilleure.Memory.IMemoryManager - { - public const int PageBits = 12; - public const int PageSize = 1 << PageBits; - public const int PageMask = PageSize - 1; - - private const long PteFlagNotModified = 1; - - internal const long PteFlagsMask = 7; - - public IntPtr Ram { get; private set; } - - private byte* _ramPtr; - - private IntPtr _pageTable; - - internal IntPtr PageTable => _pageTable; - - internal int PtLevelBits { get; } - internal int PtLevelSize { get; } - internal int PtLevelMask { get; } - - public bool HasWriteWatchSupport => MemoryManagement.HasWriteWatchSupport; - - public int AddressSpaceBits { get; } - public long AddressSpaceSize { get; } - - public MemoryManager( - IntPtr ram, - int addressSpaceBits = 48, - bool useFlatPageTable = false) - { - Ram = ram; - - _ramPtr = (byte*)ram; - - AddressSpaceBits = addressSpaceBits; - AddressSpaceSize = 1L << addressSpaceBits; - - // When flat page table is requested, we use a single - // array for the mappings of the entire address space. - // This has better performance, but also high memory usage. - // The multi level page table uses 9 bits per level, so - // the memory usage is lower, but the performance is also - // lower, since each address translation requires multiple reads. - if (useFlatPageTable) - { - PtLevelBits = addressSpaceBits - PageBits; - } - else - { - PtLevelBits = 9; - } - - PtLevelSize = 1 << PtLevelBits; - PtLevelMask = PtLevelSize - 1; - - _pageTable = Allocate((ulong)(PtLevelSize * IntPtr.Size)); - } - - public void Map(long va, long pa, long size) - { - SetPtEntries(va, _ramPtr + pa, size); - } - - public void Unmap(long position, long size) - { - SetPtEntries(position, null, size); - } - - public bool IsMapped(long position) - { - return Translate(position) != IntPtr.Zero; - } - - public long GetPhysicalAddress(long virtualAddress) - { - byte* ptr = (byte*)Translate(virtualAddress); - - return (long)(ptr - _ramPtr); - } - - private IntPtr Translate(long position) - { - if (!IsValidPosition(position)) - { - return IntPtr.Zero; - } - - byte* ptr = GetPtEntry(position); - - ulong ptrUlong = (ulong)ptr; - - if ((ptrUlong & PteFlagsMask) != 0) - { - ptrUlong &= ~(ulong)PteFlagsMask; - - ptr = (byte*)ptrUlong; - } - - return new IntPtr(ptr + (position & PageMask)); - } - - private IntPtr TranslateWrite(long position) - { - if (!IsValidPosition(position)) - { - return IntPtr.Zero; - } - - byte* ptr = GetPtEntry(position); - - ulong ptrUlong = (ulong)ptr; - - if ((ptrUlong & PteFlagsMask) != 0) - { - if ((ptrUlong & PteFlagNotModified) != 0) - { - ClearPtEntryFlag(position, PteFlagNotModified); - } - - ptrUlong &= ~(ulong)PteFlagsMask; - - ptr = (byte*)ptrUlong; - } - - return new IntPtr(ptr + (position & PageMask)); - } - - private byte* GetPtEntry(long position) - { - return *(byte**)GetPtPtr(position); - } - - private void SetPtEntries(long va, byte* ptr, long size) - { - long endPosition = (va + size + PageMask) & ~PageMask; - - while ((ulong)va < (ulong)endPosition) - { - SetPtEntry(va, ptr); - - va += PageSize; - - if (ptr != null) - { - ptr += PageSize; - } - } - } - - private void SetPtEntry(long position, byte* ptr) - { - *(byte**)GetPtPtr(position) = ptr; - } - - private void SetPtEntryFlag(long position, long flag) - { - ModifyPtEntryFlag(position, flag, setFlag: true); - } - - private void ClearPtEntryFlag(long position, long flag) - { - ModifyPtEntryFlag(position, flag, setFlag: false); - } - - private void ModifyPtEntryFlag(long position, long flag, bool setFlag) - { - IntPtr* pt = (IntPtr*)_pageTable; - - while (true) - { - IntPtr* ptPtr = GetPtPtr(position); - - IntPtr old = *ptPtr; - - long modified = old.ToInt64(); - - if (setFlag) - { - modified |= flag; - } - else - { - modified &= ~flag; - } - - IntPtr origValue = Interlocked.CompareExchange(ref *ptPtr, new IntPtr(modified), old); - - if (origValue == old) - { - break; - } - } - } - - private IntPtr* GetPtPtr(long position) - { - if (!IsValidPosition(position)) - { - throw new ArgumentOutOfRangeException(nameof(position)); - } - - IntPtr nextPtr = _pageTable; - - IntPtr* ptePtr = null; - - int bit = PageBits; - - while (true) - { - long index = (position >> bit) & PtLevelMask; - - ptePtr = &((IntPtr*)nextPtr)[index]; - - bit += PtLevelBits; - - if (bit >= AddressSpaceBits) - { - break; - } - - nextPtr = *ptePtr; - - if (nextPtr == IntPtr.Zero) - { - // Entry does not yet exist, allocate a new one. - IntPtr newPtr = Allocate((ulong)(PtLevelSize * IntPtr.Size)); - - // Try to swap the current pointer (should be zero), with the allocated one. - nextPtr = Interlocked.Exchange(ref *ptePtr, newPtr); - - // If the old pointer is not null, then another thread already has set it. - if (nextPtr != IntPtr.Zero) - { - Free(newPtr); - } - else - { - nextPtr = newPtr; - } - } - } - - return ptePtr; - } - - public bool IsRegionModified(long position, long size) - { - if (!HasWriteWatchSupport) - { - return IsRegionModifiedFallback(position, size); - } - - IntPtr address = Translate(position); - - IntPtr baseAddr = address; - IntPtr expectedAddr = address; - - long pendingPages = 0; - - long pages = size / PageSize; - - bool modified = false; - - bool IsAnyPageModified() - { - IntPtr pendingSize = new IntPtr(pendingPages * PageSize); - - IntPtr[] addresses = new IntPtr[pendingPages]; - - bool result = GetModifiedPages(baseAddr, pendingSize, addresses, out ulong count); - - if (result) - { - return count != 0; - } - else - { - return true; - } - } - - while (pages-- > 0) - { - if (address != expectedAddr) - { - modified |= IsAnyPageModified(); - - baseAddr = address; - - pendingPages = 0; - } - - expectedAddr = address + PageSize; - - pendingPages++; - - if (pages == 0) - { - break; - } - - position += PageSize; - - address = Translate(position); - } - - if (pendingPages != 0) - { - modified |= IsAnyPageModified(); - } - - return modified; - } - - private unsafe bool IsRegionModifiedFallback(long position, long size) - { - long endAddr = (position + size + PageMask) & ~PageMask; - - bool modified = false; - - while ((ulong)position < (ulong)endAddr) - { - if (IsValidPosition(position)) - { - byte* ptr = ((byte**)_pageTable)[position >> PageBits]; - - ulong ptrUlong = (ulong)ptr; - - if ((ptrUlong & PteFlagNotModified) == 0) - { - modified = true; - - SetPtEntryFlag(position, PteFlagNotModified); - } - } - else - { - modified = true; - } - - position += PageSize; - } - - return modified; - } - - public bool TryGetHostAddress(long position, long size, out IntPtr ptr) - { - if (IsContiguous(position, size)) - { - ptr = (IntPtr)Translate(position); - - return true; - } - - ptr = IntPtr.Zero; - - return false; - } - - private bool IsContiguous(long position, long size) - { - long endPos = position + size; - - position &= ~PageMask; - - long expectedPa = GetPhysicalAddress(position); - - while ((ulong)position < (ulong)endPos) - { - long pa = GetPhysicalAddress(position); - - if (pa != expectedPa) - { - return false; - } - - position += PageSize; - expectedPa += PageSize; - } - - return true; - } - - public bool IsValidPosition(long position) - { - return (ulong)position < (ulong)AddressSpaceSize; - } - - internal bool AtomicCompareExchange2xInt32( - long position, - int expectedLow, - int expectedHigh, - int desiredLow, - int desiredHigh) - { - long expected = (uint)expectedLow; - long desired = (uint)desiredLow; - - expected |= (long)expectedHigh << 32; - desired |= (long)desiredHigh << 32; - - return AtomicCompareExchangeInt64(position, expected, desired); - } - - internal bool AtomicCompareExchangeInt128( - long position, - ulong expectedLow, - ulong expectedHigh, - ulong desiredLow, - ulong desiredHigh) - { - if ((position & 0xf) != 0) - { - AbortWithAlignmentFault(position); - } - - IntPtr ptr = TranslateWrite(position); - - return InterlockedCompareExchange128(ptr, expectedLow, expectedHigh, desiredLow, desiredHigh); - } - - internal Vector128<float> AtomicReadInt128(long position) - { - if ((position & 0xf) != 0) - { - AbortWithAlignmentFault(position); - } - - IntPtr ptr = Translate(position); - - InterlockedRead128(ptr, out ulong low, out ulong high); - - Vector128<float> vector = default(Vector128<float>); - - vector = VectorHelper.VectorInsertInt(low, vector, 0, 3); - vector = VectorHelper.VectorInsertInt(high, vector, 1, 3); - - return vector; - } - - public bool AtomicCompareExchangeByte(long position, byte expected, byte desired) - { - int* ptr = (int*)Translate(position); - - int currentValue = *ptr; - - int expected32 = (currentValue & ~byte.MaxValue) | expected; - int desired32 = (currentValue & ~byte.MaxValue) | desired; - - return Interlocked.CompareExchange(ref *ptr, desired32, expected32) == expected32; - } - - public bool AtomicCompareExchangeInt16(long position, short expected, short desired) - { - if ((position & 1) != 0) - { - AbortWithAlignmentFault(position); - } - - int* ptr = (int*)Translate(position); - - int currentValue = *ptr; - - int expected32 = (currentValue & ~ushort.MaxValue) | (ushort)expected; - int desired32 = (currentValue & ~ushort.MaxValue) | (ushort)desired; - - return Interlocked.CompareExchange(ref *ptr, desired32, expected32) == expected32; - } - - public bool AtomicCompareExchangeInt32(long position, int expected, int desired) - { - if ((position & 3) != 0) - { - AbortWithAlignmentFault(position); - } - - int* ptr = (int*)TranslateWrite(position); - - return Interlocked.CompareExchange(ref *ptr, desired, expected) == expected; - } - - public bool AtomicCompareExchangeInt64(long position, long expected, long desired) - { - if ((position & 7) != 0) - { - AbortWithAlignmentFault(position); - } - - long* ptr = (long*)TranslateWrite(position); - - return Interlocked.CompareExchange(ref *ptr, desired, expected) == expected; - } - - public int AtomicIncrementInt32(long position) - { - if ((position & 3) != 0) - { - AbortWithAlignmentFault(position); - } - - int* ptr = (int*)TranslateWrite(position); - - return Interlocked.Increment(ref *ptr); - } - - public int AtomicDecrementInt32(long position) - { - if ((position & 3) != 0) - { - AbortWithAlignmentFault(position); - } - - int* ptr = (int*)TranslateWrite(position); - - return Interlocked.Decrement(ref *ptr); - } - - private void AbortWithAlignmentFault(long position) - { - // TODO: Abort mode and exception support on the CPU. - throw new InvalidOperationException($"Tried to compare exchange a misaligned address 0x{position:X16}."); - } - - public sbyte ReadSByte(long position) - { - return (sbyte)ReadByte(position); - } - - public short ReadInt16(long position) - { - return (short)ReadUInt16(position); - } - - public int ReadInt32(long position) - { - return (int)ReadUInt32(position); - } - - public long ReadInt64(long position) - { - return (long)ReadUInt64(position); - } - - public byte ReadByte(long position) - { - return *((byte*)Translate(position)); - } - - public ushort ReadUInt16(long position) - { - if ((position & 1) == 0) - { - return *((ushort*)Translate(position)); - } - else - { - return (ushort)(ReadByte(position + 0) << 0 | - ReadByte(position + 1) << 8); - } - } - - public uint ReadUInt32(long position) - { - if ((position & 3) == 0) - { - return *((uint*)Translate(position)); - } - else - { - return (uint)(ReadUInt16(position + 0) << 0 | - ReadUInt16(position + 2) << 16); - } - } - - public ulong ReadUInt64(long position) - { - if ((position & 7) == 0) - { - return *((ulong*)Translate(position)); - } - else - { - return (ulong)ReadUInt32(position + 0) << 0 | - (ulong)ReadUInt32(position + 4) << 32; - } - } - - public Vector128<float> ReadVector8(long position) - { - if (Sse2.IsSupported) - { - return Sse.StaticCast<byte, float>(Sse2.SetVector128(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ReadByte(position))); - } - else - { - Vector128<float> value = VectorHelper.VectorSingleZero(); - - value = VectorHelper.VectorInsertInt(ReadByte(position), value, 0, 0); - - return value; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector128<float> ReadVector16(long position) - { - if (Sse2.IsSupported && (position & 1) == 0) - { - return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse2.SetZeroVector128<ushort>(), ReadUInt16(position), 0)); - } - else - { - Vector128<float> value = VectorHelper.VectorSingleZero(); - - value = VectorHelper.VectorInsertInt(ReadUInt16(position), value, 0, 1); - - return value; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector128<float> ReadVector32(long position) - { - if (Sse.IsSupported && (position & 3) == 0) - { - return Sse.LoadScalarVector128((float*)Translate(position)); - } - else - { - Vector128<float> value = VectorHelper.VectorSingleZero(); - - value = VectorHelper.VectorInsertInt(ReadUInt32(position), value, 0, 2); - - return value; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector128<float> ReadVector64(long position) - { - if (Sse2.IsSupported && (position & 7) == 0) - { - return Sse.StaticCast<double, float>(Sse2.LoadScalarVector128((double*)Translate(position))); - } - else - { - Vector128<float> value = VectorHelper.VectorSingleZero(); - - value = VectorHelper.VectorInsertInt(ReadUInt64(position), value, 0, 3); - - return value; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector128<float> ReadVector128(long position) - { - if (Sse.IsSupported && (position & 15) == 0) - { - return Sse.LoadVector128((float*)Translate(position)); - } - else - { - Vector128<float> value = VectorHelper.VectorSingleZero(); - - value = VectorHelper.VectorInsertInt(ReadUInt64(position + 0), value, 0, 3); - value = VectorHelper.VectorInsertInt(ReadUInt64(position + 8), value, 1, 3); - - return value; - } - } - - public byte[] ReadBytes(long position, long size) - { - long endAddr = position + size; - - if ((ulong)size > int.MaxValue) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - if ((ulong)endAddr < (ulong)position) - { - throw new ArgumentOutOfRangeException(nameof(position)); - } - - byte[] data = new byte[size]; - - int offset = 0; - - while ((ulong)position < (ulong)endAddr) - { - long pageLimit = (position + PageSize) & ~(long)PageMask; - - if ((ulong)pageLimit > (ulong)endAddr) - { - pageLimit = endAddr; - } - - int copySize = (int)(pageLimit - position); - - Marshal.Copy(Translate(position), data, offset, copySize); - - position += copySize; - offset += copySize; - } - - return data; - } - - public void ReadBytes(long position, byte[] data, int startIndex, int size) - { - // Note: This will be moved later. - long endAddr = position + size; - - if ((ulong)size > int.MaxValue) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - if ((ulong)endAddr < (ulong)position) - { - throw new ArgumentOutOfRangeException(nameof(position)); - } - - int offset = startIndex; - - while ((ulong)position < (ulong)endAddr) - { - long pageLimit = (position + PageSize) & ~(long)PageMask; - - if ((ulong)pageLimit > (ulong)endAddr) - { - pageLimit = endAddr; - } - - int copySize = (int)(pageLimit - position); - - Marshal.Copy(Translate(position), data, offset, copySize); - - position += copySize; - offset += copySize; - } - } - - public void WriteSByte(long position, sbyte value) - { - WriteByte(position, (byte)value); - } - - public void WriteInt16(long position, short value) - { - WriteUInt16(position, (ushort)value); - } - - public void WriteInt32(long position, int value) - { - WriteUInt32(position, (uint)value); - } - - public void WriteInt64(long position, long value) - { - WriteUInt64(position, (ulong)value); - } - - public void WriteByte(long position, byte value) - { - *((byte*)TranslateWrite(position)) = value; - } - - public void WriteUInt16(long position, ushort value) - { - if ((position & 1) == 0) - { - *((ushort*)TranslateWrite(position)) = value; - } - else - { - WriteByte(position + 0, (byte)(value >> 0)); - WriteByte(position + 1, (byte)(value >> 8)); - } - } - - public void WriteUInt32(long position, uint value) - { - if ((position & 3) == 0) - { - *((uint*)TranslateWrite(position)) = value; - } - else - { - WriteUInt16(position + 0, (ushort)(value >> 0)); - WriteUInt16(position + 2, (ushort)(value >> 16)); - } - } - - public void WriteUInt64(long position, ulong value) - { - if ((position & 7) == 0) - { - *((ulong*)TranslateWrite(position)) = value; - } - else - { - WriteUInt32(position + 0, (uint)(value >> 0)); - WriteUInt32(position + 4, (uint)(value >> 32)); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector8(long position, Vector128<float> value) - { - if (Sse41.IsSupported) - { - WriteByte(position, Sse41.Extract(Sse.StaticCast<float, byte>(value), 0)); - } - else if (Sse2.IsSupported) - { - WriteByte(position, (byte)Sse2.Extract(Sse.StaticCast<float, ushort>(value), 0)); - } - else - { - WriteByte(position, (byte)VectorHelper.VectorExtractIntZx(value, 0, 0)); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector16(long position, Vector128<float> value) - { - if (Sse2.IsSupported) - { - WriteUInt16(position, Sse2.Extract(Sse.StaticCast<float, ushort>(value), 0)); - } - else - { - WriteUInt16(position, (ushort)VectorHelper.VectorExtractIntZx(value, 0, 1)); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector32(long position, Vector128<float> value) - { - if (Sse.IsSupported && (position & 3) == 0) - { - Sse.StoreScalar((float*)TranslateWrite(position), value); - } - else - { - WriteUInt32(position, (uint)VectorHelper.VectorExtractIntZx(value, 0, 2)); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector64(long position, Vector128<float> value) - { - if (Sse2.IsSupported && (position & 7) == 0) - { - Sse2.StoreScalar((double*)TranslateWrite(position), Sse.StaticCast<float, double>(value)); - } - else - { - WriteUInt64(position, VectorHelper.VectorExtractIntZx(value, 0, 3)); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector128Internal(long position, Vector128<float> value) - { - if (Sse.IsSupported && (position & 15) == 0) - { - Sse.Store((float*)TranslateWrite(position), value); - } - else - { - WriteUInt64(position + 0, VectorHelper.VectorExtractIntZx(value, 0, 3)); - WriteUInt64(position + 8, VectorHelper.VectorExtractIntZx(value, 1, 3)); - } - } - - public void WriteVector128(long position, ARMeilleure.State.V128 value) - { - WriteUInt64(position + 0, value.GetUInt64(0)); - WriteUInt64(position + 8, value.GetUInt64(1)); - } - - public void WriteBytes(long position, byte[] data) - { - long endAddr = position + data.Length; - - if ((ulong)endAddr < (ulong)position) - { - throw new ArgumentOutOfRangeException(nameof(position)); - } - - int offset = 0; - - while ((ulong)position < (ulong)endAddr) - { - long pageLimit = (position + PageSize) & ~(long)PageMask; - - if ((ulong)pageLimit > (ulong)endAddr) - { - pageLimit = endAddr; - } - - int copySize = (int)(pageLimit - position); - - Marshal.Copy(data, offset, TranslateWrite(position), copySize); - - position += copySize; - offset += copySize; - } - } - - public void WriteBytes(long position, byte[] data, int startIndex, int size) - { - // Note: This will be moved later. - long endAddr = position + size; - - if ((ulong)endAddr < (ulong)position) - { - throw new ArgumentOutOfRangeException(nameof(position)); - } - - int offset = startIndex; - - while ((ulong)position < (ulong)endAddr) - { - long pageLimit = (position + PageSize) & ~(long)PageMask; - - if ((ulong)pageLimit > (ulong)endAddr) - { - pageLimit = endAddr; - } - - int copySize = (int)(pageLimit - position); - - Marshal.Copy(data, offset, Translate(position), copySize); - - position += copySize; - offset += copySize; - } - } - - public void CopyBytes(long src, long dst, long size) - { - // Note: This will be moved later. - if (IsContiguous(src, size) && - IsContiguous(dst, size)) - { - byte* srcPtr = (byte*)Translate(src); - byte* dstPtr = (byte*)Translate(dst); - - Buffer.MemoryCopy(srcPtr, dstPtr, size, size); - } - else - { - WriteBytes(dst, ReadBytes(src, size)); - } - } - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { - IntPtr ptr = Interlocked.Exchange(ref _pageTable, IntPtr.Zero); - - if (ptr != IntPtr.Zero) - { - FreePageTableEntry(ptr, PageBits); - } - } - - private void FreePageTableEntry(IntPtr ptr, int levelBitEnd) - { - levelBitEnd += PtLevelBits; - - if (levelBitEnd >= AddressSpaceBits) - { - Free(ptr); - - return; - } - - for (int index = 0; index < PtLevelSize; index++) - { - IntPtr ptePtr = ((IntPtr*)ptr)[index]; - - if (ptePtr != IntPtr.Zero) - { - FreePageTableEntry(ptePtr, levelBitEnd); - } - } - - Free(ptr); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Memory/MemoryProtection.cs b/ChocolArm64/Memory/MemoryProtection.cs deleted file mode 100644 index d0874bfc..00000000 --- a/ChocolArm64/Memory/MemoryProtection.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace ChocolArm64.Memory -{ - [Flags] - public enum MemoryProtection - { - None = 0, - Read = 1 << 0, - Write = 1 << 1, - Execute = 1 << 2, - - ReadAndWrite = Read | Write, - ReadAndExecute = Read | Execute - } -}
\ No newline at end of file diff --git a/ChocolArm64/Memory/MemoryProtectionException.cs b/ChocolArm64/Memory/MemoryProtectionException.cs deleted file mode 100644 index 3d2cebad..00000000 --- a/ChocolArm64/Memory/MemoryProtectionException.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace ChocolArm64.Memory -{ - class MemoryProtectionException : Exception - { - public MemoryProtectionException(MemoryProtection protection) : - base($"Failed to set memory protection to \"{protection}\".") { } - } -}
\ No newline at end of file diff --git a/ChocolArm64/OpCodeTable.cs b/ChocolArm64/OpCodeTable.cs deleted file mode 100644 index 94272d51..00000000 --- a/ChocolArm64/OpCodeTable.cs +++ /dev/null @@ -1,792 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.Instructions; -using ChocolArm64.State; -using System; -using System.Collections.Generic; - -namespace ChocolArm64 -{ - static class OpCodeTable - { - private const int FastLookupSize = 0x1000; - - private class InstInfo - { - public int Mask; - public int Value; - - public Inst Inst; - - public InstInfo(int mask, int value, Inst inst) - { - Mask = mask; - Value = value; - Inst = inst; - } - } - - private static List<InstInfo> _allInstA32 = new List<InstInfo>(); - private static List<InstInfo> _allInstT32 = new List<InstInfo>(); - private static List<InstInfo> _allInstA64 = new List<InstInfo>(); - - private static InstInfo[][] _instA32FastLookup = new InstInfo[FastLookupSize][]; - private static InstInfo[][] _instT32FastLookup = new InstInfo[FastLookupSize][]; - private static InstInfo[][] _instA64FastLookup = new InstInfo[FastLookupSize][]; - - static OpCodeTable() - { -#region "OpCode Table (AArch32)" - // Integer - SetA32("<<<<0010100xxxxxxxxxxxxxxxxxxxxx", InstEmit32.Add, typeof(OpCode32AluImm)); - SetA32("<<<<0000100xxxxxxxxxxxxxxxx0xxxx", InstEmit32.Add, typeof(OpCode32AluRsImm)); - SetA32("<<<<1010xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit32.B, typeof(OpCode32BImm)); - SetA32("<<<<1011xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit32.Bl, typeof(OpCode32BImm)); - SetA32("1111101xxxxxxxxxxxxxxxxxxxxxxxxx", InstEmit32.Blx, typeof(OpCode32BImm)); - SetA32("<<<<000100101111111111110001xxxx", InstEmit32.Bx, typeof(OpCode32BReg)); - SetT32("010001110xxxx000", InstEmit32.Bx, typeof(OpCodeT16BReg)); - SetA32("<<<<00110101xxxx0000xxxxxxxxxxxx", InstEmit32.Cmp, typeof(OpCode32AluImm)); - SetA32("<<<<00010101xxxx0000xxxxxxx0xxxx", InstEmit32.Cmp, typeof(OpCode32AluRsImm)); - SetA32("<<<<100xx0x1xxxxxxxxxxxxxxxxxxxx", InstEmit32.Ldm, typeof(OpCode32MemMult)); - SetA32("<<<<010xx0x1xxxxxxxxxxxxxxxxxxxx", InstEmit32.Ldr, typeof(OpCode32MemImm)); - SetA32("<<<<010xx1x1xxxxxxxxxxxxxxxxxxxx", InstEmit32.Ldrb, typeof(OpCode32MemImm)); - SetA32("<<<<000xx1x0xxxxxxxxxxxx1101xxxx", InstEmit32.Ldrd, typeof(OpCode32MemImm8)); - SetA32("<<<<000xx1x1xxxxxxxxxxxx1011xxxx", InstEmit32.Ldrh, typeof(OpCode32MemImm8)); - SetA32("<<<<000xx1x1xxxxxxxxxxxx1101xxxx", InstEmit32.Ldrsb, typeof(OpCode32MemImm8)); - SetA32("<<<<000xx1x1xxxxxxxxxxxx1111xxxx", InstEmit32.Ldrsh, typeof(OpCode32MemImm8)); - SetA32("<<<<0011101x0000xxxxxxxxxxxxxxxx", InstEmit32.Mov, typeof(OpCode32AluImm)); - SetA32("<<<<0001101x0000xxxxxxxxxxx0xxxx", InstEmit32.Mov, typeof(OpCode32AluRsImm)); - SetT32("00100xxxxxxxxxxx", InstEmit32.Mov, typeof(OpCodeT16AluImm8)); - SetA32("<<<<100xx0x0xxxxxxxxxxxxxxxxxxxx", InstEmit32.Stm, typeof(OpCode32MemMult)); - SetA32("<<<<010xx0x0xxxxxxxxxxxxxxxxxxxx", InstEmit32.Str, typeof(OpCode32MemImm)); - SetA32("<<<<010xx1x0xxxxxxxxxxxxxxxxxxxx", InstEmit32.Strb, typeof(OpCode32MemImm)); - SetA32("<<<<000xx1x0xxxxxxxxxxxx1111xxxx", InstEmit32.Strd, typeof(OpCode32MemImm8)); - SetA32("<<<<000xx1x0xxxxxxxxxxxx1011xxxx", InstEmit32.Strh, typeof(OpCode32MemImm8)); - SetA32("<<<<0010010xxxxxxxxxxxxxxxxxxxxx", InstEmit32.Sub, typeof(OpCode32AluImm)); - SetA32("<<<<0000010xxxxxxxxxxxxxxxx0xxxx", InstEmit32.Sub, typeof(OpCode32AluRsImm)); -#endregion - -#region "OpCode Table (AArch64)" - // Integer - SetA64("x0011010000xxxxx000000xxxxxxxxxx", InstEmit.Adc, typeof(OpCodeAluRs64)); - SetA64("x0111010000xxxxx000000xxxxxxxxxx", InstEmit.Adcs, typeof(OpCodeAluRs64)); - SetA64("x00100010xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Add, typeof(OpCodeAluImm64)); - SetA64("00001011<<0xxxxx0xxxxxxxxxxxxxxx", InstEmit.Add, typeof(OpCodeAluRs64)); - SetA64("10001011<<0xxxxxxxxxxxxxxxxxxxxx", InstEmit.Add, typeof(OpCodeAluRs64)); - SetA64("x0001011001xxxxxxxx0xxxxxxxxxxxx", InstEmit.Add, typeof(OpCodeAluRx64)); - SetA64("x0001011001xxxxxxxx100xxxxxxxxxx", InstEmit.Add, typeof(OpCodeAluRx64)); - SetA64("x01100010xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Adds, typeof(OpCodeAluImm64)); - SetA64("00101011<<0xxxxx0xxxxxxxxxxxxxxx", InstEmit.Adds, typeof(OpCodeAluRs64)); - SetA64("10101011<<0xxxxxxxxxxxxxxxxxxxxx", InstEmit.Adds, typeof(OpCodeAluRs64)); - SetA64("x0101011001xxxxxxxx0xxxxxxxxxxxx", InstEmit.Adds, typeof(OpCodeAluRx64)); - SetA64("x0101011001xxxxxxxx100xxxxxxxxxx", InstEmit.Adds, typeof(OpCodeAluRx64)); - SetA64("0xx10000xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Adr, typeof(OpCodeAdr64)); - SetA64("1xx10000xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Adrp, typeof(OpCodeAdr64)); - SetA64("0001001000xxxxxxxxxxxxxxxxxxxxxx", InstEmit.And, typeof(OpCodeAluImm64)); - SetA64("100100100xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.And, typeof(OpCodeAluImm64)); - SetA64("00001010xx0xxxxx0xxxxxxxxxxxxxxx", InstEmit.And, typeof(OpCodeAluRs64)); - SetA64("10001010xx0xxxxxxxxxxxxxxxxxxxxx", InstEmit.And, typeof(OpCodeAluRs64)); - SetA64("0111001000xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Ands, typeof(OpCodeAluImm64)); - SetA64("111100100xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Ands, typeof(OpCodeAluImm64)); - SetA64("01101010xx0xxxxx0xxxxxxxxxxxxxxx", InstEmit.Ands, typeof(OpCodeAluRs64)); - SetA64("11101010xx0xxxxxxxxxxxxxxxxxxxxx", InstEmit.Ands, typeof(OpCodeAluRs64)); - SetA64("x0011010110xxxxx001010xxxxxxxxxx", InstEmit.Asrv, typeof(OpCodeAluRs64)); - SetA64("000101xxxxxxxxxxxxxxxxxxxxxxxxxx", InstEmit.B, typeof(OpCodeBImmAl64)); - SetA64("01010100xxxxxxxxxxxxxxxxxxx0xxxx", InstEmit.B_Cond, typeof(OpCodeBImmCond64)); - SetA64("00110011000xxxxx0xxxxxxxxxxxxxxx", InstEmit.Bfm, typeof(OpCodeBfm64)); - SetA64("1011001101xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Bfm, typeof(OpCodeBfm64)); - SetA64("00001010xx1xxxxx0xxxxxxxxxxxxxxx", InstEmit.Bic, typeof(OpCodeAluRs64)); - SetA64("10001010xx1xxxxxxxxxxxxxxxxxxxxx", InstEmit.Bic, typeof(OpCodeAluRs64)); - SetA64("01101010xx1xxxxx0xxxxxxxxxxxxxxx", InstEmit.Bics, typeof(OpCodeAluRs64)); - SetA64("11101010xx1xxxxxxxxxxxxxxxxxxxxx", InstEmit.Bics, typeof(OpCodeAluRs64)); - SetA64("100101xxxxxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Bl, typeof(OpCodeBImmAl64)); - SetA64("1101011000111111000000xxxxx00000", InstEmit.Blr, typeof(OpCodeBReg64)); - SetA64("1101011000011111000000xxxxx00000", InstEmit.Br, typeof(OpCodeBReg64)); - SetA64("11010100001xxxxxxxxxxxxxxxx00000", InstEmit.Brk, typeof(OpCodeException64)); - SetA64("x0110101xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Cbnz, typeof(OpCodeBImmCmp64)); - SetA64("x0110100xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Cbz, typeof(OpCodeBImmCmp64)); - SetA64("x0111010010xxxxxxxxx10xxxxx0xxxx", InstEmit.Ccmn, typeof(OpCodeCcmpImm64)); - SetA64("x0111010010xxxxxxxxx00xxxxx0xxxx", InstEmit.Ccmn, typeof(OpCodeCcmpReg64)); - SetA64("x1111010010xxxxxxxxx10xxxxx0xxxx", InstEmit.Ccmp, typeof(OpCodeCcmpImm64)); - SetA64("x1111010010xxxxxxxxx00xxxxx0xxxx", InstEmit.Ccmp, typeof(OpCodeCcmpReg64)); - SetA64("11010101000000110011xxxx01011111", InstEmit.Clrex, typeof(OpCodeSystem64)); - SetA64("x101101011000000000101xxxxxxxxxx", InstEmit.Cls, typeof(OpCodeAlu64)); - SetA64("x101101011000000000100xxxxxxxxxx", InstEmit.Clz, typeof(OpCodeAlu64)); - SetA64("00011010110xxxxx010000xxxxxxxxxx", InstEmit.Crc32b, typeof(OpCodeAluRs64)); - SetA64("00011010110xxxxx010001xxxxxxxxxx", InstEmit.Crc32h, typeof(OpCodeAluRs64)); - SetA64("00011010110xxxxx010010xxxxxxxxxx", InstEmit.Crc32w, typeof(OpCodeAluRs64)); - SetA64("10011010110xxxxx010011xxxxxxxxxx", InstEmit.Crc32x, typeof(OpCodeAluRs64)); - SetA64("00011010110xxxxx010100xxxxxxxxxx", InstEmit.Crc32cb, typeof(OpCodeAluRs64)); - SetA64("00011010110xxxxx010101xxxxxxxxxx", InstEmit.Crc32ch, typeof(OpCodeAluRs64)); - SetA64("00011010110xxxxx010110xxxxxxxxxx", InstEmit.Crc32cw, typeof(OpCodeAluRs64)); - SetA64("10011010110xxxxx010111xxxxxxxxxx", InstEmit.Crc32cx, typeof(OpCodeAluRs64)); - SetA64("x0011010100xxxxxxxxx00xxxxxxxxxx", InstEmit.Csel, typeof(OpCodeCsel64)); - SetA64("x0011010100xxxxxxxxx01xxxxxxxxxx", InstEmit.Csinc, typeof(OpCodeCsel64)); - SetA64("x1011010100xxxxxxxxx00xxxxxxxxxx", InstEmit.Csinv, typeof(OpCodeCsel64)); - SetA64("x1011010100xxxxxxxxx01xxxxxxxxxx", InstEmit.Csneg, typeof(OpCodeCsel64)); - SetA64("11010101000000110011xxxx10111111", InstEmit.Dmb, typeof(OpCodeSystem64)); - SetA64("11010101000000110011xxxx10011111", InstEmit.Dsb, typeof(OpCodeSystem64)); - SetA64("01001010xx1xxxxx0xxxxxxxxxxxxxxx", InstEmit.Eon, typeof(OpCodeAluRs64)); - SetA64("11001010xx1xxxxxxxxxxxxxxxxxxxxx", InstEmit.Eon, typeof(OpCodeAluRs64)); - SetA64("0101001000xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Eor, typeof(OpCodeAluImm64)); - SetA64("110100100xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Eor, typeof(OpCodeAluImm64)); - SetA64("01001010xx0xxxxx0xxxxxxxxxxxxxxx", InstEmit.Eor, typeof(OpCodeAluRs64)); - SetA64("11001010xx0xxxxxxxxxxxxxxxxxxxxx", InstEmit.Eor, typeof(OpCodeAluRs64)); - SetA64("00010011100xxxxx0xxxxxxxxxxxxxxx", InstEmit.Extr, typeof(OpCodeAluRs64)); - SetA64("10010011110xxxxxxxxxxxxxxxxxxxxx", InstEmit.Extr, typeof(OpCodeAluRs64)); - SetA64("11010101000000110010xxxxxxx11111", InstEmit.Hint, typeof(OpCodeSystem64)); - SetA64("11010101000000110011xxxx11011111", InstEmit.Isb, typeof(OpCodeSystem64)); - SetA64("xx001000110xxxxx1xxxxxxxxxxxxxxx", InstEmit.Ldar, typeof(OpCodeMemEx64)); - SetA64("1x001000011xxxxx1xxxxxxxxxxxxxxx", InstEmit.Ldaxp, typeof(OpCodeMemEx64)); - SetA64("xx001000010xxxxx1xxxxxxxxxxxxxxx", InstEmit.Ldaxr, typeof(OpCodeMemEx64)); - SetA64("<<10100xx1xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Ldp, typeof(OpCodeMemPair64)); - SetA64("xx111000010xxxxxxxxxxxxxxxxxxxxx", InstEmit.Ldr, typeof(OpCodeMemImm64)); - SetA64("xx11100101xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Ldr, typeof(OpCodeMemImm64)); - SetA64("xx111000011xxxxxxxxx10xxxxxxxxxx", InstEmit.Ldr, typeof(OpCodeMemReg64)); - SetA64("xx011000xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Ldr_Literal, typeof(OpCodeMemLit64)); - SetA64("0x1110001x0xxxxxxxxxxxxxxxxxxxxx", InstEmit.Ldrs, typeof(OpCodeMemImm64)); - SetA64("0x1110011xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Ldrs, typeof(OpCodeMemImm64)); - SetA64("10111000100xxxxxxxxxxxxxxxxxxxxx", InstEmit.Ldrs, typeof(OpCodeMemImm64)); - SetA64("1011100110xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Ldrs, typeof(OpCodeMemImm64)); - SetA64("0x1110001x1xxxxxxxxx10xxxxxxxxxx", InstEmit.Ldrs, typeof(OpCodeMemReg64)); - SetA64("10111000101xxxxxxxxx10xxxxxxxxxx", InstEmit.Ldrs, typeof(OpCodeMemReg64)); - SetA64("xx001000010xxxxx0xxxxxxxxxxxxxxx", InstEmit.Ldxr, typeof(OpCodeMemEx64)); - SetA64("1x001000011xxxxx0xxxxxxxxxxxxxxx", InstEmit.Ldxp, typeof(OpCodeMemEx64)); - SetA64("x0011010110xxxxx001000xxxxxxxxxx", InstEmit.Lslv, typeof(OpCodeAluRs64)); - SetA64("x0011010110xxxxx001001xxxxxxxxxx", InstEmit.Lsrv, typeof(OpCodeAluRs64)); - SetA64("x0011011000xxxxx0xxxxxxxxxxxxxxx", InstEmit.Madd, typeof(OpCodeMul64)); - SetA64("0111001010xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Movk, typeof(OpCodeMov64)); - SetA64("111100101xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Movk, typeof(OpCodeMov64)); - SetA64("0001001010xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Movn, typeof(OpCodeMov64)); - SetA64("100100101xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Movn, typeof(OpCodeMov64)); - SetA64("0101001010xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Movz, typeof(OpCodeMov64)); - SetA64("110100101xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Movz, typeof(OpCodeMov64)); - SetA64("110101010011xxxxxxxxxxxxxxxxxxxx", InstEmit.Mrs, typeof(OpCodeSystem64)); - SetA64("110101010001xxxxxxxxxxxxxxxxxxxx", InstEmit.Msr, typeof(OpCodeSystem64)); - SetA64("x0011011000xxxxx1xxxxxxxxxxxxxxx", InstEmit.Msub, typeof(OpCodeMul64)); - SetA64("11010101000000110010000000011111", InstEmit.Nop, typeof(OpCodeSystem64)); - SetA64("00101010xx1xxxxx0xxxxxxxxxxxxxxx", InstEmit.Orn, typeof(OpCodeAluRs64)); - SetA64("10101010xx1xxxxxxxxxxxxxxxxxxxxx", InstEmit.Orn, typeof(OpCodeAluRs64)); - SetA64("0011001000xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Orr, typeof(OpCodeAluImm64)); - SetA64("101100100xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Orr, typeof(OpCodeAluImm64)); - SetA64("00101010xx0xxxxx0xxxxxxxxxxxxxxx", InstEmit.Orr, typeof(OpCodeAluRs64)); - SetA64("10101010xx0xxxxxxxxxxxxxxxxxxxxx", InstEmit.Orr, typeof(OpCodeAluRs64)); - SetA64("1111100110xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Pfrm, typeof(OpCodeMemImm64)); - SetA64("11111000100xxxxxxxxx00xxxxxxxxxx", InstEmit.Pfrm, typeof(OpCodeMemImm64)); - SetA64("11011000xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Pfrm, typeof(OpCodeMemLit64)); - SetA64("x101101011000000000000xxxxxxxxxx", InstEmit.Rbit, typeof(OpCodeAlu64)); - SetA64("1101011001011111000000xxxxx00000", InstEmit.Ret, typeof(OpCodeBReg64)); - SetA64("x101101011000000000001xxxxxxxxxx", InstEmit.Rev16, typeof(OpCodeAlu64)); - SetA64("x101101011000000000010xxxxxxxxxx", InstEmit.Rev32, typeof(OpCodeAlu64)); - SetA64("1101101011000000000011xxxxxxxxxx", InstEmit.Rev64, typeof(OpCodeAlu64)); - SetA64("x0011010110xxxxx001011xxxxxxxxxx", InstEmit.Rorv, typeof(OpCodeAluRs64)); - SetA64("x1011010000xxxxx000000xxxxxxxxxx", InstEmit.Sbc, typeof(OpCodeAluRs64)); - SetA64("x1111010000xxxxx000000xxxxxxxxxx", InstEmit.Sbcs, typeof(OpCodeAluRs64)); - SetA64("00010011000xxxxx0xxxxxxxxxxxxxxx", InstEmit.Sbfm, typeof(OpCodeBfm64)); - SetA64("1001001101xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Sbfm, typeof(OpCodeBfm64)); - SetA64("x0011010110xxxxx000011xxxxxxxxxx", InstEmit.Sdiv, typeof(OpCodeAluRs64)); - SetA64("10011011001xxxxx0xxxxxxxxxxxxxxx", InstEmit.Smaddl, typeof(OpCodeMul64)); - SetA64("10011011001xxxxx1xxxxxxxxxxxxxxx", InstEmit.Smsubl, typeof(OpCodeMul64)); - SetA64("10011011010xxxxx0xxxxxxxxxxxxxxx", InstEmit.Smulh, typeof(OpCodeMul64)); - SetA64("xx001000100xxxxx1xxxxxxxxxxxxxxx", InstEmit.Stlr, typeof(OpCodeMemEx64)); - SetA64("1x001000001xxxxx1xxxxxxxxxxxxxxx", InstEmit.Stlxp, typeof(OpCodeMemEx64)); - SetA64("xx001000000xxxxx1xxxxxxxxxxxxxxx", InstEmit.Stlxr, typeof(OpCodeMemEx64)); - SetA64("x010100xx0xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Stp, typeof(OpCodeMemPair64)); - SetA64("xx111000000xxxxxxxxxxxxxxxxxxxxx", InstEmit.Str, typeof(OpCodeMemImm64)); - SetA64("xx11100100xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Str, typeof(OpCodeMemImm64)); - SetA64("xx111000001xxxxxxxxx10xxxxxxxxxx", InstEmit.Str, typeof(OpCodeMemReg64)); - SetA64("1x001000001xxxxx0xxxxxxxxxxxxxxx", InstEmit.Stxp, typeof(OpCodeMemEx64)); - SetA64("xx001000000xxxxx0xxxxxxxxxxxxxxx", InstEmit.Stxr, typeof(OpCodeMemEx64)); - SetA64("x10100010xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Sub, typeof(OpCodeAluImm64)); - SetA64("01001011<<0xxxxx0xxxxxxxxxxxxxxx", InstEmit.Sub, typeof(OpCodeAluRs64)); - SetA64("11001011<<0xxxxxxxxxxxxxxxxxxxxx", InstEmit.Sub, typeof(OpCodeAluRs64)); - SetA64("x1001011001xxxxxxxx0xxxxxxxxxxxx", InstEmit.Sub, typeof(OpCodeAluRx64)); - SetA64("x1001011001xxxxxxxx100xxxxxxxxxx", InstEmit.Sub, typeof(OpCodeAluRx64)); - SetA64("x11100010xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Subs, typeof(OpCodeAluImm64)); - SetA64("01101011<<0xxxxx0xxxxxxxxxxxxxxx", InstEmit.Subs, typeof(OpCodeAluRs64)); - SetA64("11101011<<0xxxxxxxxxxxxxxxxxxxxx", InstEmit.Subs, typeof(OpCodeAluRs64)); - SetA64("x1101011001xxxxxxxx0xxxxxxxxxxxx", InstEmit.Subs, typeof(OpCodeAluRx64)); - SetA64("x1101011001xxxxxxxx100xxxxxxxxxx", InstEmit.Subs, typeof(OpCodeAluRx64)); - SetA64("11010100000xxxxxxxxxxxxxxxx00001", InstEmit.Svc, typeof(OpCodeException64)); - SetA64("1101010100001xxxxxxxxxxxxxxxxxxx", InstEmit.Sys, typeof(OpCodeSystem64)); - SetA64("x0110111xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Tbnz, typeof(OpCodeBImmTest64)); - SetA64("x0110110xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Tbz, typeof(OpCodeBImmTest64)); - SetA64("01010011000xxxxx0xxxxxxxxxxxxxxx", InstEmit.Ubfm, typeof(OpCodeBfm64)); - SetA64("1101001101xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Ubfm, typeof(OpCodeBfm64)); - SetA64("x0011010110xxxxx000010xxxxxxxxxx", InstEmit.Udiv, typeof(OpCodeAluRs64)); - SetA64("10011011101xxxxx0xxxxxxxxxxxxxxx", InstEmit.Umaddl, typeof(OpCodeMul64)); - SetA64("10011011101xxxxx1xxxxxxxxxxxxxxx", InstEmit.Umsubl, typeof(OpCodeMul64)); - SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", InstEmit.Umulh, typeof(OpCodeMul64)); - - // Vector - SetA64("0101111011100000101110xxxxxxxxxx", InstEmit.Abs_S, typeof(OpCodeSimd64)); - SetA64("0>001110<<100000101110xxxxxxxxxx", InstEmit.Abs_V, typeof(OpCodeSimd64)); - SetA64("01011110111xxxxx100001xxxxxxxxxx", InstEmit.Add_S, typeof(OpCodeSimdReg64)); - SetA64("0>001110<<1xxxxx100001xxxxxxxxxx", InstEmit.Add_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<1xxxxx010000xxxxxxxxxx", InstEmit.Addhn_V, typeof(OpCodeSimdReg64)); - SetA64("0101111011110001101110xxxxxxxxxx", InstEmit.Addp_S, typeof(OpCodeSimd64)); - SetA64("0>001110<<1xxxxx101111xxxxxxxxxx", InstEmit.Addp_V, typeof(OpCodeSimdReg64)); - SetA64("000011100x110001101110xxxxxxxxxx", InstEmit.Addv_V, typeof(OpCodeSimd64)); - SetA64("01001110<<110001101110xxxxxxxxxx", InstEmit.Addv_V, typeof(OpCodeSimd64)); - SetA64("0100111000101000010110xxxxxxxxxx", InstEmit.Aesd_V, typeof(OpCodeSimd64)); - SetA64("0100111000101000010010xxxxxxxxxx", InstEmit.Aese_V, typeof(OpCodeSimd64)); - SetA64("0100111000101000011110xxxxxxxxxx", InstEmit.Aesimc_V, typeof(OpCodeSimd64)); - SetA64("0100111000101000011010xxxxxxxxxx", InstEmit.Aesmc_V, typeof(OpCodeSimd64)); - SetA64("0x001110001xxxxx000111xxxxxxxxxx", InstEmit.And_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110011xxxxx000111xxxxxxxxxx", InstEmit.Bic_V, typeof(OpCodeSimdReg64)); - SetA64("0x10111100000xxx0xx101xxxxxxxxxx", InstEmit.Bic_Vi, typeof(OpCodeSimdImm64)); - SetA64("0x10111100000xxx10x101xxxxxxxxxx", InstEmit.Bic_Vi, typeof(OpCodeSimdImm64)); - SetA64("0x101110111xxxxx000111xxxxxxxxxx", InstEmit.Bif_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110101xxxxx000111xxxxxxxxxx", InstEmit.Bit_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110011xxxxx000111xxxxxxxxxx", InstEmit.Bsl_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<100000010010xxxxxxxxxx", InstEmit.Cls_V, typeof(OpCodeSimd64)); - SetA64("0x101110<<100000010010xxxxxxxxxx", InstEmit.Clz_V, typeof(OpCodeSimd64)); - SetA64("01111110111xxxxx100011xxxxxxxxxx", InstEmit.Cmeq_S, typeof(OpCodeSimdReg64)); - SetA64("0101111011100000100110xxxxxxxxxx", InstEmit.Cmeq_S, typeof(OpCodeSimd64)); - SetA64("0>101110<<1xxxxx100011xxxxxxxxxx", InstEmit.Cmeq_V, typeof(OpCodeSimdReg64)); - SetA64("0>001110<<100000100110xxxxxxxxxx", InstEmit.Cmeq_V, typeof(OpCodeSimd64)); - SetA64("01011110111xxxxx001111xxxxxxxxxx", InstEmit.Cmge_S, typeof(OpCodeSimdReg64)); - SetA64("0111111011100000100010xxxxxxxxxx", InstEmit.Cmge_S, typeof(OpCodeSimd64)); - SetA64("0>001110<<1xxxxx001111xxxxxxxxxx", InstEmit.Cmge_V, typeof(OpCodeSimdReg64)); - SetA64("0>101110<<100000100010xxxxxxxxxx", InstEmit.Cmge_V, typeof(OpCodeSimd64)); - SetA64("01011110111xxxxx001101xxxxxxxxxx", InstEmit.Cmgt_S, typeof(OpCodeSimdReg64)); - SetA64("0101111011100000100010xxxxxxxxxx", InstEmit.Cmgt_S, typeof(OpCodeSimd64)); - SetA64("0>001110<<1xxxxx001101xxxxxxxxxx", InstEmit.Cmgt_V, typeof(OpCodeSimdReg64)); - SetA64("0>001110<<100000100010xxxxxxxxxx", InstEmit.Cmgt_V, typeof(OpCodeSimd64)); - SetA64("01111110111xxxxx001101xxxxxxxxxx", InstEmit.Cmhi_S, typeof(OpCodeSimdReg64)); - SetA64("0>101110<<1xxxxx001101xxxxxxxxxx", InstEmit.Cmhi_V, typeof(OpCodeSimdReg64)); - SetA64("01111110111xxxxx001111xxxxxxxxxx", InstEmit.Cmhs_S, typeof(OpCodeSimdReg64)); - SetA64("0>101110<<1xxxxx001111xxxxxxxxxx", InstEmit.Cmhs_V, typeof(OpCodeSimdReg64)); - SetA64("0111111011100000100110xxxxxxxxxx", InstEmit.Cmle_S, typeof(OpCodeSimd64)); - SetA64("0>101110<<100000100110xxxxxxxxxx", InstEmit.Cmle_V, typeof(OpCodeSimd64)); - SetA64("0101111011100000101010xxxxxxxxxx", InstEmit.Cmlt_S, typeof(OpCodeSimd64)); - SetA64("0>001110<<100000101010xxxxxxxxxx", InstEmit.Cmlt_V, typeof(OpCodeSimd64)); - SetA64("01011110111xxxxx100011xxxxxxxxxx", InstEmit.Cmtst_S, typeof(OpCodeSimdReg64)); - SetA64("0>001110<<1xxxxx100011xxxxxxxxxx", InstEmit.Cmtst_V, typeof(OpCodeSimdReg64)); - SetA64("0x00111000100000010110xxxxxxxxxx", InstEmit.Cnt_V, typeof(OpCodeSimd64)); - SetA64("0>001110000x<>>>000011xxxxxxxxxx", InstEmit.Dup_Gp, typeof(OpCodeSimdIns64)); - SetA64("01011110000xxxxx000001xxxxxxxxxx", InstEmit.Dup_S, typeof(OpCodeSimdIns64)); - SetA64("0>001110000x<>>>000001xxxxxxxxxx", InstEmit.Dup_V, typeof(OpCodeSimdIns64)); - SetA64("0x101110001xxxxx000111xxxxxxxxxx", InstEmit.Eor_V, typeof(OpCodeSimdReg64)); - SetA64("0>101110000xxxxx0<xxx0xxxxxxxxxx", InstEmit.Ext_V, typeof(OpCodeSimdExt64)); - SetA64("011111101x1xxxxx110101xxxxxxxxxx", InstEmit.Fabd_S, typeof(OpCodeSimdReg64)); - SetA64("0>1011101<1xxxxx110101xxxxxxxxxx", InstEmit.Fabd_V, typeof(OpCodeSimdReg64)); - SetA64("000111100x100000110000xxxxxxxxxx", InstEmit.Fabs_S, typeof(OpCodeSimd64)); - SetA64("0>0011101<100000111110xxxxxxxxxx", InstEmit.Fabs_V, typeof(OpCodeSimd64)); - SetA64("000111100x1xxxxx001010xxxxxxxxxx", InstEmit.Fadd_S, typeof(OpCodeSimdReg64)); - SetA64("0>0011100<1xxxxx110101xxxxxxxxxx", InstEmit.Fadd_V, typeof(OpCodeSimdReg64)); - SetA64("011111100x110000110110xxxxxxxxxx", InstEmit.Faddp_S, typeof(OpCodeSimd64)); - SetA64("0>1011100<1xxxxx110101xxxxxxxxxx", InstEmit.Faddp_V, typeof(OpCodeSimdReg64)); - SetA64("000111100x1xxxxxxxxx01xxxxx0xxxx", InstEmit.Fccmp_S, typeof(OpCodeSimdFcond64)); - SetA64("000111100x1xxxxxxxxx01xxxxx1xxxx", InstEmit.Fccmpe_S, typeof(OpCodeSimdFcond64)); - SetA64("010111100x1xxxxx111001xxxxxxxxxx", InstEmit.Fcmeq_S, typeof(OpCodeSimdReg64)); - SetA64("010111101x100000110110xxxxxxxxxx", InstEmit.Fcmeq_S, typeof(OpCodeSimd64)); - SetA64("0>0011100<1xxxxx111001xxxxxxxxxx", InstEmit.Fcmeq_V, typeof(OpCodeSimdReg64)); - SetA64("0>0011101<100000110110xxxxxxxxxx", InstEmit.Fcmeq_V, typeof(OpCodeSimd64)); - SetA64("011111100x1xxxxx111001xxxxxxxxxx", InstEmit.Fcmge_S, typeof(OpCodeSimdReg64)); - SetA64("011111101x100000110010xxxxxxxxxx", InstEmit.Fcmge_S, typeof(OpCodeSimd64)); - SetA64("0>1011100<1xxxxx111001xxxxxxxxxx", InstEmit.Fcmge_V, typeof(OpCodeSimdReg64)); - SetA64("0>1011101<100000110010xxxxxxxxxx", InstEmit.Fcmge_V, typeof(OpCodeSimd64)); - SetA64("011111101x1xxxxx111001xxxxxxxxxx", InstEmit.Fcmgt_S, typeof(OpCodeSimdReg64)); - SetA64("010111101x100000110010xxxxxxxxxx", InstEmit.Fcmgt_S, typeof(OpCodeSimd64)); - SetA64("0>1011101<1xxxxx111001xxxxxxxxxx", InstEmit.Fcmgt_V, typeof(OpCodeSimdReg64)); - SetA64("0>0011101<100000110010xxxxxxxxxx", InstEmit.Fcmgt_V, typeof(OpCodeSimd64)); - SetA64("011111101x100000110110xxxxxxxxxx", InstEmit.Fcmle_S, typeof(OpCodeSimd64)); - SetA64("0>1011101<100000110110xxxxxxxxxx", InstEmit.Fcmle_V, typeof(OpCodeSimd64)); - SetA64("010111101x100000111010xxxxxxxxxx", InstEmit.Fcmlt_S, typeof(OpCodeSimd64)); - SetA64("0>0011101<100000111010xxxxxxxxxx", InstEmit.Fcmlt_V, typeof(OpCodeSimd64)); - SetA64("000111100x1xxxxx001000xxxxx0x000", InstEmit.Fcmp_S, typeof(OpCodeSimdReg64)); - SetA64("000111100x1xxxxx001000xxxxx1x000", InstEmit.Fcmpe_S, typeof(OpCodeSimdReg64)); - SetA64("000111100x1xxxxxxxxx11xxxxxxxxxx", InstEmit.Fcsel_S, typeof(OpCodeSimdFcond64)); - SetA64("00011110xx10001xx10000xxxxxxxxxx", InstEmit.Fcvt_S, typeof(OpCodeSimd64)); - SetA64("x00111100x100100000000xxxxxxxxxx", InstEmit.Fcvtas_Gp, typeof(OpCodeSimdCvt64)); - SetA64("x00111100x100101000000xxxxxxxxxx", InstEmit.Fcvtau_Gp, typeof(OpCodeSimdCvt64)); - SetA64("0x0011100x100001011110xxxxxxxxxx", InstEmit.Fcvtl_V, typeof(OpCodeSimd64)); - SetA64("x00111100x110000000000xxxxxxxxxx", InstEmit.Fcvtms_Gp, typeof(OpCodeSimdCvt64)); - SetA64("x00111100x110001000000xxxxxxxxxx", InstEmit.Fcvtmu_Gp, typeof(OpCodeSimdCvt64)); - SetA64("0x0011100x100001011010xxxxxxxxxx", InstEmit.Fcvtn_V, typeof(OpCodeSimd64)); - SetA64("010111100x100001101010xxxxxxxxxx", InstEmit.Fcvtns_S, typeof(OpCodeSimd64)); - SetA64("0>0011100<100001101010xxxxxxxxxx", InstEmit.Fcvtns_V, typeof(OpCodeSimd64)); - SetA64("011111100x100001101010xxxxxxxxxx", InstEmit.Fcvtnu_S, typeof(OpCodeSimd64)); - SetA64("0>1011100<100001101010xxxxxxxxxx", InstEmit.Fcvtnu_V, typeof(OpCodeSimd64)); - SetA64("x00111100x101000000000xxxxxxxxxx", InstEmit.Fcvtps_Gp, typeof(OpCodeSimdCvt64)); - SetA64("x00111100x101001000000xxxxxxxxxx", InstEmit.Fcvtpu_Gp, typeof(OpCodeSimdCvt64)); - SetA64("x00111100x111000000000xxxxxxxxxx", InstEmit.Fcvtzs_Gp, typeof(OpCodeSimdCvt64)); - SetA64(">00111100x011000>xxxxxxxxxxxxxxx", InstEmit.Fcvtzs_Gp_Fixed, typeof(OpCodeSimdCvt64)); - SetA64("010111101x100001101110xxxxxxxxxx", InstEmit.Fcvtzs_S, typeof(OpCodeSimd64)); - SetA64("0>0011101<100001101110xxxxxxxxxx", InstEmit.Fcvtzs_V, typeof(OpCodeSimd64)); - SetA64("0x001111001xxxxx111111xxxxxxxxxx", InstEmit.Fcvtzs_V_Fixed, typeof(OpCodeSimdShImm64)); - SetA64("0100111101xxxxxx111111xxxxxxxxxx", InstEmit.Fcvtzs_V_Fixed, typeof(OpCodeSimdShImm64)); - SetA64("x00111100x111001000000xxxxxxxxxx", InstEmit.Fcvtzu_Gp, typeof(OpCodeSimdCvt64)); - SetA64(">00111100x011001>xxxxxxxxxxxxxxx", InstEmit.Fcvtzu_Gp_Fixed, typeof(OpCodeSimdCvt64)); - SetA64("011111101x100001101110xxxxxxxxxx", InstEmit.Fcvtzu_S, typeof(OpCodeSimd64)); - SetA64("0>1011101<100001101110xxxxxxxxxx", InstEmit.Fcvtzu_V, typeof(OpCodeSimd64)); - SetA64("0x101111001xxxxx111111xxxxxxxxxx", InstEmit.Fcvtzu_V_Fixed, typeof(OpCodeSimdShImm64)); - SetA64("0110111101xxxxxx111111xxxxxxxxxx", InstEmit.Fcvtzu_V_Fixed, typeof(OpCodeSimdShImm64)); - SetA64("000111100x1xxxxx000110xxxxxxxxxx", InstEmit.Fdiv_S, typeof(OpCodeSimdReg64)); - SetA64("0>1011100<1xxxxx111111xxxxxxxxxx", InstEmit.Fdiv_V, typeof(OpCodeSimdReg64)); - SetA64("000111110x0xxxxx0xxxxxxxxxxxxxxx", InstEmit.Fmadd_S, typeof(OpCodeSimdReg64)); - SetA64("000111100x1xxxxx010010xxxxxxxxxx", InstEmit.Fmax_S, typeof(OpCodeSimdReg64)); - SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", InstEmit.Fmax_V, typeof(OpCodeSimdReg64)); - SetA64("000111100x1xxxxx011010xxxxxxxxxx", InstEmit.Fmaxnm_S, typeof(OpCodeSimdReg64)); - SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", InstEmit.Fmaxnm_V, typeof(OpCodeSimdReg64)); - SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", InstEmit.Fmaxp_V, typeof(OpCodeSimdReg64)); - SetA64("000111100x1xxxxx010110xxxxxxxxxx", InstEmit.Fmin_S, typeof(OpCodeSimdReg64)); - SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", InstEmit.Fmin_V, typeof(OpCodeSimdReg64)); - SetA64("000111100x1xxxxx011110xxxxxxxxxx", InstEmit.Fminnm_S, typeof(OpCodeSimdReg64)); - SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", InstEmit.Fminnm_V, typeof(OpCodeSimdReg64)); - SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", InstEmit.Fminp_V, typeof(OpCodeSimdReg64)); - SetA64("010111111xxxxxxx0001x0xxxxxxxxxx", InstEmit.Fmla_Se, typeof(OpCodeSimdRegElemF64)); - SetA64("0>0011100<1xxxxx110011xxxxxxxxxx", InstEmit.Fmla_V, typeof(OpCodeSimdReg64)); - SetA64("0>0011111<xxxxxx0001x0xxxxxxxxxx", InstEmit.Fmla_Ve, typeof(OpCodeSimdRegElemF64)); - SetA64("010111111xxxxxxx0101x0xxxxxxxxxx", InstEmit.Fmls_Se, typeof(OpCodeSimdRegElemF64)); - SetA64("0>0011101<1xxxxx110011xxxxxxxxxx", InstEmit.Fmls_V, typeof(OpCodeSimdReg64)); - SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", InstEmit.Fmls_Ve, typeof(OpCodeSimdRegElemF64)); - SetA64("000111100x100000010000xxxxxxxxxx", InstEmit.Fmov_S, typeof(OpCodeSimd64)); - SetA64("000111100x1xxxxxxxx10000000xxxxx", InstEmit.Fmov_Si, typeof(OpCodeSimdFmov64)); - SetA64("0x00111100000xxx111101xxxxxxxxxx", InstEmit.Fmov_Vi, typeof(OpCodeSimdImm64)); - SetA64("0110111100000xxx111101xxxxxxxxxx", InstEmit.Fmov_Vi, typeof(OpCodeSimdImm64)); - SetA64("0001111000100110000000xxxxxxxxxx", InstEmit.Fmov_Ftoi, typeof(OpCodeSimd64)); - SetA64("1001111001100110000000xxxxxxxxxx", InstEmit.Fmov_Ftoi, typeof(OpCodeSimd64)); - SetA64("0001111000100111000000xxxxxxxxxx", InstEmit.Fmov_Itof, typeof(OpCodeSimd64)); - SetA64("1001111001100111000000xxxxxxxxxx", InstEmit.Fmov_Itof, typeof(OpCodeSimd64)); - SetA64("1001111010101110000000xxxxxxxxxx", InstEmit.Fmov_Ftoi1, typeof(OpCodeSimd64)); - SetA64("1001111010101111000000xxxxxxxxxx", InstEmit.Fmov_Itof1, typeof(OpCodeSimd64)); - SetA64("000111110x0xxxxx1xxxxxxxxxxxxxxx", InstEmit.Fmsub_S, typeof(OpCodeSimdReg64)); - SetA64("000111100x1xxxxx000010xxxxxxxxxx", InstEmit.Fmul_S, typeof(OpCodeSimdReg64)); - SetA64("010111111xxxxxxx1001x0xxxxxxxxxx", InstEmit.Fmul_Se, typeof(OpCodeSimdRegElemF64)); - SetA64("0>1011100<1xxxxx110111xxxxxxxxxx", InstEmit.Fmul_V, typeof(OpCodeSimdReg64)); - SetA64("0>0011111<xxxxxx1001x0xxxxxxxxxx", InstEmit.Fmul_Ve, typeof(OpCodeSimdRegElemF64)); - SetA64("010111100x1xxxxx110111xxxxxxxxxx", InstEmit.Fmulx_S, typeof(OpCodeSimdReg64)); - SetA64("011111111xxxxxxx1001x0xxxxxxxxxx", InstEmit.Fmulx_Se, typeof(OpCodeSimdRegElemF64)); - SetA64("0>0011100<1xxxxx110111xxxxxxxxxx", InstEmit.Fmulx_V, typeof(OpCodeSimdReg64)); - SetA64("0>1011111<xxxxxx1001x0xxxxxxxxxx", InstEmit.Fmulx_Ve, typeof(OpCodeSimdRegElemF64)); - SetA64("000111100x100001010000xxxxxxxxxx", InstEmit.Fneg_S, typeof(OpCodeSimd64)); - SetA64("0>1011101<100000111110xxxxxxxxxx", InstEmit.Fneg_V, typeof(OpCodeSimd64)); - SetA64("000111110x1xxxxx0xxxxxxxxxxxxxxx", InstEmit.Fnmadd_S, typeof(OpCodeSimdReg64)); - SetA64("000111110x1xxxxx1xxxxxxxxxxxxxxx", InstEmit.Fnmsub_S, typeof(OpCodeSimdReg64)); - SetA64("000111100x1xxxxx100010xxxxxxxxxx", InstEmit.Fnmul_S, typeof(OpCodeSimdReg64)); - SetA64("010111101x100001110110xxxxxxxxxx", InstEmit.Frecpe_S, typeof(OpCodeSimd64)); - SetA64("0>0011101<100001110110xxxxxxxxxx", InstEmit.Frecpe_V, typeof(OpCodeSimd64)); - SetA64("010111100x1xxxxx111111xxxxxxxxxx", InstEmit.Frecps_S, typeof(OpCodeSimdReg64)); - SetA64("0>0011100<1xxxxx111111xxxxxxxxxx", InstEmit.Frecps_V, typeof(OpCodeSimdReg64)); - SetA64("010111101x100001111110xxxxxxxxxx", InstEmit.Frecpx_S, typeof(OpCodeSimd64)); - SetA64("000111100x100110010000xxxxxxxxxx", InstEmit.Frinta_S, typeof(OpCodeSimd64)); - SetA64("0>1011100<100001100010xxxxxxxxxx", InstEmit.Frinta_V, typeof(OpCodeSimd64)); - SetA64("000111100x100111110000xxxxxxxxxx", InstEmit.Frinti_S, typeof(OpCodeSimd64)); - SetA64("0>1011101<100001100110xxxxxxxxxx", InstEmit.Frinti_V, typeof(OpCodeSimd64)); - SetA64("000111100x100101010000xxxxxxxxxx", InstEmit.Frintm_S, typeof(OpCodeSimd64)); - SetA64("0>0011100<100001100110xxxxxxxxxx", InstEmit.Frintm_V, typeof(OpCodeSimd64)); - SetA64("000111100x100100010000xxxxxxxxxx", InstEmit.Frintn_S, typeof(OpCodeSimd64)); - SetA64("0>0011100<100001100010xxxxxxxxxx", InstEmit.Frintn_V, typeof(OpCodeSimd64)); - SetA64("000111100x100100110000xxxxxxxxxx", InstEmit.Frintp_S, typeof(OpCodeSimd64)); - SetA64("0>0011101<100001100010xxxxxxxxxx", InstEmit.Frintp_V, typeof(OpCodeSimd64)); - SetA64("000111100x100111010000xxxxxxxxxx", InstEmit.Frintx_S, typeof(OpCodeSimd64)); - SetA64("0>1011100<100001100110xxxxxxxxxx", InstEmit.Frintx_V, typeof(OpCodeSimd64)); - SetA64("000111100x100101110000xxxxxxxxxx", InstEmit.Frintz_S, typeof(OpCodeSimd64)); - SetA64("0>0011101<100001100110xxxxxxxxxx", InstEmit.Frintz_V, typeof(OpCodeSimd64)); - SetA64("011111101x100001110110xxxxxxxxxx", InstEmit.Frsqrte_S, typeof(OpCodeSimd64)); - SetA64("0>1011101<100001110110xxxxxxxxxx", InstEmit.Frsqrte_V, typeof(OpCodeSimd64)); - SetA64("010111101x1xxxxx111111xxxxxxxxxx", InstEmit.Frsqrts_S, typeof(OpCodeSimdReg64)); - SetA64("0>0011101<1xxxxx111111xxxxxxxxxx", InstEmit.Frsqrts_V, typeof(OpCodeSimdReg64)); - SetA64("000111100x100001110000xxxxxxxxxx", InstEmit.Fsqrt_S, typeof(OpCodeSimd64)); - SetA64("0>1011101<100001111110xxxxxxxxxx", InstEmit.Fsqrt_V, typeof(OpCodeSimd64)); - SetA64("000111100x1xxxxx001110xxxxxxxxxx", InstEmit.Fsub_S, typeof(OpCodeSimdReg64)); - SetA64("0>0011101<1xxxxx110101xxxxxxxxxx", InstEmit.Fsub_V, typeof(OpCodeSimdReg64)); - SetA64("01001110000xxxxx000111xxxxxxxxxx", InstEmit.Ins_Gp, typeof(OpCodeSimdIns64)); - SetA64("01101110000xxxxx0xxxx1xxxxxxxxxx", InstEmit.Ins_V, typeof(OpCodeSimdIns64)); - SetA64("0x00110001000000xxxxxxxxxxxxxxxx", InstEmit.Ld__Vms, typeof(OpCodeSimdMemMs64)); - SetA64("0x001100110xxxxxxxxxxxxxxxxxxxxx", InstEmit.Ld__Vms, typeof(OpCodeSimdMemMs64)); - SetA64("0x00110101x00000xxxxxxxxxxxxxxxx", InstEmit.Ld__Vss, typeof(OpCodeSimdMemSs64)); - SetA64("0x00110111xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Ld__Vss, typeof(OpCodeSimdMemSs64)); - SetA64("xx10110xx1xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Ldp, typeof(OpCodeSimdMemPair64)); - SetA64("xx111100x10xxxxxxxxx00xxxxxxxxxx", InstEmit.Ldr, typeof(OpCodeSimdMemImm64)); - SetA64("xx111100x10xxxxxxxxx01xxxxxxxxxx", InstEmit.Ldr, typeof(OpCodeSimdMemImm64)); - SetA64("xx111100x10xxxxxxxxx11xxxxxxxxxx", InstEmit.Ldr, typeof(OpCodeSimdMemImm64)); - SetA64("xx111101x1xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Ldr, typeof(OpCodeSimdMemImm64)); - SetA64("xx111100x11xxxxxxxxx10xxxxxxxxxx", InstEmit.Ldr, typeof(OpCodeSimdMemReg64)); - SetA64("xx011100xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Ldr_Literal, typeof(OpCodeSimdMemLit64)); - SetA64("0x001110<<1xxxxx100101xxxxxxxxxx", InstEmit.Mla_V, typeof(OpCodeSimdReg64)); - SetA64("0x101111xxxxxxxx0000x0xxxxxxxxxx", InstEmit.Mla_Ve, typeof(OpCodeSimdRegElem64)); - SetA64("0x101110<<1xxxxx100101xxxxxxxxxx", InstEmit.Mls_V, typeof(OpCodeSimdReg64)); - SetA64("0x101111xxxxxxxx0100x0xxxxxxxxxx", InstEmit.Mls_Ve, typeof(OpCodeSimdRegElem64)); - SetA64("0x00111100000xxx0xx001xxxxxxxxxx", InstEmit.Movi_V, typeof(OpCodeSimdImm64)); - SetA64("0x00111100000xxx10x001xxxxxxxxxx", InstEmit.Movi_V, typeof(OpCodeSimdImm64)); - SetA64("0x00111100000xxx110x01xxxxxxxxxx", InstEmit.Movi_V, typeof(OpCodeSimdImm64)); - SetA64("0xx0111100000xxx111001xxxxxxxxxx", InstEmit.Movi_V, typeof(OpCodeSimdImm64)); - SetA64("0x001110<<1xxxxx100111xxxxxxxxxx", InstEmit.Mul_V, typeof(OpCodeSimdReg64)); - SetA64("0x001111xxxxxxxx1000x0xxxxxxxxxx", InstEmit.Mul_Ve, typeof(OpCodeSimdRegElem64)); - SetA64("0x10111100000xxx0xx001xxxxxxxxxx", InstEmit.Mvni_V, typeof(OpCodeSimdImm64)); - SetA64("0x10111100000xxx10x001xxxxxxxxxx", InstEmit.Mvni_V, typeof(OpCodeSimdImm64)); - SetA64("0x10111100000xxx110x01xxxxxxxxxx", InstEmit.Mvni_V, typeof(OpCodeSimdImm64)); - SetA64("0111111011100000101110xxxxxxxxxx", InstEmit.Neg_S, typeof(OpCodeSimd64)); - SetA64("0>101110<<100000101110xxxxxxxxxx", InstEmit.Neg_V, typeof(OpCodeSimd64)); - SetA64("0x10111000100000010110xxxxxxxxxx", InstEmit.Not_V, typeof(OpCodeSimd64)); - SetA64("0x001110111xxxxx000111xxxxxxxxxx", InstEmit.Orn_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110101xxxxx000111xxxxxxxxxx", InstEmit.Orr_V, typeof(OpCodeSimdReg64)); - SetA64("0x00111100000xxx0xx101xxxxxxxxxx", InstEmit.Orr_Vi, typeof(OpCodeSimdImm64)); - SetA64("0x00111100000xxx10x101xxxxxxxxxx", InstEmit.Orr_Vi, typeof(OpCodeSimdImm64)); - SetA64("0x101110<<1xxxxx010000xxxxxxxxxx", InstEmit.Raddhn_V, typeof(OpCodeSimdReg64)); - SetA64("0x10111001100000010110xxxxxxxxxx", InstEmit.Rbit_V, typeof(OpCodeSimd64)); - SetA64("0x00111000100000000110xxxxxxxxxx", InstEmit.Rev16_V, typeof(OpCodeSimd64)); - SetA64("0x1011100x100000000010xxxxxxxxxx", InstEmit.Rev32_V, typeof(OpCodeSimd64)); - SetA64("0x001110<<100000000010xxxxxxxxxx", InstEmit.Rev64_V, typeof(OpCodeSimd64)); - SetA64("0x00111100>>>xxx100011xxxxxxxxxx", InstEmit.Rshrn_V, typeof(OpCodeSimdShImm64)); - SetA64("0x101110<<1xxxxx011000xxxxxxxxxx", InstEmit.Rsubhn_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<1xxxxx011111xxxxxxxxxx", InstEmit.Saba_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<1xxxxx010100xxxxxxxxxx", InstEmit.Sabal_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<1xxxxx011101xxxxxxxxxx", InstEmit.Sabd_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<1xxxxx011100xxxxxxxxxx", InstEmit.Sabdl_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<100000011010xxxxxxxxxx", InstEmit.Sadalp_V, typeof(OpCodeSimd64)); - SetA64("0x001110<<1xxxxx000000xxxxxxxxxx", InstEmit.Saddl_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<100000001010xxxxxxxxxx", InstEmit.Saddlp_V, typeof(OpCodeSimd64)); - SetA64("000011100x110000001110xxxxxxxxxx", InstEmit.Saddlv_V, typeof(OpCodeSimd64)); - SetA64("01001110<<110000001110xxxxxxxxxx", InstEmit.Saddlv_V, typeof(OpCodeSimd64)); - SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", InstEmit.Saddw_V, typeof(OpCodeSimdReg64)); - SetA64("x00111100x100010000000xxxxxxxxxx", InstEmit.Scvtf_Gp, typeof(OpCodeSimdCvt64)); - SetA64(">00111100x000010>xxxxxxxxxxxxxxx", InstEmit.Scvtf_Gp_Fixed, typeof(OpCodeSimdCvt64)); - SetA64("010111100x100001110110xxxxxxxxxx", InstEmit.Scvtf_S, typeof(OpCodeSimd64)); - SetA64("0>0011100<100001110110xxxxxxxxxx", InstEmit.Scvtf_V, typeof(OpCodeSimd64)); - SetA64("0x001111001xxxxx111001xxxxxxxxxx", InstEmit.Scvtf_V_Fixed, typeof(OpCodeSimdShImm64)); - SetA64("0100111101xxxxxx111001xxxxxxxxxx", InstEmit.Scvtf_V_Fixed, typeof(OpCodeSimdShImm64)); - SetA64("01011110000xxxxx000000xxxxxxxxxx", InstEmit.Sha1c_V, typeof(OpCodeSimdReg64)); - SetA64("0101111000101000000010xxxxxxxxxx", InstEmit.Sha1h_V, typeof(OpCodeSimd64)); - SetA64("01011110000xxxxx001000xxxxxxxxxx", InstEmit.Sha1m_V, typeof(OpCodeSimdReg64)); - SetA64("01011110000xxxxx000100xxxxxxxxxx", InstEmit.Sha1p_V, typeof(OpCodeSimdReg64)); - SetA64("01011110000xxxxx001100xxxxxxxxxx", InstEmit.Sha1su0_V, typeof(OpCodeSimdReg64)); - SetA64("0101111000101000000110xxxxxxxxxx", InstEmit.Sha1su1_V, typeof(OpCodeSimd64)); - SetA64("01011110000xxxxx010000xxxxxxxxxx", InstEmit.Sha256h_V, typeof(OpCodeSimdReg64)); - SetA64("01011110000xxxxx010100xxxxxxxxxx", InstEmit.Sha256h2_V, typeof(OpCodeSimdReg64)); - SetA64("0101111000101000001010xxxxxxxxxx", InstEmit.Sha256su0_V, typeof(OpCodeSimd64)); - SetA64("01011110000xxxxx011000xxxxxxxxxx", InstEmit.Sha256su1_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<1xxxxx000001xxxxxxxxxx", InstEmit.Shadd_V, typeof(OpCodeSimdReg64)); - SetA64("0101111101xxxxxx010101xxxxxxxxxx", InstEmit.Shl_S, typeof(OpCodeSimdShImm64)); - SetA64("0x00111100>>>xxx010101xxxxxxxxxx", InstEmit.Shl_V, typeof(OpCodeSimdShImm64)); - SetA64("0100111101xxxxxx010101xxxxxxxxxx", InstEmit.Shl_V, typeof(OpCodeSimdShImm64)); - SetA64("0x101110<<100001001110xxxxxxxxxx", InstEmit.Shll_V, typeof(OpCodeSimd64)); - SetA64("0x00111100>>>xxx100001xxxxxxxxxx", InstEmit.Shrn_V, typeof(OpCodeSimdShImm64)); - SetA64("0x001110<<1xxxxx001001xxxxxxxxxx", InstEmit.Shsub_V, typeof(OpCodeSimdReg64)); - SetA64("0x10111100>>>xxx010101xxxxxxxxxx", InstEmit.Sli_V, typeof(OpCodeSimdShImm64)); - SetA64("0110111101xxxxxx010101xxxxxxxxxx", InstEmit.Sli_V, typeof(OpCodeSimdShImm64)); - SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", InstEmit.Smax_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstEmit.Smaxp_V, typeof(OpCodeSimdReg64)); - SetA64("000011100x110000101010xxxxxxxxxx", InstEmit.Smaxv_V, typeof(OpCodeSimd64)); - SetA64("01001110<<110000101010xxxxxxxxxx", InstEmit.Smaxv_V, typeof(OpCodeSimd64)); - SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", InstEmit.Smin_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", InstEmit.Sminp_V, typeof(OpCodeSimdReg64)); - SetA64("000011100x110001101010xxxxxxxxxx", InstEmit.Sminv_V, typeof(OpCodeSimd64)); - SetA64("01001110<<110001101010xxxxxxxxxx", InstEmit.Sminv_V, typeof(OpCodeSimd64)); - SetA64("0x001110<<1xxxxx100000xxxxxxxxxx", InstEmit.Smlal_V, typeof(OpCodeSimdReg64)); - SetA64("0x001111xxxxxxxx0010x0xxxxxxxxxx", InstEmit.Smlal_Ve, typeof(OpCodeSimdRegElem64)); - SetA64("0x001110<<1xxxxx101000xxxxxxxxxx", InstEmit.Smlsl_V, typeof(OpCodeSimdReg64)); - SetA64("0x001111xxxxxxxx0110x0xxxxxxxxxx", InstEmit.Smlsl_Ve, typeof(OpCodeSimdRegElem64)); - SetA64("0x001110000xxxxx001011xxxxxxxxxx", InstEmit.Smov_S, typeof(OpCodeSimdIns64)); - SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", InstEmit.Smull_V, typeof(OpCodeSimdReg64)); - SetA64("0x001111xxxxxxxx1010x0xxxxxxxxxx", InstEmit.Smull_Ve, typeof(OpCodeSimdRegElem64)); - SetA64("01011110xx100000011110xxxxxxxxxx", InstEmit.Sqabs_S, typeof(OpCodeSimd64)); - SetA64("0>001110<<100000011110xxxxxxxxxx", InstEmit.Sqabs_V, typeof(OpCodeSimd64)); - SetA64("01011110xx1xxxxx000011xxxxxxxxxx", InstEmit.Sqadd_S, typeof(OpCodeSimdReg64)); - SetA64("0>001110<<1xxxxx000011xxxxxxxxxx", InstEmit.Sqadd_V, typeof(OpCodeSimdReg64)); - SetA64("01011110011xxxxx101101xxxxxxxxxx", InstEmit.Sqdmulh_S, typeof(OpCodeSimdReg64)); - SetA64("01011110101xxxxx101101xxxxxxxxxx", InstEmit.Sqdmulh_S, typeof(OpCodeSimdReg64)); - SetA64("0x001110011xxxxx101101xxxxxxxxxx", InstEmit.Sqdmulh_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110101xxxxx101101xxxxxxxxxx", InstEmit.Sqdmulh_V, typeof(OpCodeSimdReg64)); - SetA64("01111110xx100000011110xxxxxxxxxx", InstEmit.Sqneg_S, typeof(OpCodeSimd64)); - SetA64("0>101110<<100000011110xxxxxxxxxx", InstEmit.Sqneg_V, typeof(OpCodeSimd64)); - SetA64("01111110011xxxxx101101xxxxxxxxxx", InstEmit.Sqrdmulh_S, typeof(OpCodeSimdReg64)); - SetA64("01111110101xxxxx101101xxxxxxxxxx", InstEmit.Sqrdmulh_S, typeof(OpCodeSimdReg64)); - SetA64("0x101110011xxxxx101101xxxxxxxxxx", InstEmit.Sqrdmulh_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110101xxxxx101101xxxxxxxxxx", InstEmit.Sqrdmulh_V, typeof(OpCodeSimdReg64)); - SetA64("0>001110<<1xxxxx010111xxxxxxxxxx", InstEmit.Sqrshl_V, typeof(OpCodeSimdReg64)); - SetA64("0101111100>>>xxx100111xxxxxxxxxx", InstEmit.Sqrshrn_S, typeof(OpCodeSimdShImm64)); - SetA64("0x00111100>>>xxx100111xxxxxxxxxx", InstEmit.Sqrshrn_V, typeof(OpCodeSimdShImm64)); - SetA64("0111111100>>>xxx100011xxxxxxxxxx", InstEmit.Sqrshrun_S, typeof(OpCodeSimdShImm64)); - SetA64("0x10111100>>>xxx100011xxxxxxxxxx", InstEmit.Sqrshrun_V, typeof(OpCodeSimdShImm64)); - SetA64("0>001110<<1xxxxx010011xxxxxxxxxx", InstEmit.Sqshl_V, typeof(OpCodeSimdReg64)); - SetA64("0101111100>>>xxx100101xxxxxxxxxx", InstEmit.Sqshrn_S, typeof(OpCodeSimdShImm64)); - SetA64("0x00111100>>>xxx100101xxxxxxxxxx", InstEmit.Sqshrn_V, typeof(OpCodeSimdShImm64)); - SetA64("0111111100>>>xxx100001xxxxxxxxxx", InstEmit.Sqshrun_S, typeof(OpCodeSimdShImm64)); - SetA64("0x10111100>>>xxx100001xxxxxxxxxx", InstEmit.Sqshrun_V, typeof(OpCodeSimdShImm64)); - SetA64("01011110xx1xxxxx001011xxxxxxxxxx", InstEmit.Sqsub_S, typeof(OpCodeSimdReg64)); - SetA64("0>001110<<1xxxxx001011xxxxxxxxxx", InstEmit.Sqsub_V, typeof(OpCodeSimdReg64)); - SetA64("01011110<<100001010010xxxxxxxxxx", InstEmit.Sqxtn_S, typeof(OpCodeSimd64)); - SetA64("0x001110<<100001010010xxxxxxxxxx", InstEmit.Sqxtn_V, typeof(OpCodeSimd64)); - SetA64("01111110<<100001001010xxxxxxxxxx", InstEmit.Sqxtun_S, typeof(OpCodeSimd64)); - SetA64("0x101110<<100001001010xxxxxxxxxx", InstEmit.Sqxtun_V, typeof(OpCodeSimd64)); - SetA64("0x001110<<1xxxxx000101xxxxxxxxxx", InstEmit.Srhadd_V, typeof(OpCodeSimdReg64)); - SetA64("0>001110<<1xxxxx010101xxxxxxxxxx", InstEmit.Srshl_V, typeof(OpCodeSimdReg64)); - SetA64("0101111101xxxxxx001001xxxxxxxxxx", InstEmit.Srshr_S, typeof(OpCodeSimdShImm64)); - SetA64("0x00111100>>>xxx001001xxxxxxxxxx", InstEmit.Srshr_V, typeof(OpCodeSimdShImm64)); - SetA64("0100111101xxxxxx001001xxxxxxxxxx", InstEmit.Srshr_V, typeof(OpCodeSimdShImm64)); - SetA64("0101111101xxxxxx001101xxxxxxxxxx", InstEmit.Srsra_S, typeof(OpCodeSimdShImm64)); - SetA64("0x00111100>>>xxx001101xxxxxxxxxx", InstEmit.Srsra_V, typeof(OpCodeSimdShImm64)); - SetA64("0100111101xxxxxx001101xxxxxxxxxx", InstEmit.Srsra_V, typeof(OpCodeSimdShImm64)); - SetA64("0>001110<<1xxxxx010001xxxxxxxxxx", InstEmit.Sshl_V, typeof(OpCodeSimdReg64)); - SetA64("0x00111100>>>xxx101001xxxxxxxxxx", InstEmit.Sshll_V, typeof(OpCodeSimdShImm64)); - SetA64("0101111101xxxxxx000001xxxxxxxxxx", InstEmit.Sshr_S, typeof(OpCodeSimdShImm64)); - SetA64("0x00111100>>>xxx000001xxxxxxxxxx", InstEmit.Sshr_V, typeof(OpCodeSimdShImm64)); - SetA64("0100111101xxxxxx000001xxxxxxxxxx", InstEmit.Sshr_V, typeof(OpCodeSimdShImm64)); - SetA64("0101111101xxxxxx000101xxxxxxxxxx", InstEmit.Ssra_S, typeof(OpCodeSimdShImm64)); - SetA64("0x00111100>>>xxx000101xxxxxxxxxx", InstEmit.Ssra_V, typeof(OpCodeSimdShImm64)); - SetA64("0100111101xxxxxx000101xxxxxxxxxx", InstEmit.Ssra_V, typeof(OpCodeSimdShImm64)); - SetA64("0x001110<<1xxxxx001000xxxxxxxxxx", InstEmit.Ssubl_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<1xxxxx001100xxxxxxxxxx", InstEmit.Ssubw_V, typeof(OpCodeSimdReg64)); - SetA64("0x00110000000000xxxxxxxxxxxxxxxx", InstEmit.St__Vms, typeof(OpCodeSimdMemMs64)); - SetA64("0x001100100xxxxxxxxxxxxxxxxxxxxx", InstEmit.St__Vms, typeof(OpCodeSimdMemMs64)); - SetA64("0x00110100x00000xxxxxxxxxxxxxxxx", InstEmit.St__Vss, typeof(OpCodeSimdMemSs64)); - SetA64("0x00110110xxxxxxxxxxxxxxxxxxxxxx", InstEmit.St__Vss, typeof(OpCodeSimdMemSs64)); - SetA64("xx10110xx0xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Stp, typeof(OpCodeSimdMemPair64)); - SetA64("xx111100x00xxxxxxxxx00xxxxxxxxxx", InstEmit.Str, typeof(OpCodeSimdMemImm64)); - SetA64("xx111100x00xxxxxxxxx01xxxxxxxxxx", InstEmit.Str, typeof(OpCodeSimdMemImm64)); - SetA64("xx111100x00xxxxxxxxx11xxxxxxxxxx", InstEmit.Str, typeof(OpCodeSimdMemImm64)); - SetA64("xx111101x0xxxxxxxxxxxxxxxxxxxxxx", InstEmit.Str, typeof(OpCodeSimdMemImm64)); - SetA64("xx111100x01xxxxxxxxx10xxxxxxxxxx", InstEmit.Str, typeof(OpCodeSimdMemReg64)); - SetA64("01111110111xxxxx100001xxxxxxxxxx", InstEmit.Sub_S, typeof(OpCodeSimdReg64)); - SetA64("0>101110<<1xxxxx100001xxxxxxxxxx", InstEmit.Sub_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<1xxxxx011000xxxxxxxxxx", InstEmit.Subhn_V, typeof(OpCodeSimdReg64)); - SetA64("01011110xx100000001110xxxxxxxxxx", InstEmit.Suqadd_S, typeof(OpCodeSimd64)); - SetA64("0>001110<<100000001110xxxxxxxxxx", InstEmit.Suqadd_V, typeof(OpCodeSimd64)); - SetA64("0x001110000xxxxx0xx000xxxxxxxxxx", InstEmit.Tbl_V, typeof(OpCodeSimdTbl64)); - SetA64("0>001110<<0xxxxx001010xxxxxxxxxx", InstEmit.Trn1_V, typeof(OpCodeSimdReg64)); - SetA64("0>001110<<0xxxxx011010xxxxxxxxxx", InstEmit.Trn2_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110<<1xxxxx011111xxxxxxxxxx", InstEmit.Uaba_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110<<1xxxxx010100xxxxxxxxxx", InstEmit.Uabal_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110<<1xxxxx011101xxxxxxxxxx", InstEmit.Uabd_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110<<1xxxxx011100xxxxxxxxxx", InstEmit.Uabdl_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110<<100000011010xxxxxxxxxx", InstEmit.Uadalp_V, typeof(OpCodeSimd64)); - SetA64("0x101110<<1xxxxx000000xxxxxxxxxx", InstEmit.Uaddl_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110<<100000001010xxxxxxxxxx", InstEmit.Uaddlp_V, typeof(OpCodeSimd64)); - SetA64("001011100x110000001110xxxxxxxxxx", InstEmit.Uaddlv_V, typeof(OpCodeSimd64)); - SetA64("01101110<<110000001110xxxxxxxxxx", InstEmit.Uaddlv_V, typeof(OpCodeSimd64)); - SetA64("0x101110<<1xxxxx000100xxxxxxxxxx", InstEmit.Uaddw_V, typeof(OpCodeSimdReg64)); - SetA64("x00111100x100011000000xxxxxxxxxx", InstEmit.Ucvtf_Gp, typeof(OpCodeSimdCvt64)); - SetA64(">00111100x000011>xxxxxxxxxxxxxxx", InstEmit.Ucvtf_Gp_Fixed, typeof(OpCodeSimdCvt64)); - SetA64("011111100x100001110110xxxxxxxxxx", InstEmit.Ucvtf_S, typeof(OpCodeSimd64)); - SetA64("0>1011100<100001110110xxxxxxxxxx", InstEmit.Ucvtf_V, typeof(OpCodeSimd64)); - SetA64("0x101111001xxxxx111001xxxxxxxxxx", InstEmit.Ucvtf_V_Fixed, typeof(OpCodeSimdShImm64)); - SetA64("0110111101xxxxxx111001xxxxxxxxxx", InstEmit.Ucvtf_V_Fixed, typeof(OpCodeSimdShImm64)); - SetA64("0x101110<<1xxxxx000001xxxxxxxxxx", InstEmit.Uhadd_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110<<1xxxxx001001xxxxxxxxxx", InstEmit.Uhsub_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110<<1xxxxx011001xxxxxxxxxx", InstEmit.Umax_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110<<1xxxxx101001xxxxxxxxxx", InstEmit.Umaxp_V, typeof(OpCodeSimdReg64)); - SetA64("001011100x110000101010xxxxxxxxxx", InstEmit.Umaxv_V, typeof(OpCodeSimd64)); - SetA64("01101110<<110000101010xxxxxxxxxx", InstEmit.Umaxv_V, typeof(OpCodeSimd64)); - SetA64("0x101110<<1xxxxx011011xxxxxxxxxx", InstEmit.Umin_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", InstEmit.Uminp_V, typeof(OpCodeSimdReg64)); - SetA64("001011100x110001101010xxxxxxxxxx", InstEmit.Uminv_V, typeof(OpCodeSimd64)); - SetA64("01101110<<110001101010xxxxxxxxxx", InstEmit.Uminv_V, typeof(OpCodeSimd64)); - SetA64("0x101110<<1xxxxx100000xxxxxxxxxx", InstEmit.Umlal_V, typeof(OpCodeSimdReg64)); - SetA64("0x101111xxxxxxxx0010x0xxxxxxxxxx", InstEmit.Umlal_Ve, typeof(OpCodeSimdRegElem64)); - SetA64("0x101110<<1xxxxx101000xxxxxxxxxx", InstEmit.Umlsl_V, typeof(OpCodeSimdReg64)); - SetA64("0x101111xxxxxxxx0110x0xxxxxxxxxx", InstEmit.Umlsl_Ve, typeof(OpCodeSimdRegElem64)); - SetA64("0x001110000xxxxx001111xxxxxxxxxx", InstEmit.Umov_S, typeof(OpCodeSimdIns64)); - SetA64("0x101110<<1xxxxx110000xxxxxxxxxx", InstEmit.Umull_V, typeof(OpCodeSimdReg64)); - SetA64("0x101111xxxxxxxx1010x0xxxxxxxxxx", InstEmit.Umull_Ve, typeof(OpCodeSimdRegElem64)); - SetA64("01111110xx1xxxxx000011xxxxxxxxxx", InstEmit.Uqadd_S, typeof(OpCodeSimdReg64)); - SetA64("0>101110<<1xxxxx000011xxxxxxxxxx", InstEmit.Uqadd_V, typeof(OpCodeSimdReg64)); - SetA64("0>101110<<1xxxxx010111xxxxxxxxxx", InstEmit.Uqrshl_V, typeof(OpCodeSimdReg64)); - SetA64("0111111100>>>xxx100111xxxxxxxxxx", InstEmit.Uqrshrn_S, typeof(OpCodeSimdShImm64)); - SetA64("0x10111100>>>xxx100111xxxxxxxxxx", InstEmit.Uqrshrn_V, typeof(OpCodeSimdShImm64)); - SetA64("0>101110<<1xxxxx010011xxxxxxxxxx", InstEmit.Uqshl_V, typeof(OpCodeSimdReg64)); - SetA64("0111111100>>>xxx100101xxxxxxxxxx", InstEmit.Uqshrn_S, typeof(OpCodeSimdShImm64)); - SetA64("0x10111100>>>xxx100101xxxxxxxxxx", InstEmit.Uqshrn_V, typeof(OpCodeSimdShImm64)); - SetA64("01111110xx1xxxxx001011xxxxxxxxxx", InstEmit.Uqsub_S, typeof(OpCodeSimdReg64)); - SetA64("0>101110<<1xxxxx001011xxxxxxxxxx", InstEmit.Uqsub_V, typeof(OpCodeSimdReg64)); - SetA64("01111110<<100001010010xxxxxxxxxx", InstEmit.Uqxtn_S, typeof(OpCodeSimd64)); - SetA64("0x101110<<100001010010xxxxxxxxxx", InstEmit.Uqxtn_V, typeof(OpCodeSimd64)); - SetA64("0x101110<<1xxxxx000101xxxxxxxxxx", InstEmit.Urhadd_V, typeof(OpCodeSimdReg64)); - SetA64("0>101110<<1xxxxx010101xxxxxxxxxx", InstEmit.Urshl_V, typeof(OpCodeSimdReg64)); - SetA64("0111111101xxxxxx001001xxxxxxxxxx", InstEmit.Urshr_S, typeof(OpCodeSimdShImm64)); - SetA64("0x10111100>>>xxx001001xxxxxxxxxx", InstEmit.Urshr_V, typeof(OpCodeSimdShImm64)); - SetA64("0110111101xxxxxx001001xxxxxxxxxx", InstEmit.Urshr_V, typeof(OpCodeSimdShImm64)); - SetA64("0111111101xxxxxx001101xxxxxxxxxx", InstEmit.Ursra_S, typeof(OpCodeSimdShImm64)); - SetA64("0x10111100>>>xxx001101xxxxxxxxxx", InstEmit.Ursra_V, typeof(OpCodeSimdShImm64)); - SetA64("0110111101xxxxxx001101xxxxxxxxxx", InstEmit.Ursra_V, typeof(OpCodeSimdShImm64)); - SetA64("0>101110<<1xxxxx010001xxxxxxxxxx", InstEmit.Ushl_V, typeof(OpCodeSimdReg64)); - SetA64("0x10111100>>>xxx101001xxxxxxxxxx", InstEmit.Ushll_V, typeof(OpCodeSimdShImm64)); - SetA64("0111111101xxxxxx000001xxxxxxxxxx", InstEmit.Ushr_S, typeof(OpCodeSimdShImm64)); - SetA64("0x10111100>>>xxx000001xxxxxxxxxx", InstEmit.Ushr_V, typeof(OpCodeSimdShImm64)); - SetA64("0110111101xxxxxx000001xxxxxxxxxx", InstEmit.Ushr_V, typeof(OpCodeSimdShImm64)); - SetA64("01111110xx100000001110xxxxxxxxxx", InstEmit.Usqadd_S, typeof(OpCodeSimd64)); - SetA64("0>101110<<100000001110xxxxxxxxxx", InstEmit.Usqadd_V, typeof(OpCodeSimd64)); - SetA64("0111111101xxxxxx000101xxxxxxxxxx", InstEmit.Usra_S, typeof(OpCodeSimdShImm64)); - SetA64("0x10111100>>>xxx000101xxxxxxxxxx", InstEmit.Usra_V, typeof(OpCodeSimdShImm64)); - SetA64("0110111101xxxxxx000101xxxxxxxxxx", InstEmit.Usra_V, typeof(OpCodeSimdShImm64)); - SetA64("0x101110<<1xxxxx001000xxxxxxxxxx", InstEmit.Usubl_V, typeof(OpCodeSimdReg64)); - SetA64("0x101110<<1xxxxx001100xxxxxxxxxx", InstEmit.Usubw_V, typeof(OpCodeSimdReg64)); - SetA64("0>001110<<0xxxxx000110xxxxxxxxxx", InstEmit.Uzp1_V, typeof(OpCodeSimdReg64)); - SetA64("0>001110<<0xxxxx010110xxxxxxxxxx", InstEmit.Uzp2_V, typeof(OpCodeSimdReg64)); - SetA64("0x001110<<100001001010xxxxxxxxxx", InstEmit.Xtn_V, typeof(OpCodeSimd64)); - SetA64("0>001110<<0xxxxx001110xxxxxxxxxx", InstEmit.Zip1_V, typeof(OpCodeSimdReg64)); - SetA64("0>001110<<0xxxxx011110xxxxxxxxxx", InstEmit.Zip2_V, typeof(OpCodeSimdReg64)); -#endregion - - FillFastLookupTable(_instA32FastLookup, _allInstA32); - FillFastLookupTable(_instT32FastLookup, _allInstT32); - FillFastLookupTable(_instA64FastLookup, _allInstA64); - } - - private static void SetA32(string encoding, InstEmitter emitter, Type type) - { - Set(encoding, new Inst(emitter, type), ExecutionMode.Aarch32Arm); - } - - private static void SetT32(string encoding, InstEmitter emitter, Type type) - { - if (encoding.Length == 16) - { - encoding = "xxxxxxxxxxxxxxxx" + encoding; - } - - Set(encoding, new Inst(emitter, type), ExecutionMode.Aarch32Thumb); - } - - private static void SetA64(string encoding, InstEmitter emitter, Type type) - { - Set(encoding, new Inst(emitter, type), ExecutionMode.Aarch64); - } - - private static void Set(string encoding, Inst inst, ExecutionMode mode) - { - int bit = encoding.Length - 1; - int value = 0; - int xMask = 0; - int xBits = 0; - - int[] xPos = new int[encoding.Length]; - - int blacklisted = 0; - - for (int index = 0; index < encoding.Length; index++, bit--) - { - // Note: < and > are used on special encodings. - // The < means that we should never have ALL bits with the '<' set. - // So, when the encoding has <<, it means that 00, 01, and 10 are valid, - // but not 11. <<< is 000, 001, ..., 110 but NOT 111, and so on... - // For >, the invalid value is zero. So, for >> 01, 10 and 11 are valid, - // but 00 isn't. - char chr = encoding[index]; - - if (chr == '1') - { - value |= 1 << bit; - } - else if (chr == 'x') - { - xMask |= 1 << bit; - } - else if (chr == '>') - { - xPos[xBits++] = bit; - } - else if (chr == '<') - { - xPos[xBits++] = bit; - - blacklisted |= 1 << bit; - } - else if (chr != '0') - { - throw new ArgumentException(nameof(encoding)); - } - } - - xMask = ~xMask; - - if (xBits == 0) - { - InsertInst(xMask, value, inst, mode); - - return; - } - - for (int index = 0; index < (1 << xBits); index++) - { - int mask = 0; - - for (int x = 0; x < xBits; x++) - { - mask |= ((index >> x) & 1) << xPos[x]; - } - - if (mask != blacklisted) - { - InsertInst(xMask, value | mask, inst, mode); - } - } - } - - private static void InsertInst(int xMask, int value, Inst inst, ExecutionMode mode) - { - InstInfo info = new InstInfo(xMask, value, inst); - - switch (mode) - { - case ExecutionMode.Aarch32Arm: _allInstA32.Add(info); break; - case ExecutionMode.Aarch32Thumb: _allInstT32.Add(info); break; - case ExecutionMode.Aarch64: _allInstA64.Add(info); break; - } - } - - private static void FillFastLookupTable(InstInfo[][] table, List<InstInfo> allInsts) - { - List<InstInfo>[] tmp = new List<InstInfo>[FastLookupSize]; - - for (int i = 0; i < FastLookupSize; i++) - { - tmp[i] = new List<InstInfo>(); - } - - foreach (InstInfo inst in allInsts) - { - int mask = ToFastLookupIndex(inst.Mask); - int value = ToFastLookupIndex(inst.Value); - - for (int i = 0; i < FastLookupSize; i++) - { - if ((i & mask) == value) - { - tmp[i].Add(inst); - } - } - } - - for (int i = 0; i < FastLookupSize; i++) - { - table[i] = tmp[i].ToArray(); - } - } - - public static Inst GetInstA32(int opCode) - { - return GetInstFromList(_instA32FastLookup[ToFastLookupIndex(opCode)], opCode); - } - - public static Inst GetInstT32(int opCode) - { - return GetInstFromList(_instT32FastLookup[ToFastLookupIndex(opCode)], opCode); - } - - public static Inst GetInstA64(int opCode) - { - return GetInstFromList(_instA64FastLookup[ToFastLookupIndex(opCode)], opCode); - } - - private static int ToFastLookupIndex(int value) - { - return ((value >> 10) & 0x00F) | ((value >> 18) & 0xFF0); - } - - private static Inst GetInstFromList(IEnumerable<InstInfo> instList, int opCode) - { - foreach (InstInfo node in instList) - { - if ((opCode & node.Mask) == node.Value) - { - return node.Inst; - } - } - - return Inst.Undefined; - } - } -} diff --git a/ChocolArm64/Optimizations.cs b/ChocolArm64/Optimizations.cs deleted file mode 100644 index 24828ebf..00000000 --- a/ChocolArm64/Optimizations.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Runtime.Intrinsics.X86; - -namespace ChocolArm64 -{ - public static class Optimizations - { - public static bool AssumeStrictAbiCompliance { get; set; } = true; - - public static bool FastFP { get; set; } = true; - - private const bool UseAllSseIfAvailable = true; - - public static bool UseSseIfAvailable { get; set; } = UseAllSseIfAvailable; - public static bool UseSse2IfAvailable { get; set; } = UseAllSseIfAvailable; - public static bool UseSse3IfAvailable { get; set; } = UseAllSseIfAvailable; - public static bool UseSsse3IfAvailable { get; set; } = UseAllSseIfAvailable; - public static bool UseSse41IfAvailable { get; set; } = UseAllSseIfAvailable; - public static bool UseSse42IfAvailable { get; set; } = UseAllSseIfAvailable; - - internal static bool UseSse => UseSseIfAvailable && Sse.IsSupported; - internal static bool UseSse2 => UseSse2IfAvailable && Sse2.IsSupported; - internal static bool UseSse3 => UseSse3IfAvailable && Sse3.IsSupported; - internal static bool UseSsse3 => UseSsse3IfAvailable && Ssse3.IsSupported; - internal static bool UseSse41 => UseSse41IfAvailable && Sse41.IsSupported; - internal static bool UseSse42 => UseSse42IfAvailable && Sse42.IsSupported; - } -}
\ No newline at end of file diff --git a/ChocolArm64/State/Aarch32Mode.cs b/ChocolArm64/State/Aarch32Mode.cs deleted file mode 100644 index bc4e4b64..00000000 --- a/ChocolArm64/State/Aarch32Mode.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace ChocolArm64.State -{ - enum Aarch32Mode - { - User = 0b10000, - Fiq = 0b10001, - Irq = 0b10010, - Supervisor = 0b10011, - Monitor = 0b10110, - Abort = 0b10111, - Hypervisor = 0b11010, - Undefined = 0b11011, - System = 0b11111 - } -}
\ No newline at end of file diff --git a/ChocolArm64/State/CpuThreadState.cs b/ChocolArm64/State/CpuThreadState.cs deleted file mode 100644 index e4baaefa..00000000 --- a/ChocolArm64/State/CpuThreadState.cs +++ /dev/null @@ -1,354 +0,0 @@ -using ChocolArm64.Translation; -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.Intrinsics; - -using static ChocolArm64.Instructions.VectorHelper; - -namespace ChocolArm64.State -{ - public class CpuThreadState : ARMeilleure.State.IExecutionContext - { - private const int MinCountForCheck = 40000; - - internal const int ErgSizeLog2 = 4; - internal const int DczSizeLog2 = 4; - - public ulong X0, X1, X2, X3, X4, X5, X6, X7, - X8, X9, X10, X11, X12, X13, X14, X15, - X16, X17, X18, X19, X20, X21, X22, X23, - X24, X25, X26, X27, X28, X29, X30, X31; - - public Vector128<float> V0, V1, V2, V3, V4, V5, V6, V7, - V8, V9, V10, V11, V12, V13, V14, V15, - V16, V17, V18, V19, V20, V21, V22, V23, - V24, V25, V26, V27, V28, V29, V30, V31; - - public bool IsAarch32 { get; set; } - - public bool Thumb; - public bool BigEndian; - - public bool Overflow; - public bool Carry; - public bool Zero; - public bool Negative; - - public int ElrHyp; - - public bool Running { get; set; } - - private bool _interrupted; - - private int _syncCount; - - public long TpidrEl0 { get; set; } - public long Tpidr { get; set; } - - public int CFpcr { get; set; } - public int CFpsr { get; set; } - - public ARMeilleure.State.FPCR Fpcr - { - get => (ARMeilleure.State.FPCR)CFpcr; - set => CFpcr = (int)value; - } - - public ARMeilleure.State.FPSR Fpsr - { - get => (ARMeilleure.State.FPSR)CFpsr; - set => CFpsr = (int)value; - } - - public int Psr - { - get - { - return (Negative ? (int)PState.NMask : 0) | - (Zero ? (int)PState.ZMask : 0) | - (Carry ? (int)PState.CMask : 0) | - (Overflow ? (int)PState.VMask : 0); - } - } - - public uint CtrEl0 => 0x8444c004; - public uint DczidEl0 => 0x00000004; - - public ulong CntfrqEl0 { get; set; } - public ulong CntpctEl0 - { - get - { - double ticks = _tickCounter.ElapsedTicks * _hostTickFreq; - - return (ulong)(ticks * CntfrqEl0); - } - } - - public event EventHandler<EventArgs> Interrupt; - public event EventHandler<ARMeilleure.State.InstExceptionEventArgs> Break; - public event EventHandler<ARMeilleure.State.InstExceptionEventArgs> SupervisorCall; - public event EventHandler<ARMeilleure.State.InstUndefinedEventArgs> Undefined; - - private static Stopwatch _tickCounter; - - private static double _hostTickFreq; - - internal Translator CurrentTranslator; - - private ulong _exclusiveAddress; - - internal ulong ExclusiveValueLow { get; set; } - internal ulong ExclusiveValueHigh { get; set; } - - public CpuThreadState() - { - ClearExclusiveAddress(); - - Running = true; - } - - static CpuThreadState() - { - _hostTickFreq = 1.0 / Stopwatch.Frequency; - - _tickCounter = new Stopwatch(); - - _tickCounter.Start(); - } - - internal void SetExclusiveAddress(ulong address) - { - _exclusiveAddress = GetMaskedExclusiveAddress(address); - } - - internal bool CheckExclusiveAddress(ulong address) - { - return GetMaskedExclusiveAddress(address) == _exclusiveAddress; - } - - internal void ClearExclusiveAddress() - { - _exclusiveAddress = ulong.MaxValue; - } - - private ulong GetMaskedExclusiveAddress(ulong address) - { - return address & ~((4UL << ErgSizeLog2) - 1); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal bool Synchronize() - { - // Firing a interrupt frequently is expensive, so we only - // do it after a given number of instructions has executed. - _syncCount++; - - if (_syncCount >= MinCountForCheck) - { - CheckInterrupt(); - } - - return Running; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - private void CheckInterrupt() - { - _syncCount = 0; - - if (_interrupted) - { - _interrupted = false; - - Interrupt?.Invoke(this, EventArgs.Empty); - } - } - - public ulong GetX(int index) - { - switch (index) - { - case 0: return X0; - case 1: return X1; - case 2: return X2; - case 3: return X3; - case 4: return X4; - case 5: return X5; - case 6: return X6; - case 7: return X7; - case 8: return X8; - case 9: return X9; - case 10: return X10; - case 11: return X11; - case 12: return X12; - case 13: return X13; - case 14: return X14; - case 15: return X15; - case 16: return X16; - case 17: return X17; - case 18: return X18; - case 19: return X19; - case 20: return X20; - case 21: return X21; - case 22: return X22; - case 23: return X23; - case 24: return X24; - case 25: return X25; - case 26: return X26; - case 27: return X27; - case 28: return X28; - case 29: return X29; - case 30: return X30; - case 31: return X31; - - default: throw new ArgumentOutOfRangeException(nameof(index)); - } - } - - public void SetX(int index, ulong value) - { - switch (index) - { - case 0: X0 = value; break; - case 1: X1 = value; break; - case 2: X2 = value; break; - case 3: X3 = value; break; - case 4: X4 = value; break; - case 5: X5 = value; break; - case 6: X6 = value; break; - case 7: X7 = value; break; - case 8: X8 = value; break; - case 9: X9 = value; break; - case 10: X10 = value; break; - case 11: X11 = value; break; - case 12: X12 = value; break; - case 13: X13 = value; break; - case 14: X14 = value; break; - case 15: X15 = value; break; - case 16: X16 = value; break; - case 17: X17 = value; break; - case 18: X18 = value; break; - case 19: X19 = value; break; - case 20: X20 = value; break; - case 21: X21 = value; break; - case 22: X22 = value; break; - case 23: X23 = value; break; - case 24: X24 = value; break; - case 25: X25 = value; break; - case 26: X26 = value; break; - case 27: X27 = value; break; - case 28: X28 = value; break; - case 29: X29 = value; break; - case 30: X30 = value; break; - case 31: X31 = value; break; - - default: throw new ArgumentOutOfRangeException(nameof(index)); - } - } - - public ARMeilleure.State.V128 GetV(int index) - { - switch (index) - { - case 0: return new ARMeilleure.State.V128(VectorExtractIntZx(V0, 0, 3), VectorExtractIntZx(V0, 1, 3)); - case 1: return new ARMeilleure.State.V128(VectorExtractIntZx(V1, 0, 3), VectorExtractIntZx(V1, 1, 3)); - case 2: return new ARMeilleure.State.V128(VectorExtractIntZx(V2, 0, 3), VectorExtractIntZx(V2, 1, 3)); - case 3: return new ARMeilleure.State.V128(VectorExtractIntZx(V3, 0, 3), VectorExtractIntZx(V3, 1, 3)); - case 4: return new ARMeilleure.State.V128(VectorExtractIntZx(V4, 0, 3), VectorExtractIntZx(V4, 1, 3)); - case 5: return new ARMeilleure.State.V128(VectorExtractIntZx(V5, 0, 3), VectorExtractIntZx(V5, 1, 3)); - case 6: return new ARMeilleure.State.V128(VectorExtractIntZx(V6, 0, 3), VectorExtractIntZx(V6, 1, 3)); - case 7: return new ARMeilleure.State.V128(VectorExtractIntZx(V7, 0, 3), VectorExtractIntZx(V7, 1, 3)); - case 8: return new ARMeilleure.State.V128(VectorExtractIntZx(V8, 0, 3), VectorExtractIntZx(V8, 1, 3)); - case 9: return new ARMeilleure.State.V128(VectorExtractIntZx(V9, 0, 3), VectorExtractIntZx(V9, 1, 3)); - case 10: return new ARMeilleure.State.V128(VectorExtractIntZx(V10, 0, 3), VectorExtractIntZx(V10, 1, 3)); - case 11: return new ARMeilleure.State.V128(VectorExtractIntZx(V11, 0, 3), VectorExtractIntZx(V11, 1, 3)); - case 12: return new ARMeilleure.State.V128(VectorExtractIntZx(V12, 0, 3), VectorExtractIntZx(V12, 1, 3)); - case 13: return new ARMeilleure.State.V128(VectorExtractIntZx(V13, 0, 3), VectorExtractIntZx(V13, 1, 3)); - case 14: return new ARMeilleure.State.V128(VectorExtractIntZx(V14, 0, 3), VectorExtractIntZx(V14, 1, 3)); - case 15: return new ARMeilleure.State.V128(VectorExtractIntZx(V15, 0, 3), VectorExtractIntZx(V15, 1, 3)); - case 16: return new ARMeilleure.State.V128(VectorExtractIntZx(V16, 0, 3), VectorExtractIntZx(V16, 1, 3)); - case 17: return new ARMeilleure.State.V128(VectorExtractIntZx(V17, 0, 3), VectorExtractIntZx(V17, 1, 3)); - case 18: return new ARMeilleure.State.V128(VectorExtractIntZx(V18, 0, 3), VectorExtractIntZx(V18, 1, 3)); - case 19: return new ARMeilleure.State.V128(VectorExtractIntZx(V19, 0, 3), VectorExtractIntZx(V19, 1, 3)); - case 20: return new ARMeilleure.State.V128(VectorExtractIntZx(V20, 0, 3), VectorExtractIntZx(V20, 1, 3)); - case 21: return new ARMeilleure.State.V128(VectorExtractIntZx(V21, 0, 3), VectorExtractIntZx(V21, 1, 3)); - case 22: return new ARMeilleure.State.V128(VectorExtractIntZx(V22, 0, 3), VectorExtractIntZx(V22, 1, 3)); - case 23: return new ARMeilleure.State.V128(VectorExtractIntZx(V23, 0, 3), VectorExtractIntZx(V23, 1, 3)); - case 24: return new ARMeilleure.State.V128(VectorExtractIntZx(V24, 0, 3), VectorExtractIntZx(V24, 1, 3)); - case 25: return new ARMeilleure.State.V128(VectorExtractIntZx(V25, 0, 3), VectorExtractIntZx(V25, 1, 3)); - case 26: return new ARMeilleure.State.V128(VectorExtractIntZx(V26, 0, 3), VectorExtractIntZx(V26, 1, 3)); - case 27: return new ARMeilleure.State.V128(VectorExtractIntZx(V27, 0, 3), VectorExtractIntZx(V27, 1, 3)); - case 28: return new ARMeilleure.State.V128(VectorExtractIntZx(V28, 0, 3), VectorExtractIntZx(V28, 1, 3)); - case 29: return new ARMeilleure.State.V128(VectorExtractIntZx(V29, 0, 3), VectorExtractIntZx(V29, 1, 3)); - case 30: return new ARMeilleure.State.V128(VectorExtractIntZx(V30, 0, 3), VectorExtractIntZx(V30, 1, 3)); - case 31: return new ARMeilleure.State.V128(VectorExtractIntZx(V31, 0, 3), VectorExtractIntZx(V31, 1, 3)); - - default: throw new ArgumentOutOfRangeException(nameof(index)); - } - } - - public bool GetPstateFlag(ARMeilleure.State.PState flag) - { - switch (flag) - { - case ARMeilleure.State.PState.NFlag: return Negative; - case ARMeilleure.State.PState.ZFlag: return Zero; - case ARMeilleure.State.PState.CFlag: return Carry; - case ARMeilleure.State.PState.VFlag: return Overflow; - - default: throw new ArgumentOutOfRangeException(nameof(flag)); - } - } - - public void RequestInterrupt() - { - _interrupted = true; - } - - internal void OnBreak(long position, int imm) - { - Break?.Invoke(this, new ARMeilleure.State.InstExceptionEventArgs((ulong)position, imm)); - } - - internal void OnSvcCall(long position, int imm) - { - SupervisorCall?.Invoke(this, new ARMeilleure.State.InstExceptionEventArgs((ulong)position, imm)); - } - - internal void OnUndefined(long position, int rawOpCode) - { - Undefined?.Invoke(this, new ARMeilleure.State.InstUndefinedEventArgs((ulong)position, rawOpCode)); - } - - internal ExecutionMode GetExecutionMode() - { - if (!IsAarch32) - { - return ExecutionMode.Aarch64; - } - else - { - return Thumb ? ExecutionMode.Aarch32Thumb : ExecutionMode.Aarch32Arm; - } - } - - internal bool GetFpcrFlag(Fpcr flag) - { - return (CFpcr & (1 << (int)flag)) != 0; - } - - internal void SetFpsrFlag(Fpsr flag) - { - CFpsr |= 1 << (int)flag; - } - - internal RoundMode FPRoundingMode() - { - return (RoundMode)((CFpcr >> (int)State.Fpcr.RMode) & 3); - } - - public void Dispose() { } - } -} diff --git a/ChocolArm64/State/ExecutionMode.cs b/ChocolArm64/State/ExecutionMode.cs deleted file mode 100644 index b735fd5f..00000000 --- a/ChocolArm64/State/ExecutionMode.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ChocolArm64.State -{ - enum ExecutionMode - { - Aarch64, - Aarch32Arm, - Aarch32Thumb - } -}
\ No newline at end of file diff --git a/ChocolArm64/State/FpExc.cs b/ChocolArm64/State/FpExc.cs deleted file mode 100644 index 5cb7a402..00000000 --- a/ChocolArm64/State/FpExc.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace ChocolArm64.State -{ - enum FpExc - { - InvalidOp = 0, - DivideByZero = 1, - Overflow = 2, - Underflow = 3, - Inexact = 4, - InputDenorm = 7 - } -} diff --git a/ChocolArm64/State/FpType.cs b/ChocolArm64/State/FpType.cs deleted file mode 100644 index fc279106..00000000 --- a/ChocolArm64/State/FpType.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace ChocolArm64.State -{ - enum FpType - { - Nonzero, - Zero, - Infinity, - QNaN, - SNaN - } -} diff --git a/ChocolArm64/State/Fpcr.cs b/ChocolArm64/State/Fpcr.cs deleted file mode 100644 index 908faee5..00000000 --- a/ChocolArm64/State/Fpcr.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace ChocolArm64.State -{ - enum Fpcr - { - Ufe = 11, - RMode = 22, - Fz = 24, - Dn = 25, - Ahp = 26 - } -} diff --git a/ChocolArm64/State/Fpsr.cs b/ChocolArm64/State/Fpsr.cs deleted file mode 100644 index ba551eef..00000000 --- a/ChocolArm64/State/Fpsr.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace ChocolArm64.State -{ - enum Fpsr - { - Ufc = 3, - Qc = 27 - } -} diff --git a/ChocolArm64/State/PState.cs b/ChocolArm64/State/PState.cs deleted file mode 100644 index 053a5357..00000000 --- a/ChocolArm64/State/PState.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace ChocolArm64.State -{ - [Flags] - enum PState - { - TBit = 5, - EBit = 9, - - VBit = 28, - CBit = 29, - ZBit = 30, - NBit = 31, - - TMask = 1 << TBit, - EMask = 1 << EBit, - - VMask = 1 << VBit, - CMask = 1 << CBit, - ZMask = 1 << ZBit, - NMask = 1 << NBit - } -} diff --git a/ChocolArm64/State/Register.cs b/ChocolArm64/State/Register.cs deleted file mode 100644 index a7a2ead0..00000000 --- a/ChocolArm64/State/Register.cs +++ /dev/null @@ -1,148 +0,0 @@ -using System; -using System.Reflection; - -namespace ChocolArm64.State -{ - struct Register : IEquatable<Register> - { - public int Index; - - public RegisterType Type; - - public Register(int index, RegisterType type) - { - Index = index; - Type = type; - } - - public override int GetHashCode() - { - return (ushort)Index | ((ushort)Type << 16); - } - - public override bool Equals(object obj) - { - return obj is Register reg && Equals(reg); - } - - public bool Equals(Register other) - { - return Index == other.Index && Type == other.Type; - } - - public FieldInfo GetField() - { - switch (Type) - { - case RegisterType.Flag: return GetFieldFlag(); - case RegisterType.Int: return GetFieldInt(); - case RegisterType.Vector: return GetFieldVector(); - } - - throw new InvalidOperationException(); - } - - private FieldInfo GetFieldFlag() - { - switch ((PState)Index) - { - case PState.TBit: return GetField(nameof(CpuThreadState.Thumb)); - case PState.EBit: return GetField(nameof(CpuThreadState.BigEndian)); - - case PState.VBit: return GetField(nameof(CpuThreadState.Overflow)); - case PState.CBit: return GetField(nameof(CpuThreadState.Carry)); - case PState.ZBit: return GetField(nameof(CpuThreadState.Zero)); - case PState.NBit: return GetField(nameof(CpuThreadState.Negative)); - } - - throw new InvalidOperationException(); - } - - private FieldInfo GetFieldInt() - { - switch (Index) - { - case 0: return GetField(nameof(CpuThreadState.X0)); - case 1: return GetField(nameof(CpuThreadState.X1)); - case 2: return GetField(nameof(CpuThreadState.X2)); - case 3: return GetField(nameof(CpuThreadState.X3)); - case 4: return GetField(nameof(CpuThreadState.X4)); - case 5: return GetField(nameof(CpuThreadState.X5)); - case 6: return GetField(nameof(CpuThreadState.X6)); - case 7: return GetField(nameof(CpuThreadState.X7)); - case 8: return GetField(nameof(CpuThreadState.X8)); - case 9: return GetField(nameof(CpuThreadState.X9)); - case 10: return GetField(nameof(CpuThreadState.X10)); - case 11: return GetField(nameof(CpuThreadState.X11)); - case 12: return GetField(nameof(CpuThreadState.X12)); - case 13: return GetField(nameof(CpuThreadState.X13)); - case 14: return GetField(nameof(CpuThreadState.X14)); - case 15: return GetField(nameof(CpuThreadState.X15)); - case 16: return GetField(nameof(CpuThreadState.X16)); - case 17: return GetField(nameof(CpuThreadState.X17)); - case 18: return GetField(nameof(CpuThreadState.X18)); - case 19: return GetField(nameof(CpuThreadState.X19)); - case 20: return GetField(nameof(CpuThreadState.X20)); - case 21: return GetField(nameof(CpuThreadState.X21)); - case 22: return GetField(nameof(CpuThreadState.X22)); - case 23: return GetField(nameof(CpuThreadState.X23)); - case 24: return GetField(nameof(CpuThreadState.X24)); - case 25: return GetField(nameof(CpuThreadState.X25)); - case 26: return GetField(nameof(CpuThreadState.X26)); - case 27: return GetField(nameof(CpuThreadState.X27)); - case 28: return GetField(nameof(CpuThreadState.X28)); - case 29: return GetField(nameof(CpuThreadState.X29)); - case 30: return GetField(nameof(CpuThreadState.X30)); - case 31: return GetField(nameof(CpuThreadState.X31)); - } - - throw new InvalidOperationException(); - } - - private FieldInfo GetFieldVector() - { - switch (Index) - { - case 0: return GetField(nameof(CpuThreadState.V0)); - case 1: return GetField(nameof(CpuThreadState.V1)); - case 2: return GetField(nameof(CpuThreadState.V2)); - case 3: return GetField(nameof(CpuThreadState.V3)); - case 4: return GetField(nameof(CpuThreadState.V4)); - case 5: return GetField(nameof(CpuThreadState.V5)); - case 6: return GetField(nameof(CpuThreadState.V6)); - case 7: return GetField(nameof(CpuThreadState.V7)); - case 8: return GetField(nameof(CpuThreadState.V8)); - case 9: return GetField(nameof(CpuThreadState.V9)); - case 10: return GetField(nameof(CpuThreadState.V10)); - case 11: return GetField(nameof(CpuThreadState.V11)); - case 12: return GetField(nameof(CpuThreadState.V12)); - case 13: return GetField(nameof(CpuThreadState.V13)); - case 14: return GetField(nameof(CpuThreadState.V14)); - case 15: return GetField(nameof(CpuThreadState.V15)); - case 16: return GetField(nameof(CpuThreadState.V16)); - case 17: return GetField(nameof(CpuThreadState.V17)); - case 18: return GetField(nameof(CpuThreadState.V18)); - case 19: return GetField(nameof(CpuThreadState.V19)); - case 20: return GetField(nameof(CpuThreadState.V20)); - case 21: return GetField(nameof(CpuThreadState.V21)); - case 22: return GetField(nameof(CpuThreadState.V22)); - case 23: return GetField(nameof(CpuThreadState.V23)); - case 24: return GetField(nameof(CpuThreadState.V24)); - case 25: return GetField(nameof(CpuThreadState.V25)); - case 26: return GetField(nameof(CpuThreadState.V26)); - case 27: return GetField(nameof(CpuThreadState.V27)); - case 28: return GetField(nameof(CpuThreadState.V28)); - case 29: return GetField(nameof(CpuThreadState.V29)); - case 30: return GetField(nameof(CpuThreadState.V30)); - case 31: return GetField(nameof(CpuThreadState.V31)); - } - - throw new InvalidOperationException(); - } - - private FieldInfo GetField(string name) - { - return typeof(CpuThreadState).GetField(name); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/State/RegisterAlias.cs b/ChocolArm64/State/RegisterAlias.cs deleted file mode 100644 index 8c2b95d7..00000000 --- a/ChocolArm64/State/RegisterAlias.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace ChocolArm64.State -{ - static class RegisterAlias - { - public const int R8Usr = 8; - public const int R9Usr = 9; - public const int R10Usr = 10; - public const int R11Usr = 11; - public const int R12Usr = 12; - public const int SpUsr = 13; - public const int LrUsr = 14; - - public const int SpHyp = 15; - - public const int LrIrq = 16; - public const int SpIrq = 17; - - public const int LrSvc = 18; - public const int SpSvc = 19; - - public const int LrAbt = 20; - public const int SpAbt = 21; - - public const int LrUnd = 22; - public const int SpUnd = 23; - - public const int R8Fiq = 24; - public const int R9Fiq = 25; - public const int R10Fiq = 26; - public const int R11Fiq = 27; - public const int R12Fiq = 28; - public const int SpFiq = 29; - public const int LrFiq = 30; - - public const int Aarch32Lr = 14; - public const int Aarch32Pc = 15; - - public const int Lr = 30; - public const int Zr = 31; - } -}
\ No newline at end of file diff --git a/ChocolArm64/State/RegisterConsts.cs b/ChocolArm64/State/RegisterConsts.cs deleted file mode 100644 index 8c34789c..00000000 --- a/ChocolArm64/State/RegisterConsts.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace ChocolArm64.State -{ - static class RegisterConsts - { - public const int RegsCount = 32; - public const int RegsMask = RegsCount - 1; - } -}
\ No newline at end of file diff --git a/ChocolArm64/State/RegisterSize.cs b/ChocolArm64/State/RegisterSize.cs deleted file mode 100644 index 7cc99599..00000000 --- a/ChocolArm64/State/RegisterSize.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ChocolArm64.State -{ - enum RegisterSize - { - Int32, - Int64, - Simd64, - Simd128 - } -}
\ No newline at end of file diff --git a/ChocolArm64/State/RegisterType.cs b/ChocolArm64/State/RegisterType.cs deleted file mode 100644 index 4476d044..00000000 --- a/ChocolArm64/State/RegisterType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ChocolArm64.State -{ - enum RegisterType - { - Flag, - Int, - Vector - } -}
\ No newline at end of file diff --git a/ChocolArm64/State/RoundMode.cs b/ChocolArm64/State/RoundMode.cs deleted file mode 100644 index b687cc8e..00000000 --- a/ChocolArm64/State/RoundMode.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ChocolArm64.State -{ - enum RoundMode - { - ToNearest = 0, - TowardsPlusInfinity = 1, - TowardsMinusInfinity = 2, - TowardsZero = 3 - } -} diff --git a/ChocolArm64/Translation/CallType.cs b/ChocolArm64/Translation/CallType.cs deleted file mode 100644 index 937ede76..00000000 --- a/ChocolArm64/Translation/CallType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ChocolArm64.Translation -{ - enum CallType - { - Call, - VirtualCall, - VirtualJump - } -}
\ No newline at end of file diff --git a/ChocolArm64/Translation/ILEmitterCtx.cs b/ChocolArm64/Translation/ILEmitterCtx.cs deleted file mode 100644 index 0deb29b2..00000000 --- a/ChocolArm64/Translation/ILEmitterCtx.cs +++ /dev/null @@ -1,709 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.Instructions; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.Memory; -using ChocolArm64.State; -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; - -namespace ChocolArm64.Translation -{ - class ILEmitterCtx - { - public MemoryManager Memory { get; } - - private TranslatorCache _cache; - private TranslatorQueue _queue; - - private Block _currBlock; - - public Block CurrBlock - { - get - { - return _currBlock; - } - set - { - _currBlock = value; - - ResetBlockState(); - } - } - - public OpCode64 CurrOp { get; set; } - - public TranslationTier Tier { get; } - - public Aarch32Mode Mode { get; } = Aarch32Mode.User; //TODO - - public bool HasIndirectJump { get; set; } - - public bool HasSlowCall { get; set; } - - private Dictionary<long, ILLabel> _labels; - - private Dictionary<ILLabel, BasicBlock> _irLabels; - - private List<BasicBlock> _irBlocks; - - private BasicBlock _irBlock; - - private bool _needsNewBlock; - - private OpCode64 _optOpLastCompare; - private OpCode64 _optOpLastFlagSet; - - // This is the index of the temporary register, used to store temporary - // values needed by some functions, since IL doesn't have a swap instruction. - // You can use any value here as long it doesn't conflict with the indices - // for the other registers. Any value >= 64 or < 0 will do. - private const int ReservedLocalsCount = 64; - - private const int RorTmpIndex = ReservedLocalsCount + 0; - private const int CmpOptTmp1Index = ReservedLocalsCount + 1; - private const int CmpOptTmp2Index = ReservedLocalsCount + 2; - private const int IntGpTmp1Index = ReservedLocalsCount + 3; - private const int IntGpTmp2Index = ReservedLocalsCount + 4; - private const int UserIntTempStart = ReservedLocalsCount + 5; - - // Vectors are part of another "set" of locals. - private const int VecGpTmp1Index = ReservedLocalsCount + 0; - private const int VecGpTmp2Index = ReservedLocalsCount + 1; - private const int VecGpTmp3Index = ReservedLocalsCount + 2; - private const int UserVecTempStart = ReservedLocalsCount + 3; - - private static int _userIntTempCount; - private static int _userVecTempCount; - - public ILEmitterCtx( - MemoryManager memory, - TranslatorCache cache, - TranslatorQueue queue, - TranslationTier tier) - { - Memory = memory ?? throw new ArgumentNullException(nameof(memory)); - _cache = cache ?? throw new ArgumentNullException(nameof(cache)); - _queue = queue ?? throw new ArgumentNullException(nameof(queue)); - - Tier = tier; - - _labels = new Dictionary<long, ILLabel>(); - - _irLabels = new Dictionary<ILLabel, BasicBlock>(); - - _irBlocks = new List<BasicBlock>(); - - NewNextBlock(); - - EmitSynchronization(); - - EmitLoadContext(); - } - - public static int GetIntTempIndex() - { - return UserIntTempStart + _userIntTempCount++; - } - - public static int GetVecTempIndex() - { - return UserVecTempStart + _userVecTempCount++; - } - - public BasicBlock[] GetBlocks() - { - return _irBlocks.ToArray(); - } - - public void EmitSynchronization() - { - EmitLdarg(TranslatedSub.StateArgIdx); - - EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.Synchronize)); - - EmitLdc_I4(0); - - ILLabel lblContinue = new ILLabel(); - - Emit(OpCodes.Bne_Un_S, lblContinue); - - EmitLdc_I8(0); - - Emit(OpCodes.Ret); - - MarkLabel(lblContinue); - } - - public void ResetBlockStateForPredicatedOp() - { - // Check if this is a predicated instruction that modifies flags, - // in this case the value of the flags is unknown as we don't know - // in advance if the instruction is going to be executed or not. - // So, we reset the block state to prevent an invalid optimization. - if (CurrOp == _optOpLastFlagSet) - { - ResetBlockState(); - } - } - - private void ResetBlockState() - { - _optOpLastFlagSet = null; - _optOpLastCompare = null; - } - - public void TranslateAhead(long position, ExecutionMode mode = ExecutionMode.Aarch64) - { - if (_cache.TryGetSubroutine(position, out TranslatedSub sub) && sub.Tier != TranslationTier.Tier0) - { - return; - } - - _queue.Enqueue(position, mode, TranslationTier.Tier1, isComplete: true); - } - - public bool TryOptEmitSubroutineCall() - { - // Calls should always have a next block, unless - // we're translating a single basic block. - if (_currBlock.Next == null) - { - return false; - } - - if (!(CurrOp is IOpCodeBImm op)) - { - return false; - } - - if (!_cache.TryGetSubroutine(op.Imm, out TranslatedSub sub) || sub.Tier != TranslationTier.Tier0) - { - return false; - } - - EmitStoreContext(); - - for (int index = 0; index < TranslatedSub.FixedArgTypes.Length; index++) - { - EmitLdarg(index); - } - - EmitCall(sub.Method); - - return true; - } - - public void TryOptMarkCondWithoutCmp() - { - _optOpLastCompare = CurrOp; - - InstEmitAluHelper.EmitAluLoadOpers(this); - - Stloc(CmpOptTmp2Index, RegisterType.Int); - Stloc(CmpOptTmp1Index, RegisterType.Int); - } - - private Dictionary<Condition, OpCode> _branchOps = new Dictionary<Condition, OpCode>() - { - { Condition.Eq, OpCodes.Beq }, - { Condition.Ne, OpCodes.Bne_Un }, - { Condition.GeUn, OpCodes.Bge_Un }, - { Condition.LtUn, OpCodes.Blt_Un }, - { Condition.GtUn, OpCodes.Bgt_Un }, - { Condition.LeUn, OpCodes.Ble_Un }, - { Condition.Ge, OpCodes.Bge }, - { Condition.Lt, OpCodes.Blt }, - { Condition.Gt, OpCodes.Bgt }, - { Condition.Le, OpCodes.Ble } - }; - - public void EmitCondBranch(ILLabel target, Condition cond) - { - if (_optOpLastCompare != null && - _optOpLastCompare == _optOpLastFlagSet && _branchOps.ContainsKey(cond)) - { - if (_optOpLastCompare.Emitter == InstEmit.Subs) - { - Ldloc(CmpOptTmp1Index, RegisterType.Int, _optOpLastCompare.RegisterSize); - Ldloc(CmpOptTmp2Index, RegisterType.Int, _optOpLastCompare.RegisterSize); - - Emit(_branchOps[cond], target); - - return; - } - else if (_optOpLastCompare.Emitter == InstEmit.Adds && cond != Condition.GeUn - && cond != Condition.LtUn - && cond != Condition.GtUn - && cond != Condition.LeUn) - { - // There are several limitations that needs to be taken into account for CMN comparisons: - // - The unsigned comparisons are not valid, as they depend on the - // carry flag value, and they will have different values for addition and - // subtraction. For addition, it's carry, and for subtraction, it's borrow. - // So, we need to make sure we're not doing a unsigned compare for the CMN case. - // - We can only do the optimization for the immediate variants, - // because when the second operand value is exactly INT_MIN, we can't - // negate the value as theres no positive counterpart. - // Such invalid values can't be encoded on the immediate encodings. - if (_optOpLastCompare is IOpCodeAluImm64 op) - { - Ldloc(CmpOptTmp1Index, RegisterType.Int, _optOpLastCompare.RegisterSize); - - if (_optOpLastCompare.RegisterSize == RegisterSize.Int32) - { - EmitLdc_I4((int)-op.Imm); - } - else - { - EmitLdc_I8(-op.Imm); - } - - Emit(_branchOps[cond], target); - - return; - } - } - } - - OpCode ilOp; - - int intCond = (int)cond; - - if (intCond < 14) - { - int condTrue = intCond >> 1; - - switch (condTrue) - { - case 0: EmitLdflg((int)PState.ZBit); break; - case 1: EmitLdflg((int)PState.CBit); break; - case 2: EmitLdflg((int)PState.NBit); break; - case 3: EmitLdflg((int)PState.VBit); break; - - case 4: - EmitLdflg((int)PState.CBit); - EmitLdflg((int)PState.ZBit); - - Emit(OpCodes.Not); - Emit(OpCodes.And); - break; - - case 5: - case 6: - EmitLdflg((int)PState.NBit); - EmitLdflg((int)PState.VBit); - - Emit(OpCodes.Ceq); - - if (condTrue == 6) - { - EmitLdflg((int)PState.ZBit); - - Emit(OpCodes.Not); - Emit(OpCodes.And); - } - break; - } - - ilOp = (intCond & 1) != 0 ? OpCodes.Brfalse : OpCodes.Brtrue; - } - else - { - ilOp = OpCodes.Br; - } - - Emit(ilOp, target); - } - - public void EmitCast(IntType intType) - { - switch (intType) - { - case IntType.UInt8: Emit(OpCodes.Conv_U1); break; - case IntType.UInt16: Emit(OpCodes.Conv_U2); break; - case IntType.UInt32: Emit(OpCodes.Conv_U4); break; - case IntType.UInt64: Emit(OpCodes.Conv_U8); break; - case IntType.Int8: Emit(OpCodes.Conv_I1); break; - case IntType.Int16: Emit(OpCodes.Conv_I2); break; - case IntType.Int32: Emit(OpCodes.Conv_I4); break; - case IntType.Int64: Emit(OpCodes.Conv_I8); break; - } - - bool sz64 = CurrOp.RegisterSize != RegisterSize.Int32; - - if (sz64 == (intType == IntType.UInt64 || intType == IntType.Int64)) - { - return; - } - - if (sz64) - { - Emit(intType >= IntType.Int8 ? OpCodes.Conv_I8 : OpCodes.Conv_U8); - } - else - { - Emit(OpCodes.Conv_U4); - } - } - - public void EmitLsl(int amount) => EmitILShift(amount, OpCodes.Shl); - public void EmitLsr(int amount) => EmitILShift(amount, OpCodes.Shr_Un); - public void EmitAsr(int amount) => EmitILShift(amount, OpCodes.Shr); - - private void EmitILShift(int amount, OpCode ilOp) - { - if (amount > 0) - { - EmitLdc_I4(amount); - - Emit(ilOp); - } - } - - public void EmitRor(int amount) - { - if (amount > 0) - { - Stloc(RorTmpIndex, RegisterType.Int); - Ldloc(RorTmpIndex, RegisterType.Int); - - EmitLdc_I4(amount); - - Emit(OpCodes.Shr_Un); - - Ldloc(RorTmpIndex, RegisterType.Int); - - EmitLdc_I4(CurrOp.GetBitsCount() - amount); - - Emit(OpCodes.Shl); - Emit(OpCodes.Or); - } - } - - public ILLabel GetLabel(long position) - { - if (!_labels.TryGetValue(position, out ILLabel output)) - { - output = new ILLabel(); - - _labels.Add(position, output); - } - - return output; - } - - public void MarkLabel(ILLabel label) - { - if (_irLabels.TryGetValue(label, out BasicBlock nextBlock)) - { - nextBlock.Index = _irBlocks.Count; - - _irBlocks.Add(nextBlock); - - NextBlock(nextBlock); - } - else - { - NewNextBlock(); - - _irLabels.Add(label, _irBlock); - } - - AddOperation(Operation.MarkLabel(label)); - } - - public void Emit(OpCode ilOp) - { - AddOperation(Operation.IL(ilOp)); - - if (ilOp == OpCodes.Ret) - { - NextBlock(null); - - _needsNewBlock = true; - } - } - - public void Emit(OpCode ilOp, ILLabel label) - { - AddOperation(Operation.ILBranch(ilOp, label)); - - _needsNewBlock = true; - - if (!_irLabels.TryGetValue(label, out BasicBlock branchBlock)) - { - branchBlock = new BasicBlock(); - - _irLabels.Add(label, branchBlock); - } - - _irBlock.Branch = branchBlock; - } - - public void EmitLdfld(FieldInfo info) - { - AddOperation(Operation.LoadField(info)); - } - - public void EmitLdarg(int index) - { - AddOperation(Operation.LoadArgument(index)); - } - - public void EmitLdintzr(int index) - { - if (index != RegisterAlias.Zr) - { - EmitLdint(index); - } - else - { - EmitLdc_I(0); - } - } - - public void EmitStintzr(int index) - { - if (index != RegisterAlias.Zr) - { - EmitStint(index); - } - else - { - Emit(OpCodes.Pop); - } - } - - public void EmitLoadContext() - { - _needsNewBlock = true; - - AddOperation(Operation.LoadContext()); - } - - public void EmitStoreContext() - { - AddOperation(Operation.StoreContext()); - } - - public void EmitLdtmp() => EmitLdint(IntGpTmp1Index); - public void EmitSttmp() => EmitStint(IntGpTmp1Index); - - public void EmitLdtmp2() => EmitLdint(IntGpTmp2Index); - public void EmitSttmp2() => EmitStint(IntGpTmp2Index); - - public void EmitLdvectmp() => EmitLdvec(VecGpTmp1Index); - public void EmitStvectmp() => EmitStvec(VecGpTmp1Index); - - public void EmitLdvectmp2() => EmitLdvec(VecGpTmp2Index); - public void EmitStvectmp2() => EmitStvec(VecGpTmp2Index); - - public void EmitLdvectmp3() => EmitLdvec(VecGpTmp3Index); - public void EmitStvectmp3() => EmitStvec(VecGpTmp3Index); - - public void EmitLdint(int index) => Ldloc(index, RegisterType.Int); - public void EmitStint(int index) => Stloc(index, RegisterType.Int); - - public void EmitLdvec(int index) => Ldloc(index, RegisterType.Vector); - public void EmitStvec(int index) => Stloc(index, RegisterType.Vector); - - public void EmitLdflg(int index) => Ldloc(index, RegisterType.Flag); - public void EmitStflg(int index) - { - // Set this only if any of the NZCV flag bits were modified. - // This is used to ensure that when emiting a direct IL branch - // instruction for compare + branch sequences, we're not expecting - // to use comparison values from an old instruction, when in fact - // the flags were already overwritten by another instruction further along. - if (index >= (int)PState.VBit) - { - _optOpLastFlagSet = CurrOp; - } - - Stloc(index, RegisterType.Flag); - } - - private void Ldloc(int index, RegisterType type) - { - AddOperation(Operation.LoadLocal(index, type, CurrOp.RegisterSize)); - } - - private void Ldloc(int index, RegisterType type, RegisterSize size) - { - AddOperation(Operation.LoadLocal(index, type, size)); - } - - private void Stloc(int index, RegisterType type) - { - AddOperation(Operation.StoreLocal(index, type, CurrOp.RegisterSize)); - } - - public void EmitCallPropGet(Type objType, string propName) - { - EmitCall(objType, $"get_{propName}"); - } - - public void EmitCallPropSet(Type objType, string propName) - { - EmitCall(objType, $"set_{propName}"); - } - - public void EmitCall(Type objType, string mthdName) - { - if (objType == null) - { - throw new ArgumentNullException(nameof(objType)); - } - - if (mthdName == null) - { - throw new ArgumentNullException(nameof(mthdName)); - } - - EmitCall(objType.GetMethod(mthdName)); - } - - public void EmitCallPrivatePropGet(Type objType, string propName) - { - EmitPrivateCall(objType, $"get_{propName}"); - } - - public void EmitCallPrivatePropSet(Type objType, string propName) - { - EmitPrivateCall(objType, $"set_{propName}"); - } - - public void EmitPrivateCall(Type objType, string mthdName) - { - if (objType == null) - { - throw new ArgumentNullException(nameof(objType)); - } - - if (mthdName == null) - { - throw new ArgumentNullException(nameof(mthdName)); - } - - EmitCall(objType.GetMethod(mthdName, BindingFlags.Instance | BindingFlags.NonPublic)); - } - - public void EmitCall(MethodInfo mthdInfo, bool isVirtual = false) - { - if (mthdInfo == null) - { - throw new ArgumentNullException(nameof(mthdInfo)); - } - - if (isVirtual) - { - AddOperation(Operation.CallVirtual(mthdInfo)); - } - else - { - AddOperation(Operation.Call(mthdInfo)); - } - } - - public void EmitLdc_I(long value) - { - if (CurrOp.RegisterSize == RegisterSize.Int32) - { - EmitLdc_I4((int)value); - } - else - { - EmitLdc_I8(value); - } - } - - public void EmitLdc_I4(int value) - { - AddOperation(Operation.LoadConstant(value)); - } - - public void EmitLdc_I8(long value) - { - AddOperation(Operation.LoadConstant(value)); - } - - public void EmitLdc_R4(float value) - { - AddOperation(Operation.LoadConstant(value)); - } - - public void EmitLdc_R8(double value) - { - AddOperation(Operation.LoadConstant(value)); - } - - public void EmitZnFlagCheck() - { - EmitZnCheck(OpCodes.Ceq, (int)PState.ZBit); - EmitZnCheck(OpCodes.Clt, (int)PState.NBit); - } - - private void EmitZnCheck(OpCode ilCmpOp, int flag) - { - Emit(OpCodes.Dup); - Emit(OpCodes.Ldc_I4_0); - - if (CurrOp.RegisterSize != RegisterSize.Int32) - { - Emit(OpCodes.Conv_I8); - } - - Emit(ilCmpOp); - - EmitStflg(flag); - } - - private void AddOperation(Operation operation) - { - if (_needsNewBlock) - { - NewNextBlock(); - } - - _irBlock.Add(operation); - } - - private void NewNextBlock() - { - BasicBlock block = new BasicBlock(_irBlocks.Count); - - _irBlocks.Add(block); - - NextBlock(block); - } - - private void NextBlock(BasicBlock nextBlock) - { - if (_irBlock != null && !EndsWithUnconditional(_irBlock)) - { - _irBlock.Next = nextBlock; - } - - _irBlock = nextBlock; - - _needsNewBlock = false; - } - - private static bool EndsWithUnconditional(BasicBlock block) - { - Operation lastOp = block.GetLastOp(); - - if (lastOp == null || lastOp.Type != OperationType.ILBranch) - { - return false; - } - - OpCode opCode = lastOp.GetArg<OpCode>(0); - - return opCode == OpCodes.Br || opCode == OpCodes.Br_S; - } - } -} diff --git a/ChocolArm64/Translation/ILGeneratorEx.cs b/ChocolArm64/Translation/ILGeneratorEx.cs deleted file mode 100644 index 6b1512d2..00000000 --- a/ChocolArm64/Translation/ILGeneratorEx.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; - -namespace ChocolArm64 -{ - using System.Reflection.Emit; - - static class ILGeneratorEx - { - public static void EmitLdc_I4(this ILGenerator generator, int value) - { - switch (value) - { - case 0: generator.Emit(OpCodes.Ldc_I4_0); break; - case 1: generator.Emit(OpCodes.Ldc_I4_1); break; - case 2: generator.Emit(OpCodes.Ldc_I4_2); break; - case 3: generator.Emit(OpCodes.Ldc_I4_3); break; - case 4: generator.Emit(OpCodes.Ldc_I4_4); break; - case 5: generator.Emit(OpCodes.Ldc_I4_5); break; - case 6: generator.Emit(OpCodes.Ldc_I4_6); break; - case 7: generator.Emit(OpCodes.Ldc_I4_7); break; - case 8: generator.Emit(OpCodes.Ldc_I4_8); break; - case -1: generator.Emit(OpCodes.Ldc_I4_M1); break; - default: generator.Emit(OpCodes.Ldc_I4, value); break; - } - } - - public static void EmitLdarg(this ILGenerator generator, int index) - { - switch (index) - { - case 0: generator.Emit(OpCodes.Ldarg_0); break; - case 1: generator.Emit(OpCodes.Ldarg_1); break; - case 2: generator.Emit(OpCodes.Ldarg_2); break; - case 3: generator.Emit(OpCodes.Ldarg_3); break; - - default: - if ((uint)index <= byte.MaxValue) - { - generator.Emit(OpCodes.Ldarg_S, (byte)index); - } - else if ((uint)index < ushort.MaxValue) - { - generator.Emit(OpCodes.Ldarg, (short)index); - } - else - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - break; - } - } - - public static void EmitStarg(this ILGenerator generator, int index) - { - if ((uint)index <= byte.MaxValue) - { - generator.Emit(OpCodes.Starg_S, (byte)index); - } - else if ((uint)index < ushort.MaxValue) - { - generator.Emit(OpCodes.Starg, (short)index); - } - else - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - } - - public static void EmitLdloc(this ILGenerator generator, int index) - { - switch (index) - { - case 0: generator.Emit(OpCodes.Ldloc_0); break; - case 1: generator.Emit(OpCodes.Ldloc_1); break; - case 2: generator.Emit(OpCodes.Ldloc_2); break; - case 3: generator.Emit(OpCodes.Ldloc_3); break; - - default: - if ((uint)index <= byte.MaxValue) - { - generator.Emit(OpCodes.Ldloc_S, (byte)index); - } - else if ((uint)index < ushort.MaxValue) - { - generator.Emit(OpCodes.Ldloc, (short)index); - } - else - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - break; - } - } - - public static void EmitStloc(this ILGenerator generator, int index) - { - switch (index) - { - case 0: generator.Emit(OpCodes.Stloc_0); break; - case 1: generator.Emit(OpCodes.Stloc_1); break; - case 2: generator.Emit(OpCodes.Stloc_2); break; - case 3: generator.Emit(OpCodes.Stloc_3); break; - - default: - if ((uint)index <= byte.MaxValue) - { - generator.Emit(OpCodes.Stloc_S, (byte)index); - } - else if ((uint)index < ushort.MaxValue) - { - generator.Emit(OpCodes.Stloc, (short)index); - } - else - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - break; - } - } - } -} diff --git a/ChocolArm64/Translation/RegisterUsage.cs b/ChocolArm64/Translation/RegisterUsage.cs deleted file mode 100644 index f88fa0cd..00000000 --- a/ChocolArm64/Translation/RegisterUsage.cs +++ /dev/null @@ -1,176 +0,0 @@ -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using System.Collections.Generic; - -namespace ChocolArm64.Translation -{ - class RegisterUsage - { - private const long CallerSavedIntRegistersMask = 0x7fL << 9; - private const long PStateNzcvFlagsMask = 0xfL << 60; - - private const long CallerSavedVecRegistersMask = 0xffffL << 16; - - private RegisterMask[] _inputs; - private RegisterMask[] _outputs; - - public RegisterUsage(BasicBlock entryBlock, int blocksCount) - { - _inputs = new RegisterMask[blocksCount]; - _outputs = new RegisterMask[blocksCount]; - - HashSet<BasicBlock> visited = new HashSet<BasicBlock>(); - - Stack<BasicBlock> blockStack = new Stack<BasicBlock>(); - - List<BasicBlock> postOrderBlocks = new List<BasicBlock>(blocksCount); - - visited.Add(entryBlock); - - blockStack.Push(entryBlock); - - while (blockStack.TryPop(out BasicBlock block)) - { - if (block.Next != null && visited.Add(block.Next)) - { - blockStack.Push(block); - blockStack.Push(block.Next); - } - else if (block.Branch != null && visited.Add(block.Branch)) - { - blockStack.Push(block); - blockStack.Push(block.Branch); - } - else - { - postOrderBlocks.Add(block); - } - } - - RegisterMask[] cmnOutputMasks = new RegisterMask[blocksCount]; - - bool modified; - - bool firstPass = true; - - do - { - modified = false; - - for (int blkIndex = postOrderBlocks.Count - 1; blkIndex >= 0; blkIndex--) - { - BasicBlock block = postOrderBlocks[blkIndex]; - - if (block.Predecessors.Count != 0 && !block.HasStateLoad) - { - BasicBlock predecessor = block.Predecessors[0]; - - RegisterMask cmnOutputs = predecessor.RegOutputs | cmnOutputMasks[predecessor.Index]; - - RegisterMask outputs = _outputs[predecessor.Index]; - - for (int pIndex = 1; pIndex < block.Predecessors.Count; pIndex++) - { - predecessor = block.Predecessors[pIndex]; - - cmnOutputs &= predecessor.RegOutputs | cmnOutputMasks[predecessor.Index]; - - outputs |= _outputs[predecessor.Index]; - } - - _inputs[block.Index] |= outputs & ~cmnOutputs; - - if (!firstPass) - { - cmnOutputs &= cmnOutputMasks[block.Index]; - } - - if (Exchange(cmnOutputMasks, block.Index, cmnOutputs)) - { - modified = true; - } - - outputs |= block.RegOutputs; - - if (Exchange(_outputs, block.Index, _outputs[block.Index] | outputs)) - { - modified = true; - } - } - else if (Exchange(_outputs, block.Index, block.RegOutputs)) - { - modified = true; - } - } - - firstPass = false; - } - while (modified); - - do - { - modified = false; - - for (int blkIndex = 0; blkIndex < postOrderBlocks.Count; blkIndex++) - { - BasicBlock block = postOrderBlocks[blkIndex]; - - RegisterMask inputs = block.RegInputs; - - if (block.Next != null) - { - inputs |= _inputs[block.Next.Index]; - } - - if (block.Branch != null) - { - inputs |= _inputs[block.Branch.Index]; - } - - inputs &= ~cmnOutputMasks[block.Index]; - - if (Exchange(_inputs, block.Index, _inputs[block.Index] | inputs)) - { - modified = true; - } - } - } - while (modified); - } - - private static bool Exchange(RegisterMask[] masks, int blkIndex, RegisterMask value) - { - RegisterMask oldValue = masks[blkIndex]; - - masks[blkIndex] = value; - - return oldValue != value; - } - - public RegisterMask GetInputs(BasicBlock entryBlock) => _inputs[entryBlock.Index]; - - public RegisterMask GetOutputs(BasicBlock block) => _outputs[block.Index]; - - public static long ClearCallerSavedIntRegs(long mask, ExecutionMode mode) - { - // TODO: ARM32 support. - if (mode == ExecutionMode.Aarch64) - { - mask &= ~(CallerSavedIntRegistersMask | PStateNzcvFlagsMask); - } - - return mask; - } - - public static long ClearCallerSavedVecRegs(long mask, ExecutionMode mode) - { - // TODO: ARM32 support. - if (mode == ExecutionMode.Aarch64) - { - mask &= ~CallerSavedVecRegistersMask; - } - - return mask; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Translation/TranslatedSub.cs b/ChocolArm64/Translation/TranslatedSub.cs deleted file mode 100644 index cf42e202..00000000 --- a/ChocolArm64/Translation/TranslatedSub.cs +++ /dev/null @@ -1,93 +0,0 @@ -using ChocolArm64.Memory; -using ChocolArm64.State; -using System; -using System.Reflection; -using System.Reflection.Emit; - -namespace ChocolArm64.Translation -{ - delegate long ArmSubroutine(CpuThreadState state, MemoryManager memory); - - class TranslatedSub - { - // This is the minimum amount of calls needed for the method - // to be retranslated with higher quality code. It's only worth - // doing that for hot code. - private const int MinCallCountForOpt = 30; - - public ArmSubroutine Delegate { get; private set; } - - public static int StateArgIdx { get; } - public static int MemoryArgIdx { get; } - - public static Type[] FixedArgTypes { get; } - - public DynamicMethod Method { get; } - - public TranslationTier Tier { get; } - - private bool _rejit; - - private int _callCount; - - public TranslatedSub(DynamicMethod method, TranslationTier tier, bool rejit) - { - Method = method ?? throw new ArgumentNullException(nameof(method)); - Tier = tier; - _rejit = rejit; - } - - static TranslatedSub() - { - MethodInfo mthdInfo = typeof(ArmSubroutine).GetMethod("Invoke"); - - ParameterInfo[] Params = mthdInfo.GetParameters(); - - FixedArgTypes = new Type[Params.Length]; - - for (int index = 0; index < Params.Length; index++) - { - Type argType = Params[index].ParameterType; - - FixedArgTypes[index] = argType; - - if (argType == typeof(CpuThreadState)) - { - StateArgIdx = index; - } - else if (argType == typeof(MemoryManager)) - { - MemoryArgIdx = index; - } - } - } - - public void PrepareMethod() - { - Delegate = (ArmSubroutine)Method.CreateDelegate(typeof(ArmSubroutine)); - } - - public long Execute(CpuThreadState threadState, MemoryManager memory) - { - return Delegate(threadState, memory); - } - - public bool Rejit() - { - if (!_rejit) - { - return false; - } - - if (_callCount++ < MinCallCountForOpt) - { - return false; - } - - // Only return true once, so that it is added to the queue only once. - _rejit = false; - - return true; - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Translation/TranslatedSubBuilder.cs b/ChocolArm64/Translation/TranslatedSubBuilder.cs deleted file mode 100644 index eb69d9ee..00000000 --- a/ChocolArm64/Translation/TranslatedSubBuilder.cs +++ /dev/null @@ -1,274 +0,0 @@ -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.Intrinsics; - -using static ChocolArm64.State.RegisterConsts; - -namespace ChocolArm64.Translation -{ - class TranslatedSubBuilder - { - private ExecutionMode _mode; - - private bool _isComplete; - - private Dictionary<Register, int> _locals; - - private RegisterUsage _regUsage; - - public TranslatedSubBuilder(ExecutionMode mode, bool isComplete = false) - { - _mode = mode; - _isComplete = isComplete; - } - - public TranslatedSub Build(BasicBlock[] blocks, string name, TranslationTier tier, bool rejit = true) - { - _regUsage = new RegisterUsage(blocks[0], blocks.Length); - - DynamicMethod method = new DynamicMethod(name, typeof(long), TranslatedSub.FixedArgTypes); - - TranslatedSub subroutine = new TranslatedSub(method, tier, rejit); - - _locals = new Dictionary<Register, int>(); - - Dictionary<ILLabel, Label> labels = new Dictionary<ILLabel, Label>(); - - ILGenerator generator = method.GetILGenerator(); - - Label GetLabel(ILLabel label) - { - if (!labels.TryGetValue(label, out Label ilLabel)) - { - ilLabel = generator.DefineLabel(); - - labels.Add(label, ilLabel); - } - - return ilLabel; - } - - foreach (BasicBlock block in blocks) - { - for (int index = 0; index < block.Count; index++) - { - Operation operation = block.GetOperation(index); - - switch (operation.Type) - { - case OperationType.Call: - generator.Emit(OpCodes.Call, operation.GetArg<MethodInfo>(0)); - break; - - case OperationType.CallVirtual: - generator.Emit(OpCodes.Callvirt, operation.GetArg<MethodInfo>(0)); - break; - - case OperationType.IL: - generator.Emit(operation.GetArg<OpCode>(0)); - break; - - case OperationType.ILBranch: - generator.Emit(operation.GetArg<OpCode>(0), GetLabel(operation.GetArg<ILLabel>(1))); - break; - - case OperationType.LoadArgument: - generator.EmitLdarg(operation.GetArg<int>(0)); - break; - - case OperationType.LoadConstant: - EmitLoadConstant(generator, operation.GetArg(0)); - break; - - case OperationType.LoadContext: - EmitLoadContext(generator, operation.Parent); - break; - - case OperationType.LoadField: - generator.Emit(OpCodes.Ldfld, operation.GetArg<FieldInfo>(0)); - break; - - case OperationType.LoadLocal: - EmitLoadLocal( - generator, - operation.GetArg<int>(0), - operation.GetArg<RegisterType>(1), - operation.GetArg<RegisterSize>(2)); - break; - - case OperationType.MarkLabel: - generator.MarkLabel(GetLabel(operation.GetArg<ILLabel>(0))); - break; - - case OperationType.StoreContext: - EmitStoreContext(generator, operation.Parent); - break; - - case OperationType.StoreLocal: - EmitStoreLocal( - generator, - operation.GetArg<int>(0), - operation.GetArg<RegisterType>(1), - operation.GetArg<RegisterSize>(2)); - break; - } - } - } - - subroutine.PrepareMethod(); - - return subroutine; - } - - private static void EmitLoadConstant(ILGenerator generator, object value) - { - switch (value) - { - case int valI4: generator.EmitLdc_I4(valI4); break; - case long valI8: generator.Emit(OpCodes.Ldc_I8, valI8); break; - case float valR4: generator.Emit(OpCodes.Ldc_R4, valR4); break; - case double valR8: generator.Emit(OpCodes.Ldc_R8, valR8); break; - } - } - - private void EmitLoadContext(ILGenerator generator, BasicBlock block) - { - RegisterMask inputs = _regUsage.GetInputs(block); - - long intInputs = inputs.IntMask; - long vecInputs = inputs.VecMask; - - if (Optimizations.AssumeStrictAbiCompliance && _isComplete) - { - intInputs = RegisterUsage.ClearCallerSavedIntRegs(intInputs, _mode); - vecInputs = RegisterUsage.ClearCallerSavedVecRegs(vecInputs, _mode); - } - - LoadLocals(generator, intInputs, RegisterType.Int); - LoadLocals(generator, vecInputs, RegisterType.Vector); - } - - private void LoadLocals(ILGenerator generator, long inputs, RegisterType baseType) - { - for (int bit = 0; bit < 64; bit++) - { - long mask = 1L << bit; - - if ((inputs & mask) != 0) - { - Register reg = GetRegFromBit(bit, baseType); - - generator.EmitLdarg(TranslatedSub.StateArgIdx); - generator.Emit(OpCodes.Ldfld, reg.GetField()); - - generator.EmitStloc(GetLocalIndex(generator, reg)); - } - } - } - - private void EmitStoreContext(ILGenerator generator, BasicBlock block) - { - RegisterMask outputs = _regUsage.GetOutputs(block); - - long intOutputs = outputs.IntMask; - long vecOutputs = outputs.VecMask; - - if (Optimizations.AssumeStrictAbiCompliance && _isComplete) - { - intOutputs = RegisterUsage.ClearCallerSavedIntRegs(intOutputs, _mode); - vecOutputs = RegisterUsage.ClearCallerSavedVecRegs(vecOutputs, _mode); - } - - StoreLocals(generator, intOutputs, RegisterType.Int); - StoreLocals(generator, vecOutputs, RegisterType.Vector); - } - - private void StoreLocals(ILGenerator generator, long outputs, RegisterType baseType) - { - for (int bit = 0; bit < 64; bit++) - { - long mask = 1L << bit; - - if ((outputs & mask) != 0) - { - Register reg = GetRegFromBit(bit, baseType); - - generator.EmitLdarg(TranslatedSub.StateArgIdx); - generator.EmitLdloc(GetLocalIndex(generator, reg)); - - generator.Emit(OpCodes.Stfld, reg.GetField()); - } - } - } - - private void EmitLoadLocal(ILGenerator generator, int index, RegisterType type, RegisterSize size) - { - Register reg = new Register(index, type); - - generator.EmitLdloc(GetLocalIndex(generator, reg)); - - if (type == RegisterType.Int && size == RegisterSize.Int32) - { - generator.Emit(OpCodes.Conv_U4); - } - } - - private void EmitStoreLocal(ILGenerator generator, int index, RegisterType type, RegisterSize size) - { - Register reg = new Register(index, type); - - if (type == RegisterType.Int && size == RegisterSize.Int32) - { - generator.Emit(OpCodes.Conv_U8); - } - - generator.EmitStloc(GetLocalIndex(generator, reg)); - } - - private int GetLocalIndex(ILGenerator generator, Register reg) - { - if (!_locals.TryGetValue(reg, out int index)) - { - generator.DeclareLocal(GetFieldType(reg.Type)); - - index = _locals.Count; - - _locals.Add(reg, index); - } - - return index; - } - - private static Type GetFieldType(RegisterType regType) - { - switch (regType) - { - case RegisterType.Flag: return typeof(bool); - case RegisterType.Int: return typeof(ulong); - case RegisterType.Vector: return typeof(Vector128<float>); - } - - throw new ArgumentException(nameof(regType)); - } - - private static Register GetRegFromBit(int bit, RegisterType baseType) - { - if (bit < RegsCount) - { - return new Register(bit, baseType); - } - else if (baseType == RegisterType.Int) - { - return new Register(bit & RegsMask, RegisterType.Flag); - } - else - { - throw new ArgumentOutOfRangeException(nameof(bit)); - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Translation/TranslationTier.cs b/ChocolArm64/Translation/TranslationTier.cs deleted file mode 100644 index 13afd9c5..00000000 --- a/ChocolArm64/Translation/TranslationTier.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace ChocolArm64.Translation -{ - enum TranslationTier - { - Tier0, - Tier1, - Tier2, - - Count - } -}
\ No newline at end of file diff --git a/ChocolArm64/Translation/Translator.cs b/ChocolArm64/Translation/Translator.cs deleted file mode 100644 index ab8f474a..00000000 --- a/ChocolArm64/Translation/Translator.cs +++ /dev/null @@ -1,252 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.Events; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.Memory; -using ChocolArm64.State; -using System; -using System.Reflection.Emit; -using System.Threading; - -namespace ChocolArm64.Translation -{ - public class Translator : ARMeilleure.Translation.ITranslator - { - private MemoryManager _memory; - - private CpuThreadState _dummyThreadState; - - private TranslatorCache _cache; - private TranslatorQueue _queue; - - private Thread _backgroundTranslator; - - public event EventHandler<CpuTraceEventArgs> CpuTrace; - - public bool EnableCpuTrace { get; set; } - - private volatile int _threadCount; - - public Translator(MemoryManager memory) - { - _memory = memory; - - _dummyThreadState = new CpuThreadState(); - - _dummyThreadState.Running = false; - - _cache = new TranslatorCache(); - _queue = new TranslatorQueue(); - } - - public void Execute(ARMeilleure.State.IExecutionContext ctx, ulong address) - { - CpuThreadState state = (CpuThreadState)ctx; - - long position = (long)address; - - if (Interlocked.Increment(ref _threadCount) == 1) - { - _backgroundTranslator = new Thread(TranslateQueuedSubs); - _backgroundTranslator.Start(); - } - - state.CurrentTranslator = this; - - do - { - if (EnableCpuTrace) - { - CpuTrace?.Invoke(this, new CpuTraceEventArgs(position)); - } - - if (!_cache.TryGetSubroutine(position, out TranslatedSub sub)) - { - sub = TranslateLowCq(position, state.GetExecutionMode()); - } - - position = sub.Execute(state, _memory); - } - while (position != 0 && state.Running); - - state.CurrentTranslator = null; - - if (Interlocked.Decrement(ref _threadCount) == 0) - { - _queue.ForceSignal(); - } - } - - internal ArmSubroutine GetOrTranslateSubroutine(CpuThreadState state, long position, CallType cs) - { - if (!_cache.TryGetSubroutine(position, out TranslatedSub sub)) - { - sub = TranslateLowCq(position, state.GetExecutionMode()); - } - - if (sub.Rejit()) - { - bool isComplete = cs == CallType.Call || - cs == CallType.VirtualCall; - - _queue.Enqueue(position, state.GetExecutionMode(), TranslationTier.Tier1, isComplete); - } - - return sub.Delegate; - } - - private void TranslateQueuedSubs() - { - while (_threadCount != 0) - { - if (_queue.TryDequeue(out TranslatorQueueItem item)) - { - bool isCached = _cache.TryGetSubroutine(item.Position, out TranslatedSub sub); - - if (isCached && item.Tier <= sub.Tier) - { - continue; - } - - if (item.Tier == TranslationTier.Tier0) - { - TranslateLowCq(item.Position, item.Mode); - } - else - { - TranslateHighCq(item.Position, item.Mode, item.IsComplete); - } - } - else - { - _queue.WaitForItems(); - } - } - } - - private TranslatedSub TranslateLowCq(long position, ExecutionMode mode) - { - Block[] blocks = Decoder.DecodeBasicBlock(_memory, (ulong)position, mode); - - ILEmitterCtx context = new ILEmitterCtx(_memory, _cache, _queue, TranslationTier.Tier0); - - BasicBlock[] bbs = EmitAndGetBlocks(context, blocks); - - TranslatedSubBuilder builder = new TranslatedSubBuilder(mode); - - string name = GetSubroutineName(position); - - TranslatedSub subroutine = builder.Build(bbs, name, TranslationTier.Tier0); - - return _cache.GetOrAdd(position, subroutine, GetOpsCount(bbs)); - } - - private TranslatedSub TranslateHighCq(long position, ExecutionMode mode, bool isComplete) - { - Block[] blocks = Decoder.DecodeSubroutine(_memory, (ulong)position, mode); - - ILEmitterCtx context = new ILEmitterCtx(_memory, _cache, _queue, TranslationTier.Tier1); - - if (blocks[0].Address != (ulong)position) - { - context.Emit(OpCodes.Br, context.GetLabel(position)); - } - - BasicBlock[] bbs = EmitAndGetBlocks(context, blocks); - - isComplete &= !context.HasIndirectJump; - - TranslatedSubBuilder builder = new TranslatedSubBuilder(mode, isComplete); - - string name = GetSubroutineName(position); - - TranslatedSub subroutine = builder.Build(bbs, name, TranslationTier.Tier1, context.HasSlowCall); - - ForceAheadOfTimeCompilation(subroutine); - - _cache.AddOrUpdate(position, subroutine, GetOpsCount(bbs)); - - return subroutine; - } - - private static BasicBlock[] EmitAndGetBlocks(ILEmitterCtx context, Block[] blocks) - { - for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) - { - Block block = blocks[blkIndex]; - - context.CurrBlock = block; - - context.MarkLabel(context.GetLabel((long)block.Address)); - - for (int opcIndex = 0; opcIndex < block.OpCodes.Count; opcIndex++) - { - OpCode64 opCode = block.OpCodes[opcIndex]; - - context.CurrOp = opCode; - - bool isLastOp = opcIndex == block.OpCodes.Count - 1; - - if (isLastOp && block.Branch != null && block.Branch.Address <= block.Address) - { - context.EmitSynchronization(); - } - - ILLabel lblPredicateSkip = null; - - if (opCode is OpCode32 op && op.Cond < Condition.Al) - { - lblPredicateSkip = new ILLabel(); - - context.EmitCondBranch(lblPredicateSkip, op.Cond.Invert()); - } - - opCode.Emitter(context); - - if (lblPredicateSkip != null) - { - context.MarkLabel(lblPredicateSkip); - - context.ResetBlockStateForPredicatedOp(); - - // If this is the last op on the block, and there's no "next" block - // after this one, then we have to return right now, with the address - // of the next instruction to be executed (in the case that the condition - // is false, and the branch was not taken, as all basic blocks should end - // with some kind of branch). - if (isLastOp && block.Next == null) - { - context.EmitStoreContext(); - context.EmitLdc_I8(opCode.Position + opCode.OpCodeSizeInBytes); - - context.Emit(OpCodes.Ret); - } - } - } - } - - return context.GetBlocks(); - } - - private static string GetSubroutineName(long position) - { - return $"Sub{position:x16}"; - } - - private static int GetOpsCount(BasicBlock[] blocks) - { - int opCount = 0; - - foreach (BasicBlock block in blocks) - { - opCount += block.Count; - } - - return opCount; - } - - private void ForceAheadOfTimeCompilation(TranslatedSub subroutine) - { - subroutine.Execute(_dummyThreadState, null); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Translation/TranslatorCache.cs b/ChocolArm64/Translation/TranslatorCache.cs deleted file mode 100644 index cf6510ad..00000000 --- a/ChocolArm64/Translation/TranslatorCache.cs +++ /dev/null @@ -1,196 +0,0 @@ -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Threading; - -namespace ChocolArm64.Translation -{ - class TranslatorCache - { - // Maximum size of the cache, the unit used is completely arbitrary. - private const int MaxTotalSize = 0x800000; - - // Minimum time required in milliseconds for a method to be eligible for deletion. - private const int MinTimeDelta = 2 * 60000; - - // Minimum number of calls required to update the timestamp. - private const int MinCallCountForUpdate = 250; - - private class CacheBucket - { - public TranslatedSub Subroutine { get; private set; } - - public LinkedListNode<long> Node { get; private set; } - - public int CallCount { get; set; } - - public int Size { get; private set; } - - public long Timestamp { get; private set; } - - public CacheBucket(TranslatedSub subroutine, LinkedListNode<long> node, int size) - { - Subroutine = subroutine; - Size = size; - - UpdateNode(node); - } - - public void UpdateNode(LinkedListNode<long> node) - { - Node = node; - - Timestamp = GetTimestamp(); - } - } - - private ConcurrentDictionary<long, CacheBucket> _cache; - - private LinkedList<long> _sortedCache; - - private int _totalSize; - - public TranslatorCache() - { - _cache = new ConcurrentDictionary<long, CacheBucket>(); - - _sortedCache = new LinkedList<long>(); - } - - public TranslatedSub GetOrAdd(long position, TranslatedSub subroutine, int size) - { - ClearCacheIfNeeded(); - - lock (_sortedCache) - { - LinkedListNode<long> node = _sortedCache.AddLast(position); - - CacheBucket bucket = new CacheBucket(subroutine, node, size); - - bucket = _cache.GetOrAdd(position, bucket); - - if (bucket.Node == node) - { - _totalSize += size; - } - else - { - _sortedCache.Remove(node); - } - - return bucket.Subroutine; - } - } - - public void AddOrUpdate(long position, TranslatedSub subroutine, int size) - { - ClearCacheIfNeeded(); - - lock (_sortedCache) - { - _totalSize += size; - - LinkedListNode<long> node = _sortedCache.AddLast(position); - - CacheBucket newBucket = new CacheBucket(subroutine, node, size); - - _cache.AddOrUpdate(position, newBucket, (key, bucket) => - { - _totalSize -= bucket.Size; - - _sortedCache.Remove(bucket.Node); - - return newBucket; - }); - } - } - - public bool HasSubroutine(long position) - { - return _cache.ContainsKey(position); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryGetSubroutine(long position, out TranslatedSub subroutine) - { - if (_cache.TryGetValue(position, out CacheBucket bucket)) - { - if (bucket.CallCount++ > MinCallCountForUpdate) - { - if (Monitor.TryEnter(_sortedCache)) - { - try - { - // The bucket value on the dictionary may have changed between the - // time we get the value from the dictionary, and we acquire the - // lock. So we need to ensure we are working with the latest value, - // we can do that by getting the value again, inside the lock. - if (_cache.TryGetValue(position, out CacheBucket latestBucket)) - { - latestBucket.CallCount = 0; - - _sortedCache.Remove(latestBucket.Node); - - latestBucket.UpdateNode(_sortedCache.AddLast(position)); - } - } - finally - { - Monitor.Exit(_sortedCache); - } - } - } - - subroutine = bucket.Subroutine; - - return true; - } - - subroutine = default(TranslatedSub); - - return false; - } - - private void ClearCacheIfNeeded() - { - long timestamp = GetTimestamp(); - - while (_totalSize > MaxTotalSize) - { - lock (_sortedCache) - { - LinkedListNode<long> node = _sortedCache.First; - - if (node == null) - { - break; - } - - CacheBucket bucket = _cache[node.Value]; - - long timeDelta = timestamp - bucket.Timestamp; - - if (timeDelta <= MinTimeDelta) - { - break; - } - - if (_cache.TryRemove(node.Value, out bucket)) - { - _totalSize -= bucket.Size; - - _sortedCache.Remove(bucket.Node); - } - } - } - } - - private static long GetTimestamp() - { - long timestamp = Stopwatch.GetTimestamp(); - - return timestamp / (Stopwatch.Frequency / 1000); - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Translation/TranslatorQueue.cs b/ChocolArm64/Translation/TranslatorQueue.cs deleted file mode 100644 index 0f1d8474..00000000 --- a/ChocolArm64/Translation/TranslatorQueue.cs +++ /dev/null @@ -1,77 +0,0 @@ -using ChocolArm64.State; -using System.Collections.Concurrent; -using System.Threading; - -namespace ChocolArm64.Translation -{ - class TranslatorQueue - { - private ConcurrentStack<TranslatorQueueItem>[] _translationQueue; - - private ManualResetEvent _queueDataReceivedEvent; - - private bool _signaled; - - public TranslatorQueue() - { - _translationQueue = new ConcurrentStack<TranslatorQueueItem>[(int)TranslationTier.Count]; - - for (int prio = 0; prio < _translationQueue.Length; prio++) - { - _translationQueue[prio] = new ConcurrentStack<TranslatorQueueItem>(); - } - - _queueDataReceivedEvent = new ManualResetEvent(false); - } - - public void Enqueue(long position, ExecutionMode mode, TranslationTier tier, bool isComplete) - { - TranslatorQueueItem item = new TranslatorQueueItem(position, mode, tier, isComplete); - - ConcurrentStack<TranslatorQueueItem> queue = _translationQueue[(int)tier]; - - queue.Push(item); - - _queueDataReceivedEvent.Set(); - } - - public bool TryDequeue(out TranslatorQueueItem item) - { - for (int prio = 0; prio < _translationQueue.Length; prio++) - { - if (_translationQueue[prio].TryPop(out item)) - { - return true; - } - } - - item = default(TranslatorQueueItem); - - return false; - } - - public void WaitForItems() - { - _queueDataReceivedEvent.WaitOne(); - - lock (_queueDataReceivedEvent) - { - if (!_signaled) - { - _queueDataReceivedEvent.Reset(); - } - } - } - - public void ForceSignal() - { - lock (_queueDataReceivedEvent) - { - _signaled = true; - - _queueDataReceivedEvent.Set(); - _queueDataReceivedEvent.Close(); - } - } - } -}
\ No newline at end of file diff --git a/ChocolArm64/Translation/TranslatorQueueItem.cs b/ChocolArm64/Translation/TranslatorQueueItem.cs deleted file mode 100644 index dde2706d..00000000 --- a/ChocolArm64/Translation/TranslatorQueueItem.cs +++ /dev/null @@ -1,27 +0,0 @@ -using ChocolArm64.State; - -namespace ChocolArm64.Translation -{ - struct TranslatorQueueItem - { - public long Position { get; } - - public ExecutionMode Mode { get; } - - public TranslationTier Tier { get; } - - public bool IsComplete { get; } - - public TranslatorQueueItem( - long position, - ExecutionMode mode, - TranslationTier tier, - bool isComplete = false) - { - Position = position; - Mode = mode; - Tier = tier; - IsComplete = isComplete; - } - } -}
\ No newline at end of file |
