diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 59a5b6e9..149efbaf 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -29,7 +29,7 @@ jobs: -B ${{github.workspace}}/build -H. -GNinja - -DDYNARMIC_USE_BUNDLED_CATCH=ON + -DOAKNUT_USE_BUNDLED_CATCH=ON - name: Build working-directory: ${{github.workspace}}/build diff --git a/CMakeLists.txt b/CMakeLists.txt index b84422d2..d2c9726b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.8) -project(oaknut LANGUAGES CXX VERSION 0.0.0) +project(oaknut LANGUAGES CXX VERSION 1.1.3) # Determine if we're built as a subproject (using add_subdirectory) # or if this is the master project. @@ -18,11 +18,13 @@ endif() # Source project files set(header_files ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/arm64_encode_helpers.inc.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/arm64_mnemonics.inc.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/enum.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/fpsimd_mnemonics.inc.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/imm.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/list.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/mnemonics_fpsimd_v8.0.inc.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/mnemonics_fpsimd_v8.1.inc.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/mnemonics_generic_v8.0.inc.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/mnemonics_generic_v8.1.inc.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/multi_typed_name.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/offset.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/oaknut/impl/reg.hpp @@ -39,7 +41,8 @@ target_compile_features(oaknut INTERFACE cxx_std_20) # Tests if (MASTER_PROJECT) - if (DYNARMIC_USE_BUNDLED_CATCH) + option(OAKNUT_USE_BUNDLED_CATCH "Use the embedded Catch2 submodule" OFF) + if (OAKNUT_USE_BUNDLED_CATCH) add_subdirectory(externals/catch) else() find_package(Catch2 3 REQUIRED) @@ -52,5 +55,33 @@ if (MASTER_PROJECT) ) target_include_directories(oaknut-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/tests) target_link_libraries(oaknut-tests PRIVATE Catch2::Catch2WithMain merry::oaknut) - target_compile_options(oaknut-tests PRIVATE -Wall -Wextra -Wcast-qual -pedantic -pedantic-errors -Wfatal-errors -Wno-missing-braces) + if (MSVC) + target_compile_options(oaknut-tests PRIVATE + /experimental:external + /external:W0 + /external:anglebrackets + /W4 + /w44263 # Non-virtual member function hides base class virtual function + /w44265 # Class has virtual functions, but destructor is not virtual + /w44456 # Declaration of 'var' hides previous local declaration + /w44457 # Declaration of 'var' hides function parameter + /w44458 # Declaration of 'var' hides class member + /w44459 # Declaration of 'var' hides global definition + /w44946 # Reinterpret-cast between related types + /wd4592 # Symbol will be dynamically initialized (implementation limitation) + /permissive- # Stricter C++ standards conformance + /MP + /Zi + /Zo + /EHsc + /Zc:externConstexpr # Allows external linkage for variables declared "extern constexpr", as the standard permits. + /Zc:inline # Omits inline functions from object-file output. + /Zc:throwingNew # Assumes new (without std::nothrow) never returns null. + /volatile:iso # Use strict standard-abiding volatile semantics + /bigobj # Increase number of sections in .obj files + /DNOMINMAX + ) + else() + target_compile_options(oaknut-tests PRIVATE -Wall -Wextra -Wcast-qual -pedantic -pedantic-errors -Wfatal-errors -Wno-missing-braces) + endif() endif() diff --git a/README.md b/README.md index 4b3356db..9f5c688c 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,19 @@ # Oaknut -*A C++20 assembler for AArch64 (ARMv8.0)* +*A C++20 assembler for AArch64 (ARMv8.0 to ARMv8.2)* Oaknut is a header-only library that allows one to dynamically assemble code in-memory at runtime. ## Usage +Provide `oaknut::CodeGenerator` with a pointer to a block of memory. Call functions on it to emit code. + Simple example: ```cpp +#include +#include + using EmittedFunction = int (*)(); EmittedFunction EmitExample(oaknut::CodeGenerator& code, int value) @@ -17,13 +22,92 @@ EmittedFunction EmitExample(oaknut::CodeGenerator& code, int value) EmittedFunction result = code.ptr(); - code.MOVZ(W0, value); + code.MOV(W0, value); code.RET(); return result; } + +int main() +{ + oaknut::CodeBlock mem{4096}; + oaknut::CodeGenerator code{mem.ptr()}; + + mem.unprotect(); + + EmittedFunction fn = EmitExample(code, 42); + + mem.protect(); + mem.invalidate_all(); + + std::printf("%i\n", fn()); // Output: 42 + + return 0; +} ``` +### Instructions + +Each AArch64 instruction corresponds to one emitter function. For a list of emitter functions see: +* ARMv8.0: [general instructions](include/oaknut/impl/mnemonics_generic_v8.0.inc.hpp), [FP & SIMD instructions](include/oaknut/impl/mnemonics_fpsimd_v8.0.inc.hpp) +* ARMv8.1: [general instructions](include/oaknut/impl/mnemonics_generic_v8.1.inc.hpp), [FP & SIMD instructions](include/oaknut/impl/mnemonics_fpsimd_v8.1.inc.hpp) +* ARMv8.2: [general instructions](include/oaknut/impl/mnemonics_generic_v8.2.inc.hpp), [FP & SIMD instructions](include/oaknut/impl/mnemonics_fpsimd_v8.2.inc.hpp) + +### Operands + +The `oaknut::util` namespace provides convenient names for operands for instructions. For example: + +|Name|Class| | +|----|----|----| +|W0, W1, ..., W30|`WReg`|32-bit general purpose registers| +|X0, X1, ..., X30|`XReg`|64-bit general purpose registers| +|WZR|`WzrReg` (convertable to `WReg`)|32-bit zero register| +|XZR|`ZrReg` (convertable to `XReg`)|64-bit zero register| +|WSP|`WspReg` (convertable to `WRegSp`)|32-bit stack pointer| +|SP|`SpReg` (convertable to `XRegSp`)|64-bit stack pointer| +|B0, B1, ..., B31|`BReg`|8-bit scalar SIMD register| +|H0, H1, ..., H31|`HReg`|16-bit scalar SIMD register| +|S0, S1, ..., S31|`SReg`|32-bit scalar SIMD register| +|D0, D1, ..., D31|`DReg`|64-bit scalar SIMD register| +|Q0, Q1, ..., Q31|`QReg`|128-bit scalar SIMD register| + +For vector operations, you can specify registers like so: + +|Name|Class| | +|----|----|----| +|V0.B8(), ...|`VReg_8B`|8 elements each 8 bits in size| +|V0.B16(), ...|`VReg_16B`|16 elements each 8 bits in size| +|V0.H4(), ...|`VReg_4H`|4 elements each 16 bits in size| +|V0.H8(), ...|`VReg_8H`|8 elements each 16 bits in size| +|V0.S2(), ...|`VReg_2S`|2 elements each 32 bits in size| +|V0.S4(), ...|`VReg_4S`|4 elements each 32 bits in size| +|V0.D1(), ...|`VReg_1D`|1 elements each 64 bits in size| +|V0.D2(), ...|`VReg_2D`|2 elements each 64 bits in size| + +And you can specify elements like so: + +|Name|Class| | +|----|----|----| +|V0.B()[0]|`BElem`|0th 8-bit element of V0 register| +|V0.H()[0]|`HElem`|0th 16-bit element of V0 register| +|V0.S()[0]|`SElem`|0th 32-bit element of V0 register| +|V0.D()[0]|`DElem`|0th 64-bit element of V0 register| + +Register lists are specified using `List`: + +``` +List{V0.B16(), V1.B16(), V2.B16()} // This expression has type List +``` + +And lists of elements similarly (both forms are equivalent): + +``` +List{V0.B()[1], V1.B()[1], V2.B()[1]} // This expression has type List +List{V0.B(), V1.B(), V2.B()}[1] // This expression has type List +``` + +You can find examples of instruction use in [tests/general.cpp](tests/general.cpp) and [tests/fpsimd.cpp](tests/fpsimd.cpp). + ## License This project is [MIT licensed](LICENSE). diff --git a/include/oaknut/code_block.hpp b/include/oaknut/code_block.hpp index 6b7deac8..e700d6ca 100644 --- a/include/oaknut/code_block.hpp +++ b/include/oaknut/code_block.hpp @@ -9,6 +9,7 @@ #include #if defined(_WIN32) +# define NOMINMAX # include #elif defined(__APPLE__) # include @@ -78,6 +79,8 @@ public: { #if defined(__APPLE__) sys_icache_invalidate(mem, size); +#elif defined(_WIN32) + FlushInstructionCache(GetCurrentProcess(), mem, size); #else static std::size_t icache_line_size = 0x10000, dcache_line_size = 0x10000; diff --git a/include/oaknut/impl/enum.hpp b/include/oaknut/impl/enum.hpp index 95a55dfc..154f0999 100644 --- a/include/oaknut/impl/enum.hpp +++ b/include/oaknut/impl/enum.hpp @@ -85,6 +85,15 @@ enum class PstateField { }; enum class SystemReg { + CNTFRQ_EL0 = 0b11'011'1110'0000'000, + CNTPCT_EL0 = 0b11'011'1110'0000'001, + CTR_EL0 = 0b11'011'0000'0000'001, + DCZID_EL0 = 0b11'011'0000'0000'111, + FPCR = 0b11'011'0100'0100'000, + FPSR = 0b11'011'0100'0100'001, + NZCV = 0b11'011'0100'0010'000, + TPIDR_EL0 = 0b11'011'1101'0000'010, + TPIDRRO_EL0 = 0b11'011'1101'0000'011, }; enum class AtOp { diff --git a/include/oaknut/impl/fpsimd_mnemonics.inc.hpp b/include/oaknut/impl/mnemonics_fpsimd_v8.0.inc.hpp similarity index 99% rename from include/oaknut/impl/fpsimd_mnemonics.inc.hpp rename to include/oaknut/impl/mnemonics_fpsimd_v8.0.inc.hpp index 8867fddd..2c77ee7b 100644 --- a/include/oaknut/impl/fpsimd_mnemonics.inc.hpp +++ b/include/oaknut/impl/mnemonics_fpsimd_v8.0.inc.hpp @@ -4038,19 +4038,19 @@ void MOV(DReg rd, DElem en) } void MOV(WReg wd, SElem en) { - emit<"00001110000ii100001111nnnnnddddd", "d", "n", "x">(wd, en.reg_index(), en.elem_index()); + emit<"00001110000xx100001111nnnnnddddd", "d", "n", "x">(wd, en.reg_index(), en.elem_index()); } void MOV(XReg xd, DElem en) { - emit<"01001110000i1000001111nnnnnddddd", "d", "n", "x">(xd, en.reg_index(), en.elem_index()); + emit<"01001110000x1000001111nnnnnddddd", "d", "n", "x">(xd, en.reg_index(), en.elem_index()); } void MOV(VReg_8B rd, VReg_8B rn) { - emit<"00001110101mmmmm000111nnnnnddddd", "d", "n">(rd, rn); + emit<"00001110101mmmmm000111nnnnnddddd", "d", "n", "m">(rd, rn, rn); } void MOV(VReg_16B rd, VReg_16B rn) { - emit<"01001110101mmmmm000111nnnnnddddd", "d", "n">(rd, rn); + emit<"01001110101mmmmm000111nnnnnddddd", "d", "n", "m">(rd, rn, rn); } void MOVI(VReg_8B rd, Imm<8> imm, LslSymbol = LslSymbol::LSL, ImmConst<0> = 0) { @@ -8279,7 +8279,7 @@ void UMOV(WReg wd, SElem en) } void UMOV(XReg xd, DElem en) { - emit<"01001110000i1000001111nnnnnddddd", "d", "n", "x">(xd, en.reg_index(), en.elem_index()); + emit<"01001110000x1000001111nnnnnddddd", "d", "n", "x">(xd, en.reg_index(), en.elem_index()); } void UMULL(VReg_4S rd, VReg_4H rn, HElem em) { diff --git a/include/oaknut/impl/mnemonics_fpsimd_v8.1.inc.hpp b/include/oaknut/impl/mnemonics_fpsimd_v8.1.inc.hpp new file mode 100644 index 00000000..71f45692 --- /dev/null +++ b/include/oaknut/impl/mnemonics_fpsimd_v8.1.inc.hpp @@ -0,0 +1,111 @@ +// SPDX-FileCopyrightText: Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +void SQRDMLAH(HReg rd, HReg rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0111111101LMmmmm1101H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void SQRDMLAH(SReg rd, SReg rn, SElem em) +{ + emit<"0111111110LMmmmm1101H0nnnnnddddd", "d", "n", "Mm", "H", "L">(rd, rn, em.reg_index(), em.elem_index() >> 1, em.elem_index() & 1); +} +void SQRDMLAH(VReg_4H rd, VReg_4H rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0010111101LMmmmm1101H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void SQRDMLAH(VReg_8H rd, VReg_8H rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0110111101LMmmmm1101H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void SQRDMLAH(VReg_2S rd, VReg_2S rn, SElem em) +{ + emit<"0010111110LMmmmm1101H0nnnnnddddd", "d", "n", "Mm", "H", "L">(rd, rn, em.reg_index(), em.elem_index() >> 1, em.elem_index() & 1); +} +void SQRDMLAH(VReg_4S rd, VReg_4S rn, SElem em) +{ + emit<"0110111110LMmmmm1101H0nnnnnddddd", "d", "n", "Mm", "H", "L">(rd, rn, em.reg_index(), em.elem_index() >> 1, em.elem_index() & 1); +} +void SQRDMLAH(HReg rd, HReg rn, HReg rm) +{ + emit<"01111110010mmmmm100001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SQRDMLAH(SReg rd, SReg rn, SReg rm) +{ + emit<"01111110100mmmmm100001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SQRDMLAH(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110010mmmmm100001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SQRDMLAH(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110010mmmmm100001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SQRDMLAH(VReg_2S rd, VReg_2S rn, VReg_2S rm) +{ + emit<"00101110100mmmmm100001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SQRDMLAH(VReg_4S rd, VReg_4S rn, VReg_4S rm) +{ + emit<"01101110100mmmmm100001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SQRDMLSH(HReg rd, HReg rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0111111101LMmmmm1111H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void SQRDMLSH(SReg rd, SReg rn, SElem em) +{ + emit<"0111111110LMmmmm1111H0nnnnnddddd", "d", "n", "Mm", "H", "L">(rd, rn, em.reg_index(), em.elem_index() >> 1, em.elem_index() & 1); +} +void SQRDMLSH(VReg_4H rd, VReg_4H rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0010111101LMmmmm1111H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void SQRDMLSH(VReg_8H rd, VReg_8H rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0110111101LMmmmm1111H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void SQRDMLSH(VReg_2S rd, VReg_2S rn, SElem em) +{ + emit<"0010111110LMmmmm1111H0nnnnnddddd", "d", "n", "Mm", "H", "L">(rd, rn, em.reg_index(), em.elem_index() >> 1, em.elem_index() & 1); +} +void SQRDMLSH(VReg_4S rd, VReg_4S rn, SElem em) +{ + emit<"0110111110LMmmmm1111H0nnnnnddddd", "d", "n", "Mm", "H", "L">(rd, rn, em.reg_index(), em.elem_index() >> 1, em.elem_index() & 1); +} +void SQRDMLSH(HReg rd, HReg rn, HReg rm) +{ + emit<"01111110010mmmmm100011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SQRDMLSH(SReg rd, SReg rn, SReg rm) +{ + emit<"01111110100mmmmm100011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SQRDMLSH(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110010mmmmm100011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SQRDMLSH(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110010mmmmm100011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SQRDMLSH(VReg_2S rd, VReg_2S rn, VReg_2S rm) +{ + emit<"00101110100mmmmm100011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SQRDMLSH(VReg_4S rd, VReg_4S rn, VReg_4S rm) +{ + emit<"01101110100mmmmm100011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} diff --git a/include/oaknut/impl/mnemonics_fpsimd_v8.2.inc.hpp b/include/oaknut/impl/mnemonics_fpsimd_v8.2.inc.hpp new file mode 100644 index 00000000..61f6ecd7 --- /dev/null +++ b/include/oaknut/impl/mnemonics_fpsimd_v8.2.inc.hpp @@ -0,0 +1,855 @@ +// SPDX-FileCopyrightText: Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +void BCAX(VReg_16B rd, VReg_16B rn, VReg_16B rm, VReg_16B ra) +{ + emit<"11001110001mmmmm0aaaaannnnnddddd", "d", "n", "m", "a">(rd, rn, rm, ra); +} +void EOR3(VReg_16B rd, VReg_16B rn, VReg_16B rm, VReg_16B ra) +{ + emit<"11001110000mmmmm0aaaaannnnnddddd", "d", "n", "m", "a">(rd, rn, rm, ra); +} +void FABD(HReg rd, HReg rn, HReg rm) +{ + emit<"01111110110mmmmm000101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FABD(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110110mmmmm000101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FABD(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110110mmmmm000101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FABS(VReg_4H rd, VReg_4H rn) +{ + emit<"0000111011111000111110nnnnnddddd", "d", "n">(rd, rn); +} +void FABS(VReg_8H rd, VReg_8H rn) +{ + emit<"0100111011111000111110nnnnnddddd", "d", "n">(rd, rn); +} +void FACGE(HReg rd, HReg rn, HReg rm) +{ + emit<"01111110010mmmmm001011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FACGE(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110010mmmmm001011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FACGE(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110010mmmmm001011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FACGT(HReg rd, HReg rn, HReg rm) +{ + emit<"01111110110mmmmm001011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FACGT(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110110mmmmm001011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FACGT(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110110mmmmm001011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FADD(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00001110010mmmmm000101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FADD(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01001110010mmmmm000101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FADDP(HReg rd, VReg_2H rn) +{ + emit<"0101111000110000110110nnnnnddddd", "d", "n">(rd, rn); +} +void FADDP(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110010mmmmm000101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FADDP(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110010mmmmm000101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FCMEQ(HReg rd, HReg rn, HReg rm) +{ + emit<"01011110010mmmmm001001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FCMEQ(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00001110010mmmmm001001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FCMEQ(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01001110010mmmmm001001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FCMEQ(HReg rd, HReg rn, ImmConstFZero) +{ + emit<"0101111011111000110110nnnnnddddd", "d", "n">(rd, rn); +} +void FCMEQ(VReg_4H rd, VReg_4H rn, ImmConstFZero) +{ + emit<"0000111011111000110110nnnnnddddd", "d", "n">(rd, rn); +} +void FCMEQ(VReg_8H rd, VReg_8H rn, ImmConstFZero) +{ + emit<"0100111011111000110110nnnnnddddd", "d", "n">(rd, rn); +} +void FCMGE(HReg rd, HReg rn, HReg rm) +{ + emit<"01111110010mmmmm001001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FCMGE(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110010mmmmm001001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FCMGE(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110010mmmmm001001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FCMGE(HReg rd, HReg rn, ImmConstFZero) +{ + emit<"0111111011111000110010nnnnnddddd", "d", "n">(rd, rn); +} +void FCMGE(VReg_4H rd, VReg_4H rn, ImmConstFZero) +{ + emit<"0010111011111000110010nnnnnddddd", "d", "n">(rd, rn); +} +void FCMGE(VReg_8H rd, VReg_8H rn, ImmConstFZero) +{ + emit<"0110111011111000110010nnnnnddddd", "d", "n">(rd, rn); +} +void FCMGT(HReg rd, HReg rn, HReg rm) +{ + emit<"01111110110mmmmm001001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FCMGT(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110110mmmmm001001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FCMGT(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110110mmmmm001001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FCMGT(HReg rd, HReg rn, ImmConstFZero) +{ + emit<"0101111011111000110010nnnnnddddd", "d", "n">(rd, rn); +} +void FCMGT(VReg_4H rd, VReg_4H rn, ImmConstFZero) +{ + emit<"0000111011111000110010nnnnnddddd", "d", "n">(rd, rn); +} +void FCMGT(VReg_8H rd, VReg_8H rn, ImmConstFZero) +{ + emit<"0100111011111000110010nnnnnddddd", "d", "n">(rd, rn); +} +void FCMLE(HReg rd, HReg rn, ImmConstFZero) +{ + emit<"0111111011111000110110nnnnnddddd", "d", "n">(rd, rn); +} +void FCMLE(VReg_4H rd, VReg_4H rn, ImmConstFZero) +{ + emit<"0010111011111000110110nnnnnddddd", "d", "n">(rd, rn); +} +void FCMLE(VReg_8H rd, VReg_8H rn, ImmConstFZero) +{ + emit<"0110111011111000110110nnnnnddddd", "d", "n">(rd, rn); +} +void FCMLT(HReg rd, HReg rn, ImmConstFZero) +{ + emit<"0101111011111000111010nnnnnddddd", "d", "n">(rd, rn); +} +void FCMLT(VReg_4H rd, VReg_4H rn, ImmConstFZero) +{ + emit<"0000111011111000111010nnnnnddddd", "d", "n">(rd, rn); +} +void FCMLT(VReg_8H rd, VReg_8H rn, ImmConstFZero) +{ + emit<"0100111011111000111010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTAS(HReg rd, HReg rn) +{ + emit<"0101111001111001110010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTAS(VReg_4H rd, VReg_4H rn) +{ + emit<"0000111001111001110010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTAS(VReg_8H rd, VReg_8H rn) +{ + emit<"0100111001111001110010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTAU(HReg rd, HReg rn) +{ + emit<"0111111001111001110010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTAU(VReg_4H rd, VReg_4H rn) +{ + emit<"0010111001111001110010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTAU(VReg_8H rd, VReg_8H rn) +{ + emit<"0110111001111001110010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTMS(HReg rd, HReg rn) +{ + emit<"0101111001111001101110nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTMS(VReg_4H rd, VReg_4H rn) +{ + emit<"0000111001111001101110nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTMS(VReg_8H rd, VReg_8H rn) +{ + emit<"0100111001111001101110nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTMU(HReg rd, HReg rn) +{ + emit<"0111111001111001101110nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTMU(VReg_4H rd, VReg_4H rn) +{ + emit<"0010111001111001101110nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTMU(VReg_8H rd, VReg_8H rn) +{ + emit<"0110111001111001101110nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTNS(HReg rd, HReg rn) +{ + emit<"0101111001111001101010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTNS(VReg_4H rd, VReg_4H rn) +{ + emit<"0000111001111001101010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTNS(VReg_8H rd, VReg_8H rn) +{ + emit<"0100111001111001101010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTNU(HReg rd, HReg rn) +{ + emit<"0111111001111001101010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTNU(VReg_4H rd, VReg_4H rn) +{ + emit<"0010111001111001101010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTNU(VReg_8H rd, VReg_8H rn) +{ + emit<"0110111001111001101010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTPS(HReg rd, HReg rn) +{ + emit<"0101111011111001101010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTPS(VReg_4H rd, VReg_4H rn) +{ + emit<"0000111011111001101010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTPS(VReg_8H rd, VReg_8H rn) +{ + emit<"0100111011111001101010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTPU(HReg rd, HReg rn) +{ + emit<"0111111011111001101010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTPU(VReg_4H rd, VReg_4H rn) +{ + emit<"0010111011111001101010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTPU(VReg_8H rd, VReg_8H rn) +{ + emit<"0110111011111001101010nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTZS(HReg rd, HReg rn) +{ + emit<"0101111011111001101110nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTZS(VReg_4H rd, VReg_4H rn) +{ + emit<"0000111011111001101110nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTZS(VReg_8H rd, VReg_8H rn) +{ + emit<"0100111011111001101110nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTZU(HReg rd, HReg rn) +{ + emit<"0111111011111001101110nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTZU(VReg_4H rd, VReg_4H rn) +{ + emit<"0010111011111001101110nnnnnddddd", "d", "n">(rd, rn); +} +void FCVTZU(VReg_8H rd, VReg_8H rn) +{ + emit<"0110111011111001101110nnnnnddddd", "d", "n">(rd, rn); +} +void FDIV(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110010mmmmm001111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FDIV(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110010mmmmm001111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMAX(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00001110010mmmmm001101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMAX(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01001110010mmmmm001101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMAXNM(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00001110010mmmmm000001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMAXNM(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01001110010mmmmm000001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMAXNMP(HReg rd, VReg_2H rn) +{ + emit<"0101111000110000110010nnnnnddddd", "d", "n">(rd, rn); +} +void FMAXNMP(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110010mmmmm000001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMAXNMP(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110010mmmmm000001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMAXNMV(HReg rd, VReg_4H rn) +{ + emit<"0000111000110000110010nnnnnddddd", "d", "n">(rd, rn); +} +void FMAXNMV(HReg rd, VReg_8H rn) +{ + emit<"0100111000110000110010nnnnnddddd", "d", "n">(rd, rn); +} +void FMAXP(HReg rd, VReg_2H rn) +{ + emit<"0101111000110000111110nnnnnddddd", "d", "n">(rd, rn); +} +void FMAXP(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110010mmmmm001101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMAXP(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110010mmmmm001101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMAXV(HReg rd, VReg_4H rn) +{ + emit<"0000111000110000111110nnnnnddddd", "d", "n">(rd, rn); +} +void FMAXV(HReg rd, VReg_8H rn) +{ + emit<"0100111000110000111110nnnnnddddd", "d", "n">(rd, rn); +} +void FMIN(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00001110110mmmmm001101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMIN(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01001110110mmmmm001101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMINNM(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00001110110mmmmm000001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMINNM(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01001110110mmmmm000001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMINNMP(HReg rd, VReg_2H rn) +{ + emit<"0101111010110000110010nnnnnddddd", "d", "n">(rd, rn); +} +void FMINNMP(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110110mmmmm000001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMINNMP(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110110mmmmm000001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMINNMV(HReg rd, VReg_4H rn) +{ + emit<"0000111010110000110010nnnnnddddd", "d", "n">(rd, rn); +} +void FMINNMV(HReg rd, VReg_8H rn) +{ + emit<"0100111010110000110010nnnnnddddd", "d", "n">(rd, rn); +} +void FMINP(HReg rd, VReg_2H rn) +{ + emit<"0101111010110000111110nnnnnddddd", "d", "n">(rd, rn); +} +void FMINP(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110110mmmmm001101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMINP(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110110mmmmm001101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMINV(HReg rd, VReg_4H rn) +{ + emit<"0000111010110000111110nnnnnddddd", "d", "n">(rd, rn); +} +void FMINV(HReg rd, VReg_8H rn) +{ + emit<"0100111010110000111110nnnnnddddd", "d", "n">(rd, rn); +} +void FMLA(HReg rd, HReg rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0101111100LMmmmm0001H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLA(VReg_8B rd, VReg_8B rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0000111100LMmmmm0001H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLA(VReg_16B rd, VReg_16B rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0100111100LMmmmm0001H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLA(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00001110010mmmmm000011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMLA(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01001110010mmmmm000011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMLAL(VReg_2S rd, VReg_2H rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0000111110LMmmmm0000H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLAL(VReg_4S rd, VReg_4H rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0100111110LMmmmm0000H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLAL2(VReg_2S rd, VReg_2H rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0010111110LMmmmm1000H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLAL2(VReg_4S rd, VReg_4H rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0110111110LMmmmm1000H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLAL(VReg_2S rd, VReg_2H rn, VReg_2H rm) +{ + emit<"00001110001mmmmm111011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMLAL(VReg_4S rd, VReg_4H rn, VReg_4H rm) +{ + emit<"01001110001mmmmm111011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMLAL2(VReg_2S rd, VReg_2H rn, VReg_2H rm) +{ + emit<"00101110001mmmmm110011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMLAL2(VReg_4S rd, VReg_4H rn, VReg_4H rm) +{ + emit<"01101110001mmmmm110011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMLS(HReg rd, HReg rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0101111100LMmmmm0101H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLS(VReg_8B rd, VReg_8B rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0000111100LMmmmm0101H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLS(VReg_16B rd, VReg_16B rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0100111100LMmmmm0101H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLS(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00001110110mmmmm000011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMLS(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01001110110mmmmm000011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMLSL(VReg_2S rd, VReg_2H rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0000111110LMmmmm0100H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLSL(VReg_4S rd, VReg_4H rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0100111110LMmmmm0100H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLSL2(VReg_2S rd, VReg_2H rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0010111110LMmmmm1100H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLSL2(VReg_4S rd, VReg_4H rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0110111110LMmmmm1100H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMLSL(VReg_2S rd, VReg_2H rn, VReg_2H rm) +{ + emit<"00001110101mmmmm111011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMLSL(VReg_4S rd, VReg_4H rn, VReg_4H rm) +{ + emit<"01001110101mmmmm111011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMLSL2(VReg_2S rd, VReg_2H rn, VReg_2H rm) +{ + emit<"00101110101mmmmm110011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMLSL2(VReg_4S rd, VReg_4H rn, VReg_4H rm) +{ + emit<"01101110101mmmmm110011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMOV(VReg_4H rd, FImm8 imm) +{ + emit<"0000111100000vvv111111vvvvvddddd", "d", "v">(rd, imm); +} +void FMOV(VReg_8H rd, FImm8 imm) +{ + emit<"0100111100000vvv111111vvvvvddddd", "d", "v">(rd, imm); +} +void FMUL(HReg rd, HReg rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0101111100LMmmmm1001H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMUL(VReg_8B rd, VReg_8B rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0000111100LMmmmm1001H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMUL(VReg_16B rd, VReg_16B rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0100111100LMmmmm1001H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMUL(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00101110010mmmmm000111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMUL(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01101110010mmmmm000111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMULX(HReg rd, HReg rn, HReg rm) +{ + emit<"01011110010mmmmm000111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMULX(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00001110010mmmmm000111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMULX(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01001110010mmmmm000111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FMULX(HReg rd, HReg rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0111111100LMmmmm1001H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMULX(VReg_8B rd, VReg_8B rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0010111100LMmmmm1001H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FMULX(VReg_16B rd, VReg_16B rn, HElem em) +{ + if (em.reg_index() >= 16) + throw "InvalidCombination"; + emit<"0110111100LMmmmm1001H0nnnnnddddd", "d", "n", "m", "H", "L", "M">(rd, rn, em.reg_index(), em.elem_index() >> 2, (em.elem_index() >> 1) & 1, em.elem_index() & 1); +} +void FNEG(VReg_4H rd, VReg_4H rn) +{ + emit<"0010111011111000111110nnnnnddddd", "d", "n">(rd, rn); +} +void FNEG(VReg_8H rd, VReg_8H rn) +{ + emit<"0110111011111000111110nnnnnddddd", "d", "n">(rd, rn); +} +void FRECPE(HReg rd, HReg rn) +{ + emit<"0101111011111001110110nnnnnddddd", "d", "n">(rd, rn); +} +void FRECPE(VReg_4H rd, VReg_4H rn) +{ + emit<"0000111011111001110110nnnnnddddd", "d", "n">(rd, rn); +} +void FRECPE(VReg_8H rd, VReg_8H rn) +{ + emit<"0100111011111001110110nnnnnddddd", "d", "n">(rd, rn); +} +void FRECPS(HReg rd, HReg rn, HReg rm) +{ + emit<"01011110010mmmmm001111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FRECPS(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00001110010mmmmm001111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FRECPS(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01001110010mmmmm001111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FRECPX(HReg rd, HReg rn) +{ + emit<"0101111011111001111110nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTA(VReg_4H rd, VReg_4H rn) +{ + emit<"0010111001111001100010nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTA(VReg_8H rd, VReg_8H rn) +{ + emit<"0110111001111001100010nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTI(VReg_4H rd, VReg_4H rn) +{ + emit<"0010111011111001100110nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTI(VReg_8H rd, VReg_8H rn) +{ + emit<"0110111011111001100110nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTM(VReg_4H rd, VReg_4H rn) +{ + emit<"0000111001111001100110nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTM(VReg_8H rd, VReg_8H rn) +{ + emit<"0100111001111001100110nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTN(VReg_4H rd, VReg_4H rn) +{ + emit<"0000111001111001100010nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTN(VReg_8H rd, VReg_8H rn) +{ + emit<"0100111001111001100010nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTP(VReg_4H rd, VReg_4H rn) +{ + emit<"0000111011111001100010nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTP(VReg_8H rd, VReg_8H rn) +{ + emit<"0100111011111001100010nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTX(VReg_4H rd, VReg_4H rn) +{ + emit<"0010111001111001100110nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTX(VReg_8H rd, VReg_8H rn) +{ + emit<"0110111001111001100110nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTZ(VReg_4H rd, VReg_4H rn) +{ + emit<"0000111011111001100110nnnnnddddd", "d", "n">(rd, rn); +} +void FRINTZ(VReg_8H rd, VReg_8H rn) +{ + emit<"0100111011111001100110nnnnnddddd", "d", "n">(rd, rn); +} +void FRSQRTE(HReg rd, HReg rn) +{ + emit<"0111111011111001110110nnnnnddddd", "d", "n">(rd, rn); +} +void FRSQRTE(VReg_4H rd, VReg_4H rn) +{ + emit<"0010111011111001110110nnnnnddddd", "d", "n">(rd, rn); +} +void FRSQRTE(VReg_8H rd, VReg_8H rn) +{ + emit<"0110111011111001110110nnnnnddddd", "d", "n">(rd, rn); +} +void FRSQRTS(HReg rd, HReg rn, HReg rm) +{ + emit<"01011110110mmmmm001111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FRSQRTS(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00001110110mmmmm001111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FRSQRTS(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01001110110mmmmm001111nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FSQRT(VReg_4H rd, VReg_4H rn) +{ + emit<"0010111011111001111110nnnnnddddd", "d", "n">(rd, rn); +} +void FSQRT(VReg_8H rd, VReg_8H rn) +{ + emit<"0110111011111001111110nnnnnddddd", "d", "n">(rd, rn); +} +void FSUB(VReg_4H rd, VReg_4H rn, VReg_4H rm) +{ + emit<"00001110110mmmmm000101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void FSUB(VReg_8H rd, VReg_8H rn, VReg_8H rm) +{ + emit<"01001110110mmmmm000101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void RAX1(VReg_2D rd, VReg_2D rn, VReg_2D rm) +{ + emit<"11001110011mmmmm100011nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SCVTF(HReg rd, HReg rn) +{ + emit<"0101111001111001110110nnnnnddddd", "d", "n">(rd, rn); +} +void SCVTF(VReg_4H rd, VReg_4H rn) +{ + emit<"0000111001111001110110nnnnnddddd", "d", "n">(rd, rn); +} +void SCVTF(VReg_8H rd, VReg_8H rn) +{ + emit<"0100111001111001110110nnnnnddddd", "d", "n">(rd, rn); +} +void SDOT(VReg_2S rd, VReg_8B rn, SElem em) +{ + emit<"0000111110LMmmmm1110H0nnnnnddddd", "d", "n", "Mm", "H", "L">(rd, rn, em.reg_index(), em.elem_index() >> 1, em.elem_index() & 1); +} +void SDOT(VReg_4S rd, VReg_16B rn, SElem em) +{ + emit<"0100111110LMmmmm1110H0nnnnnddddd", "d", "n", "Mm", "H", "L">(rd, rn, em.reg_index(), em.elem_index() >> 1, em.elem_index() & 1); +} +void SDOT(VReg_2S rd, VReg_8B rn, VReg_8B rm) +{ + emit<"00001110100mmmmm100101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SDOT(VReg_4S rd, VReg_16B rn, VReg_16B rm) +{ + emit<"01001110100mmmmm100101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SHA512H(QReg rd, QReg rn, VReg_2D rm) +{ + emit<"11001110011mmmmm100000nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SHA512H2(QReg rd, QReg rn, VReg_2D rm) +{ + emit<"11001110011mmmmm100001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SHA512SU0(VReg_2D rd, VReg_2D rn) +{ + emit<"1100111011000000100000nnnnnddddd", "d", "n">(rd, rn); +} +void SHA512SU1(VReg_2D rd, VReg_2D rn, VReg_2D rm) +{ + emit<"11001110011mmmmm100010nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SM3PARTW1(VReg_4S rd, VReg_4S rn, VReg_4S rm) +{ + emit<"11001110011mmmmm110000nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SM3PARTW2(VReg_4S rd, VReg_4S rn, VReg_4S rm) +{ + emit<"11001110011mmmmm110001nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void SM3SS1(VReg_4S rd, VReg_4S rn, VReg_4S rm, VReg_4S ra) +{ + emit<"11001110010mmmmm0aaaaannnnnddddd", "d", "n", "m", "a">(rd, rn, rm, ra); +} +void SM3TT1A(VReg_4S rd, VReg_4S rn, SElem em) +{ + emit<"11001110010mmmmm10ii00nnnnnddddd", "d", "n", "m", "i">(rd, rn, em.reg_index(), em.elem_index()); +} +void SM3TT1B(VReg_4S rd, VReg_4S rn, SElem em) +{ + emit<"11001110010mmmmm10ii01nnnnnddddd", "d", "n", "m", "i">(rd, rn, em.reg_index(), em.elem_index()); +} +void SM3TT2A(VReg_4S rd, VReg_4S rn, SElem em) +{ + emit<"11001110010mmmmm10ii10nnnnnddddd", "d", "n", "m", "i">(rd, rn, em.reg_index(), em.elem_index()); +} +void SM3TT2B(VReg_4S rd, VReg_4S rn, SElem em) +{ + emit<"11001110010mmmmm10ii11nnnnnddddd", "d", "n", "m", "i">(rd, rn, em.reg_index(), em.elem_index()); +} +void SM4E(VReg_4S rd, VReg_4S rn) +{ + emit<"1100111011000000100001nnnnnddddd", "d", "n">(rd, rn); +} +void SM4EKEY(VReg_4S rd, VReg_4S rn, VReg_4S rm) +{ + emit<"11001110011mmmmm110010nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void UCVTF(HReg rd, HReg rn) +{ + emit<"0111111001111001110110nnnnnddddd", "d", "n">(rd, rn); +} +void UCVTF(VReg_4H rd, VReg_4H rn) +{ + emit<"0010111001111001110110nnnnnddddd", "d", "n">(rd, rn); +} +void UCVTF(VReg_8H rd, VReg_8H rn) +{ + emit<"0110111001111001110110nnnnnddddd", "d", "n">(rd, rn); +} +void UDOT(VReg_2S rd, VReg_8B rn, SElem em) +{ + emit<"0010111110LMmmmm1110H0nnnnnddddd", "d", "n", "Mm", "H", "L">(rd, rn, em.reg_index(), em.elem_index() >> 1, em.elem_index() & 1); +} +void UDOT(VReg_4S rd, VReg_16B rn, SElem em) +{ + emit<"0110111110LMmmmm1110H0nnnnnddddd", "d", "n", "Mm", "H", "L">(rd, rn, em.reg_index(), em.elem_index() >> 1, em.elem_index() & 1); +} +void UDOT(VReg_2S rd, VReg_8B rn, VReg_8B rm) +{ + emit<"00101110100mmmmm100101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void UDOT(VReg_4S rd, VReg_16B rn, VReg_16B rm) +{ + emit<"01101110100mmmmm100101nnnnnddddd", "d", "n", "m">(rd, rn, rm); +} +void XAR(VReg_2D rd, VReg_2D rn, VReg_2D rm, Imm<6> rotate_amount) +{ + emit<"11001110100mmmmmiiiiiinnnnnddddd", "d", "n", "m", "i">(rd, rn, rm, rotate_amount); +} diff --git a/include/oaknut/impl/arm64_mnemonics.inc.hpp b/include/oaknut/impl/mnemonics_generic_v8.0.inc.hpp similarity index 99% rename from include/oaknut/impl/arm64_mnemonics.inc.hpp rename to include/oaknut/impl/mnemonics_generic_v8.0.inc.hpp index 7fd65f05..160dd8f9 100644 --- a/include/oaknut/impl/arm64_mnemonics.inc.hpp +++ b/include/oaknut/impl/mnemonics_generic_v8.0.inc.hpp @@ -87,11 +87,11 @@ void ADDS(XReg xd, XReg xn, XReg xm, AddSubShift shift = AddSubShift::LSL, Imm<6 { emit<"10101011ss0mmmmmiiiiiinnnnnddddd", "d", "n", "m", "s", "i">(xd, xn, xm, shift, shift_amount); } -void ADR(XReg xd, AddrOffset<21, 0> label) +void ADR(XReg xd, PageOffset<21, 0> label) { emit<"0ii10000iiiiiiiiiiiiiiiiiiiddddd", "d", "i">(xd, label); } -void ADRP(XReg xd, PageOffset<21> label) +void ADRP(XReg xd, PageOffset<21, 12> label) { emit<"1ii10000iiiiiiiiiiiiiiiiiiiddddd", "d", "i">(xd, label); } diff --git a/include/oaknut/impl/mnemonics_generic_v8.1.inc.hpp b/include/oaknut/impl/mnemonics_generic_v8.1.inc.hpp new file mode 100644 index 00000000..66ddd7c5 --- /dev/null +++ b/include/oaknut/impl/mnemonics_generic_v8.1.inc.hpp @@ -0,0 +1,1027 @@ +// SPDX-FileCopyrightText: Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +void CAS(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10001000101sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASA(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10001000111sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASAL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10001000111sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10001000101sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CAS(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11001000101sssss011111nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void CASA(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11001000111sssss011111nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void CASAL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11001000111sssss111111nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void CASL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11001000101sssss111111nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void CASAB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00001000111sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASALB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00001000111sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00001000101sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASLB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00001000101sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASAH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01001000111sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASALH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01001000111sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01001000101sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASLH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01001000101sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASP(WReg ws, WReg ws2, WReg wt, WReg wt2, XRegSp xn) +{ + if (wt.index() + 1 != wt2.index()) + throw "Invalid second register in pair"; + if (wt.index() & 1) + throw "Requires even register"; + if (ws.index() + 1 != ws2.index()) + throw "Invalid second register in pair"; + if (ws.index() & 1) + throw "Requires even register"; + emit<"00001000001sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASPA(WReg ws, WReg ws2, WReg wt, WReg wt2, XRegSp xn) +{ + if (wt.index() + 1 != wt2.index()) + throw "Invalid second register in pair"; + if (wt.index() & 1) + throw "Requires even register"; + if (ws.index() + 1 != ws2.index()) + throw "Invalid second register in pair"; + if (ws.index() & 1) + throw "Requires even register"; + emit<"00001000011sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASPAL(WReg ws, WReg ws2, WReg wt, WReg wt2, XRegSp xn) +{ + if (wt.index() + 1 != wt2.index()) + throw "Invalid second register in pair"; + if (wt.index() & 1) + throw "Requires even register"; + if (ws.index() + 1 != ws2.index()) + throw "Invalid second register in pair"; + if (ws.index() & 1) + throw "Requires even register"; + emit<"00001000011sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASPL(WReg ws, WReg ws2, WReg wt, WReg wt2, XRegSp xn) +{ + if (wt.index() + 1 != wt2.index()) + throw "Invalid second register in pair"; + if (wt.index() & 1) + throw "Requires even register"; + if (ws.index() + 1 != ws2.index()) + throw "Invalid second register in pair"; + if (ws.index() & 1) + throw "Requires even register"; + emit<"00001000001sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void CASP(XReg xs, XReg xs2, XReg xt, XReg xt2, XRegSp xn) +{ + if (xt.index() + 1 != xt2.index()) + throw "Invalid second register in pair"; + if (xt.index() & 1) + throw "Requires even register"; + if (xs.index() + 1 != xs2.index()) + throw "Invalid second register in pair"; + if (xs.index() & 1) + throw "Requires even register"; + emit<"01001000001sssss011111nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void CASPA(XReg xs, XReg xs2, XReg xt, XReg xt2, XRegSp xn) +{ + if (xt.index() + 1 != xt2.index()) + throw "Invalid second register in pair"; + if (xt.index() & 1) + throw "Requires even register"; + if (xs.index() + 1 != xs2.index()) + throw "Invalid second register in pair"; + if (xs.index() & 1) + throw "Requires even register"; + emit<"01001000011sssss011111nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void CASPAL(XReg xs, XReg xs2, XReg xt, XReg xt2, XRegSp xn) +{ + if (xt.index() + 1 != xt2.index()) + throw "Invalid second register in pair"; + if (xt.index() & 1) + throw "Requires even register"; + if (xs.index() + 1 != xs2.index()) + throw "Invalid second register in pair"; + if (xs.index() & 1) + throw "Requires even register"; + emit<"01001000011sssss111111nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void CASPL(XReg xs, XReg xs2, XReg xt, XReg xt2, XRegSp xn) +{ + if (xt.index() + 1 != xt2.index()) + throw "Invalid second register in pair"; + if (xt.index() & 1) + throw "Requires even register"; + if (xs.index() + 1 != xs2.index()) + throw "Invalid second register in pair"; + if (xs.index() & 1) + throw "Requires even register"; + emit<"01001000001sssss111111nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDADD(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000001sssss000000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDADDA(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000101sssss000000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDADDAL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000111sssss000000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDADDL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000011sssss000000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDADD(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000001sssss000000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDADDA(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000101sssss000000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDADDAL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000111sssss000000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDADDL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000011sssss000000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDADDAB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000101sssss000000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDADDALB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000111sssss000000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDADDB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000001sssss000000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDADDLB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000011sssss000000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDADDAH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000101sssss000000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDADDALH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000111sssss000000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDADDH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000001sssss000000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDADDLH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000011sssss000000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDCLR(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000001sssss000100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDCLRA(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000101sssss000100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDCLRAL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000111sssss000100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDCLRL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000011sssss000100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDCLR(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000001sssss000100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDCLRA(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000101sssss000100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDCLRAL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000111sssss000100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDCLRL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000011sssss000100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDCLRAB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000101sssss000100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDCLRALB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000111sssss000100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDCLRB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000001sssss000100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDCLRLB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000011sssss000100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDCLRAH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000101sssss000100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDCLRALH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000111sssss000100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDCLRH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000001sssss000100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDCLRLH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000011sssss000100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDEOR(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000001sssss001000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDEORA(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000101sssss001000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDEORAL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000111sssss001000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDEORL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000011sssss001000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDEOR(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000001sssss001000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDEORA(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000101sssss001000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDEORAL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000111sssss001000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDEORL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000011sssss001000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDEORAB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000101sssss001000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDEORALB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000111sssss001000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDEORB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000001sssss001000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDEORLB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000011sssss001000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDEORAH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000101sssss001000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDEORALH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000111sssss001000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDEORH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000001sssss001000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDEORLH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000011sssss001000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDLAR(WReg wt, XRegSp xn) +{ + emit<"1000100011011111011111nnnnnttttt", "t", "n">(wt, xn); +} +void LDLAR(XReg xt, XRegSp xn) +{ + emit<"1100100011011111011111nnnnnttttt", "t", "n">(xt, xn); +} +void LDLARB(WReg wt, XRegSp xn) +{ + emit<"0000100011011111011111nnnnnttttt", "t", "n">(wt, xn); +} +void LDLARH(WReg wt, XRegSp xn) +{ + emit<"0100100011011111011111nnnnnttttt", "t", "n">(wt, xn); +} +void LDSET(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000001sssss001100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSETA(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000101sssss001100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSETAL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000111sssss001100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSETL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000011sssss001100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSET(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000001sssss001100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDSETA(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000101sssss001100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDSETAL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000111sssss001100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDSETL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000011sssss001100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDSETAB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000101sssss001100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSETALB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000111sssss001100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSETB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000001sssss001100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSETLB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000011sssss001100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSETAH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000101sssss001100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSETALH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000111sssss001100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSETH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000001sssss001100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSETLH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000011sssss001100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMAX(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000001sssss010000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMAXA(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000101sssss010000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMAXAL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000111sssss010000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMAXL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000011sssss010000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMAX(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000001sssss010000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDSMAXA(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000101sssss010000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDSMAXAL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000111sssss010000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDSMAXL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000011sssss010000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDSMAXAB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000101sssss010000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMAXALB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000111sssss010000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMAXB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000001sssss010000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMAXLB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000011sssss010000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMAXAH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000101sssss010000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMAXALH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000111sssss010000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMAXH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000001sssss010000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMAXLH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000011sssss010000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMIN(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000001sssss010100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMINA(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000101sssss010100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMINAL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000111sssss010100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMINL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000011sssss010100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMIN(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000001sssss010100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDSMINA(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000101sssss010100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDSMINAL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000111sssss010100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDSMINL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000011sssss010100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDSMINAB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000101sssss010100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMINALB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000111sssss010100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMINB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000001sssss010100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMINLB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000011sssss010100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMINAH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000101sssss010100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMINALH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000111sssss010100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMINH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000001sssss010100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDSMINLH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000011sssss010100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMAX(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000001sssss011000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMAXA(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000101sssss011000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMAXAL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000111sssss011000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMAXL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000011sssss011000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMAX(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000001sssss011000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDUMAXA(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000101sssss011000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDUMAXAL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000111sssss011000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDUMAXL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000011sssss011000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDUMAXAB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000101sssss011000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMAXALB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000111sssss011000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMAXB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000001sssss011000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMAXLB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000011sssss011000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMAXAH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000101sssss011000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMAXALH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000111sssss011000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMAXH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000001sssss011000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMAXLH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000011sssss011000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMIN(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000001sssss011100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMINA(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000101sssss011100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMINAL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000111sssss011100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMINL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000011sssss011100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMIN(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000001sssss011100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDUMINA(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000101sssss011100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDUMINAL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000111sssss011100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDUMINL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000011sssss011100nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void LDUMINAB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000101sssss011100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMINALB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000111sssss011100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMINB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000001sssss011100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMINLB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000011sssss011100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMINAH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000101sssss011100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMINALH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000111sssss011100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMINH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000001sssss011100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void LDUMINLH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000011sssss011100nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void STADD(WReg ws, XRegSp xn) +{ + emit<"10111000001sssss000000nnnnn11111", "s", "n">(ws, xn); +} +void STADDL(WReg ws, XRegSp xn) +{ + emit<"10111000011sssss000000nnnnn11111", "s", "n">(ws, xn); +} +void STADD(XReg xs, XRegSp xn) +{ + emit<"11111000001sssss000000nnnnn11111", "s", "n">(xs, xn); +} +void STADDL(XReg xs, XRegSp xn) +{ + emit<"11111000011sssss000000nnnnn11111", "s", "n">(xs, xn); +} +void STADDB(WReg ws, XRegSp xn) +{ + emit<"00111000001sssss000000nnnnn11111", "s", "n">(ws, xn); +} +void STADDLB(WReg ws, XRegSp xn) +{ + emit<"00111000011sssss000000nnnnn11111", "s", "n">(ws, xn); +} +void STADDH(WReg ws, XRegSp xn) +{ + emit<"01111000001sssss000000nnnnn11111", "s", "n">(ws, xn); +} +void STADDLH(WReg ws, XRegSp xn) +{ + emit<"01111000011sssss000000nnnnn11111", "s", "n">(ws, xn); +} +void STCLR(WReg ws, XRegSp xn) +{ + emit<"10111000001sssss000100nnnnn11111", "s", "n">(ws, xn); +} +void STCLRL(WReg ws, XRegSp xn) +{ + emit<"10111000011sssss000100nnnnn11111", "s", "n">(ws, xn); +} +void STCLR(XReg xs, XRegSp xn) +{ + emit<"11111000001sssss000100nnnnn11111", "s", "n">(xs, xn); +} +void STCLRL(XReg xs, XRegSp xn) +{ + emit<"11111000011sssss000100nnnnn11111", "s", "n">(xs, xn); +} +void STCLRB(WReg ws, XRegSp xn) +{ + emit<"00111000001sssss000100nnnnn11111", "s", "n">(ws, xn); +} +void STCLRLB(WReg ws, XRegSp xn) +{ + emit<"00111000011sssss000100nnnnn11111", "s", "n">(ws, xn); +} +void STCLRH(WReg ws, XRegSp xn) +{ + emit<"01111000001sssss000100nnnnn11111", "s", "n">(ws, xn); +} +void STCLRLH(WReg ws, XRegSp xn) +{ + emit<"01111000011sssss000100nnnnn11111", "s", "n">(ws, xn); +} +void STEOR(WReg ws, XRegSp xn) +{ + emit<"10111000001sssss001000nnnnn11111", "s", "n">(ws, xn); +} +void STEORL(WReg ws, XRegSp xn) +{ + emit<"10111000011sssss001000nnnnn11111", "s", "n">(ws, xn); +} +void STEOR(XReg xs, XRegSp xn) +{ + emit<"11111000001sssss001000nnnnn11111", "s", "n">(xs, xn); +} +void STEORL(XReg xs, XRegSp xn) +{ + emit<"11111000011sssss001000nnnnn11111", "s", "n">(xs, xn); +} +void STEORB(WReg ws, XRegSp xn) +{ + emit<"00111000001sssss001000nnnnn11111", "s", "n">(ws, xn); +} +void STEORLB(WReg ws, XRegSp xn) +{ + emit<"00111000011sssss001000nnnnn11111", "s", "n">(ws, xn); +} +void STEORH(WReg ws, XRegSp xn) +{ + emit<"01111000001sssss001000nnnnn11111", "s", "n">(ws, xn); +} +void STEORLH(WReg ws, XRegSp xn) +{ + emit<"01111000011sssss001000nnnnn11111", "s", "n">(ws, xn); +} +void STLLR(WReg wt, XRegSp xn) +{ + emit<"1000100010011111011111nnnnnttttt", "t", "n">(wt, xn); +} +void STLLR(XReg xt, XRegSp xn) +{ + emit<"1100100010011111011111nnnnnttttt", "t", "n">(xt, xn); +} +void STLLRB(WReg wt, XRegSp xn) +{ + emit<"0000100010011111011111nnnnnttttt", "t", "n">(wt, xn); +} +void STLLRH(WReg wt, XRegSp xn) +{ + emit<"0100100010011111011111nnnnnttttt", "t", "n">(wt, xn); +} +void STSET(WReg ws, XRegSp xn) +{ + emit<"10111000001sssss001100nnnnn11111", "s", "n">(ws, xn); +} +void STSETL(WReg ws, XRegSp xn) +{ + emit<"10111000011sssss001100nnnnn11111", "s", "n">(ws, xn); +} +void STSET(XReg xs, XRegSp xn) +{ + emit<"11111000001sssss001100nnnnn11111", "s", "n">(xs, xn); +} +void STSETL(XReg xs, XRegSp xn) +{ + emit<"11111000011sssss001100nnnnn11111", "s", "n">(xs, xn); +} +void STSETB(WReg ws, XRegSp xn) +{ + emit<"00111000001sssss001100nnnnn11111", "s", "n">(ws, xn); +} +void STSETLB(WReg ws, XRegSp xn) +{ + emit<"00111000011sssss001100nnnnn11111", "s", "n">(ws, xn); +} +void STSETH(WReg ws, XRegSp xn) +{ + emit<"01111000001sssss001100nnnnn11111", "s", "n">(ws, xn); +} +void STSETLH(WReg ws, XRegSp xn) +{ + emit<"01111000011sssss001100nnnnn11111", "s", "n">(ws, xn); +} +void STSMAX(WReg ws, XRegSp xn) +{ + emit<"10111000001sssss010000nnnnn11111", "s", "n">(ws, xn); +} +void STSMAXL(WReg ws, XRegSp xn) +{ + emit<"10111000011sssss010000nnnnn11111", "s", "n">(ws, xn); +} +void STSMAX(XReg xs, XRegSp xn) +{ + emit<"11111000001sssss010000nnnnn11111", "s", "n">(xs, xn); +} +void STSMAXL(XReg xs, XRegSp xn) +{ + emit<"11111000011sssss010000nnnnn11111", "s", "n">(xs, xn); +} +void STSMAXB(WReg ws, XRegSp xn) +{ + emit<"00111000001sssss010000nnnnn11111", "s", "n">(ws, xn); +} +void STSMAXLB(WReg ws, XRegSp xn) +{ + emit<"00111000011sssss010000nnnnn11111", "s", "n">(ws, xn); +} +void STSMAXH(WReg ws, XRegSp xn) +{ + emit<"01111000001sssss010000nnnnn11111", "s", "n">(ws, xn); +} +void STSMAXLH(WReg ws, XRegSp xn) +{ + emit<"01111000011sssss010000nnnnn11111", "s", "n">(ws, xn); +} +void STSMIN(WReg ws, XRegSp xn) +{ + emit<"10111000001sssss010100nnnnn11111", "s", "n">(ws, xn); +} +void STSMINL(WReg ws, XRegSp xn) +{ + emit<"10111000011sssss010100nnnnn11111", "s", "n">(ws, xn); +} +void STSMIN(XReg xs, XRegSp xn) +{ + emit<"11111000001sssss010100nnnnn11111", "s", "n">(xs, xn); +} +void STSMINL(XReg xs, XRegSp xn) +{ + emit<"11111000011sssss010100nnnnn11111", "s", "n">(xs, xn); +} +void STSMINB(WReg ws, XRegSp xn) +{ + emit<"00111000001sssss010100nnnnn11111", "s", "n">(ws, xn); +} +void STSMINLB(WReg ws, XRegSp xn) +{ + emit<"00111000011sssss010100nnnnn11111", "s", "n">(ws, xn); +} +void STSMINH(WReg ws, XRegSp xn) +{ + emit<"01111000001sssss010100nnnnn11111", "s", "n">(ws, xn); +} +void STSMINLH(WReg ws, XRegSp xn) +{ + emit<"01111000011sssss010100nnnnn11111", "s", "n">(ws, xn); +} +void STUMAX(WReg ws, XRegSp xn) +{ + emit<"10111000001sssss011000nnnnn11111", "s", "n">(ws, xn); +} +void STUMAXL(WReg ws, XRegSp xn) +{ + emit<"10111000011sssss011000nnnnn11111", "s", "n">(ws, xn); +} +void STUMAX(XReg xs, XRegSp xn) +{ + emit<"11111000001sssss011000nnnnn11111", "s", "n">(xs, xn); +} +void STUMAXL(XReg xs, XRegSp xn) +{ + emit<"11111000011sssss011000nnnnn11111", "s", "n">(xs, xn); +} +void STUMAXB(WReg ws, XRegSp xn) +{ + emit<"00111000001sssss011000nnnnn11111", "s", "n">(ws, xn); +} +void STUMAXLB(WReg ws, XRegSp xn) +{ + emit<"00111000011sssss011000nnnnn11111", "s", "n">(ws, xn); +} +void STUMAXH(WReg ws, XRegSp xn) +{ + emit<"01111000001sssss011000nnnnn11111", "s", "n">(ws, xn); +} +void STUMAXLH(WReg ws, XRegSp xn) +{ + emit<"01111000011sssss011000nnnnn11111", "s", "n">(ws, xn); +} +void STUMIN(WReg ws, XRegSp xn) +{ + emit<"10111000001sssss011100nnnnn11111", "s", "n">(ws, xn); +} +void STUMINL(WReg ws, XRegSp xn) +{ + emit<"10111000011sssss011100nnnnn11111", "s", "n">(ws, xn); +} +void STUMIN(XReg xs, XRegSp xn) +{ + emit<"11111000001sssss011100nnnnn11111", "s", "n">(xs, xn); +} +void STUMINL(XReg xs, XRegSp xn) +{ + emit<"11111000011sssss011100nnnnn11111", "s", "n">(xs, xn); +} +void STUMINB(WReg ws, XRegSp xn) +{ + emit<"00111000001sssss011100nnnnn11111", "s", "n">(ws, xn); +} +void STUMINLB(WReg ws, XRegSp xn) +{ + emit<"00111000011sssss011100nnnnn11111", "s", "n">(ws, xn); +} +void STUMINH(WReg ws, XRegSp xn) +{ + emit<"01111000001sssss011100nnnnn11111", "s", "n">(ws, xn); +} +void STUMINLH(WReg ws, XRegSp xn) +{ + emit<"01111000011sssss011100nnnnn11111", "s", "n">(ws, xn); +} +void SWP(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000001sssss100000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void SWPA(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000101sssss100000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void SWPAL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000111sssss100000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void SWPL(WReg ws, WReg wt, XRegSp xn) +{ + emit<"10111000011sssss100000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void SWP(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000001sssss100000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void SWPA(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000101sssss100000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void SWPAL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000111sssss100000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void SWPL(XReg xs, XReg xt, XRegSp xn) +{ + emit<"11111000011sssss100000nnnnnttttt", "s", "t", "n">(xs, xt, xn); +} +void SWPAB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000101sssss100000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void SWPALB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000111sssss100000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void SWPB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000001sssss100000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void SWPLB(WReg ws, WReg wt, XRegSp xn) +{ + emit<"00111000011sssss100000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void SWPAH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000101sssss100000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void SWPALH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000111sssss100000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void SWPH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000001sssss100000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} +void SWPLH(WReg ws, WReg wt, XRegSp xn) +{ + emit<"01111000011sssss100000nnnnnttttt", "s", "t", "n">(ws, wt, xn); +} diff --git a/include/oaknut/impl/mnemonics_generic_v8.2.inc.hpp b/include/oaknut/impl/mnemonics_generic_v8.2.inc.hpp new file mode 100644 index 00000000..a9222bbd --- /dev/null +++ b/include/oaknut/impl/mnemonics_generic_v8.2.inc.hpp @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: Copyright (c) 2022 merryhime +// SPDX-License-Identifier: MIT + +void BFC(WReg wd, Imm<5> lsb, Imm<5> width) +{ + if (width.value() == 0 || width.value() > (32 - lsb.value())) + throw "invalid width"; + emit<"0011001100rrrrrrssssss11111ddddd", "d", "r", "s">(wd, (-lsb.value()) & 31, width.value() - 1); +} +void BFC(XReg xd, Imm<6> lsb, Imm<6> width) +{ + if (width.value() == 0 || width.value() > (64 - lsb.value())) + throw "invalid width"; + emit<"1011001101rrrrrrssssss11111ddddd", "d", "r", "s">(xd, (-lsb.value()) & 63, width.value() - 1); +} +void ESB() +{ + emit<"11010101000000110010001000011111">(); +} +void PSB() +{ + emit<"11010101000000110010001000111111">(); +} diff --git a/include/oaknut/impl/offset.hpp b/include/oaknut/impl/offset.hpp index 4f66dac6..470de8fb 100644 --- a/include/oaknut/impl/offset.hpp +++ b/include/oaknut/impl/offset.hpp @@ -64,7 +64,7 @@ private: std::variant m_payload; }; -template +template struct PageOffset { PageOffset(void* ptr) : m_payload(ptr) @@ -76,10 +76,11 @@ struct PageOffset { static std::uint32_t encode(std::uintptr_t current_addr, std::uintptr_t target) { - const std::int64_t page_diff = (static_cast(target) >> 12) - (static_cast(current_addr) >> 12); - if (detail::sign_extend(page_diff) != page_diff) + std::uint64_t diff = (static_cast(target) >> shift_amount) - (static_cast(current_addr) >> shift_amount); + if (detail::sign_extend(diff) != diff) throw "out of range"; - return static_cast(page_diff & detail::mask_from_size(bitsize)); + diff &= detail::mask_from_size(bitsize); + return static_cast(((diff & 3) << (bitsize - 2)) | (diff >> 2)); } private: diff --git a/include/oaknut/impl/reg.hpp b/include/oaknut/impl/reg.hpp index aad2fd54..787bc25b 100644 --- a/include/oaknut/impl/reg.hpp +++ b/include/oaknut/impl/reg.hpp @@ -28,6 +28,7 @@ struct HReg; struct SReg; struct DReg; struct QReg; +struct VReg_2H; struct VReg_8B; struct VReg_4H; struct VReg_2S; @@ -185,10 +186,10 @@ struct VReg : public Reg { }; struct VRegArranged : public Reg { +protected: constexpr explicit VRegArranged(unsigned bitsize_, int index_, unsigned esize_) : Reg(true, bitsize_, index_), m_esize(esize_) { - assert(bitsize_ == 64 || bitsize_ == 128); assert(esize_ != 0 && (esize_ & (esize_ - 1)) == 0 && "esize must be a power of two"); assert(esize_ <= bitsize_); } @@ -200,45 +201,9 @@ private: int m_esize : 8; }; -struct BReg : public VReg { - constexpr explicit BReg(int index_) - : VReg(8, index_) - {} - - template - friend class BasicCodeGenerator; -}; - -struct HReg : public VReg { - constexpr explicit HReg(int index_) - : VReg(16, index_) - {} - - template - friend class BasicCodeGenerator; -}; - -struct SReg : public VReg { - constexpr explicit SReg(int index_) - : VReg(32, index_) - {} - - template - friend class BasicCodeGenerator; -}; - -struct DReg : public VReg { - constexpr explicit DReg(int index_) - : VReg(64, index_) - {} - - template - friend class BasicCodeGenerator; -}; - -struct QReg : public VReg { - constexpr explicit QReg(int index_) - : VReg(128, index_) +struct VReg_2H : public VRegArranged { + constexpr explicit VReg_2H(int reg_index_) + : VRegArranged(32, reg_index_, 32 / 2) {} template @@ -344,20 +309,6 @@ private: unsigned m_elem_index; }; -template -struct ElemSelector { - constexpr explicit ElemSelector(int reg_index_) - : m_reg_index(reg_index_) - {} - - constexpr int reg_index() const { return m_reg_index; } - - constexpr E operator[](unsigned elem_index) const { return E{m_reg_index, elem_index}; } - -private: - int m_reg_index; -}; - struct BElem : public Elem { constexpr explicit BElem(int reg_, unsigned elem_index_) : Elem(2, reg_, elem_index_) @@ -391,6 +342,86 @@ struct DElem_1 : public DElem { } }; +template +struct ElemSelector { + constexpr explicit ElemSelector(int reg_index_) + : m_reg_index(reg_index_) + {} + + constexpr int reg_index() const { return m_reg_index; } + + constexpr E operator[](unsigned elem_index) const { return E{m_reg_index, elem_index}; } + +private: + int m_reg_index; +}; + +struct BReg : public VReg { + constexpr explicit BReg(int index_) + : VReg(8, index_) + {} + + template + friend class BasicCodeGenerator; +}; + +struct HReg : public VReg { + constexpr explicit HReg(int index_) + : VReg(16, index_) + {} + + template + friend class BasicCodeGenerator; +}; + +struct SReg : public VReg { + constexpr explicit SReg(int index_) + : VReg(32, index_) + {} + + template + friend class BasicCodeGenerator; +}; + +struct DReg : public VReg { + constexpr explicit DReg(int index_) + : VReg(64, index_) + {} + + template + friend class BasicCodeGenerator; + + constexpr ElemSelector Belem() const { return ElemSelector(index()); } + constexpr ElemSelector Helem() const { return ElemSelector(index()); } + constexpr ElemSelector Selem() const { return ElemSelector(index()); } + constexpr ElemSelector Delem() const { return ElemSelector(index()); } + + constexpr VReg_8B B8() const { return VReg_8B{index()}; } + constexpr VReg_4H H4() const { return VReg_4H{index()}; } + constexpr VReg_2S S2() const { return VReg_2S{index()}; } + constexpr VReg_1D D1() const { return VReg_1D{index()}; } +}; + +struct QReg : public VReg { + constexpr explicit QReg(int index_) + : VReg(128, index_) + {} + + template + friend class BasicCodeGenerator; + + constexpr ElemSelector Belem() const { return ElemSelector(index()); } + constexpr ElemSelector Helem() const { return ElemSelector(index()); } + constexpr ElemSelector Selem() const { return ElemSelector(index()); } + constexpr ElemSelector Delem() const { return ElemSelector(index()); } + + constexpr VReg_16B B16() const { return VReg_16B{index()}; } + constexpr VReg_8H H8() const { return VReg_8H{index()}; } + constexpr VReg_4S S4() const { return VReg_4S{index()}; } + constexpr VReg_2D D2() const { return VReg_2D{index()}; } + constexpr VReg_1Q Q1() const { return VReg_1Q{index()}; } +}; + constexpr BReg VReg::toB() const { return BReg{index()}; @@ -424,6 +455,7 @@ struct VRegSelector { constexpr ElemSelector S() const { return ElemSelector(index()); } constexpr ElemSelector D() const { return ElemSelector(index()); } + constexpr VReg_2H H2() const { return VReg_2H{index()}; } constexpr VReg_8B B8() const { return VReg_8B{index()}; } constexpr VReg_4H H4() const { return VReg_4H{index()}; } constexpr VReg_2S S2() const { return VReg_2S{index()}; } diff --git a/include/oaknut/oaknut.hpp b/include/oaknut/oaknut.hpp index a273d310..e6ab27ef 100644 --- a/include/oaknut/oaknut.hpp +++ b/include/oaknut/oaknut.hpp @@ -98,8 +98,12 @@ public: label.m_wbs.clear(); } -#include "oaknut/impl/arm64_mnemonics.inc.hpp" -#include "oaknut/impl/fpsimd_mnemonics.inc.hpp" +#include "oaknut/impl/mnemonics_fpsimd_v8.0.inc.hpp" +#include "oaknut/impl/mnemonics_fpsimd_v8.1.inc.hpp" +#include "oaknut/impl/mnemonics_fpsimd_v8.2.inc.hpp" +#include "oaknut/impl/mnemonics_generic_v8.0.inc.hpp" +#include "oaknut/impl/mnemonics_generic_v8.1.inc.hpp" +#include "oaknut/impl/mnemonics_generic_v8.2.inc.hpp" void RET() { @@ -112,8 +116,8 @@ public: return; if (MovImm16::is_valid(imm)) return MOVZ(wd, imm); - if (MovImm16::is_valid(~static_cast(imm))) - return MOVN(wd, imm); + if (MovImm16::is_valid(~imm)) + return MOVN(wd, ~imm); if (detail::encode_bit_imm(imm)) return ORR(wd, WzrReg{}, imm); @@ -130,7 +134,7 @@ public: if (MovImm16::is_valid(imm)) return MOVZ(xd, imm); if (MovImm16::is_valid(~imm)) - return MOVN(xd, imm); + return MOVN(xd, ~imm); if (detail::encode_bit_imm(imm)) return ORR(xd, ZrReg{}, imm); @@ -159,6 +163,27 @@ public: } } + void align(std::size_t alignment) + { + if (alignment < 4 || (alignment & (alignment - 1)) != 0) + throw "invalid alignment"; + + while (Policy::template ptr() & (alignment - 1)) { + NOP(); + } + } + + void dw(std::uint32_t value) + { + Policy::append(value); + } + + void dx(std::uint64_t value) + { + Policy::append(static_cast(value)); + Policy::append(static_cast(value >> 32)); + } + private: #include "oaknut/impl/arm64_encode_helpers.inc.hpp" @@ -199,13 +224,13 @@ private: v.m_payload); } - template - std::uint32_t encode(PageOffset v) + template + std::uint32_t encode(PageOffset v) { static_assert(std::popcount(splat) == size); const auto encode_fn = [](std::uintptr_t current_addr, std::uintptr_t target) { - return pdep(PageOffset::encode(current_addr, target)); + return pdep(PageOffset::encode(current_addr, target)); }; return std::visit(detail::overloaded{ @@ -230,7 +255,7 @@ public: template T ptr() { - static_assert(std::is_pointer_v); + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); return reinterpret_cast(m_ptr); } diff --git a/tests/basic.cpp b/tests/basic.cpp index 2f11c316..9bcd28f8 100644 --- a/tests/basic.cpp +++ b/tests/basic.cpp @@ -115,3 +115,47 @@ TEST_CASE("Immediate generation (64-bit)") REQUIRE(f() == value); } } + +TEST_CASE("ADR") +{ + CodeBlock mem{4096}; + + for (std::int64_t i = -1048576; i < 1048576; i++) { + const std::intptr_t value = reinterpret_cast(mem.ptr()) + i; + + CodeGenerator code{mem.ptr()}; + + auto f = code.ptr(); + mem.unprotect(); + code.ADR(X0, reinterpret_cast(value)); + code.RET(); + mem.protect(); + mem.invalidate_all(); + + INFO(i); + REQUIRE(f() == value); + } +} + +TEST_CASE("ADRP") +{ + CodeBlock mem{4096}; + + for (int i = 0; i < 0x200000; i++) { + const std::int64_t diff = RandInt(-4294967296, 4294967295); + const std::intptr_t value = reinterpret_cast(mem.ptr()) + diff; + const std::uint64_t expect = static_cast(value) & ~static_cast(0xfff); + + CodeGenerator code{mem.ptr()}; + + auto f = code.ptr(); + mem.unprotect(); + code.ADRP(X0, reinterpret_cast(value)); + code.RET(); + mem.protect(); + mem.invalidate_all(); + + INFO(i); + REQUIRE(f() == expect); + } +} diff --git a/tests/fpsimd.cpp b/tests/fpsimd.cpp index 3d71d862..e0cb0e26 100644 --- a/tests/fpsimd.cpp +++ b/tests/fpsimd.cpp @@ -432,6 +432,10 @@ T(0x6e135ec1, MOV(V1.B()[9], V22.B()[11])) T(0x4e0f1da9, MOV(V9.B()[7], W13)) T(0x5e0e045d, MOV(H29, V2.H()[3])) T(0x0e043ca1, MOV(W1, V5.S()[0])) +T(0x0e0c3da8, MOV(W8, V13.S()[1])) +T(0x0e143da8, MOV(W8, V13.S()[2])) +T(0x0e1c3da8, MOV(W8, V13.S()[3])) +T(0x4e183d03, MOV(X3, V8.D()[1])) T(0x4e083df7, MOV(X23, V15.D()[0])) // MOV T(0x0f06e58e, MOVI(V14.B8(), 204))