From 9cb57fb4bb3bbae0ae052a5af4a96a49fc5d864d Mon Sep 17 00:00:00 2001
From: Alex Barney <thealexbarney@gmail.com>
Date: Tue, 30 Oct 2018 19:43:02 -0600
Subject: [PATCH] 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
---
 ChocolArm64/ABitUtils.cs                      |   49 -
 ChocolArm64/AOpCodeTable.cs                   |  713 -----
 ChocolArm64/AOptimizations.cs                 |   18 -
 ChocolArm64/ATranslatedSub.cs                 |  150 --
 ChocolArm64/ATranslator.cs                    |  165 --
 ChocolArm64/ATranslatorCache.cs               |  165 --
 ChocolArm64/BitUtils.cs                       |   49 +
 ChocolArm64/{AThread.cs => CpuThread.cs}      |   26 +-
 ChocolArm64/Decoder/ABlock.cs                 |   35 -
 ChocolArm64/Decoder/ACond.cs                  |   22 -
 ChocolArm64/Decoder/ADecoder.cs               |  239 --
 ChocolArm64/Decoder/ADecoderHelper.cs         |  107 -
 ChocolArm64/Decoder/AOpCode.cs                |   40 -
 ChocolArm64/Decoder/AOpCodeAdr.cs             |   18 -
 ChocolArm64/Decoder/AOpCodeAlu.cs             |   24 -
 ChocolArm64/Decoder/AOpCodeAluImm.cs          |   39 -
 ChocolArm64/Decoder/AOpCodeAluRs.cs           |   29 -
 ChocolArm64/Decoder/AOpCodeAluRx.cs           |   19 -
 ChocolArm64/Decoder/AOpCodeBImm.cs            |   11 -
 ChocolArm64/Decoder/AOpCodeBImmAl.cs          |   12 -
 ChocolArm64/Decoder/AOpCodeBImmCmp.cs         |   21 -
 ChocolArm64/Decoder/AOpCodeBImmCond.cs        |   25 -
 ChocolArm64/Decoder/AOpCodeBImmTest.cs        |   20 -
 ChocolArm64/Decoder/AOpCodeBReg.cs            |   24 -
 ChocolArm64/Decoder/AOpCodeBfm.cs             |   29 -
 ChocolArm64/Decoder/AOpCodeCcmp.cs            |   31 -
 ChocolArm64/Decoder/AOpCodeCcmpImm.cs         |   11 -
 ChocolArm64/Decoder/AOpCodeCcmpReg.cs         |   15 -
 ChocolArm64/Decoder/AOpCodeCsel.cs            |   17 -
 ChocolArm64/Decoder/AOpCodeException.cs       |   14 -
 ChocolArm64/Decoder/AOpCodeMem.cs             |   19 -
 ChocolArm64/Decoder/AOpCodeMemEx.cs           |   16 -
 ChocolArm64/Decoder/AOpCodeMemPair.cs         |   25 -
 ChocolArm64/Decoder/AOpCodeMemReg.cs          |   20 -
 ChocolArm64/Decoder/AOpCodeMov.cs             |   36 -
 ChocolArm64/Decoder/AOpCodeMul.cs             |   16 -
 ChocolArm64/Decoder/AOpCodeSimd.cs            |   25 -
 ChocolArm64/Decoder/AOpCodeSimdCvt.cs         |   31 -
 ChocolArm64/Decoder/AOpCodeSimdExt.cs         |   14 -
 ChocolArm64/Decoder/AOpCodeSimdFcond.cs       |   17 -
 ChocolArm64/Decoder/AOpCodeSimdFmov.cs        |   33 -
 ChocolArm64/Decoder/AOpCodeSimdImm.cs         |  101 -
 ChocolArm64/Decoder/AOpCodeSimdIns.cs         |   36 -
 ChocolArm64/Decoder/AOpCodeSimdMemImm.cs      |   19 -
 ChocolArm64/Decoder/AOpCodeSimdMemLit.cs      |   31 -
 ChocolArm64/Decoder/AOpCodeSimdMemPair.cs     |   16 -
 ChocolArm64/Decoder/AOpCodeSimdMemReg.cs      |   14 -
 ChocolArm64/Decoder/AOpCodeSimdMemSs.cs       |   98 -
 ChocolArm64/Decoder/AOpCodeSimdReg.cs         |   18 -
 ChocolArm64/Decoder/AOpCodeSimdRegElem.cs     |   31 -
 ChocolArm64/Decoder/AOpCodeSimdRegElemF.cs    |   33 -
 ChocolArm64/Decoder/AOpCodeSimdShImm.cs       |   16 -
 ChocolArm64/Decoder/AOpCodeSimdTbl.cs         |   12 -
 ChocolArm64/Decoder/AOpCodeSystem.cs          |   24 -
 ChocolArm64/Decoder/IAOpCode.cs               |   13 -
 ChocolArm64/Decoder/IAOpCodeAlu.cs            |   10 -
 ChocolArm64/Decoder/IAOpCodeAluImm.cs         |    7 -
 ChocolArm64/Decoder/IAOpCodeAluRs.cs          |   10 -
 ChocolArm64/Decoder/IAOpCodeAluRx.cs          |   10 -
 ChocolArm64/Decoder/IAOpCodeCond.cs           |    7 -
 ChocolArm64/Decoder/IAOpCodeSimd.cs           |    7 -
 ChocolArm64/Decoder32/A32OpCode.cs            |   15 -
 ChocolArm64/Decoder32/A32OpCodeBImmAl.cs      |   16 -
 ChocolArm64/Decoders/Block.cs                 |   35 +
 ChocolArm64/Decoders/Cond.cs                  |   22 +
 .../ADataOp.cs => Decoders/DataOp.cs}         |    4 +-
 ChocolArm64/Decoders/Decoder.cs               |  239 ++
 ChocolArm64/Decoders/DecoderHelper.cs         |  107 +
 ChocolArm64/Decoders/IOpCode64.cs             |   13 +
 ChocolArm64/Decoders/IOpCodeAlu64.cs          |   10 +
 ChocolArm64/Decoders/IOpCodeAluImm64.cs       |    7 +
 ChocolArm64/Decoders/IOpCodeAluRs64.cs        |   10 +
 ChocolArm64/Decoders/IOpCodeAluRx64.cs        |   10 +
 ChocolArm64/Decoders/IOpCodeCond64.cs         |    7 +
 .../IOpCodeLit64.cs}                          |    4 +-
 ChocolArm64/Decoders/IOpCodeSimd64.cs         |    7 +
 .../AIntType.cs => Decoders/IntType.cs}       |    4 +-
 ChocolArm64/Decoders/OpCode64.cs              |   40 +
 ChocolArm64/Decoders/OpCodeAdr64.cs           |   18 +
 ChocolArm64/Decoders/OpCodeAlu64.cs           |   24 +
 ChocolArm64/Decoders/OpCodeAluImm64.cs        |   39 +
 ChocolArm64/Decoders/OpCodeAluRs64.cs         |   29 +
 ChocolArm64/Decoders/OpCodeAluRx64.cs         |   19 +
 ChocolArm64/Decoders/OpCodeBImm64.cs          |   11 +
 ChocolArm64/Decoders/OpCodeBImmAl64.cs        |   12 +
 ChocolArm64/Decoders/OpCodeBImmCmp64.cs       |   21 +
 ChocolArm64/Decoders/OpCodeBImmCond64.cs      |   25 +
 ChocolArm64/Decoders/OpCodeBImmTest64.cs      |   20 +
 ChocolArm64/Decoders/OpCodeBReg64.cs          |   24 +
 ChocolArm64/Decoders/OpCodeBfm64.cs           |   29 +
 ChocolArm64/Decoders/OpCodeCcmp64.cs          |   31 +
 ChocolArm64/Decoders/OpCodeCcmpImm64.cs       |   11 +
 ChocolArm64/Decoders/OpCodeCcmpReg64.cs       |   15 +
 ChocolArm64/Decoders/OpCodeCsel64.cs          |   17 +
 ChocolArm64/Decoders/OpCodeException64.cs     |   14 +
 ChocolArm64/Decoders/OpCodeMem64.cs           |   19 +
 ChocolArm64/Decoders/OpCodeMemEx64.cs         |   16 +
 .../OpCodeMemImm64.cs}                        |   24 +-
 .../OpCodeMemLit64.cs}                        |   14 +-
 ChocolArm64/Decoders/OpCodeMemPair64.cs       |   25 +
 ChocolArm64/Decoders/OpCodeMemReg64.cs        |   20 +
 ChocolArm64/Decoders/OpCodeMov64.cs           |   36 +
 ChocolArm64/Decoders/OpCodeMul64.cs           |   16 +
 ChocolArm64/Decoders/OpCodeSimd64.cs          |   25 +
 ChocolArm64/Decoders/OpCodeSimdCvt64.cs       |   31 +
 ChocolArm64/Decoders/OpCodeSimdExt64.cs       |   14 +
 ChocolArm64/Decoders/OpCodeSimdFcond64.cs     |   17 +
 ChocolArm64/Decoders/OpCodeSimdFmov64.cs      |   33 +
 ChocolArm64/Decoders/OpCodeSimdImm64.cs       |  101 +
 ChocolArm64/Decoders/OpCodeSimdIns64.cs       |   36 +
 ChocolArm64/Decoders/OpCodeSimdMemImm64.cs    |   19 +
 ChocolArm64/Decoders/OpCodeSimdMemLit64.cs    |   31 +
 .../OpCodeSimdMemMs64.cs}                     |   28 +-
 ChocolArm64/Decoders/OpCodeSimdMemPair64.cs   |   16 +
 ChocolArm64/Decoders/OpCodeSimdMemReg64.cs    |   14 +
 ChocolArm64/Decoders/OpCodeSimdMemSs64.cs     |   98 +
 ChocolArm64/Decoders/OpCodeSimdReg64.cs       |   18 +
 ChocolArm64/Decoders/OpCodeSimdRegElem64.cs   |   31 +
 ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs  |   33 +
 ChocolArm64/Decoders/OpCodeSimdShImm64.cs     |   16 +
 ChocolArm64/Decoders/OpCodeSimdTbl64.cs       |   12 +
 ChocolArm64/Decoders/OpCodeSystem64.cs        |   24 +
 .../AShiftType.cs => Decoders/ShiftType.cs}   |    4 +-
 ChocolArm64/Decoders32/A32OpCode.cs           |   15 +
 ChocolArm64/Decoders32/A32OpCodeBImmAl.cs     |   16 +
 ChocolArm64/Events/ACpuTraceEventArgs.cs      |   14 -
 ChocolArm64/Events/AInstExceptionEventArgs.cs |   16 -
 ChocolArm64/Events/AInstUndefinedEventArgs.cs |   16 -
 ChocolArm64/Events/AInvalidAccessEventArgs.cs |   14 -
 ChocolArm64/Events/CpuTraceEventArgs.cs       |   14 +
 ChocolArm64/Events/InstExceptionEventArgs.cs  |   16 +
 ChocolArm64/Events/InstUndefinedEventArgs.cs  |   16 +
 ChocolArm64/Events/InvalidAccessEventArgs.cs  |   14 +
 .../Exceptions/VmmOutOfMemoryException.cs     |    2 +-
 .../Exceptions/VmmPageFaultException.cs       |    2 +-
 ChocolArm64/Instruction/AInst.cs              |   20 -
 ChocolArm64/Instruction/AInstEmitAlu.cs       |  402 ---
 ChocolArm64/Instruction/AInstEmitAluHelper.cs |  212 --
 ChocolArm64/Instruction/AInstEmitBfm.cs       |  208 --
 ChocolArm64/Instruction/AInstEmitCcmp.cs      |   81 -
 ChocolArm64/Instruction/AInstEmitCsel.cs      |   58 -
 ChocolArm64/Instruction/AInstEmitException.cs |   86 -
 ChocolArm64/Instruction/AInstEmitFlow.cs      |  189 --
 ChocolArm64/Instruction/AInstEmitHash.cs      |  115 -
 ChocolArm64/Instruction/AInstEmitMemory.cs    |  252 --
 ChocolArm64/Instruction/AInstEmitMemoryEx.cs  |  192 --
 .../Instruction/AInstEmitMemoryHelper.cs      |  138 -
 ChocolArm64/Instruction/AInstEmitMove.cs      |   41 -
 ChocolArm64/Instruction/AInstEmitMul.cs       |   80 -
 .../Instruction/AInstEmitSimdArithmetic.cs    | 2387 -----------------
 ChocolArm64/Instruction/AInstEmitSimdCmp.cs   |  526 ----
 .../Instruction/AInstEmitSimdCrypto.cs        |   54 -
 ChocolArm64/Instruction/AInstEmitSimdCvt.cs   |  697 -----
 ChocolArm64/Instruction/AInstEmitSimdHash.cs  |  140 -
 .../Instruction/AInstEmitSimdHelper.cs        | 1495 -----------
 .../Instruction/AInstEmitSimdLogical.cs       |  311 ---
 .../Instruction/AInstEmitSimdMemory.cs        |  185 --
 ChocolArm64/Instruction/AInstEmitSimdMove.cs  |  562 ----
 ChocolArm64/Instruction/AInstEmitSimdShift.cs |  865 ------
 ChocolArm64/Instruction/AInstEmitSystem.cs    |  138 -
 ChocolArm64/Instruction/AInstEmitter.cs       |    6 -
 ChocolArm64/Instruction/AInstInterpreter.cs   |    8 -
 ChocolArm64/Instruction/ASoftFallback.cs      |  922 -------
 ChocolArm64/Instruction/ASoftFloat.cs         | 2127 ---------------
 .../Instruction32/A32InstInterpretFlow.cs     |   70 -
 .../Instruction32/A32InstInterpretHelper.cs   |   65 -
 .../CryptoHelper.cs}                          |  166 +-
 ChocolArm64/Instructions/Inst.cs              |   20 +
 ChocolArm64/Instructions/InstEmitAlu.cs       |  402 +++
 ChocolArm64/Instructions/InstEmitAluHelper.cs |  212 ++
 ChocolArm64/Instructions/InstEmitBfm.cs       |  208 ++
 ChocolArm64/Instructions/InstEmitCcmp.cs      |   81 +
 ChocolArm64/Instructions/InstEmitCsel.cs      |   58 +
 ChocolArm64/Instructions/InstEmitException.cs |   86 +
 ChocolArm64/Instructions/InstEmitFlow.cs      |  189 ++
 ChocolArm64/Instructions/InstEmitHash.cs      |  115 +
 ChocolArm64/Instructions/InstEmitMemory.cs    |  252 ++
 ChocolArm64/Instructions/InstEmitMemoryEx.cs  |  192 ++
 .../Instructions/InstEmitMemoryHelper.cs      |  138 +
 ChocolArm64/Instructions/InstEmitMove.cs      |   41 +
 ChocolArm64/Instructions/InstEmitMul.cs       |   80 +
 .../Instructions/InstEmitSimdArithmetic.cs    | 2387 +++++++++++++++++
 ChocolArm64/Instructions/InstEmitSimdCmp.cs   |  526 ++++
 .../Instructions/InstEmitSimdCrypto.cs        |   54 +
 ChocolArm64/Instructions/InstEmitSimdCvt.cs   |  697 +++++
 ChocolArm64/Instructions/InstEmitSimdHash.cs  |  140 +
 .../Instructions/InstEmitSimdHelper.cs        | 1495 +++++++++++
 .../Instructions/InstEmitSimdLogical.cs       |  311 +++
 .../Instructions/InstEmitSimdMemory.cs        |  185 ++
 ChocolArm64/Instructions/InstEmitSimdMove.cs  |  562 ++++
 ChocolArm64/Instructions/InstEmitSimdShift.cs |  865 ++++++
 ChocolArm64/Instructions/InstEmitSystem.cs    |  138 +
 ChocolArm64/Instructions/InstEmitter.cs       |    6 +
 ChocolArm64/Instructions/InstInterpreter.cs   |    8 +
 ChocolArm64/Instructions/SoftFallback.cs      |  922 +++++++
 ChocolArm64/Instructions/SoftFloat.cs         | 2127 +++++++++++++++
 .../VectorHelper.cs}                          |  494 ++--
 .../A32InstInterpretAlu.cs                    |    2 +-
 .../Instructions32/A32InstInterpretFlow.cs    |   70 +
 .../Instructions32/A32InstInterpretHelper.cs  |   65 +
 ChocolArm64/Memory/AMemory.cs                 |  745 -----
 ChocolArm64/Memory/AMemoryHelper.cs           |   67 -
 ChocolArm64/Memory/IAMemory.cs                |   37 -
 ChocolArm64/Memory/IMemory.cs                 |   37 +
 ChocolArm64/Memory/MemoryHelper.cs            |   67 +
 ChocolArm64/Memory/MemoryManager.cs           |  745 +++++
 ChocolArm64/OpCodeTable.cs                    |  713 +++++
 ChocolArm64/Optimizations.cs                  |   18 +
 ChocolArm64/State/ARegister.cs                |  142 -
 .../{AThreadState.cs => CpuThreadState.cs}    |   80 +-
 .../{AExecutionMode.cs => ExecutionMode.cs}   |    2 +-
 ChocolArm64/State/FPCR.cs                     |   11 -
 ChocolArm64/State/FPSR.cs                     |    8 -
 ChocolArm64/State/{FPExc.cs => FpExc.cs}      |    2 +-
 ChocolArm64/State/{FPType.cs => FpType.cs}    |    2 +-
 ChocolArm64/State/Fpcr.cs                     |   11 +
 ChocolArm64/State/Fpsr.cs                     |    8 +
 ChocolArm64/State/{APState.cs => PState.cs}   |    8 +-
 ChocolArm64/State/Register.cs                 |  142 +
 .../{ARegisterSize.cs => RegisterSize.cs}     |    6 +-
 .../{ARegisterType.cs => RegisterType.cs}     |    2 +-
 .../State/{ARoundMode.cs => RoundMode.cs}     |    2 +-
 ChocolArm64/TranslatedSub.cs                  |  150 ++
 ...nslatedSubType.cs => TranslatedSubType.cs} |    2 +-
 ChocolArm64/Translation/AILBarrier.cs         |    7 -
 ChocolArm64/Translation/AILBlock.cs           |   76 -
 ChocolArm64/Translation/AILEmitter.cs         |  188 --
 ChocolArm64/Translation/AILEmitterCtx.cs      |  554 ----
 ChocolArm64/Translation/AILLabel.cs           |   28 -
 ChocolArm64/Translation/AILOpCode.cs          |   19 -
 ChocolArm64/Translation/AILOpCodeBranch.cs    |   21 -
 ChocolArm64/Translation/AILOpCodeCall.cs      |   20 -
 ChocolArm64/Translation/AILOpCodeConst.cs     |   65 -
 ChocolArm64/Translation/AILOpCodeLoad.cs      |   75 -
 ChocolArm64/Translation/AILOpCodeLog.cs       |   17 -
 ChocolArm64/Translation/AILOpCodeStore.cs     |   75 -
 ChocolArm64/Translation/ALocalAlloc.cs        |  229 --
 ChocolArm64/Translation/IAILEmit.cs           |    7 -
 ChocolArm64/Translation/IILEmit.cs            |    7 +
 ChocolArm64/Translation/ILBarrier.cs          |    7 +
 ChocolArm64/Translation/ILBlock.cs            |   76 +
 ChocolArm64/Translation/ILEmitter.cs          |  188 ++
 ChocolArm64/Translation/ILEmitterCtx.cs       |  554 ++++
 ChocolArm64/Translation/ILGeneratorEx.cs      |  110 +-
 ChocolArm64/Translation/ILLabel.cs            |   28 +
 ChocolArm64/Translation/ILOpCode.cs           |   19 +
 ChocolArm64/Translation/ILOpCodeBranch.cs     |   21 +
 ChocolArm64/Translation/ILOpCodeCall.cs       |   20 +
 ChocolArm64/Translation/ILOpCodeConst.cs      |   65 +
 ChocolArm64/Translation/ILOpCodeLoad.cs       |   75 +
 ChocolArm64/Translation/ILOpCodeLog.cs        |   17 +
 ChocolArm64/Translation/ILOpCodeStore.cs      |   75 +
 .../Translation/{AIoType.cs => IoType.cs}     |    2 +-
 ChocolArm64/Translation/LocalAlloc.cs         |  229 ++
 ChocolArm64/Translator.cs                     |  165 ++
 ChocolArm64/TranslatorCache.cs                |  165 ++
 Ryujinx.Graphics/Memory/NvGpuVmm.cs           |    6 +-
 Ryujinx.Graphics/Memory/NvGpuVmmCache.cs      |    2 +-
 Ryujinx.Graphics/Texture/ImageUtils.cs        |    6 +-
 Ryujinx.Graphics/Texture/TextureHelper.cs     |    8 +-
 Ryujinx.HLE/HOS/Homebrew.cs                   |   18 +-
 Ryujinx.HLE/HOS/Ipc/IpcHandler.cs             |   12 +-
 Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs     |   48 +-
 Ryujinx.HLE/HOS/Kernel/KMemoryManager.cs      |    2 +-
 Ryujinx.HLE/HOS/Kernel/KRecursiveLock.cs      |    2 +-
 Ryujinx.HLE/HOS/Kernel/KThread.cs             |   14 +-
 Ryujinx.HLE/HOS/Kernel/SvcHandler.cs          |   14 +-
 Ryujinx.HLE/HOS/Kernel/SvcMemory.cs           |   20 +-
 Ryujinx.HLE/HOS/Kernel/SvcSystem.cs           |   32 +-
 Ryujinx.HLE/HOS/Kernel/SvcThread.cs           |   24 +-
 Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs       |   16 +-
 Ryujinx.HLE/HOS/Process.cs                    |   24 +-
 Ryujinx.HLE/HOS/ServiceCtx.cs                 |   32 +-
 Ryujinx.HLE/HOS/Services/Acc/IProfile.cs      |    2 +-
 .../HOS/Services/Aud/AudioOut/IAudioOut.cs    |    2 +-
 .../Aud/AudioRenderer/IAudioRenderer.cs       |    6 +-
 .../Aud/AudioRenderer/VoiceContext.cs         |    4 +-
 .../HOS/Services/Aud/IAudioOutManager.cs      |    2 +-
 Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs |    2 +-
 .../HOS/Services/Nv/NvGpuAS/NvGpuASIoctl.cs   |   14 +-
 .../HOS/Services/Nv/NvGpuGpu/NvGpuGpuIoctl.cs |   14 +-
 .../Nv/NvHostChannel/NvHostChannelIoctl.cs    |    8 +-
 .../Services/Nv/NvHostCtrl/NvHostCtrlIoctl.cs |   14 +-
 .../HOS/Services/Nv/NvMap/NvMapIoctl.cs       |   24 +-
 .../Services/Vi/IApplicationDisplayService.cs |    2 +-
 Ryujinx.HLE/Loaders/Executable.cs             |    4 +-
 Ryujinx.HLE/Utilities/StructReader.cs         |    8 +-
 Ryujinx.HLE/Utilities/StructWriter.cs         |    6 +-
 Ryujinx.Tests/Cpu/CpuTest.cs                  |   14 +-
 Ryujinx.Tests/Cpu/CpuTestAlu.cs               |   22 +-
 Ryujinx.Tests/Cpu/CpuTestAluImm.cs            |   40 +-
 Ryujinx.Tests/Cpu/CpuTestAluRs.cs             |  108 +-
 Ryujinx.Tests/Cpu/CpuTestAluRx.cs             |   56 +-
 Ryujinx.Tests/Cpu/CpuTestBfm.cs               |   12 +-
 Ryujinx.Tests/Cpu/CpuTestCcmpImm.cs           |    8 +-
 Ryujinx.Tests/Cpu/CpuTestCcmpReg.cs           |    8 +-
 Ryujinx.Tests/Cpu/CpuTestCsel.cs              |   16 +-
 Ryujinx.Tests/Cpu/CpuTestMisc.cs              |    2 +-
 Ryujinx.Tests/Cpu/CpuTestMov.cs               |   12 +-
 Ryujinx.Tests/Cpu/CpuTestMul.cs               |   20 +-
 Ryujinx.Tests/Cpu/CpuTestSimd.cs              |  174 +-
 Ryujinx.Tests/Cpu/CpuTestSimdArithmetic.cs    |   28 +-
 Ryujinx.Tests/Cpu/CpuTestSimdCrypto.cs        |    8 +-
 Ryujinx.Tests/Cpu/CpuTestSimdIns.cs           |   12 +-
 Ryujinx.Tests/Cpu/CpuTestSimdReg.cs           |  296 +-
 Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs       |    4 +-
 Ryujinx.Tests/Cpu/CpuTestSimdRegElemF.cs      |   16 +-
 Ryujinx.Tests/Cpu/CpuTestSimdShImm.cs         |   38 +-
 Ryujinx/Config.cs                             |  190 +-
 Ryujinx/Ui/ConsoleLog.cs                      |   44 +-
 Ryujinx/Ui/GLScreen.cs                        |  222 +-
 Ryujinx/Ui/JoyConController.cs                |  178 +-
 Ryujinx/Ui/JoyConKeyboard.cs                  |   82 +-
 Ryujinx/Ui/Program.cs                         |   36 +-
 314 files changed, 19456 insertions(+), 19456 deletions(-)
 delete mode 100644 ChocolArm64/ABitUtils.cs
 delete mode 100644 ChocolArm64/AOpCodeTable.cs
 delete mode 100644 ChocolArm64/AOptimizations.cs
 delete mode 100644 ChocolArm64/ATranslatedSub.cs
 delete mode 100644 ChocolArm64/ATranslator.cs
 delete mode 100644 ChocolArm64/ATranslatorCache.cs
 create mode 100644 ChocolArm64/BitUtils.cs
 rename ChocolArm64/{AThread.cs => CpuThread.cs} (56%)
 delete mode 100644 ChocolArm64/Decoder/ABlock.cs
 delete mode 100644 ChocolArm64/Decoder/ACond.cs
 delete mode 100644 ChocolArm64/Decoder/ADecoder.cs
 delete mode 100644 ChocolArm64/Decoder/ADecoderHelper.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCode.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeAdr.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeAlu.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeAluImm.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeAluRs.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeAluRx.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeBImm.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeBImmAl.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeBImmCmp.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeBImmCond.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeBImmTest.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeBReg.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeBfm.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeCcmp.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeCcmpImm.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeCcmpReg.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeCsel.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeException.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeMem.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeMemEx.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeMemPair.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeMemReg.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeMov.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeMul.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimd.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdCvt.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdExt.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdFcond.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdFmov.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdImm.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdIns.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdMemImm.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdMemLit.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdMemPair.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdMemReg.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdMemSs.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdReg.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdRegElem.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdRegElemF.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdShImm.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSimdTbl.cs
 delete mode 100644 ChocolArm64/Decoder/AOpCodeSystem.cs
 delete mode 100644 ChocolArm64/Decoder/IAOpCode.cs
 delete mode 100644 ChocolArm64/Decoder/IAOpCodeAlu.cs
 delete mode 100644 ChocolArm64/Decoder/IAOpCodeAluImm.cs
 delete mode 100644 ChocolArm64/Decoder/IAOpCodeAluRs.cs
 delete mode 100644 ChocolArm64/Decoder/IAOpCodeAluRx.cs
 delete mode 100644 ChocolArm64/Decoder/IAOpCodeCond.cs
 delete mode 100644 ChocolArm64/Decoder/IAOpCodeSimd.cs
 delete mode 100644 ChocolArm64/Decoder32/A32OpCode.cs
 delete mode 100644 ChocolArm64/Decoder32/A32OpCodeBImmAl.cs
 create mode 100644 ChocolArm64/Decoders/Block.cs
 create mode 100644 ChocolArm64/Decoders/Cond.cs
 rename ChocolArm64/{Decoder/ADataOp.cs => Decoders/DataOp.cs} (70%)
 create mode 100644 ChocolArm64/Decoders/Decoder.cs
 create mode 100644 ChocolArm64/Decoders/DecoderHelper.cs
 create mode 100644 ChocolArm64/Decoders/IOpCode64.cs
 create mode 100644 ChocolArm64/Decoders/IOpCodeAlu64.cs
 create mode 100644 ChocolArm64/Decoders/IOpCodeAluImm64.cs
 create mode 100644 ChocolArm64/Decoders/IOpCodeAluRs64.cs
 create mode 100644 ChocolArm64/Decoders/IOpCodeAluRx64.cs
 create mode 100644 ChocolArm64/Decoders/IOpCodeCond64.cs
 rename ChocolArm64/{Decoder/IAOpCodeLit.cs => Decoders/IOpCodeLit64.cs} (70%)
 create mode 100644 ChocolArm64/Decoders/IOpCodeSimd64.cs
 rename ChocolArm64/{Decoder/AIntType.cs => Decoders/IntType.cs} (78%)
 create mode 100644 ChocolArm64/Decoders/OpCode64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeAdr64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeAlu64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeAluImm64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeAluRs64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeAluRx64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeBImm64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeBImmAl64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeBImmCmp64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeBImmCond64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeBImmTest64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeBReg64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeBfm64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeCcmp64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeCcmpImm64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeCcmpReg64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeCsel64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeException64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeMem64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeMemEx64.cs
 rename ChocolArm64/{Decoder/AOpCodeMemImm.cs => Decoders/OpCodeMemImm64.cs} (62%)
 rename ChocolArm64/{Decoder/AOpCodeMemLit.cs => Decoders/OpCodeMemLit64.cs} (63%)
 create mode 100644 ChocolArm64/Decoders/OpCodeMemPair64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeMemReg64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeMov64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeMul64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimd64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdCvt64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdExt64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdFcond64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdFmov64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdImm64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdIns64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdMemImm64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdMemLit64.cs
 rename ChocolArm64/{Decoder/AOpCodeSimdMemMs.cs => Decoders/OpCodeSimdMemMs64.cs} (55%)
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdMemPair64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdMemReg64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdMemSs64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdReg64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdRegElem64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdShImm64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSimdTbl64.cs
 create mode 100644 ChocolArm64/Decoders/OpCodeSystem64.cs
 rename ChocolArm64/{Decoder/AShiftType.cs => Decoders/ShiftType.cs} (56%)
 create mode 100644 ChocolArm64/Decoders32/A32OpCode.cs
 create mode 100644 ChocolArm64/Decoders32/A32OpCodeBImmAl.cs
 delete mode 100644 ChocolArm64/Events/ACpuTraceEventArgs.cs
 delete mode 100644 ChocolArm64/Events/AInstExceptionEventArgs.cs
 delete mode 100644 ChocolArm64/Events/AInstUndefinedEventArgs.cs
 delete mode 100644 ChocolArm64/Events/AInvalidAccessEventArgs.cs
 create mode 100644 ChocolArm64/Events/CpuTraceEventArgs.cs
 create mode 100644 ChocolArm64/Events/InstExceptionEventArgs.cs
 create mode 100644 ChocolArm64/Events/InstUndefinedEventArgs.cs
 create mode 100644 ChocolArm64/Events/InvalidAccessEventArgs.cs
 delete mode 100644 ChocolArm64/Instruction/AInst.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitAlu.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitAluHelper.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitBfm.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitCcmp.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitCsel.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitException.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitFlow.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitHash.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitMemory.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitMemoryEx.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitMemoryHelper.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitMove.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitMul.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitSimdCmp.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitSimdCrypto.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitSimdCvt.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitSimdHash.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitSimdHelper.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitSimdLogical.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitSimdMemory.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitSimdMove.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitSimdShift.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitSystem.cs
 delete mode 100644 ChocolArm64/Instruction/AInstEmitter.cs
 delete mode 100644 ChocolArm64/Instruction/AInstInterpreter.cs
 delete mode 100644 ChocolArm64/Instruction/ASoftFallback.cs
 delete mode 100644 ChocolArm64/Instruction/ASoftFloat.cs
 delete mode 100644 ChocolArm64/Instruction32/A32InstInterpretFlow.cs
 delete mode 100644 ChocolArm64/Instruction32/A32InstInterpretHelper.cs
 rename ChocolArm64/{Instruction/ACryptoHelper.cs => Instructions/CryptoHelper.cs} (75%)
 create mode 100644 ChocolArm64/Instructions/Inst.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitAlu.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitAluHelper.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitBfm.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitCcmp.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitCsel.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitException.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitFlow.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitHash.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitMemory.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitMemoryEx.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitMemoryHelper.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitMove.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitMul.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitSimdArithmetic.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitSimdCmp.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitSimdCrypto.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitSimdCvt.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitSimdHash.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitSimdHelper.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitSimdLogical.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitSimdMemory.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitSimdMove.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitSimdShift.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitSystem.cs
 create mode 100644 ChocolArm64/Instructions/InstEmitter.cs
 create mode 100644 ChocolArm64/Instructions/InstInterpreter.cs
 create mode 100644 ChocolArm64/Instructions/SoftFallback.cs
 create mode 100644 ChocolArm64/Instructions/SoftFloat.cs
 rename ChocolArm64/{Instruction/AVectorHelper.cs => Instructions/VectorHelper.cs} (53%)
 rename ChocolArm64/{Instruction32 => Instructions32}/A32InstInterpretAlu.cs (61%)
 create mode 100644 ChocolArm64/Instructions32/A32InstInterpretFlow.cs
 create mode 100644 ChocolArm64/Instructions32/A32InstInterpretHelper.cs
 delete mode 100644 ChocolArm64/Memory/AMemory.cs
 delete mode 100644 ChocolArm64/Memory/AMemoryHelper.cs
 delete mode 100644 ChocolArm64/Memory/IAMemory.cs
 create mode 100644 ChocolArm64/Memory/IMemory.cs
 create mode 100644 ChocolArm64/Memory/MemoryHelper.cs
 create mode 100644 ChocolArm64/Memory/MemoryManager.cs
 create mode 100644 ChocolArm64/OpCodeTable.cs
 create mode 100644 ChocolArm64/Optimizations.cs
 delete mode 100644 ChocolArm64/State/ARegister.cs
 rename ChocolArm64/State/{AThreadState.cs => CpuThreadState.cs} (57%)
 rename ChocolArm64/State/{AExecutionMode.cs => ExecutionMode.cs} (76%)
 delete mode 100644 ChocolArm64/State/FPCR.cs
 delete mode 100644 ChocolArm64/State/FPSR.cs
 rename ChocolArm64/State/{FPExc.cs => FpExc.cs} (92%)
 rename ChocolArm64/State/{FPType.cs => FpType.cs} (88%)
 create mode 100644 ChocolArm64/State/Fpcr.cs
 create mode 100644 ChocolArm64/State/Fpsr.cs
 rename ChocolArm64/State/{APState.cs => PState.cs} (75%)
 create mode 100644 ChocolArm64/State/Register.cs
 rename ChocolArm64/State/{ARegisterSize.cs => RegisterSize.cs} (57%)
 rename ChocolArm64/State/{ARegisterType.cs => RegisterType.cs} (78%)
 rename ChocolArm64/State/{ARoundMode.cs => RoundMode.cs} (89%)
 create mode 100644 ChocolArm64/TranslatedSub.cs
 rename ChocolArm64/{ATranslatedSubType.cs => TranslatedSubType.cs} (72%)
 delete mode 100644 ChocolArm64/Translation/AILBarrier.cs
 delete mode 100644 ChocolArm64/Translation/AILBlock.cs
 delete mode 100644 ChocolArm64/Translation/AILEmitter.cs
 delete mode 100644 ChocolArm64/Translation/AILEmitterCtx.cs
 delete mode 100644 ChocolArm64/Translation/AILLabel.cs
 delete mode 100644 ChocolArm64/Translation/AILOpCode.cs
 delete mode 100644 ChocolArm64/Translation/AILOpCodeBranch.cs
 delete mode 100644 ChocolArm64/Translation/AILOpCodeCall.cs
 delete mode 100644 ChocolArm64/Translation/AILOpCodeConst.cs
 delete mode 100644 ChocolArm64/Translation/AILOpCodeLoad.cs
 delete mode 100644 ChocolArm64/Translation/AILOpCodeLog.cs
 delete mode 100644 ChocolArm64/Translation/AILOpCodeStore.cs
 delete mode 100644 ChocolArm64/Translation/ALocalAlloc.cs
 delete mode 100644 ChocolArm64/Translation/IAILEmit.cs
 create mode 100644 ChocolArm64/Translation/IILEmit.cs
 create mode 100644 ChocolArm64/Translation/ILBarrier.cs
 create mode 100644 ChocolArm64/Translation/ILBlock.cs
 create mode 100644 ChocolArm64/Translation/ILEmitter.cs
 create mode 100644 ChocolArm64/Translation/ILEmitterCtx.cs
 create mode 100644 ChocolArm64/Translation/ILLabel.cs
 create mode 100644 ChocolArm64/Translation/ILOpCode.cs
 create mode 100644 ChocolArm64/Translation/ILOpCodeBranch.cs
 create mode 100644 ChocolArm64/Translation/ILOpCodeCall.cs
 create mode 100644 ChocolArm64/Translation/ILOpCodeConst.cs
 create mode 100644 ChocolArm64/Translation/ILOpCodeLoad.cs
 create mode 100644 ChocolArm64/Translation/ILOpCodeLog.cs
 create mode 100644 ChocolArm64/Translation/ILOpCodeStore.cs
 rename ChocolArm64/Translation/{AIoType.cs => IoType.cs} (90%)
 create mode 100644 ChocolArm64/Translation/LocalAlloc.cs
 create mode 100644 ChocolArm64/Translator.cs
 create mode 100644 ChocolArm64/TranslatorCache.cs

