aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Barney <thealexbarney@gmail.com>2018-10-30 19:43:02 -0600
committergdkchan <gab.dark.100@gmail.com>2018-10-30 22:43:02 -0300
commit9cb57fb4bb3bbae0ae052a5af4a96a49fc5d864d (patch)
tree0c97425aeb311c142bc92a6fcc503cb2c07d4376
parent5a87e58183578f5b84ca8d01cbb76aed11820f78 (diff)
Adjust naming conventions for Ryujinx and ChocolArm64 projects (#484)
* Change naming convention for Ryujinx project * Change naming convention for ChocolArm64 project * Fix NaN * Remove unneeded this. from Ryujinx project * Adjust naming from new PRs * Name changes based on feedback * How did this get removed? * Rebasing fix * Change FP enum case * Remove prefix from ChocolArm64 classes - Part 1 * Remove prefix from ChocolArm64 classes - Part 2 * Fix alignment from last commit's renaming * Rename namespaces * Rename stragglers * Fix alignment * Rename OpCode class * Missed a few * Adjust alignment
-rw-r--r--ChocolArm64/ABitUtils.cs49
-rw-r--r--ChocolArm64/AOpCodeTable.cs713
-rw-r--r--ChocolArm64/AOptimizations.cs18
-rw-r--r--ChocolArm64/ATranslatedSub.cs150
-rw-r--r--ChocolArm64/ATranslator.cs165
-rw-r--r--ChocolArm64/ATranslatorCache.cs165
-rw-r--r--ChocolArm64/BitUtils.cs49
-rw-r--r--ChocolArm64/CpuThread.cs (renamed from ChocolArm64/AThread.cs)26
-rw-r--r--ChocolArm64/Decoder/ABlock.cs35
-rw-r--r--ChocolArm64/Decoder/ACond.cs22
-rw-r--r--ChocolArm64/Decoder/ADecoder.cs239
-rw-r--r--ChocolArm64/Decoder/ADecoderHelper.cs107
-rw-r--r--ChocolArm64/Decoder/AOpCode.cs40
-rw-r--r--ChocolArm64/Decoder/AOpCodeAdr.cs18
-rw-r--r--ChocolArm64/Decoder/AOpCodeAlu.cs24
-rw-r--r--ChocolArm64/Decoder/AOpCodeAluImm.cs39
-rw-r--r--ChocolArm64/Decoder/AOpCodeAluRs.cs29
-rw-r--r--ChocolArm64/Decoder/AOpCodeAluRx.cs19
-rw-r--r--ChocolArm64/Decoder/AOpCodeBImm.cs11
-rw-r--r--ChocolArm64/Decoder/AOpCodeBImmAl.cs12
-rw-r--r--ChocolArm64/Decoder/AOpCodeBImmCmp.cs21
-rw-r--r--ChocolArm64/Decoder/AOpCodeBImmCond.cs25
-rw-r--r--ChocolArm64/Decoder/AOpCodeBImmTest.cs20
-rw-r--r--ChocolArm64/Decoder/AOpCodeBReg.cs24
-rw-r--r--ChocolArm64/Decoder/AOpCodeBfm.cs29
-rw-r--r--ChocolArm64/Decoder/AOpCodeCcmp.cs31
-rw-r--r--ChocolArm64/Decoder/AOpCodeCcmpImm.cs11
-rw-r--r--ChocolArm64/Decoder/AOpCodeCcmpReg.cs15
-rw-r--r--ChocolArm64/Decoder/AOpCodeCsel.cs17
-rw-r--r--ChocolArm64/Decoder/AOpCodeException.cs14
-rw-r--r--ChocolArm64/Decoder/AOpCodeMem.cs19
-rw-r--r--ChocolArm64/Decoder/AOpCodeMemEx.cs16
-rw-r--r--ChocolArm64/Decoder/AOpCodeMemPair.cs25
-rw-r--r--ChocolArm64/Decoder/AOpCodeMemReg.cs20
-rw-r--r--ChocolArm64/Decoder/AOpCodeMov.cs36
-rw-r--r--ChocolArm64/Decoder/AOpCodeMul.cs16
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimd.cs25
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdCvt.cs31
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdExt.cs14
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdFcond.cs17
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdFmov.cs33
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdImm.cs101
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdIns.cs36
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdMemImm.cs19
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdMemLit.cs31
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdMemPair.cs16
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdMemReg.cs14
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdMemSs.cs98
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdReg.cs18
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdRegElem.cs31
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdRegElemF.cs33
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdShImm.cs16
-rw-r--r--ChocolArm64/Decoder/AOpCodeSimdTbl.cs12
-rw-r--r--ChocolArm64/Decoder/AOpCodeSystem.cs24
-rw-r--r--ChocolArm64/Decoder/IAOpCode.cs13
-rw-r--r--ChocolArm64/Decoder/IAOpCodeAlu.cs10
-rw-r--r--ChocolArm64/Decoder/IAOpCodeAluImm.cs7
-rw-r--r--ChocolArm64/Decoder/IAOpCodeAluRs.cs10
-rw-r--r--ChocolArm64/Decoder/IAOpCodeAluRx.cs10
-rw-r--r--ChocolArm64/Decoder/IAOpCodeCond.cs7
-rw-r--r--ChocolArm64/Decoder/IAOpCodeSimd.cs7
-rw-r--r--ChocolArm64/Decoder32/A32OpCode.cs15
-rw-r--r--ChocolArm64/Decoder32/A32OpCodeBImmAl.cs16
-rw-r--r--ChocolArm64/Decoders/Block.cs35
-rw-r--r--ChocolArm64/Decoders/Cond.cs22
-rw-r--r--ChocolArm64/Decoders/DataOp.cs (renamed from ChocolArm64/Decoder/ADataOp.cs)4
-rw-r--r--ChocolArm64/Decoders/Decoder.cs239
-rw-r--r--ChocolArm64/Decoders/DecoderHelper.cs107
-rw-r--r--ChocolArm64/Decoders/IOpCode64.cs13
-rw-r--r--ChocolArm64/Decoders/IOpCodeAlu64.cs10
-rw-r--r--ChocolArm64/Decoders/IOpCodeAluImm64.cs7
-rw-r--r--ChocolArm64/Decoders/IOpCodeAluRs64.cs10
-rw-r--r--ChocolArm64/Decoders/IOpCodeAluRx64.cs10
-rw-r--r--ChocolArm64/Decoders/IOpCodeCond64.cs7
-rw-r--r--ChocolArm64/Decoders/IOpCodeLit64.cs (renamed from ChocolArm64/Decoder/IAOpCodeLit.cs)4
-rw-r--r--ChocolArm64/Decoders/IOpCodeSimd64.cs7
-rw-r--r--ChocolArm64/Decoders/IntType.cs (renamed from ChocolArm64/Decoder/AIntType.cs)4
-rw-r--r--ChocolArm64/Decoders/OpCode64.cs40
-rw-r--r--ChocolArm64/Decoders/OpCodeAdr64.cs18
-rw-r--r--ChocolArm64/Decoders/OpCodeAlu64.cs24
-rw-r--r--ChocolArm64/Decoders/OpCodeAluImm64.cs39
-rw-r--r--ChocolArm64/Decoders/OpCodeAluRs64.cs29
-rw-r--r--ChocolArm64/Decoders/OpCodeAluRx64.cs19
-rw-r--r--ChocolArm64/Decoders/OpCodeBImm64.cs11
-rw-r--r--ChocolArm64/Decoders/OpCodeBImmAl64.cs12
-rw-r--r--ChocolArm64/Decoders/OpCodeBImmCmp64.cs21
-rw-r--r--ChocolArm64/Decoders/OpCodeBImmCond64.cs25
-rw-r--r--ChocolArm64/Decoders/OpCodeBImmTest64.cs20
-rw-r--r--ChocolArm64/Decoders/OpCodeBReg64.cs24
-rw-r--r--ChocolArm64/Decoders/OpCodeBfm64.cs29
-rw-r--r--ChocolArm64/Decoders/OpCodeCcmp64.cs31
-rw-r--r--ChocolArm64/Decoders/OpCodeCcmpImm64.cs11
-rw-r--r--ChocolArm64/Decoders/OpCodeCcmpReg64.cs15
-rw-r--r--ChocolArm64/Decoders/OpCodeCsel64.cs17
-rw-r--r--ChocolArm64/Decoders/OpCodeException64.cs14
-rw-r--r--ChocolArm64/Decoders/OpCodeMem64.cs19
-rw-r--r--ChocolArm64/Decoders/OpCodeMemEx64.cs16
-rw-r--r--ChocolArm64/Decoders/OpCodeMemImm64.cs (renamed from ChocolArm64/Decoder/AOpCodeMemImm.cs)24
-rw-r--r--ChocolArm64/Decoders/OpCodeMemLit64.cs (renamed from ChocolArm64/Decoder/AOpCodeMemLit.cs)14
-rw-r--r--ChocolArm64/Decoders/OpCodeMemPair64.cs25
-rw-r--r--ChocolArm64/Decoders/OpCodeMemReg64.cs20
-rw-r--r--ChocolArm64/Decoders/OpCodeMov64.cs36
-rw-r--r--ChocolArm64/Decoders/OpCodeMul64.cs16
-rw-r--r--ChocolArm64/Decoders/OpCodeSimd64.cs25
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdCvt64.cs31
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdExt64.cs14
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdFcond64.cs17
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdFmov64.cs33
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdImm64.cs101
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdIns64.cs36
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdMemImm64.cs19
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdMemLit64.cs31
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdMemMs64.cs (renamed from ChocolArm64/Decoder/AOpCodeSimdMemMs.cs)28
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdMemPair64.cs16
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdMemReg64.cs14
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdMemSs64.cs98
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdReg64.cs18
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdRegElem64.cs31
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs33
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdShImm64.cs16
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdTbl64.cs12
-rw-r--r--ChocolArm64/Decoders/OpCodeSystem64.cs24
-rw-r--r--ChocolArm64/Decoders/ShiftType.cs (renamed from ChocolArm64/Decoder/AShiftType.cs)4
-rw-r--r--ChocolArm64/Decoders32/A32OpCode.cs15
-rw-r--r--ChocolArm64/Decoders32/A32OpCodeBImmAl.cs16
-rw-r--r--ChocolArm64/Events/ACpuTraceEventArgs.cs14
-rw-r--r--ChocolArm64/Events/AInstExceptionEventArgs.cs16
-rw-r--r--ChocolArm64/Events/AInstUndefinedEventArgs.cs16
-rw-r--r--ChocolArm64/Events/AInvalidAccessEventArgs.cs14
-rw-r--r--ChocolArm64/Events/CpuTraceEventArgs.cs14
-rw-r--r--ChocolArm64/Events/InstExceptionEventArgs.cs16
-rw-r--r--ChocolArm64/Events/InstUndefinedEventArgs.cs16
-rw-r--r--ChocolArm64/Events/InvalidAccessEventArgs.cs14
-rw-r--r--ChocolArm64/Exceptions/VmmOutOfMemoryException.cs2
-rw-r--r--ChocolArm64/Exceptions/VmmPageFaultException.cs2
-rw-r--r--ChocolArm64/Instruction/AInst.cs20
-rw-r--r--ChocolArm64/Instruction/AInstEmitAlu.cs402
-rw-r--r--ChocolArm64/Instruction/AInstEmitAluHelper.cs212
-rw-r--r--ChocolArm64/Instruction/AInstEmitBfm.cs208
-rw-r--r--ChocolArm64/Instruction/AInstEmitCcmp.cs81
-rw-r--r--ChocolArm64/Instruction/AInstEmitCsel.cs58
-rw-r--r--ChocolArm64/Instruction/AInstEmitException.cs86
-rw-r--r--ChocolArm64/Instruction/AInstEmitFlow.cs189
-rw-r--r--ChocolArm64/Instruction/AInstEmitHash.cs115
-rw-r--r--ChocolArm64/Instruction/AInstEmitMemory.cs252
-rw-r--r--ChocolArm64/Instruction/AInstEmitMemoryEx.cs192
-rw-r--r--ChocolArm64/Instruction/AInstEmitMemoryHelper.cs138
-rw-r--r--ChocolArm64/Instruction/AInstEmitMove.cs41
-rw-r--r--ChocolArm64/Instruction/AInstEmitMul.cs80
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs2387
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdCmp.cs526
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdCrypto.cs54
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdCvt.cs697
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdHash.cs140
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdHelper.cs1495
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdLogical.cs311
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdMemory.cs185
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdMove.cs562
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdShift.cs865
-rw-r--r--ChocolArm64/Instruction/AInstEmitSystem.cs138
-rw-r--r--ChocolArm64/Instruction/AInstEmitter.cs6
-rw-r--r--ChocolArm64/Instruction/AInstInterpreter.cs8
-rw-r--r--ChocolArm64/Instruction/ASoftFallback.cs922
-rw-r--r--ChocolArm64/Instruction/ASoftFloat.cs2127
-rw-r--r--ChocolArm64/Instruction32/A32InstInterpretFlow.cs70
-rw-r--r--ChocolArm64/Instruction32/A32InstInterpretHelper.cs65
-rw-r--r--ChocolArm64/Instructions/CryptoHelper.cs (renamed from ChocolArm64/Instruction/ACryptoHelper.cs)166
-rw-r--r--ChocolArm64/Instructions/Inst.cs20
-rw-r--r--ChocolArm64/Instructions/InstEmitAlu.cs402
-rw-r--r--ChocolArm64/Instructions/InstEmitAluHelper.cs212
-rw-r--r--ChocolArm64/Instructions/InstEmitBfm.cs208
-rw-r--r--ChocolArm64/Instructions/InstEmitCcmp.cs81
-rw-r--r--ChocolArm64/Instructions/InstEmitCsel.cs58
-rw-r--r--ChocolArm64/Instructions/InstEmitException.cs86
-rw-r--r--ChocolArm64/Instructions/InstEmitFlow.cs189
-rw-r--r--ChocolArm64/Instructions/InstEmitHash.cs115
-rw-r--r--ChocolArm64/Instructions/InstEmitMemory.cs252
-rw-r--r--ChocolArm64/Instructions/InstEmitMemoryEx.cs192
-rw-r--r--ChocolArm64/Instructions/InstEmitMemoryHelper.cs138
-rw-r--r--ChocolArm64/Instructions/InstEmitMove.cs41
-rw-r--r--ChocolArm64/Instructions/InstEmitMul.cs80
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdArithmetic.cs2387
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdCmp.cs526
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdCrypto.cs54
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdCvt.cs697
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdHash.cs140
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdHelper.cs1495
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdLogical.cs311
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdMemory.cs185
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdMove.cs562
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdShift.cs865
-rw-r--r--ChocolArm64/Instructions/InstEmitSystem.cs138
-rw-r--r--ChocolArm64/Instructions/InstEmitter.cs6
-rw-r--r--ChocolArm64/Instructions/InstInterpreter.cs8
-rw-r--r--ChocolArm64/Instructions/SoftFallback.cs922
-rw-r--r--ChocolArm64/Instructions/SoftFloat.cs2127
-rw-r--r--ChocolArm64/Instructions/VectorHelper.cs (renamed from ChocolArm64/Instruction/AVectorHelper.cs)494
-rw-r--r--ChocolArm64/Instructions32/A32InstInterpretAlu.cs (renamed from ChocolArm64/Instruction32/A32InstInterpretAlu.cs)2
-rw-r--r--ChocolArm64/Instructions32/A32InstInterpretFlow.cs70
-rw-r--r--ChocolArm64/Instructions32/A32InstInterpretHelper.cs65
-rw-r--r--ChocolArm64/Memory/AMemory.cs745
-rw-r--r--ChocolArm64/Memory/AMemoryHelper.cs67
-rw-r--r--ChocolArm64/Memory/IAMemory.cs37
-rw-r--r--ChocolArm64/Memory/IMemory.cs37
-rw-r--r--ChocolArm64/Memory/MemoryHelper.cs67
-rw-r--r--ChocolArm64/Memory/MemoryManager.cs745
-rw-r--r--ChocolArm64/OpCodeTable.cs713
-rw-r--r--ChocolArm64/Optimizations.cs18
-rw-r--r--ChocolArm64/State/ARegister.cs142
-rw-r--r--ChocolArm64/State/CpuThreadState.cs (renamed from ChocolArm64/State/AThreadState.cs)80
-rw-r--r--ChocolArm64/State/ExecutionMode.cs (renamed from ChocolArm64/State/AExecutionMode.cs)2
-rw-r--r--ChocolArm64/State/FPCR.cs11
-rw-r--r--ChocolArm64/State/FPSR.cs8
-rw-r--r--ChocolArm64/State/FpExc.cs (renamed from ChocolArm64/State/FPExc.cs)2
-rw-r--r--ChocolArm64/State/FpType.cs (renamed from ChocolArm64/State/FPType.cs)2
-rw-r--r--ChocolArm64/State/Fpcr.cs11
-rw-r--r--ChocolArm64/State/Fpsr.cs8
-rw-r--r--ChocolArm64/State/PState.cs (renamed from ChocolArm64/State/APState.cs)8
-rw-r--r--ChocolArm64/State/Register.cs142
-rw-r--r--ChocolArm64/State/RegisterSize.cs (renamed from ChocolArm64/State/ARegisterSize.cs)6
-rw-r--r--ChocolArm64/State/RegisterType.cs (renamed from ChocolArm64/State/ARegisterType.cs)2
-rw-r--r--ChocolArm64/State/RoundMode.cs (renamed from ChocolArm64/State/ARoundMode.cs)2
-rw-r--r--ChocolArm64/TranslatedSub.cs150
-rw-r--r--ChocolArm64/TranslatedSubType.cs (renamed from ChocolArm64/ATranslatedSubType.cs)2
-rw-r--r--ChocolArm64/Translation/AILBarrier.cs7
-rw-r--r--ChocolArm64/Translation/AILBlock.cs76
-rw-r--r--ChocolArm64/Translation/AILEmitter.cs188
-rw-r--r--ChocolArm64/Translation/AILEmitterCtx.cs554
-rw-r--r--ChocolArm64/Translation/AILLabel.cs28
-rw-r--r--ChocolArm64/Translation/AILOpCode.cs19
-rw-r--r--ChocolArm64/Translation/AILOpCodeBranch.cs21
-rw-r--r--ChocolArm64/Translation/AILOpCodeCall.cs20
-rw-r--r--ChocolArm64/Translation/AILOpCodeConst.cs65
-rw-r--r--ChocolArm64/Translation/AILOpCodeLoad.cs75
-rw-r--r--ChocolArm64/Translation/AILOpCodeLog.cs17
-rw-r--r--ChocolArm64/Translation/AILOpCodeStore.cs75
-rw-r--r--ChocolArm64/Translation/ALocalAlloc.cs229
-rw-r--r--ChocolArm64/Translation/IAILEmit.cs7
-rw-r--r--ChocolArm64/Translation/IILEmit.cs7
-rw-r--r--ChocolArm64/Translation/ILBarrier.cs7
-rw-r--r--ChocolArm64/Translation/ILBlock.cs76
-rw-r--r--ChocolArm64/Translation/ILEmitter.cs188
-rw-r--r--ChocolArm64/Translation/ILEmitterCtx.cs554
-rw-r--r--ChocolArm64/Translation/ILGeneratorEx.cs110
-rw-r--r--ChocolArm64/Translation/ILLabel.cs28
-rw-r--r--ChocolArm64/Translation/ILOpCode.cs19
-rw-r--r--ChocolArm64/Translation/ILOpCodeBranch.cs21
-rw-r--r--ChocolArm64/Translation/ILOpCodeCall.cs20
-rw-r--r--ChocolArm64/Translation/ILOpCodeConst.cs65
-rw-r--r--ChocolArm64/Translation/ILOpCodeLoad.cs75
-rw-r--r--ChocolArm64/Translation/ILOpCodeLog.cs17
-rw-r--r--ChocolArm64/Translation/ILOpCodeStore.cs75
-rw-r--r--ChocolArm64/Translation/IoType.cs (renamed from ChocolArm64/Translation/AIoType.cs)2
-rw-r--r--ChocolArm64/Translation/LocalAlloc.cs229
-rw-r--r--ChocolArm64/Translator.cs165
-rw-r--r--ChocolArm64/TranslatorCache.cs165
-rw-r--r--Ryujinx.Graphics/Memory/NvGpuVmm.cs6
-rw-r--r--Ryujinx.Graphics/Memory/NvGpuVmmCache.cs2
-rw-r--r--Ryujinx.Graphics/Texture/ImageUtils.cs6
-rw-r--r--Ryujinx.Graphics/Texture/TextureHelper.cs8
-rw-r--r--Ryujinx.HLE/HOS/Homebrew.cs18
-rw-r--r--Ryujinx.HLE/HOS/Ipc/IpcHandler.cs12
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs48
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KMemoryManager.cs2
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KRecursiveLock.cs2
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KThread.cs14
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcHandler.cs14
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcMemory.cs20
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcSystem.cs32
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcThread.cs24
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs16
-rw-r--r--Ryujinx.HLE/HOS/Process.cs24
-rw-r--r--Ryujinx.HLE/HOS/ServiceCtx.cs32
-rw-r--r--Ryujinx.HLE/HOS/Services/Acc/IProfile.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs6
-rw-r--r--Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/VoiceContext.cs4
-rw-r--r--Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/NvGpuAS/NvGpuASIoctl.cs14
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/NvGpuGpu/NvGpuGpuIoctl.cs14
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/NvHostCtrl/NvHostCtrlIoctl.cs14
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/NvMap/NvMapIoctl.cs24
-rw-r--r--Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs2
-rw-r--r--Ryujinx.HLE/Loaders/Executable.cs4
-rw-r--r--Ryujinx.HLE/Utilities/StructReader.cs8
-rw-r--r--Ryujinx.HLE/Utilities/StructWriter.cs6
-rw-r--r--Ryujinx.Tests/Cpu/CpuTest.cs14
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestAlu.cs22
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestAluImm.cs40
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestAluRs.cs108
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestAluRx.cs56
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestBfm.cs12
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestCcmpImm.cs8
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestCcmpReg.cs8
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestCsel.cs16
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestMisc.cs2
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestMov.cs12
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestMul.cs20
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimd.cs174
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimdArithmetic.cs28
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimdCrypto.cs8
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimdIns.cs12
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimdReg.cs296
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs4
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimdRegElemF.cs16
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimdShImm.cs38
-rw-r--r--Ryujinx/Config.cs196
-rw-r--r--Ryujinx/Ui/ConsoleLog.cs44
-rw-r--r--Ryujinx/Ui/GLScreen.cs222
-rw-r--r--Ryujinx/Ui/JoyConController.cs188
-rw-r--r--Ryujinx/Ui/JoyConKeyboard.cs82
-rw-r--r--Ryujinx/Ui/Program.cs36
314 files changed, 19464 insertions, 19464 deletions
diff --git a/ChocolArm64/ABitUtils.cs b/ChocolArm64/ABitUtils.cs
deleted file mode 100644
index a2654c20..00000000
--- a/ChocolArm64/ABitUtils.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-namespace ChocolArm64
-{
- static class ABitUtils
- {
- 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 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/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs
deleted file mode 100644
index cbdff47f..00000000
--- a/ChocolArm64/AOpCodeTable.cs
+++ /dev/null
@@ -1,713 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Decoder32;
-using ChocolArm64.Instruction;
-using ChocolArm64.Instruction32;
-using ChocolArm64.State;
-using System;
-using System.Collections.Generic;
-
-namespace ChocolArm64
-{
- static class AOpCodeTable
- {
- static AOpCodeTable()
- {
-#region "OpCode Table (AArch32)"
- //Integer
- SetA32("<<<<1010xxxxxxxxxxxxxxxxxxxxxxxx", A32InstInterpret.B, typeof(A32OpCodeBImmAl));
- SetA32("<<<<1011xxxxxxxxxxxxxxxxxxxxxxxx", A32InstInterpret.Bl, typeof(A32OpCodeBImmAl));
- SetA32("1111101xxxxxxxxxxxxxxxxxxxxxxxxx", A32InstInterpret.Blx, typeof(A32OpCodeBImmAl));
-#endregion
-
-#region "OpCode Table (AArch64)"
- //Integer
- SetA64("x0011010000xxxxx000000xxxxxxxxxx", AInstEmit.Adc, typeof(AOpCodeAluRs));
- SetA64("x0111010000xxxxx000000xxxxxxxxxx", AInstEmit.Adcs, typeof(AOpCodeAluRs));
- SetA64("x00100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluImm));
- SetA64("00001011<<0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRs));
- SetA64("10001011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRs));
- SetA64("x0001011001xxxxxxxx0xxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRx));
- SetA64("x0001011001xxxxxxxx100xxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRx));
- SetA64("x01100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluImm));
- SetA64("00101011<<0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRs));
- SetA64("10101011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRs));
- SetA64("x0101011001xxxxxxxx0xxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRx));
- SetA64("x0101011001xxxxxxxx100xxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRx));
- SetA64("0xx10000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adr, typeof(AOpCodeAdr));
- SetA64("1xx10000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adrp, typeof(AOpCodeAdr));
- SetA64("0001001000xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.And, typeof(AOpCodeAluImm));
- SetA64("100100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.And, typeof(AOpCodeAluImm));
- SetA64("00001010xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.And, typeof(AOpCodeAluRs));
- SetA64("10001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.And, typeof(AOpCodeAluRs));
- SetA64("0111001000xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ands, typeof(AOpCodeAluImm));
- SetA64("111100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ands, typeof(AOpCodeAluImm));
- SetA64("01101010xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Ands, typeof(AOpCodeAluRs));
- SetA64("11101010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ands, typeof(AOpCodeAluRs));
- SetA64("x0011010110xxxxx001010xxxxxxxxxx", AInstEmit.Asrv, typeof(AOpCodeAluRs));
- SetA64("000101xxxxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.B, typeof(AOpCodeBImmAl));
- SetA64("01010100xxxxxxxxxxxxxxxxxxx0xxxx", AInstEmit.B_Cond, typeof(AOpCodeBImmCond));
- SetA64("00110011000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Bfm, typeof(AOpCodeBfm));
- SetA64("1011001101xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Bfm, typeof(AOpCodeBfm));
- SetA64("00001010xx1xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Bic, typeof(AOpCodeAluRs));
- SetA64("10001010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Bic, typeof(AOpCodeAluRs));
- SetA64("01101010xx1xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Bics, typeof(AOpCodeAluRs));
- SetA64("11101010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Bics, typeof(AOpCodeAluRs));
- SetA64("100101xxxxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Bl, typeof(AOpCodeBImmAl));
- SetA64("1101011000111111000000xxxxx00000", AInstEmit.Blr, typeof(AOpCodeBReg));
- SetA64("1101011000011111000000xxxxx00000", AInstEmit.Br, typeof(AOpCodeBReg));
- SetA64("11010100001xxxxxxxxxxxxxxxx00000", AInstEmit.Brk, typeof(AOpCodeException));
- SetA64("x0110101xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Cbnz, typeof(AOpCodeBImmCmp));
- SetA64("x0110100xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Cbz, typeof(AOpCodeBImmCmp));
- SetA64("x0111010010xxxxxxxxx10xxxxx0xxxx", AInstEmit.Ccmn, typeof(AOpCodeCcmpImm));
- SetA64("x0111010010xxxxxxxxx00xxxxx0xxxx", AInstEmit.Ccmn, typeof(AOpCodeCcmpReg));
- SetA64("x1111010010xxxxxxxxx10xxxxx0xxxx", AInstEmit.Ccmp, typeof(AOpCodeCcmpImm));
- SetA64("x1111010010xxxxxxxxx00xxxxx0xxxx", AInstEmit.Ccmp, typeof(AOpCodeCcmpReg));
- SetA64("11010101000000110011xxxx01011111", AInstEmit.Clrex, typeof(AOpCodeSystem));
- SetA64("x101101011000000000101xxxxxxxxxx", AInstEmit.Cls, typeof(AOpCodeAlu));
- SetA64("x101101011000000000100xxxxxxxxxx", AInstEmit.Clz, typeof(AOpCodeAlu));
- SetA64("00011010110xxxxx010000xxxxxxxxxx", AInstEmit.Crc32b, typeof(AOpCodeAluRs));
- SetA64("00011010110xxxxx010001xxxxxxxxxx", AInstEmit.Crc32h, typeof(AOpCodeAluRs));
- SetA64("00011010110xxxxx010010xxxxxxxxxx", AInstEmit.Crc32w, typeof(AOpCodeAluRs));
- SetA64("10011010110xxxxx010011xxxxxxxxxx", AInstEmit.Crc32x, typeof(AOpCodeAluRs));
- SetA64("00011010110xxxxx010100xxxxxxxxxx", AInstEmit.Crc32cb, typeof(AOpCodeAluRs));
- SetA64("00011010110xxxxx010101xxxxxxxxxx", AInstEmit.Crc32ch, typeof(AOpCodeAluRs));
- SetA64("00011010110xxxxx010110xxxxxxxxxx", AInstEmit.Crc32cw, typeof(AOpCodeAluRs));
- SetA64("10011010110xxxxx010111xxxxxxxxxx", AInstEmit.Crc32cx, typeof(AOpCodeAluRs));
- SetA64("x0011010100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Csel, typeof(AOpCodeCsel));
- SetA64("x0011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csinc, typeof(AOpCodeCsel));
- SetA64("x1011010100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Csinv, typeof(AOpCodeCsel));
- SetA64("x1011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csneg, typeof(AOpCodeCsel));
- SetA64("11010101000000110011xxxx10111111", AInstEmit.Dmb, typeof(AOpCodeSystem));
- SetA64("11010101000000110011xxxx10011111", AInstEmit.Dsb, typeof(AOpCodeSystem));
- SetA64("01001010xx1xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Eon, typeof(AOpCodeAluRs));
- SetA64("11001010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eon, typeof(AOpCodeAluRs));
- SetA64("0101001000xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluImm));
- SetA64("110100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluImm));
- SetA64("01001010xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluRs));
- SetA64("11001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluRs));
- SetA64("00010011100xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Extr, typeof(AOpCodeAluRs));
- SetA64("10010011110xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Extr, typeof(AOpCodeAluRs));
- SetA64("11010101000000110010xxxxxxx11111", AInstEmit.Hint, typeof(AOpCodeSystem));
- SetA64("11010101000000110011xxxx11011111", AInstEmit.Isb, typeof(AOpCodeSystem));
- SetA64("xx001000110xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldar, typeof(AOpCodeMemEx));
- SetA64("1x001000011xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldaxp, typeof(AOpCodeMemEx));
- SetA64("xx001000010xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldaxr, typeof(AOpCodeMemEx));
- SetA64("<<10100xx1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldp, typeof(AOpCodeMemPair));
- SetA64("xx111000010xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeMemImm));
- SetA64("xx11100101xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeMemImm));
- SetA64("xx111000011xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeMemReg));
- SetA64("xx011000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.LdrLit, typeof(AOpCodeMemLit));
- SetA64("0x1110001x0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemImm));
- SetA64("0x1110011xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemImm));
- SetA64("10111000100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemImm));
- SetA64("1011100110xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemImm));
- SetA64("0x1110001x1xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemReg));
- SetA64("10111000101xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemReg));
- SetA64("xx001000010xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Ldxr, typeof(AOpCodeMemEx));
- SetA64("1x001000011xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Ldxp, typeof(AOpCodeMemEx));
- SetA64("x0011010110xxxxx001000xxxxxxxxxx", AInstEmit.Lslv, typeof(AOpCodeAluRs));
- SetA64("x0011010110xxxxx001001xxxxxxxxxx", AInstEmit.Lsrv, typeof(AOpCodeAluRs));
- SetA64("x0011011000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Madd, typeof(AOpCodeMul));
- SetA64("0111001010xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movk, typeof(AOpCodeMov));
- SetA64("111100101xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movk, typeof(AOpCodeMov));
- SetA64("0001001010xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movn, typeof(AOpCodeMov));
- SetA64("100100101xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movn, typeof(AOpCodeMov));
- SetA64("0101001010xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movz, typeof(AOpCodeMov));
- SetA64("110100101xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movz, typeof(AOpCodeMov));
- SetA64("110101010011xxxxxxxxxxxxxxxxxxxx", AInstEmit.Mrs, typeof(AOpCodeSystem));
- SetA64("110101010001xxxxxxxxxxxxxxxxxxxx", AInstEmit.Msr, typeof(AOpCodeSystem));
- SetA64("x0011011000xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Msub, typeof(AOpCodeMul));
- SetA64("11010101000000110010000000011111", AInstEmit.Nop, typeof(AOpCodeSystem));
- SetA64("00101010xx1xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Orn, typeof(AOpCodeAluRs));
- SetA64("10101010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Orn, typeof(AOpCodeAluRs));
- SetA64("0011001000xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Orr, typeof(AOpCodeAluImm));
- SetA64("101100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Orr, typeof(AOpCodeAluImm));
- SetA64("00101010xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Orr, typeof(AOpCodeAluRs));
- SetA64("10101010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Orr, typeof(AOpCodeAluRs));
- SetA64("1111100110xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Pfrm, typeof(AOpCodeMemImm));
- SetA64("11111000100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Pfrm, typeof(AOpCodeMemImm));
- SetA64("11011000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Pfrm, typeof(AOpCodeMemLit));
- SetA64("x101101011000000000000xxxxxxxxxx", AInstEmit.Rbit, typeof(AOpCodeAlu));
- SetA64("1101011001011111000000xxxxx00000", AInstEmit.Ret, typeof(AOpCodeBReg));
- SetA64("x101101011000000000001xxxxxxxxxx", AInstEmit.Rev16, typeof(AOpCodeAlu));
- SetA64("x101101011000000000010xxxxxxxxxx", AInstEmit.Rev32, typeof(AOpCodeAlu));
- SetA64("1101101011000000000011xxxxxxxxxx", AInstEmit.Rev64, typeof(AOpCodeAlu));
- SetA64("x0011010110xxxxx001011xxxxxxxxxx", AInstEmit.Rorv, typeof(AOpCodeAluRs));
- SetA64("x1011010000xxxxx000000xxxxxxxxxx", AInstEmit.Sbc, typeof(AOpCodeAluRs));
- SetA64("x1111010000xxxxx000000xxxxxxxxxx", AInstEmit.Sbcs, typeof(AOpCodeAluRs));
- SetA64("00010011000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Sbfm, typeof(AOpCodeBfm));
- SetA64("1001001101xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sbfm, typeof(AOpCodeBfm));
- SetA64("x0011010110xxxxx000011xxxxxxxxxx", AInstEmit.Sdiv, typeof(AOpCodeAluRs));
- SetA64("10011011001xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Smaddl, typeof(AOpCodeMul));
- SetA64("10011011001xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Smsubl, typeof(AOpCodeMul));
- SetA64("10011011010xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Smulh, typeof(AOpCodeMul));
- SetA64("xx001000100xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Stlr, typeof(AOpCodeMemEx));
- SetA64("1x001000001xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Stlxp, typeof(AOpCodeMemEx));
- SetA64("xx001000000xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Stlxr, typeof(AOpCodeMemEx));
- SetA64("x010100xx0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Stp, typeof(AOpCodeMemPair));
- SetA64("xx111000000xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeMemImm));
- SetA64("xx11100100xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeMemImm));
- SetA64("xx111000001xxxxxxxxx10xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeMemReg));
- SetA64("1x001000001xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Stxp, typeof(AOpCodeMemEx));
- SetA64("xx001000000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Stxr, typeof(AOpCodeMemEx));
- SetA64("x10100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluImm));
- SetA64("01001011<<0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRs));
- SetA64("11001011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRs));
- SetA64("x1001011001xxxxxxxx0xxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRx));
- SetA64("x1001011001xxxxxxxx100xxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRx));
- SetA64("x11100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluImm));
- SetA64("01101011<<0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRs));
- SetA64("11101011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRs));
- SetA64("x1101011001xxxxxxxx0xxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRx));
- SetA64("x1101011001xxxxxxxx100xxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRx));
- SetA64("11010100000xxxxxxxxxxxxxxxx00001", AInstEmit.Svc, typeof(AOpCodeException));
- SetA64("1101010100001xxxxxxxxxxxxxxxxxxx", AInstEmit.Sys, typeof(AOpCodeSystem));
- SetA64("x0110111xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Tbnz, typeof(AOpCodeBImmTest));
- SetA64("x0110110xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Tbz, typeof(AOpCodeBImmTest));
- SetA64("01010011000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Ubfm, typeof(AOpCodeBfm));
- SetA64("1101001101xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ubfm, typeof(AOpCodeBfm));
- SetA64("x0011010110xxxxx000010xxxxxxxxxx", AInstEmit.Udiv, typeof(AOpCodeAluRs));
- SetA64("10011011101xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Umaddl, typeof(AOpCodeMul));
- SetA64("10011011101xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Umsubl, typeof(AOpCodeMul));
- SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Umulh, typeof(AOpCodeMul));
-
- //Vector
- SetA64("0101111011100000101110xxxxxxxxxx", AInstEmit.Abs_S, typeof(AOpCodeSimd));
- SetA64("0>001110<<100000101110xxxxxxxxxx", AInstEmit.Abs_V, typeof(AOpCodeSimd));
- SetA64("01011110111xxxxx100001xxxxxxxxxx", AInstEmit.Add_S, typeof(AOpCodeSimdReg));
- SetA64("0>001110<<1xxxxx100001xxxxxxxxxx", AInstEmit.Add_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx010000xxxxxxxxxx", AInstEmit.Addhn_V, typeof(AOpCodeSimdReg));
- SetA64("0101111011110001101110xxxxxxxxxx", AInstEmit.Addp_S, typeof(AOpCodeSimd));
- SetA64("0>001110<<1xxxxx101111xxxxxxxxxx", AInstEmit.Addp_V, typeof(AOpCodeSimdReg));
- SetA64("000011100x110001101110xxxxxxxxxx", AInstEmit.Addv_V, typeof(AOpCodeSimd));
- SetA64("01001110<<110001101110xxxxxxxxxx", AInstEmit.Addv_V, typeof(AOpCodeSimd));
- SetA64("0100111000101000010110xxxxxxxxxx", AInstEmit.Aesd_V, typeof(AOpCodeSimd));
- SetA64("0100111000101000010010xxxxxxxxxx", AInstEmit.Aese_V, typeof(AOpCodeSimd));
- SetA64("0100111000101000011110xxxxxxxxxx", AInstEmit.Aesimc_V, typeof(AOpCodeSimd));
- SetA64("0100111000101000011010xxxxxxxxxx", AInstEmit.Aesmc_V, typeof(AOpCodeSimd));
- SetA64("0x001110001xxxxx000111xxxxxxxxxx", AInstEmit.And_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110011xxxxx000111xxxxxxxxxx", AInstEmit.Bic_V, typeof(AOpCodeSimdReg));
- SetA64("0x10111100000xxx<<x101xxxxxxxxxx", AInstEmit.Bic_Vi, typeof(AOpCodeSimdImm));
- SetA64("0x101110111xxxxx000111xxxxxxxxxx", AInstEmit.Bif_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110101xxxxx000111xxxxxxxxxx", AInstEmit.Bit_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110011xxxxx000111xxxxxxxxxx", AInstEmit.Bsl_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<100000010010xxxxxxxxxx", AInstEmit.Cls_V, typeof(AOpCodeSimd));
- SetA64("0x101110<<100000010010xxxxxxxxxx", AInstEmit.Clz_V, typeof(AOpCodeSimd));
- SetA64("01111110111xxxxx100011xxxxxxxxxx", AInstEmit.Cmeq_S, typeof(AOpCodeSimdReg));
- SetA64("0101111011100000100110xxxxxxxxxx", AInstEmit.Cmeq_S, typeof(AOpCodeSimd));
- SetA64("0>101110<<1xxxxx100011xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimdReg));
- SetA64("0>001110<<100000100110xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimd));
- SetA64("01011110111xxxxx001111xxxxxxxxxx", AInstEmit.Cmge_S, typeof(AOpCodeSimdReg));
- SetA64("0111111011100000100010xxxxxxxxxx", AInstEmit.Cmge_S, typeof(AOpCodeSimd));
- SetA64("0>001110<<1xxxxx001111xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimdReg));
- SetA64("0>101110<<100000100010xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimd));
- SetA64("01011110111xxxxx001101xxxxxxxxxx", AInstEmit.Cmgt_S, typeof(AOpCodeSimdReg));
- SetA64("0101111011100000100010xxxxxxxxxx", AInstEmit.Cmgt_S, typeof(AOpCodeSimd));
- SetA64("0>001110<<1xxxxx001101xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimdReg));
- SetA64("0>001110<<100000100010xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimd));
- SetA64("01111110111xxxxx001101xxxxxxxxxx", AInstEmit.Cmhi_S, typeof(AOpCodeSimdReg));
- SetA64("0>101110<<1xxxxx001101xxxxxxxxxx", AInstEmit.Cmhi_V, typeof(AOpCodeSimdReg));
- SetA64("01111110111xxxxx001111xxxxxxxxxx", AInstEmit.Cmhs_S, typeof(AOpCodeSimdReg));
- SetA64("0>101110<<1xxxxx001111xxxxxxxxxx", AInstEmit.Cmhs_V, typeof(AOpCodeSimdReg));
- SetA64("0111111011100000100110xxxxxxxxxx", AInstEmit.Cmle_S, typeof(AOpCodeSimd));
- SetA64("0>101110<<100000100110xxxxxxxxxx", AInstEmit.Cmle_V, typeof(AOpCodeSimd));
- SetA64("0101111011100000101010xxxxxxxxxx", AInstEmit.Cmlt_S, typeof(AOpCodeSimd));
- SetA64("0>001110<<100000101010xxxxxxxxxx", AInstEmit.Cmlt_V, typeof(AOpCodeSimd));
- SetA64("01011110111xxxxx100011xxxxxxxxxx", AInstEmit.Cmtst_S, typeof(AOpCodeSimdReg));
- SetA64("0>001110<<1xxxxx100011xxxxxxxxxx", AInstEmit.Cmtst_V, typeof(AOpCodeSimdReg));
- SetA64("0x00111000100000010110xxxxxxxxxx", AInstEmit.Cnt_V, typeof(AOpCodeSimd));
- SetA64("0x001110000xxxxx000011xxxxxxxxxx", AInstEmit.Dup_Gp, typeof(AOpCodeSimdIns));
- SetA64("01011110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_S, typeof(AOpCodeSimdIns));
- SetA64("0x001110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_V, typeof(AOpCodeSimdIns));
- SetA64("0x101110001xxxxx000111xxxxxxxxxx", AInstEmit.Eor_V, typeof(AOpCodeSimdReg));
- SetA64("0>101110000xxxxx0<xxx0xxxxxxxxxx", AInstEmit.Ext_V, typeof(AOpCodeSimdExt));
- SetA64("011111101x1xxxxx110101xxxxxxxxxx", AInstEmit.Fabd_S, typeof(AOpCodeSimdReg));
- SetA64("000111100x100000110000xxxxxxxxxx", AInstEmit.Fabs_S, typeof(AOpCodeSimd));
- SetA64("0>0011101<100000111110xxxxxxxxxx", AInstEmit.Fabs_V, typeof(AOpCodeSimd));
- SetA64("000111100x1xxxxx001010xxxxxxxxxx", AInstEmit.Fadd_S, typeof(AOpCodeSimdReg));
- SetA64("0>0011100<1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg));
- SetA64("011111100x110000110110xxxxxxxxxx", AInstEmit.Faddp_S, typeof(AOpCodeSimd));
- SetA64("0>1011100<1xxxxx110101xxxxxxxxxx", AInstEmit.Faddp_V, typeof(AOpCodeSimdReg));
- SetA64("000111100x1xxxxxxxxx01xxxxx0xxxx", AInstEmit.Fccmp_S, typeof(AOpCodeSimdFcond));
- SetA64("000111100x1xxxxxxxxx01xxxxx1xxxx", AInstEmit.Fccmpe_S, typeof(AOpCodeSimdFcond));
- SetA64("010111100x1xxxxx111001xxxxxxxxxx", AInstEmit.Fcmeq_S, typeof(AOpCodeSimdReg));
- SetA64("010111101x100000110110xxxxxxxxxx", AInstEmit.Fcmeq_S, typeof(AOpCodeSimd));
- SetA64("0>0011100<1xxxxx111001xxxxxxxxxx", AInstEmit.Fcmeq_V, typeof(AOpCodeSimdReg));
- SetA64("0>0011101<100000110110xxxxxxxxxx", AInstEmit.Fcmeq_V, typeof(AOpCodeSimd));
- SetA64("011111100x1xxxxx111001xxxxxxxxxx", AInstEmit.Fcmge_S, typeof(AOpCodeSimdReg));
- SetA64("011111101x100000110010xxxxxxxxxx", AInstEmit.Fcmge_S, typeof(AOpCodeSimd));
- SetA64("0>1011100<1xxxxx111001xxxxxxxxxx", AInstEmit.Fcmge_V, typeof(AOpCodeSimdReg));
- SetA64("0>1011101<100000110010xxxxxxxxxx", AInstEmit.Fcmge_V, typeof(AOpCodeSimd));
- SetA64("011111101x1xxxxx111001xxxxxxxxxx", AInstEmit.Fcmgt_S, typeof(AOpCodeSimdReg));
- SetA64("010111101x100000110010xxxxxxxxxx", AInstEmit.Fcmgt_S, typeof(AOpCodeSimd));
- SetA64("0>1011101<1xxxxx111001xxxxxxxxxx", AInstEmit.Fcmgt_V, typeof(AOpCodeSimdReg));
- SetA64("0>0011101<100000110010xxxxxxxxxx", AInstEmit.Fcmgt_V, typeof(AOpCodeSimd));
- SetA64("011111101x100000110110xxxxxxxxxx", AInstEmit.Fcmle_S, typeof(AOpCodeSimd));
- SetA64("0>1011101<100000110110xxxxxxxxxx", AInstEmit.Fcmle_V, typeof(AOpCodeSimd));
- SetA64("010111101x100000111010xxxxxxxxxx", AInstEmit.Fcmlt_S, typeof(AOpCodeSimd));
- SetA64("0>0011101<100000111010xxxxxxxxxx", AInstEmit.Fcmlt_V, typeof(AOpCodeSimd));
- SetA64("000111100x1xxxxx001000xxxxx0x000", AInstEmit.Fcmp_S, typeof(AOpCodeSimdReg));
- SetA64("000111100x1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S, typeof(AOpCodeSimdReg));
- SetA64("000111100x1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond));
- SetA64("000111100x10001xx10000xxxxxxxxxx", AInstEmit.Fcvt_S, typeof(AOpCodeSimd));
- SetA64("x00111100x100100000000xxxxxxxxxx", AInstEmit.Fcvtas_Gp, typeof(AOpCodeSimdCvt));
- SetA64("x00111100x100101000000xxxxxxxxxx", AInstEmit.Fcvtau_Gp, typeof(AOpCodeSimdCvt));
- SetA64("0x0011100x100001011110xxxxxxxxxx", AInstEmit.Fcvtl_V, typeof(AOpCodeSimd));
- SetA64("x00111100x110000000000xxxxxxxxxx", AInstEmit.Fcvtms_Gp, typeof(AOpCodeSimdCvt));
- SetA64("x00111100x110001000000xxxxxxxxxx", AInstEmit.Fcvtmu_Gp, typeof(AOpCodeSimdCvt));
- SetA64("0x0011100x100001011010xxxxxxxxxx", AInstEmit.Fcvtn_V, typeof(AOpCodeSimd));
- SetA64("010111100x100001101010xxxxxxxxxx", AInstEmit.Fcvtns_S, typeof(AOpCodeSimd));
- SetA64("0>0011100<100001101010xxxxxxxxxx", AInstEmit.Fcvtns_V, typeof(AOpCodeSimd));
- SetA64("011111100x100001101010xxxxxxxxxx", AInstEmit.Fcvtnu_S, typeof(AOpCodeSimd));
- SetA64("0>1011100<100001101010xxxxxxxxxx", AInstEmit.Fcvtnu_V, typeof(AOpCodeSimd));
- SetA64("x00111100x101000000000xxxxxxxxxx", AInstEmit.Fcvtps_Gp, typeof(AOpCodeSimdCvt));
- SetA64("x00111100x101001000000xxxxxxxxxx", AInstEmit.Fcvtpu_Gp, typeof(AOpCodeSimdCvt));
- SetA64("x00111100x111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_Gp, typeof(AOpCodeSimdCvt));
- SetA64("x00111100x011000xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzs_Gp_Fix, typeof(AOpCodeSimdCvt));
- SetA64("010111101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_S, typeof(AOpCodeSimd));
- SetA64("0>0011101<100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd));
- SetA64("0x0011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimdShImm));
- SetA64("x00111100x111001000000xxxxxxxxxx", AInstEmit.Fcvtzu_Gp, typeof(AOpCodeSimdCvt));
- SetA64("x00111100x011001xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzu_Gp_Fix, typeof(AOpCodeSimdCvt));
- SetA64("011111101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_S, typeof(AOpCodeSimd));
- SetA64("0>1011101<100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimd));
- SetA64("0x1011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimdShImm));
- SetA64("000111100x1xxxxx000110xxxxxxxxxx", AInstEmit.Fdiv_S, typeof(AOpCodeSimdReg));
- SetA64("0>1011100<1xxxxx111111xxxxxxxxxx", AInstEmit.Fdiv_V, typeof(AOpCodeSimdReg));
- SetA64("000111110x0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fmadd_S, typeof(AOpCodeSimdReg));
- SetA64("000111100x1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg));
- SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", AInstEmit.Fmax_V, typeof(AOpCodeSimdReg));
- SetA64("000111100x1xxxxx011010xxxxxxxxxx", AInstEmit.Fmaxnm_S, typeof(AOpCodeSimdReg));
- SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", AInstEmit.Fmaxnm_V, typeof(AOpCodeSimdReg));
- SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", AInstEmit.Fmaxp_V, typeof(AOpCodeSimdReg));
- SetA64("000111100x1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg));
- SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", AInstEmit.Fmin_V, typeof(AOpCodeSimdReg));
- SetA64("000111100x1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg));
- SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", AInstEmit.Fminnm_V, typeof(AOpCodeSimdReg));
- SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", AInstEmit.Fminp_V, typeof(AOpCodeSimdReg));
- SetA64("010111111xxxxxxx0001x0xxxxxxxxxx", AInstEmit.Fmla_Se, typeof(AOpCodeSimdRegElemF));
- SetA64("0>0011100<1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg));
- SetA64("0>0011111<xxxxxx0001x0xxxxxxxxxx", AInstEmit.Fmla_Ve, typeof(AOpCodeSimdRegElemF));
- SetA64("010111111xxxxxxx0101x0xxxxxxxxxx", AInstEmit.Fmls_Se, typeof(AOpCodeSimdRegElemF));
- SetA64("0>0011101<1xxxxx110011xxxxxxxxxx", AInstEmit.Fmls_V, typeof(AOpCodeSimdReg));
- SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", AInstEmit.Fmls_Ve, typeof(AOpCodeSimdRegElemF));
- SetA64("000111100x100000010000xxxxxxxxxx", AInstEmit.Fmov_S, typeof(AOpCodeSimd));
- SetA64("00011110xx1xxxxxxxx100xxxxxxxxxx", AInstEmit.Fmov_Si, typeof(AOpCodeSimdFmov));
- SetA64("0xx0111100000xxx111101xxxxxxxxxx", AInstEmit.Fmov_V, typeof(AOpCodeSimdImm));
- SetA64("x00111100x100110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi, typeof(AOpCodeSimdCvt));
- SetA64("x00111100x100111000000xxxxxxxxxx", AInstEmit.Fmov_Itof, typeof(AOpCodeSimdCvt));
- SetA64("1001111010101110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi1, typeof(AOpCodeSimdCvt));
- SetA64("1001111010101111000000xxxxxxxxxx", AInstEmit.Fmov_Itof1, typeof(AOpCodeSimdCvt));
- SetA64("000111110x0xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fmsub_S, typeof(AOpCodeSimdReg));
- SetA64("000111100x1xxxxx000010xxxxxxxxxx", AInstEmit.Fmul_S, typeof(AOpCodeSimdReg));
- SetA64("010111111xxxxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Se, typeof(AOpCodeSimdRegElemF));
- SetA64("0>1011100<1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg));
- SetA64("0>0011111<xxxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Ve, typeof(AOpCodeSimdRegElemF));
- SetA64("010111100x1xxxxx110111xxxxxxxxxx", AInstEmit.Fmulx_S, typeof(AOpCodeSimdReg));
- SetA64("011111111xxxxxxx1001x0xxxxxxxxxx", AInstEmit.Fmulx_Se, typeof(AOpCodeSimdRegElemF));
- SetA64("0>0011100<1xxxxx110111xxxxxxxxxx", AInstEmit.Fmulx_V, typeof(AOpCodeSimdReg));
- SetA64("0>1011111<xxxxxx1001x0xxxxxxxxxx", AInstEmit.Fmulx_Ve, typeof(AOpCodeSimdRegElemF));
- SetA64("000111100x100001010000xxxxxxxxxx", AInstEmit.Fneg_S, typeof(AOpCodeSimd));
- SetA64("0>1011101<100000111110xxxxxxxxxx", AInstEmit.Fneg_V, typeof(AOpCodeSimd));
- SetA64("000111110x1xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fnmadd_S, typeof(AOpCodeSimdReg));
- SetA64("000111110x1xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fnmsub_S, typeof(AOpCodeSimdReg));
- SetA64("000111100x1xxxxx100010xxxxxxxxxx", AInstEmit.Fnmul_S, typeof(AOpCodeSimdReg));
- SetA64("010111101x100001110110xxxxxxxxxx", AInstEmit.Frecpe_S, typeof(AOpCodeSimd));
- SetA64("0>0011101<100001110110xxxxxxxxxx", AInstEmit.Frecpe_V, typeof(AOpCodeSimd));
- SetA64("010111100x1xxxxx111111xxxxxxxxxx", AInstEmit.Frecps_S, typeof(AOpCodeSimdReg));
- SetA64("0>0011100<1xxxxx111111xxxxxxxxxx", AInstEmit.Frecps_V, typeof(AOpCodeSimdReg));
- SetA64("010111101x100001111110xxxxxxxxxx", AInstEmit.Frecpx_S, typeof(AOpCodeSimd));
- SetA64("000111100x100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd));
- SetA64("0>1011100<100001100010xxxxxxxxxx", AInstEmit.Frinta_V, typeof(AOpCodeSimd));
- SetA64("000111100x100111110000xxxxxxxxxx", AInstEmit.Frinti_S, typeof(AOpCodeSimd));
- SetA64("0>1011101<100001100110xxxxxxxxxx", AInstEmit.Frinti_V, typeof(AOpCodeSimd));
- SetA64("000111100x100101010000xxxxxxxxxx", AInstEmit.Frintm_S, typeof(AOpCodeSimd));
- SetA64("0>0011100<100001100110xxxxxxxxxx", AInstEmit.Frintm_V, typeof(AOpCodeSimd));
- SetA64("000111100x100100010000xxxxxxxxxx", AInstEmit.Frintn_S, typeof(AOpCodeSimd));
- SetA64("0>0011100<100001100010xxxxxxxxxx", AInstEmit.Frintn_V, typeof(AOpCodeSimd));
- SetA64("000111100x100100110000xxxxxxxxxx", AInstEmit.Frintp_S, typeof(AOpCodeSimd));
- SetA64("0>0011101<100001100010xxxxxxxxxx", AInstEmit.Frintp_V, typeof(AOpCodeSimd));
- SetA64("000111100x100111010000xxxxxxxxxx", AInstEmit.Frintx_S, typeof(AOpCodeSimd));
- SetA64("0>1011100<100001100110xxxxxxxxxx", AInstEmit.Frintx_V, typeof(AOpCodeSimd));
- SetA64("011111101x100001110110xxxxxxxxxx", AInstEmit.Frsqrte_S, typeof(AOpCodeSimd));
- SetA64("0>1011101<100001110110xxxxxxxxxx", AInstEmit.Frsqrte_V, typeof(AOpCodeSimd));
- SetA64("010111101x1xxxxx111111xxxxxxxxxx", AInstEmit.Frsqrts_S, typeof(AOpCodeSimdReg));
- SetA64("0>0011101<1xxxxx111111xxxxxxxxxx", AInstEmit.Frsqrts_V, typeof(AOpCodeSimdReg));
- SetA64("000111100x100001110000xxxxxxxxxx", AInstEmit.Fsqrt_S, typeof(AOpCodeSimd));
- SetA64("0>1011101<100001111110xxxxxxxxxx", AInstEmit.Fsqrt_V, typeof(AOpCodeSimd));
- SetA64("000111100x1xxxxx001110xxxxxxxxxx", AInstEmit.Fsub_S, typeof(AOpCodeSimdReg));
- SetA64("0>0011101<1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg));
- SetA64("01001110000xxxxx000111xxxxxxxxxx", AInstEmit.Ins_Gp, typeof(AOpCodeSimdIns));
- SetA64("01101110000xxxxx0xxxx1xxxxxxxxxx", AInstEmit.Ins_V, typeof(AOpCodeSimdIns));
- SetA64("0x00110001000000xxxxxxxxxxxxxxxx", AInstEmit.Ld__Vms, typeof(AOpCodeSimdMemMs));
- SetA64("0x001100110xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ld__Vms, typeof(AOpCodeSimdMemMs));
- SetA64("0x00110101x00000xxxxxxxxxxxxxxxx", AInstEmit.Ld__Vss, typeof(AOpCodeSimdMemSs));
- SetA64("0x00110111xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ld__Vss, typeof(AOpCodeSimdMemSs));
- SetA64("xx10110xx1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldp, typeof(AOpCodeSimdMemPair));
- SetA64("xx111100x10xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
- SetA64("xx111100x10xxxxxxxxx01xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
- SetA64("xx111100x10xxxxxxxxx11xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
- SetA64("xx111101x1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
- SetA64("xx111100x11xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemReg));
- SetA64("xx011100xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.LdrLit, typeof(AOpCodeSimdMemLit));
- SetA64("0x001110<<1xxxxx100101xxxxxxxxxx", AInstEmit.Mla_V, typeof(AOpCodeSimdReg));
- SetA64("0x101111xxxxxxxx0000x0xxxxxxxxxx", AInstEmit.Mla_Ve, typeof(AOpCodeSimdRegElem));
- SetA64("0x101110<<1xxxxx100101xxxxxxxxxx", AInstEmit.Mls_V, typeof(AOpCodeSimdReg));
- SetA64("0x101111xxxxxxxx0100x0xxxxxxxxxx", AInstEmit.Mls_Ve, typeof(AOpCodeSimdRegElem));
- SetA64("0x00111100000xxx0xx001xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
- SetA64("0x00111100000xxx10x001xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
- SetA64("0x00111100000xxx110x01xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
- SetA64("0xx0111100000xxx111001xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
- SetA64("0x001110<<1xxxxx100111xxxxxxxxxx", AInstEmit.Mul_V, typeof(AOpCodeSimdReg));
- SetA64("0x001111xxxxxxxx1000x0xxxxxxxxxx", AInstEmit.Mul_Ve, typeof(AOpCodeSimdRegElem));
- SetA64("0x10111100000xxx0xx001xxxxxxxxxx", AInstEmit.Mvni_V, typeof(AOpCodeSimdImm));
- SetA64("0x10111100000xxx10x001xxxxxxxxxx", AInstEmit.Mvni_V, typeof(AOpCodeSimdImm));
- SetA64("0x10111100000xxx110x01xxxxxxxxxx", AInstEmit.Mvni_V, typeof(AOpCodeSimdImm));
- SetA64("0111111011100000101110xxxxxxxxxx", AInstEmit.Neg_S, typeof(AOpCodeSimd));
- SetA64("0>101110<<100000101110xxxxxxxxxx", AInstEmit.Neg_V, typeof(AOpCodeSimd));
- SetA64("0x10111000100000010110xxxxxxxxxx", AInstEmit.Not_V, typeof(AOpCodeSimd));
- SetA64("0x001110111xxxxx000111xxxxxxxxxx", AInstEmit.Orn_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110101xxxxx000111xxxxxxxxxx", AInstEmit.Orr_V, typeof(AOpCodeSimdReg));
- SetA64("0x00111100000xxx<<x101xxxxxxxxxx", AInstEmit.Orr_Vi, typeof(AOpCodeSimdImm));
- SetA64("0x101110<<1xxxxx010000xxxxxxxxxx", AInstEmit.Raddhn_V, typeof(AOpCodeSimdReg));
- SetA64("0x10111001100000010110xxxxxxxxxx", AInstEmit.Rbit_V, typeof(AOpCodeSimd));
- SetA64("0x00111000100000000110xxxxxxxxxx", AInstEmit.Rev16_V, typeof(AOpCodeSimd));
- SetA64("0x1011100x100000000010xxxxxxxxxx", AInstEmit.Rev32_V, typeof(AOpCodeSimd));
- SetA64("0x001110<<100000000010xxxxxxxxxx", AInstEmit.Rev64_V, typeof(AOpCodeSimd));
- SetA64("0x00111100>>>xxx100011xxxxxxxxxx", AInstEmit.Rshrn_V, typeof(AOpCodeSimdShImm));
- SetA64("0x101110<<1xxxxx011000xxxxxxxxxx", AInstEmit.Rsubhn_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx011111xxxxxxxxxx", AInstEmit.Saba_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx010100xxxxxxxxxx", AInstEmit.Sabal_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx011101xxxxxxxxxx", AInstEmit.Sabd_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx011100xxxxxxxxxx", AInstEmit.Sabdl_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<100000011010xxxxxxxxxx", AInstEmit.Sadalp_V, typeof(AOpCodeSimd));
- SetA64("0x001110<<1xxxxx000000xxxxxxxxxx", AInstEmit.Saddl_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<100000001010xxxxxxxxxx", AInstEmit.Saddlp_V, typeof(AOpCodeSimd));
- SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", AInstEmit.Saddw_V, typeof(AOpCodeSimdReg));
- SetA64("x0011110xx100010000000xxxxxxxxxx", AInstEmit.Scvtf_Gp, typeof(AOpCodeSimdCvt));
- SetA64("010111100x100001110110xxxxxxxxxx", AInstEmit.Scvtf_S, typeof(AOpCodeSimd));
- SetA64("0x0011100x100001110110xxxxxxxxxx", AInstEmit.Scvtf_V, typeof(AOpCodeSimd));
- SetA64("01011110000xxxxx000000xxxxxxxxxx", AInstEmit.Sha1c_V, typeof(AOpCodeSimdReg));
- SetA64("0101111000101000000010xxxxxxxxxx", AInstEmit.Sha1h_V, typeof(AOpCodeSimd));
- SetA64("01011110000xxxxx001000xxxxxxxxxx", AInstEmit.Sha1m_V, typeof(AOpCodeSimdReg));
- SetA64("01011110000xxxxx000100xxxxxxxxxx", AInstEmit.Sha1p_V, typeof(AOpCodeSimdReg));
- SetA64("01011110000xxxxx001100xxxxxxxxxx", AInstEmit.Sha1su0_V, typeof(AOpCodeSimdReg));
- SetA64("0101111000101000000110xxxxxxxxxx", AInstEmit.Sha1su1_V, typeof(AOpCodeSimd));
- SetA64("01011110000xxxxx010000xxxxxxxxxx", AInstEmit.Sha256h_V, typeof(AOpCodeSimdReg));
- SetA64("01011110000xxxxx010100xxxxxxxxxx", AInstEmit.Sha256h2_V, typeof(AOpCodeSimdReg));
- SetA64("0101111000101000001010xxxxxxxxxx", AInstEmit.Sha256su0_V, typeof(AOpCodeSimd));
- SetA64("01011110000xxxxx011000xxxxxxxxxx", AInstEmit.Sha256su1_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx000001xxxxxxxxxx", AInstEmit.Shadd_V, typeof(AOpCodeSimdReg));
- SetA64("0101111101xxxxxx010101xxxxxxxxxx", AInstEmit.Shl_S, typeof(AOpCodeSimdShImm));
- SetA64("0x00111100>>>xxx010101xxxxxxxxxx", AInstEmit.Shl_V, typeof(AOpCodeSimdShImm));
- SetA64("0100111101xxxxxx010101xxxxxxxxxx", AInstEmit.Shl_V, typeof(AOpCodeSimdShImm));
- SetA64("0x101110<<100001001110xxxxxxxxxx", AInstEmit.Shll_V, typeof(AOpCodeSimd));
- SetA64("0x00111100>>>xxx100001xxxxxxxxxx", AInstEmit.Shrn_V, typeof(AOpCodeSimdShImm));
- SetA64("0x001110<<1xxxxx001001xxxxxxxxxx", AInstEmit.Shsub_V, typeof(AOpCodeSimdReg));
- SetA64("0x1011110>>>>xxx010101xxxxxxxxxx", AInstEmit.Sli_V, typeof(AOpCodeSimdShImm));
- SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", AInstEmit.Smaxp_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", AInstEmit.Sminp_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx100000xxxxxxxxxx", AInstEmit.Smlal_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx101000xxxxxxxxxx", AInstEmit.Smlsl_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110000xxxxx001011xxxxxxxxxx", AInstEmit.Smov_S, typeof(AOpCodeSimdIns));
- SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Smull_V, typeof(AOpCodeSimdReg));
- SetA64("01011110xx100000011110xxxxxxxxxx", AInstEmit.Sqabs_S, typeof(AOpCodeSimd));
- SetA64("0>001110<<100000011110xxxxxxxxxx", AInstEmit.Sqabs_V, typeof(AOpCodeSimd));
- SetA64("01011110xx1xxxxx000011xxxxxxxxxx", AInstEmit.Sqadd_S, typeof(AOpCodeSimdReg));
- SetA64("0>001110<<1xxxxx000011xxxxxxxxxx", AInstEmit.Sqadd_V, typeof(AOpCodeSimdReg));
- SetA64("01011110011xxxxx101101xxxxxxxxxx", AInstEmit.Sqdmulh_S, typeof(AOpCodeSimdReg));
- SetA64("01011110101xxxxx101101xxxxxxxxxx", AInstEmit.Sqdmulh_S, typeof(AOpCodeSimdReg));
- SetA64("0x001110011xxxxx101101xxxxxxxxxx", AInstEmit.Sqdmulh_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110101xxxxx101101xxxxxxxxxx", AInstEmit.Sqdmulh_V, typeof(AOpCodeSimdReg));
- SetA64("01111110xx100000011110xxxxxxxxxx", AInstEmit.Sqneg_S, typeof(AOpCodeSimd));
- SetA64("0>101110<<100000011110xxxxxxxxxx", AInstEmit.Sqneg_V, typeof(AOpCodeSimd));
- SetA64("01111110011xxxxx101101xxxxxxxxxx", AInstEmit.Sqrdmulh_S, typeof(AOpCodeSimdReg));
- SetA64("01111110101xxxxx101101xxxxxxxxxx", AInstEmit.Sqrdmulh_S, typeof(AOpCodeSimdReg));
- SetA64("0x101110011xxxxx101101xxxxxxxxxx", AInstEmit.Sqrdmulh_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110101xxxxx101101xxxxxxxxxx", AInstEmit.Sqrdmulh_V, typeof(AOpCodeSimdReg));
- SetA64("0101111100>>>xxx100111xxxxxxxxxx", AInstEmit.Sqrshrn_S, typeof(AOpCodeSimdShImm));
- SetA64("0x00111100>>>xxx100111xxxxxxxxxx", AInstEmit.Sqrshrn_V, typeof(AOpCodeSimdShImm));
- SetA64("0111111100>>>xxx100011xxxxxxxxxx", AInstEmit.Sqrshrun_S, typeof(AOpCodeSimdShImm));
- SetA64("0x10111100>>>xxx100011xxxxxxxxxx", AInstEmit.Sqrshrun_V, typeof(AOpCodeSimdShImm));
- SetA64("0101111100>>>xxx100101xxxxxxxxxx", AInstEmit.Sqshrn_S, typeof(AOpCodeSimdShImm));
- SetA64("0x00111100>>>xxx100101xxxxxxxxxx", AInstEmit.Sqshrn_V, typeof(AOpCodeSimdShImm));
- SetA64("0111111100>>>xxx100001xxxxxxxxxx", AInstEmit.Sqshrun_S, typeof(AOpCodeSimdShImm));
- SetA64("0x10111100>>>xxx100001xxxxxxxxxx", AInstEmit.Sqshrun_V, typeof(AOpCodeSimdShImm));
- SetA64("01011110xx1xxxxx001011xxxxxxxxxx", AInstEmit.Sqsub_S, typeof(AOpCodeSimdReg));
- SetA64("0>001110<<1xxxxx001011xxxxxxxxxx", AInstEmit.Sqsub_V, typeof(AOpCodeSimdReg));
- SetA64("01011110<<100001010010xxxxxxxxxx", AInstEmit.Sqxtn_S, typeof(AOpCodeSimd));
- SetA64("0x001110<<100001010010xxxxxxxxxx", AInstEmit.Sqxtn_V, typeof(AOpCodeSimd));
- SetA64("01111110<<100001001010xxxxxxxxxx", AInstEmit.Sqxtun_S, typeof(AOpCodeSimd));
- SetA64("0x101110<<100001001010xxxxxxxxxx", AInstEmit.Sqxtun_V, typeof(AOpCodeSimd));
- SetA64("0x001110<<1xxxxx000101xxxxxxxxxx", AInstEmit.Srhadd_V, typeof(AOpCodeSimdReg));
- SetA64("0101111101xxxxxx001001xxxxxxxxxx", AInstEmit.Srshr_S, typeof(AOpCodeSimdShImm));
- SetA64("0x00111100>>>xxx001001xxxxxxxxxx", AInstEmit.Srshr_V, typeof(AOpCodeSimdShImm));
- SetA64("0100111101xxxxxx001001xxxxxxxxxx", AInstEmit.Srshr_V, typeof(AOpCodeSimdShImm));
- SetA64("0101111101xxxxxx001101xxxxxxxxxx", AInstEmit.Srsra_S, typeof(AOpCodeSimdShImm));
- SetA64("0x00111100>>>xxx001101xxxxxxxxxx", AInstEmit.Srsra_V, typeof(AOpCodeSimdShImm));
- SetA64("0100111101xxxxxx001101xxxxxxxxxx", AInstEmit.Srsra_V, typeof(AOpCodeSimdShImm));
- SetA64("0>001110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Sshl_V, typeof(AOpCodeSimdReg));
- SetA64("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
- SetA64("0101111101xxxxxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
- SetA64("0x00111100>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
- SetA64("0100111101xxxxxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
- SetA64("0101111101xxxxxx000101xxxxxxxxxx", AInstEmit.Ssra_S, typeof(AOpCodeSimdShImm));
- SetA64("0x00111100>>>xxx000101xxxxxxxxxx", AInstEmit.Ssra_V, typeof(AOpCodeSimdShImm));
- SetA64("0100111101xxxxxx000101xxxxxxxxxx", AInstEmit.Ssra_V, typeof(AOpCodeSimdShImm));
- SetA64("0x001110<<1xxxxx001000xxxxxxxxxx", AInstEmit.Ssubl_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx001100xxxxxxxxxx", AInstEmit.Ssubw_V, typeof(AOpCodeSimdReg));
- SetA64("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__Vms, typeof(AOpCodeSimdMemMs));
- SetA64("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__Vms, typeof(AOpCodeSimdMemMs));
- SetA64("0x00110100x00000xxxxxxxxxxxxxxxx", AInstEmit.St__Vss, typeof(AOpCodeSimdMemSs));
- SetA64("0x00110110xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__Vss, typeof(AOpCodeSimdMemSs));
- SetA64("xx10110xx0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Stp, typeof(AOpCodeSimdMemPair));
- SetA64("xx111100x00xxxxxxxxx00xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
- SetA64("xx111100x00xxxxxxxxx01xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
- SetA64("xx111100x00xxxxxxxxx11xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
- SetA64("xx111101x0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
- SetA64("xx111100x01xxxxxxxxx10xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemReg));
- SetA64("01111110111xxxxx100001xxxxxxxxxx", AInstEmit.Sub_S, typeof(AOpCodeSimdReg));
- SetA64("0>101110<<1xxxxx100001xxxxxxxxxx", AInstEmit.Sub_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<1xxxxx011000xxxxxxxxxx", AInstEmit.Subhn_V, typeof(AOpCodeSimdReg));
- SetA64("01011110xx100000001110xxxxxxxxxx", AInstEmit.Suqadd_S, typeof(AOpCodeSimd));
- SetA64("0>001110<<100000001110xxxxxxxxxx", AInstEmit.Suqadd_V, typeof(AOpCodeSimd));
- SetA64("0x001110000xxxxx0xx000xxxxxxxxxx", AInstEmit.Tbl_V, typeof(AOpCodeSimdTbl));
- SetA64("0>001110<<0xxxxx001010xxxxxxxxxx", AInstEmit.Trn1_V, typeof(AOpCodeSimdReg));
- SetA64("0>001110<<0xxxxx011010xxxxxxxxxx", AInstEmit.Trn2_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<1xxxxx011111xxxxxxxxxx", AInstEmit.Uaba_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<1xxxxx010100xxxxxxxxxx", AInstEmit.Uabal_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<1xxxxx011101xxxxxxxxxx", AInstEmit.Uabd_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<1xxxxx011100xxxxxxxxxx", AInstEmit.Uabdl_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<100000011010xxxxxxxxxx", AInstEmit.Uadalp_V, typeof(AOpCodeSimd));
- SetA64("0x101110<<1xxxxx000000xxxxxxxxxx", AInstEmit.Uaddl_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<100000001010xxxxxxxxxx", AInstEmit.Uaddlp_V, typeof(AOpCodeSimd));
- SetA64("001011100x110000001110xxxxxxxxxx", AInstEmit.Uaddlv_V, typeof(AOpCodeSimd));
- SetA64("01101110<<110000001110xxxxxxxxxx", AInstEmit.Uaddlv_V, typeof(AOpCodeSimd));
- SetA64("0x101110<<1xxxxx000100xxxxxxxxxx", AInstEmit.Uaddw_V, typeof(AOpCodeSimdReg));
- SetA64("x0011110xx100011000000xxxxxxxxxx", AInstEmit.Ucvtf_Gp, typeof(AOpCodeSimdCvt));
- SetA64("011111100x100001110110xxxxxxxxxx", AInstEmit.Ucvtf_S, typeof(AOpCodeSimd));
- SetA64("0x1011100x100001110110xxxxxxxxxx", AInstEmit.Ucvtf_V, typeof(AOpCodeSimd));
- SetA64("0x101110<<1xxxxx000001xxxxxxxxxx", AInstEmit.Uhadd_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<1xxxxx001001xxxxxxxxxx", AInstEmit.Uhsub_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Umax_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<1xxxxx101001xxxxxxxxxx", AInstEmit.Umaxp_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Umin_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", AInstEmit.Uminp_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<1xxxxx100000xxxxxxxxxx", AInstEmit.Umlal_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<1xxxxx101000xxxxxxxxxx", AInstEmit.Umlsl_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110000xxxxx001111xxxxxxxxxx", AInstEmit.Umov_S, typeof(AOpCodeSimdIns));
- SetA64("0x101110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Umull_V, typeof(AOpCodeSimdReg));
- SetA64("01111110xx1xxxxx000011xxxxxxxxxx", AInstEmit.Uqadd_S, typeof(AOpCodeSimdReg));
- SetA64("0>101110<<1xxxxx000011xxxxxxxxxx", AInstEmit.Uqadd_V, typeof(AOpCodeSimdReg));
- SetA64("0111111100>>>xxx100111xxxxxxxxxx", AInstEmit.Uqrshrn_S, typeof(AOpCodeSimdShImm));
- SetA64("0x10111100>>>xxx100111xxxxxxxxxx", AInstEmit.Uqrshrn_V, typeof(AOpCodeSimdShImm));
- SetA64("0111111100>>>xxx100101xxxxxxxxxx", AInstEmit.Uqshrn_S, typeof(AOpCodeSimdShImm));
- SetA64("0x10111100>>>xxx100101xxxxxxxxxx", AInstEmit.Uqshrn_V, typeof(AOpCodeSimdShImm));
- SetA64("01111110xx1xxxxx001011xxxxxxxxxx", AInstEmit.Uqsub_S, typeof(AOpCodeSimdReg));
- SetA64("0>101110<<1xxxxx001011xxxxxxxxxx", AInstEmit.Uqsub_V, typeof(AOpCodeSimdReg));
- SetA64("01111110<<100001010010xxxxxxxxxx", AInstEmit.Uqxtn_S, typeof(AOpCodeSimd));
- SetA64("0x101110<<100001010010xxxxxxxxxx", AInstEmit.Uqxtn_V, typeof(AOpCodeSimd));
- SetA64("0x101110<<1xxxxx000101xxxxxxxxxx", AInstEmit.Urhadd_V, typeof(AOpCodeSimdReg));
- SetA64("0111111101xxxxxx001001xxxxxxxxxx", AInstEmit.Urshr_S, typeof(AOpCodeSimdShImm));
- SetA64("0x10111100>>>xxx001001xxxxxxxxxx", AInstEmit.Urshr_V, typeof(AOpCodeSimdShImm));
- SetA64("0110111101xxxxxx001001xxxxxxxxxx", AInstEmit.Urshr_V, typeof(AOpCodeSimdShImm));
- SetA64("0111111101xxxxxx001101xxxxxxxxxx", AInstEmit.Ursra_S, typeof(AOpCodeSimdShImm));
- SetA64("0x10111100>>>xxx001101xxxxxxxxxx", AInstEmit.Ursra_V, typeof(AOpCodeSimdShImm));
- SetA64("0110111101xxxxxx001101xxxxxxxxxx", AInstEmit.Ursra_V, typeof(AOpCodeSimdShImm));
- SetA64("0>101110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg));
- SetA64("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm));
- SetA64("0111111101xxxxxx000001xxxxxxxxxx", AInstEmit.Ushr_S, typeof(AOpCodeSimdShImm));
- SetA64("0x10111100>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
- SetA64("0110111101xxxxxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
- SetA64("01111110xx100000001110xxxxxxxxxx", AInstEmit.Usqadd_S, typeof(AOpCodeSimd));
- SetA64("0>101110<<100000001110xxxxxxxxxx", AInstEmit.Usqadd_V, typeof(AOpCodeSimd));
- SetA64("0111111101xxxxxx000101xxxxxxxxxx", AInstEmit.Usra_S, typeof(AOpCodeSimdShImm));
- SetA64("0x10111100>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
- SetA64("0110111101xxxxxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
- SetA64("0x101110<<1xxxxx001000xxxxxxxxxx", AInstEmit.Usubl_V, typeof(AOpCodeSimdReg));
- SetA64("0x101110<<1xxxxx001100xxxxxxxxxx", AInstEmit.Usubw_V, typeof(AOpCodeSimdReg));
- SetA64("0>001110<<0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg));
- SetA64("0>001110<<0xxxxx010110xxxxxxxxxx", AInstEmit.Uzp2_V, typeof(AOpCodeSimdReg));
- SetA64("0x001110<<100001001010xxxxxxxxxx", AInstEmit.Xtn_V, typeof(AOpCodeSimd));
- SetA64("0>001110<<0xxxxx001110xxxxxxxxxx", AInstEmit.Zip1_V, typeof(AOpCodeSimdReg));
- SetA64("0>001110<<0xxxxx011110xxxxxxxxxx", AInstEmit.Zip2_V, typeof(AOpCodeSimdReg));
-#endregion
-
-#region "Generate InstA64FastLookup Table (AArch64)"
- var Tmp = new List<InstInfo>[FastLookupSize];
- for (int i = 0; i < FastLookupSize; i++)
- {
- Tmp[i] = new List<InstInfo>();
- }
-
- foreach (var Inst in AllInstA64)
- {
- 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++)
- {
- InstA64FastLookup[i] = Tmp[i].ToArray();
- }
-#endregion
- }
-
- private class InstInfo
- {
- public int Mask;
- public int Value;
-
- public AInst Inst;
-
- public InstInfo(int Mask, int Value, AInst Inst)
- {
- this.Mask = Mask;
- this.Value = Value;
- this.Inst = Inst;
- }
- }
-
- private static List<InstInfo> AllInstA32 = new List<InstInfo>();
- private static List<InstInfo> AllInstA64 = new List<InstInfo>();
-
- private static int FastLookupSize = 0x1000;
- private static InstInfo[][] InstA64FastLookup = new InstInfo[FastLookupSize][];
-
- private static void SetA32(string Encoding, AInstInterpreter Interpreter, Type Type)
- {
- Set(Encoding, new AInst(Interpreter, null, Type), AExecutionMode.AArch32);
- }
-
- private static void SetA64(string Encoding, AInstEmitter Emitter, Type Type)
- {
- Set(Encoding, new AInst(null, Emitter, Type), AExecutionMode.AArch64);
- }
-
- private static void Set(string Encoding, AInst Inst, AExecutionMode 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,
- AInst Inst,
- AExecutionMode Mode)
- {
- InstInfo Info = new InstInfo(XMask, Value, Inst);
-
- if (Mode == AExecutionMode.AArch64)
- {
- AllInstA64.Add(Info);
- }
- else
- {
- AllInstA32.Add(Info);
- }
- }
-
- public static AInst GetInstA32(int OpCode)
- {
- return GetInstFromList(AllInstA32, OpCode);
- }
-
- public static AInst GetInstA64(int OpCode)
- {
- return GetInstFromList(InstA64FastLookup[ToFastLookupIndex(OpCode)], OpCode);
- }
-
- private static int ToFastLookupIndex(int Value)
- {
- return ((Value >> 10) & 0x00F) | ((Value >> 18) & 0xFF0);
- }
-
- private static AInst GetInstFromList(IEnumerable<InstInfo> InstList, int OpCode)
- {
- foreach (var Node in InstList)
- {
- if ((OpCode & Node.Mask) == Node.Value)
- {
- return Node.Inst;
- }
- }
-
- return AInst.Undefined;
- }
- }
-}
diff --git a/ChocolArm64/AOptimizations.cs b/ChocolArm64/AOptimizations.cs
deleted file mode 100644
index 17205489..00000000
--- a/ChocolArm64/AOptimizations.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Runtime.Intrinsics.X86;
-
-public static class AOptimizations
-{
- internal static bool FastFP = true;
-
- private static bool UseAllSseIfAvailable = true;
-
- private static bool UseSseIfAvailable = true;
- private static bool UseSse2IfAvailable = true;
- private static bool UseSse41IfAvailable = true;
- private static bool UseSse42IfAvailable = true;
-
- internal static bool UseSse = (UseAllSseIfAvailable && UseSseIfAvailable) && Sse.IsSupported;
- internal static bool UseSse2 = (UseAllSseIfAvailable && UseSse2IfAvailable) && Sse2.IsSupported;
- internal static bool UseSse41 = (UseAllSseIfAvailable && UseSse41IfAvailable) && Sse41.IsSupported;
- internal static bool UseSse42 = (UseAllSseIfAvailable && UseSse42IfAvailable) && Sse42.IsSupported;
-}
diff --git a/ChocolArm64/ATranslatedSub.cs b/ChocolArm64/ATranslatedSub.cs
deleted file mode 100644
index a11da264..00000000
--- a/ChocolArm64/ATranslatedSub.cs
+++ /dev/null
@@ -1,150 +0,0 @@
-using ChocolArm64.Memory;
-using ChocolArm64.State;
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
-using System.Reflection;
-using System.Reflection.Emit;
-
-namespace ChocolArm64
-{
- class ATranslatedSub
- {
- private delegate long AA64Subroutine(AThreadState Register, AMemory Memory);
-
- private const int MinCallCountForReJit = 250;
-
- private AA64Subroutine ExecDelegate;
-
- public static int StateArgIdx { get; private set; }
- public static int MemoryArgIdx { get; private set; }
-
- public static Type[] FixedArgTypes { get; private set; }
-
- public DynamicMethod Method { get; private set; }
-
- public ReadOnlyCollection<ARegister> Params { get; private set; }
-
- private HashSet<long> Callers;
-
- private ATranslatedSubType Type;
-
- private int CallCount;
-
- private bool NeedsReJit;
-
- public ATranslatedSub(DynamicMethod Method, List<ARegister> Params)
- {
- if (Method == null)
- {
- throw new ArgumentNullException(nameof(Method));
- }
-
- if (Params == null)
- {
- throw new ArgumentNullException(nameof(Params));
- }
-
- this.Method = Method;
- this.Params = Params.AsReadOnly();
-
- Callers = new HashSet<long>();
-
- PrepareDelegate();
- }
-
- static ATranslatedSub()
- {
- MethodInfo MthdInfo = typeof(AA64Subroutine).GetMethod("Invoke");
-
- ParameterInfo[] Params = MthdInfo.GetParameters();
-
- FixedArgTypes = new Type[Params.Length];
-
- for (int Index = 0; Index < Params.Length; Index++)
- {
- Type ParamType = Params[Index].ParameterType;
-
- FixedArgTypes[Index] = ParamType;
-
- if (ParamType == typeof(AThreadState))
- {
- StateArgIdx = Index;
- }
- else if (ParamType == typeof(AMemory))
- {
- MemoryArgIdx = Index;
- }
- }
- }
-
- private void PrepareDelegate()
- {
- string Name = $"{Method.Name}_Dispatch";
-
- DynamicMethod Mthd = new DynamicMethod(Name, typeof(long), FixedArgTypes);
-
- ILGenerator Generator = Mthd.GetILGenerator();
-
- Generator.EmitLdargSeq(FixedArgTypes.Length);
-
- foreach (ARegister Reg in Params)
- {
- Generator.EmitLdarg(StateArgIdx);
-
- Generator.Emit(OpCodes.Ldfld, Reg.GetField());
- }
-
- Generator.Emit(OpCodes.Call, Method);
- Generator.Emit(OpCodes.Ret);
-
- ExecDelegate = (AA64Subroutine)Mthd.CreateDelegate(typeof(AA64Subroutine));
- }
-
- public bool ShouldReJit()
- {
- if (NeedsReJit && CallCount < MinCallCountForReJit)
- {
- CallCount++;
-
- return false;
- }
-
- return NeedsReJit;
- }
-
- public long Execute(AThreadState ThreadState, AMemory Memory)
- {
- return ExecDelegate(ThreadState, Memory);
- }
-
- public void AddCaller(long Position)
- {
- lock (Callers)
- {
- Callers.Add(Position);
- }
- }
-
- public long[] GetCallerPositions()
- {
- lock (Callers)
- {
- return Callers.ToArray();
- }
- }
-
- public void SetType(ATranslatedSubType Type)
- {
- this.Type = Type;
-
- if (Type == ATranslatedSubType.SubTier0)
- {
- NeedsReJit = true;
- }
- }
-
- public void MarkForReJit() => NeedsReJit = true;
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/ATranslator.cs b/ChocolArm64/ATranslator.cs
deleted file mode 100644
index 5be41d3e..00000000
--- a/ChocolArm64/ATranslator.cs
+++ /dev/null
@@ -1,165 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Events;
-using ChocolArm64.Memory;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-
-namespace ChocolArm64
-{
- public class ATranslator
- {
- private ATranslatorCache Cache;
-
- public event EventHandler<ACpuTraceEventArgs> CpuTrace;
-
- public bool EnableCpuTrace { get; set; }
-
- public ATranslator()
- {
- Cache = new ATranslatorCache();
- }
-
- internal void ExecuteSubroutine(AThread Thread, long Position)
- {
- //TODO: Both the execute A32/A64 methods should be merged on the future,
- //when both ISAs are implemented with the interpreter and JIT.
- //As of now, A32 only has a interpreter and A64 a JIT.
- AThreadState State = Thread.ThreadState;
- AMemory Memory = Thread.Memory;
-
- if (State.ExecutionMode == AExecutionMode.AArch32)
- {
- ExecuteSubroutineA32(State, Memory);
- }
- else
- {
- ExecuteSubroutineA64(State, Memory, Position);
- }
- }
-
- private void ExecuteSubroutineA32(AThreadState State, AMemory Memory)
- {
- do
- {
- AOpCode OpCode = ADecoder.DecodeOpCode(State, Memory, State.R15);
-
- OpCode.Interpreter(State, Memory, OpCode);
- }
- while (State.R15 != 0 && State.Running);
- }
-
- private void ExecuteSubroutineA64(AThreadState State, AMemory Memory, long Position)
- {
- do
- {
- if (EnableCpuTrace)
- {
- CpuTrace?.Invoke(this, new ACpuTraceEventArgs(Position));
- }
-
- if (!Cache.TryGetSubroutine(Position, out ATranslatedSub Sub))
- {
- Sub = TranslateTier0(State, Memory, Position);
- }
-
- if (Sub.ShouldReJit())
- {
- TranslateTier1(State, Memory, Position);
- }
-
- Position = Sub.Execute(State, Memory);
- }
- while (Position != 0 && State.Running);
- }
-
- internal bool HasCachedSub(long Position)
- {
- return Cache.HasSubroutine(Position);
- }
-
- private ATranslatedSub TranslateTier0(AThreadState State, AMemory Memory, long Position)
- {
- ABlock Block = ADecoder.DecodeBasicBlock(State, Memory, Position);
-
- ABlock[] Graph = new ABlock[] { Block };
-
- string SubName = GetSubroutineName(Position);
-
- AILEmitterCtx Context = new AILEmitterCtx(Cache, Graph, Block, SubName);
-
- do
- {
- Context.EmitOpCode();
- }
- while (Context.AdvanceOpCode());
-
- ATranslatedSub Subroutine = Context.GetSubroutine();
-
- Subroutine.SetType(ATranslatedSubType.SubTier0);
-
- Cache.AddOrUpdate(Position, Subroutine, Block.OpCodes.Count);
-
- AOpCode LastOp = Block.GetLastOp();
-
- return Subroutine;
- }
-
- private void TranslateTier1(AThreadState State, AMemory Memory, long Position)
- {
- (ABlock[] Graph, ABlock Root) = ADecoder.DecodeSubroutine(Cache, State, Memory, Position);
-
- string SubName = GetSubroutineName(Position);
-
- AILEmitterCtx Context = new AILEmitterCtx(Cache, Graph, Root, SubName);
-
- if (Context.CurrBlock.Position != Position)
- {
- Context.Emit(OpCodes.Br, Context.GetLabel(Position));
- }
-
- do
- {
- Context.EmitOpCode();
- }
- while (Context.AdvanceOpCode());
-
- //Mark all methods that calls this method for ReJiting,
- //since we can now call it directly which is faster.
- if (Cache.TryGetSubroutine(Position, out ATranslatedSub OldSub))
- {
- foreach (long CallerPos in OldSub.GetCallerPositions())
- {
- if (Cache.TryGetSubroutine(Position, out ATranslatedSub CallerSub))
- {
- CallerSub.MarkForReJit();
- }
- }
- }
-
- ATranslatedSub Subroutine = Context.GetSubroutine();
-
- Subroutine.SetType(ATranslatedSubType.SubTier1);
-
- Cache.AddOrUpdate(Position, Subroutine, GetGraphInstCount(Graph));
- }
-
- private string GetSubroutineName(long Position)
- {
- return $"Sub{Position:x16}";
- }
-
- private int GetGraphInstCount(ABlock[] Graph)
- {
- int Size = 0;
-
- foreach (ABlock Block in Graph)
- {
- Size += Block.OpCodes.Count;
- }
-
- return Size;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/ATranslatorCache.cs b/ChocolArm64/ATranslatorCache.cs
deleted file mode 100644
index 199b44f8..00000000
--- a/ChocolArm64/ATranslatorCache.cs
+++ /dev/null
@@ -1,165 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-using System.Threading;
-
-namespace ChocolArm64
-{
- class ATranslatorCache
- {
- //Maximum size of the cache, in bytes, measured in ARM code size.
- private const int MaxTotalSize = 4 * 1024 * 256;
-
- //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 ATranslatedSub Subroutine { get; private set; }
-
- public LinkedListNode<long> Node { get; private set; }
-
- public int CallCount { get; set; }
-
- public int Size { get; private set; }
-
- public long Timestamp { get; private set; }
-
- public CacheBucket(ATranslatedSub Subroutine, LinkedListNode<long> Node, int Size)
- {
- this.Subroutine = Subroutine;
- this.Size = Size;
-
- UpdateNode(Node);
- }
-
- public void UpdateNode(LinkedListNode<long> Node)
- {
- this.Node = Node;
-
- Timestamp = GetTimestamp();
- }
- }
-
- private ConcurrentDictionary<long, CacheBucket> Cache;
-
- private LinkedList<long> SortedCache;
-
- private int TotalSize;
-
- public ATranslatorCache()
- {
- Cache = new ConcurrentDictionary<long, CacheBucket>();
-
- SortedCache = new LinkedList<long>();
- }
-
- public void AddOrUpdate(long Position, ATranslatedSub Subroutine, int Size)
- {
- ClearCacheIfNeeded();
-
- TotalSize += Size;
-
- lock (SortedCache)
- {
- LinkedListNode<long> Node = SortedCache.AddLast(Position);
-
- CacheBucket NewBucket = new CacheBucket(Subroutine, Node, Size);
-
- Cache.AddOrUpdate(Position, NewBucket, (Key, Bucket) =>
- {
- TotalSize -= Bucket.Size;
-
- SortedCache.Remove(Bucket.Node);
-
- return NewBucket;
- });
- }
- }
-
- public bool HasSubroutine(long Position)
- {
- return Cache.ContainsKey(Position);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool TryGetSubroutine(long Position, out ATranslatedSub Subroutine)
- {
- if (Cache.TryGetValue(Position, out CacheBucket Bucket))
- {
- if (Bucket.CallCount++ > MinCallCountForUpdate)
- {
- if (Monitor.TryEnter(SortedCache))
- {
- try
- {
- Bucket.CallCount = 0;
-
- SortedCache.Remove(Bucket.Node);
-
- Bucket.UpdateNode(SortedCache.AddLast(Position));
- }
- finally
- {
- Monitor.Exit(SortedCache);
- }
- }
- }
-
- Subroutine = Bucket.Subroutine;
-
- return true;
- }
-
- Subroutine = default(ATranslatedSub);
-
- return false;
- }
-
- private void ClearCacheIfNeeded()
- {
- long Timestamp = GetTimestamp();
-
- while (TotalSize > MaxTotalSize)
- {
- lock (SortedCache)
- {
- LinkedListNode<long> Node = SortedCache.First;
-
- if (Node == null)
- {
- break;
- }
-
- CacheBucket Bucket = Cache[Node.Value];
-
- long TimeDelta = Timestamp - Bucket.Timestamp;
-
- if (TimeDelta <= MinTimeDelta)
- {
- break;
- }
-
- if (Cache.TryRemove(Node.Value, out Bucket))
- {
- TotalSize -= Bucket.Size;
-
- SortedCache.Remove(Bucket.Node);
- }
- }
- }
- }
-
- private static long GetTimestamp()
- {
- long timestamp = Stopwatch.GetTimestamp();
-
- return timestamp / (Stopwatch.Frequency / 1000);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/BitUtils.cs b/ChocolArm64/BitUtils.cs
new file mode 100644
index 00000000..881ee248
--- /dev/null
+++ b/ChocolArm64/BitUtils.cs
@@ -0,0 +1,49 @@
+namespace ChocolArm64
+{
+ 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 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/AThread.cs b/ChocolArm64/CpuThread.cs
index 38c2b53d..11f41236 100644
--- a/ChocolArm64/AThread.cs
+++ b/ChocolArm64/CpuThread.cs
@@ -5,35 +5,35 @@ using System.Threading;
namespace ChocolArm64
{
- public class AThread
+ public class CpuThread
{
- public AThreadState ThreadState { get; private set; }
- public AMemory Memory { get; private set; }
+ public CpuThreadState ThreadState { get; private set; }
+ public MemoryManager Memory { get; private set; }
- private ATranslator Translator;
+ private Translator _translator;
public Thread Work;
public event EventHandler WorkFinished;
- private int IsExecuting;
+ private int _isExecuting;
- public AThread(ATranslator Translator, AMemory Memory, long EntryPoint)
+ public CpuThread(Translator translator, MemoryManager memory, long entryPoint)
{
- this.Translator = Translator;
- this.Memory = Memory;
+ _translator = translator;
+ Memory = memory;
- ThreadState = new AThreadState();
+ ThreadState = new CpuThreadState();
- ThreadState.ExecutionMode = AExecutionMode.AArch64;
+ ThreadState.ExecutionMode = ExecutionMode.AArch64;
ThreadState.Running = true;
Work = new Thread(delegate()
{
- Translator.ExecuteSubroutine(this, EntryPoint);
+ translator.ExecuteSubroutine(this, entryPoint);
- Memory.RemoveMonitor(ThreadState.Core);
+ memory.RemoveMonitor(ThreadState.Core);
WorkFinished?.Invoke(this, EventArgs.Empty);
});
@@ -41,7 +41,7 @@ namespace ChocolArm64
public bool Execute()
{
- if (Interlocked.Exchange(ref IsExecuting, 1) == 1)
+ if (Interlocked.Exchange(ref _isExecuting, 1) == 1)
{
return false;
}
diff --git a/ChocolArm64/Decoder/ABlock.cs b/ChocolArm64/Decoder/ABlock.cs
deleted file mode 100644
index 7a0fc607..00000000
--- a/ChocolArm64/Decoder/ABlock.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System.Collections.Generic;
-
-namespace ChocolArm64.Decoder
-{
- class ABlock
- {
- public long Position { get; set; }
- public long EndPosition { get; set; }
-
- public ABlock Next { get; set; }
- public ABlock Branch { get; set; }
-
- public List<AOpCode> OpCodes { get; private set; }
-
- public ABlock()
- {
- OpCodes = new List<AOpCode>();
- }
-
- public ABlock(long Position) : this()
- {
- this.Position = Position;
- }
-
- public AOpCode GetLastOp()
- {
- if (OpCodes.Count > 0)
- {
- return OpCodes[OpCodes.Count - 1];
- }
-
- return null;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/ACond.cs b/ChocolArm64/Decoder/ACond.cs
deleted file mode 100644
index f2da8bd2..00000000
--- a/ChocolArm64/Decoder/ACond.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace ChocolArm64.Decoder
-{
- enum ACond
- {
- Eq = 0,
- Ne = 1,
- Ge_Un = 2,
- Lt_Un = 3,
- Mi = 4,
- Pl = 5,
- Vs = 6,
- Vc = 7,
- Gt_Un = 8,
- Le_Un = 9,
- Ge = 10,
- Lt = 11,
- Gt = 12,
- Le = 13,
- Al = 14,
- Nv = 15
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/ADecoder.cs b/ChocolArm64/Decoder/ADecoder.cs
deleted file mode 100644
index 64beebd2..00000000
--- a/ChocolArm64/Decoder/ADecoder.cs
+++ /dev/null
@@ -1,239 +0,0 @@
-using ChocolArm64.Instruction;
-using ChocolArm64.Memory;
-using ChocolArm64.State;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Decoder
-{
- static class ADecoder
- {
- private delegate object OpActivator(AInst Inst, long Position, int OpCode);
-
- private static ConcurrentDictionary<Type, OpActivator> OpActivators;
-
- static ADecoder()
- {
- OpActivators = new ConcurrentDictionary<Type, OpActivator>();
- }
-
- public static ABlock DecodeBasicBlock(AThreadState State, AMemory Memory, long Start)
- {
- ABlock Block = new ABlock(Start);
-
- FillBlock(State, Memory, Block);
-
- return Block;
- }
-
- public static (ABlock[] Graph, ABlock Root) DecodeSubroutine(
- ATranslatorCache Cache,
- AThreadState State,
- AMemory Memory,
- long Start)
- {
- Dictionary<long, ABlock> Visited = new Dictionary<long, ABlock>();
- Dictionary<long, ABlock> VisitedEnd = new Dictionary<long, ABlock>();
-
- Queue<ABlock> Blocks = new Queue<ABlock>();
-
- ABlock Enqueue(long Position)
- {
- if (!Visited.TryGetValue(Position, out ABlock Output))
- {
- Output = new ABlock(Position);
-
- Blocks.Enqueue(Output);
-
- Visited.Add(Position, Output);
- }
-
- return Output;
- }
-
- ABlock Root = Enqueue(Start);
-
- while (Blocks.Count > 0)
- {
- ABlock Current = Blocks.Dequeue();
-
- FillBlock(State, Memory, Current);
-
- //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.
- if (Current.OpCodes.Count > 0)
- {
- bool HasCachedSub = false;
-
- AOpCode LastOp = Current.GetLastOp();
-
- if (LastOp is AOpCodeBImm Op)
- {
- if (Op.Emitter == AInstEmit.Bl)
- {
- HasCachedSub = Cache.HasSubroutine(Op.Imm);
- }
- else
- {
- Current.Branch = Enqueue(Op.Imm);
- }
- }
-
- if (!((LastOp is AOpCodeBImmAl) ||
- (LastOp is AOpCodeBReg)) || HasCachedSub)
- {
- Current.Next = Enqueue(Current.EndPosition);
- }
- }
-
- //If we have on the graph two blocks with the same end position,
- //then we need to split the bigger block and have two small blocks,
- //the end position of the bigger "Current" block should then be == to
- //the position of the "Smaller" block.
- while (VisitedEnd.TryGetValue(Current.EndPosition, out ABlock Smaller))
- {
- if (Current.Position > Smaller.Position)
- {
- ABlock Temp = Smaller;
-
- Smaller = Current;
- Current = Temp;
- }
-
- Current.EndPosition = Smaller.Position;
- Current.Next = Smaller;
- Current.Branch = null;
-
- Current.OpCodes.RemoveRange(
- Current.OpCodes.Count - Smaller.OpCodes.Count,
- Smaller.OpCodes.Count);
-
- VisitedEnd[Smaller.EndPosition] = Smaller;
- }
-
- VisitedEnd.Add(Current.EndPosition, Current);
- }
-
- //Make and sort Graph blocks array by position.
- ABlock[] Graph = new ABlock[Visited.Count];
-
- while (Visited.Count > 0)
- {
- ulong FirstPos = ulong.MaxValue;
-
- foreach (ABlock Block in Visited.Values)
- {
- if (FirstPos > (ulong)Block.Position)
- FirstPos = (ulong)Block.Position;
- }
-
- ABlock Current = Visited[(long)FirstPos];
-
- do
- {
- Graph[Graph.Length - Visited.Count] = Current;
-
- Visited.Remove(Current.Position);
-
- Current = Current.Next;
- }
- while (Current != null);
- }
-
- return (Graph, Root);
- }
-
- private static void FillBlock(AThreadState State, AMemory Memory, ABlock Block)
- {
- long Position = Block.Position;
-
- AOpCode OpCode;
-
- do
- {
- //TODO: This needs to be changed to support both AArch32 and AArch64,
- //once JIT support is introduced on AArch32 aswell.
- OpCode = DecodeOpCode(State, Memory, Position);
-
- Block.OpCodes.Add(OpCode);
-
- Position += 4;
- }
- while (!(IsBranch(OpCode) || IsException(OpCode)));
-
- Block.EndPosition = Position;
- }
-
- private static bool IsBranch(AOpCode OpCode)
- {
- return OpCode is AOpCodeBImm ||
- OpCode is AOpCodeBReg;
- }
-
- private static bool IsException(AOpCode OpCode)
- {
- return OpCode.Emitter == AInstEmit.Brk ||
- OpCode.Emitter == AInstEmit.Svc ||
- OpCode.Emitter == AInstEmit.Und;
- }
-
- public static AOpCode DecodeOpCode(AThreadState State, AMemory Memory, long Position)
- {
- int OpCode = Memory.ReadInt32(Position);
-
- AInst Inst;
-
- if (State.ExecutionMode == AExecutionMode.AArch64)
- {
- Inst = AOpCodeTable.GetInstA64(OpCode);
- }
- else
- {
- //TODO: Thumb support.
- Inst = AOpCodeTable.GetInstA32(OpCode);
- }
-
- AOpCode DecodedOpCode = new AOpCode(AInst.Undefined, Position, OpCode);
-
- if (Inst.Type != null)
- {
- DecodedOpCode = MakeOpCode(Inst.Type, Inst, Position, OpCode);
- }
-
- return DecodedOpCode;
- }
-
- private static AOpCode MakeOpCode(Type Type, AInst Inst, long Position, int OpCode)
- {
- if (Type == null)
- {
- throw new ArgumentNullException(nameof(Type));
- }
-
- OpActivator CreateInstance = OpActivators.GetOrAdd(Type, CacheOpActivator);
-
- return (AOpCode)CreateInstance(Inst, Position, OpCode);
- }
-
- private static OpActivator CacheOpActivator(Type Type)
- {
- Type[] ArgTypes = new Type[] { typeof(AInst), 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/Decoder/ADecoderHelper.cs b/ChocolArm64/Decoder/ADecoderHelper.cs
deleted file mode 100644
index a2179f49..00000000
--- a/ChocolArm64/Decoder/ADecoderHelper.cs
+++ /dev/null
@@ -1,107 +0,0 @@
-using System;
-
-namespace ChocolArm64.Decoder
-{
- static class ADecoderHelper
- {
- 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 = ABitUtils.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 = ABitUtils.FillWithOnes(S + 1);
- long TMask = ABitUtils.FillWithOnes(((S - R) & Levels) + 1);
-
- if (R > 0)
- {
- WMask = ABitUtils.RotateRight(WMask, R, Size);
- WMask &= ABitUtils.FillWithOnes(Size);
- }
-
- return new BitMask()
- {
- WMask = ABitUtils.Replicate(WMask, Size),
- TMask = ABitUtils.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 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/Decoder/AOpCode.cs b/ChocolArm64/Decoder/AOpCode.cs
deleted file mode 100644
index bdc8f13a..00000000
--- a/ChocolArm64/Decoder/AOpCode.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using ChocolArm64.Instruction;
-using ChocolArm64.State;
-using System;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCode : IAOpCode
- {
- public long Position { get; private set; }
- public int RawOpCode { get; private set; }
-
- public AInstEmitter Emitter { get; protected set; }
- public AInstInterpreter Interpreter { get; protected set; }
- public ARegisterSize RegisterSize { get; protected set; }
-
- public AOpCode(AInst Inst, long Position, int OpCode)
- {
- this.Position = Position;
- this.RawOpCode = OpCode;
-
- RegisterSize = ARegisterSize.Int64;
-
- Emitter = Inst.Emitter;
- Interpreter = Inst.Interpreter;
- }
-
- public int GetBitsCount()
- {
- switch (RegisterSize)
- {
- case ARegisterSize.Int32: return 32;
- case ARegisterSize.Int64: return 64;
- case ARegisterSize.SIMD64: return 64;
- case ARegisterSize.SIMD128: return 128;
- }
-
- throw new InvalidOperationException();
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeAdr.cs b/ChocolArm64/Decoder/AOpCodeAdr.cs
deleted file mode 100644
index 3396281f..00000000
--- a/ChocolArm64/Decoder/AOpCodeAdr.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeAdr : AOpCode
- {
- public int Rd { get; private set; }
- public long Imm { get; private set; }
-
- public AOpCodeAdr(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Rd = OpCode & 0x1f;
-
- Imm = ADecoderHelper.DecodeImmS19_2(OpCode);
- Imm |= ((long)OpCode >> 29) & 3;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeAlu.cs b/ChocolArm64/Decoder/AOpCodeAlu.cs
deleted file mode 100644
index e1a44f04..00000000
--- a/ChocolArm64/Decoder/AOpCodeAlu.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using ChocolArm64.Instruction;
-using ChocolArm64.State;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeAlu : AOpCode, IAOpCodeAlu
- {
- public int Rd { get; protected set; }
- public int Rn { get; private set; }
-
- public ADataOp DataOp { get; private set; }
-
- public AOpCodeAlu(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Rd = (OpCode >> 0) & 0x1f;
- Rn = (OpCode >> 5) & 0x1f;
- DataOp = (ADataOp)((OpCode >> 24) & 0x3);
-
- RegisterSize = (OpCode >> 31) != 0
- ? ARegisterSize.Int64
- : ARegisterSize.Int32;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeAluImm.cs b/ChocolArm64/Decoder/AOpCodeAluImm.cs
deleted file mode 100644
index e913475a..00000000
--- a/ChocolArm64/Decoder/AOpCodeAluImm.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using ChocolArm64.Instruction;
-using System;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeAluImm : AOpCodeAlu, IAOpCodeAluImm
- {
- public long Imm { get; private set; }
-
- public AOpCodeAluImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- if (DataOp == ADataOp.Arithmetic)
- {
- Imm = (OpCode >> 10) & 0xfff;
-
- int Shift = (OpCode >> 22) & 3;
-
- Imm <<= Shift * 12;
- }
- else if (DataOp == ADataOp.Logical)
- {
- var BM = ADecoderHelper.DecodeBitMask(OpCode, true);
-
- if (BM.IsUndefined)
- {
- Emitter = AInstEmit.Und;
-
- return;
- }
-
- Imm = BM.WMask;
- }
- else
- {
- throw new ArgumentException(nameof(OpCode));
- }
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeAluRs.cs b/ChocolArm64/Decoder/AOpCodeAluRs.cs
deleted file mode 100644
index 9c215be3..00000000
--- a/ChocolArm64/Decoder/AOpCodeAluRs.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeAluRs : AOpCodeAlu, IAOpCodeAluRs
- {
- public int Shift { get; private set; }
- public int Rm { get; private set; }
-
- public AShiftType ShiftType { get; private set; }
-
- public AOpCodeAluRs(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- int Shift = (OpCode >> 10) & 0x3f;
-
- if (Shift >= GetBitsCount())
- {
- Emitter = AInstEmit.Und;
-
- return;
- }
-
- this.Shift = Shift;
-
- Rm = (OpCode >> 16) & 0x1f;
- ShiftType = (AShiftType)((OpCode >> 22) & 0x3);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeAluRx.cs b/ChocolArm64/Decoder/AOpCodeAluRx.cs
deleted file mode 100644
index 7dd72a68..00000000
--- a/ChocolArm64/Decoder/AOpCodeAluRx.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeAluRx : AOpCodeAlu, IAOpCodeAluRx
- {
- public int Shift { get; private set; }
- public int Rm { get; private set; }
-
- public AIntType IntType { get; private set; }
-
- public AOpCodeAluRx(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Shift = (OpCode >> 10) & 0x7;
- IntType = (AIntType)((OpCode >> 13) & 0x7);
- Rm = (OpCode >> 16) & 0x1f;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeBImm.cs b/ChocolArm64/Decoder/AOpCodeBImm.cs
deleted file mode 100644
index 6519d281..00000000
--- a/ChocolArm64/Decoder/AOpCodeBImm.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeBImm : AOpCode
- {
- public long Imm { get; protected set; }
-
- public AOpCodeBImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeBImmAl.cs b/ChocolArm64/Decoder/AOpCodeBImmAl.cs
deleted file mode 100644
index a4ff686d..00000000
--- a/ChocolArm64/Decoder/AOpCodeBImmAl.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeBImmAl : AOpCodeBImm
- {
- public AOpCodeBImmAl(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Imm = Position + ADecoderHelper.DecodeImm26_2(OpCode);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeBImmCmp.cs b/ChocolArm64/Decoder/AOpCodeBImmCmp.cs
deleted file mode 100644
index 0f16b73e..00000000
--- a/ChocolArm64/Decoder/AOpCodeBImmCmp.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using ChocolArm64.Instruction;
-using ChocolArm64.State;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeBImmCmp : AOpCodeBImm
- {
- public int Rt { get; private set; }
-
- public AOpCodeBImmCmp(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Rt = OpCode & 0x1f;
-
- Imm = Position + ADecoderHelper.DecodeImmS19_2(OpCode);
-
- RegisterSize = (OpCode >> 31) != 0
- ? ARegisterSize.Int64
- : ARegisterSize.Int32;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeBImmCond.cs b/ChocolArm64/Decoder/AOpCodeBImmCond.cs
deleted file mode 100644
index 1310feb8..00000000
--- a/ChocolArm64/Decoder/AOpCodeBImmCond.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeBImmCond : AOpCodeBImm, IAOpCodeCond
- {
- public ACond Cond { get; private set; }
-
- public AOpCodeBImmCond(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- int O0 = (OpCode >> 4) & 1;
-
- if (O0 != 0)
- {
- Emitter = AInstEmit.Und;
-
- return;
- }
-
- Cond = (ACond)(OpCode & 0xf);
-
- Imm = Position + ADecoderHelper.DecodeImmS19_2(OpCode);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeBImmTest.cs b/ChocolArm64/Decoder/AOpCodeBImmTest.cs
deleted file mode 100644
index 73e57b7a..00000000
--- a/ChocolArm64/Decoder/AOpCodeBImmTest.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeBImmTest : AOpCodeBImm
- {
- public int Rt { get; private set; }
- public int Pos { get; private set; }
-
- public AOpCodeBImmTest(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Rt = OpCode & 0x1f;
-
- Imm = Position + ADecoderHelper.DecodeImmS14_2(OpCode);
-
- Pos = (OpCode >> 19) & 0x1f;
- Pos |= (OpCode >> 26) & 0x20;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeBReg.cs b/ChocolArm64/Decoder/AOpCodeBReg.cs
deleted file mode 100644
index c9c600af..00000000
--- a/ChocolArm64/Decoder/AOpCodeBReg.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeBReg : AOpCode
- {
- public int Rn { get; private set; }
-
- public AOpCodeBReg(AInst 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 = AInstEmit.Und;
-
- return;
- }
-
- Rn = (OpCode >> 5) & 0x1f;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeBfm.cs b/ChocolArm64/Decoder/AOpCodeBfm.cs
deleted file mode 100644
index 6498d8ec..00000000
--- a/ChocolArm64/Decoder/AOpCodeBfm.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeBfm : AOpCodeAlu
- {
- 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 AOpCodeBfm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- var BM = ADecoderHelper.DecodeBitMask(OpCode, false);
-
- if (BM.IsUndefined)
- {
- Emitter = AInstEmit.Und;
-
- return;
- }
-
- WMask = BM.WMask;
- TMask = BM.TMask;
- Pos = BM.Pos;
- Shift = BM.Shift;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeCcmp.cs b/ChocolArm64/Decoder/AOpCodeCcmp.cs
deleted file mode 100644
index d0c7f779..00000000
--- a/ChocolArm64/Decoder/AOpCodeCcmp.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using ChocolArm64.Instruction;
-using ChocolArm64.State;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeCcmp : AOpCodeAlu, IAOpCodeCond
- {
- public int NZCV { get; private set; }
- protected int RmImm;
-
- public ACond Cond { get; private set; }
-
- public AOpCodeCcmp(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- int O3 = (OpCode >> 4) & 1;
-
- if (O3 != 0)
- {
- Emitter = AInstEmit.Und;
-
- return;
- }
-
- NZCV = (OpCode >> 0) & 0xf;
- Cond = (ACond)((OpCode >> 12) & 0xf);
- RmImm = (OpCode >> 16) & 0x1f;
-
- Rd = AThreadState.ZRIndex;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeCcmpImm.cs b/ChocolArm64/Decoder/AOpCodeCcmpImm.cs
deleted file mode 100644
index 803eefc2..00000000
--- a/ChocolArm64/Decoder/AOpCodeCcmpImm.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeCcmpImm : AOpCodeCcmp, IAOpCodeAluImm
- {
- public long Imm => RmImm;
-
- public AOpCodeCcmpImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeCcmpReg.cs b/ChocolArm64/Decoder/AOpCodeCcmpReg.cs
deleted file mode 100644
index c364ae68..00000000
--- a/ChocolArm64/Decoder/AOpCodeCcmpReg.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeCcmpReg : AOpCodeCcmp, IAOpCodeAluRs
- {
- public int Rm => RmImm;
-
- public int Shift => 0;
-
- public AShiftType ShiftType => AShiftType.Lsl;
-
- public AOpCodeCcmpReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeCsel.cs b/ChocolArm64/Decoder/AOpCodeCsel.cs
deleted file mode 100644
index cdef3e74..00000000
--- a/ChocolArm64/Decoder/AOpCodeCsel.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeCsel : AOpCodeAlu, IAOpCodeCond
- {
- public int Rm { get; private set; }
-
- public ACond Cond { get; private set; }
-
- public AOpCodeCsel(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Rm = (OpCode >> 16) & 0x1f;
- Cond = (ACond)((OpCode >> 12) & 0xf);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeException.cs b/ChocolArm64/Decoder/AOpCodeException.cs
deleted file mode 100644
index 4579c1a7..00000000
--- a/ChocolArm64/Decoder/AOpCodeException.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeException : AOpCode
- {
- public int Id { get; private set; }
-
- public AOpCodeException(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Id = (OpCode >> 5) & 0xffff;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeMem.cs b/ChocolArm64/Decoder/AOpCodeMem.cs
deleted file mode 100644
index be5367cf..00000000
--- a/ChocolArm64/Decoder/AOpCodeMem.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeMem : AOpCode
- {
- 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 AOpCodeMem(AInst 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/Decoder/AOpCodeMemEx.cs b/ChocolArm64/Decoder/AOpCodeMemEx.cs
deleted file mode 100644
index 3a28cfd7..00000000
--- a/ChocolArm64/Decoder/AOpCodeMemEx.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeMemEx : AOpCodeMem
- {
- public int Rt2 { get; private set; }
- public int Rs { get; private set; }
-
- public AOpCodeMemEx(AInst 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/Decoder/AOpCodeMemPair.cs b/ChocolArm64/Decoder/AOpCodeMemPair.cs
deleted file mode 100644
index ec866c84..00000000
--- a/ChocolArm64/Decoder/AOpCodeMemPair.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeMemPair : AOpCodeMemImm
- {
- public int Rt2 { get; private set; }
-
- public AOpCodeMemPair(AInst 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/Decoder/AOpCodeMemReg.cs b/ChocolArm64/Decoder/AOpCodeMemReg.cs
deleted file mode 100644
index 98927128..00000000
--- a/ChocolArm64/Decoder/AOpCodeMemReg.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeMemReg : AOpCodeMem
- {
- public bool Shift { get; private set; }
- public int Rm { get; private set; }
-
- public AIntType IntType { get; private set; }
-
- public AOpCodeMemReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Shift = ((OpCode >> 12) & 0x1) != 0;
- IntType = (AIntType)((OpCode >> 13) & 0x7);
- Rm = (OpCode >> 16) & 0x1f;
- Extend64 = ((OpCode >> 22) & 0x3) == 2;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeMov.cs b/ChocolArm64/Decoder/AOpCodeMov.cs
deleted file mode 100644
index d5398646..00000000
--- a/ChocolArm64/Decoder/AOpCodeMov.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using ChocolArm64.Instruction;
-using ChocolArm64.State;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeMov : AOpCode
- {
- public int Rd { get; private set; }
- public long Imm { get; private set; }
- public int Pos { get; private set; }
-
- public AOpCodeMov(AInst 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 = AInstEmit.Und;
-
- return;
- }
-
- Rd = (OpCode >> 0) & 0x1f;
- Imm = (OpCode >> 5) & 0xffff;
- Pos = (OpCode >> 21) & 0x3;
-
- Pos <<= 4;
- Imm <<= Pos;
-
- RegisterSize = (OpCode >> 31) != 0
- ? ARegisterSize.Int64
- : ARegisterSize.Int32;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeMul.cs b/ChocolArm64/Decoder/AOpCodeMul.cs
deleted file mode 100644
index ca2b0cdb..00000000
--- a/ChocolArm64/Decoder/AOpCodeMul.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeMul : AOpCodeAlu
- {
- public int Rm { get; private set; }
- public int Ra { get; private set; }
-
- public AOpCodeMul(AInst 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/Decoder/AOpCodeSimd.cs b/ChocolArm64/Decoder/AOpCodeSimd.cs
deleted file mode 100644
index 41708517..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimd.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using ChocolArm64.Instruction;
-using ChocolArm64.State;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimd : AOpCode, IAOpCodeSimd
- {
- 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 AOpCodeSimd(AInst 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
- ? ARegisterSize.SIMD128
- : ARegisterSize.SIMD64;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeSimdCvt.cs b/ChocolArm64/Decoder/AOpCodeSimdCvt.cs
deleted file mode 100644
index 41f4d3b1..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdCvt.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using ChocolArm64.Instruction;
-using ChocolArm64.State;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdCvt : AOpCodeSimd
- {
- public int FBits { get; private set; }
-
- public AOpCodeSimdCvt(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- //TODO:
- //Und of Fixed Point variants.
- int Scale = (OpCode >> 10) & 0x3f;
- int SF = (OpCode >> 31) & 0x1;
-
- /*if (Type != SF && !(Type == 2 && SF == 1))
- {
- Emitter = AInstEmit.Und;
-
- return;
- }*/
-
- FBits = 64 - Scale;
-
- RegisterSize = SF != 0
- ? ARegisterSize.Int64
- : ARegisterSize.Int32;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeSimdExt.cs b/ChocolArm64/Decoder/AOpCodeSimdExt.cs
deleted file mode 100644
index 888e4470..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdExt.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdExt : AOpCodeSimdReg
- {
- public int Imm4 { get; private set; }
-
- public AOpCodeSimdExt(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Imm4 = (OpCode >> 11) & 0xf;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeSimdFcond.cs b/ChocolArm64/Decoder/AOpCodeSimdFcond.cs
deleted file mode 100644
index e38e7424..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdFcond.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdFcond : AOpCodeSimdReg, IAOpCodeCond
- {
- public int NZCV { get; private set; }
-
- public ACond Cond { get; private set; }
-
- public AOpCodeSimdFcond(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- NZCV = (OpCode >> 0) & 0xf;
- Cond = (ACond)((OpCode >> 12) & 0xf);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeSimdFmov.cs b/ChocolArm64/Decoder/AOpCodeSimdFmov.cs
deleted file mode 100644
index 3f888959..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdFmov.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdFmov : AOpCode, IAOpCodeSimd
- {
- public int Rd { get; private set; }
- public long Imm { get; private set; }
- public int Size { get; private set; }
-
- public AOpCodeSimdFmov(AInst 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 = AInstEmit.Und;
-
- return;
- }
-
- Size = Type;
-
- long Imm;
-
- Rd = (OpCode >> 0) & 0x1f;
- Imm = (OpCode >> 13) & 0xff;
-
- this.Imm = ADecoderHelper.DecodeImm8Float(Imm, Type);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeSimdImm.cs b/ChocolArm64/Decoder/AOpCodeSimdImm.cs
deleted file mode 100644
index e7dfe621..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdImm.cs
+++ /dev/null
@@ -1,101 +0,0 @@
-using ChocolArm64.Instruction;
-using ChocolArm64.State;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdImm : AOpCode, IAOpCodeSimd
- {
- public int Rd { get; private set; }
- public long Imm { get; private set; }
- public int Size { get; private set; }
-
- public AOpCodeSimdImm(AInst 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 = ADecoderHelper.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;
- }
-
- this.Imm = Imm;
-
- RegisterSize = ((OpCode >> 30) & 1) != 0
- ? ARegisterSize.SIMD128
- : ARegisterSize.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/Decoder/AOpCodeSimdIns.cs b/ChocolArm64/Decoder/AOpCodeSimdIns.cs
deleted file mode 100644
index 0b60bbe8..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdIns.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdIns : AOpCodeSimd
- {
- public int SrcIndex { get; private set; }
- public int DstIndex { get; private set; }
-
- public AOpCodeSimdIns(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- int Imm4 = (OpCode >> 11) & 0xf;
- int Imm5 = (OpCode >> 16) & 0x1f;
-
- if (Imm5 == 0b10000)
- {
- Emitter = AInstEmit.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/Decoder/AOpCodeSimdMemImm.cs b/ChocolArm64/Decoder/AOpCodeSimdMemImm.cs
deleted file mode 100644
index 1ef19a5d..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdMemImm.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdMemImm : AOpCodeMemImm, IAOpCodeSimd
- {
- public AOpCodeSimdMemImm(AInst 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/Decoder/AOpCodeSimdMemLit.cs b/ChocolArm64/Decoder/AOpCodeSimdMemLit.cs
deleted file mode 100644
index ea6fe00b..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdMemLit.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdMemLit : AOpCode, IAOpCodeSimd, IAOpCodeLit
- {
- 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 AOpCodeSimdMemLit(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- int Opc = (OpCode >> 30) & 3;
-
- if (Opc == 3)
- {
- Emitter = AInstEmit.Und;
-
- return;
- }
-
- Rt = OpCode & 0x1f;
-
- Imm = Position + ADecoderHelper.DecodeImmS19_2(OpCode);
-
- Size = Opc + 2;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeSimdMemPair.cs b/ChocolArm64/Decoder/AOpCodeSimdMemPair.cs
deleted file mode 100644
index db99e3d4..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdMemPair.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdMemPair : AOpCodeMemPair, IAOpCodeSimd
- {
- public AOpCodeSimdMemPair(AInst 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/Decoder/AOpCodeSimdMemReg.cs b/ChocolArm64/Decoder/AOpCodeSimdMemReg.cs
deleted file mode 100644
index aabf4846..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdMemReg.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdMemReg : AOpCodeMemReg, IAOpCodeSimd
- {
- public AOpCodeSimdMemReg(AInst 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/Decoder/AOpCodeSimdMemSs.cs b/ChocolArm64/Decoder/AOpCodeSimdMemSs.cs
deleted file mode 100644
index c8794ff5..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdMemSs.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-using ChocolArm64.Instruction;
-using ChocolArm64.State;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdMemSs : AOpCodeMemReg, IAOpCodeSimd
- {
- 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 AOpCodeSimdMemSs(AInst 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 = AInst.Undefined;
-
- return;
- }
-
- Index >>= 1;
-
- break;
- }
-
- case 2:
- {
- if ((Size & 2) != 0 ||
- ((Size & 1) != 0 && S != 0))
- {
- Inst = AInst.Undefined;
-
- return;
- }
-
- if ((Size & 1) != 0)
- {
- Index >>= 3;
-
- Scale = 3;
- }
- else
- {
- Index >>= 2;
- }
-
- break;
- }
-
- case 3:
- {
- if (L == 0 || S != 0)
- {
- Inst = AInst.Undefined;
-
- return;
- }
-
- Scale = Size;
-
- Replicate = true;
-
- break;
- }
- }
-
- this.Index = Index;
- this.SElems = SElems;
- this.Size = Scale;
-
- Extend64 = false;
-
- WBack = ((OpCode >> 23) & 1) != 0;
-
- RegisterSize = Q != 0
- ? ARegisterSize.SIMD128
- : ARegisterSize.SIMD64;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeSimdReg.cs b/ChocolArm64/Decoder/AOpCodeSimdReg.cs
deleted file mode 100644
index 702ffed1..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdReg.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdReg : AOpCodeSimd
- {
- public bool Bit3 { get; private set; }
- public int Ra { get; private set; }
- public int Rm { get; protected set; }
-
- public AOpCodeSimdReg(AInst 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/Decoder/AOpCodeSimdRegElem.cs b/ChocolArm64/Decoder/AOpCodeSimdRegElem.cs
deleted file mode 100644
index d6dc4bd2..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdRegElem.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdRegElem : AOpCodeSimdReg
- {
- public int Index { get; private set; }
-
- public AOpCodeSimdRegElem(AInst 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 = AInstEmit.Und; return;
- }
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeSimdRegElemF.cs b/ChocolArm64/Decoder/AOpCodeSimdRegElemF.cs
deleted file mode 100644
index e0670def..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdRegElemF.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdRegElemF : AOpCodeSimdReg
- {
- public int Index { get; private set; }
-
- public AOpCodeSimdRegElemF(AInst 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 = AInstEmit.Und; return;
- }
- }
- }
-}
diff --git a/ChocolArm64/Decoder/AOpCodeSimdShImm.cs b/ChocolArm64/Decoder/AOpCodeSimdShImm.cs
deleted file mode 100644
index e6d5210f..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdShImm.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdShImm : AOpCodeSimd
- {
- public int Imm { get; private set; }
-
- public AOpCodeSimdShImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Imm = (OpCode >> 16) & 0x7f;
-
- Size = ABitUtils.HighestBitSetNibble(Imm >> 3);
- }
- }
-}
diff --git a/ChocolArm64/Decoder/AOpCodeSimdTbl.cs b/ChocolArm64/Decoder/AOpCodeSimdTbl.cs
deleted file mode 100644
index c8ae5bac..00000000
--- a/ChocolArm64/Decoder/AOpCodeSimdTbl.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSimdTbl : AOpCodeSimdReg
- {
- public AOpCodeSimdTbl(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Size = ((OpCode >> 13) & 3) + 1;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AOpCodeSystem.cs b/ChocolArm64/Decoder/AOpCodeSystem.cs
deleted file mode 100644
index 3d81a5d4..00000000
--- a/ChocolArm64/Decoder/AOpCodeSystem.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder
-{
- class AOpCodeSystem : AOpCode
- {
- 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 AOpCodeSystem(AInst 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/Decoder/IAOpCode.cs b/ChocolArm64/Decoder/IAOpCode.cs
deleted file mode 100644
index 44bf9cb2..00000000
--- a/ChocolArm64/Decoder/IAOpCode.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using ChocolArm64.Instruction;
-using ChocolArm64.State;
-
-namespace ChocolArm64.Decoder
-{
- interface IAOpCode
- {
- long Position { get; }
-
- AInstEmitter Emitter { get; }
- ARegisterSize RegisterSize { get; }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/IAOpCodeAlu.cs b/ChocolArm64/Decoder/IAOpCodeAlu.cs
deleted file mode 100644
index 22af4c82..00000000
--- a/ChocolArm64/Decoder/IAOpCodeAlu.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace ChocolArm64.Decoder
-{
- interface IAOpCodeAlu : IAOpCode
- {
- int Rd { get; }
- int Rn { get; }
-
- ADataOp DataOp { get; }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/IAOpCodeAluImm.cs b/ChocolArm64/Decoder/IAOpCodeAluImm.cs
deleted file mode 100644
index 04b5c5f7..00000000
--- a/ChocolArm64/Decoder/IAOpCodeAluImm.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace ChocolArm64.Decoder
-{
- interface IAOpCodeAluImm : IAOpCodeAlu
- {
- long Imm { get; }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/IAOpCodeAluRs.cs b/ChocolArm64/Decoder/IAOpCodeAluRs.cs
deleted file mode 100644
index 5ca9de40..00000000
--- a/ChocolArm64/Decoder/IAOpCodeAluRs.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace ChocolArm64.Decoder
-{
- interface IAOpCodeAluRs : IAOpCodeAlu
- {
- int Shift { get; }
- int Rm { get; }
-
- AShiftType ShiftType { get; }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/IAOpCodeAluRx.cs b/ChocolArm64/Decoder/IAOpCodeAluRx.cs
deleted file mode 100644
index b49d5325..00000000
--- a/ChocolArm64/Decoder/IAOpCodeAluRx.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace ChocolArm64.Decoder
-{
- interface IAOpCodeAluRx : IAOpCodeAlu
- {
- int Shift { get; }
- int Rm { get; }
-
- AIntType IntType { get; }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/IAOpCodeCond.cs b/ChocolArm64/Decoder/IAOpCodeCond.cs
deleted file mode 100644
index 1655abaa..00000000
--- a/ChocolArm64/Decoder/IAOpCodeCond.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace ChocolArm64.Decoder
-{
- interface IAOpCodeCond : IAOpCode
- {
- ACond Cond { get; }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/IAOpCodeSimd.cs b/ChocolArm64/Decoder/IAOpCodeSimd.cs
deleted file mode 100644
index 19032ad9..00000000
--- a/ChocolArm64/Decoder/IAOpCodeSimd.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace ChocolArm64.Decoder
-{
- interface IAOpCodeSimd : IAOpCode
- {
- int Size { get; }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder32/A32OpCode.cs b/ChocolArm64/Decoder32/A32OpCode.cs
deleted file mode 100644
index 56f870df..00000000
--- a/ChocolArm64/Decoder32/A32OpCode.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder32
-{
- class A32OpCode : AOpCode
- {
- public ACond Cond { get; private set; }
-
- public A32OpCode(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Cond = (ACond)((uint)OpCode >> 28);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoder32/A32OpCodeBImmAl.cs b/ChocolArm64/Decoder32/A32OpCodeBImmAl.cs
deleted file mode 100644
index 71bca7f9..00000000
--- a/ChocolArm64/Decoder32/A32OpCodeBImmAl.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using ChocolArm64.Instruction;
-
-namespace ChocolArm64.Decoder32
-{
- class A32OpCodeBImmAl : A32OpCode
- {
- public int Imm;
- public int H;
-
- public A32OpCodeBImmAl(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
- {
- Imm = (OpCode << 8) >> 6;
- H = (OpCode >> 23) & 2;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/Block.cs b/ChocolArm64/Decoders/Block.cs
new file mode 100644
index 00000000..c89ea7c6
--- /dev/null
+++ b/ChocolArm64/Decoders/Block.cs
@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+
+namespace ChocolArm64.Decoders
+{
+ class Block
+ {
+ public long Position { get; set; }
+ public long EndPosition { get; set; }
+
+ public Block Next { get; set; }
+ public Block Branch { get; set; }
+
+ public List<OpCode64> OpCodes { get; private set; }
+
+ public Block()
+ {
+ OpCodes = new List<OpCode64>();
+ }
+
+ public Block(long position) : this()
+ {
+ Position = position;
+ }
+
+ 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/Cond.cs b/ChocolArm64/Decoders/Cond.cs
new file mode 100644
index 00000000..57e12cd6
--- /dev/null
+++ b/ChocolArm64/Decoders/Cond.cs
@@ -0,0 +1,22 @@
+namespace ChocolArm64.Decoders
+{
+ enum Cond
+ {
+ 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
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/ADataOp.cs b/ChocolArm64/Decoders/DataOp.cs
index a5601a3a..b7768bb4 100644
--- a/ChocolArm64/Decoder/ADataOp.cs
+++ b/ChocolArm64/Decoders/DataOp.cs
@@ -1,6 +1,6 @@
-namespace ChocolArm64.Decoder
+namespace ChocolArm64.Decoders
{
- enum ADataOp
+ enum DataOp
{
Adr = 0,
Arithmetic = 1,
diff --git a/ChocolArm64/Decoders/Decoder.cs b/ChocolArm64/Decoders/Decoder.cs
new file mode 100644
index 00000000..db43ac4f
--- /dev/null
+++ b/ChocolArm64/Decoders/Decoder.cs
@@ -0,0 +1,239 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.Memory;
+using ChocolArm64.State;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Reflection.Emit;
+
+namespace ChocolArm64.Decoders
+{
+ static class Decoder
+ {
+ private delegate object OpActivator(Inst inst, long position, int opCode);
+
+ private static ConcurrentDictionary<Type, OpActivator> _opActivators;
+
+ static Decoder()
+ {
+ _opActivators = new ConcurrentDictionary<Type, OpActivator>();
+ }
+
+ public static Block DecodeBasicBlock(CpuThreadState state, MemoryManager memory, long start)
+ {
+ Block block = new Block(start);
+
+ FillBlock(state, memory, block);
+
+ return block;
+ }
+
+ public static (Block[] Graph, Block Root) DecodeSubroutine(
+ TranslatorCache cache,
+ CpuThreadState state,
+ MemoryManager memory,
+ long start)
+ {
+ Dictionary<long, Block> visited = new Dictionary<long, Block>();
+ Dictionary<long, Block> visitedEnd = new Dictionary<long, Block>();
+
+ Queue<Block> blocks = new Queue<Block>();
+
+ Block Enqueue(long position)
+ {
+ if (!visited.TryGetValue(position, out Block output))
+ {
+ output = new Block(position);
+
+ blocks.Enqueue(output);
+
+ visited.Add(position, output);
+ }
+
+ return output;
+ }
+
+ Block root = Enqueue(start);
+
+ while (blocks.Count > 0)
+ {
+ Block current = blocks.Dequeue();
+
+ FillBlock(state, memory, current);
+
+ //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.
+ if (current.OpCodes.Count > 0)
+ {
+ bool hasCachedSub = false;
+
+ OpCode64 lastOp = current.GetLastOp();
+
+ if (lastOp is OpCodeBImm64 op)
+ {
+ if (op.Emitter == InstEmit.Bl)
+ {
+ hasCachedSub = cache.HasSubroutine(op.Imm);
+ }
+ else
+ {
+ current.Branch = Enqueue(op.Imm);
+ }
+ }
+
+ if (!((lastOp is OpCodeBImmAl64) ||
+ (lastOp is OpCodeBReg64)) || hasCachedSub)
+ {
+ current.Next = Enqueue(current.EndPosition);
+ }
+ }
+
+ //If we have on the graph two blocks with the same end position,
+ //then we need to split the bigger block and have two small blocks,
+ //the end position of the bigger "Current" block should then be == to
+ //the position of the "Smaller" block.
+ while (visitedEnd.TryGetValue(current.EndPosition, out Block smaller))
+ {
+ if (current.Position > smaller.Position)
+ {
+ Block temp = smaller;
+
+ smaller = current;
+ current = temp;
+ }
+
+ current.EndPosition = smaller.Position;
+ current.Next = smaller;
+ current.Branch = null;
+
+ current.OpCodes.RemoveRange(
+ current.OpCodes.Count - smaller.OpCodes.Count,
+ smaller.OpCodes.Count);
+
+ visitedEnd[smaller.EndPosition] = smaller;
+ }
+
+ visitedEnd.Add(current.EndPosition, current);
+ }
+
+ //Make and sort Graph blocks array by position.
+ Block[] graph = new Block[visited.Count];
+
+ while (visited.Count > 0)
+ {
+ ulong firstPos = ulong.MaxValue;
+
+ foreach (Block block in visited.Values)
+ {
+ if (firstPos > (ulong)block.Position)
+ firstPos = (ulong)block.Position;
+ }
+
+ Block current = visited[(long)firstPos];
+
+ do
+ {
+ graph[graph.Length - visited.Count] = current;
+
+ visited.Remove(current.Position);
+
+ current = current.Next;
+ }
+ while (current != null);
+ }
+
+ return (graph, root);
+ }
+
+ private static void FillBlock(CpuThreadState state, MemoryManager memory, Block block)
+ {
+ long position = block.Position;
+
+ OpCode64 opCode;
+
+ do
+ {
+ //TODO: This needs to be changed to support both AArch32 and AArch64,
+ //once JIT support is introduced on AArch32 aswell.
+ opCode = DecodeOpCode(state, memory, position);
+
+ block.OpCodes.Add(opCode);
+
+ position += 4;
+ }
+ while (!(IsBranch(opCode) || IsException(opCode)));
+
+ block.EndPosition = position;
+ }
+
+ private static bool IsBranch(OpCode64 opCode)
+ {
+ return opCode is OpCodeBImm64 ||
+ opCode is OpCodeBReg64;
+ }
+
+ private static bool IsException(OpCode64 opCode)
+ {
+ return opCode.Emitter == InstEmit.Brk ||
+ opCode.Emitter == InstEmit.Svc ||
+ opCode.Emitter == InstEmit.Und;
+ }
+
+ public static OpCode64 DecodeOpCode(CpuThreadState state, MemoryManager memory, long position)
+ {
+ int opCode = memory.ReadInt32(position);
+
+ Inst inst;
+
+ if (state.ExecutionMode == ExecutionMode.AArch64)
+ {
+ inst = OpCodeTable.GetInstA64(opCode);
+ }
+ else
+ {
+ //TODO: Thumb support.
+ inst = OpCodeTable.GetInstA32(opCode);
+ }
+
+ OpCode64 decodedOpCode = new OpCode64(Inst.Undefined, position, opCode);
+
+ if (inst.Type != null)
+ {
+ decodedOpCode = MakeOpCode(inst.Type, inst, position, 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
new file mode 100644
index 00000000..6ee279d7
--- /dev/null
+++ b/ChocolArm64/Decoders/DecoderHelper.cs
@@ -0,0 +1,107 @@
+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 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/IOpCode64.cs b/ChocolArm64/Decoders/IOpCode64.cs
new file mode 100644
index 00000000..e9407123
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCode64.cs
@@ -0,0 +1,13 @@
+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
new file mode 100644
index 00000000..b9a5fe9e
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeAlu64.cs
@@ -0,0 +1,10 @@
+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
new file mode 100644
index 00000000..4b305e27
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeAluImm64.cs
@@ -0,0 +1,7 @@
+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
new file mode 100644
index 00000000..df503ae9
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeAluRs64.cs
@@ -0,0 +1,10 @@
+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
new file mode 100644
index 00000000..f41fc4d2
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeAluRx64.cs
@@ -0,0 +1,10 @@
+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/IOpCodeCond64.cs b/ChocolArm64/Decoders/IOpCodeCond64.cs
new file mode 100644
index 00000000..9c39d633
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeCond64.cs
@@ -0,0 +1,7 @@
+namespace ChocolArm64.Decoders
+{
+ interface IOpCodeCond64 : IOpCode64
+ {
+ Cond Cond { get; }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/IAOpCodeLit.cs b/ChocolArm64/Decoders/IOpCodeLit64.cs
index 0f5092d0..c6dc2c7f 100644
--- a/ChocolArm64/Decoder/IAOpCodeLit.cs
+++ b/ChocolArm64/Decoders/IOpCodeLit64.cs
@@ -1,6 +1,6 @@
-namespace ChocolArm64.Decoder
+namespace ChocolArm64.Decoders
{
- interface IAOpCodeLit : IAOpCode
+ interface IOpCodeLit64 : IOpCode64
{
int Rt { get; }
long Imm { get; }
diff --git a/ChocolArm64/Decoders/IOpCodeSimd64.cs b/ChocolArm64/Decoders/IOpCodeSimd64.cs
new file mode 100644
index 00000000..fc8f54d6
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeSimd64.cs
@@ -0,0 +1,7 @@
+namespace ChocolArm64.Decoders
+{
+ interface IOpCodeSimd64 : IOpCode64
+ {
+ int Size { get; }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoder/AIntType.cs b/ChocolArm64/Decoders/IntType.cs
index 242fdada..70f833ec 100644
--- a/ChocolArm64/Decoder/AIntType.cs
+++ b/ChocolArm64/Decoders/IntType.cs
@@ -1,6 +1,6 @@
-namespace ChocolArm64.Decoder
+namespace ChocolArm64.Decoders
{
- enum AIntType
+ enum IntType
{
UInt8 = 0,
UInt16 = 1,
diff --git a/ChocolArm64/Decoders/OpCode64.cs b/ChocolArm64/Decoders/OpCode64.cs
new file mode 100644
index 00000000..b2dc363b
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCode64.cs
@@ -0,0 +1,40 @@
+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 InstEmitter Emitter { get; protected set; }
+ public InstInterpreter Interpreter { 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;
+ Interpreter = inst.Interpreter;
+ }
+
+ 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
new file mode 100644
index 00000000..98b2f07b
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeAdr64.cs
@@ -0,0 +1,18 @@
+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
new file mode 100644
index 00000000..5f094572
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeAlu64.cs
@@ -0,0 +1,24 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+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
new file mode 100644
index 00000000..64ac08a7
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeAluImm64.cs
@@ -0,0 +1,39 @@
+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
new file mode 100644
index 00000000..f24c7f37
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeAluRs64.cs
@@ -0,0 +1,29 @@
+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
new file mode 100644
index 00000000..a36f94ca
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeAluRx64.cs
@@ -0,0 +1,19 @@
+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
new file mode 100644
index 00000000..71c61bab
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBImm64.cs
@@ -0,0 +1,11 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeBImm64 : OpCode64
+ {
+ 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
new file mode 100644
index 00000000..f419ffa0
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBImmAl64.cs
@@ -0,0 +1,12 @@
+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
new file mode 100644
index 00000000..6f433199
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBImmCmp64.cs
@@ -0,0 +1,21 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+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
new file mode 100644
index 00000000..22702309
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBImmCond64.cs
@@ -0,0 +1,25 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeBImmCond64 : OpCodeBImm64, IOpCodeCond64
+ {
+ public Cond 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 = (Cond)(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
new file mode 100644
index 00000000..a2e8baea
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBImmTest64.cs
@@ -0,0 +1,20 @@
+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
new file mode 100644
index 00000000..74dbff58
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBReg64.cs
@@ -0,0 +1,24 @@
+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
new file mode 100644
index 00000000..6891a8f4
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBfm64.cs
@@ -0,0 +1,29 @@
+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
new file mode 100644
index 00000000..e2aae96d
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeCcmp64.cs
@@ -0,0 +1,31 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeCcmp64 : OpCodeAlu64, IOpCodeCond64
+ {
+ public int Nzcv { get; private set; }
+ protected int RmImm;
+
+ public Cond 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 = (Cond)((opCode >> 12) & 0xf);
+ RmImm = (opCode >> 16) & 0x1f;
+
+ Rd = CpuThreadState.ZrIndex;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeCcmpImm64.cs b/ChocolArm64/Decoders/OpCodeCcmpImm64.cs
new file mode 100644
index 00000000..78d5de55
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeCcmpImm64.cs
@@ -0,0 +1,11 @@
+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
new file mode 100644
index 00000000..a0544d98
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeCcmpReg64.cs
@@ -0,0 +1,15 @@
+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
new file mode 100644
index 00000000..d085a823
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeCsel64.cs
@@ -0,0 +1,17 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeCsel64 : OpCodeAlu64, IOpCodeCond64
+ {
+ public int Rm { get; private set; }
+
+ public Cond Cond { get; private set; }
+
+ public OpCodeCsel64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rm = (opCode >> 16) & 0x1f;
+ Cond = (Cond)((opCode >> 12) & 0xf);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeException64.cs b/ChocolArm64/Decoders/OpCodeException64.cs
new file mode 100644
index 00000000..2554124c
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeException64.cs
@@ -0,0 +1,14 @@
+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
new file mode 100644
index 00000000..36e67583
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMem64.cs
@@ -0,0 +1,19 @@
+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
new file mode 100644
index 00000000..39935eb3
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMemEx64.cs
@@ -0,0 +1,16 @@
+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/Decoder/AOpCodeMemImm.cs b/ChocolArm64/Decoders/OpCodeMemImm64.cs
index 14edc514..edaa4970 100644
--- a/ChocolArm64/Decoder/AOpCodeMemImm.cs
+++ b/ChocolArm64/Decoders/OpCodeMemImm64.cs
@@ -1,8 +1,8 @@
-using ChocolArm64.Instruction;
+using ChocolArm64.Instructions;
-namespace ChocolArm64.Decoder
+namespace ChocolArm64.Decoders
{
- class AOpCodeMemImm : AOpCodeMem
+ class OpCodeMemImm64 : OpCodeMem64
{
public long Imm { get; protected set; }
public bool WBack { get; protected set; }
@@ -18,18 +18,18 @@ namespace ChocolArm64.Decoder
Unsigned
}
- public AOpCodeMemImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
+ public OpCodeMemImm64(Inst inst, long position, int opCode) : base(inst, position, opCode)
{
- Extend64 = ((OpCode >> 22) & 3) == 2;
- WBack = ((OpCode >> 24) & 1) == 0;
+ 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;
+ MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned;
- PostIdx = Type == MemOp.PostIndexed;
- Unscaled = Type == MemOp.Unscaled ||
- Type == MemOp.Unprivileged;
+ 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.
@@ -41,12 +41,12 @@ namespace ChocolArm64.Decoder
if (WBack || Unscaled)
{
//9-bits Signed Immediate.
- Imm = (OpCode << 43) >> 55;
+ Imm = (opCode << 43) >> 55;
}
else
{
//12-bits Unsigned Immediate.
- Imm = ((OpCode >> 10) & 0xfff) << Size;
+ Imm = ((opCode >> 10) & 0xfff) << Size;
}
}
}
diff --git a/ChocolArm64/Decoder/AOpCodeMemLit.cs b/ChocolArm64/Decoders/OpCodeMemLit64.cs
index ad719a19..29bfeee3 100644
--- a/ChocolArm64/Decoder/AOpCodeMemLit.cs
+++ b/ChocolArm64/Decoders/OpCodeMemLit64.cs
@@ -1,8 +1,8 @@
-using ChocolArm64.Instruction;
+using ChocolArm64.Instructions;
-namespace ChocolArm64.Decoder
+namespace ChocolArm64.Decoders
{
- class AOpCodeMemLit : AOpCode, IAOpCodeLit
+ class OpCodeMemLit64 : OpCode64, IOpCodeLit64
{
public int Rt { get; private set; }
public long Imm { get; private set; }
@@ -10,13 +10,13 @@ namespace ChocolArm64.Decoder
public bool Signed { get; private set; }
public bool Prefetch { get; private set; }
- public AOpCodeMemLit(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
+ public OpCodeMemLit64(Inst inst, long position, int opCode) : base(inst, position, opCode)
{
- Rt = OpCode & 0x1f;
+ Rt = opCode & 0x1f;
- Imm = Position + ADecoderHelper.DecodeImmS19_2(OpCode);
+ Imm = position + DecoderHelper.DecodeImmS19_2(opCode);
- switch ((OpCode >> 30) & 3)
+ switch ((opCode >> 30) & 3)
{
case 0: Size = 2; Signed = false; Prefetch = false; break;
case 1: Size = 3; Signed = false; Prefetch = false; break;
diff --git a/ChocolArm64/Decoders/OpCodeMemPair64.cs b/ChocolArm64/Decoders/OpCodeMemPair64.cs
new file mode 100644
index 00000000..5b81c755
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMemPair64.cs
@@ -0,0 +1,25 @@
+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
new file mode 100644
index 00000000..3dd210fb
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMemReg64.cs
@@ -0,0 +1,20 @@
+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
new file mode 100644
index 00000000..f9697854
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMov64.cs
@@ -0,0 +1,36 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+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
new file mode 100644
index 00000000..176b7b93
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMul64.cs
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 00000000..a705e489
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimd64.cs
@@ -0,0 +1,25 @@
+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
new file mode 100644
index 00000000..6c68a3af
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdCvt64.cs
@@ -0,0 +1,31 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdCvt64 : OpCodeSimd64
+ {
+ public int FBits { get; private set; }
+
+ public OpCodeSimdCvt64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ //TODO:
+ //Und of Fixed Point variants.
+ int scale = (opCode >> 10) & 0x3f;
+ int sf = (opCode >> 31) & 0x1;
+
+ /*if (Type != SF && !(Type == 2 && SF == 1))
+ {
+ Emitter = AInstEmit.Und;
+
+ return;
+ }*/
+
+ 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
new file mode 100644
index 00000000..1c57f19c
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdExt64.cs
@@ -0,0 +1,14 @@
+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
new file mode 100644
index 00000000..b0f1c0eb
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdFcond64.cs
@@ -0,0 +1,17 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdFcond64 : OpCodeSimdReg64, IOpCodeCond64
+ {
+ public int Nzcv { get; private set; }
+
+ public Cond Cond { get; private set; }
+
+ public OpCodeSimdFcond64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Nzcv = (opCode >> 0) & 0xf;
+ Cond = (Cond)((opCode >> 12) & 0xf);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdFmov64.cs b/ChocolArm64/Decoders/OpCodeSimdFmov64.cs
new file mode 100644
index 00000000..6752e185
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdFmov64.cs
@@ -0,0 +1,33 @@
+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
new file mode 100644
index 00000000..3ef6a8c6
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdImm64.cs
@@ -0,0 +1,101 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+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
new file mode 100644
index 00000000..3b25faeb
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdIns64.cs
@@ -0,0 +1,36 @@
+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
new file mode 100644
index 00000000..9fbab567
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdMemImm64.cs
@@ -0,0 +1,19 @@
+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
new file mode 100644
index 00000000..c98ffd03
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdMemLit64.cs
@@ -0,0 +1,31 @@
+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/Decoder/AOpCodeSimdMemMs.cs b/ChocolArm64/Decoders/OpCodeSimdMemMs64.cs
index a54e2360..0748ef43 100644
--- a/ChocolArm64/Decoder/AOpCodeSimdMemMs.cs
+++ b/ChocolArm64/Decoders/OpCodeSimdMemMs64.cs
@@ -1,18 +1,18 @@
-using ChocolArm64.Instruction;
+using ChocolArm64.Instructions;
using ChocolArm64.State;
-namespace ChocolArm64.Decoder
+namespace ChocolArm64.Decoders
{
- class AOpCodeSimdMemMs : AOpCodeMemReg, IAOpCodeSimd
+ 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 AOpCodeSimdMemMs(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
+ public OpCodeSimdMemMs64(Inst inst, long position, int opCode) : base(inst, position, opCode)
{
- switch ((OpCode >> 12) & 0xf)
+ switch ((opCode >> 12) & 0xf)
{
case 0b0000: Reps = 1; SElems = 4; break;
case 0b0010: Reps = 4; SElems = 1; break;
@@ -22,26 +22,26 @@ namespace ChocolArm64.Decoder
case 0b1000: Reps = 1; SElems = 2; break;
case 0b1010: Reps = 2; SElems = 1; break;
- default: Inst = AInst.Undefined; return;
+ default: inst = Inst.Undefined; return;
}
- Size = (OpCode >> 10) & 3;
- WBack = ((OpCode >> 23) & 1) != 0;
+ Size = (opCode >> 10) & 3;
+ WBack = ((opCode >> 23) & 1) != 0;
- bool Q = ((OpCode >> 30) & 1) != 0;
+ bool q = ((opCode >> 30) & 1) != 0;
- if (!Q && Size == 3 && SElems != 1)
+ if (!q && Size == 3 && SElems != 1)
{
- Inst = AInst.Undefined;
+ inst = Inst.Undefined;
return;
}
Extend64 = false;
- RegisterSize = Q
- ? ARegisterSize.SIMD128
- : ARegisterSize.SIMD64;
+ RegisterSize = q
+ ? State.RegisterSize.Simd128
+ : State.RegisterSize.Simd64;
Elems = (GetBitsCount() >> 3) >> Size;
}
diff --git a/ChocolArm64/Decoders/OpCodeSimdMemPair64.cs b/ChocolArm64/Decoders/OpCodeSimdMemPair64.cs
new file mode 100644
index 00000000..1b796742
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdMemPair64.cs
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 00000000..4ccbbed2
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdMemReg64.cs
@@ -0,0 +1,14 @@
+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
new file mode 100644
index 00000000..07ec8ab7
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdMemSs64.cs
@@ -0,0 +1,98 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+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
new file mode 100644
index 00000000..4bf462de
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdReg64.cs
@@ -0,0 +1,18 @@
+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
new file mode 100644
index 00000000..04e95861
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdRegElem64.cs
@@ -0,0 +1,31 @@
+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
new file mode 100644
index 00000000..b5db7345
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs
@@ -0,0 +1,33 @@
+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
new file mode 100644
index 00000000..d4cd88d1
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdShImm64.cs
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 00000000..13cc9090
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdTbl64.cs
@@ -0,0 +1,12 @@
+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
new file mode 100644
index 00000000..41c51565
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSystem64.cs
@@ -0,0 +1,24 @@
+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/Decoder/AShiftType.cs b/ChocolArm64/Decoders/ShiftType.cs
index 34ceea20..5f6a7a4c 100644
--- a/ChocolArm64/Decoder/AShiftType.cs
+++ b/ChocolArm64/Decoders/ShiftType.cs
@@ -1,6 +1,6 @@
-namespace ChocolArm64.Decoder
+namespace ChocolArm64.Decoders
{
- enum AShiftType
+ enum ShiftType
{
Lsl,
Lsr,
diff --git a/ChocolArm64/Decoders32/A32OpCode.cs b/ChocolArm64/Decoders32/A32OpCode.cs
new file mode 100644
index 00000000..f0177a43
--- /dev/null
+++ b/ChocolArm64/Decoders32/A32OpCode.cs
@@ -0,0 +1,15 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders32
+{
+ class A32OpCode : OpCode64
+ {
+ public Cond Cond { get; private set; }
+
+ public A32OpCode(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Cond = (Cond)((uint)opCode >> 28);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders32/A32OpCodeBImmAl.cs b/ChocolArm64/Decoders32/A32OpCodeBImmAl.cs
new file mode 100644
index 00000000..c4a196b6
--- /dev/null
+++ b/ChocolArm64/Decoders32/A32OpCodeBImmAl.cs
@@ -0,0 +1,16 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders32
+{
+ class A32OpCodeBImmAl : A32OpCode
+ {
+ public int Imm;
+ public int H;
+
+ public A32OpCodeBImmAl(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Imm = (opCode << 8) >> 6;
+ H = (opCode >> 23) & 2;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Events/ACpuTraceEventArgs.cs b/ChocolArm64/Events/ACpuTraceEventArgs.cs
deleted file mode 100644
index 0284f4ee..00000000
--- a/ChocolArm64/Events/ACpuTraceEventArgs.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-
-namespace ChocolArm64.Events
-{
- public class ACpuTraceEventArgs : EventArgs
- {
- public long Position { get; private set; }
-
- public ACpuTraceEventArgs(long Position)
- {
- this.Position = Position;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Events/AInstExceptionEventArgs.cs b/ChocolArm64/Events/AInstExceptionEventArgs.cs
deleted file mode 100644
index a6853ea1..00000000
--- a/ChocolArm64/Events/AInstExceptionEventArgs.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-
-namespace ChocolArm64.Events
-{
- public class AInstExceptionEventArgs : EventArgs
- {
- public long Position { get; private set; }
- public int Id { get; private set; }
-
- public AInstExceptionEventArgs(long Position, int Id)
- {
- this.Position = Position;
- this.Id = Id;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Events/AInstUndefinedEventArgs.cs b/ChocolArm64/Events/AInstUndefinedEventArgs.cs
deleted file mode 100644
index cdc1728b..00000000
--- a/ChocolArm64/Events/AInstUndefinedEventArgs.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-
-namespace ChocolArm64.Events
-{
- public class AInstUndefinedEventArgs : EventArgs
- {
- public long Position { get; private set; }
- public int RawOpCode { get; private set; }
-
- public AInstUndefinedEventArgs(long Position, int RawOpCode)
- {
- this.Position = Position;
- this.RawOpCode = RawOpCode;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Events/AInvalidAccessEventArgs.cs b/ChocolArm64/Events/AInvalidAccessEventArgs.cs
deleted file mode 100644
index a5c472a8..00000000
--- a/ChocolArm64/Events/AInvalidAccessEventArgs.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-
-namespace ChocolArm64.Events
-{
- public class AInvalidAccessEventArgs : EventArgs
- {
- public long Position { get; private set; }
-
- public AInvalidAccessEventArgs(long Position)
- {
- this.Position = Position;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Events/CpuTraceEventArgs.cs b/ChocolArm64/Events/CpuTraceEventArgs.cs
new file mode 100644
index 00000000..c12781ed
--- /dev/null
+++ b/ChocolArm64/Events/CpuTraceEventArgs.cs
@@ -0,0 +1,14 @@
+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
new file mode 100644
index 00000000..e3cc0ba0
--- /dev/null
+++ b/ChocolArm64/Events/InstExceptionEventArgs.cs
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 00000000..3ad7ea8b
--- /dev/null
+++ b/ChocolArm64/Events/InstUndefinedEventArgs.cs
@@ -0,0 +1,16 @@
+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/Events/InvalidAccessEventArgs.cs b/ChocolArm64/Events/InvalidAccessEventArgs.cs
new file mode 100644
index 00000000..a8046d73
--- /dev/null
+++ b/ChocolArm64/Events/InvalidAccessEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace ChocolArm64.Events
+{
+ public class InvalidAccessEventArgs : EventArgs
+ {
+ public long Position { get; private set; }
+
+ public InvalidAccessEventArgs(long position)
+ {
+ Position = position;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Exceptions/VmmOutOfMemoryException.cs b/ChocolArm64/Exceptions/VmmOutOfMemoryException.cs
index 4a03b65c..d6ddf752 100644
--- a/ChocolArm64/Exceptions/VmmOutOfMemoryException.cs
+++ b/ChocolArm64/Exceptions/VmmOutOfMemoryException.cs
@@ -8,6 +8,6 @@ namespace ChocolArm64.Exceptions
public VmmAccessException() { }
- public VmmAccessException(long Position, long Size) : base(string.Format(ExMsg, Position, Size)) { }
+ public VmmAccessException(long position, long size) : base(string.Format(ExMsg, position, size)) { }
}
} \ No newline at end of file
diff --git a/ChocolArm64/Exceptions/VmmPageFaultException.cs b/ChocolArm64/Exceptions/VmmPageFaultException.cs
index d55c2c1c..f33aafc0 100644
--- a/ChocolArm64/Exceptions/VmmPageFaultException.cs
+++ b/ChocolArm64/Exceptions/VmmPageFaultException.cs
@@ -8,6 +8,6 @@ namespace ChocolArm64.Exceptions
public VmmPageFaultException() { }
- public VmmPageFaultException(long Position) : base(string.Format(ExMsg, Position)) { }
+ public VmmPageFaultException(long position) : base(string.Format(ExMsg, position)) { }
}
} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInst.cs b/ChocolArm64/Instruction/AInst.cs
deleted file mode 100644
index 74093536..00000000
--- a/ChocolArm64/Instruction/AInst.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-
-namespace ChocolArm64.Instruction
-{
- struct AInst
- {
- public AInstInterpreter Interpreter { get; private set; }
- public AInstEmitter Emitter { get; private set; }
- public Type Type { get; private set; }
-
- public static AInst Undefined => new AInst(null, AInstEmit.Und, null);
-
- public AInst(AInstInterpreter Interpreter, AInstEmitter Emitter, Type Type)
- {
- this.Interpreter = Interpreter;
- this.Emitter = Emitter;
- this.Type = Type;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitAlu.cs b/ChocolArm64/Instruction/AInstEmitAlu.cs
deleted file mode 100644
index 4551346b..00000000
--- a/ChocolArm64/Instruction/AInstEmitAlu.cs
+++ /dev/null
@@ -1,402 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitAluHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Adc(AILEmitterCtx Context) => EmitAdc(Context, false);
- public static void Adcs(AILEmitterCtx Context) => EmitAdc(Context, true);
-
- private static void EmitAdc(AILEmitterCtx Context, bool SetFlags)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Add);
-
- Context.EmitLdflg((int)APState.CBit);
-
- Type[] MthdTypes = new Type[] { typeof(bool) };
-
- MethodInfo MthdInfo = typeof(Convert).GetMethod(nameof(Convert.ToInt32), MthdTypes);
-
- Context.EmitCall(MthdInfo);
-
- if (Context.CurrOp.RegisterSize != ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- Context.Emit(OpCodes.Add);
-
- if (SetFlags)
- {
- Context.EmitZNFlagCheck();
-
- EmitAdcsCCheck(Context);
- EmitAddsVCheck(Context);
- }
-
- EmitDataStore(Context);
- }
-
- public static void Add(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Add);
-
- public static void Adds(AILEmitterCtx Context)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Add);
-
- Context.EmitZNFlagCheck();
-
- EmitAddsCCheck(Context);
- EmitAddsVCheck(Context);
- EmitDataStoreS(Context);
- }
-
- public static void And(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.And);
-
- public static void Ands(AILEmitterCtx Context)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.And);
-
- EmitZeroCVFlags(Context);
-
- Context.EmitZNFlagCheck();
-
- EmitDataStoreS(Context);
- }
-
- public static void Asrv(AILEmitterCtx Context) => EmitDataOpShift(Context, OpCodes.Shr);
-
- public static void Bic(AILEmitterCtx Context) => EmitBic(Context, false);
- public static void Bics(AILEmitterCtx Context) => EmitBic(Context, true);
-
- private static void EmitBic(AILEmitterCtx Context, bool SetFlags)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.And);
-
- if (SetFlags)
- {
- EmitZeroCVFlags(Context);
-
- Context.EmitZNFlagCheck();
- }
-
- EmitDataStore(Context, SetFlags);
- }
-
- public static void Cls(AILEmitterCtx Context)
- {
- AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- Context.EmitLdc_I4(Op.RegisterSize == ARegisterSize.Int32 ? 32 : 64);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountLeadingSigns));
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Clz(AILEmitterCtx Context)
- {
- AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- if (Lzcnt.IsSupported)
- {
- Type TValue = Op.RegisterSize == ARegisterSize.Int32 ? typeof(uint) : typeof(ulong);
-
- Context.EmitCall(typeof(Lzcnt).GetMethod(nameof(Lzcnt.LeadingZeroCount), new Type[] { TValue }));
- }
- else
- {
- Context.EmitLdc_I4(Op.RegisterSize == ARegisterSize.Int32 ? 32 : 64);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountLeadingZeros));
- }
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Eon(AILEmitterCtx Context)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.Xor);
-
- EmitDataStore(Context);
- }
-
- public static void Eor(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Xor);
-
- public static void Extr(AILEmitterCtx Context)
- {
- //TODO: Ensure that the Shift is valid for the Is64Bits.
- AOpCodeAluRs Op = (AOpCodeAluRs)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);
- }
-
- EmitDataStore(Context);
- }
-
- public static void Lslv(AILEmitterCtx Context) => EmitDataOpShift(Context, OpCodes.Shl);
- public static void Lsrv(AILEmitterCtx Context) => EmitDataOpShift(Context, OpCodes.Shr_Un);
-
- public static void Sbc(AILEmitterCtx Context) => EmitSbc(Context, false);
- public static void Sbcs(AILEmitterCtx Context) => EmitSbc(Context, true);
-
- private static void EmitSbc(AILEmitterCtx Context, bool SetFlags)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Sub);
-
- Context.EmitLdflg((int)APState.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 != ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- Context.Emit(OpCodes.Sub);
-
- if (SetFlags)
- {
- Context.EmitZNFlagCheck();
-
- EmitSbcsCCheck(Context);
- EmitSubsVCheck(Context);
- }
-
- EmitDataStore(Context);
- }
-
- public static void Sub(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Sub);
-
- public static void Subs(AILEmitterCtx Context)
- {
- Context.TryOptMarkCondWithoutCmp();
-
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Sub);
-
- Context.EmitZNFlagCheck();
-
- EmitSubsCCheck(Context);
- EmitSubsVCheck(Context);
- EmitDataStoreS(Context);
- }
-
- public static void Orn(AILEmitterCtx Context)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.Or);
-
- EmitDataStore(Context);
- }
-
- public static void Orr(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Or);
-
- public static void Rbit(AILEmitterCtx Context) => EmitFallback32_64(Context,
- nameof(ASoftFallback.ReverseBits32),
- nameof(ASoftFallback.ReverseBits64));
-
- public static void Rev16(AILEmitterCtx Context) => EmitFallback32_64(Context,
- nameof(ASoftFallback.ReverseBytes16_32),
- nameof(ASoftFallback.ReverseBytes16_64));
-
- public static void Rev32(AILEmitterCtx Context) => EmitFallback32_64(Context,
- nameof(ASoftFallback.ReverseBytes32_32),
- nameof(ASoftFallback.ReverseBytes32_64));
-
- private static void EmitFallback32_64(AILEmitterCtx Context, string Name32, string Name64)
- {
- AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- if (Op.RegisterSize == ARegisterSize.Int32)
- {
- ASoftFallback.EmitCall(Context, Name32);
- }
- else
- {
- ASoftFallback.EmitCall(Context, Name64);
- }
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Rev64(AILEmitterCtx Context)
- {
- AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ReverseBytes64));
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Rorv(AILEmitterCtx Context)
- {
- EmitDataLoadRn(Context);
- EmitDataLoadShift(Context);
-
- Context.Emit(OpCodes.Shr_Un);
-
- EmitDataLoadRn(Context);
-
- Context.EmitLdc_I4(Context.CurrOp.GetBitsCount());
-
- EmitDataLoadShift(Context);
-
- Context.Emit(OpCodes.Sub);
- Context.Emit(OpCodes.Shl);
- Context.Emit(OpCodes.Or);
-
- EmitDataStore(Context);
- }
-
- public static void Sdiv(AILEmitterCtx Context) => EmitDiv(Context, OpCodes.Div);
- public static void Udiv(AILEmitterCtx Context) => EmitDiv(Context, OpCodes.Div_Un);
-
- private static void EmitDiv(AILEmitterCtx Context, OpCode ILOp)
- {
- //If Rm == 0, Rd = 0 (division by zero).
- Context.EmitLdc_I(0);
-
- EmitDataLoadRm(Context);
-
- Context.EmitLdc_I(0);
-
- AILLabel BadDiv = new AILLabel();
-
- 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);
-
- EmitDataLoadRn(Context);
-
- Context.EmitLdc_I(IntMin);
-
- Context.Emit(OpCodes.Ceq);
-
- EmitDataLoadRm(Context);
-
- Context.EmitLdc_I(-1);
-
- Context.Emit(OpCodes.Ceq);
- Context.Emit(OpCodes.And);
- Context.Emit(OpCodes.Brtrue_S, BadDiv);
- Context.Emit(OpCodes.Pop);
- }
-
- EmitDataLoadRn(Context);
- EmitDataLoadRm(Context);
-
- Context.Emit(ILOp);
-
- Context.MarkLabel(BadDiv);
-
- EmitDataStore(Context);
- }
-
- private static void EmitDataOp(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(ILOp);
-
- EmitDataStore(Context);
- }
-
- private static void EmitDataOpShift(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitDataLoadRn(Context);
- EmitDataLoadShift(Context);
-
- Context.Emit(ILOp);
-
- EmitDataStore(Context);
- }
-
- private static void EmitDataLoadShift(AILEmitterCtx Context)
- {
- EmitDataLoadRm(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 != ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_I4);
- }
- }
-
- private static void EmitZeroCVFlags(AILEmitterCtx Context)
- {
- Context.EmitLdc_I4(0);
-
- Context.EmitStflg((int)APState.VBit);
-
- Context.EmitLdc_I4(0);
-
- Context.EmitStflg((int)APState.CBit);
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitAluHelper.cs b/ChocolArm64/Instruction/AInstEmitAluHelper.cs
deleted file mode 100644
index ef9dd7a7..00000000
--- a/ChocolArm64/Instruction/AInstEmitAluHelper.cs
+++ /dev/null
@@ -1,212 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static class AInstEmitAluHelper
- {
- public static void EmitAdcsCCheck(AILEmitterCtx Context)
- {
- //C = (Rd == Rn && CIn) || Rd < Rn
- Context.EmitSttmp();
- Context.EmitLdtmp();
- Context.EmitLdtmp();
-
- EmitDataLoadRn(Context);
-
- Context.Emit(OpCodes.Ceq);
-
- Context.EmitLdflg((int)APState.CBit);
-
- Context.Emit(OpCodes.And);
-
- Context.EmitLdtmp();
-
- EmitDataLoadRn(Context);
-
- Context.Emit(OpCodes.Clt_Un);
- Context.Emit(OpCodes.Or);
-
- Context.EmitStflg((int)APState.CBit);
- }
-
- public static void EmitAddsCCheck(AILEmitterCtx Context)
- {
- //C = Rd < Rn
- Context.Emit(OpCodes.Dup);
-
- EmitDataLoadRn(Context);
-
- Context.Emit(OpCodes.Clt_Un);
-
- Context.EmitStflg((int)APState.CBit);
- }
-
- public static void EmitAddsVCheck(AILEmitterCtx Context)
- {
- //V = (Rd ^ Rn) & ~(Rn ^ Rm) < 0
- Context.Emit(OpCodes.Dup);
-
- EmitDataLoadRn(Context);
-
- Context.Emit(OpCodes.Xor);
-
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Xor);
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.And);
-
- Context.EmitLdc_I(0);
-
- Context.Emit(OpCodes.Clt);
-
- Context.EmitStflg((int)APState.VBit);
- }
-
- public static void EmitSbcsCCheck(AILEmitterCtx Context)
- {
- //C = (Rn == Rm && CIn) || Rn > Rm
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Ceq);
-
- Context.EmitLdflg((int)APState.CBit);
-
- Context.Emit(OpCodes.And);
-
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Cgt_Un);
- Context.Emit(OpCodes.Or);
-
- Context.EmitStflg((int)APState.CBit);
- }
-
- public static void EmitSubsCCheck(AILEmitterCtx Context)
- {
- //C = Rn == Rm || Rn > Rm = !(Rn < Rm)
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Clt_Un);
-
- Context.EmitLdc_I4(1);
-
- Context.Emit(OpCodes.Xor);
-
- Context.EmitStflg((int)APState.CBit);
- }
-
- public static void EmitSubsVCheck(AILEmitterCtx Context)
- {
- //V = (Rd ^ Rn) & (Rn ^ Rm) < 0
- Context.Emit(OpCodes.Dup);
-
- EmitDataLoadRn(Context);
-
- Context.Emit(OpCodes.Xor);
-
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Xor);
- Context.Emit(OpCodes.And);
-
- Context.EmitLdc_I(0);
-
- Context.Emit(OpCodes.Clt);
-
- Context.EmitStflg((int)APState.VBit);
- }
-
- public static void EmitDataLoadRm(AILEmitterCtx Context)
- {
- Context.EmitLdintzr(((IAOpCodeAluRs)Context.CurrOp).Rm);
- }
-
- public static void EmitDataLoadOpers(AILEmitterCtx Context)
- {
- EmitDataLoadRn(Context);
- EmitDataLoadOper2(Context);
- }
-
- public static void EmitDataLoadRn(AILEmitterCtx Context)
- {
- IAOpCodeAlu Op = (IAOpCodeAlu)Context.CurrOp;
-
- if (Op.DataOp == ADataOp.Logical || Op is IAOpCodeAluRs)
- {
- Context.EmitLdintzr(Op.Rn);
- }
- else
- {
- Context.EmitLdint(Op.Rn);
- }
- }
-
- public static void EmitDataLoadOper2(AILEmitterCtx Context)
- {
- switch (Context.CurrOp)
- {
- case IAOpCodeAluImm Op:
- Context.EmitLdc_I(Op.Imm);
- break;
-
- case IAOpCodeAluRs Op:
- Context.EmitLdintzr(Op.Rm);
-
- switch (Op.ShiftType)
- {
- case AShiftType.Lsl: Context.EmitLsl(Op.Shift); break;
- case AShiftType.Lsr: Context.EmitLsr(Op.Shift); break;
- case AShiftType.Asr: Context.EmitAsr(Op.Shift); break;
- case AShiftType.Ror: Context.EmitRor(Op.Shift); break;
- }
- break;
-
- case IAOpCodeAluRx Op:
- Context.EmitLdintzr(Op.Rm);
- Context.EmitCast(Op.IntType);
- Context.EmitLsl(Op.Shift);
- break;
- }
- }
-
- public static void EmitDataStore(AILEmitterCtx Context) => EmitDataStore(Context, false);
- public static void EmitDataStoreS(AILEmitterCtx Context) => EmitDataStore(Context, true);
-
- public static void EmitDataStore(AILEmitterCtx Context, bool SetFlags)
- {
- IAOpCodeAlu Op = (IAOpCodeAlu)Context.CurrOp;
-
- if (SetFlags || Op is IAOpCodeAluRs)
- {
- Context.EmitStintzr(Op.Rd);
- }
- else
- {
- Context.EmitStint(Op.Rd);
- }
- }
-
- public static void EmitSetNZCV(AILEmitterCtx Context, int NZCV)
- {
- Context.EmitLdc_I4((NZCV >> 0) & 1);
-
- Context.EmitStflg((int)APState.VBit);
-
- Context.EmitLdc_I4((NZCV >> 1) & 1);
-
- Context.EmitStflg((int)APState.CBit);
-
- Context.EmitLdc_I4((NZCV >> 2) & 1);
-
- Context.EmitStflg((int)APState.ZBit);
-
- Context.EmitLdc_I4((NZCV >> 3) & 1);
-
- Context.EmitStflg((int)APState.NBit);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitBfm.cs b/ChocolArm64/Instruction/AInstEmitBfm.cs
deleted file mode 100644
index 2e8f2508..00000000
--- a/ChocolArm64/Instruction/AInstEmitBfm.cs
+++ /dev/null
@@ -1,208 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Bfm(AILEmitterCtx Context)
- {
- AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
-
- EmitBfmLoadRn(Context);
-
- Context.EmitLdintzr(Op.Rd);
- Context.EmitLdc_I(~Op.WMask & Op.TMask);
-
- Context.Emit(OpCodes.And);
- Context.Emit(OpCodes.Or);
-
- Context.EmitLdintzr(Op.Rd);
- Context.EmitLdc_I(~Op.TMask);
-
- Context.Emit(OpCodes.And);
- Context.Emit(OpCodes.Or);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Sbfm(AILEmitterCtx Context)
- {
- AOpCodeBfm Op = (AOpCodeBfm)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(AILEmitterCtx Context)
- {
- AOpCodeBfm Op = (AOpCodeBfm)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(AILEmitterCtx Context) => EmitBfiz(Context, true);
- private static void EmitUbfiz(AILEmitterCtx Context) => EmitBfiz(Context, false);
-
- private static void EmitBfiz(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeBfm Op = (AOpCodeBfm)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(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitBfmCast(Context, ILOp, true);
- }
-
- private static void EmitUbfmCast(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitBfmCast(Context, ILOp, false);
- }
-
- private static void EmitBfmCast(AILEmitterCtx Context, OpCode ILOp, bool Signed)
- {
- AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- Context.Emit(ILOp);
-
- if (Op.RegisterSize != ARegisterSize.Int32)
- {
- Context.Emit(Signed
- ? OpCodes.Conv_I8
- : OpCodes.Conv_U8);
- }
-
- Context.EmitStintzr(Op.Rd);
- }
-
- private static void EmitSbfmShift(AILEmitterCtx Context)
- {
- EmitBfmShift(Context, true);
- }
-
- private static void EmitUbfmShift(AILEmitterCtx Context)
- {
- EmitBfmShift(Context, false);
- }
-
- private static void EmitBfmShift(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeBfm Op = (AOpCodeBfm)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(AILEmitterCtx Context)
- {
- AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- Context.EmitLsl(Op.GetBitsCount() - Op.Shift);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- private static void EmitBfmLoadRn(AILEmitterCtx Context)
- {
- AOpCodeBfm Op = (AOpCodeBfm)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/Instruction/AInstEmitCcmp.cs b/ChocolArm64/Instruction/AInstEmitCcmp.cs
deleted file mode 100644
index 7153a6a0..00000000
--- a/ChocolArm64/Instruction/AInstEmitCcmp.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-
-using static ChocolArm64.Instruction.AInstEmitAluHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- private enum CcmpOp
- {
- Cmp,
- Cmn
- }
-
- public static void Ccmn(AILEmitterCtx Context) => EmitCcmp(Context, CcmpOp.Cmn);
- public static void Ccmp(AILEmitterCtx Context) => EmitCcmp(Context, CcmpOp.Cmp);
-
- private static void EmitCcmp(AILEmitterCtx Context, CcmpOp CmpOp)
- {
- AOpCodeCcmp Op = (AOpCodeCcmp)Context.CurrOp;
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- Context.EmitCondBranch(LblTrue, Op.Cond);
-
- Context.EmitLdc_I4((Op.NZCV >> 0) & 1);
-
- Context.EmitStflg((int)APState.VBit);
-
- Context.EmitLdc_I4((Op.NZCV >> 1) & 1);
-
- Context.EmitStflg((int)APState.CBit);
-
- Context.EmitLdc_I4((Op.NZCV >> 2) & 1);
-
- Context.EmitStflg((int)APState.ZBit);
-
- Context.EmitLdc_I4((Op.NZCV >> 3) & 1);
-
- Context.EmitStflg((int)APState.NBit);
-
- Context.Emit(OpCodes.Br_S, LblEnd);
-
- Context.MarkLabel(LblTrue);
-
- EmitDataLoadOpers(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/Instruction/AInstEmitCsel.cs b/ChocolArm64/Instruction/AInstEmitCsel.cs
deleted file mode 100644
index 21876752..00000000
--- a/ChocolArm64/Instruction/AInstEmitCsel.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- private enum CselOperation
- {
- None,
- Increment,
- Invert,
- Negate
- }
-
- public static void Csel(AILEmitterCtx Context) => EmitCsel(Context, CselOperation.None);
- public static void Csinc(AILEmitterCtx Context) => EmitCsel(Context, CselOperation.Increment);
- public static void Csinv(AILEmitterCtx Context) => EmitCsel(Context, CselOperation.Invert);
- public static void Csneg(AILEmitterCtx Context) => EmitCsel(Context, CselOperation.Negate);
-
- private static void EmitCsel(AILEmitterCtx Context, CselOperation CselOp)
- {
- AOpCodeCsel Op = (AOpCodeCsel)Context.CurrOp;
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- 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/Instruction/AInstEmitException.cs b/ChocolArm64/Instruction/AInstEmitException.cs
deleted file mode 100644
index 73d20967..00000000
--- a/ChocolArm64/Instruction/AInstEmitException.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Brk(AILEmitterCtx Context)
- {
- EmitExceptionCall(Context, nameof(AThreadState.OnBreak));
- }
-
- public static void Svc(AILEmitterCtx Context)
- {
- EmitExceptionCall(Context, nameof(AThreadState.OnSvcCall));
- }
-
- private static void EmitExceptionCall(AILEmitterCtx Context, string MthdName)
- {
- AOpCodeException Op = (AOpCodeException)Context.CurrOp;
-
- Context.EmitStoreState();
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- Context.EmitLdc_I8(Op.Position);
- Context.EmitLdc_I4(Op.Id);
-
- Context.EmitPrivateCall(typeof(AThreadState), 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(ATranslatedSub.StateArgIdx);
-
- Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Running));
-
- AILLabel LblEnd = new AILLabel();
-
- Context.Emit(OpCodes.Brtrue_S, LblEnd);
-
- Context.EmitLdc_I8(0);
-
- Context.Emit(OpCodes.Ret);
-
- Context.MarkLabel(LblEnd);
-
- if (Context.CurrBlock.Next != null)
- {
- Context.EmitLoadState(Context.CurrBlock.Next);
- }
- else
- {
- Context.EmitLdc_I8(Op.Position + 4);
-
- Context.Emit(OpCodes.Ret);
- }
- }
-
- public static void Und(AILEmitterCtx Context)
- {
- AOpCode Op = Context.CurrOp;
-
- Context.EmitStoreState();
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- Context.EmitLdc_I8(Op.Position);
- Context.EmitLdc_I4(Op.RawOpCode);
-
- Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.OnUndefined));
-
- if (Context.CurrBlock.Next != null)
- {
- Context.EmitLoadState(Context.CurrBlock.Next);
- }
- else
- {
- Context.EmitLdc_I8(Op.Position + 4);
-
- Context.Emit(OpCodes.Ret);
- }
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitFlow.cs b/ChocolArm64/Instruction/AInstEmitFlow.cs
deleted file mode 100644
index 91262834..00000000
--- a/ChocolArm64/Instruction/AInstEmitFlow.cs
+++ /dev/null
@@ -1,189 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void B(AILEmitterCtx Context)
- {
- AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp;
-
- if (Context.CurrBlock.Branch != null)
- {
- Context.Emit(OpCodes.Br, Context.GetLabel(Op.Imm));
- }
- else
- {
- Context.EmitStoreState();
- Context.EmitLdc_I8(Op.Imm);
-
- Context.Emit(OpCodes.Ret);
- }
- }
-
- public static void B_Cond(AILEmitterCtx Context)
- {
- AOpCodeBImmCond Op = (AOpCodeBImmCond)Context.CurrOp;
-
- EmitBranch(Context, Op.Cond);
- }
-
- public static void Bl(AILEmitterCtx Context)
- {
- AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp;
-
- Context.EmitLdc_I(Op.Position + 4);
- Context.EmitStint(AThreadState.LRIndex);
- Context.EmitStoreState();
-
- if (Context.TryOptEmitSubroutineCall())
- {
- //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.
- Context.Emit(OpCodes.Dup);
-
- Context.EmitLdc_I8(Op.Position + 4);
-
- AILLabel LblContinue = new AILLabel();
-
- Context.Emit(OpCodes.Beq_S, LblContinue);
- Context.Emit(OpCodes.Ret);
-
- Context.MarkLabel(LblContinue);
-
- Context.Emit(OpCodes.Pop);
-
- Context.EmitLoadState(Context.CurrBlock.Next);
- }
- else
- {
- Context.EmitLdc_I8(Op.Imm);
-
- Context.Emit(OpCodes.Ret);
- }
- }
-
- public static void Blr(AILEmitterCtx Context)
- {
- AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;
-
- Context.EmitLdc_I(Op.Position + 4);
- Context.EmitStint(AThreadState.LRIndex);
- Context.EmitStoreState();
- Context.EmitLdintzr(Op.Rn);
-
- Context.Emit(OpCodes.Ret);
- }
-
- public static void Br(AILEmitterCtx Context)
- {
- AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;
-
- Context.EmitStoreState();
- Context.EmitLdintzr(Op.Rn);
-
- Context.Emit(OpCodes.Ret);
- }
-
- public static void Cbnz(AILEmitterCtx Context) => EmitCb(Context, OpCodes.Bne_Un);
- public static void Cbz(AILEmitterCtx Context) => EmitCb(Context, OpCodes.Beq);
-
- private static void EmitCb(AILEmitterCtx Context, OpCode ILOp)
- {
- AOpCodeBImmCmp Op = (AOpCodeBImmCmp)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rt);
- Context.EmitLdc_I(0);
-
- EmitBranch(Context, ILOp);
- }
-
- public static void Ret(AILEmitterCtx Context)
- {
- Context.EmitStoreState();
- Context.EmitLdint(AThreadState.LRIndex);
-
- Context.Emit(OpCodes.Ret);
- }
-
- public static void Tbnz(AILEmitterCtx Context) => EmitTb(Context, OpCodes.Bne_Un);
- public static void Tbz(AILEmitterCtx Context) => EmitTb(Context, OpCodes.Beq);
-
- private static void EmitTb(AILEmitterCtx Context, OpCode ILOp)
- {
- AOpCodeBImmTest Op = (AOpCodeBImmTest)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(AILEmitterCtx Context, ACond Cond)
- {
- AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp;
-
- if (Context.CurrBlock.Next != null &&
- Context.CurrBlock.Branch != null)
- {
- Context.EmitCondBranch(Context.GetLabel(Op.Imm), Cond);
- }
- else
- {
- Context.EmitStoreState();
-
- AILLabel LblTaken = new AILLabel();
-
- 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(AILEmitterCtx Context, OpCode ILOp)
- {
- AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp;
-
- if (Context.CurrBlock.Next != null &&
- Context.CurrBlock.Branch != null)
- {
- Context.Emit(ILOp, Context.GetLabel(Op.Imm));
- }
- else
- {
- Context.EmitStoreState();
-
- AILLabel LblTaken = new AILLabel();
-
- 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/Instruction/AInstEmitHash.cs b/ChocolArm64/Instruction/AInstEmitHash.cs
deleted file mode 100644
index 69bdbc48..00000000
--- a/ChocolArm64/Instruction/AInstEmitHash.cs
+++ /dev/null
@@ -1,115 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics.X86;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Crc32b(AILEmitterCtx Context)
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32b));
- }
-
- public static void Crc32h(AILEmitterCtx Context)
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32h));
- }
-
- public static void Crc32w(AILEmitterCtx Context)
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32w));
- }
-
- public static void Crc32x(AILEmitterCtx Context)
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32x));
- }
-
- public static void Crc32cb(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse42)
- {
- EmitSse42Crc32(Context, typeof(uint), typeof(byte));
- }
- else
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32cb));
- }
- }
-
- public static void Crc32ch(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse42)
- {
- EmitSse42Crc32(Context, typeof(uint), typeof(ushort));
- }
- else
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32ch));
- }
- }
-
- public static void Crc32cw(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse42)
- {
- EmitSse42Crc32(Context, typeof(uint), typeof(uint));
- }
- else
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32cw));
- }
- }
-
- public static void Crc32cx(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse42)
- {
- EmitSse42Crc32(Context, typeof(ulong), typeof(ulong));
- }
- else
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32cx));
- }
- }
-
- private static void EmitSse42Crc32(AILEmitterCtx Context, Type TCrc, Type TData)
- {
- AOpCodeAluRs Op = (AOpCodeAluRs)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(AILEmitterCtx Context, string Name)
- {
- AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- if (Op.RegisterSize != ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U4);
- }
-
- Context.EmitLdintzr(Op.Rm);
-
- ASoftFallback.EmitCall(Context, Name);
-
- if (Op.RegisterSize != ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- Context.EmitStintzr(Op.Rd);
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitMemory.cs b/ChocolArm64/Instruction/AInstEmitMemory.cs
deleted file mode 100644
index 67653ed0..00000000
--- a/ChocolArm64/Instruction/AInstEmitMemory.cs
+++ /dev/null
@@ -1,252 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-using static ChocolArm64.Instruction.AInstEmitMemoryHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Adr(AILEmitterCtx Context)
- {
- AOpCodeAdr Op = (AOpCodeAdr)Context.CurrOp;
-
- Context.EmitLdc_I(Op.Position + Op.Imm);
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Adrp(AILEmitterCtx Context)
- {
- AOpCodeAdr Op = (AOpCodeAdr)Context.CurrOp;
-
- Context.EmitLdc_I((Op.Position & ~0xfffL) + (Op.Imm << 12));
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Ldr(AILEmitterCtx Context) => EmitLdr(Context, false);
- public static void Ldrs(AILEmitterCtx Context) => EmitLdr(Context, true);
-
- private static void EmitLdr(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeMem Op = (AOpCodeMem)Context.CurrOp;
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
-
- 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 IAOpCodeSimd)
- {
- Context.EmitStvec(Op.Rt);
- }
- else
- {
- Context.EmitStintzr(Op.Rt);
- }
-
- EmitWBackIfNeeded(Context);
- }
-
- public static void LdrLit(AILEmitterCtx Context)
- {
- IAOpCodeLit Op = (IAOpCodeLit)Context.CurrOp;
-
- if (Op.Prefetch)
- {
- return;
- }
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdc_I8(Op.Imm);
-
- if (Op.Signed)
- {
- EmitReadSx64Call(Context, Op.Size);
- }
- else
- {
- EmitReadZxCall(Context, Op.Size);
- }
-
- if (Op is IAOpCodeSimd)
- {
- Context.EmitStvec(Op.Rt);
- }
- else
- {
- Context.EmitStint(Op.Rt);
- }
- }
-
- public static void Ldp(AILEmitterCtx Context)
- {
- AOpCodeMemPair Op = (AOpCodeMemPair)Context.CurrOp;
-
- void EmitReadAndStore(int Rt)
- {
- if (Op.Extend64)
- {
- EmitReadSx64Call(Context, Op.Size);
- }
- else
- {
- EmitReadZxCall(Context, Op.Size);
- }
-
- if (Op is IAOpCodeSimd)
- {
- Context.EmitStvec(Rt);
- }
- else
- {
- Context.EmitStintzr(Rt);
- }
- }
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
-
- EmitLoadAddress(Context);
-
- EmitReadAndStore(Op.Rt);
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdtmp();
- Context.EmitLdc_I8(1 << Op.Size);
-
- Context.Emit(OpCodes.Add);
-
- EmitReadAndStore(Op.Rt2);
-
- EmitWBackIfNeeded(Context);
- }
-
- public static void Str(AILEmitterCtx Context)
- {
- AOpCodeMem Op = (AOpCodeMem)Context.CurrOp;
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
-
- EmitLoadAddress(Context);
-
- if (Op is IAOpCodeSimd)
- {
- Context.EmitLdvec(Op.Rt);
- }
- else
- {
- Context.EmitLdintzr(Op.Rt);
- }
-
- EmitWriteCall(Context, Op.Size);
-
- EmitWBackIfNeeded(Context);
- }
-
- public static void Stp(AILEmitterCtx Context)
- {
- AOpCodeMemPair Op = (AOpCodeMemPair)Context.CurrOp;
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
-
- EmitLoadAddress(Context);
-
- if (Op is IAOpCodeSimd)
- {
- Context.EmitLdvec(Op.Rt);
- }
- else
- {
- Context.EmitLdintzr(Op.Rt);
- }
-
- EmitWriteCall(Context, Op.Size);
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdtmp();
- Context.EmitLdc_I8(1 << Op.Size);
-
- Context.Emit(OpCodes.Add);
-
- if (Op is IAOpCodeSimd)
- {
- Context.EmitLdvec(Op.Rt2);
- }
- else
- {
- Context.EmitLdintzr(Op.Rt2);
- }
-
- EmitWriteCall(Context, Op.Size);
-
- EmitWBackIfNeeded(Context);
- }
-
- private static void EmitLoadAddress(AILEmitterCtx Context)
- {
- switch (Context.CurrOp)
- {
- case AOpCodeMemImm Op:
- Context.EmitLdint(Op.Rn);
-
- if (!Op.PostIdx)
- {
- //Pre-indexing.
- Context.EmitLdc_I(Op.Imm);
-
- Context.Emit(OpCodes.Add);
- }
- break;
-
- case AOpCodeMemReg 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(AILEmitterCtx 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 AOpCodeMemImm 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/Instruction/AInstEmitMemoryEx.cs b/ChocolArm64/Instruction/AInstEmitMemoryEx.cs
deleted file mode 100644
index cf19b4a1..00000000
--- a/ChocolArm64/Instruction/AInstEmitMemoryEx.cs
+++ /dev/null
@@ -1,192 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Memory;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Threading;
-
-using static ChocolArm64.Instruction.AInstEmitMemoryHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- [Flags]
- private enum AccessType
- {
- None = 0,
- Ordered = 1,
- Exclusive = 2,
- OrderedEx = Ordered | Exclusive
- }
-
- public static void Clrex(AILEmitterCtx Context)
- {
- EmitMemoryCall(Context, nameof(AMemory.ClearExclusive));
- }
-
- public static void Dmb(AILEmitterCtx Context) => EmitBarrier(Context);
- public static void Dsb(AILEmitterCtx Context) => EmitBarrier(Context);
-
- public static void Ldar(AILEmitterCtx Context) => EmitLdr(Context, AccessType.Ordered);
- public static void Ldaxr(AILEmitterCtx Context) => EmitLdr(Context, AccessType.OrderedEx);
- public static void Ldxr(AILEmitterCtx Context) => EmitLdr(Context, AccessType.Exclusive);
- public static void Ldxp(AILEmitterCtx Context) => EmitLdp(Context, AccessType.Exclusive);
- public static void Ldaxp(AILEmitterCtx Context) => EmitLdp(Context, AccessType.OrderedEx);
-
- private static void EmitLdr(AILEmitterCtx Context, AccessType AccType)
- {
- EmitLoad(Context, AccType, false);
- }
-
- private static void EmitLdp(AILEmitterCtx Context, AccessType AccType)
- {
- EmitLoad(Context, AccType, true);
- }
-
- private static void EmitLoad(AILEmitterCtx Context, AccessType AccType, bool Pair)
- {
- AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp;
-
- bool Ordered = (AccType & AccessType.Ordered) != 0;
- bool Exclusive = (AccType & AccessType.Exclusive) != 0;
-
- if (Ordered)
- {
- EmitBarrier(Context);
- }
-
- if (Exclusive)
- {
- EmitMemoryCall(Context, nameof(AMemory.SetExclusive), Op.Rn);
- }
-
- Context.EmitLdint(Op.Rn);
- Context.EmitSttmp();
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdtmp();
-
- EmitReadZxCall(Context, Op.Size);
-
- Context.EmitStintzr(Op.Rt);
-
- if (Pair)
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdtmp();
- Context.EmitLdc_I8(1 << Op.Size);
-
- Context.Emit(OpCodes.Add);
-
- EmitReadZxCall(Context, Op.Size);
-
- Context.EmitStintzr(Op.Rt2);
- }
- }
-
- public static void Pfrm(AILEmitterCtx Context)
- {
- //Memory Prefetch, execute as no-op.
- }
-
- public static void Stlr(AILEmitterCtx Context) => EmitStr(Context, AccessType.Ordered);
- public static void Stlxr(AILEmitterCtx Context) => EmitStr(Context, AccessType.OrderedEx);
- public static void Stxr(AILEmitterCtx Context) => EmitStr(Context, AccessType.Exclusive);
- public static void Stxp(AILEmitterCtx Context) => EmitStp(Context, AccessType.Exclusive);
- public static void Stlxp(AILEmitterCtx Context) => EmitStp(Context, AccessType.OrderedEx);
-
- private static void EmitStr(AILEmitterCtx Context, AccessType AccType)
- {
- EmitStore(Context, AccType, false);
- }
-
- private static void EmitStp(AILEmitterCtx Context, AccessType AccType)
- {
- EmitStore(Context, AccType, true);
- }
-
- private static void EmitStore(AILEmitterCtx Context, AccessType AccType, bool Pair)
- {
- AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp;
-
- bool Ordered = (AccType & AccessType.Ordered) != 0;
- bool Exclusive = (AccType & AccessType.Exclusive) != 0;
-
- if (Ordered)
- {
- EmitBarrier(Context);
- }
-
- AILLabel LblEx = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- if (Exclusive)
- {
- EmitMemoryCall(Context, nameof(AMemory.TestExclusive), Op.Rn);
-
- Context.Emit(OpCodes.Brtrue_S, LblEx);
-
- Context.EmitLdc_I8(1);
- Context.EmitStintzr(Op.Rs);
-
- Context.Emit(OpCodes.Br_S, LblEnd);
- }
-
- Context.MarkLabel(LblEx);
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdint(Op.Rn);
- Context.EmitLdintzr(Op.Rt);
-
- EmitWriteCall(Context, Op.Size);
-
- if (Pair)
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdint(Op.Rn);
- Context.EmitLdc_I8(1 << Op.Size);
-
- Context.Emit(OpCodes.Add);
-
- Context.EmitLdintzr(Op.Rt2);
-
- EmitWriteCall(Context, Op.Size);
- }
-
- if (Exclusive)
- {
- Context.EmitLdc_I8(0);
- Context.EmitStintzr(Op.Rs);
-
- EmitMemoryCall(Context, nameof(AMemory.ClearExclusiveForStore));
- }
-
- Context.MarkLabel(LblEnd);
- }
-
- private static void EmitMemoryCall(AILEmitterCtx Context, string Name, int Rn = -1)
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Core));
-
- if (Rn != -1)
- {
- Context.EmitLdint(Rn);
- }
-
- Context.EmitCall(typeof(AMemory), Name);
- }
-
- private static void EmitBarrier(AILEmitterCtx 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/Instruction/AInstEmitMemoryHelper.cs b/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs
deleted file mode 100644
index b10551fe..00000000
--- a/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Memory;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static class AInstEmitMemoryHelper
- {
- private enum Extension
- {
- Zx,
- Sx32,
- Sx64
- }
-
- public static void EmitReadZxCall(AILEmitterCtx Context, int Size)
- {
- EmitReadCall(Context, Extension.Zx, Size);
- }
-
- public static void EmitReadSx32Call(AILEmitterCtx Context, int Size)
- {
- EmitReadCall(Context, Extension.Sx32, Size);
- }
-
- public static void EmitReadSx64Call(AILEmitterCtx Context, int Size)
- {
- EmitReadCall(Context, Extension.Sx64, Size);
- }
-
- private static void EmitReadCall(AILEmitterCtx Context, Extension Ext, int Size)
- {
- bool IsSimd = GetIsSimd(Context);
-
- string Name = null;
-
- if (Size < 0 || Size > (IsSimd ? 4 : 3))
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- if (IsSimd)
- {
- switch (Size)
- {
- case 0: Name = nameof(AMemory.ReadVector8); break;
- case 1: Name = nameof(AMemory.ReadVector16); break;
- case 2: Name = nameof(AMemory.ReadVector32); break;
- case 3: Name = nameof(AMemory.ReadVector64); break;
- case 4: Name = nameof(AMemory.ReadVector128); break;
- }
- }
- else
- {
- switch (Size)
- {
- case 0: Name = nameof(AMemory.ReadByte); break;
- case 1: Name = nameof(AMemory.ReadUInt16); break;
- case 2: Name = nameof(AMemory.ReadUInt32); break;
- case 3: Name = nameof(AMemory.ReadUInt64); break;
- }
- }
-
- Context.EmitCall(typeof(AMemory), Name);
-
- 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(AILEmitterCtx Context, int Size)
- {
- bool IsSimd = GetIsSimd(Context);
-
- string Name = null;
-
- if (Size < 0 || Size > (IsSimd ? 4 : 3))
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- if (Size < 3 && !IsSimd)
- {
- Context.Emit(OpCodes.Conv_I4);
- }
-
- if (IsSimd)
- {
- switch (Size)
- {
- case 0: Name = nameof(AMemory.WriteVector8); break;
- case 1: Name = nameof(AMemory.WriteVector16); break;
- case 2: Name = nameof(AMemory.WriteVector32); break;
- case 3: Name = nameof(AMemory.WriteVector64); break;
- case 4: Name = nameof(AMemory.WriteVector128); break;
- }
- }
- else
- {
- switch (Size)
- {
- case 0: Name = nameof(AMemory.WriteByte); break;
- case 1: Name = nameof(AMemory.WriteUInt16); break;
- case 2: Name = nameof(AMemory.WriteUInt32); break;
- case 3: Name = nameof(AMemory.WriteUInt64); break;
- }
- }
-
- Context.EmitCall(typeof(AMemory), Name);
- }
-
- private static bool GetIsSimd(AILEmitterCtx Context)
- {
- return Context.CurrOp is IAOpCodeSimd &&
- !(Context.CurrOp is AOpCodeSimdMemMs ||
- Context.CurrOp is AOpCodeSimdMemSs);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitMove.cs b/ChocolArm64/Instruction/AInstEmitMove.cs
deleted file mode 100644
index 719b53d5..00000000
--- a/ChocolArm64/Instruction/AInstEmitMove.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Movk(AILEmitterCtx Context)
- {
- AOpCodeMov Op = (AOpCodeMov)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(AILEmitterCtx Context)
- {
- AOpCodeMov Op = (AOpCodeMov)Context.CurrOp;
-
- Context.EmitLdc_I(~Op.Imm);
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Movz(AILEmitterCtx Context)
- {
- AOpCodeMov Op = (AOpCodeMov)Context.CurrOp;
-
- Context.EmitLdc_I(Op.Imm);
- Context.EmitStintzr(Op.Rd);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitMul.cs b/ChocolArm64/Instruction/AInstEmitMul.cs
deleted file mode 100644
index 3713c81f..00000000
--- a/ChocolArm64/Instruction/AInstEmitMul.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Madd(AILEmitterCtx Context) => EmitMul(Context, OpCodes.Add);
- public static void Msub(AILEmitterCtx Context) => EmitMul(Context, OpCodes.Sub);
-
- private static void EmitMul(AILEmitterCtx Context, OpCode ILOp)
- {
- AOpCodeMul Op = (AOpCodeMul)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(AILEmitterCtx Context) => EmitMull(Context, OpCodes.Add, true);
- public static void Smsubl(AILEmitterCtx Context) => EmitMull(Context, OpCodes.Sub, true);
- public static void Umaddl(AILEmitterCtx Context) => EmitMull(Context, OpCodes.Add, false);
- public static void Umsubl(AILEmitterCtx Context) => EmitMull(Context, OpCodes.Sub, false);
-
- private static void EmitMull(AILEmitterCtx Context, OpCode AddSubOp, bool Signed)
- {
- AOpCodeMul Op = (AOpCodeMul)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(AILEmitterCtx Context)
- {
- AOpCodeMul Op = (AOpCodeMul)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
- Context.EmitLdintzr(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SMulHi128));
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Umulh(AILEmitterCtx Context)
- {
- AOpCodeMul Op = (AOpCodeMul)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
- Context.EmitLdintzr(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.UMulHi128));
-
- Context.EmitStintzr(Op.Rd);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
deleted file mode 100644
index 1bd48364..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
+++ /dev/null
@@ -1,2387 +0,0 @@
-// https://github.com/intel/ARM_NEON_2_x86_SSE/blob/master/NEON_2_SSE.h
-
-using ChocolArm64.Decoder;
-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.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Abs_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpSx(Context, () => EmitAbs(Context));
- }
-
- public static void Abs_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpSx(Context, () => EmitAbs(Context));
- }
-
- public static void Add_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
- }
-
- public static void Add_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.Add));
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
- }
- }
-
- public static void Addhn_V(AILEmitterCtx Context)
- {
- EmitHighNarrow(Context, () => Context.Emit(OpCodes.Add), Round: false);
- }
-
- public static void Addp_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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(AILEmitterCtx Context)
- {
- EmitVectorPairwiseOpZx(Context, () => Context.Emit(OpCodes.Add));
- }
-
- public static void Addv_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
-
- for (int Index = 1; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
-
- Context.Emit(OpCodes.Add);
- }
-
- EmitScalarSet(Context, Op.Rd, Op.Size);
- }
-
- public static void Cls_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountLeadingSigns));
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Clz_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountLeadingZeros));
- }
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Cnt_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Elems = Op.RegisterSize == ARegisterSize.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
- {
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountSetBits8));
- }
-
- EmitVectorInsert(Context, Op.Rd, Index, 0);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Fabd_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
-
- EmitUnaryMathCall(Context, nameof(Math.Abs));
- });
- }
-
- public static void Fabs_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitUnaryMathCall(Context, nameof(Math.Abs));
- });
- }
-
- public static void Fabs_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitUnaryMathCall(Context, nameof(Math.Abs));
- });
- }
-
- public static void Fadd_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.AddScalar));
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPAdd));
- });
- }
- }
-
- public static void Fadd_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Add));
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPAdd));
- });
- }
- }
-
- public static void Faddp_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
- EmitVectorExtractF(Context, Op.Rn, 1, SizeF);
-
- Context.Emit(OpCodes.Add);
-
- EmitScalarSetF(Context, Op.Rd, SizeF);
- }
-
- public static void Faddp_V(AILEmitterCtx Context)
- {
- EmitVectorPairwiseOpF(Context, () => Context.Emit(OpCodes.Add));
- }
-
- public static void Fdiv_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.DivideScalar));
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPDiv));
- });
- }
- }
-
- public static void Fdiv_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Divide));
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPDiv));
- });
- }
- }
-
- public static void Fmadd_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (Op.Size == 0)
- {
- Type[] TypesMulAdd = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
-
- Context.EmitLdvec(Op.Ra);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), TypesMulAdd));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AddScalar), TypesMulAdd));
-
- Context.EmitStvec(Op.Rd);
-
- EmitVectorZero32_128(Context, Op.Rd);
- }
- else /* if (Op.Size == 1) */
- {
- Type[] TypesMulAdd = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
-
- EmitLdvecWithCastToDouble(Context, Op.Ra);
- EmitLdvecWithCastToDouble(Context, Op.Rn);
- EmitLdvecWithCastToDouble(Context, Op.Rm);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), TypesMulAdd));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AddScalar), TypesMulAdd));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
-
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitScalarTernaryRaOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulAdd));
- });
- }
- }
-
- public static void Fmax_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.MaxScalar));
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMax));
- });
- }
- }
-
- public static void Fmax_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Max));
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMax));
- });
- }
- }
-
- public static void Fmaxnm_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMaxNum));
- });
- }
-
- public static void Fmaxnm_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMaxNum));
- });
- }
-
- public static void Fmaxp_V(AILEmitterCtx Context)
- {
- EmitVectorPairwiseOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMax));
- });
- }
-
- public static void Fmin_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.MinScalar));
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMin));
- });
- }
- }
-
- public static void Fmin_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Min));
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMin));
- });
- }
- }
-
- public static void Fminnm_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMinNum));
- });
- }
-
- public static void Fminnm_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMinNum));
- });
- }
-
- public static void Fminp_V(AILEmitterCtx Context)
- {
- EmitVectorPairwiseOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMin));
- });
- }
-
- public static void Fmla_Se(AILEmitterCtx Context)
- {
- EmitScalarTernaryOpByElemF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Fmla_V(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Fmla_Ve(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpByElemF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Fmls_Se(AILEmitterCtx Context)
- {
- EmitScalarTernaryOpByElemF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
-
- public static void Fmls_V(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
-
- public static void Fmls_Ve(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpByElemF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
-
- public static void Fmsub_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (Op.Size == 0)
- {
- Type[] TypesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
-
- Context.EmitLdvec(Op.Ra);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), TypesMulSub));
-
- Context.EmitStvec(Op.Rd);
-
- EmitVectorZero32_128(Context, Op.Rd);
- }
- else /* if (Op.Size == 1) */
- {
- Type[] TypesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
-
- EmitLdvecWithCastToDouble(Context, Op.Ra);
- EmitLdvecWithCastToDouble(Context, Op.Rn);
- EmitLdvecWithCastToDouble(Context, Op.Rm);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), TypesMulSub));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
-
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitScalarTernaryRaOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulSub));
- });
- }
- }
-
- public static void Fmul_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.MultiplyScalar));
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMul));
- });
- }
- }
-
- public static void Fmul_Se(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpByElemF(Context, () => Context.Emit(OpCodes.Mul));
- }
-
- public static void Fmul_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Multiply));
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMul));
- });
- }
- }
-
- public static void Fmul_Ve(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpByElemF(Context, () => Context.Emit(OpCodes.Mul));
- }
-
- public static void Fmulx_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulX));
- });
- }
-
- public static void Fmulx_Se(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpByElemF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulX));
- });
- }
-
- public static void Fmulx_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulX));
- });
- }
-
- public static void Fmulx_Ve(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpByElemF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulX));
- });
- }
-
- public static void Fneg_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () => Context.Emit(OpCodes.Neg));
- }
-
- public static void Fneg_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () => Context.Emit(OpCodes.Neg));
- }
-
- public static void Fnmadd_S(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)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(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)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(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Neg);
- });
- }
-
- public static void Frecpe_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitUnarySoftFloatCall(Context, nameof(ASoftFloat.RecipEstimate));
- });
- }
-
- public static void Frecpe_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitUnarySoftFloatCall(Context, nameof(ASoftFloat.RecipEstimate));
- });
- }
-
- public static void Frecps_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- if (SizeF == 0)
- {
- Type[] TypesSsv = new Type[] { typeof(float) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
-
- Context.EmitLdc_R4(2f);
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), TypesSsv));
-
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), TypesMulSub));
-
- Context.EmitStvec(Op.Rd);
-
- EmitVectorZero32_128(Context, Op.Rd);
- }
- else /* if (SizeF == 1) */
- {
- Type[] TypesSsv = new Type[] { typeof(double) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
-
- Context.EmitLdc_R8(2d);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), TypesSsv));
-
- EmitLdvecWithCastToDouble(Context, Op.Rn);
- EmitLdvecWithCastToDouble(Context, Op.Rm);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), TypesMulSub));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
-
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRecipStepFused));
- });
- }
- }
-
- public static void Frecps_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- if (SizeF == 0)
- {
- Type[] TypesSav = new Type[] { typeof(float) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
-
- Context.EmitLdc_R4(2f);
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), TypesSav));
-
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), TypesMulSub));
-
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else /* if (SizeF == 1) */
- {
- Type[] TypesSav = new Type[] { typeof(double) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
-
- Context.EmitLdc_R8(2d);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), TypesSav));
-
- EmitLdvecWithCastToDouble(Context, Op.Rn);
- EmitLdvecWithCastToDouble(Context, Op.Rm);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), TypesMulSub));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesMulSub));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRecipStepFused));
- });
- }
- }
-
- public static void Frecpx_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRecpX));
- });
- }
-
- public static void Frinta_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
- EmitRoundMathCall(Context, MidpointRounding.AwayFromZero);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Frinta_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitRoundMathCall(Context, MidpointRounding.AwayFromZero);
- });
- }
-
- public static void Frinti_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitScalarUnaryOpF(Context, () =>
- {
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- if (Op.Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.RoundF));
- }
- else if (Op.Size == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.Round));
- }
- else
- {
- throw new InvalidOperationException();
- }
- });
- }
-
- public static void Frinti_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- EmitVectorUnaryOpF(Context, () =>
- {
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- if (SizeF == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.RoundF));
- }
- else if (SizeF == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.Round));
- }
- else
- {
- throw new InvalidOperationException();
- }
- });
- }
-
- public static void Frintm_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitUnaryMathCall(Context, nameof(Math.Floor));
- });
- }
-
- public static void Frintm_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitUnaryMathCall(Context, nameof(Math.Floor));
- });
- }
-
- public static void Frintn_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
- EmitRoundMathCall(Context, MidpointRounding.ToEven);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Frintn_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitRoundMathCall(Context, MidpointRounding.ToEven);
- });
- }
-
- public static void Frintp_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitUnaryMathCall(Context, nameof(Math.Ceiling));
- });
- }
-
- public static void Frintp_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitUnaryMathCall(Context, nameof(Math.Ceiling));
- });
- }
-
- public static void Frintx_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitScalarUnaryOpF(Context, () =>
- {
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- if (Op.Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.RoundF));
- }
- else if (Op.Size == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.Round));
- }
- else
- {
- throw new InvalidOperationException();
- }
- });
- }
-
- public static void Frintx_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorUnaryOpF(Context, () =>
- {
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- if (Op.Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.RoundF));
- }
- else if (Op.Size == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.Round));
- }
- else
- {
- throw new InvalidOperationException();
- }
- });
- }
-
- public static void Frsqrte_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitUnarySoftFloatCall(Context, nameof(ASoftFloat.InvSqrtEstimate));
- });
- }
-
- public static void Frsqrte_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitUnarySoftFloatCall(Context, nameof(ASoftFloat.InvSqrtEstimate));
- });
- }
-
- public static void Frsqrts_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- if (SizeF == 0)
- {
- Type[] TypesSsv = new Type[] { typeof(float) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
-
- Context.EmitLdc_R4(0.5f);
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), TypesSsv));
-
- Context.EmitLdc_R4(3f);
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), TypesSsv));
-
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), TypesMulSub));
-
- Context.EmitStvec(Op.Rd);
-
- EmitVectorZero32_128(Context, Op.Rd);
- }
- else /* if (SizeF == 1) */
- {
- Type[] TypesSsv = new Type[] { typeof(double) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
-
- Context.EmitLdc_R8(0.5d);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), TypesSsv));
-
- Context.EmitLdc_R8(3d);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), TypesSsv));
-
- EmitLdvecWithCastToDouble(Context, Op.Rn);
- EmitLdvecWithCastToDouble(Context, 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));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
-
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRSqrtStepFused));
- });
- }
- }
-
- public static void Frsqrts_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- if (SizeF == 0)
- {
- Type[] TypesSav = new Type[] { typeof(float) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
-
- Context.EmitLdc_R4(0.5f);
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), TypesSav));
-
- Context.EmitLdc_R4(3f);
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), TypesSav));
-
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), TypesMulSub));
-
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else /* if (SizeF == 1) */
- {
- Type[] TypesSav = new Type[] { typeof(double) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
-
- Context.EmitLdc_R8(0.5d);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), TypesSav));
-
- Context.EmitLdc_R8(3d);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), TypesSav));
-
- EmitLdvecWithCastToDouble(Context, Op.Rn);
- EmitLdvecWithCastToDouble(Context, 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));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRSqrtStepFused));
- });
- }
- }
-
- public static void Fsqrt_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.SqrtScalar));
- }
- else
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSqrt));
- });
- }
- }
-
- public static void Fsqrt_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Sqrt));
- }
- else
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSqrt));
- });
- }
- }
-
- public static void Fsub_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.SubtractScalar));
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSub));
- });
- }
- }
-
- public static void Fsub_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Subtract));
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSub));
- });
- }
- }
-
- public static void Mla_V(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Mla_Ve(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpByElemZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Mls_V(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
-
- public static void Mls_Ve(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpByElemZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
-
- public static void Mul_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Mul));
- }
-
- public static void Mul_Ve(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpByElemZx(Context, () => Context.Emit(OpCodes.Mul));
- }
-
- public static void Neg_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg));
- }
-
- public static void Neg_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg));
- }
-
- public static void Raddhn_V(AILEmitterCtx Context)
- {
- EmitHighNarrow(Context, () => Context.Emit(OpCodes.Add), Round: true);
- }
-
- public static void Rsubhn_V(AILEmitterCtx Context)
- {
- EmitHighNarrow(Context, () => Context.Emit(OpCodes.Sub), Round: true);
- }
-
- public static void Saba_V(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
-
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Sabal_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRnRmTernaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
-
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Sabd_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
- });
- }
-
- public static void Sabdl_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRnRmBinaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
- });
- }
-
- public static void Sadalp_V(AILEmitterCtx Context)
- {
- EmitAddLongPairwise(Context, Signed: true, Accumulate: true);
- }
-
- public static void Saddl_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse41)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)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) };
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NamesCvt[Op.Size], TypesCvt));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- 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));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Add));
- }
- }
-
- public static void Saddlp_V(AILEmitterCtx Context)
- {
- EmitAddLongPairwise(Context, Signed: true, Accumulate: false);
- }
-
- public static void Saddw_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Add));
- }
-
- public static void Shadd_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0)
- {
- Type[] TypesSra = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesAndXorAdd = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], VectorIntTypesPerSizeLog2[Op.Size] };
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- EmitLdvecWithSignedCast(Context, Op.Rm, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp2();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), TypesAndXorAdd));
-
- Context.EmitLdvectmp();
- Context.EmitLdvectmp2();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), TypesAndXorAdd));
-
- Context.EmitLdc_I4(1);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), TypesSra));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAndXorAdd));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.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(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.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();
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
- Context.EmitLdvectmp();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAddSub));
-
- Context.Emit(OpCodes.Dup);
-
- EmitLdvecWithSignedCast(Context, Op.Rm, Op.Size);
- 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));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.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(AILEmitterCtx Context)
- {
- 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(AILEmitterCtx 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 Smin_V(AILEmitterCtx Context)
- {
- 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(AILEmitterCtx 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 Smlal_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.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 TypeMul = Op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
-
- string NameCvt = Op.Size == 0
- ? nameof(Sse41.ConvertToVector128Int16)
- : nameof(Sse41.ConvertToVector128Int32);
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithSignedCast(Context, Op.Rd, Op.Size + 1);
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- EmitLdvecWithSignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- Context.EmitCall(TypeMul.GetMethod(nameof(Sse2.MultiplyLow), TypesMulAdd));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesMulAdd));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmTernaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
- }
-
- public static void Smlsl_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.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 TypeMul = Op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
-
- string NameCvt = Op.Size == 0
- ? nameof(Sse41.ConvertToVector128Int16)
- : nameof(Sse41.ConvertToVector128Int32);
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithSignedCast(Context, Op.Rd, Op.Size + 1);
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- EmitLdvecWithSignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- Context.EmitCall(TypeMul.GetMethod(nameof(Sse2.MultiplyLow), TypesMulSub));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesMulSub));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmTernaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
- }
-
- public static void Smull_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul));
- }
-
- public static void Sqabs_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingUnaryOpSx(Context, () => EmitAbs(Context));
- }
-
- public static void Sqabs_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingUnaryOpSx(Context, () => EmitAbs(Context));
- }
-
- public static void Sqadd_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingBinaryOpSx(Context, SaturatingFlags.Add);
- }
-
- public static void Sqadd_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingBinaryOpSx(Context, SaturatingFlags.Add);
- }
-
- public static void Sqdmulh_S(AILEmitterCtx Context)
- {
- EmitSaturatingBinaryOp(Context, () => EmitDoublingMultiplyHighHalf(Context, Round: false), SaturatingFlags.ScalarSx);
- }
-
- public static void Sqdmulh_V(AILEmitterCtx Context)
- {
- EmitSaturatingBinaryOp(Context, () => EmitDoublingMultiplyHighHalf(Context, Round: false), SaturatingFlags.VectorSx);
- }
-
- public static void Sqneg_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg));
- }
-
- public static void Sqneg_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg));
- }
-
- public static void Sqrdmulh_S(AILEmitterCtx Context)
- {
- EmitSaturatingBinaryOp(Context, () => EmitDoublingMultiplyHighHalf(Context, Round: true), SaturatingFlags.ScalarSx);
- }
-
- public static void Sqrdmulh_V(AILEmitterCtx Context)
- {
- EmitSaturatingBinaryOp(Context, () => EmitDoublingMultiplyHighHalf(Context, Round: true), SaturatingFlags.VectorSx);
- }
-
- public static void Sqsub_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingBinaryOpSx(Context, SaturatingFlags.Sub);
- }
-
- public static void Sqsub_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingBinaryOpSx(Context, SaturatingFlags.Sub);
- }
-
- public static void Sqxtn_S(AILEmitterCtx Context)
- {
- EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.ScalarSxSx);
- }
-
- public static void Sqxtn_V(AILEmitterCtx Context)
- {
- EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.VectorSxSx);
- }
-
- public static void Sqxtun_S(AILEmitterCtx Context)
- {
- EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.ScalarSxZx);
- }
-
- public static void Sqxtun_V(AILEmitterCtx Context)
- {
- EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.VectorSxZx);
- }
-
- public static void Srhadd_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.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.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
- Context.EmitLdvectmp();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesSubAdd));
-
- EmitLdvecWithSignedCast(Context, Op.Rm, Op.Size);
- 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));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.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(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse41)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)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) };
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NamesCvt[Op.Size], TypesCvt));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- 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));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Sub));
- }
- }
-
- public static void Ssubw_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Sub));
- }
-
- public static void Sub_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
- }
-
- public static void Sub_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.Subtract));
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
- }
- }
-
- public static void Subhn_V(AILEmitterCtx Context)
- {
- EmitHighNarrow(Context, () => Context.Emit(OpCodes.Sub), Round: false);
- }
-
- public static void Suqadd_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingBinaryOpSx(Context, SaturatingFlags.Accumulate);
- }
-
- public static void Suqadd_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingBinaryOpSx(Context, SaturatingFlags.Accumulate);
- }
-
- public static void Uaba_V(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
-
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Uabal_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRnRmTernaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
-
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Uabd_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
- });
- }
-
- public static void Uabdl_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRnRmBinaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
- });
- }
-
- public static void Uadalp_V(AILEmitterCtx Context)
- {
- EmitAddLongPairwise(Context, Signed: false, Accumulate: true);
- }
-
- public static void Uaddl_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse41)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)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) };
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NamesCvt[Op.Size], TypesCvt));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- 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));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
- }
- }
-
- public static void Uaddlp_V(AILEmitterCtx Context)
- {
- EmitAddLongPairwise(Context, Signed: false, Accumulate: false);
- }
-
- public static void Uaddlv_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
-
- for (int Index = 1; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
-
- Context.Emit(OpCodes.Add);
- }
-
- EmitScalarSet(Context, Op.Rd, Op.Size + 1);
- }
-
- public static void Uaddw_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
- }
-
- public static void Uhadd_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0)
- {
- Type[] TypesSrl = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesAndXorAdd = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp2();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), TypesAndXorAdd));
-
- Context.EmitLdvectmp();
- Context.EmitLdvectmp2();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), TypesAndXorAdd));
-
- Context.EmitLdc_I4(1);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesSrl));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAndXorAdd));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.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(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size < 2)
- {
- Type[] TypesAvgSub = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
- Context.Emit(OpCodes.Dup);
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), TypesAvgSub));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesAvgSub));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.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(AILEmitterCtx Context)
- {
- 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(AILEmitterCtx 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 Umin_V(AILEmitterCtx Context)
- {
- 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(AILEmitterCtx 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 Umlal_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.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 TypeMul = Op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
-
- string NameCvt = Op.Size == 0
- ? nameof(Sse41.ConvertToVector128Int16)
- : nameof(Sse41.ConvertToVector128Int32);
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size + 1);
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- Context.EmitCall(TypeMul.GetMethod(nameof(Sse2.MultiplyLow), TypesMulAdd));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesMulAdd));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmTernaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
- }
-
- public static void Umlsl_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.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 TypeMul = Op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
-
- string NameCvt = Op.Size == 0
- ? nameof(Sse41.ConvertToVector128Int16)
- : nameof(Sse41.ConvertToVector128Int32);
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size + 1);
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- Context.EmitCall(TypeMul.GetMethod(nameof(Sse2.MultiplyLow), TypesMulSub));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesMulSub));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmTernaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
- }
-
- public static void Umull_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRnRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Mul));
- }
-
- public static void Uqadd_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingBinaryOpZx(Context, SaturatingFlags.Add);
- }
-
- public static void Uqadd_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingBinaryOpZx(Context, SaturatingFlags.Add);
- }
-
- public static void Uqsub_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingBinaryOpZx(Context, SaturatingFlags.Sub);
- }
-
- public static void Uqsub_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingBinaryOpZx(Context, SaturatingFlags.Sub);
- }
-
- public static void Uqxtn_S(AILEmitterCtx Context)
- {
- EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.ScalarZxZx);
- }
-
- public static void Uqxtn_V(AILEmitterCtx Context)
- {
- EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.VectorZxZx);
- }
-
- public static void Urhadd_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size < 2)
- {
- Type[] TypesAvg = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), TypesAvg));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.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(AILEmitterCtx Context)
- {
- EmitScalarSaturatingBinaryOpZx(Context, SaturatingFlags.Accumulate);
- }
-
- public static void Usqadd_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingBinaryOpZx(Context, SaturatingFlags.Accumulate);
- }
-
- public static void Usubl_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse41)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)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) };
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NamesCvt[Op.Size], TypesCvt));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- 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));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
- }
- }
-
- public static void Usubw_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
- }
-
- private static void EmitAbs(AILEmitterCtx Context)
- {
- AILLabel LblTrue = new AILLabel();
-
- 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(AILEmitterCtx Context, bool Signed, bool Accumulate)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitDoublingMultiplyHighHalf(AILEmitterCtx Context, bool Round)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int ESize = 8 << Op.Size;
-
- Context.Emit(OpCodes.Mul);
-
- if (!Round)
- {
- Context.EmitAsr(ESize - 1);
- }
- else
- {
- long RoundConst = 1L << (ESize - 1);
-
- AILLabel LblTrue = new AILLabel();
-
- 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(AILEmitterCtx Context, Action Emit, bool Round)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int Elems = 8 >> Op.Size;
-
- int ESize = 8 << Op.Size;
-
- int Part = Op.RegisterSize == ARegisterSize.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);
- }
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdCmp.cs b/ChocolArm64/Instruction/AInstEmitSimdCmp.cs
deleted file mode 100644
index cd3480e6..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdCmp.cs
+++ /dev/null
@@ -1,526 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitAluHelper;
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Cmeq_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Beq_S, Scalar: true);
- }
-
- public static void Cmeq_V(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg Op)
- {
- if (Op.Size < 3 && AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.CompareEqual));
- }
- else if (Op.Size == 3 && AOptimizations.UseSse41)
- {
- EmitSse41Op(Context, nameof(Sse41.CompareEqual));
- }
- else
- {
- EmitCmp(Context, OpCodes.Beq_S, Scalar: false);
- }
- }
- else
- {
- EmitCmp(Context, OpCodes.Beq_S, Scalar: false);
- }
- }
-
- public static void Cmge_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bge_S, Scalar: true);
- }
-
- public static void Cmge_V(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bge_S, Scalar: false);
- }
-
- public static void Cmgt_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bgt_S, Scalar: true);
- }
-
- public static void Cmgt_V(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg Op)
- {
- if (Op.Size < 3 && AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.CompareGreaterThan));
- }
- else if (Op.Size == 3 && AOptimizations.UseSse42)
- {
- EmitSse42Op(Context, nameof(Sse42.CompareGreaterThan));
- }
- else
- {
- EmitCmp(Context, OpCodes.Bgt_S, Scalar: false);
- }
- }
- else
- {
- EmitCmp(Context, OpCodes.Bgt_S, Scalar: false);
- }
- }
-
- public static void Cmhi_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bgt_Un_S, Scalar: true);
- }
-
- public static void Cmhi_V(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bgt_Un_S, Scalar: false);
- }
-
- public static void Cmhs_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bge_Un_S, Scalar: true);
- }
-
- public static void Cmhs_V(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bge_Un_S, Scalar: false);
- }
-
- public static void Cmle_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Ble_S, Scalar: true);
- }
-
- public static void Cmle_V(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Ble_S, Scalar: false);
- }
-
- public static void Cmlt_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Blt_S, Scalar: true);
- }
-
- public static void Cmlt_V(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Blt_S, Scalar: false);
- }
-
- public static void Cmtst_S(AILEmitterCtx Context)
- {
- EmitCmtst(Context, Scalar: true);
- }
-
- public static void Cmtst_V(AILEmitterCtx Context)
- {
- EmitCmtst(Context, Scalar: false);
- }
-
- public static void Fccmp_S(AILEmitterCtx Context)
- {
- AOpCodeSimdFcond Op = (AOpCodeSimdFcond)Context.CurrOp;
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- Context.EmitCondBranch(LblTrue, Op.Cond);
-
- EmitSetNZCV(Context, Op.NZCV);
-
- Context.Emit(OpCodes.Br, LblEnd);
-
- Context.MarkLabel(LblTrue);
-
- Fcmp_S(Context);
-
- Context.MarkLabel(LblEnd);
- }
-
- public static void Fccmpe_S(AILEmitterCtx Context)
- {
- Fccmp_S(Context);
- }
-
- public static void Fcmeq_S(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.CompareEqualScalar));
- }
- else
- {
- EmitScalarFcmp(Context, OpCodes.Beq_S);
- }
- }
-
- public static void Fcmeq_V(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.CompareEqual));
- }
- else
- {
- EmitVectorFcmp(Context, OpCodes.Beq_S);
- }
- }
-
- public static void Fcmge_S(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.CompareGreaterThanOrEqualScalar));
- }
- else
- {
- EmitScalarFcmp(Context, OpCodes.Bge_S);
- }
- }
-
- public static void Fcmge_V(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.CompareGreaterThanOrEqual));
- }
- else
- {
- EmitVectorFcmp(Context, OpCodes.Bge_S);
- }
- }
-
- public static void Fcmgt_S(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.CompareGreaterThanScalar));
- }
- else
- {
- EmitScalarFcmp(Context, OpCodes.Bgt_S);
- }
- }
-
- public static void Fcmgt_V(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.CompareGreaterThan));
- }
- else
- {
- EmitVectorFcmp(Context, OpCodes.Bgt_S);
- }
- }
-
- public static void Fcmle_S(AILEmitterCtx Context)
- {
- EmitScalarFcmp(Context, OpCodes.Ble_S);
- }
-
- public static void Fcmle_V(AILEmitterCtx Context)
- {
- EmitVectorFcmp(Context, OpCodes.Ble_S);
- }
-
- public static void Fcmlt_S(AILEmitterCtx Context)
- {
- EmitScalarFcmp(Context, OpCodes.Blt_S);
- }
-
- public static void Fcmlt_V(AILEmitterCtx Context)
- {
- EmitVectorFcmp(Context, OpCodes.Blt_S);
- }
-
- public static void Fcmp_S(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- bool CmpWithZero = !(Op is AOpCodeSimdFcond) ? Op.Bit3 : false;
-
- //Handle NaN case.
- //If any number is NaN, then NZCV = 0011.
- if (CmpWithZero)
- {
- EmitNaNCheck(Context, Op.Rn);
- }
- else
- {
- EmitNaNCheck(Context, Op.Rn);
- EmitNaNCheck(Context, Op.Rm);
-
- Context.Emit(OpCodes.Or);
- }
-
- AILLabel LblNaN = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- Context.Emit(OpCodes.Brtrue_S, LblNaN);
-
- void EmitLoadOpers()
- {
- 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);
- }
- }
-
- //Z = Rn == Rm
- EmitLoadOpers();
-
- Context.Emit(OpCodes.Ceq);
- Context.Emit(OpCodes.Dup);
-
- Context.EmitStflg((int)APState.ZBit);
-
- //C = Rn >= Rm
- EmitLoadOpers();
-
- Context.Emit(OpCodes.Cgt);
- Context.Emit(OpCodes.Or);
-
- Context.EmitStflg((int)APState.CBit);
-
- //N = Rn < Rm
- EmitLoadOpers();
-
- Context.Emit(OpCodes.Clt);
-
- Context.EmitStflg((int)APState.NBit);
-
- //V = 0
- Context.EmitLdc_I4(0);
-
- Context.EmitStflg((int)APState.VBit);
-
- Context.Emit(OpCodes.Br_S, LblEnd);
-
- Context.MarkLabel(LblNaN);
-
- EmitSetNZCV(Context, 0b0011);
-
- Context.MarkLabel(LblEnd);
- }
-
- public static void Fcmpe_S(AILEmitterCtx Context)
- {
- Fcmp_S(Context);
- }
-
- private static void EmitNaNCheck(AILEmitterCtx Context, int Reg)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractF(Context, Reg, 0, Op.Size);
-
- if (Op.Size == 0)
- {
- Context.EmitCall(typeof(float), nameof(float.IsNaN));
- }
- else if (Op.Size == 1)
- {
- Context.EmitCall(typeof(double), nameof(double.IsNaN));
- }
- else
- {
- throw new InvalidOperationException();
- }
- }
-
- private static void EmitCmp(AILEmitterCtx Context, OpCode ILOp, bool Scalar)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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 AOpCodeSimdReg BinOp)
- {
- EmitVectorExtractSx(Context, BinOp.Rm, Index, Op.Size);
- }
- else
- {
- Context.EmitLdc_I8(0L);
- }
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- 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 == ARegisterSize.SIMD64) || Scalar)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitCmtst(AILEmitterCtx Context, bool Scalar)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)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);
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- 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 == ARegisterSize.SIMD64) || Scalar)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitScalarFcmp(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitFcmp(Context, ILOp, 0, Scalar: true);
- }
-
- private static void EmitVectorFcmp(AILEmitterCtx Context, OpCode ILOp)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> SizeF + 2;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitFcmp(Context, ILOp, Index, Scalar: false);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitFcmp(AILEmitterCtx Context, OpCode ILOp, int Index, bool Scalar)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- ulong SzMask = ulong.MaxValue >> (64 - (32 << SizeF));
-
- EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
-
- if (Op is AOpCodeSimdReg BinOp)
- {
- EmitVectorExtractF(Context, BinOp.Rm, Index, SizeF);
- }
- else if (SizeF == 0)
- {
- Context.EmitLdc_R4(0f);
- }
- else /* if (SizeF == 1) */
- {
- Context.EmitLdc_R8(0d);
- }
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- Context.Emit(ILOp, LblTrue);
-
- if (Scalar)
- {
- EmitVectorZeroAll(Context, Op.Rd);
- }
- else
- {
- EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, 0);
- }
-
- Context.Emit(OpCodes.Br_S, LblEnd);
-
- Context.MarkLabel(LblTrue);
-
- if (Scalar)
- {
- EmitVectorInsert(Context, Op.Rd, Index, 3, (long)SzMask);
-
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- else
- {
- EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, (long)SzMask);
- }
-
- Context.MarkLabel(LblEnd);
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdCrypto.cs b/ChocolArm64/Instruction/AInstEmitSimdCrypto.cs
deleted file mode 100644
index b2680a58..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdCrypto.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Translation;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Aesd_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Decrypt));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Aese_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Encrypt));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Aesimc_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InverseMixColumns));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Aesmc_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.MixColumns));
-
- Context.EmitStvec(Op.Rd);
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs b/ChocolArm64/Instruction/AInstEmitSimdCvt.cs
deleted file mode 100644
index f277069b..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs
+++ /dev/null
@@ -1,697 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Fcvt_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- if (AOptimizations.UseSse2)
- {
- if (Op.Size == 1 && Op.Opc == 0)
- {
- //Double -> Single.
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleZero));
-
- EmitLdvecWithCastToDouble(Context, Op.Rn);
-
- Type[] Types = new Type[] { typeof(Vector128<float>), typeof(Vector128<double>) };
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Single), Types));
-
- Context.EmitStvec(Op.Rd);
- }
- else if (Op.Size == 0 && Op.Opc == 1)
- {
- //Single -> Double.
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorDoubleZero));
-
- Context.EmitLdvec(Op.Rn);
-
- Type[] Types = new Type[] { typeof(Vector128<double>), typeof(Vector128<float>) };
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Double), Types));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
- }
- else
- {
- //Invalid encoding.
- throw new InvalidOperationException();
- }
- }
- else
- {
- EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
- EmitFloatCast(Context, Op.Opc);
-
- EmitScalarSetF(Context, Op.Rd, Op.Opc);
- }
- }
-
- public static void Fcvtas_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_s_Gp(Context, () => EmitRoundMathCall(Context, MidpointRounding.AwayFromZero));
- }
-
- public static void Fcvtau_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_u_Gp(Context, () => EmitRoundMathCall(Context, MidpointRounding.AwayFromZero));
- }
-
- public static void Fcvtl_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- int Elems = 4 >> SizeF;
-
- int Part = Op.RegisterSize == ARegisterSize.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(ATranslatedSub.StateArgIdx);
-
- Context.EmitCall(typeof(ASoftFloat16_32), nameof(ASoftFloat16_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(AILEmitterCtx Context)
- {
- EmitFcvt_s_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Floor)));
- }
-
- public static void Fcvtmu_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_u_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Floor)));
- }
-
- public static void Fcvtn_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- int Elems = 4 >> SizeF;
-
- int Part = Op.RegisterSize == ARegisterSize.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(ATranslatedSub.StateArgIdx);
-
- Context.EmitCall(typeof(ASoftFloat32_16), nameof(ASoftFloat32_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(AILEmitterCtx Context)
- {
- EmitFcvtn(Context, Signed: true, Scalar: true);
- }
-
- public static void Fcvtns_V(AILEmitterCtx Context)
- {
- EmitFcvtn(Context, Signed: true, Scalar: false);
- }
-
- public static void Fcvtnu_S(AILEmitterCtx Context)
- {
- EmitFcvtn(Context, Signed: false, Scalar: true);
- }
-
- public static void Fcvtnu_V(AILEmitterCtx Context)
- {
- EmitFcvtn(Context, Signed: false, Scalar: false);
- }
-
- public static void Fcvtps_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_s_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Ceiling)));
- }
-
- public static void Fcvtpu_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_u_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Ceiling)));
- }
-
- public static void Fcvtzs_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_s_Gp(Context, () => { });
- }
-
- public static void Fcvtzs_Gp_Fix(AILEmitterCtx Context)
- {
- EmitFcvtzs_Gp_Fix(Context);
- }
-
- public static void Fcvtzs_S(AILEmitterCtx Context)
- {
- EmitScalarFcvtzs(Context);
- }
-
- public static void Fcvtzs_V(AILEmitterCtx Context)
- {
- EmitVectorFcvtzs(Context);
- }
-
- public static void Fcvtzu_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_u_Gp(Context, () => { });
- }
-
- public static void Fcvtzu_Gp_Fix(AILEmitterCtx Context)
- {
- EmitFcvtzu_Gp_Fix(Context);
- }
-
- public static void Fcvtzu_S(AILEmitterCtx Context)
- {
- EmitScalarFcvtzu(Context);
- }
-
- public static void Fcvtzu_V(AILEmitterCtx Context)
- {
- EmitVectorFcvtzu(Context);
- }
-
- public static void Scvtf_Gp(AILEmitterCtx Context)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U4);
- }
-
- EmitFloatCast(Context, Op.Size);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Scvtf_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractSx(Context, Op.Rn, 0, Op.Size + 2);
-
- EmitFloatCast(Context, Op.Size);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Scvtf_V(AILEmitterCtx Context)
- {
- EmitVectorCvtf(Context, Signed: true);
- }
-
- public static void Ucvtf_Gp(AILEmitterCtx Context)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- if (Context.CurrOp.RegisterSize == ARegisterSize.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_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size + 2);
-
- Context.Emit(OpCodes.Conv_R_Un);
-
- EmitFloatCast(Context, Op.Size);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Ucvtf_V(AILEmitterCtx Context)
- {
- EmitVectorCvtf(Context, Signed: false);
- }
-
- private static int GetFBits(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdShImm Op)
- {
- return GetImmShr(Op);
- }
-
- return 0;
- }
-
- private static void EmitFloatCast(AILEmitterCtx 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 EmitFcvtn(AILEmitterCtx Context, bool Signed, bool Scalar)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
- int SizeI = SizeF + 2;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = !Scalar ? Bytes >> SizeI : 1;
-
- if (Scalar && (SizeF == 0))
- {
- EmitVectorZeroLowerTmp(Context);
- }
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
-
- EmitRoundMathCall(Context, MidpointRounding.ToEven);
-
- if (SizeF == 0)
- {
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.SatF32ToS32)
- : nameof(AVectorHelper.SatF32ToU32));
-
- Context.Emit(OpCodes.Conv_U8);
- }
- else /* if (SizeF == 1) */
- {
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.SatF64ToS64)
- : nameof(AVectorHelper.SatF64ToU64));
- }
-
- EmitVectorInsertTmp(Context, Index, SizeI);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitFcvt_s_Gp(AILEmitterCtx Context, Action Emit)
- {
- EmitFcvt___Gp(Context, Emit, true);
- }
-
- private static void EmitFcvt_u_Gp(AILEmitterCtx Context, Action Emit)
- {
- EmitFcvt___Gp(Context, Emit, false);
- }
-
- private static void EmitFcvt___Gp(AILEmitterCtx Context, Action Emit, bool Signed)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)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 == ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- Context.EmitStintzr(Op.Rd);
- }
-
- private static void EmitFcvtzs_Gp_Fix(AILEmitterCtx Context)
- {
- EmitFcvtz__Gp_Fix(Context, true);
- }
-
- private static void EmitFcvtzu_Gp_Fix(AILEmitterCtx Context)
- {
- EmitFcvtz__Gp_Fix(Context, false);
- }
-
- private static void EmitFcvtz__Gp_Fix(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)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 == ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- Context.EmitStintzr(Op.Rd);
- }
-
- private static void EmitVectorScvtf(AILEmitterCtx Context)
- {
- EmitVectorCvtf(Context, true);
- }
-
- private static void EmitVectorUcvtf(AILEmitterCtx Context)
- {
- EmitVectorCvtf(Context, false);
- }
-
- private static void EmitVectorCvtf(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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);
- }
-
- Context.Emit(SizeF == 0
- ? OpCodes.Conv_R4
- : OpCodes.Conv_R8);
-
- EmitI2fFBitsMul(Context, SizeF, FBits);
-
- EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitScalarFcvtzs(AILEmitterCtx Context)
- {
- EmitScalarFcvtz(Context, true);
- }
-
- private static void EmitScalarFcvtzu(AILEmitterCtx Context)
- {
- EmitScalarFcvtz(Context, false);
- }
-
- private static void EmitScalarFcvtz(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
- int SizeI = SizeF + 2;
-
- int FBits = GetFBits(Context);
-
- EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
-
- EmitF2iFBitsMul(Context, SizeF, FBits);
-
- if (SizeF == 0)
- {
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.SatF32ToS32)
- : nameof(AVectorHelper.SatF32ToU32));
- }
- else /* if (SizeF == 1) */
- {
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.SatF64ToS64)
- : nameof(AVectorHelper.SatF64ToU64));
- }
-
- if (SizeF == 0)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- EmitScalarSet(Context, Op.Rd, SizeI);
- }
-
- private static void EmitVectorFcvtzs(AILEmitterCtx Context)
- {
- EmitVectorFcvtz(Context, true);
- }
-
- private static void EmitVectorFcvtzu(AILEmitterCtx Context)
- {
- EmitVectorFcvtz(Context, false);
- }
-
- private static void EmitVectorFcvtz(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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++)
- {
- EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
-
- EmitF2iFBitsMul(Context, SizeF, FBits);
-
- if (SizeF == 0)
- {
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.SatF32ToS32)
- : nameof(AVectorHelper.SatF32ToU32));
- }
- else /* if (SizeF == 1) */
- {
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.SatF64ToS64)
- : nameof(AVectorHelper.SatF64ToU64));
- }
-
- if (SizeF == 0)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- EmitVectorInsert(Context, Op.Rd, Index, SizeI);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitScalarFcvts(AILEmitterCtx Context, int Size, int FBits)
- {
- if (Size < 0 || Size > 1)
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- EmitF2iFBitsMul(Context, Size, FBits);
-
- if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
- {
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF32ToS32));
- }
- else /* if (Size == 1) */
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF64ToS32));
- }
- }
- else
- {
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF32ToS64));
- }
- else /* if (Size == 1) */
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF64ToS64));
- }
- }
- }
-
- private static void EmitScalarFcvtu(AILEmitterCtx Context, int Size, int FBits)
- {
- if (Size < 0 || Size > 1)
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- EmitF2iFBitsMul(Context, Size, FBits);
-
- if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
- {
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF32ToU32));
- }
- else /* if (Size == 1) */
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF64ToU32));
- }
- }
- else
- {
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF32ToU64));
- }
- else /* if (Size == 1) */
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF64ToU64));
- }
- }
- }
-
- private static void EmitF2iFBitsMul(AILEmitterCtx 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(AILEmitterCtx 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);
- }
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdHash.cs b/ChocolArm64/Instruction/AInstEmitSimdHash.cs
deleted file mode 100644
index 5a59e779..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdHash.cs
+++ /dev/null
@@ -1,140 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Translation;
-
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
-#region "Sha1"
- public static void Sha1c_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- EmitVectorExtractZx(Context, Op.Rn, 0, 2);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.HashChoose));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha1h_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, 0, 2);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.FixedRotate));
-
- EmitScalarSet(Context, Op.Rd, 2);
- }
-
- public static void Sha1m_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- EmitVectorExtractZx(Context, Op.Rn, 0, 2);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.HashMajority));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha1p_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- EmitVectorExtractZx(Context, Op.Rn, 0, 2);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.HashParity));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha1su0_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Sha1SchedulePart1));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha1su1_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Sha1SchedulePart2));
-
- Context.EmitStvec(Op.Rd);
- }
-#endregion
-
-#region "Sha256"
- public static void Sha256h_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.HashLower));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha256h2_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.HashUpper));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha256su0_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Sha256SchedulePart1));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha256su1_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Sha256SchedulePart2));
-
- Context.EmitStvec(Op.Rd);
- }
-#endregion
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs
deleted file mode 100644
index ff082831..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs
+++ /dev/null
@@ -1,1495 +0,0 @@
-using ChocolArm64.Decoder;
-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.Instruction
-{
- static class AInstEmitSimdHelper
- {
- public static readonly Type[] IntTypesPerSizeLog2 = new Type[]
- {
- typeof(sbyte),
- typeof(short),
- typeof(int),
- typeof(long)
- };
-
- public static readonly Type[] UIntTypesPerSizeLog2 = new Type[]
- {
- typeof(byte),
- typeof(ushort),
- typeof(uint),
- typeof(ulong)
- };
-
- public static readonly Type[] VectorIntTypesPerSizeLog2 = new Type[]
- {
- typeof(Vector128<sbyte>),
- typeof(Vector128<short>),
- typeof(Vector128<int>),
- typeof(Vector128<long>)
- };
-
- public static readonly Type[] VectorUIntTypesPerSizeLog2 = new Type[]
- {
- typeof(Vector128<byte>),
- typeof(Vector128<ushort>),
- typeof(Vector128<uint>),
- typeof(Vector128<ulong>)
- };
-
- [Flags]
- public enum OperFlags
- {
- Rd = 1 << 0,
- Rn = 1 << 1,
- Rm = 1 << 2,
- Ra = 1 << 3,
-
- RnRm = Rn | Rm,
- RdRn = Rd | Rn,
- RaRnRm = Ra | Rn | Rm,
- RdRnRm = Rd | Rn | Rm
- }
-
- public static int GetImmShl(AOpCodeSimdShImm Op)
- {
- return Op.Imm - (8 << Op.Size);
- }
-
- public static int GetImmShr(AOpCodeSimdShImm Op)
- {
- return (8 << (Op.Size + 1)) - Op.Imm;
- }
-
- public static void EmitSse2Op(AILEmitterCtx Context, string Name)
- {
- EmitSseOp(Context, Name, typeof(Sse2));
- }
-
- public static void EmitSse41Op(AILEmitterCtx Context, string Name)
- {
- EmitSseOp(Context, Name, typeof(Sse41));
- }
-
- public static void EmitSse42Op(AILEmitterCtx Context, string Name)
- {
- EmitSseOp(Context, Name, typeof(Sse42));
- }
-
- private static void EmitSseOp(AILEmitterCtx Context, string Name, Type Type)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Type BaseType = VectorIntTypesPerSizeLog2[Op.Size];
-
- if (Op is AOpCodeSimdReg BinOp)
- {
- EmitLdvecWithSignedCast(Context, BinOp.Rm, Op.Size);
-
- Context.EmitCall(Type.GetMethod(Name, new Type[] { BaseType, BaseType }));
- }
- else
- {
- Context.EmitCall(Type.GetMethod(Name, new Type[] { BaseType }));
- }
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitLdvecWithSignedCast(AILEmitterCtx Context, int Reg, int Size)
- {
- Context.EmitLdvec(Reg);
-
- switch (Size)
- {
- case 0: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToSByte)); break;
- case 1: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToInt16)); break;
- case 2: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToInt32)); break;
- case 3: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToInt64)); break;
-
- default: throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
-
- public static void EmitLdvecWithCastToDouble(AILEmitterCtx Context, int Reg)
- {
- Context.EmitLdvec(Reg);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToDouble));
- }
-
- public static void EmitStvecWithCastFromDouble(AILEmitterCtx Context, int Reg)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorDoubleToSingle));
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitLdvecWithUnsignedCast(AILEmitterCtx Context, int Reg, int Size)
- {
- Context.EmitLdvec(Reg);
-
- switch (Size)
- {
- case 0: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToByte)); break;
- case 1: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToUInt16)); break;
- case 2: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToUInt32)); break;
- case 3: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToUInt64)); break;
-
- default: throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
-
- public static void EmitStvecWithSignedCast(AILEmitterCtx Context, int Reg, int Size)
- {
- switch (Size)
- {
- case 0: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSByteToSingle)); break;
- case 1: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInt16ToSingle)); break;
- case 2: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInt32ToSingle)); break;
- case 3: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInt64ToSingle)); break;
-
- default: throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitStvecWithUnsignedCast(AILEmitterCtx Context, int Reg, int Size)
- {
- switch (Size)
- {
- case 0: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorByteToSingle)); break;
- case 1: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorUInt16ToSingle)); break;
- case 2: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorUInt32ToSingle)); break;
- case 3: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorUInt64ToSingle)); break;
-
- default: throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitScalarSseOrSse2OpF(AILEmitterCtx Context, string Name)
- {
- EmitSseOrSse2OpF(Context, Name, true);
- }
-
- public static void EmitVectorSseOrSse2OpF(AILEmitterCtx Context, string Name)
- {
- EmitSseOrSse2OpF(Context, Name, false);
- }
-
- public static void EmitSseOrSse2OpF(AILEmitterCtx Context, string Name, bool Scalar)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- void Ldvec(int Reg)
- {
- Context.EmitLdvec(Reg);
-
- if (SizeF == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToDouble));
- }
- }
-
- Ldvec(Op.Rn);
-
- Type Type;
- Type BaseType;
-
- if (SizeF == 0)
- {
- Type = typeof(Sse);
- BaseType = typeof(Vector128<float>);
- }
- else /* if (SizeF == 1) */
- {
- Type = typeof(Sse2);
- BaseType = typeof(Vector128<double>);
- }
-
- if (Op is AOpCodeSimdReg BinOp)
- {
- Ldvec(BinOp.Rm);
-
- Context.EmitCall(Type.GetMethod(Name, new Type[] { BaseType, BaseType }));
- }
- else
- {
- Context.EmitCall(Type.GetMethod(Name, new Type[] { BaseType }));
- }
-
- if (SizeF == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorDoubleToSingle));
- }
-
- 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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitUnaryMathCall(AILEmitterCtx Context, string Name)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)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(AILEmitterCtx Context, string Name)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)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(AILEmitterCtx Context, MidpointRounding RoundMode)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)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 EmitUnarySoftFloatCall(AILEmitterCtx Context, string Name)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- MethodInfo MthdInfo;
-
- if (SizeF == 0)
- {
- MthdInfo = typeof(ASoftFloat).GetMethod(Name, new Type[] { typeof(float) });
- }
- else /* if (SizeF == 1) */
- {
- MthdInfo = typeof(ASoftFloat).GetMethod(Name, new Type[] { typeof(double) });
- }
-
- Context.EmitCall(MthdInfo);
- }
-
- public static void EmitSoftFloatCall(AILEmitterCtx Context, string Name)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
-
- Type Type = (Op.Size & 1) == 0
- ? typeof(ASoftFloat_32)
- : typeof(ASoftFloat_64);
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- Context.EmitCall(Type, Name);
- }
-
- public static void EmitScalarBinaryOpByElemF(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElemF Op = (AOpCodeSimdRegElemF)Context.CurrOp;
-
- EmitScalarOpByElemF(Context, Emit, Op.Index, Ternary: false);
- }
-
- public static void EmitScalarTernaryOpByElemF(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElemF Op = (AOpCodeSimdRegElemF)Context.CurrOp;
-
- EmitScalarOpByElemF(Context, Emit, Op.Index, Ternary: true);
- }
-
- public static void EmitScalarOpByElemF(AILEmitterCtx Context, Action Emit, int Elem, bool Ternary)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)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(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOp(Context, Emit, OperFlags.Rn, true);
- }
-
- public static void EmitScalarBinaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOp(Context, Emit, OperFlags.RnRm, true);
- }
-
- public static void EmitScalarUnaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOp(Context, Emit, OperFlags.Rn, false);
- }
-
- public static void EmitScalarBinaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOp(Context, Emit, OperFlags.RnRm, false);
- }
-
- public static void EmitScalarTernaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOp(Context, Emit, OperFlags.RdRnRm, false);
- }
-
- public static void EmitScalarOp(AILEmitterCtx Context, Action Emit, OperFlags Opers, bool Signed)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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, ((AOpCodeSimdReg)Op).Rm, 0, Op.Size, Signed);
- }
-
- Emit();
-
- EmitScalarSet(Context, Op.Rd, Op.Size);
- }
-
- public static void EmitScalarUnaryOpF(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOpF(Context, Emit, OperFlags.Rn);
- }
-
- public static void EmitScalarBinaryOpF(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOpF(Context, Emit, OperFlags.RnRm);
- }
-
- public static void EmitScalarTernaryRaOpF(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOpF(Context, Emit, OperFlags.RaRnRm);
- }
-
- public static void EmitScalarOpF(AILEmitterCtx Context, Action Emit, OperFlags Opers)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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, ((AOpCodeSimdReg)Op).Ra, 0, SizeF);
- }
-
- if (Rn)
- {
- EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
- }
-
- if (Rm)
- {
- EmitVectorExtractF(Context, ((AOpCodeSimdReg)Op).Rm, 0, SizeF);
- }
-
- Emit();
-
- EmitScalarSetF(Context, Op.Rd, SizeF);
- }
-
- public static void EmitVectorUnaryOpF(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOpF(Context, Emit, OperFlags.Rn);
- }
-
- public static void EmitVectorBinaryOpF(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOpF(Context, Emit, OperFlags.RnRm);
- }
-
- public static void EmitVectorTernaryOpF(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOpF(Context, Emit, OperFlags.RdRnRm);
- }
-
- public static void EmitVectorOpF(AILEmitterCtx Context, Action Emit, OperFlags Opers)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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, ((AOpCodeSimdReg)Op).Rm, Index, SizeF);
- }
-
- Emit();
-
- EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitVectorBinaryOpByElemF(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElemF Op = (AOpCodeSimdRegElemF)Context.CurrOp;
-
- EmitVectorOpByElemF(Context, Emit, Op.Index, Ternary: false);
- }
-
- public static void EmitVectorTernaryOpByElemF(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElemF Op = (AOpCodeSimdRegElemF)Context.CurrOp;
-
- EmitVectorOpByElemF(Context, Emit, Op.Index, Ternary: true);
- }
-
- public static void EmitVectorOpByElemF(AILEmitterCtx Context, Action Emit, int Elem, bool Ternary)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitVectorUnaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, OperFlags.Rn, true);
- }
-
- public static void EmitVectorBinaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, OperFlags.RnRm, true);
- }
-
- public static void EmitVectorTernaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, OperFlags.RdRnRm, true);
- }
-
- public static void EmitVectorUnaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, OperFlags.Rn, false);
- }
-
- public static void EmitVectorBinaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, OperFlags.RnRm, false);
- }
-
- public static void EmitVectorTernaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, OperFlags.RdRnRm, false);
- }
-
- public static void EmitVectorOp(AILEmitterCtx Context, Action Emit, OperFlags Opers, bool Signed)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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, ((AOpCodeSimdReg)Op).Rm, Index, Op.Size, Signed);
- }
-
- Emit();
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitVectorBinaryOpByElemSx(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp;
-
- EmitVectorOpByElem(Context, Emit, Op.Index, false, true);
- }
-
- public static void EmitVectorBinaryOpByElemZx(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp;
-
- EmitVectorOpByElem(Context, Emit, Op.Index, false, false);
- }
-
- public static void EmitVectorTernaryOpByElemZx(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp;
-
- EmitVectorOpByElem(Context, Emit, Op.Index, true, false);
- }
-
- public static void EmitVectorOpByElem(AILEmitterCtx Context, Action Emit, int Elem, bool Ternary, bool Signed)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)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();
-
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitVectorImmUnaryOp(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorImmOp(Context, Emit, false);
- }
-
- public static void EmitVectorImmBinaryOp(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorImmOp(Context, Emit, true);
- }
-
- public static void EmitVectorImmOp(AILEmitterCtx Context, Action Emit, bool Binary)
- {
- AOpCodeSimdImm Op = (AOpCodeSimdImm)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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitVectorWidenRmBinaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorWidenRmBinaryOp(Context, Emit, true);
- }
-
- public static void EmitVectorWidenRmBinaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorWidenRmBinaryOp(Context, Emit, false);
- }
-
- public static void EmitVectorWidenRmBinaryOp(AILEmitterCtx Context, Action Emit, bool Signed)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int Elems = 8 >> Op.Size;
-
- int Part = Op.RegisterSize == ARegisterSize.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(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorWidenRnRmOp(Context, Emit, false, true);
- }
-
- public static void EmitVectorWidenRnRmBinaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorWidenRnRmOp(Context, Emit, false, false);
- }
-
- public static void EmitVectorWidenRnRmTernaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorWidenRnRmOp(Context, Emit, true, true);
- }
-
- public static void EmitVectorWidenRnRmTernaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorWidenRnRmOp(Context, Emit, true, false);
- }
-
- public static void EmitVectorWidenRnRmOp(AILEmitterCtx Context, Action Emit, bool Ternary, bool Signed)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int Elems = 8 >> Op.Size;
-
- int Part = Op.RegisterSize == ARegisterSize.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 EmitVectorPairwiseOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorPairwiseOp(Context, Emit, true);
- }
-
- public static void EmitVectorPairwiseOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorPairwiseOp(Context, Emit, false);
- }
-
- public static void EmitVectorPairwiseOp(AILEmitterCtx Context, Action Emit, bool Signed)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitVectorPairwiseOpF(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, 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(AILEmitterCtx Context, Action Emit)
- {
- EmitSaturatingUnaryOpSx(Context, Emit, SaturatingFlags.ScalarSx);
- }
-
- public static void EmitVectorSaturatingUnaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitSaturatingUnaryOpSx(Context, Emit, SaturatingFlags.VectorSx);
- }
-
- public static void EmitSaturatingUnaryOpSx(AILEmitterCtx Context, Action Emit, SaturatingFlags Flags)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- bool Scalar = (Flags & SaturatingFlags.Scalar) != 0;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = !Scalar ? Bytes >> Op.Size : 1;
-
- if (Scalar)
- {
- EmitVectorZeroLowerTmp(Context);
- }
-
- 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);
- }
-
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitScalarSaturatingBinaryOpSx(AILEmitterCtx Context, SaturatingFlags Flags)
- {
- EmitSaturatingBinaryOp(Context, () => { }, SaturatingFlags.ScalarSx | Flags);
- }
-
- public static void EmitScalarSaturatingBinaryOpZx(AILEmitterCtx Context, SaturatingFlags Flags)
- {
- EmitSaturatingBinaryOp(Context, () => { }, SaturatingFlags.ScalarZx | Flags);
- }
-
- public static void EmitVectorSaturatingBinaryOpSx(AILEmitterCtx Context, SaturatingFlags Flags)
- {
- EmitSaturatingBinaryOp(Context, () => { }, SaturatingFlags.VectorSx | Flags);
- }
-
- public static void EmitVectorSaturatingBinaryOpZx(AILEmitterCtx Context, SaturatingFlags Flags)
- {
- EmitSaturatingBinaryOp(Context, () => { }, SaturatingFlags.VectorZx | Flags);
- }
-
- public static void EmitSaturatingBinaryOp(AILEmitterCtx Context, Action Emit, SaturatingFlags Flags)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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 (Scalar)
- {
- EmitVectorZeroLowerTmp(Context);
- }
-
- if (Add || Sub)
- {
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
- EmitVectorExtract(Context, ((AOpCodeSimdReg)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);
- }
- }
-
- EmitVectorInsertTmp(Context, 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);
- }
-
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
- }
- else
- {
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
- EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Op.Size, Signed);
-
- Emit();
-
- EmitSatQ(Context, Op.Size, true, Signed);
-
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
- {
- 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(AILEmitterCtx Context, SaturatingNarrowFlags Flags)
- {
- AOpCodeSimd Op = (AOpCodeSimd)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 == ARegisterSize.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(
- AILEmitterCtx Context,
- int SizeDst,
- bool SignedSrc,
- bool SignedDst)
- {
- if (SizeDst > 2)
- {
- throw new ArgumentOutOfRangeException(nameof(SizeDst));
- }
-
- Context.EmitLdc_I4(SizeDst);
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- if (SignedSrc)
- {
- ASoftFallback.EmitCall(Context, SignedDst
- ? nameof(ASoftFallback.SignedSrcSignedDstSatQ)
- : nameof(ASoftFallback.SignedSrcUnsignedDstSatQ));
- }
- else
- {
- ASoftFallback.EmitCall(Context, SignedDst
- ? nameof(ASoftFallback.UnsignedSrcSignedDstSatQ)
- : nameof(ASoftFallback.UnsignedSrcUnsignedDstSatQ));
- }
- }
-
- // TSrc (64bit) == TDst (64bit); signed.
- public static void EmitUnarySignedSatQAbsOrNeg(AILEmitterCtx Context)
- {
- if (((AOpCodeSimd)Context.CurrOp).Size < 3)
- {
- throw new InvalidOperationException();
- }
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.UnarySignedSatQAbsOrNeg));
- }
-
- // TSrcs (64bit) == TDst (64bit); signed, unsigned.
- public static void EmitBinarySatQAdd(AILEmitterCtx Context, bool Signed)
- {
- if (((AOpCodeSimdReg)Context.CurrOp).Size < 3)
- {
- throw new InvalidOperationException();
- }
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- ASoftFallback.EmitCall(Context, Signed
- ? nameof(ASoftFallback.BinarySignedSatQAdd)
- : nameof(ASoftFallback.BinaryUnsignedSatQAdd));
- }
-
- // TSrcs (64bit) == TDst (64bit); signed, unsigned.
- public static void EmitBinarySatQSub(AILEmitterCtx Context, bool Signed)
- {
- if (((AOpCodeSimdReg)Context.CurrOp).Size < 3)
- {
- throw new InvalidOperationException();
- }
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- ASoftFallback.EmitCall(Context, Signed
- ? nameof(ASoftFallback.BinarySignedSatQSub)
- : nameof(ASoftFallback.BinaryUnsignedSatQSub));
- }
-
- // TSrcs (64bit) == TDst (64bit); signed, unsigned.
- public static void EmitBinarySatQAccumulate(AILEmitterCtx Context, bool Signed)
- {
- if (((AOpCodeSimd)Context.CurrOp).Size < 3)
- {
- throw new InvalidOperationException();
- }
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- ASoftFallback.EmitCall(Context, Signed
- ? nameof(ASoftFallback.BinarySignedSatQAcc)
- : nameof(ASoftFallback.BinaryUnsignedSatQAcc));
- }
-
- public static void EmitScalarSet(AILEmitterCtx Context, int Reg, int Size)
- {
- EmitVectorZeroAll(Context, Reg);
- EmitVectorInsert(Context, Reg, 0, Size);
- }
-
- public static void EmitScalarSetF(AILEmitterCtx Context, int Reg, int Size)
- {
- if (AOptimizations.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);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.Sse41VectorInsertScalarSingle));
-
- Context.EmitStvec(Reg);
- }
- else
- {
- EmitVectorZeroAll(Context, Reg);
- EmitVectorInsertF(Context, Reg, 0, Size);
- }
- }
-
- public static void EmitVectorExtractSx(AILEmitterCtx Context, int Reg, int Index, int Size)
- {
- EmitVectorExtract(Context, Reg, Index, Size, true);
- }
-
- public static void EmitVectorExtractZx(AILEmitterCtx Context, int Reg, int Index, int Size)
- {
- EmitVectorExtract(Context, Reg, Index, Size, false);
- }
-
- public static void EmitVectorExtract(AILEmitterCtx Context, int Reg, int Index, int Size, bool Signed)
- {
- ThrowIfInvalid(Index, Size);
-
- Context.EmitLdvec(Reg);
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Size);
-
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.VectorExtractIntSx)
- : nameof(AVectorHelper.VectorExtractIntZx));
- }
-
- public static void EmitVectorExtractF(AILEmitterCtx Context, int Reg, int Index, int Size)
- {
- ThrowIfInvalidF(Index, Size);
-
- Context.EmitLdvec(Reg);
- Context.EmitLdc_I4(Index);
-
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorExtractSingle));
- }
- else if (Size == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorExtractDouble));
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
-
- public static void EmitVectorZeroAll(AILEmitterCtx Context, int Rd)
- {
- if (AOptimizations.UseSse2)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleZero));
-
- Context.EmitStvec(Rd);
- }
- else
- {
- EmitVectorZeroLower(Context, Rd);
- EmitVectorZeroUpper(Context, Rd);
- }
- }
-
- public static void EmitVectorZeroLower(AILEmitterCtx Context, int Rd)
- {
- EmitVectorInsert(Context, Rd, 0, 3, 0);
- }
-
- public static void EmitVectorZeroLowerTmp(AILEmitterCtx Context)
- {
- EmitVectorInsertTmp(Context, 0, 3, 0);
- }
-
- public static void EmitVectorZeroUpper(AILEmitterCtx Context, int Reg)
- {
- if (AOptimizations.UseSse2)
- {
- //TODO: Use MoveScalar once it is fixed, as of the
- //time of writing it just crashes the JIT.
- EmitLdvecWithUnsignedCast(Context, Reg, 3);
-
- Type[] Types = new Type[] { typeof(Vector128<ulong>), typeof(byte) };
-
- //Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MoveScalar), Types));
-
- Context.EmitLdc_I4(8);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical128BitLane), Types));
-
- Context.EmitLdc_I4(8);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), Types));
-
- EmitStvecWithUnsignedCast(Context, Reg, 3);
- }
- else
- {
- EmitVectorInsert(Context, Reg, 1, 3, 0);
- }
- }
-
- public static void EmitVectorZero32_128(AILEmitterCtx Context, int Reg)
- {
- Context.EmitLdvec(Reg);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorZero32_128));
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size)
- {
- ThrowIfInvalid(Index, Size);
-
- Context.EmitLdvec(Reg);
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Size);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt));
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitVectorInsertTmp(AILEmitterCtx Context, int Index, int Size)
- {
- ThrowIfInvalid(Index, Size);
-
- Context.EmitLdvectmp();
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Size);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt));
-
- Context.EmitStvectmp();
- }
-
- public static void EmitVectorInsert(AILEmitterCtx 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);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt));
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitVectorInsertTmp(AILEmitterCtx Context, int Index, int Size, long Value)
- {
- ThrowIfInvalid(Index, Size);
-
- Context.EmitLdc_I8(Value);
- Context.EmitLdvectmp();
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Size);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt));
-
- Context.EmitStvectmp();
- }
-
- public static void EmitVectorInsertF(AILEmitterCtx Context, int Reg, int Index, int Size)
- {
- ThrowIfInvalidF(Index, Size);
-
- Context.EmitLdvec(Reg);
- Context.EmitLdc_I4(Index);
-
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertSingle));
- }
- else if (Size == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertDouble));
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitVectorInsertTmpF(AILEmitterCtx Context, int Index, int Size)
- {
- ThrowIfInvalidF(Index, Size);
-
- Context.EmitLdvectmp();
- Context.EmitLdc_I4(Index);
-
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertSingle));
- }
- else if (Size == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.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/Instruction/AInstEmitSimdLogical.cs b/ChocolArm64/Instruction/AInstEmitSimdLogical.cs
deleted file mode 100644
index 1aa8981f..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdLogical.cs
+++ /dev/null
@@ -1,311 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void And_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.And));
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.And));
- }
- }
-
- public static void Bic_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Type[] Types = new Type[]
- {
- VectorUIntTypesPerSizeLog2[Op.Size],
- VectorUIntTypesPerSizeLog2[Op.Size]
- };
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), Types));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.And);
- });
- }
- }
-
- public static void Bic_Vi(AILEmitterCtx Context)
- {
- EmitVectorImmBinaryOp(Context, () =>
- {
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.And);
- });
- }
-
- public static void Bif_V(AILEmitterCtx Context)
- {
- EmitBitBif(Context, true);
- }
-
- public static void Bit_V(AILEmitterCtx Context)
- {
- EmitBitBif(Context, false);
- }
-
- private static void EmitBitBif(AILEmitterCtx Context, bool NotRm)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2)
- {
- Type[] Types = new Type[]
- {
- VectorUIntTypesPerSizeLog2[Op.Size],
- VectorUIntTypesPerSizeLog2[Op.Size]
- };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), Types));
-
- string Name = NotRm ? nameof(Sse2.AndNot) : nameof(Sse2.And);
-
- Context.EmitCall(typeof(Sse2).GetMethod(Name, Types));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), Types));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size);
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
-
- Context.Emit(OpCodes.Xor);
-
- EmitVectorExtractZx(Context, Op.Rm, Index, Op.Size);
-
- if (NotRm)
- {
- Context.Emit(OpCodes.Not);
- }
-
- Context.Emit(OpCodes.And);
-
- EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size);
-
- Context.Emit(OpCodes.Xor);
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- }
-
- public static void Bsl_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Type[] Types = new Type[]
- {
- VectorUIntTypesPerSizeLog2[Op.Size],
- VectorUIntTypesPerSizeLog2[Op.Size]
- };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), Types));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), Types));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), Types));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.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(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.Xor));
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Xor));
- }
- }
-
- public static void Not_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpZx(Context, () => Context.Emit(OpCodes.Not));
- }
-
- public static void Orn_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.Or);
- });
- }
-
- public static void Orr_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.Or));
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Or));
- }
- }
-
- public static void Orr_Vi(AILEmitterCtx Context)
- {
- EmitVectorImmBinaryOp(Context, () => Context.Emit(OpCodes.Or));
- }
-
- public static void Rbit_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Elems = Op.RegisterSize == ARegisterSize.SIMD128 ? 16 : 8;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, 0);
-
- Context.Emit(OpCodes.Conv_U4);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ReverseBits8));
-
- Context.Emit(OpCodes.Conv_U8);
-
- EmitVectorInsert(Context, Op.Rd, Index, 0);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Rev16_V(AILEmitterCtx Context)
- {
- EmitRev_V(Context, ContainerSize: 1);
- }
-
- public static void Rev32_V(AILEmitterCtx Context)
- {
- EmitRev_V(Context, ContainerSize: 2);
- }
-
- public static void Rev64_V(AILEmitterCtx Context)
- {
- EmitRev_V(Context, ContainerSize: 3);
- }
-
- private static void EmitRev_V(AILEmitterCtx Context, int ContainerSize)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- if (Op.Size >= ContainerSize)
- {
- throw new InvalidOperationException();
- }
-
- 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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdMemory.cs b/ChocolArm64/Instruction/AInstEmitSimdMemory.cs
deleted file mode 100644
index 368b014f..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdMemory.cs
+++ /dev/null
@@ -1,185 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-
-using static ChocolArm64.Instruction.AInstEmitMemoryHelper;
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Ld__Vms(AILEmitterCtx Context)
- {
- EmitSimdMemMs(Context, IsLoad: true);
- }
-
- public static void Ld__Vss(AILEmitterCtx Context)
- {
- EmitSimdMemSs(Context, IsLoad: true);
- }
-
- public static void St__Vms(AILEmitterCtx Context)
- {
- EmitSimdMemMs(Context, IsLoad: false);
- }
-
- public static void St__Vss(AILEmitterCtx Context)
- {
- EmitSimdMemSs(Context, IsLoad: false);
- }
-
- private static void EmitSimdMemMs(AILEmitterCtx Context, bool IsLoad)
- {
- AOpCodeSimdMemMs Op = (AOpCodeSimdMemMs)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.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- 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 == ARegisterSize.SIMD64 && Elem == Op.Elems - 1)
- {
- EmitVectorZeroUpper(Context, Rtt);
- }
- }
- else
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- 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(AILEmitterCtx Context, bool IsLoad)
- {
- AOpCodeSimdMemSs Op = (AOpCodeSimdMemSs)Context.CurrOp;
-
- int Offset = 0;
-
- void EmitMemAddress()
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- 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 == ARegisterSize.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(AILEmitterCtx Context, int Offset)
- {
- AOpCodeMemReg Op = (AOpCodeMemReg)Context.CurrOp;
-
- Context.EmitLdint(Op.Rn);
-
- if (Op.Rm != AThreadState.ZRIndex)
- {
- 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/Instruction/AInstEmitSimdMove.cs b/ChocolArm64/Instruction/AInstEmitSimdMove.cs
deleted file mode 100644
index 6001f48c..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdMove.cs
+++ /dev/null
@@ -1,562 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Dup_Gp(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- if (AOptimizations.UseSse2)
- {
- 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;
- }
-
- Type[] Types = new Type[] { UIntTypesPerSizeLog2[Op.Size] };
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), Types));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, 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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- }
-
- public static void Dup_S(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, Op.DstIndex, Op.Size);
-
- EmitScalarSet(Context, Op.Rd, Op.Size);
- }
-
- public static void Dup_V(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- 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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Ext_V(AILEmitterCtx Context)
- {
- AOpCodeSimdExt Op = (AOpCodeSimdExt)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitStvectmp();
-
- 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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Fcsel_S(AILEmitterCtx Context)
- {
- AOpCodeSimdFcond Op = (AOpCodeSimdFcond)Context.CurrOp;
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- 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(AILEmitterCtx Context)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, 0, 3);
-
- EmitIntZeroUpperIfNeeded(Context);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Fmov_Ftoi1(AILEmitterCtx Context)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, 1, 3);
-
- EmitIntZeroUpperIfNeeded(Context);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Fmov_Itof(AILEmitterCtx Context)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- EmitIntZeroUpperIfNeeded(Context);
-
- EmitScalarSet(Context, Op.Rd, 3);
- }
-
- public static void Fmov_Itof1(AILEmitterCtx Context)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- EmitIntZeroUpperIfNeeded(Context);
-
- EmitVectorInsert(Context, Op.Rd, 1, 3);
- }
-
- public static void Fmov_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Fmov_Si(AILEmitterCtx Context)
- {
- AOpCodeSimdFmov Op = (AOpCodeSimdFmov)Context.CurrOp;
-
- Context.EmitLdc_I8(Op.Imm);
-
- EmitScalarSet(Context, Op.Rd, Op.Size + 2);
- }
-
- public static void Fmov_V(AILEmitterCtx Context)
- {
- AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;
-
- int Elems = Op.RegisterSize == ARegisterSize.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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Ins_Gp(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- EmitVectorInsert(Context, Op.Rd, Op.DstIndex, Op.Size);
- }
-
- public static void Ins_V(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, Op.SrcIndex, Op.Size);
-
- EmitVectorInsert(Context, Op.Rd, Op.DstIndex, Op.Size);
- }
-
- public static void Movi_V(AILEmitterCtx Context)
- {
- EmitVectorImmUnaryOp(Context, () => { });
- }
-
- public static void Mvni_V(AILEmitterCtx Context)
- {
- EmitVectorImmUnaryOp(Context, () => Context.Emit(OpCodes.Not));
- }
-
- public static void Smov_S(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- EmitVectorExtractSx(Context, Op.Rn, Op.DstIndex, Op.Size);
-
- EmitIntZeroUpperIfNeeded(Context);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Tbl_V(AILEmitterCtx Context)
- {
- AOpCodeSimdTbl Op = (AOpCodeSimdTbl)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rm);
-
- for (int Index = 0; Index < Op.Size; Index++)
- {
- Context.EmitLdvec((Op.Rn + Index) & 0x1f);
- }
-
- switch (Op.Size)
- {
- case 1: AVectorHelper.EmitCall(Context,
- nameof(AVectorHelper.Tbl1_V64),
- nameof(AVectorHelper.Tbl1_V128)); break;
-
- case 2: AVectorHelper.EmitCall(Context,
- nameof(AVectorHelper.Tbl2_V64),
- nameof(AVectorHelper.Tbl2_V128)); break;
-
- case 3: AVectorHelper.EmitCall(Context,
- nameof(AVectorHelper.Tbl3_V64),
- nameof(AVectorHelper.Tbl3_V128)); break;
-
- case 4: AVectorHelper.EmitCall(Context,
- nameof(AVectorHelper.Tbl4_V64),
- nameof(AVectorHelper.Tbl4_V128)); break;
-
- default: throw new InvalidOperationException();
- }
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Trn1_V(AILEmitterCtx Context)
- {
- EmitVectorTranspose(Context, Part: 0);
- }
-
- public static void Trn2_V(AILEmitterCtx Context)
- {
- EmitVectorTranspose(Context, Part: 1);
- }
-
- public static void Umov_S(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, Op.DstIndex, Op.Size);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Uzp1_V(AILEmitterCtx Context)
- {
- EmitVectorUnzip(Context, Part: 0);
- }
-
- public static void Uzp2_V(AILEmitterCtx Context)
- {
- EmitVectorUnzip(Context, Part: 1);
- }
-
- public static void Xtn_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Elems = 8 >> Op.Size;
-
- int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
-
- if (AOptimizations.UseSse41 && Op.Size < 2)
- {
- void EmitZeroVector()
- {
- switch (Op.Size)
- {
- case 0: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInt16Zero)); break;
- case 1: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInt32Zero)); break;
- }
- }
-
- //For XTN, first operand is source, second operand is 0.
- //For XTN2, first operand is 0, second operand is source.
- if (Part != 0)
- {
- EmitZeroVector();
- }
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size + 1);
-
- //Set mask to discard the upper half of the wide elements.
- switch (Op.Size)
- {
- case 0: Context.EmitLdc_I4(0x00ff); break;
- case 1: Context.EmitLdc_I4(0x0000ffff); break;
- }
-
- Type WideType = IntTypesPerSizeLog2[Op.Size + 1];
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), new Type[] { WideType }));
-
- WideType = VectorIntTypesPerSizeLog2[Op.Size + 1];
-
- Type[] WideTypes = new Type[] { WideType, WideType };
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), WideTypes));
-
- if (Part == 0)
- {
- EmitZeroVector();
- }
-
- //Pack values with signed saturation, the signed saturation shouldn't
- //saturate anything since the upper bits were masked off.
- Type SseType = Op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
-
- Context.EmitCall(SseType.GetMethod(nameof(Sse2.PackUnsignedSaturate), WideTypes));
-
- if (Part != 0)
- {
- //For XTN2, we additionally need to discard the upper bits
- //of the target register and OR the result with it.
- EmitVectorZeroUpper(Context, Op.Rd);
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- Type NarrowType = VectorUIntTypesPerSizeLog2[Op.Size];
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), new Type[] { NarrowType, NarrowType }));
- }
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
- }
- else
- {
- 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(AILEmitterCtx Context)
- {
- EmitVectorZip(Context, Part: 0);
- }
-
- public static void Zip2_V(AILEmitterCtx Context)
- {
- EmitVectorZip(Context, Part: 1);
- }
-
- private static void EmitIntZeroUpperIfNeeded(AILEmitterCtx Context)
- {
- if (Context.CurrOp.RegisterSize == ARegisterSize.Int32 ||
- Context.CurrOp.RegisterSize == ARegisterSize.SIMD64)
- {
- Context.Emit(OpCodes.Conv_U4);
- Context.Emit(OpCodes.Conv_U8);
- }
- }
-
- private static void EmitVectorTranspose(AILEmitterCtx Context, int Part)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- 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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitVectorUnzip(AILEmitterCtx Context, int Part)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- 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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitVectorZip(AILEmitterCtx Context, int Part)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2)
- {
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Type[] Types = new Type[]
- {
- VectorUIntTypesPerSizeLog2[Op.Size],
- VectorUIntTypesPerSizeLog2[Op.Size]
- };
-
- string Name = Part == 0 || (Part != 0 && Op.RegisterSize == ARegisterSize.SIMD64)
- ? nameof(Sse2.UnpackLow)
- : nameof(Sse2.UnpackHigh);
-
- Context.EmitCall(typeof(Sse2).GetMethod(Name, Types));
-
- if (Op.RegisterSize == ARegisterSize.SIMD64 && Part != 0)
- {
- Context.EmitLdc_I4(8);
-
- Type[] ShTypes = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), ShTypes));
- }
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64 && Part == 0)
- {
- EmitVectorZeroUpper(Context, 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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdShift.cs b/ChocolArm64/Instruction/AInstEmitSimdShift.cs
deleted file mode 100644
index 4f828cf8..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdShift.cs
+++ /dev/null
@@ -1,865 +0,0 @@
-// https://github.com/intel/ARM_NEON_2_x86_SSE/blob/master/NEON_2_SSE.h
-
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Rshrn_V(AILEmitterCtx Context)
- {
- EmitVectorShrImmNarrowOpZx(Context, Round: true);
- }
-
- public static void Shl_S(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- EmitScalarUnaryOpZx(Context, () =>
- {
- Context.EmitLdc_I4(GetImmShl(Op));
-
- Context.Emit(OpCodes.Shl);
- });
- }
-
- public static void Shl_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0)
- {
- Type[] TypesSll = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(GetImmShl(Op));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), TypesSll));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorUnaryOpZx(Context, () =>
- {
- Context.EmitLdc_I4(GetImmShl(Op));
-
- Context.Emit(OpCodes.Shl);
- });
- }
- }
-
- public static void Shll_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Shift = 8 << Op.Size;
-
- EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
- }
-
- public static void Shrn_V(AILEmitterCtx Context)
- {
- EmitVectorShrImmNarrowOpZx(Context, Round: false);
- }
-
- public static void Sli_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)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 == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Sqrshrn_S(AILEmitterCtx Context)
- {
- EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarSxSx);
- }
-
- public static void Sqrshrn_V(AILEmitterCtx Context)
- {
- EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorSxSx);
- }
-
- public static void Sqrshrun_S(AILEmitterCtx Context)
- {
- EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarSxZx);
- }
-
- public static void Sqrshrun_V(AILEmitterCtx Context)
- {
- EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorSxZx);
- }
-
- public static void Sqshrn_S(AILEmitterCtx Context)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarSxSx);
- }
-
- public static void Sqshrn_V(AILEmitterCtx Context)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorSxSx);
- }
-
- public static void Sqshrun_S(AILEmitterCtx Context)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarSxZx);
- }
-
- public static void Sqshrun_V(AILEmitterCtx Context)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorSxZx);
- }
-
- public static void Srshr_S(AILEmitterCtx Context)
- {
- EmitScalarShrImmOpSx(Context, ShrImmFlags.Round);
- }
-
- public static void Srshr_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.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;
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- 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.EmitLdvectmp();
-
- Context.EmitLdc_I4(Shift);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), TypesShs));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorShrImmOpSx(Context, ShrImmFlags.Round);
- }
- }
-
- public static void Srsra_S(AILEmitterCtx Context)
- {
- EmitScalarShrImmOpSx(Context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
- }
-
- public static void Srsra_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.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;
-
- EmitLdvecWithSignedCast(Context, Op.Rd, Op.Size);
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- 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.EmitLdvectmp();
-
- 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));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorShrImmOpSx(Context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
- }
- }
-
- public static void Sshl_V(AILEmitterCtx Context)
- {
- EmitVectorShl(Context, Signed: true);
- }
-
- public static void Sshll_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- EmitVectorShImmWidenBinarySx(Context, () => Context.Emit(OpCodes.Shl), GetImmShl(Op));
- }
-
- public static void Sshr_S(AILEmitterCtx Context)
- {
- EmitShrImmOp(Context, ShrImmFlags.ScalarSx);
- }
-
- public static void Sshr_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0
- && Op.Size < 3)
- {
- Type[] TypesSra = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(GetImmShr(Op));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), TypesSra));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitShrImmOp(Context, ShrImmFlags.VectorSx);
- }
- }
-
- public static void Ssra_S(AILEmitterCtx Context)
- {
- EmitScalarShrImmOpSx(Context, ShrImmFlags.Accumulate);
- }
-
- public static void Ssra_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.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] };
-
- EmitLdvecWithSignedCast(Context, Op.Rd, Op.Size);
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(GetImmShr(Op));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), TypesSra));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorShrImmOpSx(Context, ShrImmFlags.Accumulate);
- }
- }
-
- public static void Uqrshrn_S(AILEmitterCtx Context)
- {
- EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
- }
-
- public static void Uqrshrn_V(AILEmitterCtx Context)
- {
- EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorZxZx);
- }
-
- public static void Uqshrn_S(AILEmitterCtx Context)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
- }
-
- public static void Uqshrn_V(AILEmitterCtx Context)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorZxZx);
- }
-
- public static void Urshr_S(AILEmitterCtx Context)
- {
- EmitScalarShrImmOpZx(Context, ShrImmFlags.Round);
- }
-
- public static void Urshr_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.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;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- 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.EmitLdvectmp();
-
- Context.EmitLdc_I4(Shift);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesShs));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorShrImmOpZx(Context, ShrImmFlags.Round);
- }
- }
-
- public static void Ursra_S(AILEmitterCtx Context)
- {
- EmitScalarShrImmOpZx(Context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
- }
-
- public static void Ursra_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.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;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- 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.EmitLdvectmp();
-
- 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));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorShrImmOpZx(Context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
- }
- }
-
- public static void Ushl_V(AILEmitterCtx Context)
- {
- EmitVectorShl(Context, Signed: false);
- }
-
- public static void Ushll_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), GetImmShl(Op));
- }
-
- public static void Ushr_S(AILEmitterCtx Context)
- {
- EmitShrImmOp(Context, ShrImmFlags.ScalarZx);
- }
-
- public static void Ushr_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0)
- {
- Type[] TypesSrl = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(GetImmShr(Op));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesSrl));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitShrImmOp(Context, ShrImmFlags.VectorZx);
- }
- }
-
- public static void Usra_S(AILEmitterCtx Context)
- {
- EmitScalarShrImmOpZx(Context, ShrImmFlags.Accumulate);
- }
-
- public static void Usra_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0)
- {
- Type[] TypesSrl = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesAdd = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(GetImmShr(Op));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesSrl));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorShrImmOpZx(Context, ShrImmFlags.Accumulate);
- }
- }
-
- private static void EmitVectorShl(AILEmitterCtx Context, bool Signed)
- {
- //This instruction shifts the value on vector A by the number of bits
- //specified on the signed, lower 8 bits of vector B. If the shift value
- //is greater or equal to the data size of each lane, then the result is zero.
- //Additionally, negative shifts produces right shifts by the negated shift value.
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int MaxShift = 8 << Op.Size;
-
- Action Emit = () =>
- {
- AILLabel LblShl = new AILLabel();
- AILLabel LblZero = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- void EmitShift(OpCode ILOp)
- {
- Context.Emit(OpCodes.Dup);
-
- Context.EmitLdc_I4(MaxShift);
-
- Context.Emit(OpCodes.Bge_S, LblZero);
- Context.Emit(ILOp);
- Context.Emit(OpCodes.Br_S, LblEnd);
- }
-
- Context.Emit(OpCodes.Conv_I1);
- Context.Emit(OpCodes.Dup);
-
- Context.EmitLdc_I4(0);
-
- Context.Emit(OpCodes.Bge_S, LblShl);
- Context.Emit(OpCodes.Neg);
-
- EmitShift(Signed
- ? OpCodes.Shr
- : OpCodes.Shr_Un);
-
- Context.MarkLabel(LblShl);
-
- EmitShift(OpCodes.Shl);
-
- Context.MarkLabel(LblZero);
-
- Context.Emit(OpCodes.Pop);
- Context.Emit(OpCodes.Pop);
-
- Context.EmitLdc_I8(0);
-
- Context.MarkLabel(LblEnd);
- };
-
- if (Signed)
- {
- EmitVectorBinaryOpSx(Context, Emit);
- }
- else
- {
- EmitVectorBinaryOpZx(Context, Emit);
- }
- }
-
- [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(AILEmitterCtx Context, ShrImmFlags Flags)
- {
- EmitShrImmOp(Context, ShrImmFlags.ScalarSx | Flags);
- }
-
- private static void EmitScalarShrImmOpZx(AILEmitterCtx Context, ShrImmFlags Flags)
- {
- EmitShrImmOp(Context, ShrImmFlags.ScalarZx | Flags);
- }
-
- private static void EmitVectorShrImmOpSx(AILEmitterCtx Context, ShrImmFlags Flags)
- {
- EmitShrImmOp(Context, ShrImmFlags.VectorSx | Flags);
- }
-
- private static void EmitVectorShrImmOpZx(AILEmitterCtx Context, ShrImmFlags Flags)
- {
- EmitShrImmOp(Context, ShrImmFlags.VectorZx | Flags);
- }
-
- private static void EmitShrImmOp(AILEmitterCtx Context, ShrImmFlags Flags)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)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) */
- {
- EmitShrImm_64(Context, Signed, Round ? RoundConst : 0L, Shift);
- }
-
- if (Accumulate)
- {
- EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed);
-
- Context.Emit(OpCodes.Add);
- }
-
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitVectorShrImmNarrowOpZx(AILEmitterCtx Context, bool Round)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- int Shift = GetImmShr(Op);
-
- long RoundConst = 1L << (Shift - 1);
-
- int Elems = 8 >> Op.Size;
-
- int Part = Op.RegisterSize == ARegisterSize.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(AILEmitterCtx Context, ShrImmSaturatingNarrowFlags Flags)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.Round | Flags);
- }
-
- private static void EmitShrImmSaturatingNarrowOp(AILEmitterCtx Context, ShrImmSaturatingNarrowFlags Flags)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)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 == ARegisterSize.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) */
- {
- EmitShrImm_64(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);
- }
- }
-
- // Dst_64 = (Int(Src_64, Signed) + RoundConst) >> Shift;
- private static void EmitShrImm_64(
- AILEmitterCtx Context,
- bool Signed,
- long RoundConst,
- int Shift)
- {
- Context.EmitLdc_I8(RoundConst);
- Context.EmitLdc_I4(Shift);
-
- ASoftFallback.EmitCall(Context, Signed
- ? nameof(ASoftFallback.SignedShrImm_64)
- : nameof(ASoftFallback.UnsignedShrImm_64));
- }
-
- private static void EmitVectorShImmWidenBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
- {
- EmitVectorShImmWidenBinaryOp(Context, Emit, Imm, true);
- }
-
- private static void EmitVectorShImmWidenBinaryZx(AILEmitterCtx Context, Action Emit, int Imm)
- {
- EmitVectorShImmWidenBinaryOp(Context, Emit, Imm, false);
- }
-
- private static void EmitVectorShImmWidenBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Elems = 8 >> Op.Size;
-
- int Part = Op.RegisterSize == ARegisterSize.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/Instruction/AInstEmitSystem.cs b/ChocolArm64/Instruction/AInstEmitSystem.cs
deleted file mode 100644
index a365398f..00000000
--- a/ChocolArm64/Instruction/AInstEmitSystem.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Hint(AILEmitterCtx Context)
- {
- //Execute as no-op.
- }
-
- public static void Isb(AILEmitterCtx Context)
- {
- //Execute as no-op.
- }
-
- public static void Mrs(AILEmitterCtx Context)
- {
- AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- string PropName;
-
- switch (GetPackedId(Op))
- {
- case 0b11_011_0000_0000_001: PropName = nameof(AThreadState.CtrEl0); break;
- case 0b11_011_0000_0000_111: PropName = nameof(AThreadState.DczidEl0); break;
- case 0b11_011_0100_0100_000: PropName = nameof(AThreadState.Fpcr); break;
- case 0b11_011_0100_0100_001: PropName = nameof(AThreadState.Fpsr); break;
- case 0b11_011_1101_0000_010: PropName = nameof(AThreadState.TpidrEl0); break;
- case 0b11_011_1101_0000_011: PropName = nameof(AThreadState.Tpidr); break;
- case 0b11_011_1110_0000_000: PropName = nameof(AThreadState.CntfrqEl0); break;
- case 0b11_011_1110_0000_001: PropName = nameof(AThreadState.CntpctEl0); break;
-
- default: throw new NotImplementedException($"Unknown MRS at {Op.Position:x16}");
- }
-
- Context.EmitCallPropGet(typeof(AThreadState), PropName);
-
- PropertyInfo PropInfo = typeof(AThreadState).GetProperty(PropName);
-
- if (PropInfo.PropertyType != typeof(long) &&
- PropInfo.PropertyType != typeof(ulong))
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- Context.EmitStintzr(Op.Rt);
- }
-
- public static void Msr(AILEmitterCtx Context)
- {
- AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
- Context.EmitLdintzr(Op.Rt);
-
- string PropName;
-
- switch (GetPackedId(Op))
- {
- case 0b11_011_0100_0100_000: PropName = nameof(AThreadState.Fpcr); break;
- case 0b11_011_0100_0100_001: PropName = nameof(AThreadState.Fpsr); break;
- case 0b11_011_1101_0000_010: PropName = nameof(AThreadState.TpidrEl0); break;
-
- default: throw new NotImplementedException($"Unknown MSR at {Op.Position:x16}");
- }
-
- PropertyInfo PropInfo = typeof(AThreadState).GetProperty(PropName);
-
- if (PropInfo.PropertyType != typeof(long) &&
- PropInfo.PropertyType != typeof(ulong))
- {
- Context.Emit(OpCodes.Conv_U4);
- }
-
- Context.EmitCallPropSet(typeof(AThreadState), PropName);
- }
-
- public static void Nop(AILEmitterCtx Context)
- {
- //Do nothing.
- }
-
- public static void Sys(AILEmitterCtx 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.
- AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
-
- switch (GetPackedId(Op))
- {
- case 0b11_011_0111_0100_001:
- {
- //DC ZVA
- for (int Offs = 0; Offs < (4 << AThreadState.DczSizeLog2); Offs += 8)
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdintzr(Op.Rt);
- Context.EmitLdc_I(Offs);
-
- Context.Emit(OpCodes.Add);
-
- Context.EmitLdc_I8(0);
-
- AInstEmitMemoryHelper.EmitWriteCall(Context, 3);
- }
-
- break;
- }
-
- //No-op
- case 0b11_011_0111_1110_001: //DC CIVAC
- break;
- }
- }
-
- private static int GetPackedId(AOpCodeSystem 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/Instruction/AInstEmitter.cs b/ChocolArm64/Instruction/AInstEmitter.cs
deleted file mode 100644
index 8712a736..00000000
--- a/ChocolArm64/Instruction/AInstEmitter.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-using ChocolArm64.Translation;
-
-namespace ChocolArm64.Instruction
-{
- delegate void AInstEmitter(AILEmitterCtx Context);
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstInterpreter.cs b/ChocolArm64/Instruction/AInstInterpreter.cs
deleted file mode 100644
index 6a855aec..00000000
--- a/ChocolArm64/Instruction/AInstInterpreter.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Memory;
-using ChocolArm64.State;
-
-namespace ChocolArm64.Instruction
-{
- delegate void AInstInterpreter(AThreadState State, AMemory Memory, AOpCode OpCode);
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/ASoftFallback.cs b/ChocolArm64/Instruction/ASoftFallback.cs
deleted file mode 100644
index d643fb6f..00000000
--- a/ChocolArm64/Instruction/ASoftFallback.cs
+++ /dev/null
@@ -1,922 +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.Instruction
-{
- using static AVectorHelper;
-
- static class ASoftFallback
- {
- public static void EmitCall(AILEmitterCtx Context, string MthdName)
- {
- Context.EmitCall(typeof(ASoftFallback), MthdName);
- }
-
-#region "ShrImm_64"
- public static long SignedShrImm_64(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
- {
- 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 UnsignedShrImm_64(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, AThreadState 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, AThreadState 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, AThreadState 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, AThreadState 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, AThreadState State)
- {
- if (Op == long.MinValue)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return long.MaxValue;
- }
- else
- {
- return Op;
- }
- }
-
- public static long BinarySignedSatQAdd(long Op1, long Op2, AThreadState 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, AThreadState 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, AThreadState 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, AThreadState 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, AThreadState 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, AThreadState 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 (((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[(Value >> NibbleIdx) & 0b1111];
- Count += PreCount;
- }
- while (PreCount == 4);
-
- return (ulong)Count;
- }
-
- public static ulong CountSetBits8(ulong Value) // "Size" is 8 (SIMD&FP Inst.).
- {
- if (Value == 0xfful)
- {
- return 8ul;
- }
-
- Value = ((Value >> 1) & 0x55ul) + (Value & 0x55ul);
- Value = ((Value >> 2) & 0x33ul) + (Value & 0x33ul);
-
- return (Value >> 4) + (Value & 0x0ful);
- }
-#endregion
-
-#region "Crc32"
- private const uint Crc32RevPoly = 0xedb88320;
- private const uint Crc32cRevPoly = 0x82f63b78;
-
- public static uint Crc32b(uint Crc, byte Val) => Crc32 (Crc, Crc32RevPoly, Val);
- public static uint Crc32h(uint Crc, ushort Val) => Crc32h(Crc, Crc32RevPoly, Val);
- public static uint Crc32w(uint Crc, uint Val) => Crc32w(Crc, Crc32RevPoly, Val);
- public static uint Crc32x(uint Crc, ulong Val) => Crc32x(Crc, Crc32RevPoly, Val);
-
- public static uint Crc32cb(uint Crc, byte Val) => Crc32 (Crc, Crc32cRevPoly, Val);
- public static uint Crc32ch(uint Crc, ushort Val) => Crc32h(Crc, Crc32cRevPoly, Val);
- public static uint Crc32cw(uint Crc, uint Val) => Crc32w(Crc, Crc32cRevPoly, Val);
- public static uint Crc32cx(uint Crc, ulong Val) => Crc32x(Crc, Crc32cRevPoly, Val);
-
- private static uint Crc32h(uint Crc, uint Poly, ushort Val)
- {
- Crc = Crc32(Crc, Poly, (byte)(Val >> 0));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 8));
-
- return Crc;
- }
-
- private static uint Crc32w(uint Crc, uint Poly, uint Val)
- {
- Crc = Crc32(Crc, Poly, (byte)(Val >> 0 ));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 8 ));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 16));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 24));
-
- return Crc;
- }
-
- private static uint Crc32x(uint Crc, uint Poly, ulong Val)
- {
- Crc = Crc32(Crc, Poly, (byte)(Val >> 0 ));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 8 ));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 16));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 24));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 32));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 40));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 48));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 56));
-
- return Crc;
- }
-
- private static uint Crc32(uint Crc, uint Poly, byte Val)
- {
- Crc ^= Val;
-
- for (int Bit = 7; Bit >= 0; Bit--)
- {
- uint Mask = (uint)(-(int)(Crc & 1));
-
- Crc = (Crc >> 1) ^ (Poly & Mask);
- }
-
- return Crc;
- }
-#endregion
-
-#region "Aes"
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> Decrypt(Vector128<float> value, Vector128<float> roundKey)
- {
- if (!Sse.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- return ACryptoHelper.AESInvSubBytes(ACryptoHelper.AESInvShiftRows(Sse.Xor(value, roundKey)));
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> Encrypt(Vector128<float> value, Vector128<float> roundKey)
- {
- if (!Sse.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- return ACryptoHelper.AESSubBytes(ACryptoHelper.AESShiftRows(Sse.Xor(value, roundKey)));
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> InverseMixColumns(Vector128<float> value)
- {
- return ACryptoHelper.AESInvMixColumns(value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> MixColumns(Vector128<float> value)
- {
- return ACryptoHelper.AESMixColumns(value);
- }
-#endregion
-
-#region "Sha1"
- public static Vector128<float> HashChoose(Vector128<float> hash_abcd, uint hash_e, Vector128<float> wk)
- {
- for (int e = 0; e <= 3; e++)
- {
- uint t = SHAchoose((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2),
- (uint)VectorExtractIntZx(hash_abcd, (byte)2, 2),
- (uint)VectorExtractIntZx(hash_abcd, (byte)3, 2));
-
- hash_e += Rol((uint)VectorExtractIntZx(hash_abcd, (byte)0, 2), 5) + t;
- hash_e += (uint)VectorExtractIntZx(wk, (byte)e, 2);
-
- t = Rol((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2), 30);
- hash_abcd = VectorInsertInt((ulong)t, hash_abcd, (byte)1, 2);
-
- Rol32_160(ref hash_e, ref hash_abcd);
- }
-
- return hash_abcd;
- }
-
- public static uint FixedRotate(uint hash_e)
- {
- return hash_e.Rol(30);
- }
-
- public static Vector128<float> HashMajority(Vector128<float> hash_abcd, uint hash_e, Vector128<float> wk)
- {
- for (int e = 0; e <= 3; e++)
- {
- uint t = SHAmajority((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2),
- (uint)VectorExtractIntZx(hash_abcd, (byte)2, 2),
- (uint)VectorExtractIntZx(hash_abcd, (byte)3, 2));
-
- hash_e += Rol((uint)VectorExtractIntZx(hash_abcd, (byte)0, 2), 5) + t;
- hash_e += (uint)VectorExtractIntZx(wk, (byte)e, 2);
-
- t = Rol((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2), 30);
- hash_abcd = VectorInsertInt((ulong)t, hash_abcd, (byte)1, 2);
-
- Rol32_160(ref hash_e, ref hash_abcd);
- }
-
- return hash_abcd;
- }
-
- public static Vector128<float> HashParity(Vector128<float> hash_abcd, uint hash_e, Vector128<float> wk)
- {
- for (int e = 0; e <= 3; e++)
- {
- uint t = SHAparity((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2),
- (uint)VectorExtractIntZx(hash_abcd, (byte)2, 2),
- (uint)VectorExtractIntZx(hash_abcd, (byte)3, 2));
-
- hash_e += Rol((uint)VectorExtractIntZx(hash_abcd, (byte)0, 2), 5) + t;
- hash_e += (uint)VectorExtractIntZx(wk, (byte)e, 2);
-
- t = Rol((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2), 30);
- hash_abcd = VectorInsertInt((ulong)t, hash_abcd, (byte)1, 2);
-
- Rol32_160(ref hash_e, ref hash_abcd);
- }
-
- return hash_abcd;
- }
-
- public static Vector128<float> Sha1SchedulePart1(Vector128<float> w0_3, Vector128<float> w4_7, Vector128<float> w8_11)
- {
- if (!Sse.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- Vector128<float> result = new Vector128<float>();
-
- ulong t2 = VectorExtractIntZx(w4_7, (byte)0, 3);
- ulong t1 = VectorExtractIntZx(w0_3, (byte)1, 3);
-
- result = VectorInsertInt((ulong)t1, result, (byte)0, 3);
- result = VectorInsertInt((ulong)t2, result, (byte)1, 3);
-
- return Sse.Xor(result, Sse.Xor(w0_3, w8_11));
- }
-
- public static Vector128<float> Sha1SchedulePart2(Vector128<float> tw0_3, Vector128<float> w12_15)
- {
- if (!Sse2.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- Vector128<float> result = new Vector128<float>();
-
- Vector128<float> T = Sse.Xor(tw0_3, Sse.StaticCast<uint, float>(
- Sse2.ShiftRightLogical128BitLane(Sse.StaticCast<float, uint>(w12_15), (byte)4)));
-
- uint tE0 = (uint)VectorExtractIntZx(T, (byte)0, 2);
- uint tE1 = (uint)VectorExtractIntZx(T, (byte)1, 2);
- uint tE2 = (uint)VectorExtractIntZx(T, (byte)2, 2);
- uint tE3 = (uint)VectorExtractIntZx(T, (byte)3, 2);
-
- result = VectorInsertInt((ulong)tE0.Rol(1), result, (byte)0, 2);
- result = VectorInsertInt((ulong)tE1.Rol(1), result, (byte)1, 2);
- result = VectorInsertInt((ulong)tE2.Rol(1), result, (byte)2, 2);
-
- return VectorInsertInt((ulong)(tE3.Rol(1) ^ tE0.Rol(2)), result, (byte)3, 2);
- }
-
- private static void Rol32_160(ref uint y, ref Vector128<float> X)
- {
- if (!Sse2.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- uint xE3 = (uint)VectorExtractIntZx(X, (byte)3, 2);
-
- X = Sse.StaticCast<uint, float>(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast<float, uint>(X), (byte)4));
- X = VectorInsertInt((ulong)y, X, (byte)0, 2);
-
- y = xE3;
- }
-
- private static uint SHAchoose(uint x, uint y, uint z)
- {
- return ((y ^ z) & x) ^ z;
- }
-
- private static uint SHAmajority(uint x, uint y, uint z)
- {
- return (x & y) | ((x | y) & z);
- }
-
- private static uint SHAparity(uint x, uint y, uint z)
- {
- return x ^ y ^ z;
- }
-
- private static uint Rol(this uint value, int count)
- {
- return (value << count) | (value >> (32 - count));
- }
-#endregion
-
-#region "Sha256"
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> HashLower(Vector128<float> hash_abcd, Vector128<float> hash_efgh, Vector128<float> wk)
- {
- return SHA256hash(hash_abcd, hash_efgh, wk, true);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> HashUpper(Vector128<float> hash_efgh, Vector128<float> hash_abcd, Vector128<float> wk)
- {
- return SHA256hash(hash_abcd, hash_efgh, wk, false);
- }
-
- public static Vector128<float> Sha256SchedulePart1(Vector128<float> w0_3, Vector128<float> w4_7)
- {
- Vector128<float> result = new Vector128<float>();
-
- for (int e = 0; e <= 3; e++)
- {
- uint elt = (uint)VectorExtractIntZx(e <= 2 ? w0_3 : w4_7, (byte)(e <= 2 ? e + 1 : 0), 2);
-
- elt = elt.Ror(7) ^ elt.Ror(18) ^ elt.Lsr(3);
-
- elt += (uint)VectorExtractIntZx(w0_3, (byte)e, 2);
-
- result = VectorInsertInt((ulong)elt, result, (byte)e, 2);
- }
-
- return result;
- }
-
- public static Vector128<float> Sha256SchedulePart2(Vector128<float> w0_3, Vector128<float> w8_11, Vector128<float> w12_15)
- {
- Vector128<float> result = new Vector128<float>();
-
- ulong T1 = VectorExtractIntZx(w12_15, (byte)1, 3);
-
- for (int e = 0; e <= 1; e++)
- {
- uint elt = T1.ULongPart(e);
-
- elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
-
- elt += (uint)VectorExtractIntZx(w0_3, (byte)e, 2);
- elt += (uint)VectorExtractIntZx(w8_11, (byte)(e + 1), 2);
-
- result = VectorInsertInt((ulong)elt, result, (byte)e, 2);
- }
-
- T1 = VectorExtractIntZx(result, (byte)0, 3);
-
- for (int e = 2; e <= 3; e++)
- {
- uint elt = T1.ULongPart(e - 2);
-
- elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
-
- elt += (uint)VectorExtractIntZx(w0_3, (byte)e, 2);
- elt += (uint)VectorExtractIntZx(e == 2 ? w8_11 : w12_15, (byte)(e == 2 ? 3 : 0), 2);
-
- result = VectorInsertInt((ulong)elt, result, (byte)e, 2);
- }
-
- return result;
- }
-
- private static Vector128<float> SHA256hash(Vector128<float> X, Vector128<float> Y, Vector128<float> W, bool part1)
- {
- for (int e = 0; e <= 3; e++)
- {
- uint chs = SHAchoose((uint)VectorExtractIntZx(Y, (byte)0, 2),
- (uint)VectorExtractIntZx(Y, (byte)1, 2),
- (uint)VectorExtractIntZx(Y, (byte)2, 2));
-
- uint maj = SHAmajority((uint)VectorExtractIntZx(X, (byte)0, 2),
- (uint)VectorExtractIntZx(X, (byte)1, 2),
- (uint)VectorExtractIntZx(X, (byte)2, 2));
-
- uint t1 = (uint)VectorExtractIntZx(Y, (byte)3, 2);
- t1 += SHAhashSIGMA1((uint)VectorExtractIntZx(Y, (byte)0, 2)) + chs;
- t1 += (uint)VectorExtractIntZx(W, (byte)e, 2);
-
- uint t2 = t1 + (uint)VectorExtractIntZx(X, (byte)3, 2);
- X = VectorInsertInt((ulong)t2, X, (byte)3, 2);
- t2 = t1 + SHAhashSIGMA0((uint)VectorExtractIntZx(X, (byte)0, 2)) + maj;
- Y = VectorInsertInt((ulong)t2, Y, (byte)3, 2);
-
- Rol32_256(ref Y, ref X);
- }
-
- return part1 ? X : Y;
- }
-
- private static void Rol32_256(ref Vector128<float> Y, ref Vector128<float> X)
- {
- if (!Sse2.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- uint yE3 = (uint)VectorExtractIntZx(Y, (byte)3, 2);
- uint xE3 = (uint)VectorExtractIntZx(X, (byte)3, 2);
-
- Y = Sse.StaticCast<uint, float>(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast<float, uint>(Y), (byte)4));
- X = Sse.StaticCast<uint, float>(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast<float, uint>(X), (byte)4));
-
- Y = VectorInsertInt((ulong)xE3, Y, (byte)0, 2);
- X = VectorInsertInt((ulong)yE3, X, (byte)0, 2);
- }
-
- private static uint SHAhashSIGMA0(uint x)
- {
- return x.Ror(2) ^ x.Ror(13) ^ x.Ror(22);
- }
-
- private static uint SHAhashSIGMA1(uint x)
- {
- return x.Ror(6) ^ x.Ror(11) ^ x.Ror(25);
- }
-
- private static uint Ror(this uint value, int count)
- {
- return (value >> count) | (value << (32 - count));
- }
-
- private static uint Lsr(this uint value, int count)
- {
- return value >> count;
- }
-
- private static uint ULongPart(this ulong value, int part)
- {
- return part == 0
- ? (uint)(value & 0xFFFFFFFFUL)
- : (uint)(value >> 32);
- }
-#endregion
-
-#region "Reverse"
- public static uint ReverseBits8(uint Value)
- {
- Value = ((Value & 0xaa) >> 1) | ((Value & 0x55) << 1);
- Value = ((Value & 0xcc) >> 2) | ((Value & 0x33) << 2);
-
- return (Value >> 4) | ((Value & 0x0f) << 4);
- }
-
- public static uint ReverseBits32(uint Value)
- {
- Value = ((Value & 0xaaaaaaaa) >> 1) | ((Value & 0x55555555) << 1);
- Value = ((Value & 0xcccccccc) >> 2) | ((Value & 0x33333333) << 2);
- Value = ((Value & 0xf0f0f0f0) >> 4) | ((Value & 0x0f0f0f0f) << 4);
- Value = ((Value & 0xff00ff00) >> 8) | ((Value & 0x00ff00ff) << 8);
-
- return (Value >> 16) | (Value << 16);
- }
-
- public static ulong ReverseBits64(ulong Value)
- {
- Value = ((Value & 0xaaaaaaaaaaaaaaaa) >> 1 ) | ((Value & 0x5555555555555555) << 1 );
- Value = ((Value & 0xcccccccccccccccc) >> 2 ) | ((Value & 0x3333333333333333) << 2 );
- Value = ((Value & 0xf0f0f0f0f0f0f0f0) >> 4 ) | ((Value & 0x0f0f0f0f0f0f0f0f) << 4 );
- Value = ((Value & 0xff00ff00ff00ff00) >> 8 ) | ((Value & 0x00ff00ff00ff00ff) << 8 );
- Value = ((Value & 0xffff0000ffff0000) >> 16) | ((Value & 0x0000ffff0000ffff) << 16);
-
- return (Value >> 32) | (Value << 32);
- }
-
- public static uint ReverseBytes16_32(uint Value) => (uint)ReverseBytes16_64(Value);
- public static uint ReverseBytes32_32(uint Value) => (uint)ReverseBytes32_64(Value);
-
- public static ulong ReverseBytes16_64(ulong Value) => ReverseBytes(Value, RevSize.Rev16);
- public static ulong ReverseBytes32_64(ulong Value) => ReverseBytes(Value, RevSize.Rev32);
- public static ulong ReverseBytes64(ulong Value) => ReverseBytes(Value, RevSize.Rev64);
-
- private enum RevSize
- {
- Rev16,
- Rev32,
- Rev64
- }
-
- private static ulong ReverseBytes(ulong Value, RevSize Size)
- {
- Value = ((Value & 0xff00ff00ff00ff00) >> 8) | ((Value & 0x00ff00ff00ff00ff) << 8);
-
- if (Size == RevSize.Rev16)
- {
- return Value;
- }
-
- Value = ((Value & 0xffff0000ffff0000) >> 16) | ((Value & 0x0000ffff0000ffff) << 16);
-
- if (Size == RevSize.Rev32)
- {
- return Value;
- }
-
- Value = ((Value & 0xffffffff00000000) >> 32) | ((Value & 0x00000000ffffffff) << 32);
-
- if (Size == RevSize.Rev64)
- {
- return Value;
- }
-
- throw new ArgumentException(nameof(Size));
- }
-#endregion
-
-#region "MultiplyHigh"
- public static long SMulHi128(long Left, long Right)
- {
- long Result = (long)UMulHi128((ulong)Left, (ulong)Right);
-
- if (Left < 0)
- {
- Result -= Right;
- }
-
- if (Right < 0)
- {
- Result -= Left;
- }
-
- return Result;
- }
-
- public static ulong UMulHi128(ulong Left, ulong Right)
- {
- ulong LHigh = Left >> 32;
- ulong LLow = Left & 0xFFFFFFFF;
- ulong RHigh = Right >> 32;
- ulong RLow = Right & 0xFFFFFFFF;
-
- ulong Z2 = LLow * RLow;
- ulong T = LHigh * RLow + (Z2 >> 32);
- ulong Z1 = T & 0xFFFFFFFF;
- ulong Z0 = T >> 32;
-
- Z1 += LLow * RHigh;
-
- return LHigh * RHigh + Z0 + (Z1 >> 32);
- }
-#endregion
- }
-}
diff --git a/ChocolArm64/Instruction/ASoftFloat.cs b/ChocolArm64/Instruction/ASoftFloat.cs
deleted file mode 100644
index 0912257a..00000000
--- a/ChocolArm64/Instruction/ASoftFloat.cs
+++ /dev/null
@@ -1,2127 +0,0 @@
-using ChocolArm64.State;
-using System;
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-
-namespace ChocolArm64.Instruction
-{
- static class ASoftFloat
- {
- static ASoftFloat()
- {
- RecipEstimateTable = BuildRecipEstimateTable();
- InvSqrtEstimateTable = BuildInvSqrtEstimateTable();
- }
-
- private static readonly byte[] RecipEstimateTable;
- private static readonly byte[] InvSqrtEstimateTable;
-
- private static byte[] BuildRecipEstimateTable()
- {
- byte[] Table = new byte[256];
- for (ulong index = 0; index < 256; index++)
- {
- ulong a = index | 0x100;
-
- a = (a << 1) + 1;
- ulong b = 0x80000 / a;
- b = (b + 1) >> 1;
-
- Table[index] = (byte)(b & 0xFF);
- }
- return Table;
- }
-
- private static byte[] BuildInvSqrtEstimateTable()
- {
- byte[] Table = new byte[512];
- for (ulong index = 128; index < 512; index++)
- {
- ulong a = index;
- if (a < 256)
- {
- a = (a << 1) + 1;
- }
- else
- {
- a = (a | 1) << 1;
- }
-
- ulong b = 256;
- while (a * (b + 1) * (b + 1) < (1ul << 28))
- {
- b++;
- }
- b = (b + 1) >> 1;
-
- Table[index] = (byte)(b & 0xFF);
- }
- return Table;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static float RecipEstimate(float x)
- {
- return (float)RecipEstimate((double)x);
- }
-
- public static double RecipEstimate(double x)
- {
- ulong x_bits = (ulong)BitConverter.DoubleToInt64Bits(x);
- ulong x_sign = x_bits & 0x8000000000000000;
- ulong x_exp = (x_bits >> 52) & 0x7FF;
- ulong scaled = x_bits & ((1ul << 52) - 1);
-
- if (x_exp >= 2045)
- {
- if (x_exp == 0x7ff && scaled != 0)
- {
- // NaN
- return BitConverter.Int64BitsToDouble((long)(x_bits | 0x0008000000000000));
- }
-
- // Infinity, or Out of range -> Zero
- return BitConverter.Int64BitsToDouble((long)x_sign);
- }
-
- if (x_exp == 0)
- {
- if (scaled == 0)
- {
- // Zero -> Infinity
- return BitConverter.Int64BitsToDouble((long)(x_sign | 0x7FF0000000000000));
- }
-
- // Denormal
- if ((scaled & (1ul << 51)) == 0)
- {
- x_exp = ~0ul;
- scaled <<= 2;
- }
- else
- {
- scaled <<= 1;
- }
- }
-
- scaled >>= 44;
- scaled &= 0xFF;
-
- ulong result_exp = (2045 - x_exp) & 0x7FF;
- ulong estimate = (ulong)RecipEstimateTable[scaled];
- ulong fraction = estimate << 44;
-
- if (result_exp == 0)
- {
- fraction >>= 1;
- fraction |= 1ul << 51;
- }
- else if (result_exp == 0x7FF)
- {
- result_exp = 0;
- fraction >>= 2;
- fraction |= 1ul << 50;
- }
-
- ulong result = x_sign | (result_exp << 52) | fraction;
- return BitConverter.Int64BitsToDouble((long)result);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static float InvSqrtEstimate(float x)
- {
- return (float)InvSqrtEstimate((double)x);
- }
-
- public static double InvSqrtEstimate(double x)
- {
- ulong x_bits = (ulong)BitConverter.DoubleToInt64Bits(x);
- ulong x_sign = x_bits & 0x8000000000000000;
- long x_exp = (long)((x_bits >> 52) & 0x7FF);
- ulong scaled = x_bits & ((1ul << 52) - 1);
-
- if (x_exp == 0x7FF && scaled != 0)
- {
- // NaN
- return BitConverter.Int64BitsToDouble((long)(x_bits | 0x0008000000000000));
- }
-
- if (x_exp == 0)
- {
- if (scaled == 0)
- {
- // Zero -> Infinity
- return BitConverter.Int64BitsToDouble((long)(x_sign | 0x7FF0000000000000));
- }
-
- // Denormal
- while ((scaled & (1 << 51)) == 0)
- {
- scaled <<= 1;
- x_exp--;
- }
- scaled <<= 1;
- }
-
- if (x_sign != 0)
- {
- // Negative -> NaN
- return BitConverter.Int64BitsToDouble((long)0x7FF8000000000000);
- }
-
- if (x_exp == 0x7ff && scaled == 0)
- {
- // Infinity -> Zero
- return BitConverter.Int64BitsToDouble((long)x_sign);
- }
-
- if (((ulong)x_exp & 1) == 1)
- {
- scaled >>= 45;
- scaled &= 0xFF;
- scaled |= 0x80;
- }
- else
- {
- scaled >>= 44;
- scaled &= 0xFF;
- scaled |= 0x100;
- }
-
- ulong result_exp = ((ulong)(3068 - x_exp) / 2) & 0x7FF;
- ulong estimate = (ulong)InvSqrtEstimateTable[scaled];
- ulong fraction = estimate << 44;
-
- ulong result = x_sign | (result_exp << 52) | fraction;
- return BitConverter.Int64BitsToDouble((long)result);
- }
- }
-
- static class ASoftFloat16_32
- {
- public static float FPConvert(ushort ValueBits, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat16_32.FPConvert: State.Fpcr = 0x{State.Fpcr: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, AThreadState 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, AThreadState 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 ARoundMode.ToNearest:
- RoundUp = (Error > 0.5d || (Error == 0.5d && (IntMant & 1u) == 1u));
- OverflowToInf = true;
- break;
-
- case ARoundMode.TowardsPlusInfinity:
- RoundUp = (Error != 0d && !Sign);
- OverflowToInf = !Sign;
- break;
-
- case ARoundMode.TowardsMinusInfinity:
- RoundUp = (Error != 0d && Sign);
- OverflowToInf = Sign;
- break;
-
- case ARoundMode.TowardsZero:
- RoundUp = false;
- OverflowToInf = false;
- break;
- }
-
- if (RoundUp)
- {
- IntMant++;
-
- if (IntMant == (uint)Math.Pow(2d, F))
- {
- BiasedExp = 1u;
- }
-
- if (IntMant == (uint)Math.Pow(2d, F + 1))
- {
- BiasedExp++;
- IntMant >>= 1;
- }
- }
-
- float Result;
-
- if (BiasedExp >= (uint)Math.Pow(2d, 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, AThreadState State)
- {
- int Enable = (int)Exc + 8;
-
- if ((State.Fpcr & (1 << Enable)) != 0)
- {
- throw new NotImplementedException("floating-point trap handling");
- }
- else
- {
- State.Fpsr |= 1 << (int)Exc;
- }
- }
- }
-
- static class ASoftFloat32_16
- {
- public static ushort FPConvert(float Value, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat32_16.FPConvert: State.Fpcr = 0x{State.Fpcr:X8}");
-
- double Real = Value.FPUnpackCV(out FPType Type, out bool Sign, State, out uint ValueBits);
-
- 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, AThreadState State, out uint ValueBits)
- {
- 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, AThreadState 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 ARoundMode.ToNearest:
- RoundUp = (Error > 0.5d || (Error == 0.5d && (IntMant & 1u) == 1u));
- OverflowToInf = true;
- break;
-
- case ARoundMode.TowardsPlusInfinity:
- RoundUp = (Error != 0d && !Sign);
- OverflowToInf = !Sign;
- break;
-
- case ARoundMode.TowardsMinusInfinity:
- RoundUp = (Error != 0d && Sign);
- OverflowToInf = Sign;
- break;
-
- case ARoundMode.TowardsZero:
- RoundUp = false;
- OverflowToInf = false;
- break;
- }
-
- if (RoundUp)
- {
- IntMant++;
-
- if (IntMant == (uint)Math.Pow(2d, F))
- {
- BiasedExp = 1u;
- }
-
- if (IntMant == (uint)Math.Pow(2d, F + 1))
- {
- BiasedExp++;
- IntMant >>= 1;
- }
- }
-
- ushort ResultBits;
-
- if (!State.GetFpcrFlag(FPCR.AHP))
- {
- if (BiasedExp >= (uint)Math.Pow(2d, 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 >= (uint)Math.Pow(2d, 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, AThreadState State)
- {
- int Enable = (int)Exc + 8;
-
- if ((State.Fpcr & (1 << Enable)) != 0)
- {
- throw new NotImplementedException("floating-point trap handling");
- }
- else
- {
- State.Fpsr |= 1 << (int)Exc;
- }
- }
- }
-
- static class ASoftFloat_32
- {
- public static float FPAdd(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPAdd: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
-
- return Result;
- }
-
- public static float FPDiv(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPDiv: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
-
- return Result;
- }
-
- public static float FPMax(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPMax: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
- }
-
- return Result;
- }
-
- public static float FPMaxNum(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteIf(State.Fpcr != 0, "ASoftFloat_32.FPMaxNum: ");
-
- Value1.FPUnpack(out FPType Type1, out _, out _);
- Value2.FPUnpack(out FPType Type2, out _, out _);
-
- 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, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPMin: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
- }
-
- return Result;
- }
-
- public static float FPMinNum(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteIf(State.Fpcr != 0, "ASoftFloat_32.FPMinNum: ");
-
- Value1.FPUnpack(out FPType Type1, out _, out _);
- Value2.FPUnpack(out FPType Type2, out _, out _);
-
- 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, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPMul: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
-
- return Result;
- }
-
- public static float FPMulAdd(float ValueA, float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPMulAdd: State.Fpcr = 0x{State.Fpcr:X8}");
-
- ValueA = ValueA.FPUnpack(out FPType TypeA, out bool SignA, out uint Addend);
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- 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, State, out bool Done);
-
- 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);
- }
- }
-
- return Result;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static float FPMulSub(float ValueA, float Value1, float Value2, AThreadState State)
- {
- Debug.WriteIf(State.Fpcr != 0, "ASoftFloat_32.FPMulSub: ");
-
- Value1 = Value1.FPNeg();
-
- return FPMulAdd(ValueA, Value1, Value2, State);
- }
-
- public static float FPMulX(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPMulX: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
-
- return Result;
- }
-
- public static float FPRecipStepFused(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPRecipStepFused: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPNeg();
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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);
- }
- }
-
- return Result;
- }
-
- public static float FPRecpX(float Value, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPRecpX: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value.FPUnpack(out FPType Type, out bool Sign, out uint Op);
-
- 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 FPRSqrtStepFused(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPRSqrtStepFused: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPNeg();
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
-
- return Result;
- }
-
- public static float FPSqrt(float Value, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPSqrt: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value = Value.FPUnpack(out FPType Type, out bool Sign, out uint Op);
-
- 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);
- }
-
- return Result;
- }
-
- public static float FPSub(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPSub: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
-
- 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 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 FPUnpack(this float Value, out FPType Type, out bool Sign, out uint ValueBits)
- {
- ValueBits = (uint)BitConverter.SingleToInt32Bits(Value);
-
- Sign = (~ValueBits & 0x80000000u) == 0u;
-
- if ((ValueBits & 0x7F800000u) == 0u)
- {
- if ((ValueBits & 0x007FFFFFu) == 0u)
- {
- Type = FPType.Zero;
- }
- 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;
-
- return FPZero(Sign);
- }
- }
- else
- {
- Type = FPType.Nonzero;
- }
-
- return Value;
- }
-
- private static float FPProcessNaNs(
- FPType Type1,
- FPType Type2,
- uint Op1,
- uint Op2,
- AThreadState State,
- out bool Done)
- {
- 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,
- AThreadState State,
- out bool Done)
- {
- 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, AThreadState 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, AThreadState State)
- {
- int Enable = (int)Exc + 8;
-
- if ((State.Fpcr & (1 << Enable)) != 0)
- {
- throw new NotImplementedException("floating-point trap handling");
- }
- else
- {
- State.Fpsr |= 1 << (int)Exc;
- }
- }
- }
-
- static class ASoftFloat_64
- {
- public static double FPAdd(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPAdd: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
-
- return Result;
- }
-
- public static double FPDiv(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPDiv: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
-
- return Result;
- }
-
- public static double FPMax(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPMax: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
- }
-
- return Result;
- }
-
- public static double FPMaxNum(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteIf(State.Fpcr != 0, "ASoftFloat_64.FPMaxNum: ");
-
- Value1.FPUnpack(out FPType Type1, out _, out _);
- Value2.FPUnpack(out FPType Type2, out _, out _);
-
- 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, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPMin: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
- }
-
- return Result;
- }
-
- public static double FPMinNum(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteIf(State.Fpcr != 0, "ASoftFloat_64.FPMinNum: ");
-
- Value1.FPUnpack(out FPType Type1, out _, out _);
- Value2.FPUnpack(out FPType Type2, out _, out _);
-
- 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, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPMul: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
-
- return Result;
- }
-
- public static double FPMulAdd(double ValueA, double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPMulAdd: State.Fpcr = 0x{State.Fpcr:X8}");
-
- ValueA = ValueA.FPUnpack(out FPType TypeA, out bool SignA, out ulong Addend);
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- 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, State, out bool Done);
-
- 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);
- }
- }
-
- return Result;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static double FPMulSub(double ValueA, double Value1, double Value2, AThreadState State)
- {
- Debug.WriteIf(State.Fpcr != 0, "ASoftFloat_64.FPMulSub: ");
-
- Value1 = Value1.FPNeg();
-
- return FPMulAdd(ValueA, Value1, Value2, State);
- }
-
- public static double FPMulX(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPMulX: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
-
- return Result;
- }
-
- public static double FPRecipStepFused(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPRecipStepFused: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPNeg();
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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);
- }
- }
-
- return Result;
- }
-
- public static double FPRecpX(double Value, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPRecpX: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value.FPUnpack(out FPType Type, out bool Sign, out ulong Op);
-
- 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 FPRSqrtStepFused(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPRSqrtStepFused: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPNeg();
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
-
- return Result;
- }
-
- public static double FPSqrt(double Value, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPSqrt: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value = Value.FPUnpack(out FPType Type, out bool Sign, out ulong Op);
-
- 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);
- }
-
- return Result;
- }
-
- public static double FPSub(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPSub: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- 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;
- }
- }
-
- 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 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 FPUnpack(this double Value, out FPType Type, out bool Sign, out ulong ValueBits)
- {
- ValueBits = (ulong)BitConverter.DoubleToInt64Bits(Value);
-
- Sign = (~ValueBits & 0x8000000000000000ul) == 0ul;
-
- if ((ValueBits & 0x7FF0000000000000ul) == 0ul)
- {
- if ((ValueBits & 0x000FFFFFFFFFFFFFul) == 0ul)
- {
- Type = FPType.Zero;
- }
- 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;
-
- return FPZero(Sign);
- }
- }
- else
- {
- Type = FPType.Nonzero;
- }
-
- return Value;
- }
-
- private static double FPProcessNaNs(
- FPType Type1,
- FPType Type2,
- ulong Op1,
- ulong Op2,
- AThreadState State,
- out bool Done)
- {
- 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,
- AThreadState State,
- out bool Done)
- {
- 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, AThreadState 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, AThreadState State)
- {
- int Enable = (int)Exc + 8;
-
- if ((State.Fpcr & (1 << Enable)) != 0)
- {
- throw new NotImplementedException("floating-point trap handling");
- }
- else
- {
- State.Fpsr |= 1 << (int)Exc;
- }
- }
- }
-}
diff --git a/ChocolArm64/Instruction32/A32InstInterpretFlow.cs b/ChocolArm64/Instruction32/A32InstInterpretFlow.cs
deleted file mode 100644
index 223fd186..00000000
--- a/ChocolArm64/Instruction32/A32InstInterpretFlow.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Decoder32;
-using ChocolArm64.Memory;
-using ChocolArm64.State;
-
-using static ChocolArm64.Instruction32.A32InstInterpretHelper;
-
-namespace ChocolArm64.Instruction32
-{
- static partial class A32InstInterpret
- {
- public static void B(AThreadState State, AMemory Memory, AOpCode OpCode)
- {
- A32OpCodeBImmAl Op = (A32OpCodeBImmAl)OpCode;
-
- if (IsConditionTrue(State, Op.Cond))
- {
- BranchWritePc(State, GetPc(State) + (uint)Op.Imm);
- }
- }
-
- public static void Bl(AThreadState State, AMemory Memory, AOpCode OpCode)
- {
- Blx(State, Memory, OpCode, false);
- }
-
- public static void Blx(AThreadState State, AMemory Memory, AOpCode OpCode)
- {
- Blx(State, Memory, OpCode, true);
- }
-
- public static void Blx(AThreadState State, AMemory Memory, AOpCode OpCode, bool X)
- {
- A32OpCodeBImmAl Op = (A32OpCodeBImmAl)OpCode;
-
- if (IsConditionTrue(State, Op.Cond))
- {
- uint Pc = GetPc(State);
-
- if (State.Thumb)
- {
- State.R14 = Pc | 1;
- }
- else
- {
- State.R14 = Pc - 4U;
- }
-
- if (X)
- {
- State.Thumb = !State.Thumb;
- }
-
- if (!State.Thumb)
- {
- Pc &= ~3U;
- }
-
- BranchWritePc(State, Pc + (uint)Op.Imm);
- }
- }
-
- private static void BranchWritePc(AThreadState State, uint Pc)
- {
- State.R15 = State.Thumb
- ? Pc & ~1U
- : Pc & ~3U;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction32/A32InstInterpretHelper.cs b/ChocolArm64/Instruction32/A32InstInterpretHelper.cs
deleted file mode 100644
index 9c3c098e..00000000
--- a/ChocolArm64/Instruction32/A32InstInterpretHelper.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using System;
-
-namespace ChocolArm64.Instruction32
-{
- static class A32InstInterpretHelper
- {
- public static bool IsConditionTrue(AThreadState State, ACond Cond)
- {
- switch (Cond)
- {
- case ACond.Eq: return State.Zero;
- case ACond.Ne: return !State.Zero;
- case ACond.Ge_Un: return State.Carry;
- case ACond.Lt_Un: return !State.Carry;
- case ACond.Mi: return State.Negative;
- case ACond.Pl: return !State.Negative;
- case ACond.Vs: return State.Overflow;
- case ACond.Vc: return !State.Overflow;
- case ACond.Gt_Un: return State.Carry && !State.Zero;
- case ACond.Le_Un: return !State.Carry && State.Zero;
- case ACond.Ge: return State.Negative == State.Overflow;
- case ACond.Lt: return State.Negative != State.Overflow;
- case ACond.Gt: return State.Negative == State.Overflow && !State.Zero;
- case ACond.Le: return State.Negative != State.Overflow && State.Zero;
- }
-
- return true;
- }
-
- public unsafe static uint GetReg(AThreadState State, int Reg)
- {
- if ((uint)Reg > 15)
- {
- throw new ArgumentOutOfRangeException(nameof(Reg));
- }
-
- fixed (uint* Ptr = &State.R0)
- {
- return *(Ptr + Reg);
- }
- }
-
- public unsafe static void SetReg(AThreadState State, int Reg, uint Value)
- {
- if ((uint)Reg > 15)
- {
- throw new ArgumentOutOfRangeException(nameof(Reg));
- }
-
- fixed (uint* Ptr = &State.R0)
- {
- *(Ptr + Reg) = Value;
- }
- }
-
- public static uint GetPc(AThreadState State)
- {
- //Due to the old fetch-decode-execute pipeline of old ARM CPUs,
- //the PC is 4 or 8 bytes (2 instructions) ahead of the current instruction.
- return State.R15 + (State.Thumb ? 2U : 4U);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/ACryptoHelper.cs b/ChocolArm64/Instructions/CryptoHelper.cs
index 2dc65972..bb9a22a3 100644
--- a/ChocolArm64/Instruction/ACryptoHelper.cs
+++ b/ChocolArm64/Instructions/CryptoHelper.cs
@@ -4,12 +4,12 @@ using System;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
-namespace ChocolArm64.Instruction
+namespace ChocolArm64.Instructions
{
- static class ACryptoHelper
+ static class CryptoHelper
{
#region "LookUp Tables"
- private static byte[] SBox =
+ private static byte[] _sBox =
{
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,
@@ -29,7 +29,7 @@ namespace ChocolArm64.Instruction
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
- private static byte[] InvSBox =
+ private static byte[] _invSBox =
{
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,
@@ -49,7 +49,7 @@ namespace ChocolArm64.Instruction
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};
- private static byte[] GFMul_02 =
+ private static byte[] _gfMul02 =
{
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,
@@ -69,7 +69,7 @@ namespace ChocolArm64.Instruction
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
};
- private static byte[] GFMul_03 =
+ private static byte[] _gfMul03 =
{
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,
@@ -89,7 +89,7 @@ namespace ChocolArm64.Instruction
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
};
- private static byte[] GFMul_09 =
+ private static byte[] _gfMul09 =
{
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,
@@ -109,7 +109,7 @@ namespace ChocolArm64.Instruction
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
};
- private static byte[] GFMul_0B =
+ private static byte[] _gfMul0B =
{
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,
@@ -129,7 +129,7 @@ namespace ChocolArm64.Instruction
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
};
- private static byte[] GFMul_0D =
+ private static byte[] _gfMul0D =
{
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,
@@ -149,7 +149,7 @@ namespace ChocolArm64.Instruction
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
};
- private static byte[] GFMul_0E =
+ private static byte[] _gfMul0E =
{
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,
@@ -169,149 +169,149 @@ namespace ChocolArm64.Instruction
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
};
- private static byte[] SRPerm = { 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3 };
+ private static byte[] _srPerm = { 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3 };
- private static byte[] ISRPerm = { 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11 };
+ private static byte[] _isrPerm = { 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11 };
#endregion
- public static Vector128<float> AESInvMixColumns(Vector128<float> op)
+ public static Vector128<float> AesInvMixColumns(Vector128<float> op)
{
- byte[] InState = new byte[16];
- byte[] OutState = new byte[16];
+ byte[] inState = new byte[16];
+ byte[] outState = new byte[16];
- FromVectorToByteArray(InState, ref op);
+ FromVectorToByteArray(inState, ref op);
- for (int Columns = 0; Columns <= 3; Columns++)
+ for (int columns = 0; columns <= 3; columns++)
{
- int Idx = Columns << 2;
+ 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]
+ 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)GFMul_0E[Row0] ^ GFMul_0B[Row1] ^ GFMul_0D[Row2] ^ GFMul_09[Row3]);
- OutState[Idx + 1] = (byte)((uint)GFMul_09[Row0] ^ GFMul_0E[Row1] ^ GFMul_0B[Row2] ^ GFMul_0D[Row3]);
- OutState[Idx + 2] = (byte)((uint)GFMul_0D[Row0] ^ GFMul_09[Row1] ^ GFMul_0E[Row2] ^ GFMul_0B[Row3]);
- OutState[Idx + 3] = (byte)((uint)GFMul_0B[Row0] ^ GFMul_0D[Row1] ^ GFMul_09[Row2] ^ GFMul_0E[Row3]);
+ 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);
+ FromByteArrayToVector(outState, ref op);
return op;
}
- public static Vector128<float> AESInvShiftRows(Vector128<float> op)
+ public static Vector128<float> AesInvShiftRows(Vector128<float> op)
{
- byte[] InState = new byte[16];
- byte[] OutState = new byte[16];
+ byte[] inState = new byte[16];
+ byte[] outState = new byte[16];
- FromVectorToByteArray(InState, ref op);
+ FromVectorToByteArray(inState, ref op);
- for (int Idx = 0; Idx <= 15; Idx++)
+ for (int idx = 0; idx <= 15; idx++)
{
- OutState[ISRPerm[Idx]] = InState[Idx];
+ outState[_isrPerm[idx]] = inState[idx];
}
- FromByteArrayToVector(OutState, ref op);
+ FromByteArrayToVector(outState, ref op);
return op;
}
- public static Vector128<float> AESInvSubBytes(Vector128<float> op)
+ public static Vector128<float> AesInvSubBytes(Vector128<float> op)
{
- byte[] InState = new byte[16];
- byte[] OutState = new byte[16];
+ byte[] inState = new byte[16];
+ byte[] outState = new byte[16];
- FromVectorToByteArray(InState, ref op);
+ FromVectorToByteArray(inState, ref op);
- for (int Idx = 0; Idx <= 15; Idx++)
+ for (int idx = 0; idx <= 15; idx++)
{
- OutState[Idx] = InvSBox[InState[Idx]];
+ outState[idx] = _invSBox[inState[idx]];
}
- FromByteArrayToVector(OutState, ref op);
+ FromByteArrayToVector(outState, ref op);
return op;
}
- public static Vector128<float> AESMixColumns(Vector128<float> op)
+ public static Vector128<float> AesMixColumns(Vector128<float> op)
{
- byte[] InState = new byte[16];
- byte[] OutState = new byte[16];
+ byte[] inState = new byte[16];
+ byte[] outState = new byte[16];
- FromVectorToByteArray(InState, ref op);
+ FromVectorToByteArray(inState, ref op);
- for (int Columns = 0; Columns <= 3; Columns++)
+ for (int columns = 0; columns <= 3; columns++)
{
- int Idx = Columns << 2;
+ 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]
+ 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)GFMul_02[Row0] ^ GFMul_03[Row1] ^ Row2 ^ Row3);
- OutState[Idx + 1] = (byte)((uint)Row0 ^ GFMul_02[Row1] ^ GFMul_03[Row2] ^ Row3);
- OutState[Idx + 2] = (byte)((uint)Row0 ^ Row1 ^ GFMul_02[Row2] ^ GFMul_03[Row3]);
- OutState[Idx + 3] = (byte)((uint)GFMul_03[Row0] ^ Row1 ^ Row2 ^ GFMul_02[Row3]);
+ 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);
+ FromByteArrayToVector(outState, ref op);
return op;
}
- public static Vector128<float> AESShiftRows(Vector128<float> op)
+ public static Vector128<float> AesShiftRows(Vector128<float> op)
{
- byte[] InState = new byte[16];
- byte[] OutState = new byte[16];
+ byte[] inState = new byte[16];
+ byte[] outState = new byte[16];
- FromVectorToByteArray(InState, ref op);
+ FromVectorToByteArray(inState, ref op);
- for (int Idx = 0; Idx <= 15; Idx++)
+ for (int idx = 0; idx <= 15; idx++)
{
- OutState[SRPerm[Idx]] = InState[Idx];
+ outState[_srPerm[idx]] = inState[idx];
}
- FromByteArrayToVector(OutState, ref op);
+ FromByteArrayToVector(outState, ref op);
return op;
}
- public static Vector128<float> AESSubBytes(Vector128<float> op)
+ public static Vector128<float> AesSubBytes(Vector128<float> op)
{
- byte[] InState = new byte[16];
- byte[] OutState = new byte[16];
+ byte[] inState = new byte[16];
+ byte[] outState = new byte[16];
- FromVectorToByteArray(InState, ref op);
+ FromVectorToByteArray(inState, ref op);
- for (int Idx = 0; Idx <= 15; Idx++)
+ for (int idx = 0; idx <= 15; idx++)
{
- OutState[Idx] = SBox[InState[Idx]];
+ outState[idx] = _sBox[inState[idx]];
}
- FromByteArrayToVector(OutState, ref op);
+ FromByteArrayToVector(outState, ref op);
return op;
}
- private static void FromVectorToByteArray(byte[] State, ref Vector128<float> op)
+ private static void FromVectorToByteArray(byte[] state, ref Vector128<float> op)
{
- ulong ULongLow = AVectorHelper.VectorExtractIntZx((op), (byte)0, 3);
- ulong ULongHigh = AVectorHelper.VectorExtractIntZx((op), (byte)1, 3);
+ ulong uLongLow = VectorHelper.VectorExtractIntZx((op), (byte)0, 3);
+ ulong uLongHigh = VectorHelper.VectorExtractIntZx((op), (byte)1, 3);
- for (int Idx = 0; Idx <= 7; Idx++)
+ for (int idx = 0; idx <= 7; idx++)
{
- State[Idx + 0] = (byte)(ULongLow & 0xFFUL);
- State[Idx + 8] = (byte)(ULongHigh & 0xFFUL);
+ state[idx + 0] = (byte)(uLongLow & 0xFFUL);
+ state[idx + 8] = (byte)(uLongHigh & 0xFFUL);
- ULongLow >>= 8;
- ULongHigh >>= 8;
+ uLongLow >>= 8;
+ uLongHigh >>= 8;
}
}
- private static void FromByteArrayToVector(byte[] State, ref Vector128<float> op)
+ private static void FromByteArrayToVector(byte[] state, ref Vector128<float> op)
{
if (!Sse2.IsSupported)
{
@@ -319,10 +319,10 @@ namespace ChocolArm64.Instruction
}
op = Sse.StaticCast<byte, float>(Sse2.SetVector128(
- State[15], State[14], State[13], State[12],
- State[11], State[10], State[9], State[8],
- State[7], State[6], State[5], State[4],
- State[3], State[2], State[1], State[0]));
+ state[15], state[14], state[13], state[12],
+ state[11], state[10], state[9], state[8],
+ state[7], state[6], state[5], state[4],
+ state[3], state[2], state[1], state[0]));
}
}
}
diff --git a/ChocolArm64/Instructions/Inst.cs b/ChocolArm64/Instructions/Inst.cs
new file mode 100644
index 00000000..5f6740ca
--- /dev/null
+++ b/ChocolArm64/Instructions/Inst.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace ChocolArm64.Instructions
+{
+ struct Inst
+ {
+ public InstInterpreter Interpreter { get; private set; }
+ public InstEmitter Emitter { get; private set; }
+ public Type Type { get; private set; }
+
+ public static Inst Undefined => new Inst(null, InstEmit.Und, null);
+
+ public Inst(InstInterpreter interpreter, InstEmitter emitter, Type type)
+ {
+ Interpreter = interpreter;
+ Emitter = emitter;
+ Type = type;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Instructions/InstEmitAlu.cs b/ChocolArm64/Instructions/InstEmitAlu.cs
new file mode 100644
index 00000000..c0258ed2
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitAlu.cs
@@ -0,0 +1,402 @@
+using ChocolArm64.Decoders;
+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)
+ {
+ EmitDataLoadOpers(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);
+ }
+
+ EmitDataStore(context);
+ }
+
+ public static void Add(ILEmitterCtx context) => EmitDataOp(context, OpCodes.Add);
+
+ public static void Adds(ILEmitterCtx context)
+ {
+ EmitDataLoadOpers(context);
+
+ context.Emit(OpCodes.Add);
+
+ context.EmitZnFlagCheck();
+
+ EmitAddsCCheck(context);
+ EmitAddsVCheck(context);
+ EmitDataStoreS(context);
+ }
+
+ public static void And(ILEmitterCtx context) => EmitDataOp(context, OpCodes.And);
+
+ public static void Ands(ILEmitterCtx context)
+ {
+ EmitDataLoadOpers(context);
+
+ context.Emit(OpCodes.And);
+
+ EmitZeroCvFlags(context);
+
+ context.EmitZnFlagCheck();
+
+ EmitDataStoreS(context);
+ }
+
+ public static void Asrv(ILEmitterCtx context) => EmitDataOpShift(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)
+ {
+ EmitDataLoadOpers(context);
+
+ context.Emit(OpCodes.Not);
+ context.Emit(OpCodes.And);
+
+ if (setFlags)
+ {
+ EmitZeroCvFlags(context);
+
+ context.EmitZnFlagCheck();
+ }
+
+ EmitDataStore(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)
+ {
+ EmitDataLoadOpers(context);
+
+ context.Emit(OpCodes.Not);
+ context.Emit(OpCodes.Xor);
+
+ EmitDataStore(context);
+ }
+
+ public static void Eor(ILEmitterCtx context) => EmitDataOp(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);
+ }
+
+ EmitDataStore(context);
+ }
+
+ public static void Lslv(ILEmitterCtx context) => EmitDataOpShift(context, OpCodes.Shl);
+ public static void Lsrv(ILEmitterCtx context) => EmitDataOpShift(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)
+ {
+ EmitDataLoadOpers(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);
+ }
+
+ EmitDataStore(context);
+ }
+
+ public static void Sub(ILEmitterCtx context) => EmitDataOp(context, OpCodes.Sub);
+
+ public static void Subs(ILEmitterCtx context)
+ {
+ context.TryOptMarkCondWithoutCmp();
+
+ EmitDataLoadOpers(context);
+
+ context.Emit(OpCodes.Sub);
+
+ context.EmitZnFlagCheck();
+
+ EmitSubsCCheck(context);
+ EmitSubsVCheck(context);
+ EmitDataStoreS(context);
+ }
+
+ public static void Orn(ILEmitterCtx context)
+ {
+ EmitDataLoadOpers(context);
+
+ context.Emit(OpCodes.Not);
+ context.Emit(OpCodes.Or);
+
+ EmitDataStore(context);
+ }
+
+ public static void Orr(ILEmitterCtx context) => EmitDataOp(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)
+ {
+ EmitDataLoadRn(context);
+ EmitDataLoadShift(context);
+
+ context.Emit(OpCodes.Shr_Un);
+
+ EmitDataLoadRn(context);
+
+ context.EmitLdc_I4(context.CurrOp.GetBitsCount());
+
+ EmitDataLoadShift(context);
+
+ context.Emit(OpCodes.Sub);
+ context.Emit(OpCodes.Shl);
+ context.Emit(OpCodes.Or);
+
+ EmitDataStore(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);
+
+ EmitDataLoadRm(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);
+
+ EmitDataLoadRn(context);
+
+ context.EmitLdc_I(intMin);
+
+ context.Emit(OpCodes.Ceq);
+
+ EmitDataLoadRm(context);
+
+ context.EmitLdc_I(-1);
+
+ context.Emit(OpCodes.Ceq);
+ context.Emit(OpCodes.And);
+ context.Emit(OpCodes.Brtrue_S, badDiv);
+ context.Emit(OpCodes.Pop);
+ }
+
+ EmitDataLoadRn(context);
+ EmitDataLoadRm(context);
+
+ context.Emit(ilOp);
+
+ context.MarkLabel(badDiv);
+
+ EmitDataStore(context);
+ }
+
+ private static void EmitDataOp(ILEmitterCtx context, OpCode ilOp)
+ {
+ EmitDataLoadOpers(context);
+
+ context.Emit(ilOp);
+
+ EmitDataStore(context);
+ }
+
+ private static void EmitDataOpShift(ILEmitterCtx context, OpCode ilOp)
+ {
+ EmitDataLoadRn(context);
+ EmitDataLoadShift(context);
+
+ context.Emit(ilOp);
+
+ EmitDataStore(context);
+ }
+
+ private static void EmitDataLoadShift(ILEmitterCtx context)
+ {
+ EmitDataLoadRm(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);
+ }
+ }
+}
diff --git a/ChocolArm64/Instructions/InstEmitAluHelper.cs b/ChocolArm64/Instructions/InstEmitAluHelper.cs
new file mode 100644
index 00000000..613dd234
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitAluHelper.cs
@@ -0,0 +1,212 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.State;
+using ChocolArm64.Translation;
+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();
+
+ EmitDataLoadRn(context);
+
+ context.Emit(OpCodes.Ceq);
+
+ context.EmitLdflg((int)PState.CBit);
+
+ context.Emit(OpCodes.And);
+
+ context.EmitLdtmp();
+
+ EmitDataLoadRn(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);
+
+ EmitDataLoadRn(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);
+
+ EmitDataLoadRn(context);
+
+ context.Emit(OpCodes.Xor);
+
+ EmitDataLoadOpers(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
+ EmitDataLoadOpers(context);
+
+ context.Emit(OpCodes.Ceq);
+
+ context.EmitLdflg((int)PState.CBit);
+
+ context.Emit(OpCodes.And);
+
+ EmitDataLoadOpers(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)
+ EmitDataLoadOpers(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);
+
+ EmitDataLoadRn(context);
+
+ context.Emit(OpCodes.Xor);
+
+ EmitDataLoadOpers(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 EmitDataLoadRm(ILEmitterCtx context)
+ {
+ context.EmitLdintzr(((IOpCodeAluRs64)context.CurrOp).Rm);
+ }
+
+ public static void EmitDataLoadOpers(ILEmitterCtx context)
+ {
+ EmitDataLoadRn(context);
+ EmitDataLoadOper2(context);
+ }
+
+ public static void EmitDataLoadRn(ILEmitterCtx context)
+ {
+ IOpCodeAlu64 op = (IOpCodeAlu64)context.CurrOp;
+
+ if (op.DataOp == DataOp.Logical || op is IOpCodeAluRs64)
+ {
+ context.EmitLdintzr(op.Rn);
+ }
+ else
+ {
+ context.EmitLdint(op.Rn);
+ }
+ }
+
+ public static void EmitDataLoadOper2(ILEmitterCtx context)
+ {
+ switch (context.CurrOp)
+ {
+ 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;
+ }
+ }
+
+ public static void EmitDataStore(ILEmitterCtx context) => EmitDataStore(context, false);
+ public static void EmitDataStoreS(ILEmitterCtx context) => EmitDataStore(context, true);
+
+ public static void EmitDataStore(ILEmitterCtx context, bool setFlags)
+ {
+ IOpCodeAlu64 op = (IOpCodeAlu64)context.CurrOp;
+
+ if (setFlags || op is IOpCodeAluRs64)
+ {
+ context.EmitStintzr(op.Rd);
+ }
+ else
+ {
+ context.EmitStint(op.Rd);
+ }
+ }
+
+ public static void EmitSetNzcv(ILEmitterCtx context, int nzcv)
+ {
+ context.EmitLdc_I4((nzcv >> 0) & 1);
+
+ context.EmitStflg((int)PState.VBit);
+
+ context.EmitLdc_I4((nzcv >> 1) & 1);
+
+ context.EmitStflg((int)PState.CBit);
+
+ context.EmitLdc_I4((nzcv >> 2) & 1);
+
+ context.EmitStflg((int)PState.ZBit);
+
+ context.EmitLdc_I4((nzcv >> 3) & 1);
+
+ context.EmitStflg((int)PState.NBit);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Instructions/InstEmitBfm.cs b/ChocolArm64/Instructions/InstEmitBfm.cs
new file mode 100644
index 00000000..d25af8be
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitBfm.cs
@@ -0,0 +1,208 @@
+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;
+
+ EmitBfmLoadRn(context);
+
+ context.EmitLdintzr(op.Rd);
+ context.EmitLdc_I(~op.WMask & op.TMask);
+
+ context.Emit(OpCodes.And);
+ context.Emit(OpCodes.Or);
+
+ context.EmitLdintzr(op.Rd);
+ context.EmitLdc_I(~op.TMask);
+
+ 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
new file mode 100644
index 00000000..b91104c9
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitCcmp.cs
@@ -0,0 +1,81 @@
+using ChocolArm64.Decoders;
+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);
+
+ EmitDataLoadOpers(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
new file mode 100644
index 00000000..19b073ce
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitCsel.cs
@@ -0,0 +1,58 @@
+using ChocolArm64.Decoders;
+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
new file mode 100644
index 00000000..8325a397
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitException.cs
@@ -0,0 +1,86 @@
+using ChocolArm64.Decoders;
+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.EmitStoreState();
+
+ 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.EmitLoadState(context.CurrBlock.Next);
+ }
+ else
+ {
+ context.EmitLdc_I8(op.Position + 4);
+
+ context.Emit(OpCodes.Ret);
+ }
+ }
+
+ public static void Und(ILEmitterCtx context)
+ {
+ OpCode64 op = context.CurrOp;
+
+ context.EmitStoreState();
+
+ 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.EmitLoadState(context.CurrBlock.Next);
+ }
+ 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
new file mode 100644
index 00000000..7d0897cd
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitFlow.cs
@@ -0,0 +1,189 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.State;
+using ChocolArm64.Translation;
+using System.Reflection.Emit;
+
+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.EmitStoreState();
+ 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(CpuThreadState.LrIndex);
+ context.EmitStoreState();
+
+ if (context.TryOptEmitSubroutineCall())
+ {
+ //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.
+ context.Emit(OpCodes.Dup);
+
+ context.EmitLdc_I8(op.Position + 4);
+
+ ILLabel lblContinue = new ILLabel();
+
+ context.Emit(OpCodes.Beq_S, lblContinue);
+ context.Emit(OpCodes.Ret);
+
+ context.MarkLabel(lblContinue);
+
+ context.Emit(OpCodes.Pop);
+
+ context.EmitLoadState(context.CurrBlock.Next);
+ }
+ else
+ {
+ context.EmitLdc_I8(op.Imm);
+
+ context.Emit(OpCodes.Ret);
+ }
+ }
+
+ public static void Blr(ILEmitterCtx context)
+ {
+ OpCodeBReg64 op = (OpCodeBReg64)context.CurrOp;
+
+ context.EmitLdc_I(op.Position + 4);
+ context.EmitStint(CpuThreadState.LrIndex);
+ context.EmitStoreState();
+ context.EmitLdintzr(op.Rn);
+
+ context.Emit(OpCodes.Ret);
+ }
+
+ public static void Br(ILEmitterCtx context)
+ {
+ OpCodeBReg64 op = (OpCodeBReg64)context.CurrOp;
+
+ context.EmitStoreState();
+ context.EmitLdintzr(op.Rn);
+
+ context.Emit(OpCodes.Ret);
+ }
+
+ 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.EmitStoreState();
+ context.EmitLdint(CpuThreadState.LrIndex);
+
+ 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, Cond cond)
+ {
+ OpCodeBImm64 op = (OpCodeBImm64)context.CurrOp;
+
+ if (context.CurrBlock.Next != null &&
+ context.CurrBlock.Branch != null)
+ {
+ context.EmitCondBranch(context.GetLabel(op.Imm), cond);
+ }
+ else
+ {
+ context.EmitStoreState();
+
+ 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.Next != null &&
+ context.CurrBlock.Branch != null)
+ {
+ context.Emit(ilOp, context.GetLabel(op.Imm));
+ }
+ else
+ {
+ context.EmitStoreState();
+
+ 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/InstEmitHash.cs b/ChocolArm64/Instructions/InstEmitHash.cs
new file mode 100644
index 00000000..7e21a886
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitHash.cs
@@ -0,0 +1,115 @@
+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
new file mode 100644
index 00000000..96e45b3f
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitMemory.cs
@@ -0,0 +1,252 @@
+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;
+
+ context.EmitLdarg(TranslatedSub.MemoryArgIdx);
+
+ 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 LdrLit(ILEmitterCtx context)
+ {
+ IOpCodeLit64 op = (IOpCodeLit64)context.CurrOp;
+
+ if (op.Prefetch)
+ {
+ return;
+ }
+
+ context.EmitLdarg(TranslatedSub.MemoryArgIdx);
+ 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);
+ }
+ }
+
+ context.EmitLdarg(TranslatedSub.MemoryArgIdx);
+
+ EmitLoadAddress(context);
+
+ EmitReadAndStore(op.Rt);
+
+ context.EmitLdarg(TranslatedSub.MemoryArgIdx);
+ 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;
+
+ context.EmitLdarg(TranslatedSub.MemoryArgIdx);
+
+ 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;
+
+ context.EmitLdarg(TranslatedSub.MemoryArgIdx);
+
+ EmitLoadAddress(context);
+
+ if (op is IOpCodeSimd64)
+ {
+ context.EmitLdvec(op.Rt);
+ }
+ else
+ {
+ context.EmitLdintzr(op.Rt);
+ }
+
+ EmitWriteCall(context, op.Size);
+
+ context.EmitLdarg(TranslatedSub.MemoryArgIdx);
+ 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/InstEmitMemoryEx.cs b/ChocolArm64/Instructions/InstEmitMemoryEx.cs
new file mode 100644
index 00000000..42daca63
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitMemoryEx.cs
@@ -0,0 +1,192 @@
+using ChocolArm64.Decoders;
+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)
+ {
+ EmitMemoryCall(context, nameof(MemoryManager.ClearExclusive));
+ }
+
+ 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, false);
+ }
+
+ private static void EmitLdp(ILEmitterCtx context, AccessType accType)
+ {
+ EmitLoad(context, accType, 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);
+ }
+
+ if (exclusive)
+ {
+ EmitMemoryCall(context, nameof(MemoryManager.SetExclusive), op.Rn);
+ }
+
+ context.EmitLdint(op.Rn);
+ context.EmitSttmp();
+
+ context.EmitLdarg(TranslatedSub.MemoryArgIdx);
+ context.EmitLdtmp();
+
+ EmitReadZxCall(context, op.Size);
+
+ context.EmitStintzr(op.Rt);
+
+ if (pair)
+ {
+ context.EmitLdarg(TranslatedSub.MemoryArgIdx);
+ context.EmitLdtmp();
+ context.EmitLdc_I8(1 << op.Size);
+
+ context.Emit(OpCodes.Add);
+
+ EmitReadZxCall(context, op.Size);
+
+ context.EmitStintzr(op.Rt2);
+ }
+ }
+
+ 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, false);
+ }
+
+ private static void EmitStp(ILEmitterCtx context, AccessType accType)
+ {
+ EmitStore(context, accType, 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);
+ }
+
+ ILLabel lblEx = new ILLabel();
+ ILLabel lblEnd = new ILLabel();
+
+ if (exclusive)
+ {
+ EmitMemoryCall(context, nameof(MemoryManager.TestExclusive), op.Rn);
+
+ context.Emit(OpCodes.Brtrue_S, lblEx);
+
+ context.EmitLdc_I8(1);
+ context.EmitStintzr(op.Rs);
+
+ context.Emit(OpCodes.Br_S, lblEnd);
+ }
+
+ context.MarkLabel(lblEx);
+
+ context.EmitLdarg(TranslatedSub.MemoryArgIdx);
+ context.EmitLdint(op.Rn);
+ context.EmitLdintzr(op.Rt);
+
+ EmitWriteCall(context, op.Size);
+
+ if (pair)
+ {
+ context.EmitLdarg(TranslatedSub.MemoryArgIdx);
+ context.EmitLdint(op.Rn);
+ context.EmitLdc_I8(1 << op.Size);
+
+ context.Emit(OpCodes.Add);
+
+ context.EmitLdintzr(op.Rt2);
+
+ EmitWriteCall(context, op.Size);
+ }
+
+ if (exclusive)
+ {
+ context.EmitLdc_I8(0);
+ context.EmitStintzr(op.Rs);
+
+ EmitMemoryCall(context, nameof(MemoryManager.ClearExclusiveForStore));
+ }
+
+ context.MarkLabel(lblEnd);
+ }
+
+ private static void EmitMemoryCall(ILEmitterCtx context, string name, int rn = -1)
+ {
+ context.EmitLdarg(TranslatedSub.MemoryArgIdx);
+ context.EmitLdarg(TranslatedSub.StateArgIdx);
+
+ context.EmitCallPropGet(typeof(CpuThreadState), nameof(CpuThreadState.Core));
+
+ if (rn != -1)
+ {
+ context.EmitLdint(rn);
+ }
+
+ context.EmitCall(typeof(MemoryManager), name);
+ }
+
+ 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
new file mode 100644
index 00000000..f953564c
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitMemoryHelper.cs
@@ -0,0 +1,138 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.Memory;
+using ChocolArm64.Translation;
+using System;
+using System.Reflection.Emit;
+
+namespace ChocolArm64.Instructions
+{
+ static class InstEmitMemoryHelper
+ {
+ 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)
+ {
+ bool isSimd = GetIsSimd(context);
+
+ string name = null;
+
+ if (size < 0 || size > (isSimd ? 4 : 3))
+ {
+ throw new ArgumentOutOfRangeException(nameof(size));
+ }
+
+ if (isSimd)
+ {
+ switch (size)
+ {
+ case 0: name = nameof(MemoryManager.ReadVector8); break;
+ case 1: name = nameof(MemoryManager.ReadVector16); break;
+ case 2: name = nameof(MemoryManager.ReadVector32); break;
+ case 3: name = nameof(MemoryManager.ReadVector64); break;
+ case 4: name = nameof(MemoryManager.ReadVector128); break;
+ }
+ }
+ else
+ {
+ switch (size)
+ {
+ case 0: name = nameof(MemoryManager.ReadByte); break;
+ case 1: name = nameof(MemoryManager.ReadUInt16); break;
+ case 2: name = nameof(MemoryManager.ReadUInt32); break;
+ case 3: name = nameof(MemoryManager.ReadUInt64); break;
+ }
+ }
+
+ context.EmitCall(typeof(MemoryManager), name);
+
+ 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 = GetIsSimd(context);
+
+ string name = null;
+
+ if (size < 0 || size > (isSimd ? 4 : 3))
+ {
+ throw new ArgumentOutOfRangeException(nameof(size));
+ }
+
+ if (size < 3 && !isSimd)
+ {
+ context.Emit(OpCodes.Conv_I4);
+ }
+
+ if (isSimd)
+ {
+ switch (size)
+ {
+ case 0: name = nameof(MemoryManager.WriteVector8); break;
+ case 1: name = nameof(MemoryManager.WriteVector16); break;
+ case 2: name = nameof(MemoryManager.WriteVector32); break;
+ case 3: name = nameof(MemoryManager.WriteVector64); break;
+ case 4: name = nameof(MemoryManager.WriteVector128); break;
+ }
+ }
+ else
+ {
+ switch (size)
+ {
+ case 0: name = nameof(MemoryManager.WriteByte); break;
+ case 1: name = nameof(MemoryManager.WriteUInt16); break;
+ case 2: name = nameof(MemoryManager.WriteUInt32); break;
+ case 3: name = nameof(MemoryManager.WriteUInt64); break;
+ }
+ }
+
+ context.EmitCall(typeof(MemoryManager), name);
+ }
+
+ private static bool GetIsSimd(ILEmitterCtx context)
+ {
+ return context.CurrOp is IOpCodeSimd64 &&
+ !(context.CurrOp is OpCodeSimdMemMs64 ||
+ context.CurrOp is OpCodeSimdMemSs64);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Instructions/InstEmitMove.cs b/ChocolArm64/Instructions/InstEmitMove.cs
new file mode 100644
index 00000000..be3e8e2d
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitMove.cs
@@ -0,0 +1,41 @@
+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
new file mode 100644
index 00000000..b7418e69
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitMul.cs
@@ -0,0 +1,80 @@
+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
new file mode 100644
index 00000000..9217de5f
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitSimdArithmetic.cs
@@ -0,0 +1,2387 @@
+// 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;
+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)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ int bytes = op.GetBitsCount() >> 3;
+ int elems = bytes >> op.Size;
+
+ EmitVectorExtractZx(context, op.Rn, 0, op.Size);
+
+ for (int index = 1; index < elems; index++)
+ {
+ EmitVectorExtractZx(context, op.Rn, index, op.Size);
+
+ context.Emit(OpCodes.Add);
+ }
+
+ EmitScalarSet(context, op.Rd, op.Size);
+ }
+
+ 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)
+ {
+ EmitScalarBinaryOpF(context, () =>
+ {
+ context.Emit(OpCodes.Sub);
+
+ EmitUnaryMathCall(context, nameof(Math.Abs));
+ });
+ }
+
+ public static void Fabs_S(ILEmitterCtx context)
+ {
+ EmitScalarUnaryOpF(context, () =>
+ {
+ EmitUnaryMathCall(context, nameof(Math.Abs));
+ });
+ }
+
+ public static void Fabs_V(ILEmitterCtx context)
+ {
+ EmitVectorUnaryOpF(context, () =>
+ {
+ EmitUnaryMathCall(context, nameof(Math.Abs));
+ });
+ }
+
+ public static void Fadd_S(ILEmitterCtx context)
+ {
+ if (Optimizations.FastFP && Optimizations.UseSse
+ && 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.UseSse
+ && 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;
+
+ EmitVectorExtractF(context, op.Rn, 0, sizeF);
+ EmitVectorExtractF(context, op.Rn, 1, sizeF);
+
+ context.Emit(OpCodes.Add);
+
+ EmitScalarSetF(context, op.Rd, sizeF);
+ }
+
+ public static void Faddp_V(ILEmitterCtx context)
+ {
+ EmitVectorPairwiseOpF(context, () => context.Emit(OpCodes.Add));
+ }
+
+ public static void Fdiv_S(ILEmitterCtx context)
+ {
+ if (Optimizations.FastFP && Optimizations.UseSse
+ && 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.UseSse
+ && Optimizations.UseSse2)
+ {
+ EmitVectorSseOrSse2OpF(context, nameof(Sse.Divide));
+ }
+ else
+ {
+ EmitVectorBinaryOpF(context, () =>
+ {
+ EmitSoftFloatCall(context, nameof(SoftFloat32.FPDiv));
+ });
+ }
+ }
+
+ public static void Fmadd_S(ILEmitterCtx context)
+ {
+ if (Optimizations.FastFP && Optimizations.UseSse2)
+ {
+ OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
+
+ if (op.Size == 0)
+ {
+ Type[] typesMulAdd = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
+
+ context.EmitLdvec(op.Ra);
+ context.EmitLdvec(op.Rn);
+ context.EmitLdvec(op.Rm);
+
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulAdd));
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AddScalar), typesMulAdd));
+
+ context.EmitStvec(op.Rd);
+
+ EmitVectorZero32_128(context, op.Rd);
+ }
+ else /* if (Op.Size == 1) */
+ {
+ Type[] typesMulAdd = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
+
+ EmitLdvecWithCastToDouble(context, op.Ra);
+ EmitLdvecWithCastToDouble(context, op.Rn);
+ EmitLdvecWithCastToDouble(context, op.Rm);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulAdd));
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AddScalar), typesMulAdd));
+
+ EmitStvecWithCastFromDouble(context, 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.UseSse
+ && 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.UseSse
+ && 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)
+ {
+ EmitVectorPairwiseOpF(context, () =>
+ {
+ EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax));
+ });
+ }
+
+ public static void Fmin_S(ILEmitterCtx context)
+ {
+ if (Optimizations.FastFP && Optimizations.UseSse
+ && 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.UseSse
+ && 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)
+ {
+ 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)
+ {
+ EmitVectorTernaryOpF(context, () =>
+ {
+ context.Emit(OpCodes.Mul);
+ context.Emit(OpCodes.Add);
+ });
+ }
+
+ public static void Fmla_Ve(ILEmitterCtx context)
+ {
+ EmitVectorTernaryOpByElemF(context, () =>
+ {
+ context.Emit(OpCodes.Mul);
+ context.Emit(OpCodes.Add);
+ });
+ }
+
+ public static void Fmls_Se(ILEmitterCtx context)
+ {
+ EmitScalarTernaryOpByElemF(context, () =>
+ {
+ context.Emit(OpCodes.Mul);
+ context.Emit(OpCodes.Sub);
+ });
+ }
+
+ public static void Fmls_V(ILEmitterCtx context)
+ {
+ EmitVectorTernaryOpF(context, () =>
+ {
+ context.Emit(OpCodes.Mul);
+ context.Emit(OpCodes.Sub);
+ });
+ }
+
+ public static void Fmls_Ve(ILEmitterCtx context)
+ {
+ EmitVectorTernaryOpByElemF(context, () =>
+ {
+ context.Emit(OpCodes.Mul);
+ context.Emit(OpCodes.Sub);
+ });
+ }
+
+ public static void Fmsub_S(ILEmitterCtx context)
+ {
+ if (Optimizations.FastFP && Optimizations.UseSse2)
+ {
+ OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
+
+ if (op.Size == 0)
+ {
+ Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
+
+ context.EmitLdvec(op.Ra);
+ context.EmitLdvec(op.Rn);
+ context.EmitLdvec(op.Rm);
+
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulSub));
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), typesMulSub));
+
+ context.EmitStvec(op.Rd);
+
+ EmitVectorZero32_128(context, op.Rd);
+ }
+ else /* if (Op.Size == 1) */
+ {
+ Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
+
+ EmitLdvecWithCastToDouble(context, op.Ra);
+ EmitLdvecWithCastToDouble(context, op.Rn);
+ EmitLdvecWithCastToDouble(context, op.Rm);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulSub));
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), typesMulSub));
+
+ EmitStvecWithCastFromDouble(context, 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.UseSse
+ && 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.UseSse
+ && Optimizations.UseSse2)
+ {
+ EmitVectorSseOrSse2OpF(context, nameof(Sse.Multiply));
+ }
+ else
+ {
+ EmitVectorBinaryOpF(context, () =>
+ {
+ EmitSoftFloatCall(context, nameof(SoftFloat32.FPMul));
+ });
+ }
+ }
+
+ public static void Fmul_Ve(ILEmitterCtx context)
+ {
+ EmitVectorBinaryOpByElemF(context, () => context.Emit(OpCodes.Mul));
+ }
+
+ 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)
+ {
+ EmitScalarUnaryOpF(context, () => context.Emit(OpCodes.Neg));
+ }
+
+ public static void Fneg_V(ILEmitterCtx context)
+ {
+ 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)
+ {
+ EmitScalarUnaryOpF(context, () =>
+ {
+ EmitUnarySoftFloatCall(context, nameof(SoftFloat.RecipEstimate));
+ });
+ }
+
+ public static void Frecpe_V(ILEmitterCtx context)
+ {
+ EmitVectorUnaryOpF(context, () =>
+ {
+ EmitUnarySoftFloatCall(context, nameof(SoftFloat.RecipEstimate));
+ });
+ }
+
+ public static void Frecps_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[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
+
+ context.EmitLdc_R4(2f);
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv));
+
+ context.EmitLdvec(op.Rn);
+ context.EmitLdvec(op.Rm);
+
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulSub));
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), typesMulSub));
+
+ context.EmitStvec(op.Rd);
+
+ EmitVectorZero32_128(context, op.Rd);
+ }
+ else /* if (SizeF == 1) */
+ {
+ Type[] typesSsv = new Type[] { typeof(double) };
+ Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
+
+ context.EmitLdc_R8(2d);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv));
+
+ EmitLdvecWithCastToDouble(context, op.Rn);
+ EmitLdvecWithCastToDouble(context, op.Rm);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulSub));
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), typesMulSub));
+
+ EmitStvecWithCastFromDouble(context, op.Rd);
+
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+ else
+ {
+ EmitScalarBinaryOpF(context, () =>
+ {
+ EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipStepFused));
+ });
+ }
+ }
+
+ public static void Frecps_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[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
+
+ context.EmitLdc_R4(2f);
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav));
+
+ context.EmitLdvec(op.Rn);
+ context.EmitLdvec(op.Rm);
+
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub));
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), typesMulSub));
+
+ context.EmitStvec(op.Rd);
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+ else /* if (SizeF == 1) */
+ {
+ Type[] typesSav = new Type[] { typeof(double) };
+ Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
+
+ context.EmitLdc_R8(2d);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));
+
+ EmitLdvecWithCastToDouble(context, op.Rn);
+ EmitLdvecWithCastToDouble(context, op.Rm);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulSub));
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub));
+
+ EmitStvecWithCastFromDouble(context, 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)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ EmitVectorExtractF(context, op.Rn, 0, op.Size);
+
+ EmitRoundMathCall(context, MidpointRounding.AwayFromZero);
+
+ EmitScalarSetF(context, op.Rd, op.Size);
+ }
+
+ 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;
+
+ 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));
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ });
+ }
+
+ public static void Frinti_V(ILEmitterCtx context)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ int sizeF = op.Size & 1;
+
+ 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));
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ });
+ }
+
+ public static void Frintm_S(ILEmitterCtx context)
+ {
+ EmitScalarUnaryOpF(context, () =>
+ {
+ EmitUnaryMathCall(context, nameof(Math.Floor));
+ });
+ }
+
+ public static void Frintm_V(ILEmitterCtx context)
+ {
+ EmitVectorUnaryOpF(context, () =>
+ {
+ EmitUnaryMathCall(context, nameof(Math.Floor));
+ });
+ }
+
+ public static void Frintn_S(ILEmitterCtx context)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ EmitVectorExtractF(context, op.Rn, 0, op.Size);
+
+ EmitRoundMathCall(context, MidpointRounding.ToEven);
+
+ EmitScalarSetF(context, op.Rd, op.Size);
+ }
+
+ public static void Frintn_V(ILEmitterCtx context)
+ {
+ EmitVectorUnaryOpF(context, () =>
+ {
+ EmitRoundMathCall(context, MidpointRounding.ToEven);
+ });
+ }
+
+ public static void Frintp_S(ILEmitterCtx context)
+ {
+ EmitScalarUnaryOpF(context, () =>
+ {
+ EmitUnaryMathCall(context, nameof(Math.Ceiling));
+ });
+ }
+
+ public static void Frintp_V(ILEmitterCtx context)
+ {
+ EmitVectorUnaryOpF(context, () =>
+ {
+ EmitUnaryMathCall(context, nameof(Math.Ceiling));
+ });
+ }
+
+ public static void Frintx_S(ILEmitterCtx context)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ 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));
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ });
+ }
+
+ public static void Frintx_V(ILEmitterCtx context)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ EmitVectorUnaryOpF(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));
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ });
+ }
+
+ public static void Frsqrte_S(ILEmitterCtx context)
+ {
+ EmitScalarUnaryOpF(context, () =>
+ {
+ EmitUnarySoftFloatCall(context, nameof(SoftFloat.InvSqrtEstimate));
+ });
+ }
+
+ public static void Frsqrte_V(ILEmitterCtx context)
+ {
+ EmitVectorUnaryOpF(context, () =>
+ {
+ EmitUnarySoftFloatCall(context, nameof(SoftFloat.InvSqrtEstimate));
+ });
+ }
+
+ public static void Frsqrts_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[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
+
+ context.EmitLdc_R4(0.5f);
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv));
+
+ context.EmitLdc_R4(3f);
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv));
+
+ context.EmitLdvec(op.Rn);
+ context.EmitLdvec(op.Rm);
+
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulSub));
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), typesMulSub));
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulSub));
+
+ context.EmitStvec(op.Rd);
+
+ EmitVectorZero32_128(context, op.Rd);
+ }
+ else /* if (SizeF == 1) */
+ {
+ Type[] typesSsv = new Type[] { typeof(double) };
+ Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
+
+ context.EmitLdc_R8(0.5d);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv));
+
+ context.EmitLdc_R8(3d);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv));
+
+ EmitLdvecWithCastToDouble(context, op.Rn);
+ EmitLdvecWithCastToDouble(context, 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));
+
+ EmitStvecWithCastFromDouble(context, op.Rd);
+
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+ else
+ {
+ EmitScalarBinaryOpF(context, () =>
+ {
+ EmitSoftFloatCall(context, nameof(SoftFloat32.FprSqrtStepFused));
+ });
+ }
+ }
+
+ public static void Frsqrts_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[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
+
+ context.EmitLdc_R4(0.5f);
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav));
+
+ context.EmitLdc_R4(3f);
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav));
+
+ context.EmitLdvec(op.Rn);
+ context.EmitLdvec(op.Rm);
+
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub));
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), typesMulSub));
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub));
+
+ context.EmitStvec(op.Rd);
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+ else /* if (SizeF == 1) */
+ {
+ Type[] typesSav = new Type[] { typeof(double) };
+ Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
+
+ context.EmitLdc_R8(0.5d);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));
+
+ context.EmitLdc_R8(3d);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));
+
+ EmitLdvecWithCastToDouble(context, op.Rn);
+ EmitLdvecWithCastToDouble(context, 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));
+
+ EmitStvecWithCastFromDouble(context, op.Rd);
+ }
+ }
+ else
+ {
+ EmitVectorBinaryOpF(context, () =>
+ {
+ EmitSoftFloatCall(context, nameof(SoftFloat32.FprSqrtStepFused));
+ });
+ }
+ }
+
+ public static void Fsqrt_S(ILEmitterCtx context)
+ {
+ if (Optimizations.FastFP && Optimizations.UseSse
+ && 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.UseSse
+ && 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.UseSse
+ && 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.UseSse
+ && Optimizations.UseSse2)
+ {
+ EmitVectorSseOrSse2OpF(context, nameof(Sse.Subtract));
+ }
+ else
+ {
+ EmitVectorBinaryOpF(context, () =>
+ {
+ EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub));
+ });
+ }
+ }
+
+ public static void Mla_V(ILEmitterCtx context)
+ {
+ 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)
+ {
+ 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)
+ {
+ 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)
+ {
+ 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)
+ {
+ EmitVectorBinaryOpSx(context, () =>
+ {
+ context.Emit(OpCodes.Sub);
+ EmitAbs(context);
+ });
+ }
+
+ public static void Sabdl_V(ILEmitterCtx context)
+ {
+ 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) };
+
+ int numBytes = op.RegisterSize == RegisterSize.Simd128 ? 8 : 0;
+
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl));
+
+ context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt));
+
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ 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));
+
+ EmitStvecWithSignedCast(context, op.Rd, op.Size + 1);
+ }
+ else
+ {
+ EmitVectorWidenRnRmBinaryOpSx(context, () => context.Emit(OpCodes.Add));
+ }
+ }
+
+ public static void Saddlp_V(ILEmitterCtx context)
+ {
+ EmitAddLongPairwise(context, signed: true, accumulate: false);
+ }
+
+ public static void Saddw_V(ILEmitterCtx context)
+ {
+ 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] };
+
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size);
+
+ context.Emit(OpCodes.Dup);
+ context.EmitStvectmp();
+
+ EmitLdvecWithSignedCast(context, op.Rm, op.Size);
+
+ context.Emit(OpCodes.Dup);
+ context.EmitStvectmp2();
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndXorAdd));
+
+ context.EmitLdvectmp();
+ context.EmitLdvectmp2();
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesAndXorAdd));
+
+ context.EmitLdc_I4(1);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), typesSra));
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAndXorAdd));
+
+ EmitStvecWithSignedCast(context, op.Rd, op.Size);
+
+ 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();
+
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size);
+ context.EmitLdvectmp();
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAddSub));
+
+ context.Emit(OpCodes.Dup);
+
+ EmitLdvecWithSignedCast(context, op.Rm, op.Size);
+ 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));
+
+ EmitStvecWithSignedCast(context, op.Rd, op.Size);
+
+ 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)
+ {
+ 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 Smin_V(ILEmitterCtx context)
+ {
+ 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 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 typeMul = op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
+
+ string nameCvt = op.Size == 0
+ ? nameof(Sse41.ConvertToVector128Int16)
+ : nameof(Sse41.ConvertToVector128Int32);
+
+ int numBytes = op.RegisterSize == RegisterSize.Simd128 ? 8 : 0;
+
+ EmitLdvecWithSignedCast(context, op.Rd, op.Size + 1);
+
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl));
+
+ context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt));
+
+ EmitLdvecWithSignedCast(context, op.Rm, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl));
+
+ context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt));
+
+ context.EmitCall(typeMul.GetMethod(nameof(Sse2.MultiplyLow), typesMulAdd));
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesMulAdd));
+
+ EmitStvecWithSignedCast(context, op.Rd, op.Size + 1);
+ }
+ else
+ {
+ EmitVectorWidenRnRmTernaryOpSx(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 typeMul = op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
+
+ string nameCvt = op.Size == 0
+ ? nameof(Sse41.ConvertToVector128Int16)
+ : nameof(Sse41.ConvertToVector128Int32);
+
+ int numBytes = op.RegisterSize == RegisterSize.Simd128 ? 8 : 0;
+
+ EmitLdvecWithSignedCast(context, op.Rd, op.Size + 1);
+
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl));
+
+ context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt));
+
+ EmitLdvecWithSignedCast(context, op.Rm, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl));
+
+ context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt));
+
+ context.EmitCall(typeMul.GetMethod(nameof(Sse2.MultiplyLow), typesMulSub));
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub));
+
+ EmitStvecWithSignedCast(context, op.Rd, op.Size + 1);
+ }
+ else
+ {
+ EmitVectorWidenRnRmTernaryOpSx(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 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.Emit(OpCodes.Dup);
+ context.EmitStvectmp();
+
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size);
+ context.EmitLdvectmp();
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSubAdd));
+
+ EmitLdvecWithSignedCast(context, op.Rm, op.Size);
+ 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));
+
+ EmitStvecWithSignedCast(context, op.Rd, op.Size);
+
+ 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) };
+
+ int numBytes = op.RegisterSize == RegisterSize.Simd128 ? 8 : 0;
+
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl));
+
+ context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt));
+
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ 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));
+
+ EmitStvecWithSignedCast(context, op.Rd, op.Size + 1);
+ }
+ else
+ {
+ EmitVectorWidenRnRmBinaryOpSx(context, () => context.Emit(OpCodes.Sub));
+ }
+ }
+
+ public static void Ssubw_V(ILEmitterCtx context)
+ {
+ 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)
+ {
+ EmitVectorBinaryOpZx(context, () =>
+ {
+ context.Emit(OpCodes.Sub);
+ EmitAbs(context);
+ });
+ }
+
+ public static void Uabdl_V(ILEmitterCtx context)
+ {
+ 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) };
+
+ int numBytes = op.RegisterSize == RegisterSize.Simd128 ? 8 : 0;
+
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl));
+
+ context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt));
+
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ 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));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size + 1);
+ }
+ 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)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ int bytes = op.GetBitsCount() >> 3;
+ int elems = bytes >> op.Size;
+
+ EmitVectorExtractZx(context, op.Rn, 0, op.Size);
+
+ for (int index = 1; index < elems; index++)
+ {
+ EmitVectorExtractZx(context, op.Rn, index, op.Size);
+
+ context.Emit(OpCodes.Add);
+ }
+
+ EmitScalarSet(context, op.Rd, op.Size + 1);
+ }
+
+ public static void Uaddw_V(ILEmitterCtx context)
+ {
+ 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] };
+
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+
+ context.Emit(OpCodes.Dup);
+ context.EmitStvectmp();
+
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+
+ context.Emit(OpCodes.Dup);
+ context.EmitStvectmp2();
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndXorAdd));
+
+ context.EmitLdvectmp();
+ context.EmitLdvectmp2();
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesAndXorAdd));
+
+ context.EmitLdc_I4(1);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrl));
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAndXorAdd));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ 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] };
+
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+ context.Emit(OpCodes.Dup);
+
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), typesAvgSub));
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesAvgSub));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ 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)
+ {
+ 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 Umin_V(ILEmitterCtx context)
+ {
+ 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 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 typeMul = op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
+
+ string nameCvt = op.Size == 0
+ ? nameof(Sse41.ConvertToVector128Int16)
+ : nameof(Sse41.ConvertToVector128Int32);
+
+ int numBytes = op.RegisterSize == RegisterSize.Simd128 ? 8 : 0;
+
+ EmitLdvecWithUnsignedCast(context, op.Rd, op.Size + 1);
+
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl));
+
+ context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt));
+
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl));
+
+ context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt));
+
+ context.EmitCall(typeMul.GetMethod(nameof(Sse2.MultiplyLow), typesMulAdd));
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesMulAdd));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size + 1);
+ }
+ else
+ {
+ EmitVectorWidenRnRmTernaryOpZx(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 typeMul = op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
+
+ string nameCvt = op.Size == 0
+ ? nameof(Sse41.ConvertToVector128Int16)
+ : nameof(Sse41.ConvertToVector128Int32);
+
+ int numBytes = op.RegisterSize == RegisterSize.Simd128 ? 8 : 0;
+
+ EmitLdvecWithUnsignedCast(context, op.Rd, op.Size + 1);
+
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl));
+
+ context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt));
+
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl));
+
+ context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt));
+
+ context.EmitCall(typeMul.GetMethod(nameof(Sse2.MultiplyLow), typesMulSub));
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size + 1);
+ }
+ else
+ {
+ EmitVectorWidenRnRmTernaryOpZx(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 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] };
+
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), typesAvg));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ 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) };
+
+ int numBytes = op.RegisterSize == RegisterSize.Simd128 ? 8 : 0;
+
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl));
+
+ context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt));
+
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+
+ context.EmitLdc_I4(numBytes);
+ 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));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size + 1);
+ }
+ else
+ {
+ EmitVectorWidenRnRmBinaryOpZx(context, () => context.Emit(OpCodes.Sub));
+ }
+ }
+
+ public static void Usubw_V(ILEmitterCtx context)
+ {
+ 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);
+ }
+ }
+ }
+}
diff --git a/ChocolArm64/Instructions/InstEmitSimdCmp.cs b/ChocolArm64/Instructions/InstEmitSimdCmp.cs
new file mode 100644
index 00000000..c473c0ae
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitSimdCmp.cs
@@ -0,0 +1,526 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.State;
+using ChocolArm64.Translation;
+using System;
+using System.Reflection.Emit;
+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)
+ {
+ EmitCmp(context, OpCodes.Beq_S, scalar: true);
+ }
+
+ public static void Cmeq_V(ILEmitterCtx context)
+ {
+ if (context.CurrOp is OpCodeSimdReg64 op)
+ {
+ if (op.Size < 3 && Optimizations.UseSse2)
+ {
+ EmitSse2Op(context, nameof(Sse2.CompareEqual));
+ }
+ else if (op.Size == 3 && Optimizations.UseSse41)
+ {
+ EmitSse41Op(context, nameof(Sse41.CompareEqual));
+ }
+ else
+ {
+ EmitCmp(context, OpCodes.Beq_S, scalar: false);
+ }
+ }
+ else
+ {
+ EmitCmp(context, OpCodes.Beq_S, scalar: false);
+ }
+ }
+
+ public static void Cmge_S(ILEmitterCtx context)
+ {
+ EmitCmp(context, OpCodes.Bge_S, scalar: true);
+ }
+
+ public static void Cmge_V(ILEmitterCtx context)
+ {
+ EmitCmp(context, OpCodes.Bge_S, scalar: false);
+ }
+
+ public static void Cmgt_S(ILEmitterCtx context)
+ {
+ EmitCmp(context, OpCodes.Bgt_S, scalar: true);
+ }
+
+ public static void Cmgt_V(ILEmitterCtx context)
+ {
+ if (context.CurrOp is OpCodeSimdReg64 op)
+ {
+ if (op.Size < 3 && Optimizations.UseSse2)
+ {
+ EmitSse2Op(context, nameof(Sse2.CompareGreaterThan));
+ }
+ else if (op.Size == 3 && Optimizations.UseSse42)
+ {
+ EmitSse42Op(context, nameof(Sse42.CompareGreaterThan));
+ }
+ else
+ {
+ EmitCmp(context, OpCodes.Bgt_S, scalar: false);
+ }
+ }
+ else
+ {
+ EmitCmp(context, OpCodes.Bgt_S, scalar: false);
+ }
+ }
+
+ public static void Cmhi_S(ILEmitterCtx context)
+ {
+ EmitCmp(context, OpCodes.Bgt_Un_S, scalar: true);
+ }
+
+ public static void Cmhi_V(ILEmitterCtx context)
+ {
+ EmitCmp(context, OpCodes.Bgt_Un_S, scalar: false);
+ }
+
+ public static void Cmhs_S(ILEmitterCtx context)
+ {
+ EmitCmp(context, OpCodes.Bge_Un_S, scalar: true);
+ }
+
+ public static void Cmhs_V(ILEmitterCtx context)
+ {
+ EmitCmp(context, OpCodes.Bge_Un_S, scalar: false);
+ }
+
+ public static void Cmle_S(ILEmitterCtx context)
+ {
+ EmitCmp(context, OpCodes.Ble_S, scalar: true);
+ }
+
+ public static void Cmle_V(ILEmitterCtx context)
+ {
+ EmitCmp(context, OpCodes.Ble_S, scalar: false);
+ }
+
+ public static void Cmlt_S(ILEmitterCtx context)
+ {
+ EmitCmp(context, OpCodes.Blt_S, scalar: true);
+ }
+
+ public static void Cmlt_V(ILEmitterCtx context)
+ {
+ EmitCmp(context, OpCodes.Blt_S, scalar: false);
+ }
+
+ public static void Cmtst_S(ILEmitterCtx context)
+ {
+ EmitCmtst(context, scalar: true);
+ }
+
+ public static void Cmtst_V(ILEmitterCtx context)
+ {
+ EmitCmtst(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);
+
+ EmitSetNzcv(context, op.Nzcv);
+
+ context.Emit(OpCodes.Br, lblEnd);
+
+ context.MarkLabel(lblTrue);
+
+ Fcmp_S(context);
+
+ context.MarkLabel(lblEnd);
+ }
+
+ public static void Fccmpe_S(ILEmitterCtx context)
+ {
+ Fccmp_S(context);
+ }
+
+ public static void Fcmeq_S(ILEmitterCtx context)
+ {
+ if (context.CurrOp is OpCodeSimdReg64 && Optimizations.UseSse
+ && Optimizations.UseSse2)
+ {
+ EmitScalarSseOrSse2OpF(context, nameof(Sse.CompareEqualScalar));
+ }
+ else
+ {
+ EmitScalarFcmp(context, OpCodes.Beq_S);
+ }
+ }
+
+ public static void Fcmeq_V(ILEmitterCtx context)
+ {
+ if (context.CurrOp is OpCodeSimdReg64 && Optimizations.UseSse
+ && Optimizations.UseSse2)
+ {
+ EmitVectorSseOrSse2OpF(context, nameof(Sse.CompareEqual));
+ }
+ else
+ {
+ EmitVectorFcmp(context, OpCodes.Beq_S);
+ }
+ }
+
+ public static void Fcmge_S(ILEmitterCtx context)
+ {
+ if (context.CurrOp is OpCodeSimdReg64 && Optimizations.UseSse
+ && Optimizations.UseSse2)
+ {
+ EmitScalarSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanOrEqualScalar));
+ }
+ else
+ {
+ EmitScalarFcmp(context, OpCodes.Bge_S);
+ }
+ }
+
+ public static void Fcmge_V(ILEmitterCtx context)
+ {
+ if (context.CurrOp is OpCodeSimdReg64 && Optimizations.UseSse
+ && Optimizations.UseSse2)
+ {
+ EmitVectorSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanOrEqual));
+ }
+ else
+ {
+ EmitVectorFcmp(context, OpCodes.Bge_S);
+ }
+ }
+
+ public static void Fcmgt_S(ILEmitterCtx context)
+ {
+ if (context.CurrOp is OpCodeSimdReg64 && Optimizations.UseSse
+ && Optimizations.UseSse2)
+ {
+ EmitScalarSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanScalar));
+ }
+ else
+ {
+ EmitScalarFcmp(context, OpCodes.Bgt_S);
+ }
+ }
+
+ public static void Fcmgt_V(ILEmitterCtx context)
+ {
+ if (context.CurrOp is OpCodeSimdReg64 && Optimizations.UseSse
+ && Optimizations.UseSse2)
+ {
+ EmitVectorSseOrSse2OpF(context, nameof(Sse.CompareGreaterThan));
+ }
+ else
+ {
+ EmitVectorFcmp(context, OpCodes.Bgt_S);
+ }
+ }
+
+ public static void Fcmle_S(ILEmitterCtx context)
+ {
+ EmitScalarFcmp(context, OpCodes.Ble_S);
+ }
+
+ public static void Fcmle_V(ILEmitterCtx context)
+ {
+ EmitVectorFcmp(context, OpCodes.Ble_S);
+ }
+
+ public static void Fcmlt_S(ILEmitterCtx context)
+ {
+ EmitScalarFcmp(context, OpCodes.Blt_S);
+ }
+
+ public static void Fcmlt_V(ILEmitterCtx context)
+ {
+ EmitVectorFcmp(context, OpCodes.Blt_S);
+ }
+
+ public static void Fcmp_S(ILEmitterCtx context)
+ {
+ OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
+
+ bool cmpWithZero = !(op is OpCodeSimdFcond64) ? op.Bit3 : false;
+
+ //Handle NaN case.
+ //If any number is NaN, then NZCV = 0011.
+ if (cmpWithZero)
+ {
+ EmitNaNCheck(context, op.Rn);
+ }
+ else
+ {
+ EmitNaNCheck(context, op.Rn);
+ EmitNaNCheck(context, op.Rm);
+
+ context.Emit(OpCodes.Or);
+ }
+
+ ILLabel lblNaN = new ILLabel();
+ ILLabel lblEnd = new ILLabel();
+
+ context.Emit(OpCodes.Brtrue_S, lblNaN);
+
+ void EmitLoadOpers()
+ {
+ 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);
+ }
+ }
+
+ //Z = Rn == Rm
+ EmitLoadOpers();
+
+ context.Emit(OpCodes.Ceq);
+ context.Emit(OpCodes.Dup);
+
+ context.EmitStflg((int)PState.ZBit);
+
+ //C = Rn >= Rm
+ EmitLoadOpers();
+
+ context.Emit(OpCodes.Cgt);
+ context.Emit(OpCodes.Or);
+
+ context.EmitStflg((int)PState.CBit);
+
+ //N = Rn < Rm
+ EmitLoadOpers();
+
+ context.Emit(OpCodes.Clt);
+
+ context.EmitStflg((int)PState.NBit);
+
+ //V = 0
+ context.EmitLdc_I4(0);
+
+ context.EmitStflg((int)PState.VBit);
+
+ context.Emit(OpCodes.Br_S, lblEnd);
+
+ context.MarkLabel(lblNaN);
+
+ EmitSetNzcv(context, 0b0011);
+
+ context.MarkLabel(lblEnd);
+ }
+
+ public static void Fcmpe_S(ILEmitterCtx context)
+ {
+ Fcmp_S(context);
+ }
+
+ private static void EmitNaNCheck(ILEmitterCtx context, int reg)
+ {
+ IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp;
+
+ EmitVectorExtractF(context, reg, 0, op.Size);
+
+ if (op.Size == 0)
+ {
+ context.EmitCall(typeof(float), nameof(float.IsNaN));
+ }
+ else if (op.Size == 1)
+ {
+ context.EmitCall(typeof(double), nameof(double.IsNaN));
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ }
+
+ private static void EmitCmp(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 EmitCmtst(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 EmitScalarFcmp(ILEmitterCtx context, OpCode ilOp)
+ {
+ EmitFcmp(context, ilOp, 0, scalar: true);
+ }
+
+ private static void EmitVectorFcmp(ILEmitterCtx context, OpCode ilOp)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ int sizeF = op.Size & 1;
+
+ int bytes = op.GetBitsCount() >> 3;
+ int elems = bytes >> sizeF + 2;
+
+ for (int index = 0; index < elems; index++)
+ {
+ EmitFcmp(context, ilOp, index, scalar: false);
+ }
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+
+ private static void EmitFcmp(ILEmitterCtx context, OpCode ilOp, int index, bool scalar)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ int sizeF = op.Size & 1;
+
+ ulong szMask = ulong.MaxValue >> (64 - (32 << sizeF));
+
+ 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);
+ }
+
+ ILLabel lblTrue = new ILLabel();
+ ILLabel lblEnd = new ILLabel();
+
+ context.Emit(ilOp, lblTrue);
+
+ if (scalar)
+ {
+ EmitVectorZeroAll(context, op.Rd);
+ }
+ else
+ {
+ EmitVectorInsert(context, op.Rd, index, sizeF + 2, 0);
+ }
+
+ context.Emit(OpCodes.Br_S, lblEnd);
+
+ context.MarkLabel(lblTrue);
+
+ if (scalar)
+ {
+ EmitVectorInsert(context, op.Rd, index, 3, (long)szMask);
+
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ else
+ {
+ EmitVectorInsert(context, op.Rd, index, sizeF + 2, (long)szMask);
+ }
+
+ context.MarkLabel(lblEnd);
+ }
+ }
+}
diff --git a/ChocolArm64/Instructions/InstEmitSimdCrypto.cs b/ChocolArm64/Instructions/InstEmitSimdCrypto.cs
new file mode 100644
index 00000000..33c81aab
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitSimdCrypto.cs
@@ -0,0 +1,54 @@
+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
new file mode 100644
index 00000000..fa17c09d
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitSimdCvt.cs
@@ -0,0 +1,697 @@
+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 (Optimizations.UseSse2)
+ {
+ if (op.Size == 1 && op.Opc == 0)
+ {
+ //Double -> Single.
+ VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));
+
+ EmitLdvecWithCastToDouble(context, op.Rn);
+
+ Type[] types = new Type[] { typeof(Vector128<float>), typeof(Vector128<double>) };
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Single), types));
+
+ context.EmitStvec(op.Rd);
+ }
+ else if (op.Size == 0 && op.Opc == 1)
+ {
+ //Single -> Double.
+ VectorHelper.EmitCall(context, nameof(VectorHelper.VectorDoubleZero));
+
+ context.EmitLdvec(op.Rn);
+
+ Type[] types = new Type[] { typeof(Vector128<double>), typeof(Vector128<float>) };
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Double), types));
+
+ EmitStvecWithCastFromDouble(context, op.Rd);
+ }
+ else
+ {
+ //Invalid encoding.
+ throw new InvalidOperationException();
+ }
+ }
+ else
+ {
+ EmitVectorExtractF(context, op.Rn, 0, op.Size);
+
+ EmitFloatCast(context, op.Opc);
+
+ EmitScalarSetF(context, op.Rd, 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;
+
+ 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(SoftFloat1632), nameof(SoftFloat1632.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;
+
+ 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(SoftFloat3216), nameof(SoftFloat3216.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)
+ {
+ EmitFcvtn(context, signed: true, scalar: true);
+ }
+
+ public static void Fcvtns_V(ILEmitterCtx context)
+ {
+ EmitFcvtn(context, signed: true, scalar: false);
+ }
+
+ public static void Fcvtnu_S(ILEmitterCtx context)
+ {
+ EmitFcvtn(context, signed: false, scalar: true);
+ }
+
+ public static void Fcvtnu_V(ILEmitterCtx context)
+ {
+ 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_Fix(ILEmitterCtx context)
+ {
+ EmitFcvtzs_Gp_Fix(context);
+ }
+
+ public static void Fcvtzs_S(ILEmitterCtx context)
+ {
+ EmitScalarFcvtzs(context);
+ }
+
+ public static void Fcvtzs_V(ILEmitterCtx context)
+ {
+ EmitVectorFcvtzs(context);
+ }
+
+ public static void Fcvtzu_Gp(ILEmitterCtx context)
+ {
+ EmitFcvt_u_Gp(context, () => { });
+ }
+
+ public static void Fcvtzu_Gp_Fix(ILEmitterCtx context)
+ {
+ EmitFcvtzu_Gp_Fix(context);
+ }
+
+ public static void Fcvtzu_S(ILEmitterCtx context)
+ {
+ EmitScalarFcvtzu(context);
+ }
+
+ public static void Fcvtzu_V(ILEmitterCtx context)
+ {
+ EmitVectorFcvtzu(context);
+ }
+
+ 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_U4);
+ }
+
+ EmitFloatCast(context, op.Size);
+
+ EmitScalarSetF(context, op.Rd, op.Size);
+ }
+
+ public static void Scvtf_S(ILEmitterCtx context)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ EmitVectorExtractSx(context, op.Rn, 0, op.Size + 2);
+
+ EmitFloatCast(context, op.Size);
+
+ EmitScalarSetF(context, op.Rd, op.Size);
+ }
+
+ public static void Scvtf_V(ILEmitterCtx context)
+ {
+ 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_S(ILEmitterCtx context)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ EmitVectorExtractZx(context, op.Rn, 0, op.Size + 2);
+
+ context.Emit(OpCodes.Conv_R_Un);
+
+ EmitFloatCast(context, op.Size);
+
+ EmitScalarSetF(context, op.Rd, op.Size);
+ }
+
+ public static void Ucvtf_V(ILEmitterCtx context)
+ {
+ EmitVectorCvtf(context, signed: false);
+ }
+
+ 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 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;
+
+ if (scalar && (sizeF == 0))
+ {
+ EmitVectorZeroLowerTmp(context);
+ }
+
+ 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));
+ }
+
+ EmitVectorInsertTmp(context, index, sizeI);
+ }
+
+ context.EmitLdvectmp();
+ context.EmitStvec(op.Rd);
+
+ if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
+ {
+ 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_Fix(ILEmitterCtx context)
+ {
+ EmitFcvtz__Gp_Fix(context, true);
+ }
+
+ private static void EmitFcvtzu_Gp_Fix(ILEmitterCtx context)
+ {
+ EmitFcvtz__Gp_Fix(context, false);
+ }
+
+ private static void EmitFcvtz__Gp_Fix(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 EmitVectorScvtf(ILEmitterCtx context)
+ {
+ EmitVectorCvtf(context, true);
+ }
+
+ private static void EmitVectorUcvtf(ILEmitterCtx context)
+ {
+ EmitVectorCvtf(context, false);
+ }
+
+ 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);
+ }
+
+ context.Emit(sizeF == 0
+ ? OpCodes.Conv_R4
+ : OpCodes.Conv_R8);
+
+ EmitI2fFBitsMul(context, sizeF, fBits);
+
+ EmitVectorInsertF(context, op.Rd, index, sizeF);
+ }
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+
+ private static void EmitScalarFcvtzs(ILEmitterCtx context)
+ {
+ EmitScalarFcvtz(context, true);
+ }
+
+ private static void EmitScalarFcvtzu(ILEmitterCtx context)
+ {
+ EmitScalarFcvtz(context, false);
+ }
+
+ private static void EmitScalarFcvtz(ILEmitterCtx context, bool signed)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ int sizeF = op.Size & 1;
+ int sizeI = sizeF + 2;
+
+ int fBits = GetFBits(context);
+
+ EmitVectorExtractF(context, op.Rn, 0, sizeF);
+
+ EmitF2iFBitsMul(context, sizeF, fBits);
+
+ if (sizeF == 0)
+ {
+ VectorHelper.EmitCall(context, signed
+ ? nameof(VectorHelper.SatF32ToS32)
+ : nameof(VectorHelper.SatF32ToU32));
+ }
+ else /* if (SizeF == 1) */
+ {
+ VectorHelper.EmitCall(context, signed
+ ? nameof(VectorHelper.SatF64ToS64)
+ : nameof(VectorHelper.SatF64ToU64));
+ }
+
+ if (sizeF == 0)
+ {
+ context.Emit(OpCodes.Conv_U8);
+ }
+
+ EmitScalarSet(context, op.Rd, sizeI);
+ }
+
+ private static void EmitVectorFcvtzs(ILEmitterCtx context)
+ {
+ EmitVectorFcvtz(context, true);
+ }
+
+ private static void EmitVectorFcvtzu(ILEmitterCtx context)
+ {
+ EmitVectorFcvtz(context, false);
+ }
+
+ private static void EmitVectorFcvtz(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++)
+ {
+ EmitVectorExtractF(context, op.Rn, index, sizeF);
+
+ EmitF2iFBitsMul(context, sizeF, fBits);
+
+ if (sizeF == 0)
+ {
+ VectorHelper.EmitCall(context, signed
+ ? nameof(VectorHelper.SatF32ToS32)
+ : nameof(VectorHelper.SatF32ToU32));
+ }
+ else /* if (SizeF == 1) */
+ {
+ VectorHelper.EmitCall(context, signed
+ ? nameof(VectorHelper.SatF64ToS64)
+ : nameof(VectorHelper.SatF64ToU64));
+ }
+
+ if (sizeF == 0)
+ {
+ context.Emit(OpCodes.Conv_U8);
+ }
+
+ EmitVectorInsert(context, op.Rd, index, sizeI);
+ }
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+
+ 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);
+ }
+ }
+ }
+}
diff --git a/ChocolArm64/Instructions/InstEmitSimdHash.cs b/ChocolArm64/Instructions/InstEmitSimdHash.cs
new file mode 100644
index 00000000..bb767fec
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitSimdHash.cs
@@ -0,0 +1,140 @@
+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
new file mode 100644
index 00000000..fad51510
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitSimdHelper.cs
@@ -0,0 +1,1495 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.State;
+using ChocolArm64.Translation;
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace ChocolArm64.Instructions
+{
+ static class InstEmitSimdHelper
+ {
+ public static readonly Type[] IntTypesPerSizeLog2 = new Type[]
+ {
+ typeof(sbyte),
+ typeof(short),
+ typeof(int),
+ typeof(long)
+ };
+
+ public static readonly Type[] UIntTypesPerSizeLog2 = new Type[]
+ {
+ typeof(byte),
+ typeof(ushort),
+ typeof(uint),
+ typeof(ulong)
+ };
+
+ public static readonly Type[] VectorIntTypesPerSizeLog2 = new Type[]
+ {
+ typeof(Vector128<sbyte>),
+ typeof(Vector128<short>),
+ typeof(Vector128<int>),
+ typeof(Vector128<long>)
+ };
+
+ public static readonly Type[] VectorUIntTypesPerSizeLog2 = new Type[]
+ {
+ typeof(Vector128<byte>),
+ typeof(Vector128<ushort>),
+ typeof(Vector128<uint>),
+ typeof(Vector128<ulong>)
+ };
+
+ [Flags]
+ public enum OperFlags
+ {
+ Rd = 1 << 0,
+ Rn = 1 << 1,
+ Rm = 1 << 2,
+ Ra = 1 << 3,
+
+ RnRm = Rn | Rm,
+ RdRn = Rd | Rn,
+ RaRnRm = Ra | Rn | Rm,
+ RdRnRm = Rd | Rn | Rm
+ }
+
+ public static int GetImmShl(OpCodeSimdShImm64 op)
+ {
+ return op.Imm - (8 << op.Size);
+ }
+
+ public static int GetImmShr(OpCodeSimdShImm64 op)
+ {
+ return (8 << (op.Size + 1)) - op.Imm;
+ }
+
+ public static void EmitSse2Op(ILEmitterCtx context, string name)
+ {
+ EmitSseOp(context, name, typeof(Sse2));
+ }
+
+ public static void EmitSse41Op(ILEmitterCtx context, string name)
+ {
+ EmitSseOp(context, name, typeof(Sse41));
+ }
+
+ public static void EmitSse42Op(ILEmitterCtx context, string name)
+ {
+ EmitSseOp(context, name, typeof(Sse42));
+ }
+
+ private static void EmitSseOp(ILEmitterCtx context, string name, Type type)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size);
+
+ Type baseType = VectorIntTypesPerSizeLog2[op.Size];
+
+ if (op is OpCodeSimdReg64 binOp)
+ {
+ EmitLdvecWithSignedCast(context, binOp.Rm, op.Size);
+
+ context.EmitCall(type.GetMethod(name, new Type[] { baseType, baseType }));
+ }
+ else
+ {
+ context.EmitCall(type.GetMethod(name, new Type[] { baseType }));
+ }
+
+ EmitStvecWithSignedCast(context, op.Rd, op.Size);
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+
+ public static void EmitLdvecWithSignedCast(ILEmitterCtx context, int reg, int size)
+ {
+ context.EmitLdvec(reg);
+
+ switch (size)
+ {
+ case 0: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToSByte)); break;
+ case 1: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToInt16)); break;
+ case 2: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToInt32)); break;
+ case 3: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToInt64)); break;
+
+ default: throw new ArgumentOutOfRangeException(nameof(size));
+ }
+ }
+
+ public static void EmitLdvecWithCastToDouble(ILEmitterCtx context, int reg)
+ {
+ context.EmitLdvec(reg);
+
+ VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToDouble));
+ }
+
+ public static void EmitStvecWithCastFromDouble(ILEmitterCtx context, int reg)
+ {
+ VectorHelper.EmitCall(context, nameof(VectorHelper.VectorDoubleToSingle));
+
+ context.EmitStvec(reg);
+ }
+
+ public static void EmitLdvecWithUnsignedCast(ILEmitterCtx context, int reg, int size)
+ {
+ context.EmitLdvec(reg);
+
+ switch (size)
+ {
+ case 0: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToByte)); break;
+ case 1: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToUInt16)); break;
+ case 2: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToUInt32)); break;
+ case 3: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToUInt64)); break;
+
+ default: throw new ArgumentOutOfRangeException(nameof(size));
+ }
+ }
+
+ public static void EmitStvecWithSignedCast(ILEmitterCtx context, int reg, int size)
+ {
+ switch (size)
+ {
+ case 0: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSByteToSingle)); break;
+ case 1: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInt16ToSingle)); break;
+ case 2: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInt32ToSingle)); break;
+ case 3: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInt64ToSingle)); break;
+
+ default: throw new ArgumentOutOfRangeException(nameof(size));
+ }
+
+ context.EmitStvec(reg);
+ }
+
+ public static void EmitStvecWithUnsignedCast(ILEmitterCtx context, int reg, int size)
+ {
+ switch (size)
+ {
+ case 0: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorByteToSingle)); break;
+ case 1: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorUInt16ToSingle)); break;
+ case 2: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorUInt32ToSingle)); break;
+ case 3: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorUInt64ToSingle)); break;
+
+ default: throw new ArgumentOutOfRangeException(nameof(size));
+ }
+
+ context.EmitStvec(reg);
+ }
+
+ 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;
+
+ void Ldvec(int reg)
+ {
+ context.EmitLdvec(reg);
+
+ if (sizeF == 1)
+ {
+ VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToDouble));
+ }
+ }
+
+ Ldvec(op.Rn);
+
+ Type type;
+ Type baseType;
+
+ if (sizeF == 0)
+ {
+ type = typeof(Sse);
+ baseType = typeof(Vector128<float>);
+ }
+ else /* if (SizeF == 1) */
+ {
+ type = typeof(Sse2);
+ baseType = typeof(Vector128<double>);
+ }
+
+ if (op is OpCodeSimdReg64 binOp)
+ {
+ Ldvec(binOp.Rm);
+
+ context.EmitCall(type.GetMethod(name, new Type[] { baseType, baseType }));
+ }
+ else
+ {
+ context.EmitCall(type.GetMethod(name, new Type[] { baseType }));
+ }
+
+ if (sizeF == 1)
+ {
+ VectorHelper.EmitCall(context, nameof(VectorHelper.VectorDoubleToSingle));
+ }
+
+ 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 EmitUnarySoftFloatCall(ILEmitterCtx context, string name)
+ {
+ IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp;
+
+ int sizeF = op.Size & 1;
+
+ MethodInfo mthdInfo;
+
+ if (sizeF == 0)
+ {
+ mthdInfo = typeof(SoftFloat).GetMethod(name, new Type[] { typeof(float) });
+ }
+ else /* if (SizeF == 1) */
+ {
+ mthdInfo = typeof(SoftFloat).GetMethod(name, new Type[] { typeof(double) });
+ }
+
+ context.EmitCall(mthdInfo);
+ }
+
+ public static void EmitSoftFloatCall(ILEmitterCtx context, string name)
+ {
+ IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp;
+
+ Type type = (op.Size & 1) == 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, false, true);
+ }
+
+ public static void EmitVectorBinaryOpByElemZx(ILEmitterCtx context, Action emit)
+ {
+ OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp;
+
+ EmitVectorOpByElem(context, emit, op.Index, false, false);
+ }
+
+ public static void EmitVectorTernaryOpByElemZx(ILEmitterCtx context, Action emit)
+ {
+ OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp;
+
+ EmitVectorOpByElem(context, emit, op.Index, true, 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();
+
+ EmitVectorInsertTmp(context, index, op.Size);
+ }
+
+ context.EmitLdvectmp();
+ context.EmitStvec(op.Rd);
+
+ 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 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 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);
+ }
+ }
+
+ [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;
+
+ if (scalar)
+ {
+ EmitVectorZeroLowerTmp(context);
+ }
+
+ 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);
+ }
+
+ EmitVectorInsertTmp(context, index, op.Size);
+ }
+
+ context.EmitLdvectmp();
+ context.EmitStvec(op.Rd);
+
+ if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
+ {
+ 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 (scalar)
+ {
+ EmitVectorZeroLowerTmp(context);
+ }
+
+ 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);
+ }
+ }
+
+ EmitVectorInsertTmp(context, 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);
+ }
+
+ EmitVectorInsertTmp(context, 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);
+
+ EmitVectorInsertTmp(context, index, op.Size);
+ }
+ }
+
+ context.EmitLdvectmp();
+ context.EmitStvec(op.Rd);
+
+ if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
+ {
+ 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 (sizeDst > 2)
+ {
+ 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 rd)
+ {
+ if (Optimizations.UseSse2)
+ {
+ VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));
+
+ context.EmitStvec(rd);
+ }
+ else
+ {
+ EmitVectorZeroLower(context, rd);
+ EmitVectorZeroUpper(context, rd);
+ }
+ }
+
+ public static void EmitVectorZeroLower(ILEmitterCtx context, int rd)
+ {
+ EmitVectorInsert(context, rd, 0, 3, 0);
+ }
+
+ public static void EmitVectorZeroLowerTmp(ILEmitterCtx context)
+ {
+ EmitVectorInsertTmp(context, 0, 3, 0);
+ }
+
+ public static void EmitVectorZeroUpper(ILEmitterCtx context, int reg)
+ {
+ if (Optimizations.UseSse2)
+ {
+ //TODO: Use MoveScalar once it is fixed, as of the
+ //time of writing it just crashes the JIT.
+ EmitLdvecWithUnsignedCast(context, reg, 3);
+
+ Type[] types = new Type[] { typeof(Vector128<ulong>), typeof(byte) };
+
+ //Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MoveScalar), Types));
+
+ context.EmitLdc_I4(8);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical128BitLane), types));
+
+ context.EmitLdc_I4(8);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), types));
+
+ EmitStvecWithUnsignedCast(context, reg, 3);
+ }
+ else
+ {
+ EmitVectorInsert(context, reg, 1, 3, 0);
+ }
+ }
+
+ public static void EmitVectorZero32_128(ILEmitterCtx context, int reg)
+ {
+ context.EmitLdvec(reg);
+
+ VectorHelper.EmitCall(context, nameof(VectorHelper.VectorZero32_128));
+
+ 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
new file mode 100644
index 00000000..f51568eb
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitSimdLogical.cs
@@ -0,0 +1,311 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.State;
+using ChocolArm64.Translation;
+using System;
+using System.Reflection.Emit;
+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;
+
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+
+ Type[] types = new Type[]
+ {
+ VectorUIntTypesPerSizeLog2[op.Size],
+ VectorUIntTypesPerSizeLog2[op.Size]
+ };
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), types));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ 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)
+ {
+ EmitBitBif(context, true);
+ }
+
+ public static void Bit_V(ILEmitterCtx context)
+ {
+ EmitBitBif(context, false);
+ }
+
+ private static void EmitBitBif(ILEmitterCtx context, bool notRm)
+ {
+ OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
+
+ if (Optimizations.UseSse2)
+ {
+ Type[] types = new Type[]
+ {
+ VectorUIntTypesPerSizeLog2[op.Size],
+ VectorUIntTypesPerSizeLog2[op.Size]
+ };
+
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+ EmitLdvecWithUnsignedCast(context, op.Rd, op.Size);
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), types));
+
+ string name = notRm ? nameof(Sse2.AndNot) : nameof(Sse2.And);
+
+ context.EmitCall(typeof(Sse2).GetMethod(name, types));
+
+ EmitLdvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), types));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+ else
+ {
+ int bytes = op.GetBitsCount() >> 3;
+ int elems = bytes >> op.Size;
+
+ for (int index = 0; index < elems; index++)
+ {
+ EmitVectorExtractZx(context, op.Rd, index, op.Size);
+ EmitVectorExtractZx(context, op.Rn, index, op.Size);
+
+ context.Emit(OpCodes.Xor);
+
+ EmitVectorExtractZx(context, op.Rm, index, op.Size);
+
+ if (notRm)
+ {
+ context.Emit(OpCodes.Not);
+ }
+
+ context.Emit(OpCodes.And);
+
+ EmitVectorExtractZx(context, op.Rd, index, op.Size);
+
+ context.Emit(OpCodes.Xor);
+
+ EmitVectorInsert(context, op.Rd, index, op.Size);
+ }
+
+ 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[] types = new Type[]
+ {
+ VectorUIntTypesPerSizeLog2[op.Size],
+ VectorUIntTypesPerSizeLog2[op.Size]
+ };
+
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), types));
+
+ EmitLdvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), types));
+
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), types));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ 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)
+ {
+ EmitVectorUnaryOpZx(context, () => context.Emit(OpCodes.Not));
+ }
+
+ public static void Orn_V(ILEmitterCtx context)
+ {
+ 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)
+ {
+ EmitRev_V(context, containerSize: 1);
+ }
+
+ public static void Rev32_V(ILEmitterCtx context)
+ {
+ EmitRev_V(context, containerSize: 2);
+ }
+
+ public static void Rev64_V(ILEmitterCtx context)
+ {
+ EmitRev_V(context, containerSize: 3);
+ }
+
+ private static void EmitRev_V(ILEmitterCtx context, int containerSize)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ if (op.Size >= containerSize)
+ {
+ throw new InvalidOperationException();
+ }
+
+ 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
new file mode 100644
index 00000000..eb053257
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitSimdMemory.cs
@@ -0,0 +1,185 @@
+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.EmitLdarg(TranslatedSub.MemoryArgIdx);
+ 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.EmitLdarg(TranslatedSub.MemoryArgIdx);
+ 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.EmitLdarg(TranslatedSub.MemoryArgIdx);
+ 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 != CpuThreadState.ZrIndex)
+ {
+ 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
new file mode 100644
index 00000000..3f539b8a
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitSimdMove.cs
@@ -0,0 +1,562 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.State;
+using ChocolArm64.Translation;
+using System;
+using System.Reflection.Emit;
+using System.Runtime.Intrinsics.X86;
+
+using static ChocolArm64.Instructions.InstEmitSimdHelper;
+
+namespace ChocolArm64.Instructions
+{
+ static partial class InstEmit
+ {
+ public static void Dup_Gp(ILEmitterCtx context)
+ {
+ OpCodeSimdIns64 op = (OpCodeSimdIns64)context.CurrOp;
+
+ if (Optimizations.UseSse2)
+ {
+ 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;
+ }
+
+ Type[] types = new Type[] { UIntTypesPerSizeLog2[op.Size] };
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), types));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, 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;
+
+ 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;
+
+ context.EmitLdvec(op.Rd);
+ context.EmitStvectmp();
+
+ 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)
+ {
+ OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
+
+ EmitVectorExtractZx(context, op.Rn, 0, 3);
+
+ EmitIntZeroUpperIfNeeded(context);
+
+ context.EmitStintzr(op.Rd);
+ }
+
+ public static void Fmov_Ftoi1(ILEmitterCtx context)
+ {
+ OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
+
+ EmitVectorExtractZx(context, op.Rn, 1, 3);
+
+ EmitIntZeroUpperIfNeeded(context);
+
+ context.EmitStintzr(op.Rd);
+ }
+
+ public static void Fmov_Itof(ILEmitterCtx context)
+ {
+ OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
+
+ context.EmitLdintzr(op.Rn);
+
+ EmitIntZeroUpperIfNeeded(context);
+
+ EmitScalarSet(context, op.Rd, 3);
+ }
+
+ public static void Fmov_Itof1(ILEmitterCtx context)
+ {
+ OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
+
+ context.EmitLdintzr(op.Rn);
+
+ EmitIntZeroUpperIfNeeded(context);
+
+ 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_V(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)
+ {
+ EmitVectorImmUnaryOp(context, () => { });
+ }
+
+ public static void Mvni_V(ILEmitterCtx context)
+ {
+ 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);
+
+ EmitIntZeroUpperIfNeeded(context);
+
+ context.EmitStintzr(op.Rd);
+ }
+
+ public static void Tbl_V(ILEmitterCtx context)
+ {
+ OpCodeSimdTbl64 op = (OpCodeSimdTbl64)context.CurrOp;
+
+ 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;
+
+ int elems = 8 >> op.Size;
+
+ int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0;
+
+ if (Optimizations.UseSse41 && op.Size < 2)
+ {
+ void EmitZeroVector()
+ {
+ switch (op.Size)
+ {
+ case 0: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInt16Zero)); break;
+ case 1: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInt32Zero)); break;
+ }
+ }
+
+ //For XTN, first operand is source, second operand is 0.
+ //For XTN2, first operand is 0, second operand is source.
+ if (part != 0)
+ {
+ EmitZeroVector();
+ }
+
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size + 1);
+
+ //Set mask to discard the upper half of the wide elements.
+ switch (op.Size)
+ {
+ case 0: context.EmitLdc_I4(0x00ff); break;
+ case 1: context.EmitLdc_I4(0x0000ffff); break;
+ }
+
+ Type wideType = IntTypesPerSizeLog2[op.Size + 1];
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), new Type[] { wideType }));
+
+ wideType = VectorIntTypesPerSizeLog2[op.Size + 1];
+
+ Type[] wideTypes = new Type[] { wideType, wideType };
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), wideTypes));
+
+ if (part == 0)
+ {
+ EmitZeroVector();
+ }
+
+ //Pack values with signed saturation, the signed saturation shouldn't
+ //saturate anything since the upper bits were masked off.
+ Type sseType = op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
+
+ context.EmitCall(sseType.GetMethod(nameof(Sse2.PackUnsignedSaturate), wideTypes));
+
+ if (part != 0)
+ {
+ //For XTN2, we additionally need to discard the upper bits
+ //of the target register and OR the result with it.
+ EmitVectorZeroUpper(context, op.Rd);
+
+ EmitLdvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ Type narrowType = VectorUIntTypesPerSizeLog2[op.Size];
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), new Type[] { narrowType, narrowType }));
+ }
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+ }
+ else
+ {
+ 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 EmitIntZeroUpperIfNeeded(ILEmitterCtx context)
+ {
+ if (context.CurrOp.RegisterSize == RegisterSize.Int32 ||
+ context.CurrOp.RegisterSize == RegisterSize.Simd64)
+ {
+ context.Emit(OpCodes.Conv_U4);
+ context.Emit(OpCodes.Conv_U8);
+ }
+ }
+
+ private static void EmitVectorTranspose(ILEmitterCtx context, int part)
+ {
+ 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;
+
+ 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;
+
+ 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)
+ {
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+ EmitLdvecWithUnsignedCast(context, op.Rm, op.Size);
+
+ Type[] types = new Type[]
+ {
+ VectorUIntTypesPerSizeLog2[op.Size],
+ VectorUIntTypesPerSizeLog2[op.Size]
+ };
+
+ string name = part == 0 || (part != 0 && op.RegisterSize == RegisterSize.Simd64)
+ ? nameof(Sse2.UnpackLow)
+ : nameof(Sse2.UnpackHigh);
+
+ context.EmitCall(typeof(Sse2).GetMethod(name, types));
+
+ if (op.RegisterSize == RegisterSize.Simd64 && part != 0)
+ {
+ context.EmitLdc_I4(8);
+
+ Type[] shTypes = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) };
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), shTypes));
+ }
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ if (op.RegisterSize == RegisterSize.Simd64 && part == 0)
+ {
+ EmitVectorZeroUpper(context, 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);
+ }
+ }
+ }
+ }
+}
diff --git a/ChocolArm64/Instructions/InstEmitSimdShift.cs b/ChocolArm64/Instructions/InstEmitSimdShift.cs
new file mode 100644
index 00000000..3c24ff23
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitSimdShift.cs
@@ -0,0 +1,865 @@
+// 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.X86;
+
+using static ChocolArm64.Instructions.InstEmitSimdHelper;
+
+namespace ChocolArm64.Instructions
+{
+ static partial class InstEmit
+ {
+ public static void Rshrn_V(ILEmitterCtx context)
+ {
+ EmitVectorShrImmNarrowOpZx(context, round: true);
+ }
+
+ public static void Shl_S(ILEmitterCtx context)
+ {
+ OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp;
+
+ EmitScalarUnaryOpZx(context, () =>
+ {
+ context.EmitLdc_I4(GetImmShl(op));
+
+ context.Emit(OpCodes.Shl);
+ });
+ }
+
+ public static void Shl_V(ILEmitterCtx context)
+ {
+ OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp;
+
+ if (Optimizations.UseSse2 && op.Size > 0)
+ {
+ Type[] typesSll = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) };
+
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(GetImmShl(op));
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesSll));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+ else
+ {
+ EmitVectorUnaryOpZx(context, () =>
+ {
+ context.EmitLdc_I4(GetImmShl(op));
+
+ context.Emit(OpCodes.Shl);
+ });
+ }
+ }
+
+ public static void Shll_V(ILEmitterCtx context)
+ {
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ int shift = 8 << op.Size;
+
+ EmitVectorShImmWidenBinaryZx(context, () => context.Emit(OpCodes.Shl), shift);
+ }
+
+ public static void Shrn_V(ILEmitterCtx context)
+ {
+ 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 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 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 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;
+
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size);
+
+ context.Emit(OpCodes.Dup);
+ context.EmitStvectmp();
+
+ 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.EmitLdvectmp();
+
+ context.EmitLdc_I4(shift);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), typesShs));
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd));
+
+ EmitStvecWithSignedCast(context, op.Rd, op.Size);
+
+ 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;
+
+ EmitLdvecWithSignedCast(context, op.Rd, op.Size);
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size);
+
+ context.Emit(OpCodes.Dup);
+ context.EmitStvectmp();
+
+ 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.EmitLdvectmp();
+
+ 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));
+
+ EmitStvecWithSignedCast(context, op.Rd, op.Size);
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+ else
+ {
+ EmitVectorShrImmOpSx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
+ }
+ }
+
+ public static void Sshl_V(ILEmitterCtx context)
+ {
+ EmitVectorShl(context, signed: true);
+ }
+
+ public static void Sshll_V(ILEmitterCtx context)
+ {
+ OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp;
+
+ EmitVectorShImmWidenBinarySx(context, () => context.Emit(OpCodes.Shl), GetImmShl(op));
+ }
+
+ 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) };
+
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(GetImmShr(op));
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), typesSra));
+
+ EmitStvecWithSignedCast(context, op.Rd, op.Size);
+
+ 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] };
+
+ EmitLdvecWithSignedCast(context, op.Rd, op.Size);
+ EmitLdvecWithSignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(GetImmShr(op));
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), typesSra));
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd));
+
+ EmitStvecWithSignedCast(context, op.Rd, op.Size);
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+ else
+ {
+ EmitVectorShrImmOpSx(context, ShrImmFlags.Accumulate);
+ }
+ }
+
+ 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 Uqshrn_S(ILEmitterCtx context)
+ {
+ EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
+ }
+
+ public static void Uqshrn_V(ILEmitterCtx context)
+ {
+ EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx);
+ }
+
+ 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;
+
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+
+ context.Emit(OpCodes.Dup);
+ context.EmitStvectmp();
+
+ 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.EmitLdvectmp();
+
+ context.EmitLdc_I4(shift);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesShs));
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ 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;
+
+ EmitLdvecWithUnsignedCast(context, op.Rd, op.Size);
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+
+ context.Emit(OpCodes.Dup);
+ context.EmitStvectmp();
+
+ 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.EmitLdvectmp();
+
+ 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));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+ else
+ {
+ EmitVectorShrImmOpZx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
+ }
+ }
+
+ public static void Ushl_V(ILEmitterCtx context)
+ {
+ EmitVectorShl(context, signed: false);
+ }
+
+ public static void Ushll_V(ILEmitterCtx context)
+ {
+ OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp;
+
+ EmitVectorShImmWidenBinaryZx(context, () => context.Emit(OpCodes.Shl), GetImmShl(op));
+ }
+
+ 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) };
+
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(GetImmShr(op));
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrl));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ 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] };
+
+ EmitLdvecWithUnsignedCast(context, op.Rd, op.Size);
+ EmitLdvecWithUnsignedCast(context, op.Rn, op.Size);
+
+ context.EmitLdc_I4(GetImmShr(op));
+
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrl));
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd));
+
+ EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+ else
+ {
+ EmitVectorShrImmOpZx(context, ShrImmFlags.Accumulate);
+ }
+ }
+
+ private static void EmitVectorShl(ILEmitterCtx context, bool signed)
+ {
+ //This instruction shifts the value on vector A by the number of bits
+ //specified on the signed, lower 8 bits of vector B. If the shift value
+ //is greater or equal to the data size of each lane, then the result is zero.
+ //Additionally, negative shifts produces right shifts by the negated shift value.
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+
+ int maxShift = 8 << op.Size;
+
+ Action emit = () =>
+ {
+ ILLabel lblShl = new ILLabel();
+ ILLabel lblZero = new ILLabel();
+ ILLabel lblEnd = new ILLabel();
+
+ void EmitShift(OpCode ilOp)
+ {
+ context.Emit(OpCodes.Dup);
+
+ context.EmitLdc_I4(maxShift);
+
+ context.Emit(OpCodes.Bge_S, lblZero);
+ context.Emit(ilOp);
+ context.Emit(OpCodes.Br_S, lblEnd);
+ }
+
+ context.Emit(OpCodes.Conv_I1);
+ context.Emit(OpCodes.Dup);
+
+ context.EmitLdc_I4(0);
+
+ context.Emit(OpCodes.Bge_S, lblShl);
+ context.Emit(OpCodes.Neg);
+
+ EmitShift(signed
+ ? OpCodes.Shr
+ : OpCodes.Shr_Un);
+
+ context.MarkLabel(lblShl);
+
+ EmitShift(OpCodes.Shl);
+
+ context.MarkLabel(lblZero);
+
+ context.Emit(OpCodes.Pop);
+ context.Emit(OpCodes.Pop);
+
+ context.EmitLdc_I8(0);
+
+ context.MarkLabel(lblEnd);
+ };
+
+ if (signed)
+ {
+ EmitVectorBinaryOpSx(context, emit);
+ }
+ else
+ {
+ EmitVectorBinaryOpZx(context, emit);
+ }
+ }
+
+ [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) */
+ {
+ EmitShrImm_64(context, signed, round ? roundConst : 0L, shift);
+ }
+
+ if (accumulate)
+ {
+ EmitVectorExtract(context, op.Rd, index, op.Size, signed);
+
+ context.Emit(OpCodes.Add);
+ }
+
+ EmitVectorInsertTmp(context, index, op.Size);
+ }
+
+ context.EmitLdvectmp();
+ context.EmitStvec(op.Rd);
+
+ 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) */
+ {
+ EmitShrImm_64(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);
+ }
+ }
+
+ // Dst_64 = (Int(Src_64, Signed) + RoundConst) >> Shift;
+ private static void EmitShrImm_64(
+ ILEmitterCtx context,
+ bool signed,
+ long roundConst,
+ int shift)
+ {
+ context.EmitLdc_I8(roundConst);
+ context.EmitLdc_I4(shift);
+
+ SoftFallback.EmitCall(context, signed
+ ? nameof(SoftFallback.SignedShrImm_64)
+ : nameof(SoftFallback.UnsignedShrImm_64));
+ }
+
+ 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
new file mode 100644
index 00000000..0e61d5bd
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitSystem.cs
@@ -0,0 +1,138 @@
+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.Fpcr); break;
+ case 0b11_011_0100_0100_001: propName = nameof(CpuThreadState.Fpsr); 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.Fpcr); break;
+ case 0b11_011_0100_0100_001: propName = nameof(CpuThreadState.Fpsr); 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.EmitLdarg(TranslatedSub.MemoryArgIdx);
+ 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
new file mode 100644
index 00000000..db6e8604
--- /dev/null
+++ b/ChocolArm64/Instructions/InstEmitter.cs
@@ -0,0 +1,6 @@
+using ChocolArm64.Translation;
+
+namespace ChocolArm64.Instructions
+{
+ delegate void InstEmitter(ILEmitterCtx context);
+} \ No newline at end of file
diff --git a/ChocolArm64/Instructions/InstInterpreter.cs b/ChocolArm64/Instructions/InstInterpreter.cs
new file mode 100644
index 00000000..e6354fd5
--- /dev/null
+++ b/ChocolArm64/Instructions/InstInterpreter.cs
@@ -0,0 +1,8 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.Memory;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Instructions
+{
+ delegate void InstInterpreter(CpuThreadState state, MemoryManager memory, OpCode64 opCode);
+} \ No newline at end of file
diff --git a/ChocolArm64/Instructions/SoftFallback.cs b/ChocolArm64/Instructions/SoftFallback.cs
new file mode 100644
index 00000000..a31aa34c
--- /dev/null
+++ b/ChocolArm64/Instructions/SoftFallback.cs
@@ -0,0 +1,922 @@
+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 "ShrImm_64"
+ public static long SignedShrImm_64(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
+ {
+ 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 UnsignedShrImm_64(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 (((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[(value >> nibbleIdx) & 0b1111];
+ count += preCount;
+ }
+ while (preCount == 4);
+
+ return (ulong)count;
+ }
+
+ public static ulong CountSetBits8(ulong value) // "Size" is 8 (SIMD&FP Inst.).
+ {
+ if (value == 0xfful)
+ {
+ return 8ul;
+ }
+
+ value = ((value >> 1) & 0x55ul) + (value & 0x55ul);
+ value = ((value >> 2) & 0x33ul) + (value & 0x33ul);
+
+ return (value >> 4) + (value & 0x0ful);
+ }
+#endregion
+
+#region "Crc32"
+ private const uint Crc32RevPoly = 0xedb88320;
+ private const uint Crc32CRevPoly = 0x82f63b78;
+
+ public static uint Crc32B(uint crc, byte val) => Crc32 (crc, Crc32RevPoly, val);
+ public static uint Crc32H(uint crc, ushort val) => Crc32H(crc, Crc32RevPoly, val);
+ public static uint Crc32W(uint crc, uint val) => Crc32W(crc, Crc32RevPoly, val);
+ public static uint Crc32X(uint crc, ulong val) => Crc32X(crc, Crc32RevPoly, val);
+
+ public static uint Crc32Cb(uint crc, byte val) => Crc32 (crc, Crc32CRevPoly, val);
+ public static uint Crc32Ch(uint crc, ushort val) => Crc32H(crc, Crc32CRevPoly, val);
+ public static uint Crc32Cw(uint crc, uint val) => Crc32W(crc, Crc32CRevPoly, val);
+ public static uint Crc32Cx(uint crc, ulong val) => Crc32X(crc, Crc32CRevPoly, val);
+
+ private static uint Crc32H(uint crc, uint poly, ushort val)
+ {
+ crc = Crc32(crc, poly, (byte)(val >> 0));
+ crc = Crc32(crc, poly, (byte)(val >> 8));
+
+ return crc;
+ }
+
+ private static uint Crc32W(uint crc, uint poly, uint val)
+ {
+ crc = Crc32(crc, poly, (byte)(val >> 0 ));
+ crc = Crc32(crc, poly, (byte)(val >> 8 ));
+ crc = Crc32(crc, poly, (byte)(val >> 16));
+ crc = Crc32(crc, poly, (byte)(val >> 24));
+
+ return crc;
+ }
+
+ private static uint Crc32X(uint crc, uint poly, ulong val)
+ {
+ crc = Crc32(crc, poly, (byte)(val >> 0 ));
+ crc = Crc32(crc, poly, (byte)(val >> 8 ));
+ crc = Crc32(crc, poly, (byte)(val >> 16));
+ crc = Crc32(crc, poly, (byte)(val >> 24));
+ crc = Crc32(crc, poly, (byte)(val >> 32));
+ crc = Crc32(crc, poly, (byte)(val >> 40));
+ crc = Crc32(crc, poly, (byte)(val >> 48));
+ crc = Crc32(crc, poly, (byte)(val >> 56));
+
+ return crc;
+ }
+
+ private static uint Crc32(uint crc, uint poly, byte val)
+ {
+ crc ^= val;
+
+ for (int bit = 7; bit >= 0; bit--)
+ {
+ uint mask = (uint)(-(int)(crc & 1));
+
+ crc = (crc >> 1) ^ (poly & mask);
+ }
+
+ return crc;
+ }
+#endregion
+
+#region "Aes"
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<float> Decrypt(Vector128<float> value, Vector128<float> roundKey)
+ {
+ if (!Sse.IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(Sse.Xor(value, roundKey)));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<float> Encrypt(Vector128<float> value, Vector128<float> roundKey)
+ {
+ if (!Sse.IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(Sse.Xor(value, roundKey)));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<float> InverseMixColumns(Vector128<float> value)
+ {
+ return CryptoHelper.AesInvMixColumns(value);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<float> MixColumns(Vector128<float> value)
+ {
+ return CryptoHelper.AesMixColumns(value);
+ }
+#endregion
+
+#region "Sha1"
+ public static Vector128<float> HashChoose(Vector128<float> hashAbcd, uint hashE, Vector128<float> wk)
+ {
+ for (int e = 0; e <= 3; e++)
+ {
+ uint t = ShaChoose((uint)VectorExtractIntZx(hashAbcd, (byte)1, 2),
+ (uint)VectorExtractIntZx(hashAbcd, (byte)2, 2),
+ (uint)VectorExtractIntZx(hashAbcd, (byte)3, 2));
+
+ hashE += Rol((uint)VectorExtractIntZx(hashAbcd, (byte)0, 2), 5) + t;
+ hashE += (uint)VectorExtractIntZx(wk, (byte)e, 2);
+
+ t = Rol((uint)VectorExtractIntZx(hashAbcd, (byte)1, 2), 30);
+ hashAbcd = VectorInsertInt((ulong)t, hashAbcd, (byte)1, 2);
+
+ Rol32_160(ref hashE, ref hashAbcd);
+ }
+
+ return hashAbcd;
+ }
+
+ public static uint FixedRotate(uint hashE)
+ {
+ return hashE.Rol(30);
+ }
+
+ public static Vector128<float> HashMajority(Vector128<float> hashAbcd, uint hashE, Vector128<float> wk)
+ {
+ for (int e = 0; e <= 3; e++)
+ {
+ uint t = ShaMajority((uint)VectorExtractIntZx(hashAbcd, (byte)1, 2),
+ (uint)VectorExtractIntZx(hashAbcd, (byte)2, 2),
+ (uint)VectorExtractIntZx(hashAbcd, (byte)3, 2));
+
+ hashE += Rol((uint)VectorExtractIntZx(hashAbcd, (byte)0, 2), 5) + t;
+ hashE += (uint)VectorExtractIntZx(wk, (byte)e, 2);
+
+ t = Rol((uint)VectorExtractIntZx(hashAbcd, (byte)1, 2), 30);
+ hashAbcd = VectorInsertInt((ulong)t, hashAbcd, (byte)1, 2);
+
+ Rol32_160(ref hashE, ref hashAbcd);
+ }
+
+ return hashAbcd;
+ }
+
+ public static Vector128<float> HashParity(Vector128<float> hashAbcd, uint hashE, Vector128<float> wk)
+ {
+ for (int e = 0; e <= 3; e++)
+ {
+ uint t = ShaParity((uint)VectorExtractIntZx(hashAbcd, (byte)1, 2),
+ (uint)VectorExtractIntZx(hashAbcd, (byte)2, 2),
+ (uint)VectorExtractIntZx(hashAbcd, (byte)3, 2));
+
+ hashE += Rol((uint)VectorExtractIntZx(hashAbcd, (byte)0, 2), 5) + t;
+ hashE += (uint)VectorExtractIntZx(wk, (byte)e, 2);
+
+ t = Rol((uint)VectorExtractIntZx(hashAbcd, (byte)1, 2), 30);
+ hashAbcd = VectorInsertInt((ulong)t, hashAbcd, (byte)1, 2);
+
+ Rol32_160(ref hashE, ref hashAbcd);
+ }
+
+ return hashAbcd;
+ }
+
+ public static Vector128<float> Sha1SchedulePart1(Vector128<float> w03, Vector128<float> w47, Vector128<float> w811)
+ {
+ if (!Sse.IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ Vector128<float> result = new Vector128<float>();
+
+ ulong t2 = VectorExtractIntZx(w47, (byte)0, 3);
+ ulong t1 = VectorExtractIntZx(w03, (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(w03, w811));
+ }
+
+ public static Vector128<float> Sha1SchedulePart2(Vector128<float> tw03, Vector128<float> w1215)
+ {
+ if (!Sse2.IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ Vector128<float> result = new Vector128<float>();
+
+ Vector128<float> t = Sse.Xor(tw03, Sse.StaticCast<uint, float>(
+ Sse2.ShiftRightLogical128BitLane(Sse.StaticCast<float, uint>(w1215), (byte)4)));
+
+ uint tE0 = (uint)VectorExtractIntZx(t, (byte)0, 2);
+ uint tE1 = (uint)VectorExtractIntZx(t, (byte)1, 2);
+ uint tE2 = (uint)VectorExtractIntZx(t, (byte)2, 2);
+ uint tE3 = (uint)VectorExtractIntZx(t, (byte)3, 2);
+
+ result = VectorInsertInt((ulong)tE0.Rol(1), result, (byte)0, 2);
+ result = VectorInsertInt((ulong)tE1.Rol(1), result, (byte)1, 2);
+ result = VectorInsertInt((ulong)tE2.Rol(1), result, (byte)2, 2);
+
+ return VectorInsertInt((ulong)(tE3.Rol(1) ^ tE0.Rol(2)), result, (byte)3, 2);
+ }
+
+ private static void Rol32_160(ref uint y, ref Vector128<float> x)
+ {
+ if (!Sse2.IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ uint xE3 = (uint)VectorExtractIntZx(x, (byte)3, 2);
+
+ x = Sse.StaticCast<uint, float>(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast<float, uint>(x), (byte)4));
+ x = VectorInsertInt((ulong)y, x, (byte)0, 2);
+
+ y = xE3;
+ }
+
+ private static uint ShaChoose(uint x, uint y, uint z)
+ {
+ return ((y ^ z) & x) ^ z;
+ }
+
+ private static uint ShaMajority(uint x, uint y, uint z)
+ {
+ return (x & y) | ((x | y) & z);
+ }
+
+ private static uint ShaParity(uint x, uint y, uint z)
+ {
+ return x ^ y ^ z;
+ }
+
+ private static uint Rol(this uint value, int count)
+ {
+ return (value << count) | (value >> (32 - count));
+ }
+#endregion
+
+#region "Sha256"
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<float> HashLower(Vector128<float> hashAbcd, Vector128<float> hashEfgh, Vector128<float> wk)
+ {
+ return Sha256Hash(hashAbcd, hashEfgh, wk, true);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<float> HashUpper(Vector128<float> hashEfgh, Vector128<float> hashAbcd, Vector128<float> wk)
+ {
+ return Sha256Hash(hashAbcd, hashEfgh, wk, false);
+ }
+
+ public static Vector128<float> Sha256SchedulePart1(Vector128<float> w03, Vector128<float> w47)
+ {
+ Vector128<float> result = new Vector128<float>();
+
+ for (int e = 0; e <= 3; e++)
+ {
+ uint elt = (uint)VectorExtractIntZx(e <= 2 ? w03 : w47, (byte)(e <= 2 ? e + 1 : 0), 2);
+
+ elt = elt.Ror(7) ^ elt.Ror(18) ^ elt.Lsr(3);
+
+ elt += (uint)VectorExtractIntZx(w03, (byte)e, 2);
+
+ result = VectorInsertInt((ulong)elt, result, (byte)e, 2);
+ }
+
+ return result;
+ }
+
+ public static Vector128<float> Sha256SchedulePart2(Vector128<float> w03, Vector128<float> w811, Vector128<float> w1215)
+ {
+ Vector128<float> result = new Vector128<float>();
+
+ ulong t1 = VectorExtractIntZx(w1215, (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(w03, (byte)e, 2);
+ elt += (uint)VectorExtractIntZx(w811, (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(w03, (byte)e, 2);
+ elt += (uint)VectorExtractIntZx(e == 2 ? w811 : w1215, (byte)(e == 2 ? 3 : 0), 2);
+
+ result = VectorInsertInt((ulong)elt, result, (byte)e, 2);
+ }
+
+ return result;
+ }
+
+ private static Vector128<float> Sha256Hash(Vector128<float> x, Vector128<float> y, Vector128<float> w, bool part1)
+ {
+ for (int e = 0; e <= 3; e++)
+ {
+ uint chs = ShaChoose((uint)VectorExtractIntZx(y, (byte)0, 2),
+ (uint)VectorExtractIntZx(y, (byte)1, 2),
+ (uint)VectorExtractIntZx(y, (byte)2, 2));
+
+ uint maj = ShaMajority((uint)VectorExtractIntZx(x, (byte)0, 2),
+ (uint)VectorExtractIntZx(x, (byte)1, 2),
+ (uint)VectorExtractIntZx(x, (byte)2, 2));
+
+ uint t1 = (uint)VectorExtractIntZx(y, (byte)3, 2);
+ t1 += ShaHashSigma1((uint)VectorExtractIntZx(y, (byte)0, 2)) + chs;
+ t1 += (uint)VectorExtractIntZx(w, (byte)e, 2);
+
+ uint t2 = t1 + (uint)VectorExtractIntZx(x, (byte)3, 2);
+ x = VectorInsertInt((ulong)t2, x, (byte)3, 2);
+ t2 = t1 + ShaHashSigma0((uint)VectorExtractIntZx(x, (byte)0, 2)) + maj;
+ y = VectorInsertInt((ulong)t2, y, (byte)3, 2);
+
+ Rol32_256(ref y, ref x);
+ }
+
+ return part1 ? x : y;
+ }
+
+ private static void Rol32_256(ref Vector128<float> y, ref Vector128<float> x)
+ {
+ if (!Sse2.IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ uint yE3 = (uint)VectorExtractIntZx(y, (byte)3, 2);
+ uint xE3 = (uint)VectorExtractIntZx(x, (byte)3, 2);
+
+ y = Sse.StaticCast<uint, float>(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast<float, uint>(y), (byte)4));
+ x = Sse.StaticCast<uint, float>(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast<float, uint>(x), (byte)4));
+
+ y = VectorInsertInt((ulong)xE3, y, (byte)0, 2);
+ x = VectorInsertInt((ulong)yE3, x, (byte)0, 2);
+ }
+
+ private static uint ShaHashSigma0(uint x)
+ {
+ return x.Ror(2) ^ x.Ror(13) ^ x.Ror(22);
+ }
+
+ private static uint ShaHashSigma1(uint x)
+ {
+ return x.Ror(6) ^ x.Ror(11) ^ x.Ror(25);
+ }
+
+ private static uint Ror(this uint value, int count)
+ {
+ return (value >> count) | (value << (32 - count));
+ }
+
+ private static uint Lsr(this uint value, int count)
+ {
+ return value >> count;
+ }
+
+ private static uint ULongPart(this ulong value, int part)
+ {
+ return part == 0
+ ? (uint)(value & 0xFFFFFFFFUL)
+ : (uint)(value >> 32);
+ }
+#endregion
+
+#region "Reverse"
+ public static uint ReverseBits8(uint value)
+ {
+ value = ((value & 0xaa) >> 1) | ((value & 0x55) << 1);
+ value = ((value & 0xcc) >> 2) | ((value & 0x33) << 2);
+
+ return (value >> 4) | ((value & 0x0f) << 4);
+ }
+
+ public static uint ReverseBits32(uint value)
+ {
+ value = ((value & 0xaaaaaaaa) >> 1) | ((value & 0x55555555) << 1);
+ value = ((value & 0xcccccccc) >> 2) | ((value & 0x33333333) << 2);
+ value = ((value & 0xf0f0f0f0) >> 4) | ((value & 0x0f0f0f0f) << 4);
+ value = ((value & 0xff00ff00) >> 8) | ((value & 0x00ff00ff) << 8);
+
+ return (value >> 16) | (value << 16);
+ }
+
+ public static ulong ReverseBits64(ulong value)
+ {
+ value = ((value & 0xaaaaaaaaaaaaaaaa) >> 1 ) | ((value & 0x5555555555555555) << 1 );
+ value = ((value & 0xcccccccccccccccc) >> 2 ) | ((value & 0x3333333333333333) << 2 );
+ value = ((value & 0xf0f0f0f0f0f0f0f0) >> 4 ) | ((value & 0x0f0f0f0f0f0f0f0f) << 4 );
+ value = ((value & 0xff00ff00ff00ff00) >> 8 ) | ((value & 0x00ff00ff00ff00ff) << 8 );
+ value = ((value & 0xffff0000ffff0000) >> 16) | ((value & 0x0000ffff0000ffff) << 16);
+
+ return (value >> 32) | (value << 32);
+ }
+
+ public static uint ReverseBytes16_32(uint value) => (uint)ReverseBytes16_64(value);
+ public static uint ReverseBytes32_32(uint value) => (uint)ReverseBytes32_64(value);
+
+ public static ulong ReverseBytes16_64(ulong value) => ReverseBytes(value, RevSize.Rev16);
+ public static ulong ReverseBytes32_64(ulong value) => ReverseBytes(value, RevSize.Rev32);
+ public static ulong ReverseBytes64(ulong value) => ReverseBytes(value, RevSize.Rev64);
+
+ private enum RevSize
+ {
+ Rev16,
+ Rev32,
+ Rev64
+ }
+
+ private static ulong ReverseBytes(ulong value, RevSize size)
+ {
+ value = ((value & 0xff00ff00ff00ff00) >> 8) | ((value & 0x00ff00ff00ff00ff) << 8);
+
+ if (size == RevSize.Rev16)
+ {
+ return value;
+ }
+
+ value = ((value & 0xffff0000ffff0000) >> 16) | ((value & 0x0000ffff0000ffff) << 16);
+
+ if (size == RevSize.Rev32)
+ {
+ return value;
+ }
+
+ value = ((value & 0xffffffff00000000) >> 32) | ((value & 0x00000000ffffffff) << 32);
+
+ if (size == RevSize.Rev64)
+ {
+ return value;
+ }
+
+ throw new ArgumentException(nameof(size));
+ }
+#endregion
+
+#region "MultiplyHigh"
+ public static long SMulHi128(long left, long right)
+ {
+ long result = (long)UMulHi128((ulong)left, (ulong)right);
+
+ if (left < 0)
+ {
+ result -= right;
+ }
+
+ if (right < 0)
+ {
+ result -= left;
+ }
+
+ return result;
+ }
+
+ public static ulong UMulHi128(ulong left, ulong right)
+ {
+ ulong lHigh = left >> 32;
+ ulong lLow = left & 0xFFFFFFFF;
+ ulong rHigh = right >> 32;
+ ulong rLow = right & 0xFFFFFFFF;
+
+ ulong z2 = lLow * rLow;
+ ulong t = lHigh * rLow + (z2 >> 32);
+ ulong z1 = t & 0xFFFFFFFF;
+ ulong z0 = t >> 32;
+
+ z1 += lLow * rHigh;
+
+ return lHigh * rHigh + z0 + (z1 >> 32);
+ }
+#endregion
+ }
+}
diff --git a/ChocolArm64/Instructions/SoftFloat.cs b/ChocolArm64/Instructions/SoftFloat.cs
new file mode 100644
index 00000000..79dbe954
--- /dev/null
+++ b/ChocolArm64/Instructions/SoftFloat.cs
@@ -0,0 +1,2127 @@
+using ChocolArm64.State;
+using System;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace ChocolArm64.Instructions
+{
+ static class SoftFloat
+ {
+ static SoftFloat()
+ {
+ RecipEstimateTable = BuildRecipEstimateTable();
+ InvSqrtEstimateTable = BuildInvSqrtEstimateTable();
+ }
+
+ private static readonly byte[] RecipEstimateTable;
+ private static readonly byte[] InvSqrtEstimateTable;
+
+ private static byte[] BuildRecipEstimateTable()
+ {
+ byte[] table = new byte[256];
+ for (ulong index = 0; index < 256; index++)
+ {
+ ulong a = index | 0x100;
+
+ a = (a << 1) + 1;
+ ulong b = 0x80000 / a;
+ b = (b + 1) >> 1;
+
+ table[index] = (byte)(b & 0xFF);
+ }
+ return table;
+ }
+
+ private static byte[] BuildInvSqrtEstimateTable()
+ {
+ byte[] table = new byte[512];
+ for (ulong index = 128; index < 512; index++)
+ {
+ ulong a = index;
+ if (a < 256)
+ {
+ a = (a << 1) + 1;
+ }
+ else
+ {
+ a = (a | 1) << 1;
+ }
+
+ ulong b = 256;
+ while (a * (b + 1) * (b + 1) < (1ul << 28))
+ {
+ b++;
+ }
+ b = (b + 1) >> 1;
+
+ table[index] = (byte)(b & 0xFF);
+ }
+ return table;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float RecipEstimate(float x)
+ {
+ return (float)RecipEstimate((double)x);
+ }
+
+ public static double RecipEstimate(double x)
+ {
+ ulong xBits = (ulong)BitConverter.DoubleToInt64Bits(x);
+ ulong xSign = xBits & 0x8000000000000000;
+ ulong xExp = (xBits >> 52) & 0x7FF;
+ ulong scaled = xBits & ((1ul << 52) - 1);
+
+ if (xExp >= 2045)
+ {
+ if (xExp == 0x7ff && scaled != 0)
+ {
+ // NaN
+ return BitConverter.Int64BitsToDouble((long)(xBits | 0x0008000000000000));
+ }
+
+ // Infinity, or Out of range -> Zero
+ return BitConverter.Int64BitsToDouble((long)xSign);
+ }
+
+ if (xExp == 0)
+ {
+ if (scaled == 0)
+ {
+ // Zero -> Infinity
+ return BitConverter.Int64BitsToDouble((long)(xSign | 0x7FF0000000000000));
+ }
+
+ // Denormal
+ if ((scaled & (1ul << 51)) == 0)
+ {
+ xExp = ~0ul;
+ scaled <<= 2;
+ }
+ else
+ {
+ scaled <<= 1;
+ }
+ }
+
+ scaled >>= 44;
+ scaled &= 0xFF;
+
+ ulong resultExp = (2045 - xExp) & 0x7FF;
+ ulong estimate = (ulong)RecipEstimateTable[scaled];
+ ulong fraction = estimate << 44;
+
+ if (resultExp == 0)
+ {
+ fraction >>= 1;
+ fraction |= 1ul << 51;
+ }
+ else if (resultExp == 0x7FF)
+ {
+ resultExp = 0;
+ fraction >>= 2;
+ fraction |= 1ul << 50;
+ }
+
+ ulong result = xSign | (resultExp << 52) | fraction;
+ return BitConverter.Int64BitsToDouble((long)result);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float InvSqrtEstimate(float x)
+ {
+ return (float)InvSqrtEstimate((double)x);
+ }
+
+ public static double InvSqrtEstimate(double x)
+ {
+ ulong xBits = (ulong)BitConverter.DoubleToInt64Bits(x);
+ ulong xSign = xBits & 0x8000000000000000;
+ long xExp = (long)((xBits >> 52) & 0x7FF);
+ ulong scaled = xBits & ((1ul << 52) - 1);
+
+ if (xExp == 0x7FF && scaled != 0)
+ {
+ // NaN
+ return BitConverter.Int64BitsToDouble((long)(xBits | 0x0008000000000000));
+ }
+
+ if (xExp == 0)
+ {
+ if (scaled == 0)
+ {
+ // Zero -> Infinity
+ return BitConverter.Int64BitsToDouble((long)(xSign | 0x7FF0000000000000));
+ }
+
+ // Denormal
+ while ((scaled & (1 << 51)) == 0)
+ {
+ scaled <<= 1;
+ xExp--;
+ }
+ scaled <<= 1;
+ }
+
+ if (xSign != 0)
+ {
+ // Negative -> NaN
+ return BitConverter.Int64BitsToDouble((long)0x7FF8000000000000);
+ }
+
+ if (xExp == 0x7ff && scaled == 0)
+ {
+ // Infinity -> Zero
+ return BitConverter.Int64BitsToDouble((long)xSign);
+ }
+
+ if (((ulong)xExp & 1) == 1)
+ {
+ scaled >>= 45;
+ scaled &= 0xFF;
+ scaled |= 0x80;
+ }
+ else
+ {
+ scaled >>= 44;
+ scaled &= 0xFF;
+ scaled |= 0x100;
+ }
+
+ ulong resultExp = ((ulong)(3068 - xExp) / 2) & 0x7FF;
+ ulong estimate = (ulong)InvSqrtEstimateTable[scaled];
+ ulong fraction = estimate << 44;
+
+ ulong result = xSign | (resultExp << 52) | fraction;
+ return BitConverter.Int64BitsToDouble((long)result);
+ }
+ }
+
+ static class SoftFloat1632
+ {
+ public static float FPConvert(ushort valueBits, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat16_32.FPConvert: State.Fpcr = 0x{state.Fpcr: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 == (uint)Math.Pow(2d, f))
+ {
+ biasedExp = 1u;
+ }
+
+ if (intMant == (uint)Math.Pow(2d, f + 1))
+ {
+ biasedExp++;
+ intMant >>= 1;
+ }
+ }
+
+ float result;
+
+ if (biasedExp >= (uint)Math.Pow(2d, 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.Fpcr & (1 << enable)) != 0)
+ {
+ throw new NotImplementedException("floating-point trap handling");
+ }
+ else
+ {
+ state.Fpsr |= 1 << (int)exc;
+ }
+ }
+ }
+
+ static class SoftFloat3216
+ {
+ public static ushort FPConvert(float value, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat32_16.FPConvert: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ double real = value.FPUnpackCv(out FpType type, out bool sign, state, out uint valueBits);
+
+ 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, CpuThreadState state, out uint valueBits)
+ {
+ 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 == (uint)Math.Pow(2d, f))
+ {
+ biasedExp = 1u;
+ }
+
+ if (intMant == (uint)Math.Pow(2d, f + 1))
+ {
+ biasedExp++;
+ intMant >>= 1;
+ }
+ }
+
+ ushort resultBits;
+
+ if (!state.GetFpcrFlag(Fpcr.Ahp))
+ {
+ if (biasedExp >= (uint)Math.Pow(2d, 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 >= (uint)Math.Pow(2d, 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.Fpcr & (1 << enable)) != 0)
+ {
+ throw new NotImplementedException("floating-point trap handling");
+ }
+ else
+ {
+ state.Fpsr |= 1 << (int)exc;
+ }
+ }
+ }
+
+ static class SoftFloat32
+ {
+ public static float FPAdd(float value1, float value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_32.FPAdd: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2);
+
+ float result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+
+ return result;
+ }
+
+ public static float FPDiv(float value1, float value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_32.FPDiv: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2);
+
+ float result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+
+ return result;
+ }
+
+ public static float FPMax(float value1, float value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_32.FPMax: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2);
+
+ float result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public static float FPMaxNum(float value1, float value2, CpuThreadState state)
+ {
+ Debug.WriteIf(state.Fpcr != 0, "ASoftFloat_32.FPMaxNum: ");
+
+ value1.FPUnpack(out FpType type1, out _, out _);
+ value2.FPUnpack(out FpType type2, out _, out _);
+
+ 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.Fpcr != 0, $"ASoftFloat_32.FPMin: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2);
+
+ float result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public static float FPMinNum(float value1, float value2, CpuThreadState state)
+ {
+ Debug.WriteIf(state.Fpcr != 0, "ASoftFloat_32.FPMinNum: ");
+
+ value1.FPUnpack(out FpType type1, out _, out _);
+ value2.FPUnpack(out FpType type2, out _, out _);
+
+ 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.Fpcr != 0, $"ASoftFloat_32.FPMul: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2);
+
+ float result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+
+ return result;
+ }
+
+ public static float FPMulAdd(float valueA, float value1, float value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_32.FPMulAdd: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ valueA = valueA.FPUnpack(out FpType typeA, out bool signA, out uint addend);
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2);
+
+ 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, state, out bool done);
+
+ 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);
+ }
+ }
+
+ return result;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float FPMulSub(float valueA, float value1, float value2, CpuThreadState state)
+ {
+ Debug.WriteIf(state.Fpcr != 0, "ASoftFloat_32.FPMulSub: ");
+
+ value1 = value1.FPNeg();
+
+ return FPMulAdd(valueA, value1, value2, state);
+ }
+
+ public static float FPMulX(float value1, float value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_32.FPMulX: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2);
+
+ float result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+
+ return result;
+ }
+
+ public static float FPRecipStepFused(float value1, float value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_32.FPRecipStepFused: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPNeg();
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2);
+
+ float result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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);
+ }
+ }
+
+ return result;
+ }
+
+ public static float FPRecpX(float value, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_32.FPRecpX: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value.FPUnpack(out FpType type, out bool sign, out uint op);
+
+ 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 FprSqrtStepFused(float value1, float value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_32.FPRSqrtStepFused: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPNeg();
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2);
+
+ float result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+
+ return result;
+ }
+
+ public static float FPSqrt(float value, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_32.FPSqrt: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value = value.FPUnpack(out FpType type, out bool sign, out uint op);
+
+ 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);
+ }
+
+ return result;
+ }
+
+ public static float FPSub(float value1, float value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_32.FPSub: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out uint op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out uint op2);
+
+ float result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+
+ 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 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 FPUnpack(this float value, out FpType type, out bool sign, out uint valueBits)
+ {
+ valueBits = (uint)BitConverter.SingleToInt32Bits(value);
+
+ sign = (~valueBits & 0x80000000u) == 0u;
+
+ if ((valueBits & 0x7F800000u) == 0u)
+ {
+ if ((valueBits & 0x007FFFFFu) == 0u)
+ {
+ type = FpType.Zero;
+ }
+ 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;
+
+ return FPZero(sign);
+ }
+ }
+ else
+ {
+ type = FpType.Nonzero;
+ }
+
+ return value;
+ }
+
+ private static float FPProcessNaNs(
+ FpType type1,
+ FpType type2,
+ uint op1,
+ uint op2,
+ CpuThreadState state,
+ out bool done)
+ {
+ 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,
+ CpuThreadState state,
+ out bool done)
+ {
+ 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.Fpcr & (1 << enable)) != 0)
+ {
+ throw new NotImplementedException("floating-point trap handling");
+ }
+ else
+ {
+ state.Fpsr |= 1 << (int)exc;
+ }
+ }
+ }
+
+ static class SoftFloat64
+ {
+ public static double FPAdd(double value1, double value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_64.FPAdd: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2);
+
+ double result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+
+ return result;
+ }
+
+ public static double FPDiv(double value1, double value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_64.FPDiv: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2);
+
+ double result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+
+ return result;
+ }
+
+ public static double FPMax(double value1, double value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_64.FPMax: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2);
+
+ double result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public static double FPMaxNum(double value1, double value2, CpuThreadState state)
+ {
+ Debug.WriteIf(state.Fpcr != 0, "ASoftFloat_64.FPMaxNum: ");
+
+ value1.FPUnpack(out FpType type1, out _, out _);
+ value2.FPUnpack(out FpType type2, out _, out _);
+
+ 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.Fpcr != 0, $"ASoftFloat_64.FPMin: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2);
+
+ double result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public static double FPMinNum(double value1, double value2, CpuThreadState state)
+ {
+ Debug.WriteIf(state.Fpcr != 0, "ASoftFloat_64.FPMinNum: ");
+
+ value1.FPUnpack(out FpType type1, out _, out _);
+ value2.FPUnpack(out FpType type2, out _, out _);
+
+ 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.Fpcr != 0, $"ASoftFloat_64.FPMul: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2);
+
+ double result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+
+ return result;
+ }
+
+ public static double FPMulAdd(double valueA, double value1, double value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_64.FPMulAdd: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ valueA = valueA.FPUnpack(out FpType typeA, out bool signA, out ulong addend);
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2);
+
+ 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, state, out bool done);
+
+ 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);
+ }
+ }
+
+ return result;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double FPMulSub(double valueA, double value1, double value2, CpuThreadState state)
+ {
+ Debug.WriteIf(state.Fpcr != 0, "ASoftFloat_64.FPMulSub: ");
+
+ value1 = value1.FPNeg();
+
+ return FPMulAdd(valueA, value1, value2, state);
+ }
+
+ public static double FPMulX(double value1, double value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_64.FPMulX: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2);
+
+ double result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+
+ return result;
+ }
+
+ public static double FPRecipStepFused(double value1, double value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_64.FPRecipStepFused: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPNeg();
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2);
+
+ double result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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);
+ }
+ }
+
+ return result;
+ }
+
+ public static double FPRecpX(double value, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_64.FPRecpX: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value.FPUnpack(out FpType type, out bool sign, out ulong op);
+
+ 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 FprSqrtStepFused(double value1, double value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_64.FPRSqrtStepFused: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPNeg();
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2);
+
+ double result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+
+ return result;
+ }
+
+ public static double FPSqrt(double value, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_64.FPSqrt: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value = value.FPUnpack(out FpType type, out bool sign, out ulong op);
+
+ 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);
+ }
+
+ return result;
+ }
+
+ public static double FPSub(double value1, double value2, CpuThreadState state)
+ {
+ Debug.WriteLineIf(state.Fpcr != 0, $"ASoftFloat_64.FPSub: State.Fpcr = 0x{state.Fpcr:X8}");
+
+ value1 = value1.FPUnpack(out FpType type1, out bool sign1, out ulong op1);
+ value2 = value2.FPUnpack(out FpType type2, out bool sign2, out ulong op2);
+
+ double result = FPProcessNaNs(type1, type2, op1, op2, state, out bool done);
+
+ 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;
+ }
+ }
+
+ 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 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 FPUnpack(this double value, out FpType type, out bool sign, out ulong valueBits)
+ {
+ valueBits = (ulong)BitConverter.DoubleToInt64Bits(value);
+
+ sign = (~valueBits & 0x8000000000000000ul) == 0ul;
+
+ if ((valueBits & 0x7FF0000000000000ul) == 0ul)
+ {
+ if ((valueBits & 0x000FFFFFFFFFFFFFul) == 0ul)
+ {
+ type = FpType.Zero;
+ }
+ 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;
+
+ return FPZero(sign);
+ }
+ }
+ else
+ {
+ type = FpType.Nonzero;
+ }
+
+ return value;
+ }
+
+ private static double FPProcessNaNs(
+ FpType type1,
+ FpType type2,
+ ulong op1,
+ ulong op2,
+ CpuThreadState state,
+ out bool done)
+ {
+ 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,
+ CpuThreadState state,
+ out bool done)
+ {
+ 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.Fpcr & (1 << enable)) != 0)
+ {
+ throw new NotImplementedException("floating-point trap handling");
+ }
+ else
+ {
+ state.Fpsr |= 1 << (int)exc;
+ }
+ }
+ }
+}
diff --git a/ChocolArm64/Instruction/AVectorHelper.cs b/ChocolArm64/Instructions/VectorHelper.cs
index 41e865b9..8ef15818 100644
--- a/ChocolArm64/Instruction/AVectorHelper.cs
+++ b/ChocolArm64/Instructions/VectorHelper.cs
@@ -5,287 +5,287 @@ using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
-namespace ChocolArm64.Instruction
+namespace ChocolArm64.Instructions
{
- static class AVectorHelper
+ static class VectorHelper
{
- private static readonly Vector128<float> Zero32_128Mask;
+ private static readonly Vector128<float> Zero32128Mask;
- static AVectorHelper()
+ static VectorHelper()
{
if (!Sse2.IsSupported)
{
throw new PlatformNotSupportedException();
}
- Zero32_128Mask = Sse.StaticCast<uint, float>(Sse2.SetVector128(0, 0, 0, 0xffffffff));
+ Zero32128Mask = Sse.StaticCast<uint, float>(Sse2.SetVector128(0, 0, 0, 0xffffffff));
}
- public static void EmitCall(AILEmitterCtx Context, string Name64, string Name128)
+ public static void EmitCall(ILEmitterCtx context, string name64, string name128)
{
- bool IsSimd64 = Context.CurrOp.RegisterSize == ARegisterSize.SIMD64;
+ bool isSimd64 = context.CurrOp.RegisterSize == RegisterSize.Simd64;
- Context.EmitCall(typeof(AVectorHelper), IsSimd64 ? Name64 : Name128);
+ context.EmitCall(typeof(VectorHelper), isSimd64 ? name64 : name128);
}
- public static void EmitCall(AILEmitterCtx Context, string MthdName)
+ public static void EmitCall(ILEmitterCtx context, string mthdName)
{
- Context.EmitCall(typeof(AVectorHelper), MthdName);
+ context.EmitCall(typeof(VectorHelper), mthdName);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int SatF32ToS32(float Value)
+ public static int SatF32ToS32(float value)
{
- if (float.IsNaN(Value)) return 0;
+ if (float.IsNaN(value)) return 0;
- return Value > int.MaxValue ? int.MaxValue :
- Value < int.MinValue ? int.MinValue : (int)Value;
+ return value > int.MaxValue ? int.MaxValue :
+ value < int.MinValue ? int.MinValue : (int)value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static long SatF32ToS64(float Value)
+ public static long SatF32ToS64(float value)
{
- if (float.IsNaN(Value)) return 0;
+ if (float.IsNaN(value)) return 0;
- return Value > long.MaxValue ? long.MaxValue :
- Value < long.MinValue ? long.MinValue : (long)Value;
+ return value > long.MaxValue ? long.MaxValue :
+ value < long.MinValue ? long.MinValue : (long)value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static uint SatF32ToU32(float Value)
+ public static uint SatF32ToU32(float value)
{
- if (float.IsNaN(Value)) return 0;
+ if (float.IsNaN(value)) return 0;
- return Value > uint.MaxValue ? uint.MaxValue :
- Value < uint.MinValue ? uint.MinValue : (uint)Value;
+ return value > uint.MaxValue ? uint.MaxValue :
+ value < uint.MinValue ? uint.MinValue : (uint)value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ulong SatF32ToU64(float Value)
+ public static ulong SatF32ToU64(float value)
{
- if (float.IsNaN(Value)) return 0;
+ if (float.IsNaN(value)) return 0;
- return Value > ulong.MaxValue ? ulong.MaxValue :
- Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
+ return value > ulong.MaxValue ? ulong.MaxValue :
+ value < ulong.MinValue ? ulong.MinValue : (ulong)value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int SatF64ToS32(double Value)
+ public static int SatF64ToS32(double value)
{
- if (double.IsNaN(Value)) return 0;
+ if (double.IsNaN(value)) return 0;
- return Value > int.MaxValue ? int.MaxValue :
- Value < int.MinValue ? int.MinValue : (int)Value;
+ return value > int.MaxValue ? int.MaxValue :
+ value < int.MinValue ? int.MinValue : (int)value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static long SatF64ToS64(double Value)
+ public static long SatF64ToS64(double value)
{
- if (double.IsNaN(Value)) return 0;
+ if (double.IsNaN(value)) return 0;
- return Value > long.MaxValue ? long.MaxValue :
- Value < long.MinValue ? long.MinValue : (long)Value;
+ return value > long.MaxValue ? long.MaxValue :
+ value < long.MinValue ? long.MinValue : (long)value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static uint SatF64ToU32(double Value)
+ public static uint SatF64ToU32(double value)
{
- if (double.IsNaN(Value)) return 0;
+ if (double.IsNaN(value)) return 0;
- return Value > uint.MaxValue ? uint.MaxValue :
- Value < uint.MinValue ? uint.MinValue : (uint)Value;
+ return value > uint.MaxValue ? uint.MaxValue :
+ value < uint.MinValue ? uint.MinValue : (uint)value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ulong SatF64ToU64(double Value)
+ public static ulong SatF64ToU64(double value)
{
- if (double.IsNaN(Value)) return 0;
+ if (double.IsNaN(value)) return 0;
- return Value > ulong.MaxValue ? ulong.MaxValue :
- Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
+ return value > ulong.MaxValue ? ulong.MaxValue :
+ value < ulong.MinValue ? ulong.MinValue : (ulong)value;
}
- public static double Round(double Value, AThreadState State)
+ public static double Round(double value, CpuThreadState state)
{
- switch (State.FPRoundingMode())
+ switch (state.FPRoundingMode())
{
- case ARoundMode.ToNearest: return Math.Round (Value);
- case ARoundMode.TowardsPlusInfinity: return Math.Ceiling (Value);
- case ARoundMode.TowardsMinusInfinity: return Math.Floor (Value);
- case ARoundMode.TowardsZero: return Math.Truncate(Value);
+ case RoundMode.ToNearest: return Math.Round (value);
+ case RoundMode.TowardsPlusInfinity: return Math.Ceiling (value);
+ case RoundMode.TowardsMinusInfinity: return Math.Floor (value);
+ case RoundMode.TowardsZero: return Math.Truncate(value);
}
throw new InvalidOperationException();
}
- public static float RoundF(float Value, AThreadState State)
+ public static float RoundF(float value, CpuThreadState state)
{
- switch (State.FPRoundingMode())
+ switch (state.FPRoundingMode())
{
- case ARoundMode.ToNearest: return MathF.Round (Value);
- case ARoundMode.TowardsPlusInfinity: return MathF.Ceiling (Value);
- case ARoundMode.TowardsMinusInfinity: return MathF.Floor (Value);
- case ARoundMode.TowardsZero: return MathF.Truncate(Value);
+ case RoundMode.ToNearest: return MathF.Round (value);
+ case RoundMode.TowardsPlusInfinity: return MathF.Ceiling (value);
+ case RoundMode.TowardsMinusInfinity: return MathF.Floor (value);
+ case RoundMode.TowardsZero: return MathF.Truncate(value);
}
throw new InvalidOperationException();
}
public static Vector128<float> Tbl1_V64(
- Vector128<float> Vector,
- Vector128<float> Tb0)
+ Vector128<float> vector,
+ Vector128<float> tb0)
{
- return Tbl(Vector, 8, Tb0);
+ return Tbl(vector, 8, tb0);
}
public static Vector128<float> Tbl1_V128(
- Vector128<float> Vector,
- Vector128<float> Tb0)
+ Vector128<float> vector,
+ Vector128<float> tb0)
{
- return Tbl(Vector, 16, Tb0);
+ return Tbl(vector, 16, tb0);
}
public static Vector128<float> Tbl2_V64(
- Vector128<float> Vector,
- Vector128<float> Tb0,
- Vector128<float> Tb1)
+ Vector128<float> vector,
+ Vector128<float> tb0,
+ Vector128<float> tb1)
{
- return Tbl(Vector, 8, Tb0, Tb1);
+ return Tbl(vector, 8, tb0, tb1);
}
public static Vector128<float> Tbl2_V128(
- Vector128<float> Vector,
- Vector128<float> Tb0,
- Vector128<float> Tb1)
+ Vector128<float> vector,
+ Vector128<float> tb0,
+ Vector128<float> tb1)
{
- return Tbl(Vector, 16, Tb0, Tb1);
+ return Tbl(vector, 16, tb0, tb1);
}
public static Vector128<float> Tbl3_V64(
- Vector128<float> Vector,
- Vector128<float> Tb0,
- Vector128<float> Tb1,
- Vector128<float> Tb2)
+ Vector128<float> vector,
+ Vector128<float> tb0,
+ Vector128<float> tb1,
+ Vector128<float> tb2)
{
- return Tbl(Vector, 8, Tb0, Tb1, Tb2);
+ return Tbl(vector, 8, tb0, tb1, tb2);
}
public static Vector128<float> Tbl3_V128(
- Vector128<float> Vector,
- Vector128<float> Tb0,
- Vector128<float> Tb1,
- Vector128<float> Tb2)
+ Vector128<float> vector,
+ Vector128<float> tb0,
+ Vector128<float> tb1,
+ Vector128<float> tb2)
{
- return Tbl(Vector, 16, Tb0, Tb1, Tb2);
+ return Tbl(vector, 16, tb0, tb1, tb2);
}
public static Vector128<float> Tbl4_V64(
- Vector128<float> Vector,
- Vector128<float> Tb0,
- Vector128<float> Tb1,
- Vector128<float> Tb2,
- Vector128<float> Tb3)
+ Vector128<float> vector,
+ Vector128<float> tb0,
+ Vector128<float> tb1,
+ Vector128<float> tb2,
+ Vector128<float> tb3)
{
- return Tbl(Vector, 8, Tb0, Tb1, Tb2, Tb3);
+ return Tbl(vector, 8, tb0, tb1, tb2, tb3);
}
public static Vector128<float> Tbl4_V128(
- Vector128<float> Vector,
- Vector128<float> Tb0,
- Vector128<float> Tb1,
- Vector128<float> Tb2,
- Vector128<float> Tb3)
+ Vector128<float> vector,
+ Vector128<float> tb0,
+ Vector128<float> tb1,
+ Vector128<float> tb2,
+ Vector128<float> tb3)
{
- return Tbl(Vector, 16, Tb0, Tb1, Tb2, Tb3);
+ return Tbl(vector, 16, tb0, tb1, tb2, tb3);
}
- private static Vector128<float> Tbl(Vector128<float> Vector, int Bytes, params Vector128<float>[] Tb)
+ private static Vector128<float> Tbl(Vector128<float> vector, int bytes, params Vector128<float>[] tb)
{
- Vector128<float> Res = new Vector128<float>();
+ Vector128<float> res = new Vector128<float>();
- byte[] Table = new byte[Tb.Length * 16];
+ byte[] table = new byte[tb.Length * 16];
- for (byte Index = 0; Index < Tb.Length; Index++)
- for (byte Index2 = 0; Index2 < 16; Index2++)
+ 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);
+ table[index * 16 + index2] = (byte)VectorExtractIntZx(tb[index], index2, 0);
}
- for (byte Index = 0; Index < Bytes; Index++)
+ for (byte index = 0; index < bytes; index++)
{
- byte TblIdx = (byte)VectorExtractIntZx(Vector, Index, 0);
+ byte tblIdx = (byte)VectorExtractIntZx(vector, index, 0);
- if (TblIdx < Table.Length)
+ if (tblIdx < table.Length)
{
- Res = VectorInsertInt(Table[TblIdx], Res, Index, 0);
+ res = VectorInsertInt(table[tblIdx], res, index, 0);
}
}
- return Res;
+ return res;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static double VectorExtractDouble(Vector128<float> Vector, byte Index)
+ public static double VectorExtractDouble(Vector128<float> vector, byte index)
{
if (Sse41.IsSupported)
{
- return BitConverter.Int64BitsToDouble(Sse41.Extract(Sse.StaticCast<float, long>(Vector), Index));
+ return BitConverter.Int64BitsToDouble(Sse41.Extract(Sse.StaticCast<float, long>(vector), index));
}
else if (Sse2.IsSupported)
{
- return BitConverter.Int64BitsToDouble((long)VectorExtractIntZx(Vector, Index, 3));
+ return BitConverter.Int64BitsToDouble((long)VectorExtractIntZx(vector, index, 3));
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static long VectorExtractIntSx(Vector128<float> Vector, byte Index, int Size)
+ public static long VectorExtractIntSx(Vector128<float> vector, byte index, int size)
{
if (Sse41.IsSupported)
{
- if (Size == 0)
+ if (size == 0)
{
- return (sbyte)Sse41.Extract(Sse.StaticCast<float, byte>(Vector), Index);
+ return (sbyte)Sse41.Extract(Sse.StaticCast<float, byte>(vector), index);
}
- else if (Size == 1)
+ else if (size == 1)
{
- return (short)Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), Index);
+ return (short)Sse2.Extract(Sse.StaticCast<float, ushort>(vector), index);
}
- else if (Size == 2)
+ else if (size == 2)
{
- return Sse41.Extract(Sse.StaticCast<float, int>(Vector), Index);
+ return Sse41.Extract(Sse.StaticCast<float, int>(vector), index);
}
- else if (Size == 3)
+ else if (size == 3)
{
- return Sse41.Extract(Sse.StaticCast<float, long>(Vector), Index);
+ return Sse41.Extract(Sse.StaticCast<float, long>(vector), index);
}
else
{
- throw new ArgumentOutOfRangeException(nameof(Size));
+ throw new ArgumentOutOfRangeException(nameof(size));
}
}
else if (Sse2.IsSupported)
{
- if (Size == 0)
+ if (size == 0)
{
- return (sbyte)VectorExtractIntZx(Vector, Index, Size);
+ return (sbyte)VectorExtractIntZx(vector, index, size);
}
- else if (Size == 1)
+ else if (size == 1)
{
- return (short)VectorExtractIntZx(Vector, Index, Size);
+ return (short)VectorExtractIntZx(vector, index, size);
}
- else if (Size == 2)
+ else if (size == 2)
{
- return (int)VectorExtractIntZx(Vector, Index, Size);
+ return (int)VectorExtractIntZx(vector, index, size);
}
- else if (Size == 3)
+ else if (size == 3)
{
- return (long)VectorExtractIntZx(Vector, Index, Size);
+ return (long)VectorExtractIntZx(vector, index, size);
}
else
{
- throw new ArgumentOutOfRangeException(nameof(Size));
+ throw new ArgumentOutOfRangeException(nameof(size));
}
}
@@ -293,67 +293,67 @@ namespace ChocolArm64.Instruction
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ulong VectorExtractIntZx(Vector128<float> Vector, byte Index, int Size)
+ public static ulong VectorExtractIntZx(Vector128<float> vector, byte index, int size)
{
if (Sse41.IsSupported)
{
- if (Size == 0)
+ if (size == 0)
{
- return Sse41.Extract(Sse.StaticCast<float, byte>(Vector), Index);
+ return Sse41.Extract(Sse.StaticCast<float, byte>(vector), index);
}
- else if (Size == 1)
+ else if (size == 1)
{
- return Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), Index);
+ return Sse2.Extract(Sse.StaticCast<float, ushort>(vector), index);
}
- else if (Size == 2)
+ else if (size == 2)
{
- return Sse41.Extract(Sse.StaticCast<float, uint>(Vector), Index);
+ return Sse41.Extract(Sse.StaticCast<float, uint>(vector), index);
}
- else if (Size == 3)
+ else if (size == 3)
{
- return Sse41.Extract(Sse.StaticCast<float, ulong>(Vector), Index);
+ return Sse41.Extract(Sse.StaticCast<float, ulong>(vector), index);
}
else
{
- throw new ArgumentOutOfRangeException(nameof(Size));
+ throw new ArgumentOutOfRangeException(nameof(size));
}
}
else if (Sse2.IsSupported)
{
- int ShortIdx = Size == 0
- ? Index >> 1
- : Index << (Size - 1);
+ int shortIdx = size == 0
+ ? index >> 1
+ : index << (size - 1);
- ushort Value = Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), (byte)ShortIdx);
+ ushort value = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)shortIdx);
- if (Size == 0)
+ if (size == 0)
{
- return (byte)(Value >> (Index & 1) * 8);
+ return (byte)(value >> (index & 1) * 8);
}
- else if (Size == 1)
+ else if (size == 1)
{
- return Value;
+ return value;
}
- else if (Size == 2 || Size == 3)
+ else if (size == 2 || size == 3)
{
- ushort Value1 = Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), (byte)(ShortIdx + 1));
+ ushort value1 = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)(shortIdx + 1));
- if (Size == 2)
+ if (size == 2)
{
- return (uint)(Value | (Value1 << 16));
+ return (uint)(value | (value1 << 16));
}
- ushort Value2 = Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), (byte)(ShortIdx + 2));
- ushort Value3 = Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), (byte)(ShortIdx + 3));
+ ushort value2 = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)(shortIdx + 2));
+ ushort value3 = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)(shortIdx + 3));
- return ((ulong)Value << 0) |
- ((ulong)Value1 << 16) |
- ((ulong)Value2 << 32) |
- ((ulong)Value3 << 48);
+ return ((ulong)value << 0) |
+ ((ulong)value1 << 16) |
+ ((ulong)value2 << 32) |
+ ((ulong)value3 << 48);
}
else
{
- throw new ArgumentOutOfRangeException(nameof(Size));
+ throw new ArgumentOutOfRangeException(nameof(size));
}
}
@@ -361,97 +361,97 @@ namespace ChocolArm64.Instruction
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static float VectorExtractSingle(Vector128<float> Vector, byte Index)
+ public static float VectorExtractSingle(Vector128<float> vector, byte index)
{
if (Sse41.IsSupported)
{
- return Sse41.Extract(Vector, Index);
+ return Sse41.Extract(vector, index);
}
else if (Sse2.IsSupported)
{
- Vector128<ushort> ShortVector = Sse.StaticCast<float, ushort>(Vector);
+ Vector128<ushort> shortVector = Sse.StaticCast<float, ushort>(vector);
- int Low = Sse2.Extract(ShortVector, (byte)(Index * 2 + 0));
- int High = Sse2.Extract(ShortVector, (byte)(Index * 2 + 1));
+ int low = Sse2.Extract(shortVector, (byte)(index * 2 + 0));
+ int high = Sse2.Extract(shortVector, (byte)(index * 2 + 1));
- return BitConverter.Int32BitsToSingle(Low | (High << 16));
+ return BitConverter.Int32BitsToSingle(low | (high << 16));
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorInsertDouble(double Value, Vector128<float> Vector, byte Index)
+ public static Vector128<float> VectorInsertDouble(double value, Vector128<float> vector, byte index)
{
- return VectorInsertInt((ulong)BitConverter.DoubleToInt64Bits(Value), Vector, Index, 3);
+ return VectorInsertInt((ulong)BitConverter.DoubleToInt64Bits(value), vector, index, 3);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorInsertInt(ulong Value, Vector128<float> Vector, byte Index, int Size)
+ public static Vector128<float> VectorInsertInt(ulong value, Vector128<float> vector, byte index, int size)
{
if (Sse41.IsSupported)
{
- if (Size == 0)
+ if (size == 0)
{
- return Sse.StaticCast<byte, float>(Sse41.Insert(Sse.StaticCast<float, byte>(Vector), (byte)Value, Index));
+ return Sse.StaticCast<byte, float>(Sse41.Insert(Sse.StaticCast<float, byte>(vector), (byte)value, index));
}
- else if (Size == 1)
+ else if (size == 1)
{
- return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse.StaticCast<float, ushort>(Vector), (ushort)Value, Index));
+ return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse.StaticCast<float, ushort>(vector), (ushort)value, index));
}
- else if (Size == 2)
+ else if (size == 2)
{
- return Sse.StaticCast<uint, float>(Sse41.Insert(Sse.StaticCast<float, uint>(Vector), (uint)Value, Index));
+ return Sse.StaticCast<uint, float>(Sse41.Insert(Sse.StaticCast<float, uint>(vector), (uint)value, index));
}
- else if (Size == 3)
+ else if (size == 3)
{
- return Sse.StaticCast<ulong, float>(Sse41.Insert(Sse.StaticCast<float, ulong>(Vector), Value, Index));
+ return Sse.StaticCast<ulong, float>(Sse41.Insert(Sse.StaticCast<float, ulong>(vector), value, index));
}
else
{
- throw new ArgumentOutOfRangeException(nameof(Size));
+ throw new ArgumentOutOfRangeException(nameof(size));
}
}
else if (Sse2.IsSupported)
{
- Vector128<ushort> ShortVector = Sse.StaticCast<float, ushort>(Vector);
+ Vector128<ushort> shortVector = Sse.StaticCast<float, ushort>(vector);
- int ShortIdx = Size == 0
- ? Index >> 1
- : Index << (Size - 1);
+ int shortIdx = size == 0
+ ? index >> 1
+ : index << (size - 1);
- if (Size == 0)
+ if (size == 0)
{
- ushort ShortVal = Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), (byte)ShortIdx);
+ ushort shortVal = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)shortIdx);
- int Shift = (Index & 1) * 8;
+ int shift = (index & 1) * 8;
- ShortVal &= (ushort)(0xff00 >> Shift);
+ shortVal &= (ushort)(0xff00 >> shift);
- ShortVal |= (ushort)((byte)Value << Shift);
+ shortVal |= (ushort)((byte)value << shift);
- return Sse.StaticCast<ushort, float>(Sse2.Insert(ShortVector, ShortVal, (byte)ShortIdx));
+ return Sse.StaticCast<ushort, float>(Sse2.Insert(shortVector, shortVal, (byte)shortIdx));
}
- else if (Size == 1)
+ else if (size == 1)
{
- return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse.StaticCast<float, ushort>(Vector), (ushort)Value, Index));
+ return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse.StaticCast<float, ushort>(vector), (ushort)value, index));
}
- else if (Size == 2 || Size == 3)
+ 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));
+ shortVector = Sse2.Insert(shortVector, (ushort)(value >> 0), (byte)(shortIdx + 0));
+ shortVector = Sse2.Insert(shortVector, (ushort)(value >> 16), (byte)(shortIdx + 1));
- if (Size == 3)
+ if (size == 3)
{
- ShortVector = Sse2.Insert(ShortVector, (ushort)(Value >> 32), (byte)(ShortIdx + 2));
- ShortVector = Sse2.Insert(ShortVector, (ushort)(Value >> 48), (byte)(ShortIdx + 3));
+ shortVector = Sse2.Insert(shortVector, (ushort)(value >> 32), (byte)(shortIdx + 2));
+ shortVector = Sse2.Insert(shortVector, (ushort)(value >> 48), (byte)(shortIdx + 3));
}
- return Sse.StaticCast<ushort, float>(ShortVector);
+ return Sse.StaticCast<ushort, float>(shortVector);
}
else
{
- throw new ArgumentOutOfRangeException(nameof(Size));
+ throw new ArgumentOutOfRangeException(nameof(size));
}
}
@@ -459,57 +459,57 @@ namespace ChocolArm64.Instruction
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorInsertSingle(float Value, Vector128<float> Vector, byte Index)
+ public static Vector128<float> VectorInsertSingle(float value, Vector128<float> vector, byte index)
{
if (Sse41.IsSupported)
{
//Note: The if/else if is necessary to enable the JIT to
//produce a single INSERTPS instruction instead of the
//jump table fallback.
- if (Index == 0)
+ if (index == 0)
{
- return Sse41.Insert(Vector, Value, 0x00);
+ return Sse41.Insert(vector, value, 0x00);
}
- else if (Index == 1)
+ else if (index == 1)
{
- return Sse41.Insert(Vector, Value, 0x10);
+ return Sse41.Insert(vector, value, 0x10);
}
- else if (Index == 2)
+ else if (index == 2)
{
- return Sse41.Insert(Vector, Value, 0x20);
+ return Sse41.Insert(vector, value, 0x20);
}
- else if (Index == 3)
+ else if (index == 3)
{
- return Sse41.Insert(Vector, Value, 0x30);
+ return Sse41.Insert(vector, value, 0x30);
}
else
{
- throw new ArgumentOutOfRangeException(nameof(Index));
+ throw new ArgumentOutOfRangeException(nameof(index));
}
}
else if (Sse2.IsSupported)
{
- int IntValue = BitConverter.SingleToInt32Bits(Value);
+ int intValue = BitConverter.SingleToInt32Bits(value);
- ushort Low = (ushort)(IntValue >> 0);
- ushort High = (ushort)(IntValue >> 16);
+ ushort low = (ushort)(intValue >> 0);
+ ushort high = (ushort)(intValue >> 16);
- Vector128<ushort> ShortVector = Sse.StaticCast<float, ushort>(Vector);
+ Vector128<ushort> shortVector = Sse.StaticCast<float, ushort>(vector);
- ShortVector = Sse2.Insert(ShortVector, Low, (byte)(Index * 2 + 0));
- ShortVector = Sse2.Insert(ShortVector, High, (byte)(Index * 2 + 1));
+ shortVector = Sse2.Insert(shortVector, low, (byte)(index * 2 + 0));
+ shortVector = Sse2.Insert(shortVector, high, (byte)(index * 2 + 1));
- return Sse.StaticCast<ushort, float>(ShortVector);
+ return Sse.StaticCast<ushort, float>(shortVector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> Sse41VectorInsertScalarSingle(float Value, Vector128<float> Vector)
+ public static Vector128<float> Sse41VectorInsertScalarSingle(float value, Vector128<float> vector)
{
//Note: 0b1110 is the mask to zero the upper bits.
- return Sse41.Insert(Vector, Value, 0b1110);
+ return Sse41.Insert(vector, value, 0b1110);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -579,209 +579,209 @@ namespace ChocolArm64.Instruction
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorZero32_128(Vector128<float> Vector)
+ public static Vector128<float> VectorZero32_128(Vector128<float> vector)
{
if (Sse.IsSupported)
{
- return Sse.And(Vector, Zero32_128Mask);
+ return Sse.And(vector, Zero32128Mask);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<sbyte> VectorSingleToSByte(Vector128<float> Vector)
+ public static Vector128<sbyte> VectorSingleToSByte(Vector128<float> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<float, sbyte>(Vector);
+ return Sse.StaticCast<float, sbyte>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<short> VectorSingleToInt16(Vector128<float> Vector)
+ public static Vector128<short> VectorSingleToInt16(Vector128<float> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<float, short>(Vector);
+ return Sse.StaticCast<float, short>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<int> VectorSingleToInt32(Vector128<float> Vector)
+ public static Vector128<int> VectorSingleToInt32(Vector128<float> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<float, int>(Vector);
+ return Sse.StaticCast<float, int>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<long> VectorSingleToInt64(Vector128<float> Vector)
+ public static Vector128<long> VectorSingleToInt64(Vector128<float> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<float, long>(Vector);
+ return Sse.StaticCast<float, long>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<byte> VectorSingleToByte(Vector128<float> Vector)
+ public static Vector128<byte> VectorSingleToByte(Vector128<float> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<float, byte>(Vector);
+ return Sse.StaticCast<float, byte>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<ushort> VectorSingleToUInt16(Vector128<float> Vector)
+ public static Vector128<ushort> VectorSingleToUInt16(Vector128<float> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<float, ushort>(Vector);
+ return Sse.StaticCast<float, ushort>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<uint> VectorSingleToUInt32(Vector128<float> Vector)
+ public static Vector128<uint> VectorSingleToUInt32(Vector128<float> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<float, uint>(Vector);
+ return Sse.StaticCast<float, uint>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<ulong> VectorSingleToUInt64(Vector128<float> Vector)
+ public static Vector128<ulong> VectorSingleToUInt64(Vector128<float> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<float, ulong>(Vector);
+ return Sse.StaticCast<float, ulong>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<double> VectorSingleToDouble(Vector128<float> Vector)
+ public static Vector128<double> VectorSingleToDouble(Vector128<float> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<float, double>(Vector);
+ return Sse.StaticCast<float, double>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorSByteToSingle(Vector128<sbyte> Vector)
+ public static Vector128<float> VectorSByteToSingle(Vector128<sbyte> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<sbyte, float>(Vector);
+ return Sse.StaticCast<sbyte, float>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorInt16ToSingle(Vector128<short> Vector)
+ public static Vector128<float> VectorInt16ToSingle(Vector128<short> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<short, float>(Vector);
+ return Sse.StaticCast<short, float>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorInt32ToSingle(Vector128<int> Vector)
+ public static Vector128<float> VectorInt32ToSingle(Vector128<int> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<int, float>(Vector);
+ return Sse.StaticCast<int, float>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorInt64ToSingle(Vector128<long> Vector)
+ public static Vector128<float> VectorInt64ToSingle(Vector128<long> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<long, float>(Vector);
+ return Sse.StaticCast<long, float>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorByteToSingle(Vector128<byte> Vector)
+ public static Vector128<float> VectorByteToSingle(Vector128<byte> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<byte, float>(Vector);
+ return Sse.StaticCast<byte, float>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorUInt16ToSingle(Vector128<ushort> Vector)
+ public static Vector128<float> VectorUInt16ToSingle(Vector128<ushort> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<ushort, float>(Vector);
+ return Sse.StaticCast<ushort, float>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorUInt32ToSingle(Vector128<uint> Vector)
+ public static Vector128<float> VectorUInt32ToSingle(Vector128<uint> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<uint, float>(Vector);
+ return Sse.StaticCast<uint, float>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorUInt64ToSingle(Vector128<ulong> Vector)
+ public static Vector128<float> VectorUInt64ToSingle(Vector128<ulong> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<ulong, float>(Vector);
+ return Sse.StaticCast<ulong, float>(vector);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorDoubleToSingle(Vector128<double> Vector)
+ public static Vector128<float> VectorDoubleToSingle(Vector128<double> vector)
{
if (Sse.IsSupported)
{
- return Sse.StaticCast<double, float>(Vector);
+ return Sse.StaticCast<double, float>(vector);
}
throw new PlatformNotSupportedException();
diff --git a/ChocolArm64/Instruction32/A32InstInterpretAlu.cs b/ChocolArm64/Instructions32/A32InstInterpretAlu.cs
index 41b9d22a..f3be823f 100644
--- a/ChocolArm64/Instruction32/A32InstInterpretAlu.cs
+++ b/ChocolArm64/Instructions32/A32InstInterpretAlu.cs
@@ -1,4 +1,4 @@
-namespace ChocolArm64.Instruction32
+namespace ChocolArm64.Instructions32
{
static partial class A32InstInterpret
{
diff --git a/ChocolArm64/Instructions32/A32InstInterpretFlow.cs b/ChocolArm64/Instructions32/A32InstInterpretFlow.cs
new file mode 100644
index 00000000..cdf7e4c6
--- /dev/null
+++ b/ChocolArm64/Instructions32/A32InstInterpretFlow.cs
@@ -0,0 +1,70 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.Decoders32;
+using ChocolArm64.Memory;
+using ChocolArm64.State;
+
+using static ChocolArm64.Instructions32.A32InstInterpretHelper;
+
+namespace ChocolArm64.Instructions32
+{
+ static partial class A32InstInterpret
+ {
+ public static void B(CpuThreadState state, MemoryManager memory, OpCode64 opCode)
+ {
+ A32OpCodeBImmAl op = (A32OpCodeBImmAl)opCode;
+
+ if (IsConditionTrue(state, op.Cond))
+ {
+ BranchWritePc(state, GetPc(state) + (uint)op.Imm);
+ }
+ }
+
+ public static void Bl(CpuThreadState state, MemoryManager memory, OpCode64 opCode)
+ {
+ Blx(state, memory, opCode, false);
+ }
+
+ public static void Blx(CpuThreadState state, MemoryManager memory, OpCode64 opCode)
+ {
+ Blx(state, memory, opCode, true);
+ }
+
+ public static void Blx(CpuThreadState state, MemoryManager memory, OpCode64 opCode, bool x)
+ {
+ A32OpCodeBImmAl op = (A32OpCodeBImmAl)opCode;
+
+ if (IsConditionTrue(state, op.Cond))
+ {
+ uint pc = GetPc(state);
+
+ if (state.Thumb)
+ {
+ state.R14 = pc | 1;
+ }
+ else
+ {
+ state.R14 = pc - 4U;
+ }
+
+ if (x)
+ {
+ state.Thumb = !state.Thumb;
+ }
+
+ if (!state.Thumb)
+ {
+ pc &= ~3U;
+ }
+
+ BranchWritePc(state, pc + (uint)op.Imm);
+ }
+ }
+
+ private static void BranchWritePc(CpuThreadState state, uint pc)
+ {
+ state.R15 = state.Thumb
+ ? pc & ~1U
+ : pc & ~3U;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Instructions32/A32InstInterpretHelper.cs b/ChocolArm64/Instructions32/A32InstInterpretHelper.cs
new file mode 100644
index 00000000..b08e1298
--- /dev/null
+++ b/ChocolArm64/Instructions32/A32InstInterpretHelper.cs
@@ -0,0 +1,65 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.State;
+using System;
+
+namespace ChocolArm64.Instructions32
+{
+ static class A32InstInterpretHelper
+ {
+ public static bool IsConditionTrue(CpuThreadState state, Cond cond)
+ {
+ switch (cond)
+ {
+ case Cond.Eq: return state.Zero;
+ case Cond.Ne: return !state.Zero;
+ case Cond.GeUn: return state.Carry;
+ case Cond.LtUn: return !state.Carry;
+ case Cond.Mi: return state.Negative;
+ case Cond.Pl: return !state.Negative;
+ case Cond.Vs: return state.Overflow;
+ case Cond.Vc: return !state.Overflow;
+ case Cond.GtUn: return state.Carry && !state.Zero;
+ case Cond.LeUn: return !state.Carry && state.Zero;
+ case Cond.Ge: return state.Negative == state.Overflow;
+ case Cond.Lt: return state.Negative != state.Overflow;
+ case Cond.Gt: return state.Negative == state.Overflow && !state.Zero;
+ case Cond.Le: return state.Negative != state.Overflow && state.Zero;
+ }
+
+ return true;
+ }
+
+ public unsafe static uint GetReg(CpuThreadState state, int reg)
+ {
+ if ((uint)reg > 15)
+ {
+ throw new ArgumentOutOfRangeException(nameof(reg));
+ }
+
+ fixed (uint* ptr = &state.R0)
+ {
+ return *(ptr + reg);
+ }
+ }
+
+ public unsafe static void SetReg(CpuThreadState state, int reg, uint value)
+ {
+ if ((uint)reg > 15)
+ {
+ throw new ArgumentOutOfRangeException(nameof(reg));
+ }
+
+ fixed (uint* ptr = &state.R0)
+ {
+ *(ptr + reg) = value;
+ }
+ }
+
+ public static uint GetPc(CpuThreadState state)
+ {
+ //Due to the old fetch-decode-execute pipeline of old ARM CPUs,
+ //the PC is 4 or 8 bytes (2 instructions) ahead of the current instruction.
+ return state.R15 + (state.Thumb ? 2U : 4U);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs
deleted file mode 100644
index 2854871e..00000000
--- a/ChocolArm64/Memory/AMemory.cs
+++ /dev/null
@@ -1,745 +0,0 @@
-using ChocolArm64.Events;
-using ChocolArm64.Exceptions;
-using ChocolArm64.State;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-using System.Threading;
-
-namespace ChocolArm64.Memory
-{
- public unsafe class AMemory : IAMemory, IDisposable
- {
- private const int PTLvl0Bits = 13;
- private const int PTLvl1Bits = 14;
- private const int PTPageBits = 12;
-
- private const int PTLvl0Size = 1 << PTLvl0Bits;
- private const int PTLvl1Size = 1 << PTLvl1Bits;
- public const int PageSize = 1 << PTPageBits;
-
- private const int PTLvl0Mask = PTLvl0Size - 1;
- private const int PTLvl1Mask = PTLvl1Size - 1;
- public const int PageMask = PageSize - 1;
-
- private const int PTLvl0Bit = PTPageBits + PTLvl1Bits;
- private const int PTLvl1Bit = PTPageBits;
-
- private const long ErgMask = (4 << AThreadState.ErgSizeLog2) - 1;
-
- private class ArmMonitor
- {
- public long Position;
- public bool ExState;
-
- public bool HasExclusiveAccess(long Position)
- {
- return this.Position == Position && ExState;
- }
- }
-
- private Dictionary<int, ArmMonitor> Monitors;
-
- private ConcurrentDictionary<long, IntPtr> ObservedPages;
-
- public IntPtr Ram { get; private set; }
-
- private byte* RamPtr;
-
- private byte*** PageTable;
-
- public event EventHandler<AInvalidAccessEventArgs> InvalidAccess;
-
- public AMemory(IntPtr Ram)
- {
- Monitors = new Dictionary<int, ArmMonitor>();
-
- ObservedPages = new ConcurrentDictionary<long, IntPtr>();
-
- this.Ram = Ram;
-
- RamPtr = (byte*)Ram;
-
- PageTable = (byte***)Marshal.AllocHGlobal(PTLvl0Size * IntPtr.Size);
-
- for (int L0 = 0; L0 < PTLvl0Size; L0++)
- {
- PageTable[L0] = null;
- }
- }
-
- public void RemoveMonitor(int Core)
- {
- lock (Monitors)
- {
- ClearExclusive(Core);
-
- Monitors.Remove(Core);
- }
- }
-
- public void SetExclusive(int Core, long Position)
- {
- Position &= ~ErgMask;
-
- lock (Monitors)
- {
- foreach (ArmMonitor Mon in Monitors.Values)
- {
- if (Mon.Position == Position && Mon.ExState)
- {
- Mon.ExState = false;
- }
- }
-
- if (!Monitors.TryGetValue(Core, out ArmMonitor ThreadMon))
- {
- ThreadMon = new ArmMonitor();
-
- Monitors.Add(Core, ThreadMon);
- }
-
- ThreadMon.Position = Position;
- ThreadMon.ExState = true;
- }
- }
-
- public bool TestExclusive(int Core, long Position)
- {
- //Note: Any call to this method also should be followed by a
- //call to ClearExclusiveForStore if this method returns true.
- Position &= ~ErgMask;
-
- Monitor.Enter(Monitors);
-
- if (!Monitors.TryGetValue(Core, out ArmMonitor ThreadMon))
- {
- return false;
- }
-
- bool ExState = ThreadMon.HasExclusiveAccess(Position);
-
- if (!ExState)
- {
- Monitor.Exit(Monitors);
- }
-
- return ExState;
- }
-
- public void ClearExclusiveForStore(int Core)
- {
- if (Monitors.TryGetValue(Core, out ArmMonitor ThreadMon))
- {
- ThreadMon.ExState = false;
- }
-
- Monitor.Exit(Monitors);
- }
-
- public void ClearExclusive(int Core)
- {
- lock (Monitors)
- {
- if (Monitors.TryGetValue(Core, out ArmMonitor ThreadMon))
- {
- ThreadMon.ExState = false;
- }
- }
- }
-
- public void WriteInt32ToSharedAddr(long Position, int Value)
- {
- long MaskedPosition = Position & ~ErgMask;
-
- lock (Monitors)
- {
- foreach (ArmMonitor Mon in Monitors.Values)
- {
- if (Mon.Position == MaskedPosition && Mon.ExState)
- {
- Mon.ExState = false;
- }
- }
-
- WriteInt32(Position, Value);
- }
- }
-
- 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)
- {
- return *((ushort*)Translate(Position));
- }
-
- public uint ReadUInt32(long Position)
- {
- return *((uint*)Translate(Position));
- }
-
- public ulong ReadUInt64(long Position)
- {
- return *((ulong*)Translate(Position));
- }
-
- public Vector128<float> ReadVector8(long Position)
- {
- if (Sse2.IsSupported)
- {
- return Sse.StaticCast<byte, float>(Sse2.SetVector128(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ReadByte(Position)));
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector128<float> ReadVector16(long Position)
- {
- if (Sse2.IsSupported)
- {
- return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse2.SetZeroVector128<ushort>(), ReadUInt16(Position), 0));
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector128<float> ReadVector32(long Position)
- {
- if (Sse.IsSupported)
- {
- return Sse.LoadScalarVector128((float*)Translate(Position));
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector128<float> ReadVector64(long Position)
- {
- if (Sse2.IsSupported)
- {
- return Sse.StaticCast<double, float>(Sse2.LoadScalarVector128((double*)Translate(Position)));
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector128<float> ReadVector128(long Position)
- {
- if (Sse.IsSupported)
- {
- return Sse.LoadVector128((float*)Translate(Position));
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public byte[] ReadBytes(long Position, long Size)
- {
- if ((uint)Size > int.MaxValue)
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- EnsureRangeIsValid(Position, Size);
-
- byte[] Data = new byte[Size];
-
- Marshal.Copy((IntPtr)Translate(Position), Data, 0, (int)Size);
-
- return Data;
- }
-
- public void ReadBytes(long Position, byte[] Data, int StartIndex, int Size)
- {
- //Note: This will be moved later.
- EnsureRangeIsValid(Position, (uint)Size);
-
- Marshal.Copy((IntPtr)Translate(Position), Data, StartIndex, Size);
- }
-
- 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)
- {
- *((ushort*)TranslateWrite(Position)) = Value;
- }
-
- public void WriteUInt32(long Position, uint Value)
- {
- *((uint*)TranslateWrite(Position)) = Value;
- }
-
- public void WriteUInt64(long Position, ulong Value)
- {
- *((ulong*)TranslateWrite(Position)) = Value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void WriteVector8(long Position, Vector128<float> Value)
- {
- if (Sse41.IsSupported)
- {
- WriteByte(Position, Sse41.Extract(Sse.StaticCast<float, byte>(Value), 0));
- }
- else if (Sse2.IsSupported)
- {
- WriteByte(Position, (byte)Sse2.Extract(Sse.StaticCast<float, ushort>(Value), 0));
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void WriteVector16(long Position, Vector128<float> Value)
- {
- if (Sse2.IsSupported)
- {
- WriteUInt16(Position, Sse2.Extract(Sse.StaticCast<float, ushort>(Value), 0));
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void WriteVector32(long Position, Vector128<float> Value)
- {
- if (Sse.IsSupported)
- {
- Sse.StoreScalar((float*)TranslateWrite(Position), Value);
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void WriteVector64(long Position, Vector128<float> Value)
- {
- if (Sse2.IsSupported)
- {
- Sse2.StoreScalar((double*)TranslateWrite(Position), Sse.StaticCast<float, double>(Value));
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void WriteVector128(long Position, Vector128<float> Value)
- {
- if (Sse.IsSupported)
- {
- Sse.Store((float*)TranslateWrite(Position), Value);
- }
- else
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public void WriteBytes(long Position, byte[] Data)
- {
- EnsureRangeIsValid(Position, (uint)Data.Length);
-
- Marshal.Copy(Data, 0, (IntPtr)TranslateWrite(Position), Data.Length);
- }
-
- public void WriteBytes(long Position, byte[] Data, int StartIndex, int Size)
- {
- //Note: This will be moved later.
- //Using Translate instead of TranslateWrite is on purpose.
- EnsureRangeIsValid(Position, (uint)Size);
-
- Marshal.Copy(Data, StartIndex, (IntPtr)Translate(Position), Size);
- }
-
- public void CopyBytes(long Src, long Dst, long Size)
- {
- //Note: This will be moved later.
- EnsureRangeIsValid(Src, Size);
- EnsureRangeIsValid(Dst, Size);
-
- byte* SrcPtr = Translate(Src);
- byte* DstPtr = TranslateWrite(Dst);
-
- Buffer.MemoryCopy(SrcPtr, DstPtr, Size, 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);
-
- StopObservingRegion(Position, Size);
- }
-
- public bool IsMapped(long Position)
- {
- if (!(IsValidPosition(Position)))
- {
- return false;
- }
-
- long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
- long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask;
-
- if (PageTable[L0] == null)
- {
- return false;
- }
-
- return PageTable[L0][L1] != null || ObservedPages.ContainsKey(Position >> PTPageBits);
- }
-
- public long GetPhysicalAddress(long VirtualAddress)
- {
- byte* Ptr = Translate(VirtualAddress);
-
- return (long)(Ptr - RamPtr);
- }
-
- internal byte* Translate(long Position)
- {
- long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
- long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask;
-
- long Old = Position;
-
- byte** Lvl1 = PageTable[L0];
-
- if ((Position >> (PTLvl0Bit + PTLvl0Bits)) != 0)
- {
- goto Unmapped;
- }
-
- if (Lvl1 == null)
- {
- goto Unmapped;
- }
-
- Position &= PageMask;
-
- byte* Ptr = Lvl1[L1];
-
- if (Ptr == null)
- {
- goto Unmapped;
- }
-
- return Ptr + Position;
-
-Unmapped:
- return HandleNullPte(Old);
- }
-
- private byte* HandleNullPte(long Position)
- {
- long Key = Position >> PTPageBits;
-
- if (ObservedPages.TryGetValue(Key, out IntPtr Ptr))
- {
- return (byte*)Ptr + (Position & PageMask);
- }
-
- InvalidAccess?.Invoke(this, new AInvalidAccessEventArgs(Position));
-
- throw new VmmPageFaultException(Position);
- }
-
- internal byte* TranslateWrite(long Position)
- {
- long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
- long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask;
-
- long Old = Position;
-
- byte** Lvl1 = PageTable[L0];
-
- if ((Position >> (PTLvl0Bit + PTLvl0Bits)) != 0)
- {
- goto Unmapped;
- }
-
- if (Lvl1 == null)
- {
- goto Unmapped;
- }
-
- Position &= PageMask;
-
- byte* Ptr = Lvl1[L1];
-
- if (Ptr == null)
- {
- goto Unmapped;
- }
-
- return Ptr + Position;
-
-Unmapped:
- return HandleNullPteWrite(Old);
- }
-
- private byte* HandleNullPteWrite(long Position)
- {
- long Key = Position >> PTPageBits;
-
- if (ObservedPages.TryGetValue(Key, out IntPtr Ptr))
- {
- SetPTEntry(Position, (byte*)Ptr);
-
- return (byte*)Ptr + (Position & PageMask);
- }
-
- InvalidAccess?.Invoke(this, new AInvalidAccessEventArgs(Position));
-
- throw new VmmPageFaultException(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)
- {
- if (!IsValidPosition(Position))
- {
- throw new ArgumentOutOfRangeException(nameof(Position));
- }
-
- long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
- long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask;
-
- if (PageTable[L0] == null)
- {
- byte** Lvl1 = (byte**)Marshal.AllocHGlobal(PTLvl1Size * IntPtr.Size);
-
- for (int ZL1 = 0; ZL1 < PTLvl1Size; ZL1++)
- {
- Lvl1[ZL1] = null;
- }
-
- Thread.MemoryBarrier();
-
- PageTable[L0] = Lvl1;
- }
-
- PageTable[L0][L1] = Ptr;
- }
-
- public (bool[], int) IsRegionModified(long Position, long Size)
- {
- long EndPosition = (Position + Size + PageMask) & ~PageMask;
-
- Position &= ~PageMask;
-
- Size = EndPosition - Position;
-
- bool[] Modified = new bool[Size >> PTPageBits];
-
- int Count = 0;
-
- lock (ObservedPages)
- {
- for (int Page = 0; Page < Modified.Length; Page++)
- {
- byte* Ptr = Translate(Position);
-
- if (ObservedPages.TryAdd(Position >> PTPageBits, (IntPtr)Ptr))
- {
- Modified[Page] = true;
-
- Count++;
- }
- else
- {
- long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
- long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask;
-
- byte** Lvl1 = PageTable[L0];
-
- if (Lvl1 != null)
- {
- if (Modified[Page] = Lvl1[L1] != null)
- {
- Count++;
- }
- }
- }
-
- SetPTEntry(Position, null);
-
- Position += PageSize;
- }
- }
-
- return (Modified, Count);
- }
-
- public void StopObservingRegion(long Position, long Size)
- {
- long EndPosition = (Position + Size + PageMask) & ~PageMask;
-
- while (Position < EndPosition)
- {
- lock (ObservedPages)
- {
- if (ObservedPages.TryRemove(Position >> PTPageBits, out IntPtr Ptr))
- {
- SetPTEntry(Position, (byte*)Ptr);
- }
- }
-
- Position += PageSize;
- }
- }
-
- public IntPtr GetHostAddress(long Position, long Size)
- {
- EnsureRangeIsValid(Position, Size);
-
- return (IntPtr)Translate(Position);
- }
-
- internal void EnsureRangeIsValid(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)
- {
- throw new VmmAccessException(Position, Size);
- }
-
- Position += PageSize;
- ExpectedPA += PageSize;
- }
- }
-
- public bool IsValidPosition(long Position)
- {
- return Position >> (PTLvl0Bits + PTLvl1Bits + PTPageBits) == 0;
- }
-
- public void Dispose()
- {
- Dispose(true);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (PageTable == null)
- {
- return;
- }
-
- for (int L0 = 0; L0 < PTLvl0Size; L0++)
- {
- if (PageTable[L0] != null)
- {
- Marshal.FreeHGlobal((IntPtr)PageTable[L0]);
- }
-
- PageTable[L0] = null;
- }
-
- Marshal.FreeHGlobal((IntPtr)PageTable);
-
- PageTable = null;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Memory/AMemoryHelper.cs b/ChocolArm64/Memory/AMemoryHelper.cs
deleted file mode 100644
index ea877834..00000000
--- a/ChocolArm64/Memory/AMemoryHelper.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System;
-using System.IO;
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace ChocolArm64.Memory
-{
- public static class AMemoryHelper
- {
- public static void FillWithZeros(AMemory Memory, long Position, int Size)
- {
- int Size8 = Size & ~(8 - 1);
-
- for (int Offs = 0; Offs < Size8; Offs += 8)
- {
- Memory.WriteInt64(Position + Offs, 0);
- }
-
- for (int Offs = Size8; Offs < (Size - Size8); Offs++)
- {
- Memory.WriteByte(Position + Offs, 0);
- }
- }
-
- public unsafe static T Read<T>(AMemory Memory, long Position) where T : struct
- {
- long Size = Marshal.SizeOf<T>();
-
- Memory.EnsureRangeIsValid(Position, Size);
-
- IntPtr Ptr = (IntPtr)Memory.Translate(Position);
-
- return Marshal.PtrToStructure<T>(Ptr);
- }
-
- public unsafe static void Write<T>(AMemory Memory, long Position, T Value) where T : struct
- {
- long Size = Marshal.SizeOf<T>();
-
- Memory.EnsureRangeIsValid(Position, Size);
-
- IntPtr Ptr = (IntPtr)Memory.TranslateWrite(Position);
-
- Marshal.StructureToPtr<T>(Value, Ptr, false);
- }
-
- public static string ReadAsciiString(AMemory 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/IAMemory.cs b/ChocolArm64/Memory/IAMemory.cs
deleted file mode 100644
index 5b7d17bb..00000000
--- a/ChocolArm64/Memory/IAMemory.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-namespace ChocolArm64.Memory
-{
- public interface IAMemory
- {
- 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/IMemory.cs b/ChocolArm64/Memory/IMemory.cs
new file mode 100644
index 00000000..dc582155
--- /dev/null
+++ b/ChocolArm64/Memory/IMemory.cs
@@ -0,0 +1,37 @@
+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
new file mode 100644
index 00000000..2e721afa
--- /dev/null
+++ b/ChocolArm64/Memory/MemoryHelper.cs
@@ -0,0 +1,67 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace ChocolArm64.Memory
+{
+ public static class MemoryHelper
+ {
+ public static void FillWithZeros(MemoryManager memory, long position, int size)
+ {
+ int size8 = size & ~(8 - 1);
+
+ for (int offs = 0; offs < size8; offs += 8)
+ {
+ memory.WriteInt64(position + offs, 0);
+ }
+
+ for (int offs = size8; offs < (size - size8); offs++)
+ {
+ memory.WriteByte(position + offs, 0);
+ }
+ }
+
+ public unsafe static T Read<T>(MemoryManager memory, long position) where T : struct
+ {
+ long size = Marshal.SizeOf<T>();
+
+ memory.EnsureRangeIsValid(position, size);
+
+ IntPtr ptr = (IntPtr)memory.Translate(position);
+
+ return Marshal.PtrToStructure<T>(ptr);
+ }
+
+ public unsafe static void Write<T>(MemoryManager memory, long position, T value) where T : struct
+ {
+ long size = Marshal.SizeOf<T>();
+
+ memory.EnsureRangeIsValid(position, size);
+
+ IntPtr ptr = (IntPtr)memory.TranslateWrite(position);
+
+ Marshal.StructureToPtr<T>(value, ptr, false);
+ }
+
+ 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/MemoryManager.cs b/ChocolArm64/Memory/MemoryManager.cs
new file mode 100644
index 00000000..308dd17e
--- /dev/null
+++ b/ChocolArm64/Memory/MemoryManager.cs
@@ -0,0 +1,745 @@
+using ChocolArm64.Events;
+using ChocolArm64.Exceptions;
+using ChocolArm64.State;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+using System.Threading;
+
+namespace ChocolArm64.Memory
+{
+ public unsafe class MemoryManager : IMemory, IDisposable
+ {
+ private const int PtLvl0Bits = 13;
+ private const int PtLvl1Bits = 14;
+ private const int PtPageBits = 12;
+
+ private const int PtLvl0Size = 1 << PtLvl0Bits;
+ private const int PtLvl1Size = 1 << PtLvl1Bits;
+ public const int PageSize = 1 << PtPageBits;
+
+ private const int PtLvl0Mask = PtLvl0Size - 1;
+ private const int PtLvl1Mask = PtLvl1Size - 1;
+ public const int PageMask = PageSize - 1;
+
+ private const int PtLvl0Bit = PtPageBits + PtLvl1Bits;
+ private const int PtLvl1Bit = PtPageBits;
+
+ private const long ErgMask = (4 << CpuThreadState.ErgSizeLog2) - 1;
+
+ private class ArmMonitor
+ {
+ public long Position;
+ public bool ExState;
+
+ public bool HasExclusiveAccess(long position)
+ {
+ return Position == position && ExState;
+ }
+ }
+
+ private Dictionary<int, ArmMonitor> _monitors;
+
+ private ConcurrentDictionary<long, IntPtr> _observedPages;
+
+ public IntPtr Ram { get; private set; }
+
+ private byte* _ramPtr;
+
+ private byte*** _pageTable;
+
+ public event EventHandler<InvalidAccessEventArgs> InvalidAccess;
+
+ public MemoryManager(IntPtr ram)
+ {
+ _monitors = new Dictionary<int, ArmMonitor>();
+
+ _observedPages = new ConcurrentDictionary<long, IntPtr>();
+
+ Ram = ram;
+
+ _ramPtr = (byte*)ram;
+
+ _pageTable = (byte***)Marshal.AllocHGlobal(PtLvl0Size * IntPtr.Size);
+
+ for (int l0 = 0; l0 < PtLvl0Size; l0++)
+ {
+ _pageTable[l0] = null;
+ }
+ }
+
+ public void RemoveMonitor(int core)
+ {
+ lock (_monitors)
+ {
+ ClearExclusive(core);
+
+ _monitors.Remove(core);
+ }
+ }
+
+ public void SetExclusive(int core, long position)
+ {
+ position &= ~ErgMask;
+
+ lock (_monitors)
+ {
+ foreach (ArmMonitor mon in _monitors.Values)
+ {
+ if (mon.Position == position && mon.ExState)
+ {
+ mon.ExState = false;
+ }
+ }
+
+ if (!_monitors.TryGetValue(core, out ArmMonitor threadMon))
+ {
+ threadMon = new ArmMonitor();
+
+ _monitors.Add(core, threadMon);
+ }
+
+ threadMon.Position = position;
+ threadMon.ExState = true;
+ }
+ }
+
+ public bool TestExclusive(int core, long position)
+ {
+ //Note: Any call to this method also should be followed by a
+ //call to ClearExclusiveForStore if this method returns true.
+ position &= ~ErgMask;
+
+ Monitor.Enter(_monitors);
+
+ if (!_monitors.TryGetValue(core, out ArmMonitor threadMon))
+ {
+ return false;
+ }
+
+ bool exState = threadMon.HasExclusiveAccess(position);
+
+ if (!exState)
+ {
+ Monitor.Exit(_monitors);
+ }
+
+ return exState;
+ }
+
+ public void ClearExclusiveForStore(int core)
+ {
+ if (_monitors.TryGetValue(core, out ArmMonitor threadMon))
+ {
+ threadMon.ExState = false;
+ }
+
+ Monitor.Exit(_monitors);
+ }
+
+ public void ClearExclusive(int core)
+ {
+ lock (_monitors)
+ {
+ if (_monitors.TryGetValue(core, out ArmMonitor threadMon))
+ {
+ threadMon.ExState = false;
+ }
+ }
+ }
+
+ public void WriteInt32ToSharedAddr(long position, int value)
+ {
+ long maskedPosition = position & ~ErgMask;
+
+ lock (_monitors)
+ {
+ foreach (ArmMonitor mon in _monitors.Values)
+ {
+ if (mon.Position == maskedPosition && mon.ExState)
+ {
+ mon.ExState = false;
+ }
+ }
+
+ WriteInt32(position, value);
+ }
+ }
+
+ 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)
+ {
+ return *((ushort*)Translate(position));
+ }
+
+ public uint ReadUInt32(long position)
+ {
+ return *((uint*)Translate(position));
+ }
+
+ public ulong ReadUInt64(long position)
+ {
+ return *((ulong*)Translate(position));
+ }
+
+ public Vector128<float> ReadVector8(long position)
+ {
+ if (Sse2.IsSupported)
+ {
+ return Sse.StaticCast<byte, float>(Sse2.SetVector128(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ReadByte(position)));
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector128<float> ReadVector16(long position)
+ {
+ if (Sse2.IsSupported)
+ {
+ return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse2.SetZeroVector128<ushort>(), ReadUInt16(position), 0));
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector128<float> ReadVector32(long position)
+ {
+ if (Sse.IsSupported)
+ {
+ return Sse.LoadScalarVector128((float*)Translate(position));
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector128<float> ReadVector64(long position)
+ {
+ if (Sse2.IsSupported)
+ {
+ return Sse.StaticCast<double, float>(Sse2.LoadScalarVector128((double*)Translate(position)));
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector128<float> ReadVector128(long position)
+ {
+ if (Sse.IsSupported)
+ {
+ return Sse.LoadVector128((float*)Translate(position));
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ public byte[] ReadBytes(long position, long size)
+ {
+ if ((uint)size > int.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException(nameof(size));
+ }
+
+ EnsureRangeIsValid(position, size);
+
+ byte[] data = new byte[size];
+
+ Marshal.Copy((IntPtr)Translate(position), data, 0, (int)size);
+
+ return data;
+ }
+
+ public void ReadBytes(long position, byte[] data, int startIndex, int size)
+ {
+ //Note: This will be moved later.
+ EnsureRangeIsValid(position, (uint)size);
+
+ Marshal.Copy((IntPtr)Translate(position), data, startIndex, size);
+ }
+
+ 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)
+ {
+ *((ushort*)TranslateWrite(position)) = value;
+ }
+
+ public void WriteUInt32(long position, uint value)
+ {
+ *((uint*)TranslateWrite(position)) = value;
+ }
+
+ public void WriteUInt64(long position, ulong value)
+ {
+ *((ulong*)TranslateWrite(position)) = value;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void WriteVector8(long position, Vector128<float> value)
+ {
+ if (Sse41.IsSupported)
+ {
+ WriteByte(position, Sse41.Extract(Sse.StaticCast<float, byte>(value), 0));
+ }
+ else if (Sse2.IsSupported)
+ {
+ WriteByte(position, (byte)Sse2.Extract(Sse.StaticCast<float, ushort>(value), 0));
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void WriteVector16(long position, Vector128<float> value)
+ {
+ if (Sse2.IsSupported)
+ {
+ WriteUInt16(position, Sse2.Extract(Sse.StaticCast<float, ushort>(value), 0));
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void WriteVector32(long position, Vector128<float> value)
+ {
+ if (Sse.IsSupported)
+ {
+ Sse.StoreScalar((float*)TranslateWrite(position), value);
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void WriteVector64(long position, Vector128<float> value)
+ {
+ if (Sse2.IsSupported)
+ {
+ Sse2.StoreScalar((double*)TranslateWrite(position), Sse.StaticCast<float, double>(value));
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void WriteVector128(long position, Vector128<float> value)
+ {
+ if (Sse.IsSupported)
+ {
+ Sse.Store((float*)TranslateWrite(position), value);
+ }
+ else
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ public void WriteBytes(long position, byte[] data)
+ {
+ EnsureRangeIsValid(position, (uint)data.Length);
+
+ Marshal.Copy(data, 0, (IntPtr)TranslateWrite(position), data.Length);
+ }
+
+ public void WriteBytes(long position, byte[] data, int startIndex, int size)
+ {
+ //Note: This will be moved later.
+ //Using Translate instead of TranslateWrite is on purpose.
+ EnsureRangeIsValid(position, (uint)size);
+
+ Marshal.Copy(data, startIndex, (IntPtr)Translate(position), size);
+ }
+
+ public void CopyBytes(long src, long dst, long size)
+ {
+ //Note: This will be moved later.
+ EnsureRangeIsValid(src, size);
+ EnsureRangeIsValid(dst, size);
+
+ byte* srcPtr = Translate(src);
+ byte* dstPtr = TranslateWrite(dst);
+
+ Buffer.MemoryCopy(srcPtr, dstPtr, size, 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);
+
+ StopObservingRegion(position, size);
+ }
+
+ public bool IsMapped(long position)
+ {
+ if (!(IsValidPosition(position)))
+ {
+ return false;
+ }
+
+ long l0 = (position >> PtLvl0Bit) & PtLvl0Mask;
+ long l1 = (position >> PtLvl1Bit) & PtLvl1Mask;
+
+ if (_pageTable[l0] == null)
+ {
+ return false;
+ }
+
+ return _pageTable[l0][l1] != null || _observedPages.ContainsKey(position >> PtPageBits);
+ }
+
+ public long GetPhysicalAddress(long virtualAddress)
+ {
+ byte* ptr = Translate(virtualAddress);
+
+ return (long)(ptr - _ramPtr);
+ }
+
+ internal byte* Translate(long position)
+ {
+ long l0 = (position >> PtLvl0Bit) & PtLvl0Mask;
+ long l1 = (position >> PtLvl1Bit) & PtLvl1Mask;
+
+ long old = position;
+
+ byte** lvl1 = _pageTable[l0];
+
+ if ((position >> (PtLvl0Bit + PtLvl0Bits)) != 0)
+ {
+ goto Unmapped;
+ }
+
+ if (lvl1 == null)
+ {
+ goto Unmapped;
+ }
+
+ position &= PageMask;
+
+ byte* ptr = lvl1[l1];
+
+ if (ptr == null)
+ {
+ goto Unmapped;
+ }
+
+ return ptr + position;
+
+Unmapped:
+ return HandleNullPte(old);
+ }
+
+ private byte* HandleNullPte(long position)
+ {
+ long key = position >> PtPageBits;
+
+ if (_observedPages.TryGetValue(key, out IntPtr ptr))
+ {
+ return (byte*)ptr + (position & PageMask);
+ }
+
+ InvalidAccess?.Invoke(this, new InvalidAccessEventArgs(position));
+
+ throw new VmmPageFaultException(position);
+ }
+
+ internal byte* TranslateWrite(long position)
+ {
+ long l0 = (position >> PtLvl0Bit) & PtLvl0Mask;
+ long l1 = (position >> PtLvl1Bit) & PtLvl1Mask;
+
+ long old = position;
+
+ byte** lvl1 = _pageTable[l0];
+
+ if ((position >> (PtLvl0Bit + PtLvl0Bits)) != 0)
+ {
+ goto Unmapped;
+ }
+
+ if (lvl1 == null)
+ {
+ goto Unmapped;
+ }
+
+ position &= PageMask;
+
+ byte* ptr = lvl1[l1];
+
+ if (ptr == null)
+ {
+ goto Unmapped;
+ }
+
+ return ptr + position;
+
+Unmapped:
+ return HandleNullPteWrite(old);
+ }
+
+ private byte* HandleNullPteWrite(long position)
+ {
+ long key = position >> PtPageBits;
+
+ if (_observedPages.TryGetValue(key, out IntPtr ptr))
+ {
+ SetPtEntry(position, (byte*)ptr);
+
+ return (byte*)ptr + (position & PageMask);
+ }
+
+ InvalidAccess?.Invoke(this, new InvalidAccessEventArgs(position));
+
+ throw new VmmPageFaultException(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)
+ {
+ if (!IsValidPosition(position))
+ {
+ throw new ArgumentOutOfRangeException(nameof(position));
+ }
+
+ long l0 = (position >> PtLvl0Bit) & PtLvl0Mask;
+ long l1 = (position >> PtLvl1Bit) & PtLvl1Mask;
+
+ if (_pageTable[l0] == null)
+ {
+ byte** lvl1 = (byte**)Marshal.AllocHGlobal(PtLvl1Size * IntPtr.Size);
+
+ for (int zl1 = 0; zl1 < PtLvl1Size; zl1++)
+ {
+ lvl1[zl1] = null;
+ }
+
+ Thread.MemoryBarrier();
+
+ _pageTable[l0] = lvl1;
+ }
+
+ _pageTable[l0][l1] = ptr;
+ }
+
+ public (bool[], int) IsRegionModified(long position, long size)
+ {
+ long endPosition = (position + size + PageMask) & ~PageMask;
+
+ position &= ~PageMask;
+
+ size = endPosition - position;
+
+ bool[] modified = new bool[size >> PtPageBits];
+
+ int count = 0;
+
+ lock (_observedPages)
+ {
+ for (int page = 0; page < modified.Length; page++)
+ {
+ byte* ptr = Translate(position);
+
+ if (_observedPages.TryAdd(position >> PtPageBits, (IntPtr)ptr))
+ {
+ modified[page] = true;
+
+ count++;
+ }
+ else
+ {
+ long l0 = (position >> PtLvl0Bit) & PtLvl0Mask;
+ long l1 = (position >> PtLvl1Bit) & PtLvl1Mask;
+
+ byte** lvl1 = _pageTable[l0];
+
+ if (lvl1 != null)
+ {
+ if (modified[page] = lvl1[l1] != null)
+ {
+ count++;
+ }
+ }
+ }
+
+ SetPtEntry(position, null);
+
+ position += PageSize;
+ }
+ }
+
+ return (modified, count);
+ }
+
+ public void StopObservingRegion(long position, long size)
+ {
+ long endPosition = (position + size + PageMask) & ~PageMask;
+
+ while (position < endPosition)
+ {
+ lock (_observedPages)
+ {
+ if (_observedPages.TryRemove(position >> PtPageBits, out IntPtr ptr))
+ {
+ SetPtEntry(position, (byte*)ptr);
+ }
+ }
+
+ position += PageSize;
+ }
+ }
+
+ public IntPtr GetHostAddress(long position, long size)
+ {
+ EnsureRangeIsValid(position, size);
+
+ return (IntPtr)Translate(position);
+ }
+
+ internal void EnsureRangeIsValid(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)
+ {
+ throw new VmmAccessException(position, size);
+ }
+
+ position += PageSize;
+ expectedPa += PageSize;
+ }
+ }
+
+ public bool IsValidPosition(long position)
+ {
+ return position >> (PtLvl0Bits + PtLvl1Bits + PtPageBits) == 0;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_pageTable == null)
+ {
+ return;
+ }
+
+ for (int l0 = 0; l0 < PtLvl0Size; l0++)
+ {
+ if (_pageTable[l0] != null)
+ {
+ Marshal.FreeHGlobal((IntPtr)_pageTable[l0]);
+ }
+
+ _pageTable[l0] = null;
+ }
+
+ Marshal.FreeHGlobal((IntPtr)_pageTable);
+
+ _pageTable = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/OpCodeTable.cs b/ChocolArm64/OpCodeTable.cs
new file mode 100644
index 00000000..b2a75bb7
--- /dev/null
+++ b/ChocolArm64/OpCodeTable.cs
@@ -0,0 +1,713 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.Decoders32;
+using ChocolArm64.Instructions;
+using ChocolArm64.Instructions32;
+using ChocolArm64.State;
+using System;
+using System.Collections.Generic;
+
+namespace ChocolArm64
+{
+ static class OpCodeTable
+ {
+ static OpCodeTable()
+ {
+#region "OpCode Table (AArch32)"
+ //Integer
+ SetA32("<<<<1010xxxxxxxxxxxxxxxxxxxxxxxx", A32InstInterpret.B, typeof(A32OpCodeBImmAl));
+ SetA32("<<<<1011xxxxxxxxxxxxxxxxxxxxxxxx", A32InstInterpret.Bl, typeof(A32OpCodeBImmAl));
+ SetA32("1111101xxxxxxxxxxxxxxxxxxxxxxxxx", A32InstInterpret.Blx, typeof(A32OpCodeBImmAl));
+#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.LdrLit, 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("0x10111100000xxx<<x101xxxxxxxxxx", 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("0x001110000xxxxx000011xxxxxxxxxx", InstEmit.Dup_Gp, typeof(OpCodeSimdIns64));
+ SetA64("01011110000xxxxx000001xxxxxxxxxx", InstEmit.Dup_S, typeof(OpCodeSimdIns64));
+ SetA64("0x001110000xxxxx000001xxxxxxxxxx", InstEmit.Dup_V, typeof(OpCodeSimdIns64));
+ SetA64("0x101110001xxxxx000111xxxxxxxxxx", InstEmit.Eor_V, typeof(OpCodeSimdReg64));
+ SetA64("0>101110000xxxxx0<xxx0xxxxxxxxxx", InstEmit.Ext_V, typeof(OpCodeSimdExt64));
+ SetA64("011111101x1xxxxx110101xxxxxxxxxx", InstEmit.Fabd_S, typeof(OpCodeSimdReg64));
+ SetA64("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("000111100x10001xx10000xxxxxxxxxx", 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("x00111100x011000xxxxxxxxxxxxxxxx", InstEmit.Fcvtzs_Gp_Fix, typeof(OpCodeSimdCvt64));
+ SetA64("010111101x100001101110xxxxxxxxxx", InstEmit.Fcvtzs_S, typeof(OpCodeSimd64));
+ SetA64("0>0011101<100001101110xxxxxxxxxx", InstEmit.Fcvtzs_V, typeof(OpCodeSimd64));
+ SetA64("0x0011110>>xxxxx111111xxxxxxxxxx", InstEmit.Fcvtzs_V, typeof(OpCodeSimdShImm64));
+ SetA64("x00111100x111001000000xxxxxxxxxx", InstEmit.Fcvtzu_Gp, typeof(OpCodeSimdCvt64));
+ SetA64("x00111100x011001xxxxxxxxxxxxxxxx", InstEmit.Fcvtzu_Gp_Fix, typeof(OpCodeSimdCvt64));
+ SetA64("011111101x100001101110xxxxxxxxxx", InstEmit.Fcvtzu_S, typeof(OpCodeSimd64));
+ SetA64("0>1011101<100001101110xxxxxxxxxx", InstEmit.Fcvtzu_V, typeof(OpCodeSimd64));
+ SetA64("0x1011110>>xxxxx111111xxxxxxxxxx", InstEmit.Fcvtzu_V, typeof(OpCodeSimdShImm64));
+ SetA64("000111100x1xxxxx000110xxxxxxxxxx", InstEmit.Fdiv_S, typeof(OpCodeSimdReg64));
+ SetA64("0>1011100<1xxxxx111111xxxxxxxxxx", InstEmit.Fdiv_V, typeof(OpCodeSimdReg64));
+ SetA64("000111110x0xxxxx0xxxxxxxxxxxxxxx", InstEmit.Fmadd_S, typeof(OpCodeSimdReg64));
+ SetA64("000111100x1xxxxx010010xxxxxxxxxx", InstEmit.Fmax_S, typeof(OpCodeSimdReg64));
+ SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", InstEmit.Fmax_V, typeof(OpCodeSimdReg64));
+ SetA64("000111100x1xxxxx011010xxxxxxxxxx", InstEmit.Fmaxnm_S, typeof(OpCodeSimdReg64));
+ SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", InstEmit.Fmaxnm_V, typeof(OpCodeSimdReg64));
+ SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", InstEmit.Fmaxp_V, typeof(OpCodeSimdReg64));
+ SetA64("000111100x1xxxxx010110xxxxxxxxxx", InstEmit.Fmin_S, typeof(OpCodeSimdReg64));
+ SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", InstEmit.Fmin_V, typeof(OpCodeSimdReg64));
+ SetA64("000111100x1xxxxx011110xxxxxxxxxx", InstEmit.Fminnm_S, typeof(OpCodeSimdReg64));
+ SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", InstEmit.Fminnm_V, typeof(OpCodeSimdReg64));
+ SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", InstEmit.Fminp_V, typeof(OpCodeSimdReg64));
+ SetA64("010111111xxxxxxx0001x0xxxxxxxxxx", InstEmit.Fmla_Se, typeof(OpCodeSimdRegElemF64));
+ SetA64("0>0011100<1xxxxx110011xxxxxxxxxx", InstEmit.Fmla_V, typeof(OpCodeSimdReg64));
+ SetA64("0>0011111<xxxxxx0001x0xxxxxxxxxx", InstEmit.Fmla_Ve, typeof(OpCodeSimdRegElemF64));
+ SetA64("010111111xxxxxxx0101x0xxxxxxxxxx", InstEmit.Fmls_Se, typeof(OpCodeSimdRegElemF64));
+ SetA64("0>0011101<1xxxxx110011xxxxxxxxxx", InstEmit.Fmls_V, typeof(OpCodeSimdReg64));
+ SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", InstEmit.Fmls_Ve, typeof(OpCodeSimdRegElemF64));
+ SetA64("000111100x100000010000xxxxxxxxxx", InstEmit.Fmov_S, typeof(OpCodeSimd64));
+ SetA64("00011110xx1xxxxxxxx100xxxxxxxxxx", InstEmit.Fmov_Si, typeof(OpCodeSimdFmov64));
+ SetA64("0xx0111100000xxx111101xxxxxxxxxx", InstEmit.Fmov_V, typeof(OpCodeSimdImm64));
+ SetA64("x00111100x100110000000xxxxxxxxxx", InstEmit.Fmov_Ftoi, typeof(OpCodeSimdCvt64));
+ SetA64("x00111100x100111000000xxxxxxxxxx", InstEmit.Fmov_Itof, typeof(OpCodeSimdCvt64));
+ SetA64("1001111010101110000000xxxxxxxxxx", InstEmit.Fmov_Ftoi1, typeof(OpCodeSimdCvt64));
+ SetA64("1001111010101111000000xxxxxxxxxx", InstEmit.Fmov_Itof1, typeof(OpCodeSimdCvt64));
+ SetA64("000111110x0xxxxx1xxxxxxxxxxxxxxx", InstEmit.Fmsub_S, typeof(OpCodeSimdReg64));
+ SetA64("000111100x1xxxxx000010xxxxxxxxxx", InstEmit.Fmul_S, typeof(OpCodeSimdReg64));
+ SetA64("010111111xxxxxxx1001x0xxxxxxxxxx", InstEmit.Fmul_Se, typeof(OpCodeSimdRegElemF64));
+ SetA64("0>1011100<1xxxxx110111xxxxxxxxxx", InstEmit.Fmul_V, typeof(OpCodeSimdReg64));
+ SetA64("0>0011111<xxxxxx1001x0xxxxxxxxxx", InstEmit.Fmul_Ve, typeof(OpCodeSimdRegElemF64));
+ SetA64("010111100x1xxxxx110111xxxxxxxxxx", InstEmit.Fmulx_S, typeof(OpCodeSimdReg64));
+ SetA64("011111111xxxxxxx1001x0xxxxxxxxxx", InstEmit.Fmulx_Se, typeof(OpCodeSimdRegElemF64));
+ SetA64("0>0011100<1xxxxx110111xxxxxxxxxx", InstEmit.Fmulx_V, typeof(OpCodeSimdReg64));
+ SetA64("0>1011111<xxxxxx1001x0xxxxxxxxxx", InstEmit.Fmulx_Ve, typeof(OpCodeSimdRegElemF64));
+ SetA64("000111100x100001010000xxxxxxxxxx", InstEmit.Fneg_S, typeof(OpCodeSimd64));
+ SetA64("0>1011101<100000111110xxxxxxxxxx", InstEmit.Fneg_V, typeof(OpCodeSimd64));
+ SetA64("000111110x1xxxxx0xxxxxxxxxxxxxxx", InstEmit.Fnmadd_S, typeof(OpCodeSimdReg64));
+ SetA64("000111110x1xxxxx1xxxxxxxxxxxxxxx", InstEmit.Fnmsub_S, typeof(OpCodeSimdReg64));
+ SetA64("000111100x1xxxxx100010xxxxxxxxxx", InstEmit.Fnmul_S, typeof(OpCodeSimdReg64));
+ SetA64("010111101x100001110110xxxxxxxxxx", InstEmit.Frecpe_S, typeof(OpCodeSimd64));
+ SetA64("0>0011101<100001110110xxxxxxxxxx", InstEmit.Frecpe_V, typeof(OpCodeSimd64));
+ SetA64("010111100x1xxxxx111111xxxxxxxxxx", InstEmit.Frecps_S, typeof(OpCodeSimdReg64));
+ SetA64("0>0011100<1xxxxx111111xxxxxxxxxx", InstEmit.Frecps_V, typeof(OpCodeSimdReg64));
+ SetA64("010111101x100001111110xxxxxxxxxx", InstEmit.Frecpx_S, typeof(OpCodeSimd64));
+ SetA64("000111100x100110010000xxxxxxxxxx", InstEmit.Frinta_S, typeof(OpCodeSimd64));
+ SetA64("0>1011100<100001100010xxxxxxxxxx", InstEmit.Frinta_V, typeof(OpCodeSimd64));
+ SetA64("000111100x100111110000xxxxxxxxxx", InstEmit.Frinti_S, typeof(OpCodeSimd64));
+ SetA64("0>1011101<100001100110xxxxxxxxxx", InstEmit.Frinti_V, typeof(OpCodeSimd64));
+ SetA64("000111100x100101010000xxxxxxxxxx", InstEmit.Frintm_S, typeof(OpCodeSimd64));
+ SetA64("0>0011100<100001100110xxxxxxxxxx", InstEmit.Frintm_V, typeof(OpCodeSimd64));
+ SetA64("000111100x100100010000xxxxxxxxxx", InstEmit.Frintn_S, typeof(OpCodeSimd64));
+ SetA64("0>0011100<100001100010xxxxxxxxxx", InstEmit.Frintn_V, typeof(OpCodeSimd64));
+ SetA64("000111100x100100110000xxxxxxxxxx", InstEmit.Frintp_S, typeof(OpCodeSimd64));
+ SetA64("0>0011101<100001100010xxxxxxxxxx", InstEmit.Frintp_V, typeof(OpCodeSimd64));
+ SetA64("000111100x100111010000xxxxxxxxxx", InstEmit.Frintx_S, typeof(OpCodeSimd64));
+ SetA64("0>1011100<100001100110xxxxxxxxxx", InstEmit.Frintx_V, typeof(OpCodeSimd64));
+ SetA64("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.LdrLit, 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("0x00111100000xxx<<x101xxxxxxxxxx", 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("0x001110<<1xxxxx000100xxxxxxxxxx", InstEmit.Saddw_V, typeof(OpCodeSimdReg64));
+ SetA64("x0011110xx100010000000xxxxxxxxxx", InstEmit.Scvtf_Gp, typeof(OpCodeSimdCvt64));
+ SetA64("010111100x100001110110xxxxxxxxxx", InstEmit.Scvtf_S, typeof(OpCodeSimd64));
+ SetA64("0x0011100x100001110110xxxxxxxxxx", InstEmit.Scvtf_V, typeof(OpCodeSimd64));
+ 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("0x1011110>>>>xxx010101xxxxxxxxxx", InstEmit.Sli_V, typeof(OpCodeSimdShImm64));
+ SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", InstEmit.Smax_V, typeof(OpCodeSimdReg64));
+ SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstEmit.Smaxp_V, typeof(OpCodeSimdReg64));
+ SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", InstEmit.Smin_V, typeof(OpCodeSimdReg64));
+ SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", InstEmit.Sminp_V, typeof(OpCodeSimdReg64));
+ SetA64("0x001110<<1xxxxx100000xxxxxxxxxx", InstEmit.Smlal_V, typeof(OpCodeSimdReg64));
+ SetA64("0x001110<<1xxxxx101000xxxxxxxxxx", InstEmit.Smlsl_V, typeof(OpCodeSimdReg64));
+ SetA64("0x001110000xxxxx001011xxxxxxxxxx", InstEmit.Smov_S, typeof(OpCodeSimdIns64));
+ SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", InstEmit.Smull_V, typeof(OpCodeSimdReg64));
+ 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("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("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("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("x0011110xx100011000000xxxxxxxxxx", InstEmit.Ucvtf_Gp, typeof(OpCodeSimdCvt64));
+ SetA64("011111100x100001110110xxxxxxxxxx", InstEmit.Ucvtf_S, typeof(OpCodeSimd64));
+ SetA64("0x1011100x100001110110xxxxxxxxxx", InstEmit.Ucvtf_V, typeof(OpCodeSimd64));
+ 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("0x101110<<1xxxxx011011xxxxxxxxxx", InstEmit.Umin_V, typeof(OpCodeSimdReg64));
+ SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", InstEmit.Uminp_V, typeof(OpCodeSimdReg64));
+ SetA64("0x101110<<1xxxxx100000xxxxxxxxxx", InstEmit.Umlal_V, typeof(OpCodeSimdReg64));
+ SetA64("0x101110<<1xxxxx101000xxxxxxxxxx", InstEmit.Umlsl_V, typeof(OpCodeSimdReg64));
+ SetA64("0x001110000xxxxx001111xxxxxxxxxx", InstEmit.Umov_S, typeof(OpCodeSimdIns64));
+ SetA64("0x101110<<1xxxxx110000xxxxxxxxxx", InstEmit.Umull_V, typeof(OpCodeSimdReg64));
+ SetA64("01111110xx1xxxxx000011xxxxxxxxxx", InstEmit.Uqadd_S, typeof(OpCodeSimdReg64));
+ SetA64("0>101110<<1xxxxx000011xxxxxxxxxx", InstEmit.Uqadd_V, typeof(OpCodeSimdReg64));
+ SetA64("0111111100>>>xxx100111xxxxxxxxxx", InstEmit.Uqrshrn_S, typeof(OpCodeSimdShImm64));
+ SetA64("0x10111100>>>xxx100111xxxxxxxxxx", InstEmit.Uqrshrn_V, typeof(OpCodeSimdShImm64));
+ 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("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
+
+#region "Generate InstA64FastLookup Table (AArch64)"
+ var tmp = new List<InstInfo>[_fastLookupSize];
+ for (int i = 0; i < _fastLookupSize; i++)
+ {
+ tmp[i] = new List<InstInfo>();
+ }
+
+ foreach (var inst in _allInstA64)
+ {
+ 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++)
+ {
+ _instA64FastLookup[i] = tmp[i].ToArray();
+ }
+#endregion
+ }
+
+ private class InstInfo
+ {
+ public int Mask;
+ public int Value;
+
+ public Inst Inst;
+
+ public InstInfo(int mask, int value, Inst inst)
+ {
+ Mask = mask;
+ Value = value;
+ Inst = inst;
+ }
+ }
+
+ private static List<InstInfo> _allInstA32 = new List<InstInfo>();
+ private static List<InstInfo> _allInstA64 = new List<InstInfo>();
+
+ private static int _fastLookupSize = 0x1000;
+ private static InstInfo[][] _instA64FastLookup = new InstInfo[_fastLookupSize][];
+
+ private static void SetA32(string encoding, InstInterpreter interpreter, Type type)
+ {
+ Set(encoding, new Inst(interpreter, null, type), ExecutionMode.AArch32);
+ }
+
+ private static void SetA64(string encoding, InstEmitter emitter, Type type)
+ {
+ Set(encoding, new Inst(null, 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);
+
+ if (mode == ExecutionMode.AArch64)
+ {
+ _allInstA64.Add(info);
+ }
+ else
+ {
+ _allInstA32.Add(info);
+ }
+ }
+
+ public static Inst GetInstA32(int opCode)
+ {
+ return GetInstFromList(_allInstA32, opCode);
+ }
+
+ public static Inst GetInstA64(int opCode)
+ {
+ return GetInstFromList(_instA64FastLookup[ToFastLookupIndex(opCode)], opCode);
+ }
+
+ private static int ToFastLookupIndex(int value)
+ {
+ return ((value >> 10) & 0x00F) | ((value >> 18) & 0xFF0);
+ }
+
+ private static Inst GetInstFromList(IEnumerable<InstInfo> instList, int opCode)
+ {
+ foreach (var 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
new file mode 100644
index 00000000..f2b0ffba
--- /dev/null
+++ b/ChocolArm64/Optimizations.cs
@@ -0,0 +1,18 @@
+using System.Runtime.Intrinsics.X86;
+
+public static class Optimizations
+{
+ internal static bool FastFP = true;
+
+ private static bool _useAllSseIfAvailable = true;
+
+ private static bool _useSseIfAvailable = true;
+ private static bool _useSse2IfAvailable = true;
+ private static bool _useSse41IfAvailable = true;
+ private static bool _useSse42IfAvailable = true;
+
+ internal static bool UseSse = (_useAllSseIfAvailable && _useSseIfAvailable) && Sse.IsSupported;
+ internal static bool UseSse2 = (_useAllSseIfAvailable && _useSse2IfAvailable) && Sse2.IsSupported;
+ internal static bool UseSse41 = (_useAllSseIfAvailable && _useSse41IfAvailable) && Sse41.IsSupported;
+ internal static bool UseSse42 = (_useAllSseIfAvailable && _useSse42IfAvailable) && Sse42.IsSupported;
+}
diff --git a/ChocolArm64/State/ARegister.cs b/ChocolArm64/State/ARegister.cs
deleted file mode 100644
index 5861db8c..00000000
--- a/ChocolArm64/State/ARegister.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-using System;
-using System.Reflection;
-
-namespace ChocolArm64.State
-{
- struct ARegister
- {
- public int Index;
-
- public ARegisterType Type;
-
- public ARegister(int Index, ARegisterType Type)
- {
- this.Index = Index;
- this.Type = Type;
- }
-
- public override int GetHashCode()
- {
- return (ushort)Index | ((ushort)Type << 16);
- }
-
- public override bool Equals(object Obj)
- {
- return Obj is ARegister Reg &&
- Reg.Index == Index &&
- Reg.Type == Type;
- }
-
- public FieldInfo GetField()
- {
- switch (Type)
- {
- case ARegisterType.Flag: return GetFieldFlag();
- case ARegisterType.Int: return GetFieldInt();
- case ARegisterType.Vector: return GetFieldVector();
- }
-
- throw new InvalidOperationException();
- }
-
- private FieldInfo GetFieldFlag()
- {
- switch ((APState)Index)
- {
- case APState.VBit: return GetField(nameof(AThreadState.Overflow));
- case APState.CBit: return GetField(nameof(AThreadState.Carry));
- case APState.ZBit: return GetField(nameof(AThreadState.Zero));
- case APState.NBit: return GetField(nameof(AThreadState.Negative));
- }
-
- throw new InvalidOperationException();
- }
-
- private FieldInfo GetFieldInt()
- {
- switch (Index)
- {
- case 0: return GetField(nameof(AThreadState.X0));
- case 1: return GetField(nameof(AThreadState.X1));
- case 2: return GetField(nameof(AThreadState.X2));
- case 3: return GetField(nameof(AThreadState.X3));
- case 4: return GetField(nameof(AThreadState.X4));
- case 5: return GetField(nameof(AThreadState.X5));
- case 6: return GetField(nameof(AThreadState.X6));
- case 7: return GetField(nameof(AThreadState.X7));
- case 8: return GetField(nameof(AThreadState.X8));
- case 9: return GetField(nameof(AThreadState.X9));
- case 10: return GetField(nameof(AThreadState.X10));
- case 11: return GetField(nameof(AThreadState.X11));
- case 12: return GetField(nameof(AThreadState.X12));
- case 13: return GetField(nameof(AThreadState.X13));
- case 14: return GetField(nameof(AThreadState.X14));
- case 15: return GetField(nameof(AThreadState.X15));
- case 16: return GetField(nameof(AThreadState.X16));
- case 17: return GetField(nameof(AThreadState.X17));
- case 18: return GetField(nameof(AThreadState.X18));
- case 19: return GetField(nameof(AThreadState.X19));
- case 20: return GetField(nameof(AThreadState.X20));
- case 21: return GetField(nameof(AThreadState.X21));
- case 22: return GetField(nameof(AThreadState.X22));
- case 23: return GetField(nameof(AThreadState.X23));
- case 24: return GetField(nameof(AThreadState.X24));
- case 25: return GetField(nameof(AThreadState.X25));
- case 26: return GetField(nameof(AThreadState.X26));
- case 27: return GetField(nameof(AThreadState.X27));
- case 28: return GetField(nameof(AThreadState.X28));
- case 29: return GetField(nameof(AThreadState.X29));
- case 30: return GetField(nameof(AThreadState.X30));
- case 31: return GetField(nameof(AThreadState.X31));
- }
-
- throw new InvalidOperationException();
- }
-
- private FieldInfo GetFieldVector()
- {
- switch (Index)
- {
- case 0: return GetField(nameof(AThreadState.V0));
- case 1: return GetField(nameof(AThreadState.V1));
- case 2: return GetField(nameof(AThreadState.V2));
- case 3: return GetField(nameof(AThreadState.V3));
- case 4: return GetField(nameof(AThreadState.V4));
- case 5: return GetField(nameof(AThreadState.V5));
- case 6: return GetField(nameof(AThreadState.V6));
- case 7: return GetField(nameof(AThreadState.V7));
- case 8: return GetField(nameof(AThreadState.V8));
- case 9: return GetField(nameof(AThreadState.V9));
- case 10: return GetField(nameof(AThreadState.V10));
- case 11: return GetField(nameof(AThreadState.V11));
- case 12: return GetField(nameof(AThreadState.V12));
- case 13: return GetField(nameof(AThreadState.V13));
- case 14: return GetField(nameof(AThreadState.V14));
- case 15: return GetField(nameof(AThreadState.V15));
- case 16: return GetField(nameof(AThreadState.V16));
- case 17: return GetField(nameof(AThreadState.V17));
- case 18: return GetField(nameof(AThreadState.V18));
- case 19: return GetField(nameof(AThreadState.V19));
- case 20: return GetField(nameof(AThreadState.V20));
- case 21: return GetField(nameof(AThreadState.V21));
- case 22: return GetField(nameof(AThreadState.V22));
- case 23: return GetField(nameof(AThreadState.V23));
- case 24: return GetField(nameof(AThreadState.V24));
- case 25: return GetField(nameof(AThreadState.V25));
- case 26: return GetField(nameof(AThreadState.V26));
- case 27: return GetField(nameof(AThreadState.V27));
- case 28: return GetField(nameof(AThreadState.V28));
- case 29: return GetField(nameof(AThreadState.V29));
- case 30: return GetField(nameof(AThreadState.V30));
- case 31: return GetField(nameof(AThreadState.V31));
- }
-
- throw new InvalidOperationException();
- }
-
- private FieldInfo GetField(string Name)
- {
- return typeof(AThreadState).GetField(Name);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/State/AThreadState.cs b/ChocolArm64/State/CpuThreadState.cs
index fbfac5bc..ed106f71 100644
--- a/ChocolArm64/State/AThreadState.cs
+++ b/ChocolArm64/State/CpuThreadState.cs
@@ -6,17 +6,17 @@ using System.Runtime.Intrinsics;
namespace ChocolArm64.State
{
- public class AThreadState
+ public class CpuThreadState
{
- internal const int LRIndex = 30;
- internal const int ZRIndex = 31;
+ internal const int LrIndex = 30;
+ internal const int ZrIndex = 31;
internal const int ErgSizeLog2 = 4;
internal const int DczSizeLog2 = 4;
private const int MinInstForCheck = 4000000;
- internal AExecutionMode ExecutionMode;
+ internal ExecutionMode ExecutionMode;
//AArch32 state.
public uint R0, R1, R2, R3,
@@ -45,9 +45,9 @@ namespace ChocolArm64.State
public bool Running { get; set; }
public int Core { get; set; }
- private bool Interrupted;
+ private bool _interrupted;
- private int SyncCount;
+ private int _syncCount;
public long TpidrEl0 { get; set; }
public long Tpidr { get; set; }
@@ -59,10 +59,10 @@ namespace ChocolArm64.State
{
get
{
- return (Negative ? (int)APState.N : 0) |
- (Zero ? (int)APState.Z : 0) |
- (Carry ? (int)APState.C : 0) |
- (Overflow ? (int)APState.V : 0);
+ return (Negative ? (int)PState.N : 0) |
+ (Zero ? (int)PState.Z : 0) |
+ (Carry ? (int)PState.C : 0) |
+ (Overflow ? (int)PState.V : 0);
}
}
@@ -74,38 +74,38 @@ namespace ChocolArm64.State
{
get
{
- double Ticks = TickCounter.ElapsedTicks * HostTickFreq;
+ double ticks = _tickCounter.ElapsedTicks * _hostTickFreq;
- return (ulong)(Ticks * CntfrqEl0);
+ return (ulong)(ticks * CntfrqEl0);
}
}
public event EventHandler<EventArgs> Interrupt;
- public event EventHandler<AInstExceptionEventArgs> Break;
- public event EventHandler<AInstExceptionEventArgs> SvcCall;
- public event EventHandler<AInstUndefinedEventArgs> Undefined;
+ public event EventHandler<InstExceptionEventArgs> Break;
+ public event EventHandler<InstExceptionEventArgs> SvcCall;
+ public event EventHandler<InstUndefinedEventArgs> Undefined;
- private static Stopwatch TickCounter;
+ private static Stopwatch _tickCounter;
- private static double HostTickFreq;
+ private static double _hostTickFreq;
- static AThreadState()
+ static CpuThreadState()
{
- HostTickFreq = 1.0 / Stopwatch.Frequency;
+ _hostTickFreq = 1.0 / Stopwatch.Frequency;
- TickCounter = new Stopwatch();
+ _tickCounter = new Stopwatch();
- TickCounter.Start();
+ _tickCounter.Start();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal bool Synchronize(int BbWeight)
+ internal bool Synchronize(int bbWeight)
{
//Firing a interrupt frequently is expensive, so we only
//do it after a given number of instructions has executed.
- SyncCount += BbWeight;
+ _syncCount += bbWeight;
- if (SyncCount >= MinInstForCheck)
+ if (_syncCount >= MinInstForCheck)
{
CheckInterrupt();
}
@@ -115,50 +115,50 @@ namespace ChocolArm64.State
internal void RequestInterrupt()
{
- Interrupted = true;
+ _interrupted = true;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void CheckInterrupt()
{
- SyncCount = 0;
+ _syncCount = 0;
- if (Interrupted)
+ if (_interrupted)
{
- Interrupted = false;
+ _interrupted = false;
Interrupt?.Invoke(this, EventArgs.Empty);
}
}
- internal void OnBreak(long Position, int Imm)
+ internal void OnBreak(long position, int imm)
{
- Break?.Invoke(this, new AInstExceptionEventArgs(Position, Imm));
+ Break?.Invoke(this, new InstExceptionEventArgs(position, imm));
}
- internal void OnSvcCall(long Position, int Imm)
+ internal void OnSvcCall(long position, int imm)
{
- SvcCall?.Invoke(this, new AInstExceptionEventArgs(Position, Imm));
+ SvcCall?.Invoke(this, new InstExceptionEventArgs(position, imm));
}
- internal void OnUndefined(long Position, int RawOpCode)
+ internal void OnUndefined(long position, int rawOpCode)
{
- Undefined?.Invoke(this, new AInstUndefinedEventArgs(Position, RawOpCode));
+ Undefined?.Invoke(this, new InstUndefinedEventArgs(position, rawOpCode));
}
- internal bool GetFpcrFlag(FPCR Flag)
+ internal bool GetFpcrFlag(Fpcr flag)
{
- return (Fpcr & (1 << (int)Flag)) != 0;
+ return (Fpcr & (1 << (int)flag)) != 0;
}
- internal void SetFpsrFlag(FPSR Flag)
+ internal void SetFpsrFlag(Fpsr flag)
{
- Fpsr |= 1 << (int)Flag;
+ Fpsr |= 1 << (int)flag;
}
- internal ARoundMode FPRoundingMode()
+ internal RoundMode FPRoundingMode()
{
- return (ARoundMode)((Fpcr >> (int)FPCR.RMode) & 3);
+ return (RoundMode)((Fpcr >> (int)State.Fpcr.RMode) & 3);
}
}
}
diff --git a/ChocolArm64/State/AExecutionMode.cs b/ChocolArm64/State/ExecutionMode.cs
index 8632da77..4b8c17ce 100644
--- a/ChocolArm64/State/AExecutionMode.cs
+++ b/ChocolArm64/State/ExecutionMode.cs
@@ -1,6 +1,6 @@
namespace ChocolArm64.State
{
- enum AExecutionMode
+ enum ExecutionMode
{
AArch32,
AArch64
diff --git a/ChocolArm64/State/FPCR.cs b/ChocolArm64/State/FPCR.cs
deleted file mode 100644
index 8f47cf90..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 d71cde78..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/FPExc.cs b/ChocolArm64/State/FpExc.cs
index a665957d..5cb7a402 100644
--- a/ChocolArm64/State/FPExc.cs
+++ b/ChocolArm64/State/FpExc.cs
@@ -1,6 +1,6 @@
namespace ChocolArm64.State
{
- enum FPExc
+ enum FpExc
{
InvalidOp = 0,
DivideByZero = 1,
diff --git a/ChocolArm64/State/FPType.cs b/ChocolArm64/State/FpType.cs
index b00f5fee..fc279106 100644
--- a/ChocolArm64/State/FPType.cs
+++ b/ChocolArm64/State/FpType.cs
@@ -1,6 +1,6 @@
namespace ChocolArm64.State
{
- enum FPType
+ enum FpType
{
Nonzero,
Zero,
diff --git a/ChocolArm64/State/Fpcr.cs b/ChocolArm64/State/Fpcr.cs
new file mode 100644
index 00000000..908faee5
--- /dev/null
+++ b/ChocolArm64/State/Fpcr.cs
@@ -0,0 +1,11 @@
+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
new file mode 100644
index 00000000..ba551eef
--- /dev/null
+++ b/ChocolArm64/State/Fpsr.cs
@@ -0,0 +1,8 @@
+namespace ChocolArm64.State
+{
+ enum Fpsr
+ {
+ Ufc = 3,
+ Qc = 27
+ }
+}
diff --git a/ChocolArm64/State/APState.cs b/ChocolArm64/State/PState.cs
index aaf0ff0c..40636c87 100644
--- a/ChocolArm64/State/APState.cs
+++ b/ChocolArm64/State/PState.cs
@@ -3,7 +3,7 @@ using System;
namespace ChocolArm64.State
{
[Flags]
- enum APState
+ enum PState
{
VBit = 28,
CBit = 29,
@@ -15,9 +15,9 @@ namespace ChocolArm64.State
Z = 1 << ZBit,
N = 1 << NBit,
- NZ = N | Z,
- CV = C | V,
+ Nz = N | Z,
+ Cv = C | V,
- NZCV = NZ | CV
+ Nzcv = Nz | Cv
}
}
diff --git a/ChocolArm64/State/Register.cs b/ChocolArm64/State/Register.cs
new file mode 100644
index 00000000..ea29e7b6
--- /dev/null
+++ b/ChocolArm64/State/Register.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Reflection;
+
+namespace ChocolArm64.State
+{
+ struct Register
+ {
+ public int Index;
+
+ public RegisterType Type;
+
+ public Register(int index, RegisterType type)
+ {
+ Index = index;
+ Type = type;
+ }
+
+ public override int GetHashCode()
+ {
+ return (ushort)Index | ((ushort)Type << 16);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is Register reg &&
+ reg.Index == Index &&
+ reg.Type == 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.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/ARegisterSize.cs b/ChocolArm64/State/RegisterSize.cs
index 144f36b9..7cc99599 100644
--- a/ChocolArm64/State/ARegisterSize.cs
+++ b/ChocolArm64/State/RegisterSize.cs
@@ -1,10 +1,10 @@
namespace ChocolArm64.State
{
- enum ARegisterSize
+ enum RegisterSize
{
Int32,
Int64,
- SIMD64,
- SIMD128
+ Simd64,
+ Simd128
}
} \ No newline at end of file
diff --git a/ChocolArm64/State/ARegisterType.cs b/ChocolArm64/State/RegisterType.cs
index f9776bb7..4476d044 100644
--- a/ChocolArm64/State/ARegisterType.cs
+++ b/ChocolArm64/State/RegisterType.cs
@@ -1,6 +1,6 @@
namespace ChocolArm64.State
{
- enum ARegisterType
+ enum RegisterType
{
Flag,
Int,
diff --git a/ChocolArm64/State/ARoundMode.cs b/ChocolArm64/State/RoundMode.cs
index 297d0137..b687cc8e 100644
--- a/ChocolArm64/State/ARoundMode.cs
+++ b/ChocolArm64/State/RoundMode.cs
@@ -1,6 +1,6 @@
namespace ChocolArm64.State
{
- enum ARoundMode
+ enum RoundMode
{
ToNearest = 0,
TowardsPlusInfinity = 1,
diff --git a/ChocolArm64/TranslatedSub.cs b/ChocolArm64/TranslatedSub.cs
new file mode 100644
index 00000000..8b3ec3f0
--- /dev/null
+++ b/ChocolArm64/TranslatedSub.cs
@@ -0,0 +1,150 @@
+using ChocolArm64.Memory;
+using ChocolArm64.State;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace ChocolArm64
+{
+ class TranslatedSub
+ {
+ private delegate long Aa64Subroutine(CpuThreadState register, MemoryManager memory);
+
+ private const int MinCallCountForReJit = 250;
+
+ private Aa64Subroutine _execDelegate;
+
+ public static int StateArgIdx { get; private set; }
+ public static int MemoryArgIdx { get; private set; }
+
+ public static Type[] FixedArgTypes { get; private set; }
+
+ public DynamicMethod Method { get; private set; }
+
+ public ReadOnlyCollection<Register> Params { get; private set; }
+
+ private HashSet<long> _callers;
+
+ private TranslatedSubType _type;
+
+ private int _callCount;
+
+ private bool _needsReJit;
+
+ public TranslatedSub(DynamicMethod method, List<Register> Params)
+ {
+ if (method == null)
+ {
+ throw new ArgumentNullException(nameof(method));
+ }
+
+ if (Params == null)
+ {
+ throw new ArgumentNullException(nameof(Params));
+ }
+
+ Method = method;
+ this.Params = Params.AsReadOnly();
+
+ _callers = new HashSet<long>();
+
+ PrepareDelegate();
+ }
+
+ static TranslatedSub()
+ {
+ MethodInfo mthdInfo = typeof(Aa64Subroutine).GetMethod("Invoke");
+
+ ParameterInfo[] Params = mthdInfo.GetParameters();
+
+ FixedArgTypes = new Type[Params.Length];
+
+ for (int index = 0; index < Params.Length; index++)
+ {
+ Type paramType = Params[index].ParameterType;
+
+ FixedArgTypes[index] = paramType;
+
+ if (paramType == typeof(CpuThreadState))
+ {
+ StateArgIdx = index;
+ }
+ else if (paramType == typeof(MemoryManager))
+ {
+ MemoryArgIdx = index;
+ }
+ }
+ }
+
+ private void PrepareDelegate()
+ {
+ string name = $"{Method.Name}_Dispatch";
+
+ DynamicMethod mthd = new DynamicMethod(name, typeof(long), FixedArgTypes);
+
+ ILGenerator generator = mthd.GetILGenerator();
+
+ generator.EmitLdargSeq(FixedArgTypes.Length);
+
+ foreach (Register reg in Params)
+ {
+ generator.EmitLdarg(StateArgIdx);
+
+ generator.Emit(OpCodes.Ldfld, reg.GetField());
+ }
+
+ generator.Emit(OpCodes.Call, Method);
+ generator.Emit(OpCodes.Ret);
+
+ _execDelegate = (Aa64Subroutine)mthd.CreateDelegate(typeof(Aa64Subroutine));
+ }
+
+ public bool ShouldReJit()
+ {
+ if (_needsReJit && _callCount < MinCallCountForReJit)
+ {
+ _callCount++;
+
+ return false;
+ }
+
+ return _needsReJit;
+ }
+
+ public long Execute(CpuThreadState threadState, MemoryManager memory)
+ {
+ return _execDelegate(threadState, memory);
+ }
+
+ public void AddCaller(long position)
+ {
+ lock (_callers)
+ {
+ _callers.Add(position);
+ }
+ }
+
+ public long[] GetCallerPositions()
+ {
+ lock (_callers)
+ {
+ return _callers.ToArray();
+ }
+ }
+
+ public void SetType(TranslatedSubType type)
+ {
+ _type = type;
+
+ if (type == TranslatedSubType.SubTier0)
+ {
+ _needsReJit = true;
+ }
+ }
+
+ public void MarkForReJit() => _needsReJit = true;
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/ATranslatedSubType.cs b/ChocolArm64/TranslatedSubType.cs
index 14893abd..f57aea94 100644
--- a/ChocolArm64/ATranslatedSubType.cs
+++ b/ChocolArm64/TranslatedSubType.cs
@@ -1,6 +1,6 @@
namespace ChocolArm64
{
- enum ATranslatedSubType
+ enum TranslatedSubType
{
SubTier0,
SubTier1
diff --git a/ChocolArm64/Translation/AILBarrier.cs b/ChocolArm64/Translation/AILBarrier.cs
deleted file mode 100644
index 25b08de3..00000000
--- a/ChocolArm64/Translation/AILBarrier.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace ChocolArm64.Translation
-{
- struct AILBarrier : IAILEmit
- {
- public void Emit(AILEmitter Context) { }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/AILBlock.cs b/ChocolArm64/Translation/AILBlock.cs
deleted file mode 100644
index e580e09c..00000000
--- a/ChocolArm64/Translation/AILBlock.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using System.Collections.Generic;
-
-namespace ChocolArm64.Translation
-{
- class AILBlock : IAILEmit
- {
- public long IntInputs { get; private set; }
- public long IntOutputs { get; private set; }
- public long IntAwOutputs { get; private set; }
-
- public long VecInputs { get; private set; }
- public long VecOutputs { get; private set; }
- public long VecAwOutputs { get; private set; }
-
- public bool HasStateStore { get; private set; }
-
- public List<IAILEmit> ILEmitters { get; private set; }
-
- public AILBlock Next { get; set; }
- public AILBlock Branch { get; set; }
-
- public AILBlock()
- {
- ILEmitters = new List<IAILEmit>();
- }
-
- public void Add(IAILEmit ILEmitter)
- {
- if (ILEmitter is AILBarrier)
- {
- //Those barriers are used to separate the groups of CIL
- //opcodes emitted by each ARM instruction.
- //We can only consider the new outputs for doing input elimination
- //after all the CIL opcodes used by the instruction being emitted.
- IntAwOutputs = IntOutputs;
- VecAwOutputs = VecOutputs;
- }
- else if (ILEmitter is AILOpCodeLoad Ld && AILEmitter.IsRegIndex(Ld.Index))
- {
- switch (Ld.IoType)
- {
- case AIoType.Flag: IntInputs |= ((1L << Ld.Index) << 32) & ~IntAwOutputs; break;
- case AIoType.Int: IntInputs |= (1L << Ld.Index) & ~IntAwOutputs; break;
- case AIoType.Vector: VecInputs |= (1L << Ld.Index) & ~VecAwOutputs; break;
- }
- }
- else if (ILEmitter is AILOpCodeStore St)
- {
- if (AILEmitter.IsRegIndex(St.Index))
- {
- switch (St.IoType)
- {
- case AIoType.Flag: IntOutputs |= (1L << St.Index) << 32; break;
- case AIoType.Int: IntOutputs |= 1L << St.Index; break;
- case AIoType.Vector: VecOutputs |= 1L << St.Index; break;
- }
- }
-
- if (St.IoType == AIoType.Fields)
- {
- HasStateStore = true;
- }
- }
-
- ILEmitters.Add(ILEmitter);
- }
-
- public void Emit(AILEmitter Context)
- {
- foreach (IAILEmit ILEmitter in ILEmitters)
- {
- ILEmitter.Emit(Context);
- }
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/AILEmitter.cs b/ChocolArm64/Translation/AILEmitter.cs
deleted file mode 100644
index 8c780535..00000000
--- a/ChocolArm64/Translation/AILEmitter.cs
+++ /dev/null
@@ -1,188 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using System;
-using System.Collections.Generic;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics;
-
-namespace ChocolArm64.Translation
-{
- class AILEmitter
- {
- public ALocalAlloc LocalAlloc { get; private set; }
-
- public ILGenerator Generator { get; private set; }
-
- private Dictionary<ARegister, int> Locals;
-
- private AILBlock[] ILBlocks;
-
- private AILBlock Root;
-
- private ATranslatedSub Subroutine;
-
- private string SubName;
-
- private int LocalsCount;
-
- public AILEmitter(ABlock[] Graph, ABlock Root, string SubName)
- {
- this.SubName = SubName;
-
- Locals = new Dictionary<ARegister, int>();
-
- ILBlocks = new AILBlock[Graph.Length];
-
- AILBlock GetBlock(int Index)
- {
- if (Index < 0 || Index >= ILBlocks.Length)
- {
- return null;
- }
-
- if (ILBlocks[Index] == null)
- {
- ILBlocks[Index] = new AILBlock();
- }
-
- return ILBlocks[Index];
- }
-
- for (int Index = 0; Index < ILBlocks.Length; Index++)
- {
- AILBlock Block = GetBlock(Index);
-
- Block.Next = GetBlock(Array.IndexOf(Graph, Graph[Index].Next));
- Block.Branch = GetBlock(Array.IndexOf(Graph, Graph[Index].Branch));
- }
-
- this.Root = ILBlocks[Array.IndexOf(Graph, Root)];
- }
-
- public AILBlock GetILBlock(int Index) => ILBlocks[Index];
-
- public ATranslatedSub GetSubroutine()
- {
- LocalAlloc = new ALocalAlloc(ILBlocks, Root);
-
- InitSubroutine();
- InitLocals();
-
- foreach (AILBlock ILBlock in ILBlocks)
- {
- ILBlock.Emit(this);
- }
-
- return Subroutine;
- }
-
- private void InitSubroutine()
- {
- List<ARegister> Params = new List<ARegister>();
-
- void SetParams(long Inputs, ARegisterType BaseType)
- {
- for (int Bit = 0; Bit < 64; Bit++)
- {
- long Mask = 1L << Bit;
-
- if ((Inputs & Mask) != 0)
- {
- Params.Add(GetRegFromBit(Bit, BaseType));
- }
- }
- }
-
- SetParams(LocalAlloc.GetIntInputs(Root), ARegisterType.Int);
- SetParams(LocalAlloc.GetVecInputs(Root), ARegisterType.Vector);
-
- DynamicMethod Mthd = new DynamicMethod(SubName, typeof(long), GetParamTypes(Params));
-
- Generator = Mthd.GetILGenerator();
-
- Subroutine = new ATranslatedSub(Mthd, Params);
- }
-
- private void InitLocals()
- {
- int ParamsStart = ATranslatedSub.FixedArgTypes.Length;
-
- Locals = new Dictionary<ARegister, int>();
-
- for (int Index = 0; Index < Subroutine.Params.Count; Index++)
- {
- ARegister Reg = Subroutine.Params[Index];
-
- Generator.EmitLdarg(Index + ParamsStart);
- Generator.EmitStloc(GetLocalIndex(Reg));
- }
- }
-
- private Type[] GetParamTypes(IList<ARegister> Params)
- {
- Type[] FixedArgs = ATranslatedSub.FixedArgTypes;
-
- Type[] Output = new Type[Params.Count + FixedArgs.Length];
-
- FixedArgs.CopyTo(Output, 0);
-
- int TypeIdx = FixedArgs.Length;
-
- for (int Index = 0; Index < Params.Count; Index++)
- {
- Output[TypeIdx++] = GetFieldType(Params[Index].Type);
- }
-
- return Output;
- }
-
- public int GetLocalIndex(ARegister Reg)
- {
- if (!Locals.TryGetValue(Reg, out int Index))
- {
- Generator.DeclareLocal(GetLocalType(Reg));
-
- Index = LocalsCount++;
-
- Locals.Add(Reg, Index);
- }
-
- return Index;
- }
-
- public Type GetLocalType(ARegister Reg) => GetFieldType(Reg.Type);
-
- public Type GetFieldType(ARegisterType RegType)
- {
- switch (RegType)
- {
- case ARegisterType.Flag: return typeof(bool);
- case ARegisterType.Int: return typeof(ulong);
- case ARegisterType.Vector: return typeof(Vector128<float>);
- }
-
- throw new ArgumentException(nameof(RegType));
- }
-
- public static ARegister GetRegFromBit(int Bit, ARegisterType BaseType)
- {
- if (Bit < 32)
- {
- return new ARegister(Bit, BaseType);
- }
- else if (BaseType == ARegisterType.Int)
- {
- return new ARegister(Bit & 0x1f, ARegisterType.Flag);
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Bit));
- }
- }
-
- public static bool IsRegIndex(int Index)
- {
- return Index >= 0 && Index < 32;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/AILEmitterCtx.cs b/ChocolArm64/Translation/AILEmitterCtx.cs
deleted file mode 100644
index e5288bc8..00000000
--- a/ChocolArm64/Translation/AILEmitterCtx.cs
+++ /dev/null
@@ -1,554 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Instruction;
-using ChocolArm64.State;
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Translation
-{
- class AILEmitterCtx
- {
- private ATranslatorCache Cache;
-
- private Dictionary<long, AILLabel> Labels;
-
- private int BlkIndex;
- private int OpcIndex;
-
- private ABlock[] Graph;
- private ABlock Root;
- public ABlock CurrBlock => Graph[BlkIndex];
- public AOpCode CurrOp => Graph[BlkIndex].OpCodes[OpcIndex];
-
- private AILEmitter Emitter;
-
- private AILBlock ILBlock;
-
- private AOpCode OptOpLastCompare;
- private AOpCode 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 Tmp1Index = -1;
- private const int Tmp2Index = -2;
- private const int Tmp3Index = -3;
- private const int Tmp4Index = -4;
- private const int Tmp5Index = -5;
- private const int Tmp6Index = -6;
-
- public AILEmitterCtx(
- ATranslatorCache Cache,
- ABlock[] Graph,
- ABlock Root,
- string SubName)
- {
- this.Cache = Cache ?? throw new ArgumentNullException(nameof(Cache));
- this.Graph = Graph ?? throw new ArgumentNullException(nameof(Graph));
- this.Root = Root ?? throw new ArgumentNullException(nameof(Root));
-
- Labels = new Dictionary<long, AILLabel>();
-
- Emitter = new AILEmitter(Graph, Root, SubName);
-
- ILBlock = Emitter.GetILBlock(0);
-
- OpcIndex = -1;
-
- if (Graph.Length == 0 || !AdvanceOpCode())
- {
- throw new ArgumentException(nameof(Graph));
- }
- }
-
- public ATranslatedSub GetSubroutine()
- {
- return Emitter.GetSubroutine();
- }
-
- public bool AdvanceOpCode()
- {
- if (OpcIndex + 1 == CurrBlock.OpCodes.Count &&
- BlkIndex + 1 == Graph.Length)
- {
- return false;
- }
-
- while (++OpcIndex >= (CurrBlock?.OpCodes.Count ?? 0))
- {
- BlkIndex++;
- OpcIndex = -1;
-
- OptOpLastFlagSet = null;
- OptOpLastCompare = null;
-
- ILBlock = Emitter.GetILBlock(BlkIndex);
- }
-
- return true;
- }
-
- public void EmitOpCode()
- {
- if (OpcIndex == 0)
- {
- MarkLabel(GetLabel(CurrBlock.Position));
-
- EmitSynchronization();
- }
-
- CurrOp.Emitter(this);
-
- ILBlock.Add(new AILBarrier());
- }
-
- private void EmitSynchronization()
- {
- EmitLdarg(ATranslatedSub.StateArgIdx);
-
- EmitLdc_I4(CurrBlock.OpCodes.Count);
-
- EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.Synchronize));
-
- EmitLdc_I4(0);
-
- AILLabel LblContinue = new AILLabel();
-
- Emit(OpCodes.Bne_Un_S, LblContinue);
-
- EmitLdc_I8(0);
-
- Emit(OpCodes.Ret);
-
- MarkLabel(LblContinue);
- }
-
- public bool TryOptEmitSubroutineCall()
- {
- if (CurrBlock.Next == null)
- {
- return false;
- }
-
- if (CurrOp.Emitter != AInstEmit.Bl)
- {
- return false;
- }
-
- if (!Cache.TryGetSubroutine(((AOpCodeBImmAl)CurrOp).Imm, out ATranslatedSub Subroutine))
- {
- return false;
- }
-
- for (int Index = 0; Index < ATranslatedSub.FixedArgTypes.Length; Index++)
- {
- EmitLdarg(Index);
- }
-
- foreach (ARegister Reg in Subroutine.Params)
- {
- switch (Reg.Type)
- {
- case ARegisterType.Flag: Ldloc(Reg.Index, AIoType.Flag); break;
- case ARegisterType.Int: Ldloc(Reg.Index, AIoType.Int); break;
- case ARegisterType.Vector: Ldloc(Reg.Index, AIoType.Vector); break;
- }
- }
-
- EmitCall(Subroutine.Method);
-
- Subroutine.AddCaller(Root.Position);
-
- return true;
- }
-
- public void TryOptMarkCondWithoutCmp()
- {
- OptOpLastCompare = CurrOp;
-
- AInstEmitAluHelper.EmitDataLoadOpers(this);
-
- Stloc(Tmp4Index, AIoType.Int);
- Stloc(Tmp3Index, AIoType.Int);
- }
-
- private Dictionary<ACond, OpCode> BranchOps = new Dictionary<ACond, OpCode>()
- {
- { ACond.Eq, OpCodes.Beq },
- { ACond.Ne, OpCodes.Bne_Un },
- { ACond.Ge_Un, OpCodes.Bge_Un },
- { ACond.Lt_Un, OpCodes.Blt_Un },
- { ACond.Gt_Un, OpCodes.Bgt_Un },
- { ACond.Le_Un, OpCodes.Ble_Un },
- { ACond.Ge, OpCodes.Bge },
- { ACond.Lt, OpCodes.Blt },
- { ACond.Gt, OpCodes.Bgt },
- { ACond.Le, OpCodes.Ble }
- };
-
- public void EmitCondBranch(AILLabel Target, ACond Cond)
- {
- OpCode ILOp;
-
- int IntCond = (int)Cond;
-
- if (OptOpLastCompare != null &&
- OptOpLastCompare == OptOpLastFlagSet && BranchOps.ContainsKey(Cond))
- {
- Ldloc(Tmp3Index, AIoType.Int, OptOpLastCompare.RegisterSize);
- Ldloc(Tmp4Index, AIoType.Int, OptOpLastCompare.RegisterSize);
-
- ILOp = BranchOps[Cond];
- }
- else if (IntCond < 14)
- {
- int CondTrue = IntCond >> 1;
-
- switch (CondTrue)
- {
- case 0: EmitLdflg((int)APState.ZBit); break;
- case 1: EmitLdflg((int)APState.CBit); break;
- case 2: EmitLdflg((int)APState.NBit); break;
- case 3: EmitLdflg((int)APState.VBit); break;
-
- case 4:
- EmitLdflg((int)APState.CBit);
- EmitLdflg((int)APState.ZBit);
-
- Emit(OpCodes.Not);
- Emit(OpCodes.And);
- break;
-
- case 5:
- case 6:
- EmitLdflg((int)APState.NBit);
- EmitLdflg((int)APState.VBit);
-
- Emit(OpCodes.Ceq);
-
- if (CondTrue == 6)
- {
- EmitLdflg((int)APState.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(AIntType IntType)
- {
- switch (IntType)
- {
- case AIntType.UInt8: Emit(OpCodes.Conv_U1); break;
- case AIntType.UInt16: Emit(OpCodes.Conv_U2); break;
- case AIntType.UInt32: Emit(OpCodes.Conv_U4); break;
- case AIntType.UInt64: Emit(OpCodes.Conv_U8); break;
- case AIntType.Int8: Emit(OpCodes.Conv_I1); break;
- case AIntType.Int16: Emit(OpCodes.Conv_I2); break;
- case AIntType.Int32: Emit(OpCodes.Conv_I4); break;
- case AIntType.Int64: Emit(OpCodes.Conv_I8); break;
- }
-
- bool Sz64 = CurrOp.RegisterSize != ARegisterSize.Int32;
-
- if (Sz64 == (IntType == AIntType.UInt64 ||
- IntType == AIntType.Int64))
- {
- return;
- }
-
- if (Sz64)
- {
- Emit(IntType >= AIntType.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(Tmp2Index, AIoType.Int);
- Ldloc(Tmp2Index, AIoType.Int);
-
- EmitLdc_I4(Amount);
-
- Emit(OpCodes.Shr_Un);
-
- Ldloc(Tmp2Index, AIoType.Int);
-
- EmitLdc_I4(CurrOp.GetBitsCount() - Amount);
-
- Emit(OpCodes.Shl);
- Emit(OpCodes.Or);
- }
- }
-
- public AILLabel GetLabel(long Position)
- {
- if (!Labels.TryGetValue(Position, out AILLabel Output))
- {
- Output = new AILLabel();
-
- Labels.Add(Position, Output);
- }
-
- return Output;
- }
-
- public void MarkLabel(AILLabel Label)
- {
- ILBlock.Add(Label);
- }
-
- public void Emit(OpCode ILOp)
- {
- ILBlock.Add(new AILOpCode(ILOp));
- }
-
- public void Emit(OpCode ILOp, AILLabel Label)
- {
- ILBlock.Add(new AILOpCodeBranch(ILOp, Label));
- }
-
- public void Emit(string Text)
- {
- ILBlock.Add(new AILOpCodeLog(Text));
- }
-
- public void EmitLdarg(int Index)
- {
- ILBlock.Add(new AILOpCodeLoad(Index, AIoType.Arg));
- }
-
- public void EmitLdintzr(int Index)
- {
- if (Index != AThreadState.ZRIndex)
- {
- EmitLdint(Index);
- }
- else
- {
- EmitLdc_I(0);
- }
- }
-
- public void EmitStintzr(int Index)
- {
- if (Index != AThreadState.ZRIndex)
- {
- EmitStint(Index);
- }
- else
- {
- Emit(OpCodes.Pop);
- }
- }
-
- public void EmitLoadState(ABlock RetBlk)
- {
- ILBlock.Add(new AILOpCodeLoad(Array.IndexOf(Graph, RetBlk), AIoType.Fields));
- }
-
- public void EmitStoreState()
- {
- ILBlock.Add(new AILOpCodeStore(Array.IndexOf(Graph, CurrBlock), AIoType.Fields));
- }
-
- public void EmitLdtmp() => EmitLdint(Tmp1Index);
- public void EmitSttmp() => EmitStint(Tmp1Index);
-
- public void EmitLdvectmp() => EmitLdvec(Tmp5Index);
- public void EmitStvectmp() => EmitStvec(Tmp5Index);
-
- public void EmitLdvectmp2() => EmitLdvec(Tmp6Index);
- public void EmitStvectmp2() => EmitStvec(Tmp6Index);
-
- public void EmitLdint(int Index) => Ldloc(Index, AIoType.Int);
- public void EmitStint(int Index) => Stloc(Index, AIoType.Int);
-
- public void EmitLdvec(int Index) => Ldloc(Index, AIoType.Vector);
- public void EmitStvec(int Index) => Stloc(Index, AIoType.Vector);
-
- public void EmitLdflg(int Index) => Ldloc(Index, AIoType.Flag);
- public void EmitStflg(int Index)
- {
- OptOpLastFlagSet = CurrOp;
-
- Stloc(Index, AIoType.Flag);
- }
-
- private void Ldloc(int Index, AIoType IoType)
- {
- ILBlock.Add(new AILOpCodeLoad(Index, IoType, CurrOp.RegisterSize));
- }
-
- private void Ldloc(int Index, AIoType IoType, ARegisterSize RegisterSize)
- {
- ILBlock.Add(new AILOpCodeLoad(Index, IoType, RegisterSize));
- }
-
- private void Stloc(int Index, AIoType IoType)
- {
- ILBlock.Add(new AILOpCodeStore(Index, IoType, CurrOp.RegisterSize));
- }
-
- public void EmitCallPropGet(Type ObjType, string PropName)
- {
- if (ObjType == null)
- {
- throw new ArgumentNullException(nameof(ObjType));
- }
-
- if (PropName == null)
- {
- throw new ArgumentNullException(nameof(PropName));
- }
-
- EmitCall(ObjType.GetMethod($"get_{PropName}"));
- }
-
- public void EmitCallPropSet(Type ObjType, string PropName)
- {
- if (ObjType == null)
- {
- throw new ArgumentNullException(nameof(ObjType));
- }
-
- if (PropName == null)
- {
- throw new ArgumentNullException(nameof(PropName));
- }
-
- EmitCall(ObjType.GetMethod($"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 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)
- {
- if (MthdInfo == null)
- {
- throw new ArgumentNullException(nameof(MthdInfo));
- }
-
- ILBlock.Add(new AILOpCodeCall(MthdInfo));
- }
-
- public void EmitLdc_I(long Value)
- {
- if (CurrOp.RegisterSize == ARegisterSize.Int32)
- {
- EmitLdc_I4((int)Value);
- }
- else
- {
- EmitLdc_I8(Value);
- }
- }
-
- public void EmitLdc_I4(int Value)
- {
- ILBlock.Add(new AILOpCodeConst(Value));
- }
-
- public void EmitLdc_I8(long Value)
- {
- ILBlock.Add(new AILOpCodeConst(Value));
- }
-
- public void EmitLdc_R4(float Value)
- {
- ILBlock.Add(new AILOpCodeConst(Value));
- }
-
- public void EmitLdc_R8(double Value)
- {
- ILBlock.Add(new AILOpCodeConst(Value));
- }
-
- public void EmitZNFlagCheck()
- {
- EmitZNCheck(OpCodes.Ceq, (int)APState.ZBit);
- EmitZNCheck(OpCodes.Clt, (int)APState.NBit);
- }
-
- private void EmitZNCheck(OpCode ILCmpOp, int Flag)
- {
- Emit(OpCodes.Dup);
- Emit(OpCodes.Ldc_I4_0);
-
- if (CurrOp.RegisterSize != ARegisterSize.Int32)
- {
- Emit(OpCodes.Conv_I8);
- }
-
- Emit(ILCmpOp);
-
- EmitStflg(Flag);
- }
- }
-}
diff --git a/ChocolArm64/Translation/AILLabel.cs b/ChocolArm64/Translation/AILLabel.cs
deleted file mode 100644
index 0ee39ad7..00000000
--- a/ChocolArm64/Translation/AILLabel.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Translation
-{
- class AILLabel : IAILEmit
- {
- private bool HasLabel;
-
- private Label Lbl;
-
- public void Emit(AILEmitter Context)
- {
- Context.Generator.MarkLabel(GetLabel(Context));
- }
-
- public Label GetLabel(AILEmitter Context)
- {
- if (!HasLabel)
- {
- Lbl = Context.Generator.DefineLabel();
-
- HasLabel = true;
- }
-
- return Lbl;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/AILOpCode.cs b/ChocolArm64/Translation/AILOpCode.cs
deleted file mode 100644
index a4bc93a0..00000000
--- a/ChocolArm64/Translation/AILOpCode.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Translation
-{
- struct AILOpCode : IAILEmit
- {
- private OpCode ILOp;
-
- public AILOpCode(OpCode ILOp)
- {
- this.ILOp = ILOp;
- }
-
- public void Emit(AILEmitter Context)
- {
- Context.Generator.Emit(ILOp);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/AILOpCodeBranch.cs b/ChocolArm64/Translation/AILOpCodeBranch.cs
deleted file mode 100644
index e4caad1f..00000000
--- a/ChocolArm64/Translation/AILOpCodeBranch.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Translation
-{
- struct AILOpCodeBranch : IAILEmit
- {
- private OpCode ILOp;
- private AILLabel Label;
-
- public AILOpCodeBranch(OpCode ILOp, AILLabel Label)
- {
- this.ILOp = ILOp;
- this.Label = Label;
- }
-
- public void Emit(AILEmitter Context)
- {
- Context.Generator.Emit(ILOp, Label.GetLabel(Context));
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/AILOpCodeCall.cs b/ChocolArm64/Translation/AILOpCodeCall.cs
deleted file mode 100644
index 8cd944eb..00000000
--- a/ChocolArm64/Translation/AILOpCodeCall.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System.Reflection;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Translation
-{
- struct AILOpCodeCall : IAILEmit
- {
- private MethodInfo MthdInfo;
-
- public AILOpCodeCall(MethodInfo MthdInfo)
- {
- this.MthdInfo = MthdInfo;
- }
-
- public void Emit(AILEmitter Context)
- {
- Context.Generator.Emit(OpCodes.Call, MthdInfo);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/AILOpCodeConst.cs b/ChocolArm64/Translation/AILOpCodeConst.cs
deleted file mode 100644
index fee86407..00000000
--- a/ChocolArm64/Translation/AILOpCodeConst.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System.Reflection.Emit;
-using System.Runtime.InteropServices;
-
-namespace ChocolArm64.Translation
-{
- class AILOpCodeConst : IAILEmit
- {
- [StructLayout(LayoutKind.Explicit, Size = 8)]
- private struct ImmVal
- {
- [FieldOffset(0)] public int I4;
- [FieldOffset(0)] public long I8;
- [FieldOffset(0)] public float R4;
- [FieldOffset(0)] public double R8;
- }
-
- private ImmVal Value;
-
- private enum ConstType
- {
- Int32,
- Int64,
- Single,
- Double
- }
-
- private ConstType Type;
-
- private AILOpCodeConst(ConstType Type)
- {
- this.Type = Type;
- }
-
- public AILOpCodeConst(int Value) : this(ConstType.Int32)
- {
- this.Value = new ImmVal { I4 = Value };
- }
-
- public AILOpCodeConst(long Value) : this(ConstType.Int64)
- {
- this.Value = new ImmVal { I8 = Value };
- }
-
- public AILOpCodeConst(float Value) : this(ConstType.Single)
- {
- this.Value = new ImmVal { R4 = Value };
- }
-
- public AILOpCodeConst(double Value) : this(ConstType.Double)
- {
- this.Value = new ImmVal { R8 = Value };
- }
-
- public void Emit(AILEmitter Context)
- {
- switch (Type)
- {
- case ConstType.Int32: Context.Generator.EmitLdc_I4(Value.I4); break;
- case ConstType.Int64: Context.Generator.Emit(OpCodes.Ldc_I8, Value.I8); break;
- case ConstType.Single: Context.Generator.Emit(OpCodes.Ldc_R4, Value.R4); break;
- case ConstType.Double: Context.Generator.Emit(OpCodes.Ldc_R8, Value.R8); break;
- }
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/AILOpCodeLoad.cs b/ChocolArm64/Translation/AILOpCodeLoad.cs
deleted file mode 100644
index d60ce539..00000000
--- a/ChocolArm64/Translation/AILOpCodeLoad.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-using ChocolArm64.State;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Translation
-{
- struct AILOpCodeLoad : IAILEmit
- {
- public int Index { get; private set; }
-
- public AIoType IoType { get; private set; }
-
- public ARegisterSize RegisterSize { get; private set; }
-
- public AILOpCodeLoad(int Index, AIoType IoType, ARegisterSize RegisterSize = 0)
- {
- this.Index = Index;
- this.IoType = IoType;
- this.RegisterSize = RegisterSize;
- }
-
- public void Emit(AILEmitter Context)
- {
- switch (IoType)
- {
- case AIoType.Arg: Context.Generator.EmitLdarg(Index); break;
-
- case AIoType.Fields:
- {
- long IntInputs = Context.LocalAlloc.GetIntInputs(Context.GetILBlock(Index));
- long VecInputs = Context.LocalAlloc.GetVecInputs(Context.GetILBlock(Index));
-
- LoadLocals(Context, IntInputs, ARegisterType.Int);
- LoadLocals(Context, VecInputs, ARegisterType.Vector);
-
- break;
- }
-
- case AIoType.Flag: EmitLdloc(Context, Index, ARegisterType.Flag); break;
- case AIoType.Int: EmitLdloc(Context, Index, ARegisterType.Int); break;
- case AIoType.Vector: EmitLdloc(Context, Index, ARegisterType.Vector); break;
- }
- }
-
- private void LoadLocals(AILEmitter Context, long Inputs, ARegisterType BaseType)
- {
- for (int Bit = 0; Bit < 64; Bit++)
- {
- long Mask = 1L << Bit;
-
- if ((Inputs & Mask) != 0)
- {
- ARegister Reg = AILEmitter.GetRegFromBit(Bit, BaseType);
-
- Context.Generator.EmitLdarg(ATranslatedSub.StateArgIdx);
- Context.Generator.Emit(OpCodes.Ldfld, Reg.GetField());
-
- Context.Generator.EmitStloc(Context.GetLocalIndex(Reg));
- }
- }
- }
-
- private void EmitLdloc(AILEmitter Context, int Index, ARegisterType RegisterType)
- {
- ARegister Reg = new ARegister(Index, RegisterType);
-
- Context.Generator.EmitLdloc(Context.GetLocalIndex(Reg));
-
- if (RegisterType == ARegisterType.Int &&
- RegisterSize == ARegisterSize.Int32)
- {
- Context.Generator.Emit(OpCodes.Conv_U4);
- }
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/AILOpCodeLog.cs b/ChocolArm64/Translation/AILOpCodeLog.cs
deleted file mode 100644
index 1338ca1f..00000000
--- a/ChocolArm64/Translation/AILOpCodeLog.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace ChocolArm64.Translation
-{
- struct AILOpCodeLog : IAILEmit
- {
- private string Text;
-
- public AILOpCodeLog(string Text)
- {
- this.Text = Text;
- }
-
- public void Emit(AILEmitter Context)
- {
- Context.Generator.EmitWriteLine(Text);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/AILOpCodeStore.cs b/ChocolArm64/Translation/AILOpCodeStore.cs
deleted file mode 100644
index a0feb437..00000000
--- a/ChocolArm64/Translation/AILOpCodeStore.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-using ChocolArm64.State;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Translation
-{
- struct AILOpCodeStore : IAILEmit
- {
- public int Index { get; private set; }
-
- public AIoType IoType { get; private set; }
-
- public ARegisterSize RegisterSize { get; private set; }
-
- public AILOpCodeStore(int Index, AIoType IoType, ARegisterSize RegisterSize = 0)
- {
- this.Index = Index;
- this.IoType = IoType;
- this.RegisterSize = RegisterSize;
- }
-
- public void Emit(AILEmitter Context)
- {
- switch (IoType)
- {
- case AIoType.Arg: Context.Generator.EmitStarg(Index); break;
-
- case AIoType.Fields:
- {
- long IntOutputs = Context.LocalAlloc.GetIntOutputs(Context.GetILBlock(Index));
- long VecOutputs = Context.LocalAlloc.GetVecOutputs(Context.GetILBlock(Index));
-
- StoreLocals(Context, IntOutputs, ARegisterType.Int);
- StoreLocals(Context, VecOutputs, ARegisterType.Vector);
-
- break;
- }
-
- case AIoType.Flag: EmitStloc(Context, Index, ARegisterType.Flag); break;
- case AIoType.Int: EmitStloc(Context, Index, ARegisterType.Int); break;
- case AIoType.Vector: EmitStloc(Context, Index, ARegisterType.Vector); break;
- }
- }
-
- private void StoreLocals(AILEmitter Context, long Outputs, ARegisterType BaseType)
- {
- for (int Bit = 0; Bit < 64; Bit++)
- {
- long Mask = 1L << Bit;
-
- if ((Outputs & Mask) != 0)
- {
- ARegister Reg = AILEmitter.GetRegFromBit(Bit, BaseType);
-
- Context.Generator.EmitLdarg(ATranslatedSub.StateArgIdx);
- Context.Generator.EmitLdloc(Context.GetLocalIndex(Reg));
-
- Context.Generator.Emit(OpCodes.Stfld, Reg.GetField());
- }
- }
- }
-
- private void EmitStloc(AILEmitter Context, int Index, ARegisterType RegisterType)
- {
- ARegister Reg = new ARegister(Index, RegisterType);
-
- if (RegisterType == ARegisterType.Int &&
- RegisterSize == ARegisterSize.Int32)
- {
- Context.Generator.Emit(OpCodes.Conv_U8);
- }
-
- Context.Generator.EmitStloc(Context.GetLocalIndex(Reg));
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/ALocalAlloc.cs b/ChocolArm64/Translation/ALocalAlloc.cs
deleted file mode 100644
index 8e904780..00000000
--- a/ChocolArm64/Translation/ALocalAlloc.cs
+++ /dev/null
@@ -1,229 +0,0 @@
-using System.Collections.Generic;
-
-namespace ChocolArm64.Translation
-{
- class ALocalAlloc
- {
- private class PathIo
- {
- private Dictionary<AILBlock, long> AllInputs;
- private Dictionary<AILBlock, long> CmnOutputs;
-
- private long AllOutputs;
-
- public PathIo()
- {
- AllInputs = new Dictionary<AILBlock, long>();
- CmnOutputs = new Dictionary<AILBlock, long>();
- }
-
- public PathIo(AILBlock Root, long Inputs, long Outputs) : this()
- {
- Set(Root, Inputs, Outputs);
- }
-
- public void Set(AILBlock Root, long Inputs, long Outputs)
- {
- if (!AllInputs.TryAdd(Root, Inputs))
- {
- AllInputs[Root] |= Inputs;
- }
-
- if (!CmnOutputs.TryAdd(Root, Outputs))
- {
- CmnOutputs[Root] &= Outputs;
- }
-
- AllOutputs |= Outputs;
- }
-
- public long GetInputs(AILBlock Root)
- {
- if (AllInputs.TryGetValue(Root, out long Inputs))
- {
- return Inputs | (AllOutputs & ~CmnOutputs[Root]);
- }
-
- return 0;
- }
-
- public long GetOutputs()
- {
- return AllOutputs;
- }
- }
-
- private Dictionary<AILBlock, PathIo> IntPaths;
- private Dictionary<AILBlock, PathIo> VecPaths;
-
- private struct BlockIo
- {
- public AILBlock Block;
- public AILBlock Entry;
-
- public long IntInputs;
- public long VecInputs;
- public long IntOutputs;
- public long VecOutputs;
- }
-
- private const int MaxOptGraphLength = 40;
-
- public ALocalAlloc(AILBlock[] Graph, AILBlock Root)
- {
- IntPaths = new Dictionary<AILBlock, PathIo>();
- VecPaths = new Dictionary<AILBlock, PathIo>();
-
- if (Graph.Length > 1 &&
- Graph.Length < MaxOptGraphLength)
- {
- InitializeOptimal(Graph, Root);
- }
- else
- {
- InitializeFast(Graph);
- }
- }
-
- private void InitializeOptimal(AILBlock[] Graph, AILBlock Root)
- {
- //This will go through all possible paths on the graph,
- //and store all inputs/outputs for each block. A register
- //that was previously written to already is not considered an input.
- //When a block can be reached by more than one path, then the
- //output from all paths needs to be set for this block, and
- //only outputs present in all of the parent blocks can be considered
- //when doing input elimination. Each block chain have a root, that's where
- //the code starts executing. They are present on the subroutine start point,
- //and on call return points too (address written to X30 by BL).
- HashSet<BlockIo> Visited = new HashSet<BlockIo>();
-
- Queue<BlockIo> Unvisited = new Queue<BlockIo>();
-
- void Enqueue(BlockIo Block)
- {
- if (!Visited.Contains(Block))
- {
- Unvisited.Enqueue(Block);
-
- Visited.Add(Block);
- }
- }
-
- Enqueue(new BlockIo()
- {
- Block = Root,
- Entry = Root
- });
-
- while (Unvisited.Count > 0)
- {
- BlockIo Current = Unvisited.Dequeue();
-
- Current.IntInputs |= Current.Block.IntInputs & ~Current.IntOutputs;
- Current.VecInputs |= Current.Block.VecInputs & ~Current.VecOutputs;
- Current.IntOutputs |= Current.Block.IntOutputs;
- Current.VecOutputs |= Current.Block.VecOutputs;
-
- //Check if this is a exit block
- //(a block that returns or calls another sub).
- if ((Current.Block.Next == null &&
- Current.Block.Branch == null) || Current.Block.HasStateStore)
- {
- if (!IntPaths.TryGetValue(Current.Block, out PathIo IntPath))
- {
- IntPaths.Add(Current.Block, IntPath = new PathIo());
- }
-
- if (!VecPaths.TryGetValue(Current.Block, out PathIo VecPath))
- {
- VecPaths.Add(Current.Block, VecPath = new PathIo());
- }
-
- IntPath.Set(Current.Entry, Current.IntInputs, Current.IntOutputs);
- VecPath.Set(Current.Entry, Current.VecInputs, Current.VecOutputs);
- }
-
- void EnqueueFromCurrent(AILBlock Block, bool RetTarget)
- {
- BlockIo BlkIO = new BlockIo() { Block = Block };
-
- if (RetTarget)
- {
- BlkIO.Entry = Block;
- }
- else
- {
- BlkIO.Entry = Current.Entry;
- BlkIO.IntInputs = Current.IntInputs;
- BlkIO.VecInputs = Current.VecInputs;
- BlkIO.IntOutputs = Current.IntOutputs;
- BlkIO.VecOutputs = Current.VecOutputs;
- }
-
- Enqueue(BlkIO);
- }
-
- if (Current.Block.Next != null)
- {
- EnqueueFromCurrent(Current.Block.Next, Current.Block.HasStateStore);
- }
-
- if (Current.Block.Branch != null)
- {
- EnqueueFromCurrent(Current.Block.Branch, false);
- }
- }
- }
-
- private void InitializeFast(AILBlock[] Graph)
- {
- //This is WAY faster than InitializeOptimal, but results in
- //uneeded loads and stores, so the resulting code will be slower.
- long IntInputs = 0, IntOutputs = 0;
- long VecInputs = 0, VecOutputs = 0;
-
- foreach (AILBlock Block in Graph)
- {
- IntInputs |= Block.IntInputs;
- IntOutputs |= Block.IntOutputs;
- VecInputs |= Block.VecInputs;
- VecOutputs |= Block.VecOutputs;
- }
-
- //It's possible that not all code paths writes to those output registers,
- //in those cases if we attempt to write an output registers that was
- //not written, we will be just writing zero and messing up the old register value.
- //So we just need to ensure that all outputs are loaded.
- if (Graph.Length > 1)
- {
- IntInputs |= IntOutputs;
- VecInputs |= VecOutputs;
- }
-
- foreach (AILBlock Block in Graph)
- {
- IntPaths.Add(Block, new PathIo(Block, IntInputs, IntOutputs));
- VecPaths.Add(Block, new PathIo(Block, VecInputs, VecOutputs));
- }
- }
-
- public long GetIntInputs(AILBlock Root) => GetInputsImpl(Root, IntPaths.Values);
- public long GetVecInputs(AILBlock Root) => GetInputsImpl(Root, VecPaths.Values);
-
- private long GetInputsImpl(AILBlock Root, IEnumerable<PathIo> Values)
- {
- long Inputs = 0;
-
- foreach (PathIo Path in Values)
- {
- Inputs |= Path.GetInputs(Root);
- }
-
- return Inputs;
- }
-
- public long GetIntOutputs(AILBlock Block) => IntPaths[Block].GetOutputs();
- public long GetVecOutputs(AILBlock Block) => VecPaths[Block].GetOutputs();
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/IAILEmit.cs b/ChocolArm64/Translation/IAILEmit.cs
deleted file mode 100644
index 6e4e9a78..00000000
--- a/ChocolArm64/Translation/IAILEmit.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace ChocolArm64.Translation
-{
- interface IAILEmit
- {
- void Emit(AILEmitter Context);
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Translation/IILEmit.cs b/ChocolArm64/Translation/IILEmit.cs
new file mode 100644
index 00000000..3c3925ee
--- /dev/null
+++ b/ChocolArm64/Translation/IILEmit.cs
@@ -0,0 +1,7 @@
+namespace ChocolArm64.Translation
+{
+ interface IILEmit
+ {
+ void Emit(ILEmitter context);
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translation/ILBarrier.cs b/ChocolArm64/Translation/ILBarrier.cs
new file mode 100644
index 00000000..f931e992
--- /dev/null
+++ b/ChocolArm64/Translation/ILBarrier.cs
@@ -0,0 +1,7 @@
+namespace ChocolArm64.Translation
+{
+ struct ILBarrier : IILEmit
+ {
+ public void Emit(ILEmitter context) { }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translation/ILBlock.cs b/ChocolArm64/Translation/ILBlock.cs
new file mode 100644
index 00000000..d51e8d9e
--- /dev/null
+++ b/ChocolArm64/Translation/ILBlock.cs
@@ -0,0 +1,76 @@
+using System.Collections.Generic;
+
+namespace ChocolArm64.Translation
+{
+ class ILBlock : IILEmit
+ {
+ public long IntInputs { get; private set; }
+ public long IntOutputs { get; private set; }
+ public long IntAwOutputs { get; private set; }
+
+ public long VecInputs { get; private set; }
+ public long VecOutputs { get; private set; }
+ public long VecAwOutputs { get; private set; }
+
+ public bool HasStateStore { get; private set; }
+
+ public List<IILEmit> IlEmitters { get; private set; }
+
+ public ILBlock Next { get; set; }
+ public ILBlock Branch { get; set; }
+
+ public ILBlock()
+ {
+ IlEmitters = new List<IILEmit>();
+ }
+
+ public void Add(IILEmit ilEmitter)
+ {
+ if (ilEmitter is ILBarrier)
+ {
+ //Those barriers are used to separate the groups of CIL
+ //opcodes emitted by each ARM instruction.
+ //We can only consider the new outputs for doing input elimination
+ //after all the CIL opcodes used by the instruction being emitted.
+ IntAwOutputs = IntOutputs;
+ VecAwOutputs = VecOutputs;
+ }
+ else if (ilEmitter is IlOpCodeLoad ld && ILEmitter.IsRegIndex(ld.Index))
+ {
+ switch (ld.IoType)
+ {
+ case IoType.Flag: IntInputs |= ((1L << ld.Index) << 32) & ~IntAwOutputs; break;
+ case IoType.Int: IntInputs |= (1L << ld.Index) & ~IntAwOutputs; break;
+ case IoType.Vector: VecInputs |= (1L << ld.Index) & ~VecAwOutputs; break;
+ }
+ }
+ else if (ilEmitter is IlOpCodeStore st)
+ {
+ if (ILEmitter.IsRegIndex(st.Index))
+ {
+ switch (st.IoType)
+ {
+ case IoType.Flag: IntOutputs |= (1L << st.Index) << 32; break;
+ case IoType.Int: IntOutputs |= 1L << st.Index; break;
+ case IoType.Vector: VecOutputs |= 1L << st.Index; break;
+ }
+ }
+
+ if (st.IoType == IoType.Fields)
+ {
+ HasStateStore = true;
+ }
+ }
+
+ IlEmitters.Add(ilEmitter);
+ }
+
+ public void Emit(ILEmitter context)
+ {
+ foreach (IILEmit ilEmitter in IlEmitters)
+ {
+ ilEmitter.Emit(context);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translation/ILEmitter.cs b/ChocolArm64/Translation/ILEmitter.cs
new file mode 100644
index 00000000..543528d7
--- /dev/null
+++ b/ChocolArm64/Translation/ILEmitter.cs
@@ -0,0 +1,188 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.State;
+using System;
+using System.Collections.Generic;
+using System.Reflection.Emit;
+using System.Runtime.Intrinsics;
+
+namespace ChocolArm64.Translation
+{
+ class ILEmitter
+ {
+ public LocalAlloc LocalAlloc { get; private set; }
+
+ public ILGenerator Generator { get; private set; }
+
+ private Dictionary<Register, int> _locals;
+
+ private ILBlock[] _ilBlocks;
+
+ private ILBlock _root;
+
+ private TranslatedSub _subroutine;
+
+ private string _subName;
+
+ private int _localsCount;
+
+ public ILEmitter(Block[] graph, Block root, string subName)
+ {
+ _subName = subName;
+
+ _locals = new Dictionary<Register, int>();
+
+ _ilBlocks = new ILBlock[graph.Length];
+
+ ILBlock GetBlock(int index)
+ {
+ if (index < 0 || index >= _ilBlocks.Length)
+ {
+ return null;
+ }
+
+ if (_ilBlocks[index] == null)
+ {
+ _ilBlocks[index] = new ILBlock();
+ }
+
+ return _ilBlocks[index];
+ }
+
+ for (int index = 0; index < _ilBlocks.Length; index++)
+ {
+ ILBlock block = GetBlock(index);
+
+ block.Next = GetBlock(Array.IndexOf(graph, graph[index].Next));
+ block.Branch = GetBlock(Array.IndexOf(graph, graph[index].Branch));
+ }
+
+ _root = _ilBlocks[Array.IndexOf(graph, root)];
+ }
+
+ public ILBlock GetIlBlock(int index) => _ilBlocks[index];
+
+ public TranslatedSub GetSubroutine()
+ {
+ LocalAlloc = new LocalAlloc(_ilBlocks, _root);
+
+ InitSubroutine();
+ InitLocals();
+
+ foreach (ILBlock ilBlock in _ilBlocks)
+ {
+ ilBlock.Emit(this);
+ }
+
+ return _subroutine;
+ }
+
+ private void InitSubroutine()
+ {
+ List<Register> Params = new List<Register>();
+
+ void SetParams(long inputs, RegisterType baseType)
+ {
+ for (int bit = 0; bit < 64; bit++)
+ {
+ long mask = 1L << bit;
+
+ if ((inputs & mask) != 0)
+ {
+ Params.Add(GetRegFromBit(bit, baseType));
+ }
+ }
+ }
+
+ SetParams(LocalAlloc.GetIntInputs(_root), RegisterType.Int);
+ SetParams(LocalAlloc.GetVecInputs(_root), RegisterType.Vector);
+
+ DynamicMethod mthd = new DynamicMethod(_subName, typeof(long), GetParamTypes(Params));
+
+ Generator = mthd.GetILGenerator();
+
+ _subroutine = new TranslatedSub(mthd, Params);
+ }
+
+ private void InitLocals()
+ {
+ int paramsStart = TranslatedSub.FixedArgTypes.Length;
+
+ _locals = new Dictionary<Register, int>();
+
+ for (int index = 0; index < _subroutine.Params.Count; index++)
+ {
+ Register reg = _subroutine.Params[index];
+
+ Generator.EmitLdarg(index + paramsStart);
+ Generator.EmitStloc(GetLocalIndex(reg));
+ }
+ }
+
+ private Type[] GetParamTypes(IList<Register> Params)
+ {
+ Type[] fixedArgs = TranslatedSub.FixedArgTypes;
+
+ Type[] output = new Type[Params.Count + fixedArgs.Length];
+
+ fixedArgs.CopyTo(output, 0);
+
+ int typeIdx = fixedArgs.Length;
+
+ for (int index = 0; index < Params.Count; index++)
+ {
+ output[typeIdx++] = GetFieldType(Params[index].Type);
+ }
+
+ return output;
+ }
+
+ public int GetLocalIndex(Register reg)
+ {
+ if (!_locals.TryGetValue(reg, out int index))
+ {
+ Generator.DeclareLocal(GetLocalType(reg));
+
+ index = _localsCount++;
+
+ _locals.Add(reg, index);
+ }
+
+ return index;
+ }
+
+ public Type GetLocalType(Register reg) => GetFieldType(reg.Type);
+
+ public Type GetFieldType(RegisterType regType)
+ {
+ switch (regType)
+ {
+ case RegisterType.Flag: return typeof(bool);
+ case RegisterType.Int: return typeof(ulong);
+ case RegisterType.Vector: return typeof(Vector128<float>);
+ }
+
+ throw new ArgumentException(nameof(regType));
+ }
+
+ public static Register GetRegFromBit(int bit, RegisterType baseType)
+ {
+ if (bit < 32)
+ {
+ return new Register(bit, baseType);
+ }
+ else if (baseType == RegisterType.Int)
+ {
+ return new Register(bit & 0x1f, RegisterType.Flag);
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException(nameof(bit));
+ }
+ }
+
+ public static bool IsRegIndex(int index)
+ {
+ return index >= 0 && index < 32;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translation/ILEmitterCtx.cs b/ChocolArm64/Translation/ILEmitterCtx.cs
new file mode 100644
index 00000000..c1d1be36
--- /dev/null
+++ b/ChocolArm64/Translation/ILEmitterCtx.cs
@@ -0,0 +1,554 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace ChocolArm64.Translation
+{
+ class ILEmitterCtx
+ {
+ private TranslatorCache _cache;
+
+ private Dictionary<long, ILLabel> _labels;
+
+ private int _blkIndex;
+ private int _opcIndex;
+
+ private Block[] _graph;
+ private Block _root;
+ public Block CurrBlock => _graph[_blkIndex];
+ public OpCode64 CurrOp => _graph[_blkIndex].OpCodes[_opcIndex];
+
+ private ILEmitter _emitter;
+
+ private ILBlock _ilBlock;
+
+ 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 Tmp1Index = -1;
+ private const int Tmp2Index = -2;
+ private const int Tmp3Index = -3;
+ private const int Tmp4Index = -4;
+ private const int Tmp5Index = -5;
+ private const int Tmp6Index = -6;
+
+ public ILEmitterCtx(
+ TranslatorCache cache,
+ Block[] graph,
+ Block root,
+ string subName)
+ {
+ _cache = cache ?? throw new ArgumentNullException(nameof(cache));
+ _graph = graph ?? throw new ArgumentNullException(nameof(graph));
+ _root = root ?? throw new ArgumentNullException(nameof(root));
+
+ _labels = new Dictionary<long, ILLabel>();
+
+ _emitter = new ILEmitter(graph, root, subName);
+
+ _ilBlock = _emitter.GetIlBlock(0);
+
+ _opcIndex = -1;
+
+ if (graph.Length == 0 || !AdvanceOpCode())
+ {
+ throw new ArgumentException(nameof(graph));
+ }
+ }
+
+ public TranslatedSub GetSubroutine()
+ {
+ return _emitter.GetSubroutine();
+ }
+
+ public bool AdvanceOpCode()
+ {
+ if (_opcIndex + 1 == CurrBlock.OpCodes.Count &&
+ _blkIndex + 1 == _graph.Length)
+ {
+ return false;
+ }
+
+ while (++_opcIndex >= (CurrBlock?.OpCodes.Count ?? 0))
+ {
+ _blkIndex++;
+ _opcIndex = -1;
+
+ _optOpLastFlagSet = null;
+ _optOpLastCompare = null;
+
+ _ilBlock = _emitter.GetIlBlock(_blkIndex);
+ }
+
+ return true;
+ }
+
+ public void EmitOpCode()
+ {
+ if (_opcIndex == 0)
+ {
+ MarkLabel(GetLabel(CurrBlock.Position));
+
+ EmitSynchronization();
+ }
+
+ CurrOp.Emitter(this);
+
+ _ilBlock.Add(new ILBarrier());
+ }
+
+ private void EmitSynchronization()
+ {
+ EmitLdarg(TranslatedSub.StateArgIdx);
+
+ EmitLdc_I4(CurrBlock.OpCodes.Count);
+
+ 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 bool TryOptEmitSubroutineCall()
+ {
+ if (CurrBlock.Next == null)
+ {
+ return false;
+ }
+
+ if (CurrOp.Emitter != InstEmit.Bl)
+ {
+ return false;
+ }
+
+ if (!_cache.TryGetSubroutine(((OpCodeBImmAl64)CurrOp).Imm, out TranslatedSub subroutine))
+ {
+ return false;
+ }
+
+ for (int index = 0; index < TranslatedSub.FixedArgTypes.Length; index++)
+ {
+ EmitLdarg(index);
+ }
+
+ foreach (Register reg in subroutine.Params)
+ {
+ switch (reg.Type)
+ {
+ case RegisterType.Flag: Ldloc(reg.Index, IoType.Flag); break;
+ case RegisterType.Int: Ldloc(reg.Index, IoType.Int); break;
+ case RegisterType.Vector: Ldloc(reg.Index, IoType.Vector); break;
+ }
+ }
+
+ EmitCall(subroutine.Method);
+
+ subroutine.AddCaller(_root.Position);
+
+ return true;
+ }
+
+ public void TryOptMarkCondWithoutCmp()
+ {
+ _optOpLastCompare = CurrOp;
+
+ InstEmitAluHelper.EmitDataLoadOpers(this);
+
+ Stloc(Tmp4Index, IoType.Int);
+ Stloc(Tmp3Index, IoType.Int);
+ }
+
+ private Dictionary<Cond, System.Reflection.Emit.OpCode> _branchOps = new Dictionary<Cond, System.Reflection.Emit.OpCode>()
+ {
+ { Cond.Eq, OpCodes.Beq },
+ { Cond.Ne, OpCodes.Bne_Un },
+ { Cond.GeUn, OpCodes.Bge_Un },
+ { Cond.LtUn, OpCodes.Blt_Un },
+ { Cond.GtUn, OpCodes.Bgt_Un },
+ { Cond.LeUn, OpCodes.Ble_Un },
+ { Cond.Ge, OpCodes.Bge },
+ { Cond.Lt, OpCodes.Blt },
+ { Cond.Gt, OpCodes.Bgt },
+ { Cond.Le, OpCodes.Ble }
+ };
+
+ public void EmitCondBranch(ILLabel target, Cond cond)
+ {
+ System.Reflection.Emit.OpCode ilOp;
+
+ int intCond = (int)cond;
+
+ if (_optOpLastCompare != null &&
+ _optOpLastCompare == _optOpLastFlagSet && _branchOps.ContainsKey(cond))
+ {
+ Ldloc(Tmp3Index, IoType.Int, _optOpLastCompare.RegisterSize);
+ Ldloc(Tmp4Index, IoType.Int, _optOpLastCompare.RegisterSize);
+
+ ilOp = _branchOps[cond];
+ }
+ else 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, System.Reflection.Emit.OpCode ilOp)
+ {
+ if (amount > 0)
+ {
+ EmitLdc_I4(amount);
+
+ Emit(ilOp);
+ }
+ }
+
+ public void EmitRor(int amount)
+ {
+ if (amount > 0)
+ {
+ Stloc(Tmp2Index, IoType.Int);
+ Ldloc(Tmp2Index, IoType.Int);
+
+ EmitLdc_I4(amount);
+
+ Emit(OpCodes.Shr_Un);
+
+ Ldloc(Tmp2Index, IoType.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)
+ {
+ _ilBlock.Add(label);
+ }
+
+ public void Emit(System.Reflection.Emit.OpCode ilOp)
+ {
+ _ilBlock.Add(new ILOpCode(ilOp));
+ }
+
+ public void Emit(System.Reflection.Emit.OpCode ilOp, ILLabel label)
+ {
+ _ilBlock.Add(new ILOpCodeBranch(ilOp, label));
+ }
+
+ public void Emit(string text)
+ {
+ _ilBlock.Add(new ILOpCodeLog(text));
+ }
+
+ public void EmitLdarg(int index)
+ {
+ _ilBlock.Add(new IlOpCodeLoad(index, IoType.Arg));
+ }
+
+ public void EmitLdintzr(int index)
+ {
+ if (index != CpuThreadState.ZrIndex)
+ {
+ EmitLdint(index);
+ }
+ else
+ {
+ EmitLdc_I(0);
+ }
+ }
+
+ public void EmitStintzr(int index)
+ {
+ if (index != CpuThreadState.ZrIndex)
+ {
+ EmitStint(index);
+ }
+ else
+ {
+ Emit(OpCodes.Pop);
+ }
+ }
+
+ public void EmitLoadState(Block retBlk)
+ {
+ _ilBlock.Add(new IlOpCodeLoad(Array.IndexOf(_graph, retBlk), IoType.Fields));
+ }
+
+ public void EmitStoreState()
+ {
+ _ilBlock.Add(new IlOpCodeStore(Array.IndexOf(_graph, CurrBlock), IoType.Fields));
+ }
+
+ public void EmitLdtmp() => EmitLdint(Tmp1Index);
+ public void EmitSttmp() => EmitStint(Tmp1Index);
+
+ public void EmitLdvectmp() => EmitLdvec(Tmp5Index);
+ public void EmitStvectmp() => EmitStvec(Tmp5Index);
+
+ public void EmitLdvectmp2() => EmitLdvec(Tmp6Index);
+ public void EmitStvectmp2() => EmitStvec(Tmp6Index);
+
+ public void EmitLdint(int index) => Ldloc(index, IoType.Int);
+ public void EmitStint(int index) => Stloc(index, IoType.Int);
+
+ public void EmitLdvec(int index) => Ldloc(index, IoType.Vector);
+ public void EmitStvec(int index) => Stloc(index, IoType.Vector);
+
+ public void EmitLdflg(int index) => Ldloc(index, IoType.Flag);
+ public void EmitStflg(int index)
+ {
+ _optOpLastFlagSet = CurrOp;
+
+ Stloc(index, IoType.Flag);
+ }
+
+ private void Ldloc(int index, IoType ioType)
+ {
+ _ilBlock.Add(new IlOpCodeLoad(index, ioType, CurrOp.RegisterSize));
+ }
+
+ private void Ldloc(int index, IoType ioType, RegisterSize registerSize)
+ {
+ _ilBlock.Add(new IlOpCodeLoad(index, ioType, registerSize));
+ }
+
+ private void Stloc(int index, IoType ioType)
+ {
+ _ilBlock.Add(new IlOpCodeStore(index, ioType, CurrOp.RegisterSize));
+ }
+
+ public void EmitCallPropGet(Type objType, string propName)
+ {
+ if (objType == null)
+ {
+ throw new ArgumentNullException(nameof(objType));
+ }
+
+ if (propName == null)
+ {
+ throw new ArgumentNullException(nameof(propName));
+ }
+
+ EmitCall(objType.GetMethod($"get_{propName}"));
+ }
+
+ public void EmitCallPropSet(Type objType, string propName)
+ {
+ if (objType == null)
+ {
+ throw new ArgumentNullException(nameof(objType));
+ }
+
+ if (propName == null)
+ {
+ throw new ArgumentNullException(nameof(propName));
+ }
+
+ EmitCall(objType.GetMethod($"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 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)
+ {
+ if (mthdInfo == null)
+ {
+ throw new ArgumentNullException(nameof(mthdInfo));
+ }
+
+ _ilBlock.Add(new ILOpCodeCall(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)
+ {
+ _ilBlock.Add(new ILOpCodeConst(value));
+ }
+
+ public void EmitLdc_I8(long value)
+ {
+ _ilBlock.Add(new ILOpCodeConst(value));
+ }
+
+ public void EmitLdc_R4(float value)
+ {
+ _ilBlock.Add(new ILOpCodeConst(value));
+ }
+
+ public void EmitLdc_R8(double value)
+ {
+ _ilBlock.Add(new ILOpCodeConst(value));
+ }
+
+ public void EmitZnFlagCheck()
+ {
+ EmitZnCheck(OpCodes.Ceq, (int)PState.ZBit);
+ EmitZnCheck(OpCodes.Clt, (int)PState.NBit);
+ }
+
+ private void EmitZnCheck(System.Reflection.Emit.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);
+ }
+ }
+}
diff --git a/ChocolArm64/Translation/ILGeneratorEx.cs b/ChocolArm64/Translation/ILGeneratorEx.cs
index 40c6efa4..318098cc 100644
--- a/ChocolArm64/Translation/ILGeneratorEx.cs
+++ b/ChocolArm64/Translation/ILGeneratorEx.cs
@@ -6,123 +6,123 @@ namespace ChocolArm64
static class ILGeneratorEx
{
- public static void EmitLdc_I4(this ILGenerator Generator, int Value)
+ public static void EmitLdc_I4(this ILGenerator generator, int value)
{
- switch (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;
+ 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)
+ public static void EmitLdarg(this ILGenerator generator, int index)
{
- switch (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;
+ 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)
+ if ((uint)index <= byte.MaxValue)
{
- Generator.Emit(OpCodes.Ldarg_S, (byte)Index);
+ generator.Emit(OpCodes.Ldarg_S, (byte)index);
}
- else if ((uint)Index < ushort.MaxValue)
+ else if ((uint)index < ushort.MaxValue)
{
- Generator.Emit(OpCodes.Ldarg, (short)Index);
+ generator.Emit(OpCodes.Ldarg, (short)index);
}
else
{
- throw new ArgumentOutOfRangeException(nameof(Index));
+ throw new ArgumentOutOfRangeException(nameof(index));
}
break;
}
}
- public static void EmitStarg(this ILGenerator Generator, int Index)
+ public static void EmitStarg(this ILGenerator generator, int index)
{
- if ((uint)Index <= byte.MaxValue)
+ if ((uint)index <= byte.MaxValue)
{
- Generator.Emit(OpCodes.Starg_S, (byte)Index);
+ generator.Emit(OpCodes.Starg_S, (byte)index);
}
- else if ((uint)Index < ushort.MaxValue)
+ else if ((uint)index < ushort.MaxValue)
{
- Generator.Emit(OpCodes.Starg, (short)Index);
+ generator.Emit(OpCodes.Starg, (short)index);
}
else
{
- throw new ArgumentOutOfRangeException(nameof(Index));
+ throw new ArgumentOutOfRangeException(nameof(index));
}
}
- public static void EmitLdloc(this ILGenerator Generator, int Index)
+ public static void EmitLdloc(this ILGenerator generator, int index)
{
- switch (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;
+ 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)
+ if ((uint)index <= byte.MaxValue)
{
- Generator.Emit(OpCodes.Ldloc_S, (byte)Index);
+ generator.Emit(OpCodes.Ldloc_S, (byte)index);
}
- else if ((uint)Index < ushort.MaxValue)
+ else if ((uint)index < ushort.MaxValue)
{
- Generator.Emit(OpCodes.Ldloc, (short)Index);
+ generator.Emit(OpCodes.Ldloc, (short)index);
}
else
{
- throw new ArgumentOutOfRangeException(nameof(Index));
+ throw new ArgumentOutOfRangeException(nameof(index));
}
break;
}
}
- public static void EmitStloc(this ILGenerator Generator, int Index)
+ public static void EmitStloc(this ILGenerator generator, int index)
{
- switch (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;
+ 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)
+ if ((uint)index <= byte.MaxValue)
{
- Generator.Emit(OpCodes.Stloc_S, (byte)Index);
+ generator.Emit(OpCodes.Stloc_S, (byte)index);
}
- else if ((uint)Index < ushort.MaxValue)
+ else if ((uint)index < ushort.MaxValue)
{
- Generator.Emit(OpCodes.Stloc, (short)Index);
+ generator.Emit(OpCodes.Stloc, (short)index);
}
else
{
- throw new ArgumentOutOfRangeException(nameof(Index));
+ throw new ArgumentOutOfRangeException(nameof(index));
}
break;
}
}
- public static void EmitLdargSeq(this ILGenerator Generator, int Count)
+ public static void EmitLdargSeq(this ILGenerator generator, int count)
{
- for (int Index = 0; Index < Count; Index++)
+ for (int index = 0; index < count; index++)
{
- Generator.EmitLdarg(Index);
+ generator.EmitLdarg(index);
}
}
}
diff --git a/ChocolArm64/Translation/ILLabel.cs b/ChocolArm64/Translation/ILLabel.cs
new file mode 100644
index 00000000..4f96edcc
--- /dev/null
+++ b/ChocolArm64/Translation/ILLabel.cs
@@ -0,0 +1,28 @@
+using System.Reflection.Emit;
+
+namespace ChocolArm64.Translation
+{
+ class ILLabel : IILEmit
+ {
+ private bool _hasLabel;
+
+ private Label _lbl;
+
+ public void Emit(ILEmitter context)
+ {
+ context.Generator.MarkLabel(GetLabel(context));
+ }
+
+ public Label GetLabel(ILEmitter context)
+ {
+ if (!_hasLabel)
+ {
+ _lbl = context.Generator.DefineLabel();
+
+ _hasLabel = true;
+ }
+
+ return _lbl;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translation/ILOpCode.cs b/ChocolArm64/Translation/ILOpCode.cs
new file mode 100644
index 00000000..eb91639e
--- /dev/null
+++ b/ChocolArm64/Translation/ILOpCode.cs
@@ -0,0 +1,19 @@
+using System.Reflection.Emit;
+
+namespace ChocolArm64.Translation
+{
+ struct ILOpCode : IILEmit
+ {
+ private OpCode _ilOp;
+
+ public ILOpCode(OpCode ilOp)
+ {
+ _ilOp = ilOp;
+ }
+
+ public void Emit(ILEmitter context)
+ {
+ context.Generator.Emit(_ilOp);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translation/ILOpCodeBranch.cs b/ChocolArm64/Translation/ILOpCodeBranch.cs
new file mode 100644
index 00000000..b0ba2331
--- /dev/null
+++ b/ChocolArm64/Translation/ILOpCodeBranch.cs
@@ -0,0 +1,21 @@
+using System.Reflection.Emit;
+
+namespace ChocolArm64.Translation
+{
+ struct ILOpCodeBranch : IILEmit
+ {
+ private OpCode _ilOp;
+ private ILLabel _label;
+
+ public ILOpCodeBranch(OpCode ilOp, ILLabel label)
+ {
+ _ilOp = ilOp;
+ _label = label;
+ }
+
+ public void Emit(ILEmitter context)
+ {
+ context.Generator.Emit(_ilOp, _label.GetLabel(context));
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translation/ILOpCodeCall.cs b/ChocolArm64/Translation/ILOpCodeCall.cs
new file mode 100644
index 00000000..0b591d46
--- /dev/null
+++ b/ChocolArm64/Translation/ILOpCodeCall.cs
@@ -0,0 +1,20 @@
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace ChocolArm64.Translation
+{
+ struct ILOpCodeCall : IILEmit
+ {
+ private MethodInfo _mthdInfo;
+
+ public ILOpCodeCall(MethodInfo mthdInfo)
+ {
+ _mthdInfo = mthdInfo;
+ }
+
+ public void Emit(ILEmitter context)
+ {
+ context.Generator.Emit(OpCodes.Call, _mthdInfo);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translation/ILOpCodeConst.cs b/ChocolArm64/Translation/ILOpCodeConst.cs
new file mode 100644
index 00000000..5497eba1
--- /dev/null
+++ b/ChocolArm64/Translation/ILOpCodeConst.cs
@@ -0,0 +1,65 @@
+using System.Reflection.Emit;
+using System.Runtime.InteropServices;
+
+namespace ChocolArm64.Translation
+{
+ class ILOpCodeConst : IILEmit
+ {
+ [StructLayout(LayoutKind.Explicit, Size = 8)]
+ private struct ImmVal
+ {
+ [FieldOffset(0)] public int I4;
+ [FieldOffset(0)] public long I8;
+ [FieldOffset(0)] public float R4;
+ [FieldOffset(0)] public double R8;
+ }
+
+ private ImmVal _value;
+
+ private enum ConstType
+ {
+ Int32,
+ Int64,
+ Single,
+ Double
+ }
+
+ private ConstType _type;
+
+ private ILOpCodeConst(ConstType type)
+ {
+ _type = type;
+ }
+
+ public ILOpCodeConst(int value) : this(ConstType.Int32)
+ {
+ _value = new ImmVal { I4 = value };
+ }
+
+ public ILOpCodeConst(long value) : this(ConstType.Int64)
+ {
+ _value = new ImmVal { I8 = value };
+ }
+
+ public ILOpCodeConst(float value) : this(ConstType.Single)
+ {
+ _value = new ImmVal { R4 = value };
+ }
+
+ public ILOpCodeConst(double value) : this(ConstType.Double)
+ {
+ _value = new ImmVal { R8 = value };
+ }
+
+ public void Emit(ILEmitter context)
+ {
+ switch (_type)
+ {
+ case ConstType.Int32: context.Generator.EmitLdc_I4(_value.I4); break;
+ case ConstType.Int64: context.Generator.Emit(OpCodes.Ldc_I8, _value.I8); break;
+ case ConstType.Single: context.Generator.Emit(OpCodes.Ldc_R4, _value.R4); break;
+ case ConstType.Double: context.Generator.Emit(OpCodes.Ldc_R8, _value.R8); break;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translation/ILOpCodeLoad.cs b/ChocolArm64/Translation/ILOpCodeLoad.cs
new file mode 100644
index 00000000..9dae10cc
--- /dev/null
+++ b/ChocolArm64/Translation/ILOpCodeLoad.cs
@@ -0,0 +1,75 @@
+using ChocolArm64.State;
+using System.Reflection.Emit;
+
+namespace ChocolArm64.Translation
+{
+ struct IlOpCodeLoad : IILEmit
+ {
+ public int Index { get; private set; }
+
+ public IoType IoType { get; private set; }
+
+ public RegisterSize RegisterSize { get; private set; }
+
+ public IlOpCodeLoad(int index, IoType ioType, RegisterSize registerSize = 0)
+ {
+ Index = index;
+ IoType = ioType;
+ RegisterSize = registerSize;
+ }
+
+ public void Emit(ILEmitter context)
+ {
+ switch (IoType)
+ {
+ case IoType.Arg: context.Generator.EmitLdarg(Index); break;
+
+ case IoType.Fields:
+ {
+ long intInputs = context.LocalAlloc.GetIntInputs(context.GetIlBlock(Index));
+ long vecInputs = context.LocalAlloc.GetVecInputs(context.GetIlBlock(Index));
+
+ LoadLocals(context, intInputs, RegisterType.Int);
+ LoadLocals(context, vecInputs, RegisterType.Vector);
+
+ break;
+ }
+
+ case IoType.Flag: EmitLdloc(context, Index, RegisterType.Flag); break;
+ case IoType.Int: EmitLdloc(context, Index, RegisterType.Int); break;
+ case IoType.Vector: EmitLdloc(context, Index, RegisterType.Vector); break;
+ }
+ }
+
+ private void LoadLocals(ILEmitter context, long inputs, RegisterType baseType)
+ {
+ for (int bit = 0; bit < 64; bit++)
+ {
+ long mask = 1L << bit;
+
+ if ((inputs & mask) != 0)
+ {
+ Register reg = ILEmitter.GetRegFromBit(bit, baseType);
+
+ context.Generator.EmitLdarg(TranslatedSub.StateArgIdx);
+ context.Generator.Emit(OpCodes.Ldfld, reg.GetField());
+
+ context.Generator.EmitStloc(context.GetLocalIndex(reg));
+ }
+ }
+ }
+
+ private void EmitLdloc(ILEmitter context, int index, RegisterType registerType)
+ {
+ Register reg = new Register(index, registerType);
+
+ context.Generator.EmitLdloc(context.GetLocalIndex(reg));
+
+ if (registerType == RegisterType.Int &&
+ RegisterSize == RegisterSize.Int32)
+ {
+ context.Generator.Emit(OpCodes.Conv_U4);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translation/ILOpCodeLog.cs b/ChocolArm64/Translation/ILOpCodeLog.cs
new file mode 100644
index 00000000..2c77021b
--- /dev/null
+++ b/ChocolArm64/Translation/ILOpCodeLog.cs
@@ -0,0 +1,17 @@
+namespace ChocolArm64.Translation
+{
+ struct ILOpCodeLog : IILEmit
+ {
+ private string _text;
+
+ public ILOpCodeLog(string text)
+ {
+ _text = text;
+ }
+
+ public void Emit(ILEmitter context)
+ {
+ context.Generator.EmitWriteLine(_text);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translation/ILOpCodeStore.cs b/ChocolArm64/Translation/ILOpCodeStore.cs
new file mode 100644
index 00000000..41326fe1
--- /dev/null
+++ b/ChocolArm64/Translation/ILOpCodeStore.cs
@@ -0,0 +1,75 @@
+using ChocolArm64.State;
+using System.Reflection.Emit;
+
+namespace ChocolArm64.Translation
+{
+ struct IlOpCodeStore : IILEmit
+ {
+ public int Index { get; private set; }
+
+ public IoType IoType { get; private set; }
+
+ public RegisterSize RegisterSize { get; private set; }
+
+ public IlOpCodeStore(int index, IoType ioType, RegisterSize registerSize = 0)
+ {
+ Index = index;
+ IoType = ioType;
+ RegisterSize = registerSize;
+ }
+
+ public void Emit(ILEmitter context)
+ {
+ switch (IoType)
+ {
+ case IoType.Arg: context.Generator.EmitStarg(Index); break;
+
+ case IoType.Fields:
+ {
+ long intOutputs = context.LocalAlloc.GetIntOutputs(context.GetIlBlock(Index));
+ long vecOutputs = context.LocalAlloc.GetVecOutputs(context.GetIlBlock(Index));
+
+ StoreLocals(context, intOutputs, RegisterType.Int);
+ StoreLocals(context, vecOutputs, RegisterType.Vector);
+
+ break;
+ }
+
+ case IoType.Flag: EmitStloc(context, Index, RegisterType.Flag); break;
+ case IoType.Int: EmitStloc(context, Index, RegisterType.Int); break;
+ case IoType.Vector: EmitStloc(context, Index, RegisterType.Vector); break;
+ }
+ }
+
+ private void StoreLocals(ILEmitter context, long outputs, RegisterType baseType)
+ {
+ for (int bit = 0; bit < 64; bit++)
+ {
+ long mask = 1L << bit;
+
+ if ((outputs & mask) != 0)
+ {
+ Register reg = ILEmitter.GetRegFromBit(bit, baseType);
+
+ context.Generator.EmitLdarg(TranslatedSub.StateArgIdx);
+ context.Generator.EmitLdloc(context.GetLocalIndex(reg));
+
+ context.Generator.Emit(OpCodes.Stfld, reg.GetField());
+ }
+ }
+ }
+
+ private void EmitStloc(ILEmitter context, int index, RegisterType registerType)
+ {
+ Register reg = new Register(index, registerType);
+
+ if (registerType == RegisterType.Int &&
+ RegisterSize == RegisterSize.Int32)
+ {
+ context.Generator.Emit(OpCodes.Conv_U8);
+ }
+
+ context.Generator.EmitStloc(context.GetLocalIndex(reg));
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translation/AIoType.cs b/ChocolArm64/Translation/IoType.cs
index 94f89081..290b159f 100644
--- a/ChocolArm64/Translation/AIoType.cs
+++ b/ChocolArm64/Translation/IoType.cs
@@ -3,7 +3,7 @@ using System;
namespace ChocolArm64.Translation
{
[Flags]
- enum AIoType
+ enum IoType
{
Arg,
Fields,
diff --git a/ChocolArm64/Translation/LocalAlloc.cs b/ChocolArm64/Translation/LocalAlloc.cs
new file mode 100644
index 00000000..8237bd54
--- /dev/null
+++ b/ChocolArm64/Translation/LocalAlloc.cs
@@ -0,0 +1,229 @@
+using System.Collections.Generic;
+
+namespace ChocolArm64.Translation
+{
+ class LocalAlloc
+ {
+ private class PathIo
+ {
+ private Dictionary<ILBlock, long> _allInputs;
+ private Dictionary<ILBlock, long> _cmnOutputs;
+
+ private long _allOutputs;
+
+ public PathIo()
+ {
+ _allInputs = new Dictionary<ILBlock, long>();
+ _cmnOutputs = new Dictionary<ILBlock, long>();
+ }
+
+ public PathIo(ILBlock root, long inputs, long outputs) : this()
+ {
+ Set(root, inputs, outputs);
+ }
+
+ public void Set(ILBlock root, long inputs, long outputs)
+ {
+ if (!_allInputs.TryAdd(root, inputs))
+ {
+ _allInputs[root] |= inputs;
+ }
+
+ if (!_cmnOutputs.TryAdd(root, outputs))
+ {
+ _cmnOutputs[root] &= outputs;
+ }
+
+ _allOutputs |= outputs;
+ }
+
+ public long GetInputs(ILBlock root)
+ {
+ if (_allInputs.TryGetValue(root, out long inputs))
+ {
+ return inputs | (_allOutputs & ~_cmnOutputs[root]);
+ }
+
+ return 0;
+ }
+
+ public long GetOutputs()
+ {
+ return _allOutputs;
+ }
+ }
+
+ private Dictionary<ILBlock, PathIo> _intPaths;
+ private Dictionary<ILBlock, PathIo> _vecPaths;
+
+ private struct BlockIo
+ {
+ public ILBlock Block;
+ public ILBlock Entry;
+
+ public long IntInputs;
+ public long VecInputs;
+ public long IntOutputs;
+ public long VecOutputs;
+ }
+
+ private const int MaxOptGraphLength = 40;
+
+ public LocalAlloc(ILBlock[] graph, ILBlock root)
+ {
+ _intPaths = new Dictionary<ILBlock, PathIo>();
+ _vecPaths = new Dictionary<ILBlock, PathIo>();
+
+ if (graph.Length > 1 &&
+ graph.Length < MaxOptGraphLength)
+ {
+ InitializeOptimal(graph, root);
+ }
+ else
+ {
+ InitializeFast(graph);
+ }
+ }
+
+ private void InitializeOptimal(ILBlock[] graph, ILBlock root)
+ {
+ //This will go through all possible paths on the graph,
+ //and store all inputs/outputs for each block. A register
+ //that was previously written to already is not considered an input.
+ //When a block can be reached by more than one path, then the
+ //output from all paths needs to be set for this block, and
+ //only outputs present in all of the parent blocks can be considered
+ //when doing input elimination. Each block chain have a root, that's where
+ //the code starts executing. They are present on the subroutine start point,
+ //and on call return points too (address written to X30 by BL).
+ HashSet<BlockIo> visited = new HashSet<BlockIo>();
+
+ Queue<BlockIo> unvisited = new Queue<BlockIo>();
+
+ void Enqueue(BlockIo block)
+ {
+ if (!visited.Contains(block))
+ {
+ unvisited.Enqueue(block);
+
+ visited.Add(block);
+ }
+ }
+
+ Enqueue(new BlockIo()
+ {
+ Block = root,
+ Entry = root
+ });
+
+ while (unvisited.Count > 0)
+ {
+ BlockIo current = unvisited.Dequeue();
+
+ current.IntInputs |= current.Block.IntInputs & ~current.IntOutputs;
+ current.VecInputs |= current.Block.VecInputs & ~current.VecOutputs;
+ current.IntOutputs |= current.Block.IntOutputs;
+ current.VecOutputs |= current.Block.VecOutputs;
+
+ //Check if this is a exit block
+ //(a block that returns or calls another sub).
+ if ((current.Block.Next == null &&
+ current.Block.Branch == null) || current.Block.HasStateStore)
+ {
+ if (!_intPaths.TryGetValue(current.Block, out PathIo intPath))
+ {
+ _intPaths.Add(current.Block, intPath = new PathIo());
+ }
+
+ if (!_vecPaths.TryGetValue(current.Block, out PathIo vecPath))
+ {
+ _vecPaths.Add(current.Block, vecPath = new PathIo());
+ }
+
+ intPath.Set(current.Entry, current.IntInputs, current.IntOutputs);
+ vecPath.Set(current.Entry, current.VecInputs, current.VecOutputs);
+ }
+
+ void EnqueueFromCurrent(ILBlock block, bool retTarget)
+ {
+ BlockIo blkIO = new BlockIo() { Block = block };
+
+ if (retTarget)
+ {
+ blkIO.Entry = block;
+ }
+ else
+ {
+ blkIO.Entry = current.Entry;
+ blkIO.IntInputs = current.IntInputs;
+ blkIO.VecInputs = current.VecInputs;
+ blkIO.IntOutputs = current.IntOutputs;
+ blkIO.VecOutputs = current.VecOutputs;
+ }
+
+ Enqueue(blkIO);
+ }
+
+ if (current.Block.Next != null)
+ {
+ EnqueueFromCurrent(current.Block.Next, current.Block.HasStateStore);
+ }
+
+ if (current.Block.Branch != null)
+ {
+ EnqueueFromCurrent(current.Block.Branch, false);
+ }
+ }
+ }
+
+ private void InitializeFast(ILBlock[] graph)
+ {
+ //This is WAY faster than InitializeOptimal, but results in
+ //uneeded loads and stores, so the resulting code will be slower.
+ long intInputs = 0, intOutputs = 0;
+ long vecInputs = 0, vecOutputs = 0;
+
+ foreach (ILBlock block in graph)
+ {
+ intInputs |= block.IntInputs;
+ intOutputs |= block.IntOutputs;
+ vecInputs |= block.VecInputs;
+ vecOutputs |= block.VecOutputs;
+ }
+
+ //It's possible that not all code paths writes to those output registers,
+ //in those cases if we attempt to write an output registers that was
+ //not written, we will be just writing zero and messing up the old register value.
+ //So we just need to ensure that all outputs are loaded.
+ if (graph.Length > 1)
+ {
+ intInputs |= intOutputs;
+ vecInputs |= vecOutputs;
+ }
+
+ foreach (ILBlock block in graph)
+ {
+ _intPaths.Add(block, new PathIo(block, intInputs, intOutputs));
+ _vecPaths.Add(block, new PathIo(block, vecInputs, vecOutputs));
+ }
+ }
+
+ public long GetIntInputs(ILBlock root) => GetInputsImpl(root, _intPaths.Values);
+ public long GetVecInputs(ILBlock root) => GetInputsImpl(root, _vecPaths.Values);
+
+ private long GetInputsImpl(ILBlock root, IEnumerable<PathIo> values)
+ {
+ long inputs = 0;
+
+ foreach (PathIo path in values)
+ {
+ inputs |= path.GetInputs(root);
+ }
+
+ return inputs;
+ }
+
+ public long GetIntOutputs(ILBlock block) => _intPaths[block].GetOutputs();
+ public long GetVecOutputs(ILBlock block) => _vecPaths[block].GetOutputs();
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Translator.cs b/ChocolArm64/Translator.cs
new file mode 100644
index 00000000..3bf06dc4
--- /dev/null
+++ b/ChocolArm64/Translator.cs
@@ -0,0 +1,165 @@
+using ChocolArm64.Decoders;
+using ChocolArm64.Events;
+using ChocolArm64.Memory;
+using ChocolArm64.State;
+using ChocolArm64.Translation;
+using System;
+using System.Reflection.Emit;
+
+namespace ChocolArm64
+{
+ public class Translator
+ {
+ private TranslatorCache _cache;
+
+ public event EventHandler<CpuTraceEventArgs> CpuTrace;
+
+ public bool EnableCpuTrace { get; set; }
+
+ public Translator()
+ {
+ _cache = new TranslatorCache();
+ }
+
+ internal void ExecuteSubroutine(CpuThread thread, long position)
+ {
+ //TODO: Both the execute A32/A64 methods should be merged on the future,
+ //when both ISAs are implemented with the interpreter and JIT.
+ //As of now, A32 only has a interpreter and A64 a JIT.
+ CpuThreadState state = thread.ThreadState;
+ MemoryManager memory = thread.Memory;
+
+ if (state.ExecutionMode == ExecutionMode.AArch32)
+ {
+ ExecuteSubroutineA32(state, memory);
+ }
+ else
+ {
+ ExecuteSubroutineA64(state, memory, position);
+ }
+ }
+
+ private void ExecuteSubroutineA32(CpuThreadState state, MemoryManager memory)
+ {
+ do
+ {
+ OpCode64 opCode = Decoder.DecodeOpCode(state, memory, state.R15);
+
+ opCode.Interpreter(state, memory, opCode);
+ }
+ while (state.R15 != 0 && state.Running);
+ }
+
+ private void ExecuteSubroutineA64(CpuThreadState state, MemoryManager memory, long position)
+ {
+ do
+ {
+ if (EnableCpuTrace)
+ {
+ CpuTrace?.Invoke(this, new CpuTraceEventArgs(position));
+ }
+
+ if (!_cache.TryGetSubroutine(position, out TranslatedSub sub))
+ {
+ sub = TranslateTier0(state, memory, position);
+ }
+
+ if (sub.ShouldReJit())
+ {
+ TranslateTier1(state, memory, position);
+ }
+
+ position = sub.Execute(state, memory);
+ }
+ while (position != 0 && state.Running);
+ }
+
+ internal bool HasCachedSub(long position)
+ {
+ return _cache.HasSubroutine(position);
+ }
+
+ private TranslatedSub TranslateTier0(CpuThreadState state, MemoryManager memory, long position)
+ {
+ Block block = Decoder.DecodeBasicBlock(state, memory, position);
+
+ Block[] graph = new Block[] { block };
+
+ string subName = GetSubroutineName(position);
+
+ ILEmitterCtx context = new ILEmitterCtx(_cache, graph, block, subName);
+
+ do
+ {
+ context.EmitOpCode();
+ }
+ while (context.AdvanceOpCode());
+
+ TranslatedSub subroutine = context.GetSubroutine();
+
+ subroutine.SetType(TranslatedSubType.SubTier0);
+
+ _cache.AddOrUpdate(position, subroutine, block.OpCodes.Count);
+
+ OpCode64 lastOp = block.GetLastOp();
+
+ return subroutine;
+ }
+
+ private void TranslateTier1(CpuThreadState state, MemoryManager memory, long position)
+ {
+ (Block[] graph, Block root) = Decoder.DecodeSubroutine(_cache, state, memory, position);
+
+ string subName = GetSubroutineName(position);
+
+ ILEmitterCtx context = new ILEmitterCtx(_cache, graph, root, subName);
+
+ if (context.CurrBlock.Position != position)
+ {
+ context.Emit(OpCodes.Br, context.GetLabel(position));
+ }
+
+ do
+ {
+ context.EmitOpCode();
+ }
+ while (context.AdvanceOpCode());
+
+ //Mark all methods that calls this method for ReJiting,
+ //since we can now call it directly which is faster.
+ if (_cache.TryGetSubroutine(position, out TranslatedSub oldSub))
+ {
+ foreach (long callerPos in oldSub.GetCallerPositions())
+ {
+ if (_cache.TryGetSubroutine(position, out TranslatedSub callerSub))
+ {
+ callerSub.MarkForReJit();
+ }
+ }
+ }
+
+ TranslatedSub subroutine = context.GetSubroutine();
+
+ subroutine.SetType(TranslatedSubType.SubTier1);
+
+ _cache.AddOrUpdate(position, subroutine, GetGraphInstCount(graph));
+ }
+
+ private string GetSubroutineName(long position)
+ {
+ return $"Sub{position:x16}";
+ }
+
+ private int GetGraphInstCount(Block[] graph)
+ {
+ int size = 0;
+
+ foreach (Block block in graph)
+ {
+ size += block.OpCodes.Count;
+ }
+
+ return size;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/TranslatorCache.cs b/ChocolArm64/TranslatorCache.cs
new file mode 100644
index 00000000..7d650357
--- /dev/null
+++ b/ChocolArm64/TranslatorCache.cs
@@ -0,0 +1,165 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+namespace ChocolArm64
+{
+ class TranslatorCache
+ {
+ //Maximum size of the cache, in bytes, measured in ARM code size.
+ private const int MaxTotalSize = 4 * 1024 * 256;
+
+ //Minimum time required in milliseconds for a method to be eligible for deletion.
+ private const int MinTimeDelta = 2 * 60000;
+
+ //Minimum number of calls required to update the timestamp.
+ private const int MinCallCountForUpdate = 250;
+
+ private class CacheBucket
+ {
+ public TranslatedSub Subroutine { get; private set; }
+
+ public LinkedListNode<long> Node { get; private set; }
+
+ public int CallCount { get; set; }
+
+ public int Size { get; private set; }
+
+ public long Timestamp { get; private set; }
+
+ public CacheBucket(TranslatedSub subroutine, LinkedListNode<long> node, int size)
+ {
+ Subroutine = subroutine;
+ Size = size;
+
+ UpdateNode(node);
+ }
+
+ public void UpdateNode(LinkedListNode<long> node)
+ {
+ Node = node;
+
+ Timestamp = GetTimestamp();
+ }
+ }
+
+ private ConcurrentDictionary<long, CacheBucket> _cache;
+
+ private LinkedList<long> _sortedCache;
+
+ private int _totalSize;
+
+ public TranslatorCache()
+ {
+ _cache = new ConcurrentDictionary<long, CacheBucket>();
+
+ _sortedCache = new LinkedList<long>();
+ }
+
+ public void AddOrUpdate(long position, TranslatedSub subroutine, int size)
+ {
+ ClearCacheIfNeeded();
+
+ _totalSize += size;
+
+ lock (_sortedCache)
+ {
+ LinkedListNode<long> node = _sortedCache.AddLast(position);
+
+ CacheBucket newBucket = new CacheBucket(subroutine, node, size);
+
+ _cache.AddOrUpdate(position, newBucket, (key, bucket) =>
+ {
+ _totalSize -= bucket.Size;
+
+ _sortedCache.Remove(bucket.Node);
+
+ return newBucket;
+ });
+ }
+ }
+
+ public bool HasSubroutine(long position)
+ {
+ return _cache.ContainsKey(position);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool TryGetSubroutine(long position, out TranslatedSub subroutine)
+ {
+ if (_cache.TryGetValue(position, out CacheBucket bucket))
+ {
+ if (bucket.CallCount++ > MinCallCountForUpdate)
+ {
+ if (Monitor.TryEnter(_sortedCache))
+ {
+ try
+ {
+ bucket.CallCount = 0;
+
+ _sortedCache.Remove(bucket.Node);
+
+ bucket.UpdateNode(_sortedCache.AddLast(position));
+ }
+ finally
+ {
+ Monitor.Exit(_sortedCache);
+ }
+ }
+ }
+
+ subroutine = bucket.Subroutine;
+
+ return true;
+ }
+
+ subroutine = default(TranslatedSub);
+
+ return false;
+ }
+
+ private void ClearCacheIfNeeded()
+ {
+ long timestamp = GetTimestamp();
+
+ while (_totalSize > MaxTotalSize)
+ {
+ lock (_sortedCache)
+ {
+ LinkedListNode<long> node = _sortedCache.First;
+
+ if (node == null)
+ {
+ break;
+ }
+
+ CacheBucket bucket = _cache[node.Value];
+
+ long timeDelta = timestamp - bucket.Timestamp;
+
+ if (timeDelta <= MinTimeDelta)
+ {
+ break;
+ }
+
+ if (_cache.TryRemove(node.Value, out bucket))
+ {
+ _totalSize -= bucket.Size;
+
+ _sortedCache.Remove(bucket.Node);
+ }
+ }
+ }
+ }
+
+ private static long GetTimestamp()
+ {
+ long timestamp = Stopwatch.GetTimestamp();
+
+ return timestamp / (Stopwatch.Frequency / 1000);
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Memory/NvGpuVmm.cs b/Ryujinx.Graphics/Memory/NvGpuVmm.cs
index 0082fb27..ec660bf0 100644
--- a/Ryujinx.Graphics/Memory/NvGpuVmm.cs
+++ b/Ryujinx.Graphics/Memory/NvGpuVmm.cs
@@ -4,7 +4,7 @@ using System;
namespace Ryujinx.Graphics.Memory
{
- public class NvGpuVmm : IAMemory, IGalMemory
+ public class NvGpuVmm : IMemory, IGalMemory
{
public const long AddrSize = 1L << 40;
@@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Memory
private const int PTLvl0Bit = PTPageBits + PTLvl1Bits;
private const int PTLvl1Bit = PTPageBits;
- public AMemory 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(AMemory Memory)
+ public NvGpuVmm(MemoryManager Memory)
{
this.Memory = Memory;
diff --git a/Ryujinx.Graphics/Memory/NvGpuVmmCache.cs b/Ryujinx.Graphics/Memory/NvGpuVmmCache.cs
index f1c16a36..57e25a2f 100644
--- a/Ryujinx.Graphics/Memory/NvGpuVmmCache.cs
+++ b/Ryujinx.Graphics/Memory/NvGpuVmmCache.cs
@@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Memory
CachedRanges = new ValueRangeSet<int>();
}
- public bool IsRegionModified(AMemory Memory, NvGpuBufferType BufferType, long PA, long Size)
+ public bool IsRegionModified(MemoryManager Memory, NvGpuBufferType BufferType, long PA, long Size)
{
(bool[] Modified, long ModifiedCount) = Memory.IsRegionModified(PA, Size);
diff --git a/Ryujinx.Graphics/Texture/ImageUtils.cs b/Ryujinx.Graphics/Texture/ImageUtils.cs
index d2172c2e..97da17a0 100644
--- a/Ryujinx.Graphics/Texture/ImageUtils.cs
+++ b/Ryujinx.Graphics/Texture/ImageUtils.cs
@@ -216,9 +216,9 @@ namespace Ryujinx.Graphics.Texture
throw new NotImplementedException(Format.ToString());
}
- public static byte[] ReadTexture(IAMemory Memory, GalImage Image, long Position)
+ public static byte[] ReadTexture(IMemory Memory, GalImage Image, long Position)
{
- AMemory CpuMemory;
+ MemoryManager CpuMemory;
if (Memory is NvGpuVmm Vmm)
{
@@ -226,7 +226,7 @@ namespace Ryujinx.Graphics.Texture
}
else
{
- CpuMemory = (AMemory)Memory;
+ CpuMemory = (MemoryManager)Memory;
}
ISwizzle Swizzle = TextureHelper.GetSwizzle(Image);
diff --git a/Ryujinx.Graphics/Texture/TextureHelper.cs b/Ryujinx.Graphics/Texture/TextureHelper.cs
index 9e966e6b..6ac91d8b 100644
--- a/Ryujinx.Graphics/Texture/TextureHelper.cs
+++ b/Ryujinx.Graphics/Texture/TextureHelper.cs
@@ -27,16 +27,16 @@ namespace Ryujinx.Graphics.Texture
}
}
- public static (AMemory Memory, long Position) GetMemoryAndPosition(
- IAMemory Memory,
- long Position)
+ public static (MemoryManager Memory, long Position) GetMemoryAndPosition(
+ IMemory Memory,
+ long Position)
{
if (Memory is NvGpuVmm Vmm)
{
return (Vmm.Memory, Vmm.GetPhysicalAddress(Position));
}
- return ((AMemory)Memory, Position);
+ return ((MemoryManager)Memory, Position);
}
}
}
diff --git a/Ryujinx.HLE/HOS/Homebrew.cs b/Ryujinx.HLE/HOS/Homebrew.cs
index 1f862a4a..ffb22c7f 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(AMemory 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(
- AMemory 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(AMemory Memory, long Position)
+ public static string ReadHbAbiNextLoadPath(MemoryManager Memory, long Position)
{
string FileName = null;
@@ -59,7 +59,7 @@ namespace Ryujinx.HLE.HOS
long Value0 = Memory.ReadInt64(Position + 0x08);
long Value1 = Memory.ReadInt64(Position + 0x10);
- FileName = AMemoryHelper.ReadAsciiString(Memory, Value0, Value1 - Value0);
+ FileName = MemoryHelper.ReadAsciiString(Memory, Value0, Value1 - Value0);
break;
}
diff --git a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs
index fca995c0..ec27a6ea 100644
--- a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs
+++ b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs
@@ -8,12 +8,12 @@ namespace Ryujinx.HLE.HOS.Ipc
static class IpcHandler
{
public static long IpcCall(
- Switch Ns,
- Process Process,
- AMemory Memory,
- KSession Session,
- IpcMessage Request,
- long CmdPtr)
+ Switch Ns,
+ Process Process,
+ MemoryManager Memory,
+ KSession Session,
+ IpcMessage Request,
+ long CmdPtr)
{
IpcMessage Response = new IpcMessage();
diff --git a/Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs b/Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs
index 73309e1e..4a0f955f 100644
--- a/Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs
+++ b/Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs
@@ -24,11 +24,11 @@ namespace Ryujinx.HLE.HOS.Kernel
}
public long ArbitrateLock(
- Process Process,
- AMemory Memory,
- int OwnerHandle,
- long MutexAddress,
- int RequesterHandle)
+ Process Process,
+ MemoryManager Memory,
+ int OwnerHandle,
+ long MutexAddress,
+ int RequesterHandle)
{
System.CriticalSectionLock.Lock();
@@ -80,7 +80,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return (uint)CurrentThread.ObjSyncResult;
}
- public long ArbitrateUnlock(AMemory Memory, long MutexAddress)
+ public long ArbitrateUnlock(MemoryManager Memory, long MutexAddress)
{
System.CriticalSectionLock.Lock();
@@ -100,11 +100,11 @@ namespace Ryujinx.HLE.HOS.Kernel
}
public long WaitProcessWideKeyAtomic(
- AMemory Memory,
- long MutexAddress,
- long CondVarAddress,
- int ThreadHandle,
- long Timeout)
+ MemoryManager Memory,
+ long MutexAddress,
+ long CondVarAddress,
+ int ThreadHandle,
+ long Timeout)
{
System.CriticalSectionLock.Lock();
@@ -167,7 +167,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return (uint)CurrentThread.ObjSyncResult;
}
- private (long, KThread) MutexUnlock(AMemory Memory, KThread CurrentThread, long MutexAddress)
+ private (long, KThread) MutexUnlock(MemoryManager Memory, KThread CurrentThread, long MutexAddress)
{
KThread NewOwnerThread = CurrentThread.RelinquishMutex(MutexAddress, out int Count);
@@ -198,7 +198,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return (Result, NewOwnerThread);
}
- public void SignalProcessWideKey(Process Process, AMemory Memory, long Address, int Count)
+ public void SignalProcessWideKey(Process Process, MemoryManager Memory, long Address, int Count)
{
Queue<KThread> SignaledThreads = new Queue<KThread>();
@@ -227,7 +227,7 @@ namespace Ryujinx.HLE.HOS.Kernel
System.CriticalSectionLock.Unlock();
}
- private KThread TryAcquireMutex(Process Process, AMemory Memory, KThread Requester)
+ private KThread TryAcquireMutex(Process Process, MemoryManager Memory, KThread Requester)
{
long Address = Requester.MutexAddress;
@@ -301,7 +301,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return MutexOwner;
}
- public long WaitForAddressIfEqual(AMemory Memory, long Address, int Value, long Timeout)
+ public long WaitForAddressIfEqual(MemoryManager Memory, long Address, int Value, long Timeout)
{
KThread CurrentThread = System.Scheduler.GetCurrentThread();
@@ -373,11 +373,11 @@ namespace Ryujinx.HLE.HOS.Kernel
}
public long WaitForAddressIfLessThan(
- AMemory Memory,
- long Address,
- int Value,
- bool ShouldDecrement,
- long Timeout)
+ MemoryManager Memory,
+ long Address,
+ int Value,
+ bool ShouldDecrement,
+ long Timeout)
{
KThread CurrentThread = System.Scheduler.GetCurrentThread();
@@ -507,7 +507,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return 0;
}
- public long SignalAndIncrementIfEqual(AMemory Memory, long Address, int Value, int Count)
+ public long SignalAndIncrementIfEqual(MemoryManager Memory, long Address, int Value, int Count)
{
System.CriticalSectionLock.Lock();
@@ -552,7 +552,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return 0;
}
- public long SignalAndModifyIfEqual(AMemory Memory, long Address, int Value, int Count)
+ public long SignalAndModifyIfEqual(MemoryManager Memory, long Address, int Value, int Count)
{
System.CriticalSectionLock.Lock();
@@ -649,7 +649,7 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
- private bool UserToKernelInt32(AMemory Memory, long Address, out int Value)
+ private bool UserToKernelInt32(MemoryManager Memory, long Address, out int Value)
{
if (Memory.IsMapped(Address))
{
@@ -663,7 +663,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return false;
}
- private bool KernelToUserInt32(AMemory Memory, long Address, int Value)
+ private bool KernelToUserInt32(MemoryManager Memory, long Address, int Value)
{
if (Memory.IsMapped(Address))
{
diff --git a/Ryujinx.HLE/HOS/Kernel/KMemoryManager.cs b/Ryujinx.HLE/HOS/Kernel/KMemoryManager.cs
index 8cf73785..4cfb2aa2 100644
--- a/Ryujinx.HLE/HOS/Kernel/KMemoryManager.cs
+++ b/Ryujinx.HLE/HOS/Kernel/KMemoryManager.cs
@@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Kernel
private LinkedList<KMemoryBlock> Blocks;
- private AMemory CpuMemory;
+ private MemoryManager CpuMemory;
private ArenaAllocator Allocator;
diff --git a/Ryujinx.HLE/HOS/Kernel/KRecursiveLock.cs b/Ryujinx.HLE/HOS/Kernel/KRecursiveLock.cs
index a21531de..30c1a880 100644
--- a/Ryujinx.HLE/HOS/Kernel/KRecursiveLock.cs
+++ b/Ryujinx.HLE/HOS/Kernel/KRecursiveLock.cs
@@ -53,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Kernel
if (CoreContext.ContextSwitchNeeded)
{
- AThread CurrentHleThread = CoreContext.CurrentThread?.Context;
+ CpuThread CurrentHleThread = CoreContext.CurrentThread?.Context;
if (CurrentHleThread == null)
{
diff --git a/Ryujinx.HLE/HOS/Kernel/KThread.cs b/Ryujinx.HLE/HOS/Kernel/KThread.cs
index 74ad28f3..73ee2322 100644
--- a/Ryujinx.HLE/HOS/Kernel/KThread.cs
+++ b/Ryujinx.HLE/HOS/Kernel/KThread.cs
@@ -9,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KThread : KSynchronizationObject, IKFutureSchedulerObject
{
- public AThread Context { get; private set; }
+ public CpuThread Context { get; private set; }
public long AffinityMask { get; set; }
@@ -66,12 +66,12 @@ namespace Ryujinx.HLE.HOS.Kernel
public long LastPc { get; set; }
public KThread(
- AThread Thread,
- Process Process,
- Horizon System,
- int ProcessorId,
- int Priority,
- int ThreadId) : base(System)
+ CpuThread Thread,
+ Process Process,
+ Horizon System,
+ int ProcessorId,
+ int Priority,
+ int ThreadId) : base(System)
{
this.ThreadId = ThreadId;
diff --git a/Ryujinx.HLE/HOS/Kernel/SvcHandler.cs b/Ryujinx.HLE/HOS/Kernel/SvcHandler.cs
index d098aab0..9b475d4e 100644
--- a/Ryujinx.HLE/HOS/Kernel/SvcHandler.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SvcHandler.cs
@@ -10,14 +10,14 @@ namespace Ryujinx.HLE.HOS.Kernel
{
partial class SvcHandler
{
- private delegate void SvcFunc(AThreadState ThreadState);
+ private delegate void SvcFunc(CpuThreadState ThreadState);
private Dictionary<int, SvcFunc> SvcFuncs;
- private Switch Device;
- private Process Process;
- private Horizon System;
- private AMemory Memory;
+ private Switch Device;
+ private Process Process;
+ private Horizon System;
+ private MemoryManager Memory;
private struct HleIpcMessage
{
@@ -101,9 +101,9 @@ namespace Ryujinx.HLE.HOS.Kernel
Rng = new Random();
}
- public void SvcCall(object sender, AInstExceptionEventArgs e)
+ public void SvcCall(object sender, InstExceptionEventArgs e)
{
- AThreadState ThreadState = (AThreadState)sender;
+ CpuThreadState ThreadState = (CpuThreadState)sender;
Process.GetThread(ThreadState.Tpidr).LastPc = e.Position;
diff --git a/Ryujinx.HLE/HOS/Kernel/SvcMemory.cs b/Ryujinx.HLE/HOS/Kernel/SvcMemory.cs
index 07bc474b..560ad4b3 100644
--- a/Ryujinx.HLE/HOS/Kernel/SvcMemory.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SvcMemory.cs
@@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Kernel
{
partial class SvcHandler
{
- private void SvcSetHeapSize(AThreadState ThreadState)
+ private void SvcSetHeapSize(CpuThreadState ThreadState)
{
ulong Size = ThreadState.X1;
@@ -34,7 +34,7 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
- private void SvcSetMemoryAttribute(AThreadState ThreadState)
+ private void SvcSetMemoryAttribute(CpuThreadState ThreadState)
{
long Position = (long)ThreadState.X0;
long Size = (long)ThreadState.X1;
@@ -90,7 +90,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = (ulong)Result;
}
- private void SvcMapMemory(AThreadState ThreadState)
+ private void SvcMapMemory(CpuThreadState ThreadState)
{
long Dst = (long)ThreadState.X0;
long Src = (long)ThreadState.X1;
@@ -151,7 +151,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = (ulong)Result;
}
- private void SvcUnmapMemory(AThreadState ThreadState)
+ private void SvcUnmapMemory(CpuThreadState ThreadState)
{
long Dst = (long)ThreadState.X0;
long Src = (long)ThreadState.X1;
@@ -212,7 +212,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = (ulong)Result;
}
- private void SvcQueryMemory(AThreadState ThreadState)
+ private void SvcQueryMemory(CpuThreadState ThreadState)
{
long InfoPtr = (long)ThreadState.X0;
long Position = (long)ThreadState.X2;
@@ -232,7 +232,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X1 = 0;
}
- private void SvcMapSharedMemory(AThreadState ThreadState)
+ private void SvcMapSharedMemory(CpuThreadState ThreadState)
{
int Handle = (int)ThreadState.X0;
long Position = (long)ThreadState.X1;
@@ -315,7 +315,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = (ulong)Result;
}
- private void SvcUnmapSharedMemory(AThreadState ThreadState)
+ private void SvcUnmapSharedMemory(CpuThreadState ThreadState)
{
int Handle = (int)ThreadState.X0;
long Position = (long)ThreadState.X1;
@@ -378,7 +378,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = (ulong)Result;
}
- private void SvcCreateTransferMemory(AThreadState ThreadState)
+ private void SvcCreateTransferMemory(CpuThreadState ThreadState)
{
long Position = (long)ThreadState.X1;
long Size = (long)ThreadState.X2;
@@ -431,7 +431,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X1 = (ulong)Handle;
}
- private void SvcMapPhysicalMemory(AThreadState ThreadState)
+ private void SvcMapPhysicalMemory(CpuThreadState ThreadState)
{
long Position = (long)ThreadState.X0;
long Size = (long)ThreadState.X1;
@@ -482,7 +482,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = (ulong)Result;
}
- private void SvcUnmapPhysicalMemory(AThreadState ThreadState)
+ private void SvcUnmapPhysicalMemory(CpuThreadState ThreadState)
{
long Position = (long)ThreadState.X0;
long Size = (long)ThreadState.X1;
diff --git a/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs b/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
index 6eb8419c..54aef5d7 100644
--- a/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
@@ -17,12 +17,12 @@ namespace Ryujinx.HLE.HOS.Kernel
private const bool EnableProcessDebugging = false;
- private void SvcExitProcess(AThreadState ThreadState)
+ private void SvcExitProcess(CpuThreadState ThreadState)
{
Device.System.ExitProcess(Process.ProcessId);
}
- private void SignalEvent64(AThreadState ThreadState)
+ private void SignalEvent64(CpuThreadState ThreadState)
{
ThreadState.X0 = (ulong)SignalEvent((int)ThreadState.X0);
}
@@ -52,7 +52,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return Result;
}
- private void ClearEvent64(AThreadState ThreadState)
+ private void ClearEvent64(CpuThreadState ThreadState)
{
ThreadState.X0 = (ulong)ClearEvent((int)ThreadState.X0);
}
@@ -82,7 +82,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return Result;
}
- private void SvcCloseHandle(AThreadState ThreadState)
+ private void SvcCloseHandle(CpuThreadState ThreadState)
{
int Handle = (int)ThreadState.X0;
@@ -113,7 +113,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = 0;
}
- private void ResetSignal64(AThreadState ThreadState)
+ private void ResetSignal64(CpuThreadState ThreadState)
{
ThreadState.X0 = (ulong)ResetSignal((int)ThreadState.X0);
}
@@ -146,17 +146,17 @@ namespace Ryujinx.HLE.HOS.Kernel
return Result;
}
- private void SvcGetSystemTick(AThreadState ThreadState)
+ private void SvcGetSystemTick(CpuThreadState ThreadState)
{
ThreadState.X0 = ThreadState.CntpctEl0;
}
- private void SvcConnectToNamedPort(AThreadState ThreadState)
+ private void SvcConnectToNamedPort(CpuThreadState ThreadState)
{
long StackPtr = (long)ThreadState.X0;
long NamePtr = (long)ThreadState.X1;
- string Name = AMemoryHelper.ReadAsciiString(Memory, NamePtr, 8);
+ string Name = MemoryHelper.ReadAsciiString(Memory, NamePtr, 8);
//TODO: Validate that app has perms to access the service, and that the service
//actually exists, return error codes otherwise.
@@ -171,12 +171,12 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X1 = (uint)Handle;
}
- private void SvcSendSyncRequest(AThreadState ThreadState)
+ private void SvcSendSyncRequest(CpuThreadState ThreadState)
{
SendSyncRequest(ThreadState, ThreadState.Tpidr, 0x100, (int)ThreadState.X0);
}
- private void SvcSendSyncRequestWithUserBuffer(AThreadState ThreadState)
+ private void SvcSendSyncRequestWithUserBuffer(CpuThreadState ThreadState)
{
SendSyncRequest(
ThreadState,
@@ -185,7 +185,7 @@ namespace Ryujinx.HLE.HOS.Kernel
(int)ThreadState.X2);
}
- private void SendSyncRequest(AThreadState ThreadState, long MessagePtr, long Size, int Handle)
+ private void SendSyncRequest(CpuThreadState ThreadState, long MessagePtr, long Size, int Handle)
{
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
@@ -241,7 +241,7 @@ namespace Ryujinx.HLE.HOS.Kernel
IpcMessage.Thread.Reschedule(ThreadSchedState.Running);
}
- private void SvcBreak(AThreadState ThreadState)
+ private void SvcBreak(CpuThreadState ThreadState)
{
long Reason = (long)ThreadState.X0;
long Unknown = (long)ThreadState.X1;
@@ -260,19 +260,19 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
- private void SvcOutputDebugString(AThreadState ThreadState)
+ private void SvcOutputDebugString(CpuThreadState ThreadState)
{
long Position = (long)ThreadState.X0;
long Size = (long)ThreadState.X1;
- string Str = AMemoryHelper.ReadAsciiString(Memory, Position, Size);
+ string Str = MemoryHelper.ReadAsciiString(Memory, Position, Size);
Logger.PrintWarning(LogClass.KernelSvc, Str);
ThreadState.X0 = 0;
}
- private void SvcGetInfo(AThreadState ThreadState)
+ private void SvcGetInfo(CpuThreadState ThreadState)
{
long StackPtr = (long)ThreadState.X0;
int InfoType = (int)ThreadState.X1;
@@ -366,7 +366,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = 0;
}
- private void CreateEvent64(AThreadState State)
+ private void CreateEvent64(CpuThreadState State)
{
KernelResult Result = CreateEvent(out int WEventHandle, out int REventHandle);
diff --git a/Ryujinx.HLE/HOS/Kernel/SvcThread.cs b/Ryujinx.HLE/HOS/Kernel/SvcThread.cs
index 4c1744e6..53a557de 100644
--- a/Ryujinx.HLE/HOS/Kernel/SvcThread.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SvcThread.cs
@@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Kernel
{
partial class SvcHandler
{
- private void SvcCreateThread(AThreadState ThreadState)
+ private void SvcCreateThread(CpuThreadState ThreadState)
{
long EntryPoint = (long)ThreadState.X1;
long ArgsPtr = (long)ThreadState.X2;
@@ -49,7 +49,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X1 = (ulong)Handle;
}
- private void SvcStartThread(AThreadState ThreadState)
+ private void SvcStartThread(CpuThreadState ThreadState)
{
int Handle = (int)ThreadState.X0;
@@ -74,7 +74,7 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
- private void SvcExitThread(AThreadState ThreadState)
+ private void SvcExitThread(CpuThreadState ThreadState)
{
KThread CurrentThread = System.Scheduler.GetCurrentThread();
@@ -83,7 +83,7 @@ namespace Ryujinx.HLE.HOS.Kernel
System.Scheduler.StopThread(CurrentThread);
}
- private void SvcSleepThread(AThreadState ThreadState)
+ private void SvcSleepThread(CpuThreadState ThreadState)
{
long Timeout = (long)ThreadState.X0;
@@ -108,7 +108,7 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
- private void SvcGetThreadPriority(AThreadState ThreadState)
+ private void SvcGetThreadPriority(CpuThreadState ThreadState)
{
int Handle = (int)ThreadState.X1;
@@ -127,7 +127,7 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
- private void SvcSetThreadPriority(AThreadState ThreadState)
+ private void SvcSetThreadPriority(CpuThreadState ThreadState)
{
int Handle = (int)ThreadState.X0;
int Priority = (int)ThreadState.X1;
@@ -154,7 +154,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = 0;
}
- private void SvcGetThreadCoreMask(AThreadState ThreadState)
+ private void SvcGetThreadCoreMask(CpuThreadState ThreadState)
{
int Handle = (int)ThreadState.X2;
@@ -176,7 +176,7 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
- private void SvcSetThreadCoreMask(AThreadState ThreadState)
+ private void SvcSetThreadCoreMask(CpuThreadState ThreadState)
{
int Handle = (int)ThreadState.X0;
int PrefferedCore = (int)ThreadState.X1;
@@ -240,12 +240,12 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = (ulong)Result;
}
- private void SvcGetCurrentProcessorNumber(AThreadState ThreadState)
+ private void SvcGetCurrentProcessorNumber(CpuThreadState ThreadState)
{
ThreadState.X0 = (ulong)Process.GetThread(ThreadState.Tpidr).CurrentCore;
}
- private void SvcGetThreadId(AThreadState ThreadState)
+ private void SvcGetThreadId(CpuThreadState ThreadState)
{
int Handle = (int)ThreadState.X1;
@@ -264,7 +264,7 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
- private void SvcSetThreadActivity(AThreadState ThreadState)
+ private void SvcSetThreadActivity(CpuThreadState ThreadState)
{
int Handle = (int)ThreadState.X0;
bool Pause = (int)ThreadState.X1 == 1;
@@ -299,7 +299,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = (ulong)Result;
}
- private void SvcGetThreadContext3(AThreadState ThreadState)
+ private void SvcGetThreadContext3(CpuThreadState ThreadState)
{
long Position = (long)ThreadState.X0;
int Handle = (int)ThreadState.X1;
diff --git a/Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs b/Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs
index 73719c19..318bd290 100644
--- a/Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs
@@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Kernel
{
partial class SvcHandler
{
- private void SvcWaitSynchronization(AThreadState ThreadState)
+ private void SvcWaitSynchronization(CpuThreadState ThreadState)
{
long HandlesPtr = (long)ThreadState.X1;
int HandlesCount = (int)ThreadState.X2;
@@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X1 = (uint)HndIndex | High;
}
- private void SvcCancelSynchronization(AThreadState ThreadState)
+ private void SvcCancelSynchronization(CpuThreadState ThreadState)
{
int ThreadHandle = (int)ThreadState.X0;
@@ -87,7 +87,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = 0;
}
- private void SvcArbitrateLock(AThreadState ThreadState)
+ private void SvcArbitrateLock(CpuThreadState ThreadState)
{
int OwnerHandle = (int)ThreadState.X0;
long MutexAddress = (long)ThreadState.X1;
@@ -131,7 +131,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = (ulong)Result;
}
- private void SvcArbitrateUnlock(AThreadState ThreadState)
+ private void SvcArbitrateUnlock(CpuThreadState ThreadState)
{
long MutexAddress = (long)ThreadState.X0;
@@ -165,7 +165,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = (ulong)Result;
}
- private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState)
+ private void SvcWaitProcessWideKeyAtomic(CpuThreadState ThreadState)
{
long MutexAddress = (long)ThreadState.X0;
long CondVarAddress = (long)ThreadState.X1;
@@ -218,7 +218,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = (ulong)Result;
}
- private void SvcSignalProcessWideKey(AThreadState ThreadState)
+ private void SvcSignalProcessWideKey(CpuThreadState ThreadState)
{
long Address = (long)ThreadState.X0;
int Count = (int)ThreadState.X1;
@@ -232,7 +232,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = 0;
}
- private void SvcWaitForAddress(AThreadState ThreadState)
+ private void SvcWaitForAddress(CpuThreadState ThreadState)
{
long Address = (long)ThreadState.X0;
ArbitrationType Type = (ArbitrationType)ThreadState.X1;
@@ -292,7 +292,7 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = (ulong)Result;
}
- private void SvcSignalToAddress(AThreadState ThreadState)
+ private void SvcSignalToAddress(CpuThreadState ThreadState)
{
long Address = (long)ThreadState.X0;
SignalType Type = (SignalType)ThreadState.X1;
diff --git a/Ryujinx.HLE/HOS/Process.cs b/Ryujinx.HLE/HOS/Process.cs
index 1d8bfeb8..93b2d68d 100644
--- a/Ryujinx.HLE/HOS/Process.cs
+++ b/Ryujinx.HLE/HOS/Process.cs
@@ -33,9 +33,9 @@ namespace Ryujinx.HLE.HOS
public int ProcessId { get; private set; }
- private ATranslator Translator;
+ private Translator Translator;
- public AMemory Memory { get; private set; }
+ public MemoryManager Memory { get; private set; }
public KMemoryManager MemoryManager { get; private set; }
@@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS
this.MetaData = MetaData;
this.ProcessId = ProcessId;
- Memory = new AMemory(Device.Memory.RamPointer);
+ Memory = new MemoryManager(Device.Memory.RamPointer);
Memory.InvalidAccess += CpuInvalidAccessHandler;
@@ -221,7 +221,7 @@ namespace Ryujinx.HLE.HOS
throw new ObjectDisposedException(nameof(Process));
}
- AThread CpuThread = new AThread(GetTranslator(), Memory, EntryPoint);
+ CpuThread CpuThread = new CpuThread(GetTranslator(), Memory, EntryPoint);
long Tpidr = GetFreeTls();
@@ -283,14 +283,14 @@ namespace Ryujinx.HLE.HOS
Device.System.Scheduler.ContextSwitch();
}
- private void BreakHandler(object sender, AInstExceptionEventArgs e)
+ private void BreakHandler(object sender, InstExceptionEventArgs e)
{
PrintStackTraceForCurrentThread();
throw new GuestBrokeExecutionException();
}
- private void UndefinedHandler(object sender, AInstUndefinedEventArgs e)
+ private void UndefinedHandler(object sender, InstUndefinedEventArgs e)
{
PrintStackTraceForCurrentThread();
@@ -307,7 +307,7 @@ namespace Ryujinx.HLE.HOS
Translator.EnableCpuTrace = false;
}
- private void CpuTraceHandler(object sender, ACpuTraceEventArgs e)
+ private void CpuTraceHandler(object sender, CpuTraceEventArgs e)
{
Executable Exe = GetExecutable(e.Position);
@@ -328,11 +328,11 @@ namespace Ryujinx.HLE.HOS
Logger.PrintDebug(LogClass.Cpu, ExeNameWithAddr + " " + SubName);
}
- private ATranslator GetTranslator()
+ private Translator GetTranslator()
{
if (Translator == null)
{
- Translator = new ATranslator();
+ Translator = new Translator();
Translator.CpuTrace += CpuTraceHandler;
}
@@ -340,7 +340,7 @@ namespace Ryujinx.HLE.HOS
return Translator;
}
- private void CpuInvalidAccessHandler(object sender, AInvalidAccessEventArgs e)
+ private void CpuInvalidAccessHandler(object sender, InvalidAccessEventArgs e)
{
PrintStackTraceForCurrentThread();
}
@@ -358,7 +358,7 @@ namespace Ryujinx.HLE.HOS
}
}
- public void PrintStackTrace(AThreadState ThreadState)
+ public void PrintStackTrace(CpuThreadState ThreadState)
{
StringBuilder Trace = new StringBuilder();
@@ -457,7 +457,7 @@ namespace Ryujinx.HLE.HOS
private void ThreadFinished(object sender, EventArgs e)
{
- if (sender is AThread Thread)
+ if (sender is CpuThread Thread)
{
if (Threads.TryRemove(Thread.ThreadState.Tpidr, out KThread KernelThread))
{
diff --git a/Ryujinx.HLE/HOS/ServiceCtx.cs b/Ryujinx.HLE/HOS/ServiceCtx.cs
index d8c9fdf6..a591673e 100644
--- a/Ryujinx.HLE/HOS/ServiceCtx.cs
+++ b/Ryujinx.HLE/HOS/ServiceCtx.cs
@@ -7,24 +7,24 @@ namespace Ryujinx.HLE.HOS
{
class ServiceCtx
{
- public Switch Device { get; private set; }
- public Process Process { get; private set; }
- public AMemory Memory { get; private set; }
- public KSession Session { get; private set; }
- public IpcMessage Request { get; private set; }
- public IpcMessage Response { get; private set; }
- public BinaryReader RequestData { get; private set; }
- public BinaryWriter ResponseData { get; private set; }
+ public Switch Device { get; private set; }
+ public Process Process { get; private set; }
+ public MemoryManager Memory { get; private set; }
+ public KSession Session { get; private set; }
+ public IpcMessage Request { get; private set; }
+ public IpcMessage Response { get; private set; }
+ public BinaryReader RequestData { get; private set; }
+ public BinaryWriter ResponseData { get; private set; }
public ServiceCtx(
- Switch Device,
- Process Process,
- AMemory Memory,
- KSession Session,
- IpcMessage Request,
- IpcMessage Response,
- BinaryReader RequestData,
- BinaryWriter ResponseData)
+ Switch Device,
+ Process Process,
+ MemoryManager Memory,
+ KSession Session,
+ IpcMessage Request,
+ IpcMessage Response,
+ BinaryReader RequestData,
+ BinaryWriter ResponseData)
{
this.Device = Device;
this.Process = Process;
diff --git a/Ryujinx.HLE/HOS/Services/Acc/IProfile.cs b/Ryujinx.HLE/HOS/Services/Acc/IProfile.cs
index 1776b37b..1d1a15cb 100644
--- a/Ryujinx.HLE/HOS/Services/Acc/IProfile.cs
+++ b/Ryujinx.HLE/HOS/Services/Acc/IProfile.cs
@@ -41,7 +41,7 @@ namespace Ryujinx.HLE.HOS.Services.Acc
long Position = Context.Request.ReceiveBuff[0].Position;
- AMemoryHelper.FillWithZeros(Context.Memory, Position, 0x80);
+ MemoryHelper.FillWithZeros(Context.Memory, Position, 0x80);
Context.Memory.WriteInt32(Position, 0);
Context.Memory.WriteInt32(Position + 4, 1);
diff --git a/Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs b/Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs
index cd3d6e49..1ad049c6 100644
--- a/Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs
+++ b/Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs
@@ -105,7 +105,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioOut
{
long Tag = Context.RequestData.ReadInt64();
- AudioOutData Data = AMemoryHelper.Read<AudioOutData>(
+ AudioOutData Data = MemoryHelper.Read<AudioOutData>(
Context.Memory,
Position);
diff --git a/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs b/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs
index 7963cbb4..aae45081 100644
--- a/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs
+++ b/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs
@@ -26,7 +26,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
private KEvent UpdateEvent;
- private AMemory Memory;
+ private MemoryManager Memory;
private IAalOutput AudioOut;
@@ -42,7 +42,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
public IAudioRenderer(
Horizon System,
- AMemory Memory,
+ MemoryManager Memory,
IAalOutput AudioOut,
AudioRendererParameter Params)
{
@@ -143,7 +143,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
long OutputPosition = Context.Request.ReceiveBuff[0].Position;
long OutputSize = Context.Request.ReceiveBuff[0].Size;
- AMemoryHelper.FillWithZeros(Context.Memory, OutputPosition, (int)OutputSize);
+ MemoryHelper.FillWithZeros(Context.Memory, OutputPosition, (int)OutputSize);
long InputPosition = Context.Request.SendBuff[0].Position;
diff --git a/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/VoiceContext.cs b/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/VoiceContext.cs
index 044b2efc..7d6e1c58 100644
--- a/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/VoiceContext.cs
+++ b/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/VoiceContext.cs
@@ -61,7 +61,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
OutStatus.VoiceDropsCount = 0;
}
- public int[] GetBufferData(AMemory Memory, int MaxSamples, out int SamplesCount)
+ public int[] GetBufferData(MemoryManager Memory, int MaxSamples, out int SamplesCount)
{
if (!Playing)
{
@@ -118,7 +118,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
return Output;
}
- private void UpdateBuffer(AMemory Memory)
+ private void UpdateBuffer(MemoryManager Memory)
{
//TODO: Implement conversion for formats other
//than interleaved stereo (2 channels).
diff --git a/Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs b/Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs
index 2bc2d820..b08f7640 100644
--- a/Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs
+++ b/Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs
@@ -96,7 +96,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud
private long OpenAudioOutImpl(ServiceCtx Context, long SendPosition, long SendSize, long ReceivePosition, long ReceiveSize)
{
- string DeviceName = AMemoryHelper.ReadAsciiString(
+ string DeviceName = MemoryHelper.ReadAsciiString(
Context.Memory,
SendPosition,
SendSize);
diff --git a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs
index 4f4c8add..b8ae11ce 100644
--- a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs
+++ b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs
@@ -60,7 +60,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
{
long NamePtr = Context.Request.SendBuff[0].Position;
- string Name = AMemoryHelper.ReadAsciiString(Context.Memory, NamePtr);
+ string Name = MemoryHelper.ReadAsciiString(Context.Memory, NamePtr);
int Fd = Fds.Add(Context.Process, new NvFd(Name));
diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvGpuAS/NvGpuASIoctl.cs b/Ryujinx.HLE/HOS/Services/Nv/NvGpuAS/NvGpuASIoctl.cs
index 0ccc1949..fed41042 100644
--- a/Ryujinx.HLE/HOS/Services/Nv/NvGpuAS/NvGpuASIoctl.cs
+++ b/Ryujinx.HLE/HOS/Services/Nv/NvGpuAS/NvGpuASIoctl.cs
@@ -52,7 +52,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuAS
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvGpuASAllocSpace Args = AMemoryHelper.Read<NvGpuASAllocSpace>(Context.Memory, InputPosition);
+ NvGpuASAllocSpace Args = MemoryHelper.Read<NvGpuASAllocSpace>(Context.Memory, InputPosition);
NvGpuASCtx ASCtx = GetASCtx(Context);
@@ -88,7 +88,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuAS
}
}
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return Result;
}
@@ -98,7 +98,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuAS
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvGpuASAllocSpace Args = AMemoryHelper.Read<NvGpuASAllocSpace>(Context.Memory, InputPosition);
+ NvGpuASAllocSpace Args = MemoryHelper.Read<NvGpuASAllocSpace>(Context.Memory, InputPosition);
NvGpuASCtx ASCtx = GetASCtx(Context);
@@ -130,7 +130,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuAS
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvGpuASUnmapBuffer Args = AMemoryHelper.Read<NvGpuASUnmapBuffer>(Context.Memory, InputPosition);
+ NvGpuASUnmapBuffer Args = MemoryHelper.Read<NvGpuASUnmapBuffer>(Context.Memory, InputPosition);
NvGpuASCtx ASCtx = GetASCtx(Context);
@@ -159,7 +159,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuAS
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvGpuASMapBufferEx Args = AMemoryHelper.Read<NvGpuASMapBufferEx>(Context.Memory, InputPosition);
+ NvGpuASMapBufferEx Args = MemoryHelper.Read<NvGpuASMapBufferEx>(Context.Memory, InputPosition);
NvGpuASCtx ASCtx = GetASCtx(Context);
@@ -255,7 +255,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuAS
}
}
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return Result;
}
@@ -288,7 +288,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuAS
for (int Index = 0; Index < Count; Index++, InputPosition += 0x14)
{
- NvGpuASRemap Args = AMemoryHelper.Read<NvGpuASRemap>(Context.Memory, InputPosition);
+ NvGpuASRemap Args = MemoryHelper.Read<NvGpuASRemap>(Context.Memory, InputPosition);
NvGpuVmm Vmm = GetASCtx(Context).Vmm;
diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvGpuGpu/NvGpuGpuIoctl.cs b/Ryujinx.HLE/HOS/Services/Nv/NvGpuGpu/NvGpuGpuIoctl.cs
index 387fe5b4..7ee770f4 100644
--- a/Ryujinx.HLE/HOS/Services/Nv/NvGpuGpu/NvGpuGpuIoctl.cs
+++ b/Ryujinx.HLE/HOS/Services/Nv/NvGpuGpu/NvGpuGpuIoctl.cs
@@ -44,7 +44,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuGpu
Args.Size = 1;
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
Logger.PrintStub(LogClass.ServiceNv, "Stubbed.");
@@ -68,7 +68,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuGpu
Args.SubregionHeightAlignPixels = 0x40;
Args.SubregionCount = 0x10;
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
Logger.PrintStub(LogClass.ServiceNv, "Stubbed.");
@@ -90,7 +90,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuGpu
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvGpuGpuGetCharacteristics Args = AMemoryHelper.Read<NvGpuGpuGetCharacteristics>(Context.Memory, InputPosition);
+ NvGpuGpuGetCharacteristics Args = MemoryHelper.Read<NvGpuGpuGetCharacteristics>(Context.Memory, InputPosition);
Args.BufferSize = 0xa0;
@@ -130,7 +130,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuGpu
Args.ChipName = 0x6230326d67;
Args.GrCompbitStoreBaseHw = 0x0;
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return NvResult.Success;
}
@@ -140,14 +140,14 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuGpu
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvGpuGpuGetTpcMasks Args = AMemoryHelper.Read<NvGpuGpuGetTpcMasks>(Context.Memory, InputPosition);
+ NvGpuGpuGetTpcMasks Args = MemoryHelper.Read<NvGpuGpuGetTpcMasks>(Context.Memory, InputPosition);
if (Args.MaskBufferSize != 0)
{
Args.TpcMask = 3;
}
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return NvResult.Success;
}
@@ -161,7 +161,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuGpu
Args.Slot = 0x07;
Args.Mask = 0x01;
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
Logger.PrintStub(LogClass.ServiceNv, "Stubbed.");
diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs b/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs
index d2dd089d..5443a3bf 100644
--- a/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs
+++ b/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs
@@ -86,7 +86,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvHostChannelSubmitGpfifo Args = AMemoryHelper.Read<NvHostChannelSubmitGpfifo>(Context.Memory, InputPosition);
+ NvHostChannelSubmitGpfifo Args = MemoryHelper.Read<NvHostChannelSubmitGpfifo>(Context.Memory, InputPosition);
NvGpuVmm Vmm = NvGpuASIoctl.GetASCtx(Context).Vmm;;
@@ -100,7 +100,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel
Args.SyncptId = 0;
Args.SyncptValue = 0;
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return NvResult.Success;
}
@@ -160,7 +160,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvHostChannelSubmitGpfifo Args = AMemoryHelper.Read<NvHostChannelSubmitGpfifo>(Context.Memory, InputPosition);
+ NvHostChannelSubmitGpfifo Args = MemoryHelper.Read<NvHostChannelSubmitGpfifo>(Context.Memory, InputPosition);
NvGpuVmm Vmm = NvGpuASIoctl.GetASCtx(Context).Vmm;;
@@ -174,7 +174,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostChannel
Args.SyncptId = 0;
Args.SyncptValue = 0;
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return NvResult.Success;
}
diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvHostCtrl/NvHostCtrlIoctl.cs b/Ryujinx.HLE/HOS/Services/Nv/NvHostCtrl/NvHostCtrlIoctl.cs
index 0b70928e..6cb14741 100644
--- a/Ryujinx.HLE/HOS/Services/Nv/NvHostCtrl/NvHostCtrlIoctl.cs
+++ b/Ryujinx.HLE/HOS/Services/Nv/NvHostCtrl/NvHostCtrlIoctl.cs
@@ -84,8 +84,8 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostCtrl
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- string Domain = AMemoryHelper.ReadAsciiString(Context.Memory, InputPosition + 0, 0x41);
- string Name = AMemoryHelper.ReadAsciiString(Context.Memory, InputPosition + 0x41, 0x41);
+ string Domain = MemoryHelper.ReadAsciiString(Context.Memory, InputPosition + 0, 0x41);
+ string Name = MemoryHelper.ReadAsciiString(Context.Memory, InputPosition + 0x41, 0x41);
if (Set.NxSettings.Settings.TryGetValue($"{Domain}!{Name}", out object NvSetting))
{
@@ -154,7 +154,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostCtrl
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvHostCtrlSyncptRead Args = AMemoryHelper.Read<NvHostCtrlSyncptRead>(Context.Memory, InputPosition);
+ NvHostCtrlSyncptRead Args = MemoryHelper.Read<NvHostCtrlSyncptRead>(Context.Memory, InputPosition);
if ((uint)Args.Id >= NvHostSyncpt.SyncptsCount)
{
@@ -170,7 +170,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostCtrl
Args.Value = GetUserCtx(Context).Syncpt.GetMin(Args.Id);
}
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return NvResult.Success;
}
@@ -180,7 +180,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostCtrl
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvHostCtrlSyncptWait Args = AMemoryHelper.Read<NvHostCtrlSyncptWait>(Context.Memory, InputPosition);
+ NvHostCtrlSyncptWait Args = MemoryHelper.Read<NvHostCtrlSyncptWait>(Context.Memory, InputPosition);
NvHostSyncpt Syncpt = GetUserCtx(Context).Syncpt;
@@ -248,7 +248,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostCtrl
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvHostCtrlSyncptWaitEx Args = AMemoryHelper.Read<NvHostCtrlSyncptWaitEx>(Context.Memory, InputPosition);
+ NvHostCtrlSyncptWaitEx Args = MemoryHelper.Read<NvHostCtrlSyncptWaitEx>(Context.Memory, InputPosition);
if ((uint)Args.Id >= NvHostSyncpt.SyncptsCount)
{
@@ -257,7 +257,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvHostCtrl
void WriteArgs()
{
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
}
NvHostSyncpt Syncpt = GetUserCtx(Context).Syncpt;
diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvMap/NvMapIoctl.cs b/Ryujinx.HLE/HOS/Services/Nv/NvMap/NvMapIoctl.cs
index 7953d665..f5378ef7 100644
--- a/Ryujinx.HLE/HOS/Services/Nv/NvMap/NvMapIoctl.cs
+++ b/Ryujinx.HLE/HOS/Services/Nv/NvMap/NvMapIoctl.cs
@@ -39,7 +39,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvMap
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvMapCreate Args = AMemoryHelper.Read<NvMapCreate>(Context.Memory, InputPosition);
+ NvMapCreate Args = MemoryHelper.Read<NvMapCreate>(Context.Memory, InputPosition);
if (Args.Size == 0)
{
@@ -54,7 +54,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvMap
Logger.PrintInfo(LogClass.ServiceNv, $"Created map {Args.Handle} with size 0x{Size:x8}!");
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return NvResult.Success;
}
@@ -64,7 +64,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvMap
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvMapFromId Args = AMemoryHelper.Read<NvMapFromId>(Context.Memory, InputPosition);
+ NvMapFromId Args = MemoryHelper.Read<NvMapFromId>(Context.Memory, InputPosition);
NvMapHandle Map = GetNvMap(Context, Args.Id);
@@ -79,7 +79,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvMap
Args.Handle = Args.Id;
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return NvResult.Success;
}
@@ -89,7 +89,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvMap
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvMapAlloc Args = AMemoryHelper.Read<NvMapAlloc>(Context.Memory, InputPosition);
+ NvMapAlloc Args = MemoryHelper.Read<NvMapAlloc>(Context.Memory, InputPosition);
NvMapHandle Map = GetNvMap(Context, Args.Handle);
@@ -143,7 +143,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvMap
}
}
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return Result;
}
@@ -153,7 +153,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvMap
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvMapFree Args = AMemoryHelper.Read<NvMapFree>(Context.Memory, InputPosition);
+ NvMapFree Args = MemoryHelper.Read<NvMapFree>(Context.Memory, InputPosition);
NvMapHandle Map = GetNvMap(Context, Args.Handle);
@@ -181,7 +181,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvMap
Args.Size = Map.Size;
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return NvResult.Success;
}
@@ -191,7 +191,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvMap
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvMapParam Args = AMemoryHelper.Read<NvMapParam>(Context.Memory, InputPosition);
+ NvMapParam Args = MemoryHelper.Read<NvMapParam>(Context.Memory, InputPosition);
NvMapHandle Map = GetNvMap(Context, Args.Handle);
@@ -215,7 +215,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvMap
default: return NvResult.InvalidInput;
}
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return NvResult.Success;
}
@@ -225,7 +225,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvMap
long InputPosition = Context.Request.GetBufferType0x21().Position;
long OutputPosition = Context.Request.GetBufferType0x22().Position;
- NvMapGetId Args = AMemoryHelper.Read<NvMapGetId>(Context.Memory, InputPosition);
+ NvMapGetId Args = MemoryHelper.Read<NvMapGetId>(Context.Memory, InputPosition);
NvMapHandle Map = GetNvMap(Context, Args.Handle);
@@ -238,7 +238,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvMap
Args.Id = Args.Handle;
- AMemoryHelper.Write(Context.Memory, OutputPosition, Args);
+ MemoryHelper.Write(Context.Memory, OutputPosition, Args);
return NvResult.Success;
}
diff --git a/Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs b/Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs
index 33a1dee9..5d1ddd84 100644
--- a/Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs
+++ b/Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs
@@ -77,7 +77,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
{
long RecBuffPtr = Context.Request.ReceiveBuff[0].Position;
- AMemoryHelper.FillWithZeros(Context.Memory, RecBuffPtr, 0x60);
+ MemoryHelper.FillWithZeros(Context.Memory, RecBuffPtr, 0x60);
//Add only the default display to buffer
Context.Memory.WriteBytes(RecBuffPtr, Encoding.ASCII.GetBytes("Default"));
diff --git a/Ryujinx.HLE/Loaders/Executable.cs b/Ryujinx.HLE/Loaders/Executable.cs
index 3c63af14..d4d79073 100644
--- a/Ryujinx.HLE/Loaders/Executable.cs
+++ b/Ryujinx.HLE/Loaders/Executable.cs
@@ -13,7 +13,7 @@ namespace Ryujinx.HLE.Loaders
{
class Executable
{
- private AMemory Memory;
+ private MemoryManager Memory;
private List<ElfDyn> Dynamic;
@@ -28,7 +28,7 @@ namespace Ryujinx.HLE.Loaders
private KMemoryManager MemoryManager;
- public Executable(IExecutable Exe, KMemoryManager MemoryManager, AMemory Memory, long ImageBase)
+ public Executable(IExecutable Exe, KMemoryManager MemoryManager, MemoryManager Memory, long ImageBase)
{
Dynamic = new List<ElfDyn>();
diff --git a/Ryujinx.HLE/Utilities/StructReader.cs b/Ryujinx.HLE/Utilities/StructReader.cs
index 6e942a9b..19fd2674 100644
--- a/Ryujinx.HLE/Utilities/StructReader.cs
+++ b/Ryujinx.HLE/Utilities/StructReader.cs
@@ -5,11 +5,11 @@ namespace Ryujinx.HLE.Utilities
{
class StructReader
{
- private AMemory Memory;
+ private MemoryManager Memory;
public long Position { get; private set; }
- public StructReader(AMemory Memory, long Position)
+ public StructReader(MemoryManager Memory, long Position)
{
this.Memory = Memory;
this.Position = Position;
@@ -17,7 +17,7 @@ namespace Ryujinx.HLE.Utilities
public T Read<T>() where T : struct
{
- T Value = AMemoryHelper.Read<T>(Memory, Position);
+ T Value = MemoryHelper.Read<T>(Memory, Position);
Position += Marshal.SizeOf<T>();
@@ -34,7 +34,7 @@ namespace Ryujinx.HLE.Utilities
for (int Index = 0; Index < Count; Index++)
{
- Output[Index] = AMemoryHelper.Read<T>(Memory, Position);
+ Output[Index] = MemoryHelper.Read<T>(Memory, Position);
Position += StructSize;
}
diff --git a/Ryujinx.HLE/Utilities/StructWriter.cs b/Ryujinx.HLE/Utilities/StructWriter.cs
index 8b88105c..a537e7a4 100644
--- a/Ryujinx.HLE/Utilities/StructWriter.cs
+++ b/Ryujinx.HLE/Utilities/StructWriter.cs
@@ -5,11 +5,11 @@ namespace Ryujinx.HLE.Utilities
{
class StructWriter
{
- private AMemory Memory;
+ private MemoryManager Memory;
public long Position { get; private set; }
- public StructWriter(AMemory Memory, long Position)
+ public StructWriter(MemoryManager Memory, long Position)
{
this.Memory = Memory;
this.Position = Position;
@@ -17,7 +17,7 @@ namespace Ryujinx.HLE.Utilities
public void Write<T>(T Value) where T : struct
{
- AMemoryHelper.Write(Memory, Position, Value);
+ MemoryHelper.Write(Memory, Position, Value);
Position += Marshal.SizeOf<T>();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs
index 4587189b..c273e89d 100644
--- a/Ryujinx.Tests/Cpu/CpuTest.cs
+++ b/Ryujinx.Tests/Cpu/CpuTest.cs
@@ -24,8 +24,8 @@ namespace Ryujinx.Tests.Cpu
private IntPtr RamPointer;
- private AMemory Memory;
- private AThread Thread;
+ private MemoryManager Memory;
+ private CpuThread Thread;
private static bool UnicornAvailable;
private UnicornAArch64 UnicornEmu;
@@ -48,11 +48,11 @@ namespace Ryujinx.Tests.Cpu
EntryPoint = Position;
- ATranslator Translator = new ATranslator();
+ Translator Translator = new Translator();
RamPointer = Marshal.AllocHGlobal(new IntPtr(Size));
- Memory = new AMemory(RamPointer);
+ Memory = new MemoryManager(RamPointer);
Memory.Map(Position, 0, Size);
- Thread = new AThread(Translator, Memory, EntryPoint);
+ Thread = new CpuThread(Translator, Memory, EntryPoint);
if (UnicornAvailable)
{
@@ -158,9 +158,9 @@ namespace Ryujinx.Tests.Cpu
}
}
- protected AThreadState GetThreadState() => Thread.ThreadState;
+ protected CpuThreadState GetThreadState() => Thread.ThreadState;
- protected AThreadState SingleOpcode(uint Opcode,
+ protected CpuThreadState SingleOpcode(uint Opcode,
ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, ulong X3 = 0, ulong X31 = 0,
Vector128<float> V0 = default(Vector128<float>),
Vector128<float> V1 = default(Vector128<float>),
diff --git a/Ryujinx.Tests/Cpu/CpuTestAlu.cs b/Ryujinx.Tests/Cpu/CpuTestAlu.cs
index 43952d19..666d279f 100644
--- a/Ryujinx.Tests/Cpu/CpuTestAlu.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestAlu.cs
@@ -23,7 +23,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -39,7 +39,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
@@ -55,7 +55,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -71,7 +71,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
@@ -87,7 +87,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -103,7 +103,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
@@ -119,7 +119,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -135,7 +135,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
@@ -151,7 +151,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -167,7 +167,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
@@ -183,7 +183,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestAluImm.cs b/Ryujinx.Tests/Cpu/CpuTestAluImm.cs
index 61eadefd..58d41fea 100644
--- a/Ryujinx.Tests/Cpu/CpuTestAluImm.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestAluImm.cs
@@ -27,7 +27,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -53,7 +53,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -79,7 +79,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -105,7 +105,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -133,7 +133,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -152,7 +152,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -171,7 +171,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
@@ -190,7 +190,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -209,7 +209,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -228,7 +228,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
@@ -247,7 +247,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -266,7 +266,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -285,7 +285,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
@@ -304,7 +304,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -323,7 +323,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -342,7 +342,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
@@ -359,7 +359,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -385,7 +385,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -411,7 +411,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -437,7 +437,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
diff --git a/Ryujinx.Tests/Cpu/CpuTestAluRs.cs b/Ryujinx.Tests/Cpu/CpuTestAluRs.cs
index 58a99dfb..833d5d6d 100644
--- a/Ryujinx.Tests/Cpu/CpuTestAluRs.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestAluRs.cs
@@ -29,7 +29,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31, Carry: CarryIn);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31, Carry: CarryIn);
CompareAgainstUnicorn();
}
@@ -49,7 +49,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31, Carry: CarryIn);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31, Carry: CarryIn);
CompareAgainstUnicorn();
}
@@ -69,7 +69,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31, Carry: CarryIn);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31, Carry: CarryIn);
CompareAgainstUnicorn();
}
@@ -89,7 +89,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31, Carry: CarryIn);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31, Carry: CarryIn);
CompareAgainstUnicorn();
}
@@ -111,7 +111,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -133,7 +133,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -155,7 +155,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -177,7 +177,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -199,7 +199,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -221,7 +221,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -243,7 +243,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -265,7 +265,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -284,7 +284,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -303,7 +303,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -325,7 +325,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -347,7 +347,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -369,7 +369,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -391,7 +391,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -411,7 +411,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Xm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Xm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -429,7 +429,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -447,7 +447,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -465,7 +465,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -485,7 +485,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Xm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Xm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -503,7 +503,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -521,7 +521,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -539,7 +539,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -561,7 +561,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -583,7 +583,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -605,7 +605,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -627,7 +627,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -648,7 +648,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -669,7 +669,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -688,7 +688,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -707,7 +707,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -726,7 +726,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -745,7 +745,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -767,7 +767,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -789,7 +789,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -811,7 +811,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -833,7 +833,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -852,7 +852,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -871,7 +871,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -891,7 +891,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31, Carry: CarryIn);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31, Carry: CarryIn);
CompareAgainstUnicorn();
}
@@ -911,7 +911,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31, Carry: CarryIn);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31, Carry: CarryIn);
CompareAgainstUnicorn();
}
@@ -931,7 +931,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31, Carry: CarryIn);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31, Carry: CarryIn);
CompareAgainstUnicorn();
}
@@ -951,7 +951,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31, Carry: CarryIn);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31, Carry: CarryIn);
CompareAgainstUnicorn();
}
@@ -970,7 +970,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -989,7 +989,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -1011,7 +1011,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -1033,7 +1033,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -1055,7 +1055,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -1077,7 +1077,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -1096,7 +1096,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -1115,7 +1115,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestAluRx.cs b/Ryujinx.Tests/Cpu/CpuTestAluRx.cs
index 9c66532b..8a11fa94 100644
--- a/Ryujinx.Tests/Cpu/CpuTestAluRx.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestAluRx.cs
@@ -27,7 +27,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -59,7 +59,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -91,7 +91,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -123,7 +123,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -155,7 +155,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -187,7 +187,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -219,7 +219,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -250,7 +250,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Xm, X31: Xn_SP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Xm, X31: Xn_SP);
CompareAgainstUnicorn();
}
@@ -271,7 +271,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
CompareAgainstUnicorn();
}
@@ -292,7 +292,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
CompareAgainstUnicorn();
}
@@ -313,7 +313,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
CompareAgainstUnicorn();
}
@@ -334,7 +334,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
CompareAgainstUnicorn();
}
@@ -355,7 +355,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
CompareAgainstUnicorn();
}
@@ -376,7 +376,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
CompareAgainstUnicorn();
}
@@ -396,7 +396,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -428,7 +428,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -460,7 +460,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -492,7 +492,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -524,7 +524,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -556,7 +556,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -588,7 +588,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState;
+ CpuThreadState ThreadState;
if (Rn != 31)
{
@@ -619,7 +619,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Xm, X31: Xn_SP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Xm, X31: Xn_SP);
CompareAgainstUnicorn();
}
@@ -640,7 +640,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
CompareAgainstUnicorn();
}
@@ -661,7 +661,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
CompareAgainstUnicorn();
}
@@ -682,7 +682,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
CompareAgainstUnicorn();
}
@@ -703,7 +703,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
CompareAgainstUnicorn();
}
@@ -724,7 +724,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
CompareAgainstUnicorn();
}
@@ -745,7 +745,7 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestBfm.cs b/Ryujinx.Tests/Cpu/CpuTestBfm.cs
index 427396f8..59434029 100644
--- a/Ryujinx.Tests/Cpu/CpuTestBfm.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestBfm.cs
@@ -29,7 +29,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X0: _Xd, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X0: _Xd, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -49,7 +49,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X0: _Wd, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X0: _Wd, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
@@ -68,7 +68,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -87,7 +87,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
@@ -106,7 +106,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -125,7 +125,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestCcmpImm.cs b/Ryujinx.Tests/Cpu/CpuTestCcmpImm.cs
index 7ca92d4f..7eebedf3 100644
--- a/Ryujinx.Tests/Cpu/CpuTestCcmpImm.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestCcmpImm.cs
@@ -31,7 +31,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -53,7 +53,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
@@ -75,7 +75,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
CompareAgainstUnicorn();
}
@@ -97,7 +97,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestCcmpReg.cs b/Ryujinx.Tests/Cpu/CpuTestCcmpReg.cs
index 36120f74..68640877 100644
--- a/Ryujinx.Tests/Cpu/CpuTestCcmpReg.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestCcmpReg.cs
@@ -32,7 +32,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -56,7 +56,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -80,7 +80,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -104,7 +104,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestCsel.cs b/Ryujinx.Tests/Cpu/CpuTestCsel.cs
index 2d88b9f0..f9691ed1 100644
--- a/Ryujinx.Tests/Cpu/CpuTestCsel.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestCsel.cs
@@ -31,7 +31,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -55,7 +55,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -79,7 +79,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -103,7 +103,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -127,7 +127,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -151,7 +151,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
@@ -175,7 +175,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -199,7 +199,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestMisc.cs b/Ryujinx.Tests/Cpu/CpuTestMisc.cs
index d7b75f5e..ac6d3405 100644
--- a/Ryujinx.Tests/Cpu/CpuTestMisc.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestMisc.cs
@@ -262,7 +262,7 @@ namespace Ryujinx.Tests.Cpu
public void SanityCheck(ulong A)
{
uint Opcode = 0xD503201F; // NOP
- AThreadState ThreadState = SingleOpcode(Opcode, X0: A);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X0: A);
Assert.That(ThreadState.X0, Is.EqualTo(A));
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestMov.cs b/Ryujinx.Tests/Cpu/CpuTestMov.cs
index 175c9f06..3c1a174b 100644
--- a/Ryujinx.Tests/Cpu/CpuTestMov.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestMov.cs
@@ -24,7 +24,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X0: _Xd, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X0: _Xd, X31: _X31);
CompareAgainstUnicorn();
}
@@ -41,7 +41,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X0: _Wd, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X0: _Wd, X31: _W31);
CompareAgainstUnicorn();
}
@@ -57,7 +57,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X31: _X31);
CompareAgainstUnicorn();
}
@@ -73,7 +73,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X31: _W31);
CompareAgainstUnicorn();
}
@@ -89,7 +89,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X31: _X31);
CompareAgainstUnicorn();
}
@@ -105,7 +105,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X31: _W31);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestMul.cs b/Ryujinx.Tests/Cpu/CpuTestMul.cs
index 056c4543..4058585b 100644
--- a/Ryujinx.Tests/Cpu/CpuTestMul.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestMul.cs
@@ -29,7 +29,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X3: Xa, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X3: Xa, X31: _X31);
CompareAgainstUnicorn();
}
@@ -51,7 +51,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Wa, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Wa, X31: _W31);
CompareAgainstUnicorn();
}
@@ -73,7 +73,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X3: Xa, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X3: Xa, X31: _X31);
CompareAgainstUnicorn();
}
@@ -95,7 +95,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Wa, X31: _W31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Wa, X31: _W31);
CompareAgainstUnicorn();
}
@@ -117,7 +117,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31);
CompareAgainstUnicorn();
}
@@ -139,7 +139,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31);
CompareAgainstUnicorn();
}
@@ -161,7 +161,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31);
CompareAgainstUnicorn();
}
@@ -183,7 +183,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31);
CompareAgainstUnicorn();
}
@@ -202,7 +202,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
@@ -221,7 +221,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestSimd.cs b/Ryujinx.Tests/Cpu/CpuTestSimd.cs
index 3bb24f3a..8cd36b10 100644
--- a/Ryujinx.Tests/Cpu/CpuTestSimd.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestSimd.cs
@@ -408,7 +408,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -427,7 +427,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -446,7 +446,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -463,7 +463,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -482,7 +482,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -501,7 +501,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -520,7 +520,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -539,7 +539,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -558,7 +558,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -577,7 +577,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -594,7 +594,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -613,7 +613,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -632,7 +632,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -649,7 +649,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -668,7 +668,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -687,7 +687,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -704,7 +704,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -723,7 +723,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -742,7 +742,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -759,7 +759,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -778,7 +778,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -797,7 +797,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -814,7 +814,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -833,7 +833,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -852,7 +852,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -869,7 +869,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -886,7 +886,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -899,7 +899,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE1(Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -912,7 +912,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -925,7 +925,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -938,7 +938,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE1(Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -957,7 +957,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A * Q);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -974,7 +974,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1001,7 +1001,7 @@ namespace Ryujinx.Tests.Cpu
Fpcr |= Rnd & (1 << (int)FPCR.DN);
Fpcr |= Rnd & (1 << (int)FPCR.AHP);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC | FPSR.OFC | FPSR.UFC | FPSR.IXC);
}
@@ -1021,7 +1021,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Q == 0u ? Z : 0ul, Q == 1u ? Z : 0ul);
Vector128<float> V1 = MakeVectorE0E1(Q == 0u ? A : 0ul, Q == 1u ? A : 0ul);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1048,7 +1048,7 @@ namespace Ryujinx.Tests.Cpu
Fpcr |= Rnd & (1 << (int)FPCR.DN);
Fpcr |= Rnd & (1 << (int)FPCR.AHP);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC | FPSR.OFC | FPSR.UFC | FPSR.IXC | FPSR.IDC);
}
@@ -1068,7 +1068,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1083,7 +1083,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC);
}
@@ -1098,7 +1098,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC);
}
@@ -1119,7 +1119,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC);
}
@@ -1138,7 +1138,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC);
}
@@ -1155,7 +1155,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1174,7 +1174,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1193,7 +1193,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1210,7 +1210,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1227,7 +1227,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1244,7 +1244,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1261,7 +1261,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1278,7 +1278,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1295,7 +1295,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1314,7 +1314,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1333,7 +1333,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1352,7 +1352,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1371,7 +1371,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1390,7 +1390,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1409,7 +1409,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1428,7 +1428,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1447,7 +1447,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1464,7 +1464,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z0, Z1);
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1481,7 +1481,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z0, Z1);
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1500,7 +1500,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1519,7 +1519,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1538,7 +1538,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1557,7 +1557,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1576,7 +1576,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1595,7 +1595,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1614,7 +1614,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1633,7 +1633,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1652,7 +1652,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1671,7 +1671,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1690,7 +1690,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1709,7 +1709,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1728,7 +1728,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1747,7 +1747,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1766,7 +1766,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1785,7 +1785,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1804,7 +1804,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1823,7 +1823,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1842,7 +1842,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1861,7 +1861,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1880,7 +1880,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1899,7 +1899,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1918,7 +1918,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1937,7 +1937,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1956,7 +1956,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -1975,7 +1975,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -1994,7 +1994,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdArithmetic.cs b/Ryujinx.Tests/Cpu/CpuTestSimdArithmetic.cs
index 08e2894c..770eb4cf 100644
--- a/Ryujinx.Tests/Cpu/CpuTestSimdArithmetic.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestSimdArithmetic.cs
@@ -21,7 +21,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
@@ -78,7 +78,7 @@ namespace Ryujinx.Tests.Cpu
FpcrTemp = 0x2000000;
}
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
@@ -107,7 +107,7 @@ namespace Ryujinx.Tests.Cpu
FpcrTemp = 0x2000000;
}
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() =>
{
@@ -177,7 +177,7 @@ namespace Ryujinx.Tests.Cpu
FpcrTemp |= 1 << 25;
}
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
@@ -233,7 +233,7 @@ namespace Ryujinx.Tests.Cpu
FpcrTemp |= 1 << 25;
}
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() =>
{
@@ -294,7 +294,7 @@ namespace Ryujinx.Tests.Cpu
FpcrTemp = 0x2000000;
}
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
@@ -319,7 +319,7 @@ namespace Ryujinx.Tests.Cpu
FpcrTemp = 0x2000000;
}
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() =>
{
@@ -381,7 +381,7 @@ namespace Ryujinx.Tests.Cpu
FpcrTemp = 0x2000000;
}
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
@@ -409,7 +409,7 @@ namespace Ryujinx.Tests.Cpu
FpcrTemp = 0x2000000;
}
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() =>
{
@@ -470,7 +470,7 @@ namespace Ryujinx.Tests.Cpu
FpcrTemp = 0x2000000;
}
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
@@ -495,7 +495,7 @@ namespace Ryujinx.Tests.Cpu
FpcrTemp = 0x2000000;
}
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() =>
{
@@ -565,7 +565,7 @@ namespace Ryujinx.Tests.Cpu
FpcrTemp |= 1 << 25;
}
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
@@ -621,7 +621,7 @@ namespace Ryujinx.Tests.Cpu
FpcrTemp |= 1 << 25;
}
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() =>
{
@@ -639,7 +639,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdCrypto.cs b/Ryujinx.Tests/Cpu/CpuTestSimdCrypto.cs
index 4efd8f31..ce2b50f0 100644
--- a/Ryujinx.Tests/Cpu/CpuTestSimdCrypto.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestSimdCrypto.cs
@@ -26,7 +26,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(RoundKeyL ^ ValueL, RoundKeyH ^ ValueH);
Vector128<float> V1 = MakeVectorE0E1(RoundKeyL, RoundKeyH);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
Assert.Multiple(() =>
{
@@ -58,7 +58,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(RoundKeyL ^ ValueL, RoundKeyH ^ ValueH);
Vector128<float> V1 = MakeVectorE0E1(RoundKeyL, RoundKeyH);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
Assert.Multiple(() =>
{
@@ -87,7 +87,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V = MakeVectorE0E1(ValueL, ValueH);
- AThreadState ThreadState = SingleOpcode(
+ CpuThreadState ThreadState = SingleOpcode(
Opcode,
V0: Rn == 0u ? V : default(Vector128<float>),
V1: Rn == 1u ? V : default(Vector128<float>));
@@ -122,7 +122,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V = MakeVectorE0E1(ValueL, ValueH);
- AThreadState ThreadState = SingleOpcode(
+ CpuThreadState ThreadState = SingleOpcode(
Opcode,
V0: Rn == 0u ? V : default(Vector128<float>),
V1: Rn == 1u ? V : default(Vector128<float>));
diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdIns.cs b/Ryujinx.Tests/Cpu/CpuTestSimdIns.cs
index 0b227edb..c07e47c8 100644
--- a/Ryujinx.Tests/Cpu/CpuTestSimdIns.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestSimdIns.cs
@@ -70,7 +70,7 @@ namespace Ryujinx.Tests.Cpu
ulong Z = TestContext.CurrentContext.Random.NextULong();
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, V0: V0);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, V0: V0);
CompareAgainstUnicorn();
}
@@ -86,7 +86,7 @@ namespace Ryujinx.Tests.Cpu
ulong Z = TestContext.CurrentContext.Random.NextULong();
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
- AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, V0: V0);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, V0: V0);
CompareAgainstUnicorn();
}
@@ -108,7 +108,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, X0: _X0, X31: _W31, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X0: _X0, X31: _W31, V1: V1);
CompareAgainstUnicorn();
}
@@ -129,7 +129,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, X31: _X31, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X31: _X31, V1: V1);
CompareAgainstUnicorn();
}
@@ -151,7 +151,7 @@ namespace Ryujinx.Tests.Cpu
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, X0: _X0, X31: _W31, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X0: _X0, X31: _W31, V1: V1);
CompareAgainstUnicorn();
}
@@ -172,7 +172,7 @@ namespace Ryujinx.Tests.Cpu
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, X31: _X31, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, X31: _X31, V1: V1);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdReg.cs b/Ryujinx.Tests/Cpu/CpuTestSimdReg.cs
index e986d7f6..3f0188cc 100644
--- a/Ryujinx.Tests/Cpu/CpuTestSimdReg.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestSimdReg.cs
@@ -397,7 +397,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -419,7 +419,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -441,7 +441,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -463,7 +463,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -485,7 +485,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -507,7 +507,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -529,7 +529,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -549,7 +549,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -569,7 +569,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -589,7 +589,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -609,7 +609,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -629,7 +629,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -649,7 +649,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -669,7 +669,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -689,7 +689,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -709,7 +709,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -729,7 +729,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -749,7 +749,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -771,7 +771,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -793,7 +793,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -813,7 +813,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -835,7 +835,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -857,7 +857,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -877,7 +877,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -899,7 +899,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -921,7 +921,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -941,7 +941,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -963,7 +963,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -985,7 +985,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1005,7 +1005,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1027,7 +1027,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1049,7 +1049,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1069,7 +1069,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1091,7 +1091,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1113,7 +1113,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1133,7 +1133,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1153,7 +1153,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1170,7 +1170,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC | FPSR.DZC);
}
@@ -1187,7 +1187,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC | FPSR.DZC);
}
@@ -1211,7 +1211,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC | FPSR.DZC);
}
@@ -1233,7 +1233,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC | FPSR.DZC);
}
@@ -1252,7 +1252,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, V3: V3, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, V3: V3, Fpcr: Fpcr);
CompareAgainstUnicorn(FPSR.IOC, FpSkips.IfUnderflow, FpTolerances.UpToOneUlps_S);
}
@@ -1271,7 +1271,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, V3: V3, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, V3: V3, Fpcr: Fpcr);
CompareAgainstUnicorn(FPSR.IOC, FpSkips.IfUnderflow, FpTolerances.UpToOneUlps_D);
}
@@ -1288,7 +1288,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC);
}
@@ -1305,7 +1305,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC);
}
@@ -1329,7 +1329,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC);
}
@@ -1351,7 +1351,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC);
}
@@ -1368,7 +1368,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FPSR.IOC, FpSkips.IfUnderflow, FpTolerances.UpToOneUlps_S);
}
@@ -1385,7 +1385,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FPSR.IOC, FpSkips.IfUnderflow, FpTolerances.UpToOneUlps_D);
}
@@ -1409,7 +1409,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FPSR.IOC, FpSkips.IfUnderflow, FpTolerances.UpToOneUlps_S);
}
@@ -1431,7 +1431,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FPSR.IOC, FpSkips.IfUnderflow, FpTolerances.UpToOneUlps_D);
}
@@ -1451,7 +1451,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1471,7 +1471,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1491,7 +1491,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1511,7 +1511,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1533,7 +1533,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1555,7 +1555,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1577,7 +1577,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1599,7 +1599,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1621,7 +1621,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1643,7 +1643,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1665,7 +1665,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1687,7 +1687,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE1(A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1709,7 +1709,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1731,7 +1731,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1753,7 +1753,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1775,7 +1775,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE1(A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1797,7 +1797,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1819,7 +1819,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE1(A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1841,7 +1841,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1863,7 +1863,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1883,7 +1883,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
Vector128<float> V2 = MakeVectorE0E1(B0, B1);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1903,7 +1903,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
Vector128<float> V2 = MakeVectorE0E1(B0, B1);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1925,7 +1925,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1947,7 +1947,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1969,7 +1969,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -1991,7 +1991,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2013,7 +2013,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2035,7 +2035,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE1(A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2057,7 +2057,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2079,7 +2079,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE1(A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2101,7 +2101,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -2123,7 +2123,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -2145,7 +2145,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -2167,7 +2167,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -2189,7 +2189,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -2211,7 +2211,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -2233,7 +2233,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -2255,7 +2255,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -2277,7 +2277,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -2299,7 +2299,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -2321,7 +2321,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -2343,7 +2343,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -2365,7 +2365,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2387,7 +2387,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2409,7 +2409,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2431,7 +2431,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE1(A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2453,7 +2453,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2475,7 +2475,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2495,7 +2495,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2517,7 +2517,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2539,7 +2539,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2561,7 +2561,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2583,7 +2583,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2605,7 +2605,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2627,7 +2627,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2649,7 +2649,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2671,7 +2671,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2693,7 +2693,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2715,7 +2715,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2737,7 +2737,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2759,7 +2759,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE1(A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2781,7 +2781,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2803,7 +2803,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2825,7 +2825,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2847,7 +2847,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE1(A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2869,7 +2869,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2891,7 +2891,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE1(A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2913,7 +2913,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2935,7 +2935,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2957,7 +2957,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -2979,7 +2979,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3001,7 +3001,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3023,7 +3023,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3045,7 +3045,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3067,7 +3067,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE1(A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3089,7 +3089,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3111,7 +3111,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE1(A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3133,7 +3133,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -3155,7 +3155,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -3177,7 +3177,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -3199,7 +3199,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -3221,7 +3221,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -3243,7 +3243,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -3265,7 +3265,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3287,7 +3287,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3309,7 +3309,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3331,7 +3331,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE1(A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3353,7 +3353,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3375,7 +3375,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE1(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3397,7 +3397,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3419,7 +3419,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3441,7 +3441,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3463,7 +3463,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3485,7 +3485,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3507,7 +3507,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3529,7 +3529,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -3551,7 +3551,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs b/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs
index 61552062..10d3105c 100644
--- a/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs
@@ -74,7 +74,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A * Q);
Vector128<float> V2 = MakeVectorE0E1(B, B * H);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
@@ -101,7 +101,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V1 = MakeVectorE0E1(A, A * Q);
Vector128<float> V2 = MakeVectorE0E1(B, B * H);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2);
CompareAgainstUnicorn();
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdRegElemF.cs b/Ryujinx.Tests/Cpu/CpuTestSimdRegElemF.cs
index 3945cce1..e9591a19 100644
--- a/Ryujinx.Tests/Cpu/CpuTestSimdRegElemF.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestSimdRegElemF.cs
@@ -238,7 +238,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FPSR.IOC, FpSkips.IfUnderflow, FpTolerances.UpToOneUlps_S);
}
@@ -260,7 +260,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FPSR.IOC, FpSkips.IfUnderflow, FpTolerances.UpToOneUlps_D);
}
@@ -289,7 +289,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FPSR.IOC, FpSkips.IfUnderflow, FpTolerances.UpToOneUlps_S);
}
@@ -315,7 +315,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FPSR.IOC, FpSkips.IfUnderflow, FpTolerances.UpToOneUlps_D);
}
@@ -338,7 +338,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC);
}
@@ -360,7 +360,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC);
}
@@ -389,7 +389,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC);
}
@@ -415,7 +415,7 @@ namespace Ryujinx.Tests.Cpu
int Fpcr = (int)TestContext.CurrentContext.Random.NextUInt() & (1 << (int)FPCR.DN);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1, V2: V2, Fpcr: Fpcr);
CompareAgainstUnicorn(FpsrMask: FPSR.IOC);
}
diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdShImm.cs b/Ryujinx.Tests/Cpu/CpuTestSimdShImm.cs
index edc50d4d..7ae41b4e 100644
--- a/Ryujinx.Tests/Cpu/CpuTestSimdShImm.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestSimdShImm.cs
@@ -251,7 +251,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -274,7 +274,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A * Q);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -297,7 +297,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A * Q);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -320,7 +320,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A * Q);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -341,7 +341,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -362,7 +362,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -385,7 +385,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A * Q);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -408,7 +408,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A * Q);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -431,7 +431,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A * Q);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -452,7 +452,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -475,7 +475,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -498,7 +498,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -521,7 +521,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn();
}
@@ -542,7 +542,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -563,7 +563,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -584,7 +584,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -607,7 +607,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -630,7 +630,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
@@ -653,7 +653,7 @@ namespace Ryujinx.Tests.Cpu
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
- AThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
+ CpuThreadState ThreadState = SingleOpcode(Opcodes, V0: V0, V1: V1);
CompareAgainstUnicorn(FpsrMask: FPSR.QC);
}
diff --git a/Ryujinx/Config.cs b/Ryujinx/Config.cs
index 3e4d4dd3..2e739852 100644
--- a/Ryujinx/Config.cs
+++ b/Ryujinx/Config.cs
@@ -15,29 +15,29 @@ namespace Ryujinx
public static JoyConKeyboard JoyConKeyboard { get; private set; }
public static JoyConController JoyConController { get; private set; }
- public static void Read(Switch Device)
+ public static void Read(Switch device)
{
- string IniFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
+ string iniFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
- string IniPath = Path.Combine(IniFolder, "Ryujinx.conf");
+ string iniPath = Path.Combine(iniFolder, "Ryujinx.conf");
- IniParser Parser = new IniParser(IniPath);
+ IniParser parser = new IniParser(iniPath);
- GraphicsConfig.ShadersDumpPath = Parser.Value("Graphics_Shaders_Dump_Path");
+ GraphicsConfig.ShadersDumpPath = parser.Value("Graphics_Shaders_Dump_Path");
- Logger.SetEnable(LogLevel.Debug, Convert.ToBoolean(Parser.Value("Logging_Enable_Debug")));
- Logger.SetEnable(LogLevel.Stub, Convert.ToBoolean(Parser.Value("Logging_Enable_Stub")));
- Logger.SetEnable(LogLevel.Info, Convert.ToBoolean(Parser.Value("Logging_Enable_Info")));
- Logger.SetEnable(LogLevel.Warning, Convert.ToBoolean(Parser.Value("Logging_Enable_Warn")));
- Logger.SetEnable(LogLevel.Error, Convert.ToBoolean(Parser.Value("Logging_Enable_Error")));
+ Logger.SetEnable(LogLevel.Debug, Convert.ToBoolean(parser.Value("Logging_Enable_Debug")));
+ Logger.SetEnable(LogLevel.Stub, Convert.ToBoolean(parser.Value("Logging_Enable_Stub")));
+ Logger.SetEnable(LogLevel.Info, Convert.ToBoolean(parser.Value("Logging_Enable_Info")));
+ Logger.SetEnable(LogLevel.Warning, Convert.ToBoolean(parser.Value("Logging_Enable_Warn")));
+ Logger.SetEnable(LogLevel.Error, Convert.ToBoolean(parser.Value("Logging_Enable_Error")));
- string[] FilteredLogClasses = Parser.Value("Logging_Filtered_Classes").Split(',', StringSplitOptions.RemoveEmptyEntries);
+ string[] filteredLogClasses = parser.Value("Logging_Filtered_Classes").Split(',', StringSplitOptions.RemoveEmptyEntries);
//When the classes are specified on the list, we only
//enable the classes that are on the list.
//So, first disable everything, then enable
//the classes that the user added to the list.
- if (FilteredLogClasses.Length > 0)
+ if (filteredLogClasses.Length > 0)
{
foreach (LogClass Class in Enum.GetValues(typeof(LogClass)))
{
@@ -45,13 +45,13 @@ namespace Ryujinx
}
}
- foreach (string LogClass in FilteredLogClasses)
+ foreach (string logClass in filteredLogClasses)
{
- if (!string.IsNullOrEmpty(LogClass.Trim()))
+ if (!string.IsNullOrEmpty(logClass.Trim()))
{
foreach (LogClass Class in Enum.GetValues(typeof(LogClass)))
{
- if (Class.ToString().ToLower().Contains(LogClass.Trim().ToLower()))
+ if (Class.ToString().ToLower().Contains(logClass.Trim().ToLower()))
{
Logger.SetEnable(Class, true);
}
@@ -59,111 +59,111 @@ namespace Ryujinx
}
}
- Device.System.State.DockedMode = Convert.ToBoolean(Parser.Value("Docked_Mode"));
+ device.System.State.DockedMode = Convert.ToBoolean(parser.Value("Docked_Mode"));
- Device.EnableDeviceVsync = Convert.ToBoolean(Parser.Value("Enable_Vsync"));
+ device.EnableDeviceVsync = Convert.ToBoolean(parser.Value("Enable_Vsync"));
- if (Convert.ToBoolean(Parser.Value("Enable_MultiCore_Scheduling")))
+ if (Convert.ToBoolean(parser.Value("Enable_MultiCore_Scheduling")))
{
- Device.System.EnableMultiCoreScheduling();
+ device.System.EnableMultiCoreScheduling();
}
- Device.System.EnableFsIntegrityChecks = Convert.ToBoolean(Parser.Value("Enable_FS_Integrity_Checks"));
+ device.System.EnableFsIntegrityChecks = Convert.ToBoolean(parser.Value("Enable_FS_Integrity_Checks"));
JoyConKeyboard = new JoyConKeyboard(
new JoyConKeyboardLeft
{
- StickUp = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_Stick_Up")),
- StickDown = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_Stick_Down")),
- StickLeft = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_Stick_Left")),
- StickRight = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_Stick_Right")),
- StickButton = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_Stick_Button")),
- DPadUp = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_DPad_Up")),
- DPadDown = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_DPad_Down")),
- DPadLeft = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_DPad_Left")),
- DPadRight = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_DPad_Right")),
- ButtonMinus = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_Button_Minus")),
- ButtonL = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_Button_L")),
- ButtonZL = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_Button_ZL"))
+ StickUp = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Stick_Up")),
+ StickDown = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Stick_Down")),
+ StickLeft = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Stick_Left")),
+ StickRight = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Stick_Right")),
+ StickButton = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Stick_Button")),
+ DPadUp = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_DPad_Up")),
+ DPadDown = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_DPad_Down")),
+ DPadLeft = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_DPad_Left")),
+ DPadRight = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_DPad_Right")),
+ ButtonMinus = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Button_Minus")),
+ ButtonL = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Button_L")),
+ ButtonZl = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Button_ZL"))
},
new JoyConKeyboardRight
{
- StickUp = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Stick_Up")),
- StickDown = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Stick_Down")),
- StickLeft = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Stick_Left")),
- StickRight = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Stick_Right")),
- StickButton = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Stick_Button")),
- ButtonA = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Button_A")),
- ButtonB = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Button_B")),
- ButtonX = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Button_X")),
- ButtonY = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Button_Y")),
- ButtonPlus = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Button_Plus")),
- ButtonR = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Button_R")),
- ButtonZR = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Button_ZR"))
+ StickUp = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Stick_Up")),
+ StickDown = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Stick_Down")),
+ StickLeft = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Stick_Left")),
+ StickRight = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Stick_Right")),
+ StickButton = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Stick_Button")),
+ ButtonA = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_A")),
+ ButtonB = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_B")),
+ ButtonX = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_X")),
+ ButtonY = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_Y")),
+ ButtonPlus = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_Plus")),
+ ButtonR = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_R")),
+ ButtonZr = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_ZR"))
});
JoyConController = new JoyConController(
- Convert.ToBoolean(Parser.Value("GamePad_Enable")),
- Convert.ToInt32 (Parser.Value("GamePad_Index")),
- (float)Convert.ToDouble (Parser.Value("GamePad_Deadzone"), CultureInfo.InvariantCulture),
- (float)Convert.ToDouble (Parser.Value("GamePad_Trigger_Threshold"), CultureInfo.InvariantCulture),
+ Convert.ToBoolean(parser.Value("GamePad_Enable")),
+ Convert.ToInt32 (parser.Value("GamePad_Index")),
+ (float)Convert.ToDouble (parser.Value("GamePad_Deadzone"), CultureInfo.InvariantCulture),
+ (float)Convert.ToDouble (parser.Value("GamePad_Trigger_Threshold"), CultureInfo.InvariantCulture),
new JoyConControllerLeft
{
- Stick = ToID(Parser.Value("Controls_Left_JoyConController_Stick")),
- StickButton = ToID(Parser.Value("Controls_Left_JoyConController_Stick_Button")),
- DPadUp = ToID(Parser.Value("Controls_Left_JoyConController_DPad_Up")),
- DPadDown = ToID(Parser.Value("Controls_Left_JoyConController_DPad_Down")),
- DPadLeft = ToID(Parser.Value("Controls_Left_JoyConController_DPad_Left")),
- DPadRight = ToID(Parser.Value("Controls_Left_JoyConController_DPad_Right")),
- ButtonMinus = ToID(Parser.Value("Controls_Left_JoyConController_Button_Minus")),
- ButtonL = ToID(Parser.Value("Controls_Left_JoyConController_Button_L")),
- ButtonZL = ToID(Parser.Value("Controls_Left_JoyConController_Button_ZL"))
+ Stick = ToId(parser.Value("Controls_Left_JoyConController_Stick")),
+ StickButton = ToId(parser.Value("Controls_Left_JoyConController_Stick_Button")),
+ DPadUp = ToId(parser.Value("Controls_Left_JoyConController_DPad_Up")),
+ DPadDown = ToId(parser.Value("Controls_Left_JoyConController_DPad_Down")),
+ DPadLeft = ToId(parser.Value("Controls_Left_JoyConController_DPad_Left")),
+ DPadRight = ToId(parser.Value("Controls_Left_JoyConController_DPad_Right")),
+ ButtonMinus = ToId(parser.Value("Controls_Left_JoyConController_Button_Minus")),
+ ButtonL = ToId(parser.Value("Controls_Left_JoyConController_Button_L")),
+ ButtonZl = ToId(parser.Value("Controls_Left_JoyConController_Button_ZL"))
},
new JoyConControllerRight
{
- Stick = ToID(Parser.Value("Controls_Right_JoyConController_Stick")),
- StickButton = ToID(Parser.Value("Controls_Right_JoyConController_Stick_Button")),
- ButtonA = ToID(Parser.Value("Controls_Right_JoyConController_Button_A")),
- ButtonB = ToID(Parser.Value("Controls_Right_JoyConController_Button_B")),
- ButtonX = ToID(Parser.Value("Controls_Right_JoyConController_Button_X")),
- ButtonY = ToID(Parser.Value("Controls_Right_JoyConController_Button_Y")),
- ButtonPlus = ToID(Parser.Value("Controls_Right_JoyConController_Button_Plus")),
- ButtonR = ToID(Parser.Value("Controls_Right_JoyConController_Button_R")),
- ButtonZR = ToID(Parser.Value("Controls_Right_JoyConController_Button_ZR"))
+ Stick = ToId(parser.Value("Controls_Right_JoyConController_Stick")),
+ StickButton = ToId(parser.Value("Controls_Right_JoyConController_Stick_Button")),
+ ButtonA = ToId(parser.Value("Controls_Right_JoyConController_Button_A")),
+ ButtonB = ToId(parser.Value("Controls_Right_JoyConController_Button_B")),
+ ButtonX = ToId(parser.Value("Controls_Right_JoyConController_Button_X")),
+ ButtonY = ToId(parser.Value("Controls_Right_JoyConController_Button_Y")),
+ ButtonPlus = ToId(parser.Value("Controls_Right_JoyConController_Button_Plus")),
+ ButtonR = ToId(parser.Value("Controls_Right_JoyConController_Button_R")),
+ ButtonZr = ToId(parser.Value("Controls_Right_JoyConController_Button_ZR"))
});
}
- private static ControllerInputID ToID(string Key)
+ private static ControllerInputId ToId(string key)
{
- switch (Key.ToUpper())
+ switch (key.ToUpper())
{
- case "LSTICK": return ControllerInputID.LStick;
- case "DPADUP": return ControllerInputID.DPadUp;
- case "DPADDOWN": return ControllerInputID.DPadDown;
- case "DPADLEFT": return ControllerInputID.DPadLeft;
- case "DPADRIGHT": return ControllerInputID.DPadRight;
- case "BACK": return ControllerInputID.Back;
- case "LSHOULDER": return ControllerInputID.LShoulder;
- case "LTRIGGER": return ControllerInputID.LTrigger;
-
- case "RSTICK": return ControllerInputID.RStick;
- case "A": return ControllerInputID.A;
- case "B": return ControllerInputID.B;
- case "X": return ControllerInputID.X;
- case "Y": return ControllerInputID.Y;
- case "START": return ControllerInputID.Start;
- case "RSHOULDER": return ControllerInputID.RShoulder;
- case "RTRIGGER": return ControllerInputID.RTrigger;
-
- case "LJOYSTICK": return ControllerInputID.LJoystick;
- case "RJOYSTICK": return ControllerInputID.RJoystick;
-
- default: return ControllerInputID.Invalid;
+ case "LSTICK": return ControllerInputId.LStick;
+ case "DPADUP": return ControllerInputId.DPadUp;
+ case "DPADDOWN": return ControllerInputId.DPadDown;
+ case "DPADLEFT": return ControllerInputId.DPadLeft;
+ case "DPADRIGHT": return ControllerInputId.DPadRight;
+ case "BACK": return ControllerInputId.Back;
+ case "LSHOULDER": return ControllerInputId.LShoulder;
+ case "LTRIGGER": return ControllerInputId.LTrigger;
+
+ case "RSTICK": return ControllerInputId.RStick;
+ case "A": return ControllerInputId.A;
+ case "B": return ControllerInputId.B;
+ case "X": return ControllerInputId.X;
+ case "Y": return ControllerInputId.Y;
+ case "START": return ControllerInputId.Start;
+ case "RSHOULDER": return ControllerInputId.RShoulder;
+ case "RTRIGGER": return ControllerInputId.RTrigger;
+
+ case "LJOYSTICK": return ControllerInputId.LJoystick;
+ case "RJOYSTICK": return ControllerInputId.RJoystick;
+
+ default: return ControllerInputId.Invalid;
}
}
}
@@ -171,19 +171,19 @@ namespace Ryujinx
//https://stackoverflow.com/a/37772571
public class IniParser
{
- private readonly Dictionary<string, string> Values;
+ private readonly Dictionary<string, string> _values;
- public IniParser(string Path)
+ public IniParser(string path)
{
- Values = File.ReadLines(Path)
- .Where(Line => !string.IsNullOrWhiteSpace(Line) && !Line.StartsWith('#'))
- .Select(Line => Line.Split('=', 2))
- .ToDictionary(Parts => Parts[0].Trim(), Parts => Parts.Length > 1 ? Parts[1].Trim() : null);
+ _values = File.ReadLines(path)
+ .Where(line => !string.IsNullOrWhiteSpace(line) && !line.StartsWith('#'))
+ .Select(line => line.Split('=', 2))
+ .ToDictionary(parts => parts[0].Trim(), parts => parts.Length > 1 ? parts[1].Trim() : null);
}
- public string Value(string Name)
+ public string Value(string name)
{
- return Values.TryGetValue(Name, out string Value) ? Value : null;
+ return _values.TryGetValue(name, out string value) ? value : null;
}
}
} \ No newline at end of file
diff --git a/Ryujinx/Ui/ConsoleLog.cs b/Ryujinx/Ui/ConsoleLog.cs
index 5ae13817..1ecd4cde 100644
--- a/Ryujinx/Ui/ConsoleLog.cs
+++ b/Ryujinx/Ui/ConsoleLog.cs
@@ -8,17 +8,17 @@ namespace Ryujinx
{
static class ConsoleLog
{
- private static Thread MessageThread;
+ private static Thread _messageThread;
- private static BlockingCollection<LogEventArgs> MessageQueue;
+ private static BlockingCollection<LogEventArgs> _messageQueue;
- private static Dictionary<LogLevel, ConsoleColor> LogColors;
+ private static Dictionary<LogLevel, ConsoleColor> _logColors;
- private static object ConsoleLock;
+ private static object _consoleLock;
static ConsoleLog()
{
- LogColors = new Dictionary<LogLevel, ConsoleColor>()
+ _logColors = new Dictionary<LogLevel, ConsoleColor>()
{
{ LogLevel.Stub, ConsoleColor.DarkGray },
{ LogLevel.Info, ConsoleColor.White },
@@ -26,17 +26,17 @@ namespace Ryujinx
{ LogLevel.Error, ConsoleColor.Red }
};
- MessageQueue = new BlockingCollection<LogEventArgs>();
+ _messageQueue = new BlockingCollection<LogEventArgs>();
- ConsoleLock = new object();
+ _consoleLock = new object();
- MessageThread = new Thread(() =>
+ _messageThread = new Thread(() =>
{
- while (!MessageQueue.IsCompleted)
+ while (!_messageQueue.IsCompleted)
{
try
{
- PrintLog(MessageQueue.Take());
+ PrintLog(_messageQueue.Take());
}
catch (InvalidOperationException)
{
@@ -49,39 +49,39 @@ namespace Ryujinx
}
});
- MessageThread.IsBackground = true;
- MessageThread.Start();
+ _messageThread.IsBackground = true;
+ _messageThread.Start();
}
private static void PrintLog(LogEventArgs e)
{
- string FormattedTime = e.Time.ToString(@"hh\:mm\:ss\.fff");
+ string formattedTime = e.Time.ToString(@"hh\:mm\:ss\.fff");
- string CurrentThread = Thread.CurrentThread.ManagedThreadId.ToString("d4");
+ string currentThread = Thread.CurrentThread.ManagedThreadId.ToString("d4");
- string Message = FormattedTime + " | " + CurrentThread + " " + e.Message;
+ string message = formattedTime + " | " + currentThread + " " + e.Message;
- if (LogColors.TryGetValue(e.Level, out ConsoleColor Color))
+ if (_logColors.TryGetValue(e.Level, out ConsoleColor color))
{
- lock (ConsoleLock)
+ lock (_consoleLock)
{
- Console.ForegroundColor = Color;
+ Console.ForegroundColor = color;
- Console.WriteLine(Message);
+ Console.WriteLine(message);
Console.ResetColor();
}
}
else
{
- Console.WriteLine(Message);
+ Console.WriteLine(message);
}
}
public static void Log(object sender, LogEventArgs e)
{
- if (!MessageQueue.IsAddingCompleted)
+ if (!_messageQueue.IsAddingCompleted)
{
- MessageQueue.Add(e);
+ _messageQueue.Add(e);
}
}
}
diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs
index 27f3f08b..a654d150 100644
--- a/Ryujinx/Ui/GLScreen.cs
+++ b/Ryujinx/Ui/GLScreen.cs
@@ -11,37 +11,37 @@ using Stopwatch = System.Diagnostics.Stopwatch;
namespace Ryujinx
{
- public class GLScreen : GameWindow
+ public class GlScreen : GameWindow
{
private const int TouchScreenWidth = 1280;
private const int TouchScreenHeight = 720;
- private const int TargetFPS = 60;
+ private const int TargetFps = 60;
- private Switch Device;
+ private Switch _device;
- private IGalRenderer Renderer;
+ private IGalRenderer _renderer;
- private KeyboardState? Keyboard = null;
+ private KeyboardState? _keyboard = null;
- private MouseState? Mouse = null;
+ private MouseState? _mouse = null;
- private Thread RenderThread;
+ private Thread _renderThread;
- private bool ResizeEvent;
+ private bool _resizeEvent;
- private bool TitleEvent;
+ private bool _titleEvent;
- private string NewTitle;
+ private string _newTitle;
- public GLScreen(Switch Device, IGalRenderer Renderer)
+ public GlScreen(Switch device, IGalRenderer renderer)
: base(1280, 720,
new GraphicsMode(), "Ryujinx", 0,
DisplayDevice.Default, 3, 3,
GraphicsContextFlags.ForwardCompatible)
{
- this.Device = Device;
- this.Renderer = Renderer;
+ _device = device;
+ _renderer = renderer;
Location = new Point(
(DisplayDevice.Default.Width / 2) - (Width / 2),
@@ -52,40 +52,40 @@ namespace Ryujinx
{
MakeCurrent();
- Stopwatch Chrono = new Stopwatch();
+ Stopwatch chrono = new Stopwatch();
- Chrono.Start();
+ chrono.Start();
- long TicksPerFrame = Stopwatch.Frequency / TargetFPS;
+ long ticksPerFrame = Stopwatch.Frequency / TargetFps;
- long Ticks = 0;
+ long ticks = 0;
while (Exists && !IsExiting)
{
- if (Device.WaitFifo())
+ if (_device.WaitFifo())
{
- Device.ProcessFrame();
+ _device.ProcessFrame();
}
- Renderer.RunActions();
+ _renderer.RunActions();
- if (ResizeEvent)
+ if (_resizeEvent)
{
- ResizeEvent = false;
+ _resizeEvent = false;
- Renderer.RenderTarget.SetWindowSize(Width, Height);
+ _renderer.RenderTarget.SetWindowSize(Width, Height);
}
- Ticks += Chrono.ElapsedTicks;
+ ticks += chrono.ElapsedTicks;
- Chrono.Restart();
+ chrono.Restart();
- if (Ticks >= TicksPerFrame)
+ if (ticks >= ticksPerFrame)
{
RenderFrame();
//Queue max. 1 vsync
- Ticks = Math.Min(Ticks - TicksPerFrame, TicksPerFrame);
+ ticks = Math.Min(ticks - ticksPerFrame, ticksPerFrame);
}
}
}
@@ -96,14 +96,14 @@ namespace Ryujinx
Visible = true;
- Renderer.RenderTarget.SetWindowSize(Width, Height);
+ _renderer.RenderTarget.SetWindowSize(Width, Height);
Context.MakeCurrent(null);
//OpenTK doesn't like sleeps in its thread, to avoid this a renderer thread is created
- RenderThread = new Thread(RenderLoop);
+ _renderThread = new Thread(RenderLoop);
- RenderThread.Start();
+ _renderThread.Start();
while (Exists && !IsExiting)
{
@@ -113,11 +113,11 @@ namespace Ryujinx
{
UpdateFrame();
- if (TitleEvent)
+ if (_titleEvent)
{
- TitleEvent = false;
+ _titleEvent = false;
- Title = NewTitle;
+ Title = _newTitle;
}
}
@@ -128,94 +128,94 @@ namespace Ryujinx
private new void UpdateFrame()
{
- HidControllerButtons CurrentButton = 0;
- HidJoystickPosition LeftJoystick;
- HidJoystickPosition RightJoystick;
+ HidControllerButtons currentButton = 0;
+ HidJoystickPosition leftJoystick;
+ HidJoystickPosition rightJoystick;
- int LeftJoystickDX = 0;
- int LeftJoystickDY = 0;
- int RightJoystickDX = 0;
- int RightJoystickDY = 0;
+ int leftJoystickDx = 0;
+ int leftJoystickDy = 0;
+ int rightJoystickDx = 0;
+ int rightJoystickDy = 0;
//Keyboard Input
- if (Keyboard.HasValue)
+ if (_keyboard.HasValue)
{
- KeyboardState Keyboard = this.Keyboard.Value;
+ KeyboardState keyboard = _keyboard.Value;
- CurrentButton = Config.JoyConKeyboard.GetButtons(Keyboard);
+ currentButton = Config.JoyConKeyboard.GetButtons(keyboard);
- (LeftJoystickDX, LeftJoystickDY) = Config.JoyConKeyboard.GetLeftStick(Keyboard);
+ (leftJoystickDx, leftJoystickDy) = Config.JoyConKeyboard.GetLeftStick(keyboard);
- (RightJoystickDX, RightJoystickDY) = Config.JoyConKeyboard.GetRightStick(Keyboard);
+ (rightJoystickDx, rightJoystickDy) = Config.JoyConKeyboard.GetRightStick(keyboard);
}
//Controller Input
- CurrentButton |= Config.JoyConController.GetButtons();
+ currentButton |= Config.JoyConController.GetButtons();
//Keyboard has priority stick-wise
- if (LeftJoystickDX == 0 && LeftJoystickDY == 0)
+ if (leftJoystickDx == 0 && leftJoystickDy == 0)
{
- (LeftJoystickDX, LeftJoystickDY) = Config.JoyConController.GetLeftStick();
+ (leftJoystickDx, leftJoystickDy) = Config.JoyConController.GetLeftStick();
}
- if (RightJoystickDX == 0 && RightJoystickDY == 0)
+ if (rightJoystickDx == 0 && rightJoystickDy == 0)
{
- (RightJoystickDX, RightJoystickDY) = Config.JoyConController.GetRightStick();
+ (rightJoystickDx, rightJoystickDy) = Config.JoyConController.GetRightStick();
}
- LeftJoystick = new HidJoystickPosition
+ leftJoystick = new HidJoystickPosition
{
- DX = LeftJoystickDX,
- DY = LeftJoystickDY
+ DX = leftJoystickDx,
+ DY = leftJoystickDy
};
- RightJoystick = new HidJoystickPosition
+ rightJoystick = new HidJoystickPosition
{
- DX = RightJoystickDX,
- DY = RightJoystickDY
+ DX = rightJoystickDx,
+ DY = rightJoystickDy
};
- bool HasTouch = false;
+ bool hasTouch = false;
//Get screen touch position from left mouse click
//OpenTK always captures mouse events, even if out of focus, so check if window is focused.
- if (Focused && Mouse?.LeftButton == ButtonState.Pressed)
+ if (Focused && _mouse?.LeftButton == ButtonState.Pressed)
{
- MouseState Mouse = this.Mouse.Value;
+ MouseState mouse = _mouse.Value;
- int ScrnWidth = Width;
- int ScrnHeight = Height;
+ int scrnWidth = Width;
+ int scrnHeight = Height;
if (Width > (Height * TouchScreenWidth) / TouchScreenHeight)
{
- ScrnWidth = (Height * TouchScreenWidth) / TouchScreenHeight;
+ scrnWidth = (Height * TouchScreenWidth) / TouchScreenHeight;
}
else
{
- ScrnHeight = (Width * TouchScreenHeight) / TouchScreenWidth;
+ scrnHeight = (Width * TouchScreenHeight) / TouchScreenWidth;
}
- int StartX = (Width - ScrnWidth) >> 1;
- int StartY = (Height - ScrnHeight) >> 1;
+ int startX = (Width - scrnWidth) >> 1;
+ int startY = (Height - scrnHeight) >> 1;
- int EndX = StartX + ScrnWidth;
- int EndY = StartY + ScrnHeight;
+ int endX = startX + scrnWidth;
+ int endY = startY + scrnHeight;
- if (Mouse.X >= StartX &&
- Mouse.Y >= StartY &&
- Mouse.X < EndX &&
- Mouse.Y < EndY)
+ if (mouse.X >= startX &&
+ mouse.Y >= startY &&
+ mouse.X < endX &&
+ mouse.Y < endY)
{
- int ScrnMouseX = Mouse.X - StartX;
- int ScrnMouseY = Mouse.Y - StartY;
+ int scrnMouseX = mouse.X - startX;
+ int scrnMouseY = mouse.Y - startY;
- int MX = (ScrnMouseX * TouchScreenWidth) / ScrnWidth;
- int MY = (ScrnMouseY * TouchScreenHeight) / ScrnHeight;
+ int mX = (scrnMouseX * TouchScreenWidth) / scrnWidth;
+ int mY = (scrnMouseY * TouchScreenHeight) / scrnHeight;
- HidTouchPoint CurrentPoint = new HidTouchPoint
+ HidTouchPoint currentPoint = new HidTouchPoint
{
- X = MX,
- Y = MY,
+ X = mX,
+ Y = mY,
//Placeholder values till more data is acquired
DiameterX = 10,
@@ -223,76 +223,76 @@ namespace Ryujinx
Angle = 90
};
- HasTouch = true;
+ hasTouch = true;
- Device.Hid.SetTouchPoints(CurrentPoint);
+ _device.Hid.SetTouchPoints(currentPoint);
}
}
- if (!HasTouch)
+ if (!hasTouch)
{
- Device.Hid.SetTouchPoints();
+ _device.Hid.SetTouchPoints();
}
- Device.Hid.SetJoyconButton(
+ _device.Hid.SetJoyconButton(
HidControllerId.CONTROLLER_HANDHELD,
HidControllerLayouts.Handheld_Joined,
- CurrentButton,
- LeftJoystick,
- RightJoystick);
+ currentButton,
+ leftJoystick,
+ rightJoystick);
- Device.Hid.SetJoyconButton(
+ _device.Hid.SetJoyconButton(
HidControllerId.CONTROLLER_HANDHELD,
HidControllerLayouts.Main,
- CurrentButton,
- LeftJoystick,
- RightJoystick);
+ currentButton,
+ leftJoystick,
+ rightJoystick);
}
private new void RenderFrame()
{
- Renderer.RenderTarget.Render();
+ _renderer.RenderTarget.Render();
- Device.Statistics.RecordSystemFrameTime();
+ _device.Statistics.RecordSystemFrameTime();
- double HostFps = Device.Statistics.GetSystemFrameRate();
- double GameFps = Device.Statistics.GetGameFrameRate();
+ double hostFps = _device.Statistics.GetSystemFrameRate();
+ double gameFps = _device.Statistics.GetGameFrameRate();
- string TitleSection = string.IsNullOrWhiteSpace(Device.System.CurrentTitle) ? string.Empty
- : " | " + Device.System.CurrentTitle;
+ string titleSection = string.IsNullOrWhiteSpace(_device.System.CurrentTitle) ? string.Empty
+ : " | " + _device.System.CurrentTitle;
- NewTitle = $"Ryujinx{TitleSection} | Host FPS: {HostFps:0.0} | Game FPS: {GameFps:0.0} | " +
- $"Game Vsync: {(Device.EnableDeviceVsync ? "On" : "Off")}";
+ _newTitle = $"Ryujinx{titleSection} | Host FPS: {hostFps:0.0} | Game FPS: {gameFps:0.0} | " +
+ $"Game Vsync: {(_device.EnableDeviceVsync ? "On" : "Off")}";
- TitleEvent = true;
+ _titleEvent = true;
SwapBuffers();
- Device.System.SignalVsync();
+ _device.System.SignalVsync();
- Device.VsyncEvent.Set();
+ _device.VsyncEvent.Set();
}
protected override void OnUnload(EventArgs e)
{
- RenderThread.Join();
+ _renderThread.Join();
base.OnUnload(e);
}
protected override void OnResize(EventArgs e)
{
- ResizeEvent = true;
+ _resizeEvent = true;
}
protected override void OnKeyDown(KeyboardKeyEventArgs e)
{
- bool ToggleFullscreen = e.Key == Key.F11 ||
+ bool toggleFullscreen = e.Key == Key.F11 ||
(e.Modifiers.HasFlag(KeyModifiers.Alt) && e.Key == Key.Enter);
if (WindowState == WindowState.Fullscreen)
{
- if (e.Key == Key.Escape || ToggleFullscreen)
+ if (e.Key == Key.Escape || toggleFullscreen)
{
WindowState = WindowState.Normal;
}
@@ -304,33 +304,33 @@ namespace Ryujinx
Exit();
}
- if (ToggleFullscreen)
+ if (toggleFullscreen)
{
WindowState = WindowState.Fullscreen;
}
}
- Keyboard = e.Keyboard;
+ _keyboard = e.Keyboard;
}
protected override void OnKeyUp(KeyboardKeyEventArgs e)
{
- Keyboard = e.Keyboard;
+ _keyboard = e.Keyboard;
}
protected override void OnMouseDown(MouseButtonEventArgs e)
{
- Mouse = e.Mouse;
+ _mouse = e.Mouse;
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
- Mouse = e.Mouse;
+ _mouse = e.Mouse;
}
protected override void OnMouseMove(MouseMoveEventArgs e)
{
- Mouse = e.Mouse;
+ _mouse = e.Mouse;
}
}
} \ No newline at end of file
diff --git a/Ryujinx/Ui/JoyConController.cs b/Ryujinx/Ui/JoyConController.cs
index aac8efd7..28b631b2 100644
--- a/Ryujinx/Ui/JoyConController.cs
+++ b/Ryujinx/Ui/JoyConController.cs
@@ -5,7 +5,7 @@ using System;
namespace Ryujinx.UI.Input
{
- public enum ControllerInputID
+ public enum ControllerInputId
{
Invalid,
@@ -34,28 +34,28 @@ namespace Ryujinx.UI.Input
public struct JoyConControllerLeft
{
- public ControllerInputID Stick;
- public ControllerInputID StickButton;
- public ControllerInputID DPadUp;
- public ControllerInputID DPadDown;
- public ControllerInputID DPadLeft;
- public ControllerInputID DPadRight;
- public ControllerInputID ButtonMinus;
- public ControllerInputID ButtonL;
- public ControllerInputID ButtonZL;
+ public ControllerInputId Stick;
+ public ControllerInputId StickButton;
+ public ControllerInputId DPadUp;
+ public ControllerInputId DPadDown;
+ public ControllerInputId DPadLeft;
+ public ControllerInputId DPadRight;
+ public ControllerInputId ButtonMinus;
+ public ControllerInputId ButtonL;
+ public ControllerInputId ButtonZl;
}
public struct JoyConControllerRight
{
- public ControllerInputID Stick;
- public ControllerInputID StickButton;
- public ControllerInputID ButtonA;
- public ControllerInputID ButtonB;
- public ControllerInputID ButtonX;
- public ControllerInputID ButtonY;
- public ControllerInputID ButtonPlus;
- public ControllerInputID ButtonR;
- public ControllerInputID ButtonZR;
+ public ControllerInputId Stick;
+ public ControllerInputId StickButton;
+ public ControllerInputId ButtonA;
+ public ControllerInputId ButtonB;
+ public ControllerInputId ButtonX;
+ public ControllerInputId ButtonY;
+ public ControllerInputId ButtonPlus;
+ public ControllerInputId ButtonR;
+ public ControllerInputId ButtonZr;
}
public class JoyConController
@@ -69,24 +69,24 @@ namespace Ryujinx.UI.Input
public JoyConControllerRight Right { private set; get; }
public JoyConController(
- bool Enabled,
- int Index,
- float Deadzone,
- float TriggerThreshold,
- JoyConControllerLeft Left,
- JoyConControllerRight Right)
+ bool enabled,
+ int index,
+ float deadzone,
+ float triggerThreshold,
+ JoyConControllerLeft left,
+ JoyConControllerRight right)
{
- this.Enabled = Enabled;
- this.Index = Index;
- this.Deadzone = Deadzone;
- this.TriggerThreshold = TriggerThreshold;
- this.Left = Left;
- this.Right = Right;
+ Enabled = enabled;
+ Index = index;
+ Deadzone = deadzone;
+ TriggerThreshold = triggerThreshold;
+ Left = left;
+ Right = right;
//Unmapped controllers are problematic, skip them
- if (GamePad.GetName(Index) == "Unmapped Controller")
+ if (GamePad.GetName(index) == "Unmapped Controller")
{
- this.Enabled = false;
+ Enabled = false;
}
}
@@ -97,29 +97,29 @@ namespace Ryujinx.UI.Input
return 0;
}
- GamePadState GpState = GamePad.GetState(Index);
-
- HidControllerButtons Buttons = 0;
-
- if (IsPressed(GpState, Left.DPadUp)) Buttons |= HidControllerButtons.KEY_DUP;
- if (IsPressed(GpState, Left.DPadDown)) Buttons |= HidControllerButtons.KEY_DDOWN;
- if (IsPressed(GpState, Left.DPadLeft)) Buttons |= HidControllerButtons.KEY_DLEFT;
- if (IsPressed(GpState, Left.DPadRight)) Buttons |= HidControllerButtons.KEY_DRIGHT;
- if (IsPressed(GpState, Left.StickButton)) Buttons |= HidControllerButtons.KEY_LSTICK;
- if (IsPressed(GpState, Left.ButtonMinus)) Buttons |= HidControllerButtons.KEY_MINUS;
- if (IsPressed(GpState, Left.ButtonL)) Buttons |= HidControllerButtons.KEY_L;
- if (IsPressed(GpState, Left.ButtonZL)) Buttons |= HidControllerButtons.KEY_ZL;
-
- if (IsPressed(GpState, Right.ButtonA)) Buttons |= HidControllerButtons.KEY_A;
- if (IsPressed(GpState, Right.ButtonB)) Buttons |= HidControllerButtons.KEY_B;
- if (IsPressed(GpState, Right.ButtonX)) Buttons |= HidControllerButtons.KEY_X;
- if (IsPressed(GpState, Right.ButtonY)) Buttons |= HidControllerButtons.KEY_Y;
- if (IsPressed(GpState, Right.StickButton)) Buttons |= HidControllerButtons.KEY_RSTICK;
- if (IsPressed(GpState, Right.ButtonPlus)) Buttons |= HidControllerButtons.KEY_PLUS;
- if (IsPressed(GpState, Right.ButtonR)) Buttons |= HidControllerButtons.KEY_R;
- if (IsPressed(GpState, Right.ButtonZR)) Buttons |= HidControllerButtons.KEY_ZR;
-
- return Buttons;
+ GamePadState gpState = GamePad.GetState(Index);
+
+ HidControllerButtons buttons = 0;
+
+ if (IsPressed(gpState, Left.DPadUp)) buttons |= HidControllerButtons.KEY_DUP;
+ if (IsPressed(gpState, Left.DPadDown)) buttons |= HidControllerButtons.KEY_DDOWN;
+ if (IsPressed(gpState, Left.DPadLeft)) buttons |= HidControllerButtons.KEY_DLEFT;
+ if (IsPressed(gpState, Left.DPadRight)) buttons |= HidControllerButtons.KEY_DRIGHT;
+ if (IsPressed(gpState, Left.StickButton)) buttons |= HidControllerButtons.KEY_LSTICK;
+ if (IsPressed(gpState, Left.ButtonMinus)) buttons |= HidControllerButtons.KEY_MINUS;
+ if (IsPressed(gpState, Left.ButtonL)) buttons |= HidControllerButtons.KEY_L;
+ if (IsPressed(gpState, Left.ButtonZl)) buttons |= HidControllerButtons.KEY_ZL;
+
+ if (IsPressed(gpState, Right.ButtonA)) buttons |= HidControllerButtons.KEY_A;
+ if (IsPressed(gpState, Right.ButtonB)) buttons |= HidControllerButtons.KEY_B;
+ if (IsPressed(gpState, Right.ButtonX)) buttons |= HidControllerButtons.KEY_X;
+ if (IsPressed(gpState, Right.ButtonY)) buttons |= HidControllerButtons.KEY_Y;
+ if (IsPressed(gpState, Right.StickButton)) buttons |= HidControllerButtons.KEY_RSTICK;
+ if (IsPressed(gpState, Right.ButtonPlus)) buttons |= HidControllerButtons.KEY_PLUS;
+ if (IsPressed(gpState, Right.ButtonR)) buttons |= HidControllerButtons.KEY_R;
+ if (IsPressed(gpState, Right.ButtonZr)) buttons |= HidControllerButtons.KEY_ZR;
+
+ return buttons;
}
public (short, short) GetLeftStick()
@@ -142,71 +142,71 @@ namespace Ryujinx.UI.Input
return GetStick(Right.Stick);
}
- private (short, short) GetStick(ControllerInputID Joystick)
+ private (short, short) GetStick(ControllerInputId joystick)
{
- GamePadState GpState = GamePad.GetState(Index);
+ GamePadState gpState = GamePad.GetState(Index);
- switch (Joystick)
+ switch (joystick)
{
- case ControllerInputID.LJoystick:
- return ApplyDeadzone(GpState.ThumbSticks.Left);
+ case ControllerInputId.LJoystick:
+ return ApplyDeadzone(gpState.ThumbSticks.Left);
- case ControllerInputID.RJoystick:
- return ApplyDeadzone(GpState.ThumbSticks.Right);
+ case ControllerInputId.RJoystick:
+ return ApplyDeadzone(gpState.ThumbSticks.Right);
default:
return (0, 0);
}
}
- private (short, short) ApplyDeadzone(Vector2 Axis)
+ private (short, short) ApplyDeadzone(Vector2 axis)
{
- return (ClampAxis(MathF.Abs(Axis.X) > Deadzone ? Axis.X : 0f),
- ClampAxis(MathF.Abs(Axis.Y) > Deadzone ? Axis.Y : 0f));
+ return (ClampAxis(MathF.Abs(axis.X) > Deadzone ? axis.X : 0f),
+ ClampAxis(MathF.Abs(axis.Y) > Deadzone ? axis.Y : 0f));
}
- private static short ClampAxis(float Value)
+ private static short ClampAxis(float value)
{
- if (Value <= -short.MaxValue)
+ if (value <= -short.MaxValue)
{
return -short.MaxValue;
}
else
{
- return (short)(Value * short.MaxValue);
+ return (short)(value * short.MaxValue);
}
}
- private bool IsPressed(GamePadState GpState, ControllerInputID Button)
+ private bool IsPressed(GamePadState gpState, ControllerInputId button)
{
- switch (Button)
+ switch (button)
{
- case ControllerInputID.A: return GpState.Buttons.A == ButtonState.Pressed;
- case ControllerInputID.B: return GpState.Buttons.B == ButtonState.Pressed;
- case ControllerInputID.X: return GpState.Buttons.X == ButtonState.Pressed;
- case ControllerInputID.Y: return GpState.Buttons.Y == ButtonState.Pressed;
- case ControllerInputID.LStick: return GpState.Buttons.LeftStick == ButtonState.Pressed;
- case ControllerInputID.RStick: return GpState.Buttons.RightStick == ButtonState.Pressed;
- case ControllerInputID.LShoulder: return GpState.Buttons.LeftShoulder == ButtonState.Pressed;
- case ControllerInputID.RShoulder: return GpState.Buttons.RightShoulder == ButtonState.Pressed;
- case ControllerInputID.DPadUp: return GpState.DPad.Up == ButtonState.Pressed;
- case ControllerInputID.DPadDown: return GpState.DPad.Down == ButtonState.Pressed;
- case ControllerInputID.DPadLeft: return GpState.DPad.Left == ButtonState.Pressed;
- case ControllerInputID.DPadRight: return GpState.DPad.Right == ButtonState.Pressed;
- case ControllerInputID.Start: return GpState.Buttons.Start == ButtonState.Pressed;
- case ControllerInputID.Back: return GpState.Buttons.Back == ButtonState.Pressed;
-
- case ControllerInputID.LTrigger: return GpState.Triggers.Left >= TriggerThreshold;
- case ControllerInputID.RTrigger: return GpState.Triggers.Right >= TriggerThreshold;
+ case ControllerInputId.A: return gpState.Buttons.A == ButtonState.Pressed;
+ case ControllerInputId.B: return gpState.Buttons.B == ButtonState.Pressed;
+ case ControllerInputId.X: return gpState.Buttons.X == ButtonState.Pressed;
+ case ControllerInputId.Y: return gpState.Buttons.Y == ButtonState.Pressed;
+ case ControllerInputId.LStick: return gpState.Buttons.LeftStick == ButtonState.Pressed;
+ case ControllerInputId.RStick: return gpState.Buttons.RightStick == ButtonState.Pressed;
+ case ControllerInputId.LShoulder: return gpState.Buttons.LeftShoulder == ButtonState.Pressed;
+ case ControllerInputId.RShoulder: return gpState.Buttons.RightShoulder == ButtonState.Pressed;
+ case ControllerInputId.DPadUp: return gpState.DPad.Up == ButtonState.Pressed;
+ case ControllerInputId.DPadDown: return gpState.DPad.Down == ButtonState.Pressed;
+ case ControllerInputId.DPadLeft: return gpState.DPad.Left == ButtonState.Pressed;
+ case ControllerInputId.DPadRight: return gpState.DPad.Right == ButtonState.Pressed;
+ case ControllerInputId.Start: return gpState.Buttons.Start == ButtonState.Pressed;
+ case ControllerInputId.Back: return gpState.Buttons.Back == ButtonState.Pressed;
+
+ case ControllerInputId.LTrigger: return gpState.Triggers.Left >= TriggerThreshold;
+ case ControllerInputId.RTrigger: return gpState.Triggers.Right >= TriggerThreshold;
//Using thumbsticks as buttons is not common, but it would be nice not to ignore them
- case ControllerInputID.LJoystick:
- return GpState.ThumbSticks.Left.X >= Deadzone ||
- GpState.ThumbSticks.Left.Y >= Deadzone;
+ case ControllerInputId.LJoystick:
+ return gpState.ThumbSticks.Left.X >= Deadzone ||
+ gpState.ThumbSticks.Left.Y >= Deadzone;
- case ControllerInputID.RJoystick:
- return GpState.ThumbSticks.Right.X >= Deadzone ||
- GpState.ThumbSticks.Right.Y >= Deadzone;
+ case ControllerInputId.RJoystick:
+ return gpState.ThumbSticks.Right.X >= Deadzone ||
+ gpState.ThumbSticks.Right.Y >= Deadzone;
default:
return false;
diff --git a/Ryujinx/Ui/JoyConKeyboard.cs b/Ryujinx/Ui/JoyConKeyboard.cs
index ea964553..fd399fe8 100644
--- a/Ryujinx/Ui/JoyConKeyboard.cs
+++ b/Ryujinx/Ui/JoyConKeyboard.cs
@@ -16,7 +16,7 @@ namespace Ryujinx.UI.Input
public int DPadRight;
public int ButtonMinus;
public int ButtonL;
- public int ButtonZL;
+ public int ButtonZl;
}
public struct JoyConKeyboardRight
@@ -32,7 +32,7 @@ namespace Ryujinx.UI.Input
public int ButtonY;
public int ButtonPlus;
public int ButtonR;
- public int ButtonZR;
+ public int ButtonZr;
}
public class JoyConKeyboard
@@ -41,62 +41,62 @@ namespace Ryujinx.UI.Input
public JoyConKeyboardRight Right;
public JoyConKeyboard(
- JoyConKeyboardLeft Left,
- JoyConKeyboardRight Right)
+ JoyConKeyboardLeft left,
+ JoyConKeyboardRight right)
{
- this.Left = Left;
- this.Right = Right;
+ Left = left;
+ Right = right;
}
- public HidControllerButtons GetButtons(KeyboardState Keyboard)
+ public HidControllerButtons GetButtons(KeyboardState keyboard)
{
- HidControllerButtons Buttons = 0;
+ HidControllerButtons buttons = 0;
- if (Keyboard[(Key)Left.StickButton]) Buttons |= HidControllerButtons.KEY_LSTICK;
- if (Keyboard[(Key)Left.DPadUp]) Buttons |= HidControllerButtons.KEY_DUP;
- if (Keyboard[(Key)Left.DPadDown]) Buttons |= HidControllerButtons.KEY_DDOWN;
- if (Keyboard[(Key)Left.DPadLeft]) Buttons |= HidControllerButtons.KEY_DLEFT;
- if (Keyboard[(Key)Left.DPadRight]) Buttons |= HidControllerButtons.KEY_DRIGHT;
- if (Keyboard[(Key)Left.ButtonMinus]) Buttons |= HidControllerButtons.KEY_MINUS;
- if (Keyboard[(Key)Left.ButtonL]) Buttons |= HidControllerButtons.KEY_L;
- if (Keyboard[(Key)Left.ButtonZL]) Buttons |= HidControllerButtons.KEY_ZL;
+ if (keyboard[(Key)Left.StickButton]) buttons |= HidControllerButtons.KEY_LSTICK;
+ if (keyboard[(Key)Left.DPadUp]) buttons |= HidControllerButtons.KEY_DUP;
+ if (keyboard[(Key)Left.DPadDown]) buttons |= HidControllerButtons.KEY_DDOWN;
+ if (keyboard[(Key)Left.DPadLeft]) buttons |= HidControllerButtons.KEY_DLEFT;
+ if (keyboard[(Key)Left.DPadRight]) buttons |= HidControllerButtons.KEY_DRIGHT;
+ if (keyboard[(Key)Left.ButtonMinus]) buttons |= HidControllerButtons.KEY_MINUS;
+ if (keyboard[(Key)Left.ButtonL]) buttons |= HidControllerButtons.KEY_L;
+ if (keyboard[(Key)Left.ButtonZl]) buttons |= HidControllerButtons.KEY_ZL;
- if (Keyboard[(Key)Right.StickButton]) Buttons |= HidControllerButtons.KEY_RSTICK;
- if (Keyboard[(Key)Right.ButtonA]) Buttons |= HidControllerButtons.KEY_A;
- if (Keyboard[(Key)Right.ButtonB]) Buttons |= HidControllerButtons.KEY_B;
- if (Keyboard[(Key)Right.ButtonX]) Buttons |= HidControllerButtons.KEY_X;
- if (Keyboard[(Key)Right.ButtonY]) Buttons |= HidControllerButtons.KEY_Y;
- if (Keyboard[(Key)Right.ButtonPlus]) Buttons |= HidControllerButtons.KEY_PLUS;
- if (Keyboard[(Key)Right.ButtonR]) Buttons |= HidControllerButtons.KEY_R;
- if (Keyboard[(Key)Right.ButtonZR]) Buttons |= HidControllerButtons.KEY_ZR;
+ if (keyboard[(Key)Right.StickButton]) buttons |= HidControllerButtons.KEY_RSTICK;
+ if (keyboard[(Key)Right.ButtonA]) buttons |= HidControllerButtons.KEY_A;
+ if (keyboard[(Key)Right.ButtonB]) buttons |= HidControllerButtons.KEY_B;
+ if (keyboard[(Key)Right.ButtonX]) buttons |= HidControllerButtons.KEY_X;
+ if (keyboard[(Key)Right.ButtonY]) buttons |= HidControllerButtons.KEY_Y;
+ if (keyboard[(Key)Right.ButtonPlus]) buttons |= HidControllerButtons.KEY_PLUS;
+ if (keyboard[(Key)Right.ButtonR]) buttons |= HidControllerButtons.KEY_R;
+ if (keyboard[(Key)Right.ButtonZr]) buttons |= HidControllerButtons.KEY_ZR;
- return Buttons;
+ return buttons;
}
- public (short, short) GetLeftStick(KeyboardState Keyboard)
+ public (short, short) GetLeftStick(KeyboardState keyboard)
{
- short DX = 0;
- short DY = 0;
+ short dx = 0;
+ short dy = 0;
- if (Keyboard[(Key)Left.StickUp]) DY = short.MaxValue;
- if (Keyboard[(Key)Left.StickDown]) DY = -short.MaxValue;
- if (Keyboard[(Key)Left.StickLeft]) DX = -short.MaxValue;
- if (Keyboard[(Key)Left.StickRight]) DX = short.MaxValue;
+ if (keyboard[(Key)Left.StickUp]) dy = short.MaxValue;
+ if (keyboard[(Key)Left.StickDown]) dy = -short.MaxValue;
+ if (keyboard[(Key)Left.StickLeft]) dx = -short.MaxValue;
+ if (keyboard[(Key)Left.StickRight]) dx = short.MaxValue;
- return (DX, DY);
+ return (dx, dy);
}
- public (short, short) GetRightStick(KeyboardState Keyboard)
+ public (short, short) GetRightStick(KeyboardState keyboard)
{
- short DX = 0;
- short DY = 0;
+ short dx = 0;
+ short dy = 0;
- if (Keyboard[(Key)Right.StickUp]) DY = short.MaxValue;
- if (Keyboard[(Key)Right.StickDown]) DY = -short.MaxValue;
- if (Keyboard[(Key)Right.StickLeft]) DX = -short.MaxValue;
- if (Keyboard[(Key)Right.StickRight]) DX = short.MaxValue;
+ if (keyboard[(Key)Right.StickUp]) dy = short.MaxValue;
+ if (keyboard[(Key)Right.StickDown]) dy = -short.MaxValue;
+ if (keyboard[(Key)Right.StickLeft]) dx = -short.MaxValue;
+ if (keyboard[(Key)Right.StickRight]) dx = short.MaxValue;
- return (DX, DY);
+ return (dx, dy);
}
}
}
diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs
index 145ff33f..4edf6e47 100644
--- a/Ryujinx/Ui/Program.cs
+++ b/Ryujinx/Ui/Program.cs
@@ -15,13 +15,13 @@ namespace Ryujinx
{
Console.Title = "Ryujinx Console";
- IGalRenderer Renderer = new OGLRenderer();
+ IGalRenderer renderer = new OGLRenderer();
- IAalOutput AudioOut = new OpenALAudioOut();
+ IAalOutput audioOut = new OpenALAudioOut();
- Switch Device = new Switch(Renderer, AudioOut);
+ Switch device = new Switch(renderer, audioOut);
- Config.Read(Device);
+ Config.Read(device);
Logger.Updated += ConsoleLog.Log;
@@ -29,24 +29,24 @@ namespace Ryujinx
{
if (Directory.Exists(args[0]))
{
- string[] RomFsFiles = Directory.GetFiles(args[0], "*.istorage");
+ string[] romFsFiles = Directory.GetFiles(args[0], "*.istorage");
- if (RomFsFiles.Length == 0)
+ if (romFsFiles.Length == 0)
{
- RomFsFiles = Directory.GetFiles(args[0], "*.romfs");
+ romFsFiles = Directory.GetFiles(args[0], "*.romfs");
}
- if (RomFsFiles.Length > 0)
+ if (romFsFiles.Length > 0)
{
Console.WriteLine("Loading as cart with RomFS.");
- Device.LoadCart(args[0], RomFsFiles[0]);
+ device.LoadCart(args[0], romFsFiles[0]);
}
else
{
Console.WriteLine("Loading as cart WITHOUT RomFS.");
- Device.LoadCart(args[0]);
+ device.LoadCart(args[0]);
}
}
else if (File.Exists(args[0]))
@@ -55,19 +55,19 @@ namespace Ryujinx
{
case ".xci":
Console.WriteLine("Loading as XCI.");
- Device.LoadXci(args[0]);
+ device.LoadXci(args[0]);
break;
case ".nca":
Console.WriteLine("Loading as NCA.");
- Device.LoadNca(args[0]);
+ device.LoadNca(args[0]);
break;
case ".nsp":
Console.WriteLine("Loading as NSP.");
- Device.LoadNsp(args[0]);
+ device.LoadNsp(args[0]);
break;
default:
Console.WriteLine("Loading as homebrew.");
- Device.LoadProgram(args[0]);
+ device.LoadProgram(args[0]);
break;
}
}
@@ -77,14 +77,14 @@ namespace Ryujinx
Console.WriteLine("Please specify the folder with the NSOs/IStorage or a NSO/NRO.");
}
- using (GLScreen Screen = new GLScreen(Device, Renderer))
+ using (GlScreen screen = new GlScreen(device, renderer))
{
- Screen.MainLoop();
+ screen.MainLoop();
- Device.Dispose();
+ device.Dispose();
}
- AudioOut.Dispose();
+ audioOut.Dispose();
}
}
}