From eee639d6ba544fa5dd9352426d55e91bc54e157d Mon Sep 17 00:00:00 2001 From: LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> Date: Thu, 31 Oct 2019 19:09:03 +0100 Subject: [PATCH] .NET Core 3.0 is here! (#784) * .NET Core 3.0 is here! * Remove IMemoryManager.cs and its references. * Add T Math/F.FusedMultiplyAdd(T, T, T). Nits. * Nit. * Update appveyor.yml * Revert "Resolve Visual Studio build issues" This reverts commit 1772128ce0fc058e6280001aace3a77a7a96897b. * Update SvcTable.cs --- ARMeilleure/ARMeilleure.csproj | 3 +- .../Instructions/InstEmitSimdArithmetic.cs | 10 +- ARMeilleure/Instructions/SoftFloat.cs | 30 +- ARMeilleure/Memory/IMemoryManager.cs | 40 - ARMeilleure/Memory/MemoryHelper.cs | 8 +- ARMeilleure/Memory/MemoryManager.cs | 2 +- ARMeilleure/State/ExecutionContext.cs | 2 +- ARMeilleure/State/IExecutionContext.cs | 37 - ARMeilleure/Translation/ITranslator.cs | 9 - ARMeilleure/Translation/Translator.cs | 6 +- ChocolArm64/ChocolArm64.csproj | 39 - ChocolArm64/Decoders/BitUtils.cs | 59 - ChocolArm64/Decoders/Block.cs | 99 - ChocolArm64/Decoders/Condition.cs | 32 - ChocolArm64/Decoders/DataOp.cs | 10 - ChocolArm64/Decoders/Decoder.cs | 379 -- ChocolArm64/Decoders/DecoderHelper.cs | 112 - ChocolArm64/Decoders/IOpCode32.cs | 9 - ChocolArm64/Decoders/IOpCode32Alu.cs | 10 - ChocolArm64/Decoders/IOpCode32BImm.cs | 4 - ChocolArm64/Decoders/IOpCode32BReg.cs | 7 - ChocolArm64/Decoders/IOpCode32Mem.cs | 12 - ChocolArm64/Decoders/IOpCode32MemMult.cs | 13 - ChocolArm64/Decoders/IOpCode64.cs | 13 - ChocolArm64/Decoders/IOpCodeAlu64.cs | 10 - ChocolArm64/Decoders/IOpCodeAluImm64.cs | 7 - ChocolArm64/Decoders/IOpCodeAluRs64.cs | 10 - ChocolArm64/Decoders/IOpCodeAluRx64.cs | 10 - ChocolArm64/Decoders/IOpCodeBImm.cs | 7 - ChocolArm64/Decoders/IOpCodeCond64.cs | 7 - ChocolArm64/Decoders/IOpCodeLit64.cs | 11 - ChocolArm64/Decoders/IOpCodeSimd64.cs | 7 - ChocolArm64/Decoders/IntType.cs | 14 - ChocolArm64/Decoders/OpCode32.cs | 24 - ChocolArm64/Decoders/OpCode32Alu.cs | 20 - ChocolArm64/Decoders/OpCode32AluImm.cs | 21 - ChocolArm64/Decoders/OpCode32AluRsImm.cs | 20 - ChocolArm64/Decoders/OpCode32BImm.cs | 29 - ChocolArm64/Decoders/OpCode32BReg.cs | 14 - ChocolArm64/Decoders/OpCode32Mem.cs | 37 - ChocolArm64/Decoders/OpCode32MemImm.cs | 12 - ChocolArm64/Decoders/OpCode32MemImm8.cs | 15 - ChocolArm64/Decoders/OpCode32MemMult.cs | 57 - ChocolArm64/Decoders/OpCode64.cs | 40 - ChocolArm64/Decoders/OpCodeAdr64.cs | 18 - ChocolArm64/Decoders/OpCodeAlu64.cs | 23 - ChocolArm64/Decoders/OpCodeAluImm64.cs | 39 - ChocolArm64/Decoders/OpCodeAluRs64.cs | 29 - ChocolArm64/Decoders/OpCodeAluRx64.cs | 19 - ChocolArm64/Decoders/OpCodeBImm64.cs | 11 - ChocolArm64/Decoders/OpCodeBImmAl64.cs | 12 - ChocolArm64/Decoders/OpCodeBImmCmp64.cs | 20 - ChocolArm64/Decoders/OpCodeBImmCond64.cs | 25 - ChocolArm64/Decoders/OpCodeBImmTest64.cs | 20 - ChocolArm64/Decoders/OpCodeBReg64.cs | 24 - ChocolArm64/Decoders/OpCodeBfm64.cs | 29 - ChocolArm64/Decoders/OpCodeCcmp64.cs | 31 - ChocolArm64/Decoders/OpCodeCcmpImm64.cs | 11 - ChocolArm64/Decoders/OpCodeCcmpReg64.cs | 15 - ChocolArm64/Decoders/OpCodeCsel64.cs | 17 - ChocolArm64/Decoders/OpCodeException64.cs | 14 - ChocolArm64/Decoders/OpCodeMem64.cs | 19 - ChocolArm64/Decoders/OpCodeMemEx64.cs | 16 - ChocolArm64/Decoders/OpCodeMemImm64.cs | 53 - ChocolArm64/Decoders/OpCodeMemLit64.cs | 28 - ChocolArm64/Decoders/OpCodeMemPair64.cs | 25 - ChocolArm64/Decoders/OpCodeMemReg64.cs | 20 - ChocolArm64/Decoders/OpCodeMov64.cs | 35 - ChocolArm64/Decoders/OpCodeMul64.cs | 16 - ChocolArm64/Decoders/OpCodeSimd64.cs | 25 - ChocolArm64/Decoders/OpCodeSimdCvt64.cs | 21 - ChocolArm64/Decoders/OpCodeSimdExt64.cs | 14 - ChocolArm64/Decoders/OpCodeSimdFcond64.cs | 17 - ChocolArm64/Decoders/OpCodeSimdFmov64.cs | 33 - ChocolArm64/Decoders/OpCodeSimdImm64.cs | 100 - ChocolArm64/Decoders/OpCodeSimdIns64.cs | 36 - ChocolArm64/Decoders/OpCodeSimdMemImm64.cs | 19 - ChocolArm64/Decoders/OpCodeSimdMemLit64.cs | 31 - ChocolArm64/Decoders/OpCodeSimdMemMs64.cs | 48 - ChocolArm64/Decoders/OpCodeSimdMemPair64.cs | 16 - ChocolArm64/Decoders/OpCodeSimdMemReg64.cs | 14 - ChocolArm64/Decoders/OpCodeSimdMemSs64.cs | 97 - ChocolArm64/Decoders/OpCodeSimdReg64.cs | 18 - ChocolArm64/Decoders/OpCodeSimdRegElem64.cs | 31 - ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs | 33 - ChocolArm64/Decoders/OpCodeSimdShImm64.cs | 16 - ChocolArm64/Decoders/OpCodeSimdTbl64.cs | 12 - ChocolArm64/Decoders/OpCodeSystem64.cs | 24 - ChocolArm64/Decoders/OpCodeT16.cs | 14 - ChocolArm64/Decoders/OpCodeT16AluImm8.cs | 22 - ChocolArm64/Decoders/OpCodeT16BReg.cs | 14 - ChocolArm64/Decoders/ShiftType.cs | 10 - ChocolArm64/Events/CpuTraceEventArgs.cs | 14 - ChocolArm64/Events/InstExceptionEventArgs.cs | 16 - ChocolArm64/Events/InstUndefinedEventArgs.cs | 16 - ChocolArm64/Instructions/CryptoHelper.cs | 331 -- ChocolArm64/Instructions/Inst.cs | 18 - ChocolArm64/Instructions/InstEmit32Helper.cs | 146 - ChocolArm64/Instructions/InstEmitAlu.cs | 422 -- ChocolArm64/Instructions/InstEmitAlu32.cs | 142 - ChocolArm64/Instructions/InstEmitAluHelper.cs | 462 -- ChocolArm64/Instructions/InstEmitBfm.cs | 243 -- ChocolArm64/Instructions/InstEmitCcmp.cs | 82 - ChocolArm64/Instructions/InstEmitCsel.cs | 59 - ChocolArm64/Instructions/InstEmitException.cs | 87 - ChocolArm64/Instructions/InstEmitFlow.cs | 181 - ChocolArm64/Instructions/InstEmitFlow32.cs | 81 - .../Instructions/InstEmitFlowHelper.cs | 144 - ChocolArm64/Instructions/InstEmitHash.cs | 115 - ChocolArm64/Instructions/InstEmitMemory.cs | 241 -- ChocolArm64/Instructions/InstEmitMemory32.cs | 320 -- ChocolArm64/Instructions/InstEmitMemoryEx.cs | 350 -- .../Instructions/InstEmitMemoryHelper.cs | 475 --- ChocolArm64/Instructions/InstEmitMove.cs | 41 - ChocolArm64/Instructions/InstEmitMul.cs | 80 - .../Instructions/InstEmitSimdArithmetic.cs | 3797 ----------------- ChocolArm64/Instructions/InstEmitSimdCmp.cs | 862 ---- .../Instructions/InstEmitSimdCrypto.cs | 54 - ChocolArm64/Instructions/InstEmitSimdCvt.cs | 1382 ------ ChocolArm64/Instructions/InstEmitSimdHash.cs | 140 - .../Instructions/InstEmitSimdHelper.cs | 1580 ------- .../Instructions/InstEmitSimdLogical.cs | 437 -- .../Instructions/InstEmitSimdMemory.cs | 182 - ChocolArm64/Instructions/InstEmitSimdMove.cs | 793 ---- ChocolArm64/Instructions/InstEmitSimdShift.cs | 1175 ----- ChocolArm64/Instructions/InstEmitSystem.cs | 137 - ChocolArm64/Instructions/InstEmitter.cs | 6 - ChocolArm64/Instructions/SoftFallback.cs | 1194 ------ ChocolArm64/Instructions/SoftFloat.cs | 2790 ------------ ChocolArm64/Instructions/VectorHelper.cs | 646 --- .../IntermediateRepresentation/BasicBlock.cs | 122 - .../IntermediateRepresentation/ILLabel.cs | 4 - .../IntermediateRepresentation/Operation.cs | 112 - .../OperationType.cs | 18 - .../RegisterMask.cs | 56 - ChocolArm64/Memory/CompareExchange128.cs | 151 - ChocolArm64/Memory/IMemory.cs | 37 - ChocolArm64/Memory/MemoryHelper.cs | 71 - ChocolArm64/Memory/MemoryManagement.cs | 114 - ChocolArm64/Memory/MemoryManagementUnix.cs | 70 - ChocolArm64/Memory/MemoryManagementWindows.cs | 155 - ChocolArm64/Memory/MemoryManager.cs | 1017 ----- ChocolArm64/Memory/MemoryProtection.cs | 16 - .../Memory/MemoryProtectionException.cs | 10 - ChocolArm64/OpCodeTable.cs | 792 ---- ChocolArm64/Optimizations.cs | 27 - ChocolArm64/State/Aarch32Mode.cs | 15 - ChocolArm64/State/CpuThreadState.cs | 354 -- ChocolArm64/State/ExecutionMode.cs | 9 - ChocolArm64/State/FpExc.cs | 12 - ChocolArm64/State/FpType.cs | 11 - ChocolArm64/State/Fpcr.cs | 11 - ChocolArm64/State/Fpsr.cs | 8 - ChocolArm64/State/PState.cs | 24 - ChocolArm64/State/Register.cs | 148 - ChocolArm64/State/RegisterAlias.cs | 41 - ChocolArm64/State/RegisterConsts.cs | 8 - ChocolArm64/State/RegisterSize.cs | 10 - ChocolArm64/State/RegisterType.cs | 9 - ChocolArm64/State/RoundMode.cs | 10 - ChocolArm64/Translation/CallType.cs | 9 - ChocolArm64/Translation/ILEmitterCtx.cs | 709 --- ChocolArm64/Translation/ILGeneratorEx.cs | 121 - ChocolArm64/Translation/RegisterUsage.cs | 176 - ChocolArm64/Translation/TranslatedSub.cs | 93 - .../Translation/TranslatedSubBuilder.cs | 274 -- ChocolArm64/Translation/TranslationTier.cs | 11 - ChocolArm64/Translation/Translator.cs | 252 -- ChocolArm64/Translation/TranslatorCache.cs | 196 - ChocolArm64/Translation/TranslatorQueue.cs | 77 - .../Translation/TranslatorQueueItem.cs | 27 - README.md | 60 +- Ryujinx.Audio/Ryujinx.Audio.csproj | 4 +- Ryujinx.Common/Ryujinx.Common.csproj | 2 +- .../Graphics3d/Texture/ImageUtils.cs | 4 +- .../Graphics3d/Texture/TextureHelper.cs | 4 +- Ryujinx.Graphics/Memory/NvGpuVmm.cs | 4 +- Ryujinx.Graphics/Memory/NvGpuVmmCache.cs | 4 +- Ryujinx.Graphics/Ryujinx.Graphics.csproj | 4 +- Ryujinx.HLE/HOS/Homebrew.cs | 16 +- Ryujinx.HLE/HOS/Horizon.cs | 2 - Ryujinx.HLE/HOS/Ipc/IpcHandler.cs | 2 +- .../HOS/Kernel/Memory/KMemoryManager.cs | 4 +- .../HOS/Kernel/Process/HleProcessDebugger.cs | 7 +- Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs | 19 +- .../HOS/Kernel/SupervisorCall/SvcHandler.cs | 4 +- .../HOS/Kernel/SupervisorCall/SvcTable.cs | 24 +- .../HOS/Kernel/SupervisorCall/SvcThread.cs | 4 +- Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs | 12 +- Ryujinx.HLE/HOS/ServiceCtx.cs | 4 +- .../AudioRendererManager/IAudioRenderer.cs | 4 +- .../AudioRendererManager/VoiceContext.cs | 4 +- Ryujinx.HLE/Ryujinx.HLE.csproj | 12 +- Ryujinx.HLE/Utilities/StructReader.cs | 4 +- Ryujinx.HLE/Utilities/StructWriter.cs | 4 +- Ryujinx.LLE/Luea.csproj | 2 +- Ryujinx.Profiler/Ryujinx.Profiler.csproj | 2 +- .../Ryujinx.ShaderTools.csproj | 2 +- .../Ryujinx.Tests.Unicorn.csproj | 4 +- Ryujinx.Tests/Ryujinx.Tests.csproj | 3 +- Ryujinx.sln | 10 - Ryujinx/Config.json | 1 - Ryujinx/Configuration.cs | 13 +- Ryujinx/Ryujinx.csproj | 9 +- Ryujinx/Ui/SwitchSettings.cs | 3 - Ryujinx/Ui/SwitchSettings.glade | 20 +- Ryujinx/_schema.json | 12 - appveyor.yml | 12 +- 208 files changed, 138 insertions(+), 27346 deletions(-) delete mode 100644 ARMeilleure/Memory/IMemoryManager.cs delete mode 100644 ARMeilleure/State/IExecutionContext.cs delete mode 100644 ARMeilleure/Translation/ITranslator.cs delete mode 100644 ChocolArm64/ChocolArm64.csproj delete mode 100644 ChocolArm64/Decoders/BitUtils.cs delete mode 100644 ChocolArm64/Decoders/Block.cs delete mode 100644 ChocolArm64/Decoders/Condition.cs delete mode 100644 ChocolArm64/Decoders/DataOp.cs delete mode 100644 ChocolArm64/Decoders/Decoder.cs delete mode 100644 ChocolArm64/Decoders/DecoderHelper.cs delete mode 100644 ChocolArm64/Decoders/IOpCode32.cs delete mode 100644 ChocolArm64/Decoders/IOpCode32Alu.cs delete mode 100644 ChocolArm64/Decoders/IOpCode32BImm.cs delete mode 100644 ChocolArm64/Decoders/IOpCode32BReg.cs delete mode 100644 ChocolArm64/Decoders/IOpCode32Mem.cs delete mode 100644 ChocolArm64/Decoders/IOpCode32MemMult.cs delete mode 100644 ChocolArm64/Decoders/IOpCode64.cs delete mode 100644 ChocolArm64/Decoders/IOpCodeAlu64.cs delete mode 100644 ChocolArm64/Decoders/IOpCodeAluImm64.cs delete mode 100644 ChocolArm64/Decoders/IOpCodeAluRs64.cs delete mode 100644 ChocolArm64/Decoders/IOpCodeAluRx64.cs delete mode 100644 ChocolArm64/Decoders/IOpCodeBImm.cs delete mode 100644 ChocolArm64/Decoders/IOpCodeCond64.cs delete mode 100644 ChocolArm64/Decoders/IOpCodeLit64.cs delete mode 100644 ChocolArm64/Decoders/IOpCodeSimd64.cs delete mode 100644 ChocolArm64/Decoders/IntType.cs delete mode 100644 ChocolArm64/Decoders/OpCode32.cs delete mode 100644 ChocolArm64/Decoders/OpCode32Alu.cs delete mode 100644 ChocolArm64/Decoders/OpCode32AluImm.cs delete mode 100644 ChocolArm64/Decoders/OpCode32AluRsImm.cs delete mode 100644 ChocolArm64/Decoders/OpCode32BImm.cs delete mode 100644 ChocolArm64/Decoders/OpCode32BReg.cs delete mode 100644 ChocolArm64/Decoders/OpCode32Mem.cs delete mode 100644 ChocolArm64/Decoders/OpCode32MemImm.cs delete mode 100644 ChocolArm64/Decoders/OpCode32MemImm8.cs delete mode 100644 ChocolArm64/Decoders/OpCode32MemMult.cs delete mode 100644 ChocolArm64/Decoders/OpCode64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeAdr64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeAlu64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeAluImm64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeAluRs64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeAluRx64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeBImm64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeBImmAl64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeBImmCmp64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeBImmCond64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeBImmTest64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeBReg64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeBfm64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeCcmp64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeCcmpImm64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeCcmpReg64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeCsel64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeException64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeMem64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeMemEx64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeMemImm64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeMemLit64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeMemPair64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeMemReg64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeMov64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeMul64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimd64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdCvt64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdExt64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdFcond64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdFmov64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdImm64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdIns64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdMemImm64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdMemLit64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdMemMs64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdMemPair64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdMemReg64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdMemSs64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdReg64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdRegElem64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdShImm64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSimdTbl64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeSystem64.cs delete mode 100644 ChocolArm64/Decoders/OpCodeT16.cs delete mode 100644 ChocolArm64/Decoders/OpCodeT16AluImm8.cs delete mode 100644 ChocolArm64/Decoders/OpCodeT16BReg.cs delete mode 100644 ChocolArm64/Decoders/ShiftType.cs delete mode 100644 ChocolArm64/Events/CpuTraceEventArgs.cs delete mode 100644 ChocolArm64/Events/InstExceptionEventArgs.cs delete mode 100644 ChocolArm64/Events/InstUndefinedEventArgs.cs delete mode 100644 ChocolArm64/Instructions/CryptoHelper.cs delete mode 100644 ChocolArm64/Instructions/Inst.cs delete mode 100644 ChocolArm64/Instructions/InstEmit32Helper.cs delete mode 100644 ChocolArm64/Instructions/InstEmitAlu.cs delete mode 100644 ChocolArm64/Instructions/InstEmitAlu32.cs delete mode 100644 ChocolArm64/Instructions/InstEmitAluHelper.cs delete mode 100644 ChocolArm64/Instructions/InstEmitBfm.cs delete mode 100644 ChocolArm64/Instructions/InstEmitCcmp.cs delete mode 100644 ChocolArm64/Instructions/InstEmitCsel.cs delete mode 100644 ChocolArm64/Instructions/InstEmitException.cs delete mode 100644 ChocolArm64/Instructions/InstEmitFlow.cs delete mode 100644 ChocolArm64/Instructions/InstEmitFlow32.cs delete mode 100644 ChocolArm64/Instructions/InstEmitFlowHelper.cs delete mode 100644 ChocolArm64/Instructions/InstEmitHash.cs delete mode 100644 ChocolArm64/Instructions/InstEmitMemory.cs delete mode 100644 ChocolArm64/Instructions/InstEmitMemory32.cs delete mode 100644 ChocolArm64/Instructions/InstEmitMemoryEx.cs delete mode 100644 ChocolArm64/Instructions/InstEmitMemoryHelper.cs delete mode 100644 ChocolArm64/Instructions/InstEmitMove.cs delete mode 100644 ChocolArm64/Instructions/InstEmitMul.cs delete mode 100644 ChocolArm64/Instructions/InstEmitSimdArithmetic.cs delete mode 100644 ChocolArm64/Instructions/InstEmitSimdCmp.cs delete mode 100644 ChocolArm64/Instructions/InstEmitSimdCrypto.cs delete mode 100644 ChocolArm64/Instructions/InstEmitSimdCvt.cs delete mode 100644 ChocolArm64/Instructions/InstEmitSimdHash.cs delete mode 100644 ChocolArm64/Instructions/InstEmitSimdHelper.cs delete mode 100644 ChocolArm64/Instructions/InstEmitSimdLogical.cs delete mode 100644 ChocolArm64/Instructions/InstEmitSimdMemory.cs delete mode 100644 ChocolArm64/Instructions/InstEmitSimdMove.cs delete mode 100644 ChocolArm64/Instructions/InstEmitSimdShift.cs delete mode 100644 ChocolArm64/Instructions/InstEmitSystem.cs delete mode 100644 ChocolArm64/Instructions/InstEmitter.cs delete mode 100644 ChocolArm64/Instructions/SoftFallback.cs delete mode 100644 ChocolArm64/Instructions/SoftFloat.cs delete mode 100644 ChocolArm64/Instructions/VectorHelper.cs delete mode 100644 ChocolArm64/IntermediateRepresentation/BasicBlock.cs delete mode 100644 ChocolArm64/IntermediateRepresentation/ILLabel.cs delete mode 100644 ChocolArm64/IntermediateRepresentation/Operation.cs delete mode 100644 ChocolArm64/IntermediateRepresentation/OperationType.cs delete mode 100644 ChocolArm64/IntermediateRepresentation/RegisterMask.cs delete mode 100644 ChocolArm64/Memory/CompareExchange128.cs delete mode 100644 ChocolArm64/Memory/IMemory.cs delete mode 100644 ChocolArm64/Memory/MemoryHelper.cs delete mode 100644 ChocolArm64/Memory/MemoryManagement.cs delete mode 100644 ChocolArm64/Memory/MemoryManagementUnix.cs delete mode 100644 ChocolArm64/Memory/MemoryManagementWindows.cs delete mode 100644 ChocolArm64/Memory/MemoryManager.cs delete mode 100644 ChocolArm64/Memory/MemoryProtection.cs delete mode 100644 ChocolArm64/Memory/MemoryProtectionException.cs delete mode 100644 ChocolArm64/OpCodeTable.cs delete mode 100644 ChocolArm64/Optimizations.cs delete mode 100644 ChocolArm64/State/Aarch32Mode.cs delete mode 100644 ChocolArm64/State/CpuThreadState.cs delete mode 100644 ChocolArm64/State/ExecutionMode.cs delete mode 100644 ChocolArm64/State/FpExc.cs delete mode 100644 ChocolArm64/State/FpType.cs delete mode 100644 ChocolArm64/State/Fpcr.cs delete mode 100644 ChocolArm64/State/Fpsr.cs delete mode 100644 ChocolArm64/State/PState.cs delete mode 100644 ChocolArm64/State/Register.cs delete mode 100644 ChocolArm64/State/RegisterAlias.cs delete mode 100644 ChocolArm64/State/RegisterConsts.cs delete mode 100644 ChocolArm64/State/RegisterSize.cs delete mode 100644 ChocolArm64/State/RegisterType.cs delete mode 100644 ChocolArm64/State/RoundMode.cs delete mode 100644 ChocolArm64/Translation/CallType.cs delete mode 100644 ChocolArm64/Translation/ILEmitterCtx.cs delete mode 100644 ChocolArm64/Translation/ILGeneratorEx.cs delete mode 100644 ChocolArm64/Translation/RegisterUsage.cs delete mode 100644 ChocolArm64/Translation/TranslatedSub.cs delete mode 100644 ChocolArm64/Translation/TranslatedSubBuilder.cs delete mode 100644 ChocolArm64/Translation/TranslationTier.cs delete mode 100644 ChocolArm64/Translation/Translator.cs delete mode 100644 ChocolArm64/Translation/TranslatorCache.cs delete mode 100644 ChocolArm64/Translation/TranslatorQueue.cs delete mode 100644 ChocolArm64/Translation/TranslatorQueueItem.cs diff --git a/ARMeilleure/ARMeilleure.csproj b/ARMeilleure/ARMeilleure.csproj index 15e5c027..4f55243f 100644 --- a/ARMeilleure/ARMeilleure.csproj +++ b/ARMeilleure/ARMeilleure.csproj @@ -1,9 +1,8 @@ - netcoreapp2.1 + netcoreapp3.0 win-x64;osx-x64;linux-x64 - latest diff --git a/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs b/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs index 44659e80..c411a6d3 100644 --- a/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs +++ b/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs @@ -1033,14 +1033,13 @@ namespace ARMeilleure.Instructions } } - public static void Fnmadd_S(ArmEmitterContext context) + public static void Fnmadd_S(ArmEmitterContext context) // Fused. { OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; int sizeF = op.Size & 1; - OperandType type = sizeF != 0 ? OperandType.FP64 - : OperandType.FP32; + OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32; Operand ne = context.VectorExtract(type, GetVec(op.Rn), 0); Operand me = context.VectorExtract(type, GetVec(op.Rm), 0); @@ -1051,14 +1050,13 @@ namespace ARMeilleure.Instructions context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0)); } - public static void Fnmsub_S(ArmEmitterContext context) + public static void Fnmsub_S(ArmEmitterContext context) // Fused. { OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; int sizeF = op.Size & 1; - OperandType type = sizeF != 0 ? OperandType.FP64 - : OperandType.FP32; + OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32; Operand ne = context.VectorExtract(type, GetVec(op.Rn), 0); Operand me = context.VectorExtract(type, GetVec(op.Rm), 0); diff --git a/ARMeilleure/Instructions/SoftFloat.cs b/ARMeilleure/Instructions/SoftFloat.cs index 7358e6b2..af22c85d 100644 --- a/ARMeilleure/Instructions/SoftFloat.cs +++ b/ARMeilleure/Instructions/SoftFloat.cs @@ -1073,10 +1073,7 @@ namespace ARMeilleure.Instructions } else { - // TODO: When available, use: T MathF.FusedMultiplyAdd(T, T, T); - // https://github.com/dotnet/corefx/issues/31903 - - result = valueA + (value1 * value2); + result = MathF.FusedMultiplyAdd(value1, value2, valueA); if ((context.Fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result)) { @@ -1256,10 +1253,7 @@ namespace ARMeilleure.Instructions } else { - // TODO: When available, use: T MathF.FusedMultiplyAdd(T, T, T); - // https://github.com/dotnet/corefx/issues/31903 - - result = 2f + (value1 * value2); + result = MathF.FusedMultiplyAdd(value1, value2, 2f); if ((context.Fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result)) { @@ -1388,10 +1382,7 @@ namespace ARMeilleure.Instructions } else { - // TODO: When available, use: T MathF.FusedMultiplyAdd(T, T, T); - // https://github.com/dotnet/corefx/issues/31903 - - result = (3f + (value1 * value2)) / 2f; + result = MathF.FusedMultiplyAdd(value1, value2, 3f) / 2f; if ((context.Fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result)) { @@ -2142,10 +2133,7 @@ namespace ARMeilleure.Instructions } else { - // TODO: When available, use: T Math.FusedMultiplyAdd(T, T, T); - // https://github.com/dotnet/corefx/issues/31903 - - result = valueA + (value1 * value2); + result = Math.FusedMultiplyAdd(value1, value2, valueA); if ((context.Fpcr & FPCR.Fz) != 0 && double.IsSubnormal(result)) { @@ -2323,10 +2311,7 @@ namespace ARMeilleure.Instructions } else { - // TODO: When available, use: T Math.FusedMultiplyAdd(T, T, T); - // https://github.com/dotnet/corefx/issues/31903 - - result = 2d + (value1 * value2); + result = Math.FusedMultiplyAdd(value1, value2, 2d); if ((context.Fpcr & FPCR.Fz) != 0 && double.IsSubnormal(result)) { @@ -2455,10 +2440,7 @@ namespace ARMeilleure.Instructions } else { - // TODO: When available, use: T Math.FusedMultiplyAdd(T, T, T); - // https://github.com/dotnet/corefx/issues/31903 - - result = (3d + (value1 * value2)) / 2d; + result = Math.FusedMultiplyAdd(value1, value2, 3d) / 2d; if ((context.Fpcr & FPCR.Fz) != 0 && double.IsSubnormal(result)) { diff --git a/ARMeilleure/Memory/IMemoryManager.cs b/ARMeilleure/Memory/IMemoryManager.cs deleted file mode 100644 index bcee5db2..00000000 --- a/ARMeilleure/Memory/IMemoryManager.cs +++ /dev/null @@ -1,40 +0,0 @@ -using ARMeilleure.State; -using System; - -namespace ARMeilleure.Memory -{ - public interface IMemoryManager : IMemory, IDisposable - { - void Map(long va, long pa, long size); - - void Unmap(long position, long size); - - bool IsMapped(long position); - - long GetPhysicalAddress(long virtualAddress); - - bool IsRegionModified(long position, long size); - - bool TryGetHostAddress(long position, long size, out IntPtr ptr); - - bool IsValidPosition(long position); - - bool AtomicCompareExchangeInt32(long position, int expected, int desired); - - int AtomicIncrementInt32(long position); - - int AtomicDecrementInt32(long position); - - byte[] ReadBytes(long position, long size); - - void ReadBytes(long position, byte[] data, int startIndex, int size); - - void WriteVector128(long position, V128 value); - - void WriteBytes(long position, byte[] data); - - void WriteBytes(long position, byte[] data, int startIndex, int size); - - void CopyBytes(long src, long dst, long size); - } -} \ No newline at end of file diff --git a/ARMeilleure/Memory/MemoryHelper.cs b/ARMeilleure/Memory/MemoryHelper.cs index 71ddac23..8e310d4d 100644 --- a/ARMeilleure/Memory/MemoryHelper.cs +++ b/ARMeilleure/Memory/MemoryHelper.cs @@ -7,7 +7,7 @@ namespace ARMeilleure.Memory { public static class MemoryHelper { - public static void FillWithZeros(IMemoryManager memory, long position, int size) + public static void FillWithZeros(MemoryManager memory, long position, int size) { int size8 = size & ~(8 - 1); @@ -22,7 +22,7 @@ namespace ARMeilleure.Memory } } - public unsafe static T Read(IMemoryManager memory, long position) where T : struct + public unsafe static T Read(MemoryManager memory, long position) where T : struct { long size = Marshal.SizeOf(); @@ -34,7 +34,7 @@ namespace ARMeilleure.Memory } } - public unsafe static void Write(IMemoryManager memory, long position, T value) where T : struct + public unsafe static void Write(MemoryManager memory, long position, T value) where T : struct { long size = Marshal.SizeOf(); @@ -48,7 +48,7 @@ namespace ARMeilleure.Memory memory.WriteBytes(position, data); } - public static string ReadAsciiString(IMemoryManager memory, long position, long maxSize = -1) + public static string ReadAsciiString(MemoryManager memory, long position, long maxSize = -1) { using (MemoryStream ms = new MemoryStream()) { diff --git a/ARMeilleure/Memory/MemoryManager.cs b/ARMeilleure/Memory/MemoryManager.cs index 12c11843..c6224988 100644 --- a/ARMeilleure/Memory/MemoryManager.cs +++ b/ARMeilleure/Memory/MemoryManager.cs @@ -7,7 +7,7 @@ using static ARMeilleure.Memory.MemoryManagement; namespace ARMeilleure.Memory { - public unsafe class MemoryManager : IMemoryManager + public unsafe class MemoryManager { public const int PageBits = 12; public const int PageSize = 1 << PageBits; diff --git a/ARMeilleure/State/ExecutionContext.cs b/ARMeilleure/State/ExecutionContext.cs index 22cfcb69..40676680 100644 --- a/ARMeilleure/State/ExecutionContext.cs +++ b/ARMeilleure/State/ExecutionContext.cs @@ -3,7 +3,7 @@ using System.Diagnostics; namespace ARMeilleure.State { - public class ExecutionContext : IExecutionContext + public class ExecutionContext { private const int MinCountForCheck = 40000; diff --git a/ARMeilleure/State/IExecutionContext.cs b/ARMeilleure/State/IExecutionContext.cs deleted file mode 100644 index df91b7a1..00000000 --- a/ARMeilleure/State/IExecutionContext.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; - -namespace ARMeilleure.State -{ - public interface IExecutionContext : IDisposable - { - uint CtrEl0 { get; } - uint DczidEl0 { get; } - - ulong CntfrqEl0 { get; set; } - ulong CntpctEl0 { get; } - - long TpidrEl0 { get; set; } - long Tpidr { get; set; } - - FPCR Fpcr { get; set; } - FPSR Fpsr { get; set; } - - bool IsAarch32 { get; set; } - - bool Running { get; set; } - - event EventHandler Interrupt; - event EventHandler Break; - event EventHandler SupervisorCall; - event EventHandler Undefined; - - ulong GetX(int index); - void SetX(int index, ulong value); - - V128 GetV(int index); - - bool GetPstateFlag(PState flag); - - void RequestInterrupt(); - } -} \ No newline at end of file diff --git a/ARMeilleure/Translation/ITranslator.cs b/ARMeilleure/Translation/ITranslator.cs deleted file mode 100644 index 1063d3a6..00000000 --- a/ARMeilleure/Translation/ITranslator.cs +++ /dev/null @@ -1,9 +0,0 @@ -using ARMeilleure.State; - -namespace ARMeilleure.Translation -{ - public interface ITranslator - { - void Execute(IExecutionContext context, ulong address); - } -} \ No newline at end of file diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs index 6a745121..6531e9f0 100644 --- a/ARMeilleure/Translation/Translator.cs +++ b/ARMeilleure/Translation/Translator.cs @@ -12,7 +12,7 @@ using static ARMeilleure.IntermediateRepresentation.OperandHelper; namespace ARMeilleure.Translation { - public class Translator : ITranslator + public class Translator { private const ulong CallFlag = InstEmitFlowHelper.CallFlag; @@ -54,10 +54,8 @@ namespace ARMeilleure.Translation } } - public void Execute(IExecutionContext ctx, ulong address) + public void Execute(State.ExecutionContext context, ulong address) { - State.ExecutionContext context = (State.ExecutionContext)ctx; - if (Interlocked.Increment(ref _threadCount) == 1) { Thread backgroundTranslatorThread = new Thread(TranslateQueuedSubs); 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 @@ - - - - netcoreapp2.1 - win-x64;osx-x64;linux-x64 - Debug;Release;Profile Debug;Profile Release - - - - true - - - - true - TRACE;USE_PROFILING - false - - - - true - - - - true - TRACE;USE_PROFILING - true - - - - - - - - - - - - - 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 OpCodes { get; private set; } - - public Block() - { - OpCodes = new List(); - } - - 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 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 _opActivators; - - static Decoder() - { - _opActivators = new ConcurrentDictionary(); - } - - 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 blocks = new List(); - - Queue workQueue = new Queue(); - - Dictionary visited = new Dictionary(); - - 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 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 AesInvMixColumns(Vector128 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 AesInvShiftRows(Vector128 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 AesInvSubBytes(Vector128 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 AesMixColumns(Vector128 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 AesShiftRows(Vector128 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 AesSubBytes(Vector128 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 op, byte[] state) - { - if (!Sse2.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - fixed (byte* ptr = &state[0]) - { - Sse2.Store(ptr, Sse.StaticCast(op)); - } - } - - private unsafe static void FromByteArrayToVector(byte[] state, ref Vector128 op) - { - if (!Sse2.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - fixed (byte* ptr = &state[0]) - { - op = Sse.StaticCast(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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128), typeof(byte) }; - Type[] typesMulAdd = new Type[] { typeof(Vector128), typeof(Vector128) }; - - 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), typeof(Vector128), typeof(byte) }; - Type[] typesMulAdd = new Type[] { typeof(Vector128), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128), typeof(byte) }; - Type[] typesMulSub = new Type[] { typeof(Vector128), typeof(Vector128) }; - - 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), typeof(Vector128), typeof(byte) }; - Type[] typesMulSub = new Type[] { typeof(Vector128), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128), typeof(byte) }; - Type[] typesMul = new Type[] { typeof(Vector128), typeof(Vector128) }; - - 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), typeof(Vector128), typeof(byte) }; - Type[] typesMul = new Type[] { typeof(Vector128), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - 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), typeof(Vector128) }; - 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), typeof(Vector128) }; - 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), typeof(Vector128) } - : new Type[] { typeof(Vector128), typeof(Vector128) }; - - 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) } - : new Type[] { typeof(Vector128) }; - - 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), typeof(Vector128), typeof(Vector128) }; - Type[] typesMul = new Type[] { typeof(Vector128), typeof(Vector128) }; - Type[] typesShs = new Type[] { typeof(Vector128), 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - 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), typeof(Vector128) }; - 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), typeof(Vector128) }; - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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) }; - - 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) }; - - 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), typeof(Vector128) }; - Type[] typesRndCvt = new Type[] { typeof(Vector128) }; - 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), typeof(Vector128) }; - Type[] typesRndCvt = new Type[] { typeof(Vector128) }; - 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), typeof(Vector128) }; - Type[] typesAdd = new Type[] { typeof(Vector128), typeof(Vector128) }; - Type[] typesRndCvt = new Type[] { typeof(Vector128) }; - 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), typeof(Vector128) }; - Type[] typesAdd = new Type[] { typeof(Vector128), typeof(Vector128) }; - Type[] typesRndCvt = new Type[] { typeof(Vector128) }; - 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), typeof(Vector128) }; - Type[] typesCvt = new Type[] { typeof(Vector128) }; - 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), typeof(Vector128) }; - Type[] typesSrlSll = new Type[] { typeof(Vector128), typeof(byte) }; - Type[] typesCvt = new Type[] { typeof(Vector128) }; - 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), - typeof(Vector128), - typeof(Vector128), - typeof(Vector128) - }; - - public static readonly Type[] VectorUIntTypesPerSizeLog2 = new Type[] - { - typeof(Vector128), - typeof(Vector128), - typeof(Vector128), - typeof(Vector128) - }; - - [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); - } - else /* if (sizeF == 1) */ - { - type = typeof(Sse2); - baseType = typeof(Vector128); - } - - 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), typeof(Vector128) }; - - 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), typeof(Vector128), typeof(byte) }; - Type[] types = new Type[] { typeof(Vector128), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(Vector128) }; - - 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), typeof(byte) }; - Type[] typesOr = new Type[] { typeof(Vector128), typeof(Vector128) }; - - 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), typeof(Vector128) }; - Type[] typesOr = new Type[] { typeof(Vector128), typeof(Vector128) }; - 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), typeof(Vector128) }; - 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), typeof(Vector128) }; - 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 Decrypt(Vector128 value, Vector128 roundKey) - { - if (!Sse.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(Sse.Xor(value, roundKey))); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 Encrypt(Vector128 value, Vector128 roundKey) - { - if (!Sse.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(Sse.Xor(value, roundKey))); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 InverseMixColumns(Vector128 value) - { - return CryptoHelper.AesInvMixColumns(value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 MixColumns(Vector128 value) - { - return CryptoHelper.AesMixColumns(value); - } -#endregion - -#region "Sha1" - public static Vector128 HashChoose(Vector128 hash_abcd, uint hash_e, Vector128 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 HashMajority(Vector128 hash_abcd, uint hash_e, Vector128 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 HashParity(Vector128 hash_abcd, uint hash_e, Vector128 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 Sha1SchedulePart1(Vector128 w0_3, Vector128 w4_7, Vector128 w8_11) - { - if (!Sse.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - Vector128 result = new Vector128(); - - 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 Sha1SchedulePart2(Vector128 tw0_3, Vector128 w12_15) - { - if (!Sse2.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - Vector128 result = new Vector128(); - - Vector128 t = Sse.Xor(tw0_3, Sse.StaticCast( - Sse2.ShiftRightLogical128BitLane(Sse.StaticCast(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 x) - { - if (!Sse2.IsSupported) - { - throw new PlatformNotSupportedException(); - } - - uint xE3 = (uint)VectorExtractIntZx(x, (byte)3, 2); - - x = Sse.StaticCast(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast(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 HashLower(Vector128 hash_abcd, Vector128 hash_efgh, Vector128 wk) - { - return Sha256Hash(hash_abcd, hash_efgh, wk, true); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 HashUpper(Vector128 hash_efgh, Vector128 hash_abcd, Vector128 wk) - { - return Sha256Hash(hash_abcd, hash_efgh, wk, false); - } - - public static Vector128 Sha256SchedulePart1(Vector128 w0_3, Vector128 w4_7) - { - Vector128 result = new Vector128(); - - 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 Sha256SchedulePart2(Vector128 w0_3, Vector128 w8_11, Vector128 w12_15) - { - Vector128 result = new Vector128(); - - 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 Sha256Hash(Vector128 x, Vector128 y, Vector128 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 y, ref Vector128 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(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast(y), (byte)4)); - x = Sse.StaticCast(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast(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 Sse41ScalarRound(Vector128 upper, Vector128 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 Sse41ScalarRoundF(Vector128 upper, Vector128 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 Sse41VectorRound(Vector128 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 Sse41VectorRoundF(Vector128 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 Tbl1_V64( - Vector128 vector, - Vector128 tb0) - { - return Tbl(vector, 8, tb0); - } - - public static Vector128 Tbl1_V128( - Vector128 vector, - Vector128 tb0) - { - return Tbl(vector, 16, tb0); - } - - public static Vector128 Tbl2_V64( - Vector128 vector, - Vector128 tb0, - Vector128 tb1) - { - return Tbl(vector, 8, tb0, tb1); - } - - public static Vector128 Tbl2_V128( - Vector128 vector, - Vector128 tb0, - Vector128 tb1) - { - return Tbl(vector, 16, tb0, tb1); - } - - public static Vector128 Tbl3_V64( - Vector128 vector, - Vector128 tb0, - Vector128 tb1, - Vector128 tb2) - { - return Tbl(vector, 8, tb0, tb1, tb2); - } - - public static Vector128 Tbl3_V128( - Vector128 vector, - Vector128 tb0, - Vector128 tb1, - Vector128 tb2) - { - return Tbl(vector, 16, tb0, tb1, tb2); - } - - public static Vector128 Tbl4_V64( - Vector128 vector, - Vector128 tb0, - Vector128 tb1, - Vector128 tb2, - Vector128 tb3) - { - return Tbl(vector, 8, tb0, tb1, tb2, tb3); - } - - public static Vector128 Tbl4_V128( - Vector128 vector, - Vector128 tb0, - Vector128 tb1, - Vector128 tb2, - Vector128 tb3) - { - return Tbl(vector, 16, tb0, tb1, tb2, tb3); - } - - private static Vector128 Tbl(Vector128 vector, int bytes, params Vector128[] tb) - { - Vector128 res = new Vector128(); - - 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 vector, byte index) - { - if (Sse41.IsSupported) - { - return BitConverter.Int64BitsToDouble(Sse41.Extract(Sse.StaticCast(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 vector, byte index, int size) - { - if (Sse41.IsSupported) - { - if (size == 0) - { - return (sbyte)Sse41.Extract(Sse.StaticCast(vector), index); - } - else if (size == 1) - { - return (short)Sse2.Extract(Sse.StaticCast(vector), index); - } - else if (size == 2) - { - return Sse41.Extract(Sse.StaticCast(vector), index); - } - else if (size == 3) - { - return Sse41.Extract(Sse.StaticCast(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 vector, byte index, int size) - { - if (Sse41.IsSupported) - { - if (size == 0) - { - return Sse41.Extract(Sse.StaticCast(vector), index); - } - else if (size == 1) - { - return Sse2.Extract(Sse.StaticCast(vector), index); - } - else if (size == 2) - { - return Sse41.Extract(Sse.StaticCast(vector), index); - } - else if (size == 3) - { - return Sse41.Extract(Sse.StaticCast(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(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(vector), (byte)(shortIdx + 1)); - - if (size == 2) - { - return (uint)(value | (value1 << 16)); - } - - ushort value2 = Sse2.Extract(Sse.StaticCast(vector), (byte)(shortIdx + 2)); - ushort value3 = Sse2.Extract(Sse.StaticCast(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 vector, byte index) - { - if (Sse41.IsSupported) - { - return Sse41.Extract(vector, index); - } - else if (Sse2.IsSupported) - { - Vector128 shortVector = Sse.StaticCast(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 VectorInsertDouble(double value, Vector128 vector, byte index) - { - return VectorInsertInt((ulong)BitConverter.DoubleToInt64Bits(value), vector, index, 3); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 VectorInsertInt(ulong value, Vector128 vector, byte index, int size) - { - if (Sse41.IsSupported) - { - if (size == 0) - { - return Sse.StaticCast(Sse41.Insert(Sse.StaticCast(vector), (byte)value, index)); - } - else if (size == 1) - { - return Sse.StaticCast(Sse2.Insert(Sse.StaticCast(vector), (ushort)value, index)); - } - else if (size == 2) - { - return Sse.StaticCast(Sse41.Insert(Sse.StaticCast(vector), (uint)value, index)); - } - else if (size == 3) - { - return Sse.StaticCast(Sse41.Insert(Sse.StaticCast(vector), value, index)); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - } - else if (Sse2.IsSupported) - { - Vector128 shortVector = Sse.StaticCast(vector); - - int shortIdx = size == 0 - ? index >> 1 - : index << (size - 1); - - if (size == 0) - { - ushort shortVal = Sse2.Extract(Sse.StaticCast(vector), (byte)shortIdx); - - int shift = (index & 1) * 8; - - shortVal &= (ushort)(0xff00 >> shift); - - shortVal |= (ushort)((byte)value << shift); - - return Sse.StaticCast(Sse2.Insert(shortVector, shortVal, (byte)shortIdx)); - } - else if (size == 1) - { - return Sse.StaticCast(Sse2.Insert(Sse.StaticCast(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(shortVector); - } - else - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - } - - throw new PlatformNotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 VectorInsertSingle(float value, Vector128 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 shortVector = Sse.StaticCast(vector); - - shortVector = Sse2.Insert(shortVector, low, (byte)(index * 2 + 0)); - shortVector = Sse2.Insert(shortVector, high, (byte)(index * 2 + 1)); - - return Sse.StaticCast(shortVector); - } - - throw new PlatformNotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 Sse41VectorInsertScalarSingle(float value, Vector128 vector) - { - // Note: 0b1110 is the mask to zero the upper bits. - return Sse41.Insert(vector, value, 0b1110); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 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 _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 Predecessors { get; } - - public BasicBlock(int index = 0) - { - Index = index; - - _operations = new List(); - - Predecessors = new List(); - } - - 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(0); - - if (IsRegIndex(index)) - { - long intMask = 0; - long vecMask = 0; - - switch (operation.GetArg(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(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 - { - 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(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(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(MemoryManager memory, long position) where T : struct - { - long size = Marshal.SizeOf(); - - byte[] data = memory.ReadBytes(position, size); - - fixed (byte* ptr = data) - { - return Marshal.PtrToStructure((IntPtr)ptr); - } - } - - public unsafe static void Write(MemoryManager memory, long position, T value) where T : struct - { - long size = Marshal.SizeOf(); - - byte[] data = new byte[size]; - - fixed (byte* ptr = data) - { - Marshal.StructureToPtr(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 AtomicReadInt128(long position) - { - if ((position & 0xf) != 0) - { - AbortWithAlignmentFault(position); - } - - IntPtr ptr = Translate(position); - - InterlockedRead128(ptr, out ulong low, out ulong high); - - Vector128 vector = default(Vector128); - - 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 ReadVector8(long position) - { - if (Sse2.IsSupported) - { - return Sse.StaticCast(Sse2.SetVector128(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ReadByte(position))); - } - else - { - Vector128 value = VectorHelper.VectorSingleZero(); - - value = VectorHelper.VectorInsertInt(ReadByte(position), value, 0, 0); - - return value; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector128 ReadVector16(long position) - { - if (Sse2.IsSupported && (position & 1) == 0) - { - return Sse.StaticCast(Sse2.Insert(Sse2.SetZeroVector128(), ReadUInt16(position), 0)); - } - else - { - Vector128 value = VectorHelper.VectorSingleZero(); - - value = VectorHelper.VectorInsertInt(ReadUInt16(position), value, 0, 1); - - return value; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector128 ReadVector32(long position) - { - if (Sse.IsSupported && (position & 3) == 0) - { - return Sse.LoadScalarVector128((float*)Translate(position)); - } - else - { - Vector128 value = VectorHelper.VectorSingleZero(); - - value = VectorHelper.VectorInsertInt(ReadUInt32(position), value, 0, 2); - - return value; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector128 ReadVector64(long position) - { - if (Sse2.IsSupported && (position & 7) == 0) - { - return Sse.StaticCast(Sse2.LoadScalarVector128((double*)Translate(position))); - } - else - { - Vector128 value = VectorHelper.VectorSingleZero(); - - value = VectorHelper.VectorInsertInt(ReadUInt64(position), value, 0, 3); - - return value; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector128 ReadVector128(long position) - { - if (Sse.IsSupported && (position & 15) == 0) - { - return Sse.LoadVector128((float*)Translate(position)); - } - else - { - Vector128 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 value) - { - if (Sse41.IsSupported) - { - WriteByte(position, Sse41.Extract(Sse.StaticCast(value), 0)); - } - else if (Sse2.IsSupported) - { - WriteByte(position, (byte)Sse2.Extract(Sse.StaticCast(value), 0)); - } - else - { - WriteByte(position, (byte)VectorHelper.VectorExtractIntZx(value, 0, 0)); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector16(long position, Vector128 value) - { - if (Sse2.IsSupported) - { - WriteUInt16(position, Sse2.Extract(Sse.StaticCast(value), 0)); - } - else - { - WriteUInt16(position, (ushort)VectorHelper.VectorExtractIntZx(value, 0, 1)); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector32(long position, Vector128 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 value) - { - if (Sse2.IsSupported && (position & 7) == 0) - { - Sse2.StoreScalar((double*)TranslateWrite(position), Sse.StaticCast(value)); - } - else - { - WriteUInt64(position, VectorHelper.VectorExtractIntZx(value, 0, 3)); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector128Internal(long position, Vector128 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 _allInstA32 = new List(); - private static List _allInstT32 = new List(); - private static List _allInstA64 = new List(); - - 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>101110000xxxxx01011101<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>00111110011101<1xxxxx110011xxxxxxxxxx", InstEmit.Fmls_V, typeof(OpCodeSimdReg64)); - SetA64("0>00111111011100<1xxxxx110111xxxxxxxxxx", InstEmit.Fmul_V, typeof(OpCodeSimdReg64)); - SetA64("0>00111110011100<1xxxxx110111xxxxxxxxxx", InstEmit.Fmulx_V, typeof(OpCodeSimdReg64)); - SetA64("0>10111111011101<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 allInsts) - { - List[] tmp = new List[FastLookupSize]; - - for (int i = 0; i < FastLookupSize; i++) - { - tmp[i] = new List(); - } - - 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 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 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 Interrupt; - public event EventHandler Break; - public event EventHandler SupervisorCall; - public event EventHandler 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 - { - 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 _labels; - - private Dictionary _irLabels; - - private List _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(); - - _irLabels = new Dictionary(); - - _irBlocks = new List(); - - 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 _branchOps = new Dictionary() - { - { 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(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 visited = new HashSet(); - - Stack blockStack = new Stack(); - - List postOrderBlocks = new List(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 _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(); - - Dictionary labels = new Dictionary(); - - 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(0)); - break; - - case OperationType.CallVirtual: - generator.Emit(OpCodes.Callvirt, operation.GetArg(0)); - break; - - case OperationType.IL: - generator.Emit(operation.GetArg(0)); - break; - - case OperationType.ILBranch: - generator.Emit(operation.GetArg(0), GetLabel(operation.GetArg(1))); - break; - - case OperationType.LoadArgument: - generator.EmitLdarg(operation.GetArg(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(0)); - break; - - case OperationType.LoadLocal: - EmitLoadLocal( - generator, - operation.GetArg(0), - operation.GetArg(1), - operation.GetArg(2)); - break; - - case OperationType.MarkLabel: - generator.MarkLabel(GetLabel(operation.GetArg(0))); - break; - - case OperationType.StoreContext: - EmitStoreContext(generator, operation.Parent); - break; - - case OperationType.StoreLocal: - EmitStoreLocal( - generator, - operation.GetArg(0), - operation.GetArg(1), - operation.GetArg(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); - } - - 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 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 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 node, int size) - { - Subroutine = subroutine; - Size = size; - - UpdateNode(node); - } - - public void UpdateNode(LinkedListNode node) - { - Node = node; - - Timestamp = GetTimestamp(); - } - } - - private ConcurrentDictionary _cache; - - private LinkedList _sortedCache; - - private int _totalSize; - - public TranslatorCache() - { - _cache = new ConcurrentDictionary(); - - _sortedCache = new LinkedList(); - } - - public TranslatedSub GetOrAdd(long position, TranslatedSub subroutine, int size) - { - ClearCacheIfNeeded(); - - lock (_sortedCache) - { - LinkedListNode 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 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 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[] _translationQueue; - - private ManualResetEvent _queueDataReceivedEvent; - - private bool _signaled; - - public TranslatorQueue() - { - _translationQueue = new ConcurrentStack[(int)TranslationTier.Count]; - - for (int prio = 0; prio < _translationQueue.Length; prio++) - { - _translationQueue[prio] = new ConcurrentStack(); - } - - _queueDataReceivedEvent = new ManualResetEvent(false); - } - - public void Enqueue(long position, ExecutionMode mode, TranslationTier tier, bool isComplete) - { - TranslatorQueueItem item = new TranslatorQueueItem(position, mode, tier, isComplete); - - ConcurrentStack 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 diff --git a/README.md b/README.md index 13f91eb6..2af97c3c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@

- Ryujinx + Ryujinx - + @@ -21,12 +21,12 @@ ## Usage -To run this emulator, you need the [.NET Core 2.1 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet-core). +To run this emulator, you need the [.NET Core 3.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet-core). -If you use a pre-built version, you can use the graphical interface to run your games and homebrew. +If you use a pre-built version, you can use the graphical interface to run your games and homebrew. -If you build it yourself you will need to: -Run `dotnet run -c Release -- path\to\homebrew.nro` inside the Ryujinx project folder to run homebrew apps. +If you build it yourself you will need to: +Run `dotnet run -c Release -- path\to\homebrew.nro` inside the Ryujinx project folder to run homebrew apps. Run `dotnet run -c Release -- path\to\game.nsp/xci` to run official games. Every file related to Ryujinx is stored in the `RyuFs` folder. Located in `C:\Users\USERNAME\AppData\Roaming\` for Windows, `/home/USERNAME/.config` for Linux or `/Users/USERNAME/Library/Application Support/` for macOS. It can also be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI. @@ -39,48 +39,46 @@ The latest automatic build for Windows, macOS, and Linux can be found on the [Of ## Requirements - - **Switch Keys** - - Everything on the Switch is encrypted, so if you want to run anything other than homebrew, you have to dump encryption keys from your console. To get more information please take a look at our [Keys Documentation](KEYS.md) *(Outdated)* - - - **FFmpeg Dependencies** - + - **Switch Keys** + + Everything on the Switch is encrypted, so if you want to run anything other than homebrew, you have to dump encryption keys from your console. To get more information please take a look at our [Keys Documentation](KEYS.md) *(Outdated)*. + + - **FFmpeg Dependencies** + Ryujinx has a basic implementation of `NVDEC`, a video decoder used by the Switch's GPU. Many games include videos that use it, so you need to download [Zeranoe's FFmpeg Builds](http://ffmpeg.zeranoe.com/builds/) for **Shared** linking and your computer's operating system. When it's done, extract the contents of the `bin` folder directly into your Ryujinx folder. - - - **System Titles** - + + - **System Titles** + Some of our System Module implementations, like `time`, require [System Data Archives](https://switchbrew.org/wiki/Title_list#System_Data_Archives). You can install them by mounting your nand partition using [HacDiskMount](https://switchtools.sshnuke.net/) and copying the content to `RyuFs/nand/system`. - + - **Executables** - + Ryujinx is able to run both official games and homebrew. - + Homebrew is available on many websites, such as the [Switch Appstore](https://www.switchbru.com/appstore/). - + A hacked Switch is needed to dump games, which you can learn how to do [here](https://nh-server.github.io/switch-guide/). Once you've hacked your Switch, you need to dump your own games with [NxDumpTool](https://github.com/DarkMatterCore/nxdumptool) to get an XCI dump or [SwitchSDTool](https://github.com/CaitSith2/SwitchSDTool) to get an NSP dump. ## Features - - **Audio** - + - **Audio** + Everything for audio is partially supported. We currently use a C# wrapper for [libsoundio](http://libsound.io/), and we support [OpenAL](https://openal.org/downloads/OpenAL11CoreSDK.zip) (installation needed) too as a fallback. Our current Opus implementation is pretty incomplete. -- **CPU** +- **CPU** - The CPU emulator, ARMeilleure, emulates an ARMv8 CPU, and currently only has support for the new 64-bit ARMv8 instructions (with a few instructions still missing). It translates the ARM code to a custom IR, performs a few optimizations, and turns that into x86 code. To handle that, we use our own JIT called ARMeilleure, which uses the custom IR and compiles the code to x86. - - ChocolArm is the old ARM emulator which worked by translating the ARM code to .NET IL. The runtime JIT then compiles that to the platform CPU code. On .NET Core, the JIT is called RyuJIT, hence the project name, Ryujinx. It is being replaced by ARMeilleure, but can still be enabled inside the configuration menu. + The CPU emulator, ARMeilleure, emulates an ARMv8 CPU, and currently only has support for the new 64-bit ARMv8 instructions (with a few instructions still missing). It translates the ARM code to a custom IR, performs a few optimizations, and turns that into x86 code. To handle that, we use our own JIT called ARMeilleure, which uses the custom IR and compiles the code to x86. -- **GPU** +- **GPU** The GPU emulator emulates the Switch's Maxwell GPU using the OpenGL API (version 4.2 minimum) through a custom build of OpenTK. - -- **Input** + +- **Input** We currently have support for keyboard, mouse, touch input, JoyCon input support emulated through the keyboard, and some controllers too. You can set up everything inside the configuration menu. - -- **Configuration** - + +- **Configuration** + The emulator has settings for dumping shaders, enabling or disabling some logging, remapping controllers, and more. You can configure all of them through the graphical interface or manually through the config file, `Config.json`. For more information [you can go here](CONFIG.md) *(Outdated)*. diff --git a/Ryujinx.Audio/Ryujinx.Audio.csproj b/Ryujinx.Audio/Ryujinx.Audio.csproj index e25066ee..588b6918 100644 --- a/Ryujinx.Audio/Ryujinx.Audio.csproj +++ b/Ryujinx.Audio/Ryujinx.Audio.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + netcoreapp3.0 win-x64;osx-x64;linux-x64 Debug;Release;Profile Debug;Profile Release @@ -28,7 +28,7 @@ - + diff --git a/Ryujinx.Common/Ryujinx.Common.csproj b/Ryujinx.Common/Ryujinx.Common.csproj index 86c6c570..c777b402 100644 --- a/Ryujinx.Common/Ryujinx.Common.csproj +++ b/Ryujinx.Common/Ryujinx.Common.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp3.0 win-x64;osx-x64;linux-x64 Debug;Release;Profile Debug;Profile Release diff --git a/Ryujinx.Graphics/Graphics3d/Texture/ImageUtils.cs b/Ryujinx.Graphics/Graphics3d/Texture/ImageUtils.cs index ab45e985..10c36fe1 100644 --- a/Ryujinx.Graphics/Graphics3d/Texture/ImageUtils.cs +++ b/Ryujinx.Graphics/Graphics3d/Texture/ImageUtils.cs @@ -230,7 +230,7 @@ namespace Ryujinx.Graphics.Texture public static byte[] ReadTexture(IMemory memory, GalImage image, long position) { - IMemoryManager cpuMemory; + MemoryManager cpuMemory; if (memory is NvGpuVmm vmm) { @@ -238,7 +238,7 @@ namespace Ryujinx.Graphics.Texture } else { - cpuMemory = (IMemoryManager)memory; + cpuMemory = (MemoryManager)memory; } ISwizzle swizzle = TextureHelper.GetSwizzle(image); diff --git a/Ryujinx.Graphics/Graphics3d/Texture/TextureHelper.cs b/Ryujinx.Graphics/Graphics3d/Texture/TextureHelper.cs index 22b803db..e07eb037 100644 --- a/Ryujinx.Graphics/Graphics3d/Texture/TextureHelper.cs +++ b/Ryujinx.Graphics/Graphics3d/Texture/TextureHelper.cs @@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Texture } } - public static (IMemoryManager Memory, long Position) GetMemoryAndPosition( + public static (MemoryManager Memory, long Position) GetMemoryAndPosition( IMemory memory, long position) { @@ -47,7 +47,7 @@ namespace Ryujinx.Graphics.Texture return (vmm.Memory, vmm.GetPhysicalAddress(position)); } - return ((IMemoryManager)memory, position); + return ((MemoryManager)memory, position); } } } diff --git a/Ryujinx.Graphics/Memory/NvGpuVmm.cs b/Ryujinx.Graphics/Memory/NvGpuVmm.cs index d8ccd6c7..c72b82e3 100644 --- a/Ryujinx.Graphics/Memory/NvGpuVmm.cs +++ b/Ryujinx.Graphics/Memory/NvGpuVmm.cs @@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Memory private const int PtLvl0Bit = PtPageBits + PtLvl1Bits; private const int PtLvl1Bit = PtPageBits; - public IMemoryManager Memory { get; private set; } + public MemoryManager Memory { get; private set; } private NvGpuVmmCache _cache; @@ -32,7 +32,7 @@ namespace Ryujinx.Graphics.Memory private long[][] _pageTable; - public NvGpuVmm(IMemoryManager memory) + public NvGpuVmm(MemoryManager memory) { Memory = memory; diff --git a/Ryujinx.Graphics/Memory/NvGpuVmmCache.cs b/Ryujinx.Graphics/Memory/NvGpuVmmCache.cs index 37ead4e0..2a505443 100644 --- a/Ryujinx.Graphics/Memory/NvGpuVmmCache.cs +++ b/Ryujinx.Graphics/Memory/NvGpuVmmCache.cs @@ -12,9 +12,9 @@ namespace Ryujinx.Graphics.Memory private ConcurrentDictionary[] _cachedPages; - private IMemoryManager _memory; + private MemoryManager _memory; - public NvGpuVmmCache(IMemoryManager memory) + public NvGpuVmmCache(MemoryManager memory) { _memory = memory; diff --git a/Ryujinx.Graphics/Ryujinx.Graphics.csproj b/Ryujinx.Graphics/Ryujinx.Graphics.csproj index e2bf1693..4467fcdd 100644 --- a/Ryujinx.Graphics/Ryujinx.Graphics.csproj +++ b/Ryujinx.Graphics/Ryujinx.Graphics.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + netcoreapp3.0 win-x64;osx-x64;linux-x64 Debug;Release;Profile Debug;Profile Release @@ -27,7 +27,7 @@ - + diff --git a/Ryujinx.HLE/HOS/Homebrew.cs b/Ryujinx.HLE/HOS/Homebrew.cs index 8e54f82c..dca02d91 100644 --- a/Ryujinx.HLE/HOS/Homebrew.cs +++ b/Ryujinx.HLE/HOS/Homebrew.cs @@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS public const string TemporaryNroSuffix = ".ryu_tmp.nro"; // http://switchbrew.org/index.php?title=Homebrew_ABI - public static void WriteHbAbiData(IMemoryManager memory, long position, int mainThreadHandle, string switchPath) + public static void WriteHbAbiData(MemoryManager memory, long position, int mainThreadHandle, string switchPath) { // MainThreadHandle. WriteConfigEntry(memory, ref position, 1, 0, mainThreadHandle); @@ -31,12 +31,12 @@ namespace Ryujinx.HLE.HOS } private static void WriteConfigEntry( - IMemoryManager memory, - ref long position, - int key, - int flags = 0, - long value0 = 0, - long value1 = 0) + MemoryManager memory, + ref long position, + int key, + int flags = 0, + long value0 = 0, + long value1 = 0) { memory.WriteInt32(position + 0x00, key); memory.WriteInt32(position + 0x04, flags); @@ -46,7 +46,7 @@ namespace Ryujinx.HLE.HOS position += 0x18; } - public static string ReadHbAbiNextLoadPath(IMemoryManager memory, long position) + public static string ReadHbAbiNextLoadPath(MemoryManager memory, long position) { string fileName = null; diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index 0deb7ac1..1e218c87 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -115,8 +115,6 @@ namespace Ryujinx.HLE.HOS public int GlobalAccessLogMode { get; set; } - public bool UseLegacyJit { get; set; } - internal long HidBaseAddress { get; private set; } internal FileSystemServer FsServer { get; private set; } diff --git a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs index dd36871a..ee3ace68 100644 --- a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs +++ b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs @@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Ipc public static KernelResult IpcCall( Switch device, KProcess process, - IMemoryManager memory, + MemoryManager memory, KThread thread, KClientSession session, IpcMessage request, diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs index fd80b3b9..fd2078ee 100644 --- a/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs @@ -29,7 +29,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory private LinkedList _blocks; - private IMemoryManager _cpuMemory; + private MemoryManager _cpuMemory; private Horizon _system; @@ -72,7 +72,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory private MersenneTwister _randomNumberGenerator; - public KMemoryManager(Horizon system, IMemoryManager cpuMemory) + public KMemoryManager(Horizon system, MemoryManager cpuMemory) { _system = system; _cpuMemory = cpuMemory; diff --git a/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs b/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs index e2ca44b5..4219eb75 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs @@ -1,5 +1,4 @@ using ARMeilleure.Memory; -using ARMeilleure.State; using Ryujinx.HLE.HOS.Diagnostics.Demangler; using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.Loaders.Elf; @@ -40,7 +39,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process _images = new List(); } - public string GetGuestStackTrace(IExecutionContext context) + public string GetGuestStackTrace(ARMeilleure.State.ExecutionContext context) { EnsureLoaded(); @@ -218,7 +217,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } - private void LoadMod0Symbols(IMemoryManager memory, long textOffset) + private void LoadMod0Symbols(MemoryManager memory, long textOffset) { long mod0Offset = textOffset + memory.ReadUInt32(textOffset + 4); @@ -288,7 +287,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } - private ElfSymbol GetSymbol(IMemoryManager memory, long address, long strTblAddr) + private ElfSymbol GetSymbol(MemoryManager memory, long address, long strTblAddr) { int nameIndex = memory.ReadInt32(address + 0); int info = memory.ReadByte (address + 4); diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index c6283afd..1b16d79a 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -78,9 +78,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public bool IsPaused { get; private set; } - public IMemoryManager CpuMemory { get; private set; } + public MemoryManager CpuMemory { get; private set; } - public ITranslator Translator { get; private set; } + public Translator Translator { get; private set; } private SvcHandler _svcHandler; @@ -791,7 +791,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } - public void SubscribeThreadEventHandlers(IExecutionContext context) + public void SubscribeThreadEventHandlers(ARMeilleure.State.ExecutionContext context) { context.Interrupt += InterruptHandler; context.SupervisorCall += _svcHandler.SvcCall; @@ -1022,18 +1022,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process bool useFlatPageTable = memRegion == MemoryRegion.Application; - if (_system.UseLegacyJit) - { - CpuMemory = new ChocolArm64.Memory.MemoryManager(_system.Device.Memory.RamPointer, addrSpaceBits, useFlatPageTable); + CpuMemory = new MemoryManager(_system.Device.Memory.RamPointer, addrSpaceBits, useFlatPageTable); - Translator = new ChocolArm64.Translation.Translator((ChocolArm64.Memory.MemoryManager)CpuMemory); - } - else - { - CpuMemory = new MemoryManager(_system.Device.Memory.RamPointer, addrSpaceBits, useFlatPageTable); - - Translator = new Translator((MemoryManager)CpuMemory); - } + Translator = new Translator(CpuMemory); MemoryManager = new KMemoryManager(_system, CpuMemory); } diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs index 7509ae04..e3a4b375 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs @@ -19,14 +19,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public void SvcCall(object sender, InstExceptionEventArgs e) { - Action svcFunc = SvcTable.GetSvcFunc(e.Id); + Action svcFunc = SvcTable.GetSvcFunc(e.Id); if (svcFunc == null) { throw new NotImplementedException($"SVC 0x{e.Id:X4} is not implemented."); } - IExecutionContext context = (IExecutionContext)sender; + ExecutionContext context = (ExecutionContext)sender; svcFunc(this, context); } diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs index b740253f..9ec0931a 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs @@ -14,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall private static Dictionary _svcFuncs64; - private static Action[] _svcTable64; + private static Action[] _svcTable64; static SvcTable() { @@ -77,10 +77,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { 0x78, nameof(SvcHandler.UnmapProcessCodeMemory64) } }; - _svcTable64 = new Action[0x80]; + _svcTable64 = new Action[0x80]; } - public static Action GetSvcFunc(int svcId) + public static Action GetSvcFunc(int svcId) { if (_svcTable64[svcId] != null) { @@ -95,9 +95,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return null; } - private static Action GenerateMethod(string svcName) + private static Action GenerateMethod(string svcName) { - Type[] argTypes = new Type[] { typeof(SvcHandler), typeof(IExecutionContext) }; + Type[] argTypes = new Type[] { typeof(SvcHandler), typeof(ExecutionContext) }; DynamicMethod method = new DynamicMethod(svcName, null, argTypes); @@ -188,7 +188,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldc_I4, byRefArgsCount + index); - MethodInfo info = typeof(IExecutionContext).GetMethod(nameof(IExecutionContext.GetX)); + MethodInfo info = typeof(ExecutionContext).GetMethod(nameof(ExecutionContext.GetX)); generator.Emit(OpCodes.Call, info); @@ -234,7 +234,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldc_I4, index); - MethodInfo info = typeof(IExecutionContext).GetMethod(nameof(IExecutionContext.GetX)); + MethodInfo info = typeof(ExecutionContext).GetMethod(nameof(ExecutionContext.GetX)); generator.Emit(OpCodes.Call, info); @@ -250,7 +250,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldc_I4, byRefArgsCount + index); - MethodInfo info = typeof(IExecutionContext).GetMethod(nameof(IExecutionContext.GetX)); + MethodInfo info = typeof(ExecutionContext).GetMethod(nameof(ExecutionContext.GetX)); generator.Emit(OpCodes.Call, info); @@ -288,7 +288,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall ConvertToFieldType(retType); - MethodInfo info = typeof(IExecutionContext).GetMethod(nameof(IExecutionContext.SetX)); + MethodInfo info = typeof(ExecutionContext).GetMethod(nameof(ExecutionContext.SetX)); generator.Emit(OpCodes.Call, info); } @@ -301,7 +301,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall ConvertToFieldType(locals[index].LocalType); - MethodInfo info = typeof(IExecutionContext).GetMethod(nameof(IExecutionContext.SetX)); + MethodInfo info = typeof(ExecutionContext).GetMethod(nameof(ExecutionContext.SetX)); generator.Emit(OpCodes.Call, info); } @@ -313,14 +313,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall generator.Emit(OpCodes.Ldc_I4, outRegIndex++); generator.Emit(OpCodes.Ldc_I8, 0L); - MethodInfo info = typeof(IExecutionContext).GetMethod(nameof(IExecutionContext.SetX)); + MethodInfo info = typeof(ExecutionContext).GetMethod(nameof(ExecutionContext.SetX)); generator.Emit(OpCodes.Call, info); } generator.Emit(OpCodes.Ret); - return (Action)method.CreateDelegate(typeof(Action)); + return (Action)method.CreateDelegate(typeof(Action)); } private static void CheckIfTypeIsSupported(Type type, string svcName) diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs index e49da023..0908de10 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs @@ -348,7 +348,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidThread; } - IMemoryManager memory = currentProcess.CpuMemory; + MemoryManager memory = currentProcess.CpuMemory; memory.WriteUInt64((long)address + 0x0, thread.Context.GetX(0)); memory.WriteUInt64((long)address + 0x8, thread.Context.GetX(1)); @@ -427,7 +427,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.Success; } - private static int GetPsr(IExecutionContext context) + private static int GetPsr(ExecutionContext context) { return (context.GetPstateFlag(PState.NFlag) ? (1 << 31) : 0) | (context.GetPstateFlag(PState.ZFlag) ? (1 << 30) : 0) | diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs index 54d5d06c..d4965b41 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs @@ -1,5 +1,4 @@ using ARMeilleure.Memory; -using ARMeilleure.State; using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Process; @@ -17,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public Thread HostThread { get; private set; } - public IExecutionContext Context { get; private set; } + public ARMeilleure.State.ExecutionContext Context { get; private set; } public long AffinityMask { get; set; } @@ -159,14 +158,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading HostThread = new Thread(() => ThreadStart(entrypoint)); - if (System.UseLegacyJit) - { - Context = new ChocolArm64.State.CpuThreadState(); - } - else - { - Context = new ARMeilleure.State.ExecutionContext(); - } + Context = new ARMeilleure.State.ExecutionContext(); bool isAarch32 = (Owner.MmuFlags & 1) == 0; diff --git a/Ryujinx.HLE/HOS/ServiceCtx.cs b/Ryujinx.HLE/HOS/ServiceCtx.cs index df74ba0a..fa6cfca3 100644 --- a/Ryujinx.HLE/HOS/ServiceCtx.cs +++ b/Ryujinx.HLE/HOS/ServiceCtx.cs @@ -11,7 +11,7 @@ namespace Ryujinx.HLE.HOS { public Switch Device { get; } public KProcess Process { get; } - public IMemoryManager Memory { get; } + public MemoryManager Memory { get; } public KThread Thread { get; } public KClientSession Session { get; } public IpcMessage Request { get; } @@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS public ServiceCtx( Switch device, KProcess process, - IMemoryManager memory, + MemoryManager memory, KThread thread, KClientSession session, IpcMessage request, diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/IAudioRenderer.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/IAudioRenderer.cs index 0075fd5f..aa9b6e51 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/IAudioRenderer.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/IAudioRenderer.cs @@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRendererManager private KEvent _updateEvent; - private IMemoryManager _memory; + private MemoryManager _memory; private IAalOutput _audioOut; @@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRendererManager public IAudioRenderer( Horizon system, - IMemoryManager memory, + MemoryManager memory, IAalOutput audioOut, AudioRendererParameter Params) { diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/VoiceContext.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/VoiceContext.cs index 4bf15a59..60fe2e23 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/VoiceContext.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/VoiceContext.cs @@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRendererManager _outStatus.VoiceDropsCount = 0; } - public int[] GetBufferData(IMemoryManager memory, int maxSamples, out int samplesCount) + public int[] GetBufferData(MemoryManager memory, int maxSamples, out int samplesCount) { if (!Playing) { @@ -122,7 +122,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRendererManager return output; } - private void UpdateBuffer(IMemoryManager memory) + private void UpdateBuffer(MemoryManager memory) { // TODO: Implement conversion for formats other // than interleaved stereo (2 channels). diff --git a/Ryujinx.HLE/Ryujinx.HLE.csproj b/Ryujinx.HLE/Ryujinx.HLE.csproj index 0f36843e..42bc4ddc 100644 --- a/Ryujinx.HLE/Ryujinx.HLE.csproj +++ b/Ryujinx.HLE/Ryujinx.HLE.csproj @@ -1,10 +1,9 @@ - + - netcoreapp2.1 + netcoreapp3.0 win-x64;osx-x64;linux-x64 Debug;Release;Profile Debug;Profile Release - 7.1 @@ -27,6 +26,11 @@ true + + + NU1605 + + @@ -43,13 +47,11 @@ - - diff --git a/Ryujinx.HLE/Utilities/StructReader.cs b/Ryujinx.HLE/Utilities/StructReader.cs index 36e5c7d1..cd274a95 100644 --- a/Ryujinx.HLE/Utilities/StructReader.cs +++ b/Ryujinx.HLE/Utilities/StructReader.cs @@ -5,11 +5,11 @@ namespace Ryujinx.HLE.Utilities { class StructReader { - private IMemoryManager _memory; + private MemoryManager _memory; public long Position { get; private set; } - public StructReader(IMemoryManager memory, long position) + public StructReader(MemoryManager memory, long position) { _memory = memory; Position = position; diff --git a/Ryujinx.HLE/Utilities/StructWriter.cs b/Ryujinx.HLE/Utilities/StructWriter.cs index c156956d..b488b5d6 100644 --- a/Ryujinx.HLE/Utilities/StructWriter.cs +++ b/Ryujinx.HLE/Utilities/StructWriter.cs @@ -5,11 +5,11 @@ namespace Ryujinx.HLE.Utilities { class StructWriter { - private IMemoryManager _memory; + private MemoryManager _memory; public long Position { get; private set; } - public StructWriter(IMemoryManager memory, long position) + public StructWriter(MemoryManager memory, long position) { _memory = memory; Position = position; diff --git a/Ryujinx.LLE/Luea.csproj b/Ryujinx.LLE/Luea.csproj index 895f27ee..7eb546d8 100644 --- a/Ryujinx.LLE/Luea.csproj +++ b/Ryujinx.LLE/Luea.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp3.0 win-x64;osx-x64;linux-x64 Exe Debug;Release;Profile Debug;Profile Release diff --git a/Ryujinx.Profiler/Ryujinx.Profiler.csproj b/Ryujinx.Profiler/Ryujinx.Profiler.csproj index bcc2d17d..0e089ccf 100644 --- a/Ryujinx.Profiler/Ryujinx.Profiler.csproj +++ b/Ryujinx.Profiler/Ryujinx.Profiler.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + netcoreapp3.0 win-x64;osx-x64;linux-x64 true Debug;Release;Profile Debug;Profile Release diff --git a/Ryujinx.ShaderTools/Ryujinx.ShaderTools.csproj b/Ryujinx.ShaderTools/Ryujinx.ShaderTools.csproj index a2ff36d9..2a71319d 100644 --- a/Ryujinx.ShaderTools/Ryujinx.ShaderTools.csproj +++ b/Ryujinx.ShaderTools/Ryujinx.ShaderTools.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp3.0 win-x64;osx-x64;linux-x64 Exe Debug;Release;Profile Debug;Profile Release diff --git a/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj b/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj index d15a405b..f01e8ced 100644 --- a/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj +++ b/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp3.0 win-x64;osx-x64;linux-x64 true Debug;Release;Profile Debug;Profile Release @@ -22,7 +22,7 @@ - + diff --git a/Ryujinx.Tests/Ryujinx.Tests.csproj b/Ryujinx.Tests/Ryujinx.Tests.csproj index 52832d86..143c4cec 100644 --- a/Ryujinx.Tests/Ryujinx.Tests.csproj +++ b/Ryujinx.Tests/Ryujinx.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp3.0 win-x64;osx-x64;linux-x64 Exe false @@ -14,7 +14,6 @@ false - latest diff --git a/Ryujinx.sln b/Ryujinx.sln index 18df571b..e3cb4528 100644 --- a/Ryujinx.sln +++ b/Ryujinx.sln @@ -14,8 +14,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE", "Ryujinx.HLE\ {4E69B67F-8CA7-42CF-A9E1-CCB0915DFB34} = {4E69B67F-8CA7-42CF-A9E1-CCB0915DFB34} EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChocolArm64", "ChocolArm64\ChocolArm64.csproj", "{2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics", "Ryujinx.Graphics\Ryujinx.Graphics.csproj", "{EAAE36AF-7781-4578-A7E0-F0EFD2025569}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio", "Ryujinx.Audio\Ryujinx.Audio.csproj", "{5C1D818E-682A-46A5-9D54-30006E26C270}" @@ -70,14 +68,6 @@ Global {CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Profile Release|Any CPU.Build.0 = Profile Release|Any CPU {CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.ActiveCfg = Release|Any CPU {CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.Build.0 = Release|Any CPU - {2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}.Profile Debug|Any CPU.ActiveCfg = Profile Debug|Any CPU - {2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}.Profile Debug|Any CPU.Build.0 = Profile Debug|Any CPU - {2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}.Profile Release|Any CPU.ActiveCfg = Profile Release|Any CPU - {2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}.Profile Release|Any CPU.Build.0 = Profile Release|Any CPU - {2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}.Release|Any CPU.Build.0 = Release|Any CPU {EAAE36AF-7781-4578-A7E0-F0EFD2025569}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EAAE36AF-7781-4578-A7E0-F0EFD2025569}.Debug|Any CPU.Build.0 = Debug|Any CPU {EAAE36AF-7781-4578-A7E0-F0EFD2025569}.Profile Debug|Any CPU.ActiveCfg = Profile Debug|Any CPU diff --git a/Ryujinx/Config.json b/Ryujinx/Config.json index d6ed189a..a68dd5a3 100644 --- a/Ryujinx/Config.json +++ b/Ryujinx/Config.json @@ -15,7 +15,6 @@ "enable_vsync": true, "enable_multicore_scheduling": true, "enable_fs_integrity_checks": true, - "enable_legacy_jit": false, "ignore_missing_services": false, "controller_type": "Handheld", "gui_columns": [ true, true, true, true, true, true, true, true, true ], diff --git a/Ryujinx/Configuration.cs b/Ryujinx/Configuration.cs index 57980c50..c950c453 100644 --- a/Ryujinx/Configuration.cs +++ b/Ryujinx/Configuration.cs @@ -111,11 +111,6 @@ namespace Ryujinx /// public int FsGlobalAccessLogMode { get; set; } - /// - /// Use old ChocolArm64 ARM emulator - /// - public bool EnableLegacyJit { get; set; } - /// /// Enable or disable ignoring missing services /// @@ -285,13 +280,11 @@ namespace Ryujinx device.System.GlobalAccessLogMode = SwitchConfig.FsGlobalAccessLogMode; - device.System.UseLegacyJit = SwitchConfig.EnableLegacyJit; - ServiceConfiguration.IgnoreMissingServices = SwitchConfig.IgnoreMissingServices; } - - public static void ConfigureHid(Switch device, Configuration SwitchConfig) - { + + public static void ConfigureHid(Switch device, Configuration SwitchConfig) + { if (SwitchConfig.JoystickControls.Enabled) { if (!Joystick.GetState(SwitchConfig.JoystickControls.Index).IsConnected) diff --git a/Ryujinx/Ryujinx.csproj b/Ryujinx/Ryujinx.csproj index 9ea3fe42..90c3f8e5 100644 --- a/Ryujinx/Ryujinx.csproj +++ b/Ryujinx/Ryujinx.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + netcoreapp3.0 win-x64;osx-x64;linux-x64 Exe true @@ -18,6 +18,11 @@ false + + + false + + @@ -36,7 +41,7 @@ - + diff --git a/Ryujinx/Ui/SwitchSettings.cs b/Ryujinx/Ui/SwitchSettings.cs index fcfc8fd4..589d9a7d 100644 --- a/Ryujinx/Ui/SwitchSettings.cs +++ b/Ryujinx/Ui/SwitchSettings.cs @@ -37,7 +37,6 @@ namespace Ryujinx.UI [GUI] CheckButton _vSyncToggle; [GUI] CheckButton _multiSchedToggle; [GUI] CheckButton _fsicToggle; - [GUI] CheckButton _legacyJitToggle; [GUI] CheckButton _ignoreToggle; [GUI] CheckButton _directKeyboardAccess; [GUI] ComboBoxText _systemLanguageSelect; @@ -134,7 +133,6 @@ namespace Ryujinx.UI if (SwitchConfig.EnableVsync) { _vSyncToggle.Click(); } if (SwitchConfig.EnableMulticoreScheduling) { _multiSchedToggle.Click(); } if (SwitchConfig.EnableFsIntegrityChecks) { _fsicToggle.Click(); } - if (SwitchConfig.EnableLegacyJit) { _legacyJitToggle.Click(); } if (SwitchConfig.IgnoreMissingServices) { _ignoreToggle.Click(); } if (SwitchConfig.EnableKeyboard) { _directKeyboardAccess.Click(); } if (SwitchConfig.EnableCustomTheme) { _custThemeToggle.Click(); } @@ -316,7 +314,6 @@ namespace Ryujinx.UI SwitchConfig.EnableVsync = _vSyncToggle.Active; SwitchConfig.EnableMulticoreScheduling = _multiSchedToggle.Active; SwitchConfig.EnableFsIntegrityChecks = _fsicToggle.Active; - SwitchConfig.EnableLegacyJit = _legacyJitToggle.Active; SwitchConfig.IgnoreMissingServices = _ignoreToggle.Active; SwitchConfig.EnableKeyboard = _directKeyboardAccess.Active; SwitchConfig.EnableCustomTheme = _custThemeToggle.Active; diff --git a/Ryujinx/Ui/SwitchSettings.glade b/Ryujinx/Ui/SwitchSettings.glade index 30a689a8..74141a2b 100644 --- a/Ryujinx/Ui/SwitchSettings.glade +++ b/Ryujinx/Ui/SwitchSettings.glade @@ -1475,24 +1475,6 @@ 1 - - - Use old ChocolArm64 ARM emulator - True - True - False - Uses old ChocolArm64 ARM emulator rather then the new ARMeilleure - start - 5 - 5 - True - - - False - True - 2 - - Enable FS Integrity Checks @@ -1508,7 +1490,7 @@ False True - 3 + 2 diff --git a/Ryujinx/_schema.json b/Ryujinx/_schema.json index b9546a84..24a5b73f 100644 --- a/Ryujinx/_schema.json +++ b/Ryujinx/_schema.json @@ -20,7 +20,6 @@ "enable_multicore_scheduling", "enable_fs_integrity_checks", "fs_global_access_log_mode", - "enable_legacy_jit", "controller_type", "enable_keyboard", "keyboard_controls", @@ -472,17 +471,6 @@ 3 ] }, - "enable_legacy_jit": { - "$id": "#/properties/enable_legacy_jit", - "type": "boolean", - "title": "Enable legacy JIT", - "description": "Use old ChocolArm64 ARM emulator", - "default": false, - "examples": [ - true, - false - ] - }, "ignore_missing_services": { "$id": "#/properties/ignore_missing_services", "type": "boolean", diff --git a/appveyor.yml b/appveyor.yml index a1201aa6..73f4654d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,7 +2,7 @@ version: 1.0.{build} branches: only: - master -image: Visual Studio 2017 +image: Visual Studio 2019 environment: matrix: - config: Release @@ -15,18 +15,18 @@ build_script: dotnet --version dotnet publish -c $env:config -r win-x64 - + dotnet publish -c $env:config -r linux-x64 - + dotnet publish -c $env:config -r osx-x64 - 7z a ryujinx$env:config_name$env:APPVEYOR_BUILD_VERSION-win_x64.zip $env:APPVEYOR_BUILD_FOLDER\Ryujinx\bin\$env:config\netcoreapp2.1\win-x64\publish\ + 7z a ryujinx$env:config_name$env:APPVEYOR_BUILD_VERSION-win_x64.zip $env:APPVEYOR_BUILD_FOLDER\Ryujinx\bin\$env:config\netcoreapp3.0\win-x64\publish\ - 7z a ryujinx$env:config_name$env:APPVEYOR_BUILD_VERSION-linux_x64.tar $env:APPVEYOR_BUILD_FOLDER\Ryujinx\bin\$env:config\netcoreapp2.1\linux-x64\publish\ + 7z a ryujinx$env:config_name$env:APPVEYOR_BUILD_VERSION-linux_x64.tar $env:APPVEYOR_BUILD_FOLDER\Ryujinx\bin\$env:config\netcoreapp3.0\linux-x64\publish\ 7z a ryujinx$env:config_name$env:APPVEYOR_BUILD_VERSION-linux_x64.tar.gz ryujinx$env:config_name$env:APPVEYOR_BUILD_VERSION-linux_x64.tar - 7z a ryujinx$env:config_name$env:APPVEYOR_BUILD_VERSION-osx_x64.zip $env:APPVEYOR_BUILD_FOLDER\Ryujinx\bin\$env:config\netcoreapp2.1\osx-x64\publish\ + 7z a ryujinx$env:config_name$env:APPVEYOR_BUILD_VERSION-osx_x64.zip $env:APPVEYOR_BUILD_FOLDER\Ryujinx\bin\$env:config\netcoreapp3.0\osx-x64\publish\ artifacts: - path: ryujinx%config_name%%APPVEYOR_BUILD_VERSION%-win_x64.zip