diff --git a/ChocolArm64/ABitUtils.cs b/ChocolArm64/ABitUtils.cs
deleted file mode 100644
index a2654c20a3..0000000000
--- 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 cbdff47fd8..0000000000
--- 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 17205489a6..0000000000
--- 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 a11da2646f..0000000000
--- 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 5be41d3ef7..0000000000
--- 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 199b44f80d..0000000000
--- 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 0000000000..881ee24842
--- /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
similarity index 56%
rename from ChocolArm64/AThread.cs
rename to ChocolArm64/CpuThread.cs
index 38c2b53db0..11f41236e3 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 7a0fc60773..0000000000
--- 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 f2da8bd29f..0000000000
--- 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 64beebd2a3..0000000000
--- 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 a2179f49e3..0000000000
--- 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 bdc8f13aa0..0000000000
--- 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 3396281f45..0000000000
--- 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 e1a44f04b4..0000000000
--- 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 e913475ad2..0000000000
--- 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 9c215be383..0000000000
--- 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 7dd72a6842..0000000000
--- 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 6519d281dc..0000000000
--- 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 a4ff686d6d..0000000000
--- 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 0f16b73e0e..0000000000
--- 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 1310feb8d3..0000000000
--- 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 73e57b7ab9..0000000000
--- 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 c9c600af5b..0000000000
--- 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 6498d8ec69..0000000000
--- 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 d0c7f779c8..0000000000
--- 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 803eefc249..0000000000
--- 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 c364ae68b4..0000000000
--- 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 cdef3e745c..0000000000
--- 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 4579c1a7b9..0000000000
--- 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 be5367cf61..0000000000
--- 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 3a28cfd73a..0000000000
--- 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 ec866c84e5..0000000000
--- 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 989271282f..0000000000
--- 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 d5398646d1..0000000000
--- 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 ca2b0cdb38..0000000000
--- 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 4170851721..0000000000
--- 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 41f4d3b143..0000000000
--- 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 888e447030..0000000000
--- 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 e38e742473..0000000000
--- 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 3f88895985..0000000000
--- 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 e7dfe62114..0000000000
--- 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 0b60bbe837..0000000000
--- 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 1ef19a5d67..0000000000
--- 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 ea6fe00be9..0000000000
--- 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 db99e3d44d..0000000000
--- 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 aabf484611..0000000000
--- 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 c8794ff5a5..0000000000
--- 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 702ffed1e2..0000000000
--- 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 d6dc4bd231..0000000000
--- 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 e0670def45..0000000000
--- 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 e6d5210f2f..0000000000
--- 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 c8ae5bac74..0000000000
--- 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 3d81a5d451..0000000000
--- 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 44bf9cb2f1..0000000000
--- 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 22af4c82d6..0000000000
--- 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 04b5c5f7d1..0000000000
--- 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 5ca9de4032..0000000000
--- 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 b49d5325a9..0000000000
--- 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 1655abaac0..0000000000
--- 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 19032ad940..0000000000
--- 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 56f870df6c..0000000000
--- 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 71bca7f95d..0000000000
--- 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 0000000000..c89ea7c6fb
--- /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 0000000000..57e12cd609
--- /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
similarity index 70%
rename from ChocolArm64/Decoder/ADataOp.cs
rename to ChocolArm64/Decoders/DataOp.cs
index a5601a3abc..b7768bb4d0 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 0000000000..db43ac4fe8
--- /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 0000000000..6ee279d7d6
--- /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 0000000000..e940712311
--- /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 0000000000..b9a5fe9e68
--- /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 0000000000..4b305e27b7
--- /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 0000000000..df503ae9d8
--- /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 0000000000..f41fc4d2f0
--- /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 0000000000..9c39d63329
--- /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
similarity index 70%
rename from ChocolArm64/Decoder/IAOpCodeLit.cs
rename to ChocolArm64/Decoders/IOpCodeLit64.cs
index 0f5092d076..c6dc2c7fc1 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 0000000000..fc8f54d608
--- /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
similarity index 78%
rename from ChocolArm64/Decoder/AIntType.cs
rename to ChocolArm64/Decoders/IntType.cs
index 242fdada14..70f833ec56 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 0000000000..b2dc363b8b
--- /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 0000000000..98b2f07bbe
--- /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 0000000000..5f094572ef
--- /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 0000000000..64ac08a7a6
--- /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 0000000000..f24c7f37bd
--- /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 0000000000..a36f94ca89
--- /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 0000000000..71c61bab3b
--- /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 0000000000..f419ffa033
--- /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 0000000000..6f43319918
--- /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 0000000000..227023092e
--- /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 0000000000..a2e8baeaeb
--- /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 0000000000..74dbff5839
--- /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 0000000000..6891a8f4fc
--- /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 0000000000..e2aae96dee
--- /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 0000000000..78d5de5502
--- /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 0000000000..a0544d987a
--- /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 0000000000..d085a82378
--- /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 0000000000..2554124c78
--- /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 0000000000..36e6758352
--- /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 0000000000..39935eb36e
--- /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
similarity index 62%
rename from ChocolArm64/Decoder/AOpCodeMemImm.cs
rename to ChocolArm64/Decoders/OpCodeMemImm64.cs
index 14edc51487..edaa4970ae 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
similarity index 63%
rename from ChocolArm64/Decoder/AOpCodeMemLit.cs
rename to ChocolArm64/Decoders/OpCodeMemLit64.cs
index ad719a1942..29bfeee31f 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 0000000000..5b81c75589
--- /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 0000000000..3dd210fbd2
--- /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 0000000000..f969785479
--- /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 0000000000..176b7b93b5
--- /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 0000000000..a705e489cc
--- /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 0000000000..6c68a3af26
--- /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 0000000000..1c57f19cc4
--- /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 0000000000..b0f1c0eb93
--- /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 0000000000..6752e185e5
--- /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 0000000000..3ef6a8c6e2
--- /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 0000000000..3b25faebfd
--- /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 0000000000..9fbab5674f
--- /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 0000000000..c98ffd030b
--- /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
similarity index 55%
rename from ChocolArm64/Decoder/AOpCodeSimdMemMs.cs
rename to ChocolArm64/Decoders/OpCodeSimdMemMs64.cs
index a54e2360c5..0748ef43f3 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 0000000000..1b796742e3
--- /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 0000000000..4ccbbed2da
--- /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 0000000000..07ec8ab730
--- /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 0000000000..4bf462dee4
--- /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 0000000000..04e9586199
--- /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 0000000000..b5db7345ca
--- /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 0000000000..d4cd88d13b
--- /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 0000000000..13cc9090f5
--- /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 0000000000..41c51565d9
--- /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
similarity index 56%
rename from ChocolArm64/Decoder/AShiftType.cs
rename to ChocolArm64/Decoders/ShiftType.cs
index 34ceea2087..5f6a7a4ca8 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 0000000000..f0177a4384
--- /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 0000000000..c4a196b63e
--- /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 0284f4eeb9..0000000000
--- 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 a6853ea10e..0000000000
--- 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 cdc1728bd8..0000000000
--- 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 a5c472a889..0000000000
--- 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 0000000000..c12781ed86
--- /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 0000000000..e3cc0ba0e0
--- /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 0000000000..3ad7ea8b9e
--- /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 0000000000..a8046d7375
--- /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 4a03b65cb9..d6ddf75227 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 d55c2c1ca9..f33aafc013 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 7409353614..0000000000
--- 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 4551346bd9..0000000000
--- 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 ef9dd7a7a5..0000000000
--- 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 2e8f250858..0000000000
--- 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 7153a6a0d1..0000000000
--- 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 218767524e..0000000000
--- 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 73d2096732..0000000000
--- 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 91262834f9..0000000000
--- 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 69bdbc480d..0000000000
--- 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 67653ed06c..0000000000
--- 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 cf19b4a105..0000000000
--- 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 b10551fe07..0000000000
--- 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 719b53d5d5..0000000000
--- 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 3713c81f6c..0000000000
--- 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 1bd483640c..0000000000
--- 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 cd3480e649..0000000000
--- 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 b2680a588a..0000000000
--- 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 f277069bff..0000000000
--- 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 5a59e779f3..0000000000
--- 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 ff08283120..0000000000
--- 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 1aa8981f54..0000000000
--- 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 368b014fba..0000000000
--- 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 6001f48caf..0000000000
--- 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 4f828cf8ad..0000000000
--- 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 a365398ff7..0000000000
--- 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 8712a7367c..0000000000
--- 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 6a855aecb0..0000000000
--- 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 d643fb6f76..0000000000
--- 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 0912257a49..0000000000
--- 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 223fd186ca..0000000000
--- 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 9c3c098e8e..0000000000
--- 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
similarity index 75%
rename from ChocolArm64/Instruction/ACryptoHelper.cs
rename to ChocolArm64/Instructions/CryptoHelper.cs
index 2dc65972b2..bb9a22a3e6 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 0000000000..5f6740caec
--- /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 0000000000..c0258ed2b7
--- /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 0000000000..613dd23402
--- /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 0000000000..d25af8be8a
--- /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 0000000000..b91104c938
--- /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 0000000000..19b073ceaf
--- /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 0000000000..8325a3978f
--- /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 0000000000..7d0897cd6f
--- /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 0000000000..7e21a88604
--- /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 0000000000..96e45b3f74
--- /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 0000000000..42daca63b7
--- /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 0000000000..f953564c46
--- /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 0000000000..be3e8e2d31
--- /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 0000000000..b7418e6922
--- /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 0000000000..9217de5fd9
--- /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 0000000000..c473c0aea1
--- /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 0000000000..33c81aab0a
--- /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 0000000000..fa17c09dcd
--- /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 0000000000..bb767fec07
--- /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 0000000000..fad5151029
--- /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 0000000000..f51568ebbe
--- /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 0000000000..eb05325786
--- /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 0000000000..3f539b8ad4
--- /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 0000000000..3c24ff23c2
--- /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 0000000000..0e61d5bded
--- /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 0000000000..db6e8604f8
--- /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 0000000000..e6354fd5a7
--- /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 0000000000..a31aa34c50
--- /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 0000000000..79dbe95410
--- /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
similarity index 53%
rename from ChocolArm64/Instruction/AVectorHelper.cs
rename to ChocolArm64/Instructions/VectorHelper.cs
index 41e865b94a..8ef15818ce 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
similarity index 61%
rename from ChocolArm64/Instruction32/A32InstInterpretAlu.cs
rename to ChocolArm64/Instructions32/A32InstInterpretAlu.cs
index 41b9d22aeb..f3be823ffc 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 0000000000..cdf7e4c6af
--- /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 0000000000..b08e12984a
--- /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 2854871e35..0000000000
--- 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 ea87783438..0000000000
--- 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 5b7d17bb8b..0000000000
--- 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 0000000000..dc582155f8
--- /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 0000000000..2e721afa1c
--- /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 0000000000..308dd17ec7
--- /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 0000000000..b2a75bb7c5
--- /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 0000000000..f2b0ffba1a
--- /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 5861db8c64..0000000000
--- 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
similarity index 57%
rename from ChocolArm64/State/AThreadState.cs
rename to ChocolArm64/State/CpuThreadState.cs
index fbfac5bcac..ed106f71cc 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
similarity index 76%
rename from ChocolArm64/State/AExecutionMode.cs
rename to ChocolArm64/State/ExecutionMode.cs
index 8632da7747..4b8c17cec0 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 8f47cf9087..0000000000
--- 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 d71cde7852..0000000000
--- 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
similarity index 92%
rename from ChocolArm64/State/FPExc.cs
rename to ChocolArm64/State/FpExc.cs
index a665957d6d..5cb7a402ff 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
similarity index 88%
rename from ChocolArm64/State/FPType.cs
rename to ChocolArm64/State/FpType.cs
index b00f5fee0d..fc2791063a 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 0000000000..908faee5f4
--- /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 0000000000..ba551eefaa
--- /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
similarity index 75%
rename from ChocolArm64/State/APState.cs
rename to ChocolArm64/State/PState.cs
index aaf0ff0ce1..40636c8705 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 0000000000..ea29e7b6b3
--- /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
similarity index 57%
rename from ChocolArm64/State/ARegisterSize.cs
rename to ChocolArm64/State/RegisterSize.cs
index 144f36b929..7cc9959931 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
similarity index 78%
rename from ChocolArm64/State/ARegisterType.cs
rename to ChocolArm64/State/RegisterType.cs
index f9776bb7dd..4476d04426 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
similarity index 89%
rename from ChocolArm64/State/ARoundMode.cs
rename to ChocolArm64/State/RoundMode.cs
index 297d0137cb..b687cc8e9f 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 0000000000..8b3ec3f013
--- /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
similarity index 72%
rename from ChocolArm64/ATranslatedSubType.cs
rename to ChocolArm64/TranslatedSubType.cs
index 14893abdfa..f57aea945d 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 25b08de31d..0000000000
--- 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 e580e09c9b..0000000000
--- 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 8c7805353b..0000000000
--- 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 e5288bc81c..0000000000
--- 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 0ee39ad7e2..0000000000
--- 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 a4bc93a065..0000000000
--- 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 e4caad1ffa..0000000000
--- 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 8cd944eb01..0000000000
--- 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 fee8640768..0000000000
--- 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 d60ce539f7..0000000000
--- 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 1338ca1f3a..0000000000
--- 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 a0feb43773..0000000000
--- 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 8e9047804d..0000000000
--- 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 6e4e9a7855..0000000000
--- 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 0000000000..3c3925ee0a
--- /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 0000000000..f931e9922d
--- /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 0000000000..d51e8d9ec3
--- /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 0000000000..543528d716
--- /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 0000000000..c1d1be366e
--- /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 40c6efa4d7..318098cc78 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 0000000000..4f96edccf1
--- /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 0000000000..eb91639e63
--- /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 0000000000..b0ba23313f
--- /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 0000000000..0b591d46ce
--- /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 0000000000..5497eba16f
--- /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 0000000000..9dae10cc4b
--- /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 0000000000..2c77021b10
--- /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 0000000000..41326fe127
--- /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
similarity index 90%
rename from ChocolArm64/Translation/AIoType.cs
rename to ChocolArm64/Translation/IoType.cs
index 94f8908142..290b159fc5 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 0000000000..8237bd5454
--- /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 0000000000..3bf06dc469
--- /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 0000000000..7d65035777
--- /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 0082fb2751..ec660bf0e9 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 f1c16a3657..57e25a2fce 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 d2172c2ef8..97da17a0a8 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 9e966e6bd0..6ac91d8b59 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 1f862a4ae8..ffb22c7f5c 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 fca995c08a..ec27a6eaf9 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 73309e1e26..4a0f955fe3 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 8cf73785e0..4cfb2aa20a 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 a21531deb2..30c1a88051 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 74ad28f360..73ee2322d0 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 d098aab0e5..9b475d4ebf 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 07bc474b80..560ad4b3f7 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 6eb8419cb2..54aef5d708 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 4c1744e6e3..53a557de5e 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 73719c19f7..318bd290f9 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 1d8bfeb8f5..93b2d68d0c 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 d8c9fdf6ed..a591673e2c 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 1776b37b2c..1d1a15cbfb 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 cd3d6e4902..1ad049c6bd 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 7963cbb47d..aae45081be 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 044b2efc2c..7d6e1c583e 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 2bc2d82068..b08f7640f4 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 4f4c8add17..b8ae11cea1 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 0ccc1949b7..fed4104229 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 387fe5b416..7ee770f4c9 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 d2dd089da5..5443a3bf70 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 0b70928ea2..6cb1474105 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 7953d66542..f5378ef7fb 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 33a1dee974..5d1ddd84b3 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 3c63af141b..d4d79073ec 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 6e942a9b0d..19fd267475 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 8b88105c6a..a537e7a418 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 4587189b90..c273e89de2 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 43952d195b..666d279fba 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 61eadefd35..58d41fea38 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 58a99dfb18..833d5d6d74 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 9c66532b9a..8a11fa941e 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 427396f8be..59434029e3 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 7ca92d4fea..7eebedf31d 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 36120f7409..686408773a 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 2d88b9f033..f9691ed14a 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 d7b75f5e35..ac6d3405f4 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 175c9f0687..3c1a174b78 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 056c45437a..4058585bd7 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 3bb24f3a03..8cd36b10af 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 08e2894ca9..770eb4cf12 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 4efd8f31a2..ce2b50f0be 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 0b227edbb6..c07e47c8c4 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 e986d7f662..3f0188ccf2 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 615520625a..10d3105cfb 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 3945cce1a7..e9591a19bb 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 edc50d4d0b..7ae41b4edc 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 3e4d4dd3f4..2e73985250 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 "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 "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;
+                case "LJOYSTICK": return ControllerInputId.LJoystick;
+                case "RJOYSTICK": return ControllerInputId.RJoystick;
 
-                default: return ControllerInputID.Invalid;
+                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 5ae13817e4..1ecd4cde44 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 27f3f08b56..a654d15033 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 aac8efd7c4..28b631b235 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);
+            GamePadState gpState = GamePad.GetState(Index);
 
-            HidControllerButtons Buttons = 0;
+            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, 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;
+            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;
+            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.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.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 ea9645539a..fd399fe8d1 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 145ff33fd8..4edf6e4714 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();
         }
     }
 }