Squashed 'externals/oaknut/' changes from 816481f10..c24f918e5

c24f918e5 oaknut: 1.1.6
3a70cd40a oaknut: Run clang-format
dc54784b8 oaknut: Add support for iOS memory protection.
14207278a oaknut: 1.1.5
841f9b693 oaknut: throw OaknutException instead of plain C string

git-subtree-dir: externals/oaknut
git-subtree-split: c24f918e52e629fc315c6e4bca4ea62def8b55e8
This commit is contained in:
Merry 2023-04-27 22:20:30 +01:00
parent b65b07d566
commit 720d6bbcd8
18 changed files with 436 additions and 328 deletions

View file

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.8) cmake_minimum_required(VERSION 3.8)
project(oaknut LANGUAGES CXX VERSION 1.1.4) project(oaknut LANGUAGES CXX VERSION 1.1.6)
# Determine if we're built as a subproject (using add_subdirectory) # Determine if we're built as a subproject (using add_subdirectory)
# or if this is the master project. # or if this is the master project.

View file

@ -12,6 +12,7 @@
# define NOMINMAX # define NOMINMAX
# include <windows.h> # include <windows.h>
#elif defined(__APPLE__) #elif defined(__APPLE__)
# include <TargetConditionals.h>
# include <libkern/OSCacheControl.h> # include <libkern/OSCacheControl.h>
# include <pthread.h> # include <pthread.h>
# include <sys/mman.h> # include <sys/mman.h>
@ -30,7 +31,11 @@ public:
#if defined(_WIN32) #if defined(_WIN32)
m_memory = (std::uint32_t*)VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); m_memory = (std::uint32_t*)VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#elif defined(__APPLE__) #elif defined(__APPLE__)
# if TARGET_OS_IPHONE
m_memory = (std::uint32_t*)mmap(nullptr, size, PROT_READ | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
# else
m_memory = (std::uint32_t*)mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0); m_memory = (std::uint32_t*)mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0);
# endif
#else #else
m_memory = (std::uint32_t*)mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); m_memory = (std::uint32_t*)mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
#endif #endif
@ -64,14 +69,22 @@ public:
void protect() void protect()
{ {
#if defined(__APPLE__) #if defined(__APPLE__)
# if TARGET_OS_IPHONE
mprotect(m_memory, m_size, PROT_READ | PROT_EXEC);
# else
pthread_jit_write_protect_np(1); pthread_jit_write_protect_np(1);
# endif
#endif #endif
} }
void unprotect() void unprotect()
{ {
#if defined(__APPLE__) #if defined(__APPLE__)
# if TARGET_OS_IPHONE
mprotect(m_memory, m_size, PROT_READ | PROT_WRITE);
# else
pthread_jit_write_protect_np(0); pthread_jit_write_protect_np(0);
# endif
#endif #endif
} }

View file

@ -55,7 +55,7 @@ std::uint32_t encode(MovImm16 v)
if constexpr (std::popcount(splat) == 17) { if constexpr (std::popcount(splat) == 17) {
constexpr std::uint32_t mask = (1 << std::popcount(splat)) - 1; constexpr std::uint32_t mask = (1 << std::popcount(splat)) - 1;
if ((v.m_encoded & mask) != v.m_encoded) if ((v.m_encoded & mask) != v.m_encoded)
throw "invalid MovImm16"; throw OaknutException{ExceptionType::InvalidMovImm16};
} }
return pdep<splat>(v.m_encoded); return pdep<splat>(v.m_encoded);
} }
@ -136,7 +136,7 @@ void addsubext_verify_reg_size(AddSubExt ext, RReg rm)
return; return;
if (rm.bitsize() == 64 && (static_cast<int>(ext) & 0b011) == 0b011) if (rm.bitsize() == 64 && (static_cast<int>(ext) & 0b011) == 0b011)
return; return;
throw "invalid AddSubExt choice for rm size"; throw OaknutException{ExceptionType::InvalidAddSubExt};
} }
void indexext_verify_reg_size(IndexExt ext, RReg rm) void indexext_verify_reg_size(IndexExt ext, RReg rm)
@ -145,11 +145,11 @@ void indexext_verify_reg_size(IndexExt ext, RReg rm)
return; return;
if (rm.bitsize() == 64 && (static_cast<int>(ext) & 1) == 1) if (rm.bitsize() == 64 && (static_cast<int>(ext) & 1) == 1)
return; return;
throw "invalid IndexExt choice for rm size"; throw OaknutException{ExceptionType::InvalidIndexExt};
} }
void tbz_verify_reg_size(RReg rt, Imm<6> imm) void tbz_verify_reg_size(RReg rt, Imm<6> imm)
{ {
if (rt.bitsize() == 32 && imm.value() >= 32) if (rt.bitsize() == 32 && imm.value() >= 32)
throw "invalid imm choice for rt size"; throw OaknutException{ExceptionType::BitPositionOutOfRange};
} }

View file

@ -199,7 +199,7 @@ enum class TlbiOp {
VALE1 = 0b000'0111'101, VALE1 = 0b000'0111'101,
VAALE1 = 0b000'0111'111, VAALE1 = 0b000'0111'111,
IPAS2E1IS = 0b100'0000'001, IPAS2E1IS = 0b100'0000'001,
RIPAS2E1IS = 0b100'0000'010, // ARMv8.4-TLBI RIPAS2E1IS = 0b100'0000'010, // ARMv8.4-TLBI
IPAS2LE1IS = 0b100'0000'101, IPAS2LE1IS = 0b100'0000'101,
RIPAS2LE1IS = 0b100'0000'110, // ARMv8.4-TLBI RIPAS2LE1IS = 0b100'0000'110, // ARMv8.4-TLBI
ALLE2OS = 0b100'0001'000, // ARMv8.4-TLBI ALLE2OS = 0b100'0001'000, // ARMv8.4-TLBI
@ -214,11 +214,11 @@ enum class TlbiOp {
ALLE1IS = 0b100'0011'100, ALLE1IS = 0b100'0011'100,
VALE2IS = 0b100'0011'101, VALE2IS = 0b100'0011'101,
VMALLS12E1IS = 0b100'0011'110, VMALLS12E1IS = 0b100'0011'110,
IPAS2E1OS = 0b100'0100'000, // ARMv8.4-TLBI IPAS2E1OS = 0b100'0100'000, // ARMv8.4-TLBI
IPAS2E1 = 0b100'0100'001, IPAS2E1 = 0b100'0100'001,
RIPAS2E1 = 0b100'0100'010, // ARMv8.4-TLBI RIPAS2E1 = 0b100'0100'010, // ARMv8.4-TLBI
RIPAS2E1OS = 0b100'0100'011, // ARMv8.4-TLBI RIPAS2E1OS = 0b100'0100'011, // ARMv8.4-TLBI
IPAS2LE1OS = 0b100'0100'100, // ARMv8.4-TLBI IPAS2LE1OS = 0b100'0100'100, // ARMv8.4-TLBI
IPAS2LE1 = 0b100'0100'101, IPAS2LE1 = 0b100'0100'101,
RIPAS2LE1 = 0b100'0100'110, // ARMv8.4-TLBI RIPAS2LE1 = 0b100'0100'110, // ARMv8.4-TLBI
RIPAS2LE1OS = 0b100'0100'111, // ARMv8.4-TLBI RIPAS2LE1OS = 0b100'0100'111, // ARMv8.4-TLBI

View file

@ -9,6 +9,8 @@
#include <cstdint> #include <cstdint>
#include <optional> #include <optional>
#include "oaknut/oaknut_exception.hpp"
namespace oaknut { namespace oaknut {
template<std::size_t bit_size_> template<std::size_t bit_size_>
@ -22,7 +24,7 @@ public:
: m_value(value_) : m_value(value_)
{ {
if (!is_valid(value_)) if (!is_valid(value_))
throw "outsized Imm value"; throw OaknutException{ExceptionType::ImmOutOfRange};
} }
constexpr auto operator<=>(const Imm& other) const { return m_value <=> other.m_value; } constexpr auto operator<=>(const Imm& other) const { return m_value <=> other.m_value; }
@ -52,7 +54,7 @@ public:
: m_encoded(value_ | ((shift_ == AddSubImmShift::SHL_12) ? 1 << 12 : 0)) : m_encoded(value_ | ((shift_ == AddSubImmShift::SHL_12) ? 1 << 12 : 0))
{ {
if ((value_ & 0xFFF) != value_) if ((value_ & 0xFFF) != value_)
throw "invalid AddSubImm"; throw OaknutException{ExceptionType::InvalidAddSubImm};
} }
constexpr /* implicit */ AddSubImm(std::uint64_t value_) constexpr /* implicit */ AddSubImm(std::uint64_t value_)
@ -62,7 +64,7 @@ public:
} else if ((value_ & 0xFFF000) == value_) { } else if ((value_ & 0xFFF000) == value_) {
m_encoded = (value_ >> 12) | (1 << 12); m_encoded = (value_ >> 12) | (1 << 12);
} else { } else {
throw "invalid AddSubImm"; throw OaknutException{ExceptionType::InvalidAddSubImm};
} }
} }
@ -99,7 +101,7 @@ public:
m_encoded = lsw | (shift << 16); m_encoded = lsw | (shift << 16);
return; return;
} else if (lsw != 0) { } else if (lsw != 0) {
throw "invalid MovImm16"; throw OaknutException{ExceptionType::InvalidMovImm16};
} }
value_ >>= 16; value_ >>= 16;
shift++; shift++;
@ -161,7 +163,7 @@ public:
{ {
const auto encoded = detail::encode_bit_imm(value); const auto encoded = detail::encode_bit_imm(value);
if (!encoded || (*encoded & 0x1000) != 0) if (!encoded || (*encoded & 0x1000) != 0)
throw "invalid BitImm32"; throw OaknutException{ExceptionType::InvalidBitImm32};
m_encoded = *encoded; m_encoded = *encoded;
} }
@ -181,7 +183,7 @@ public:
{ {
const auto encoded = detail::encode_bit_imm(value); const auto encoded = detail::encode_bit_imm(value);
if (!encoded) if (!encoded)
throw "invalid BitImm64"; throw OaknutException{ExceptionType::InvalidBitImm64};
m_encoded = *encoded; m_encoded = *encoded;
} }
@ -224,7 +226,7 @@ struct ImmConst {
constexpr /* implicit */ ImmConst(int value) constexpr /* implicit */ ImmConst(int value)
{ {
if (value != A) { if (value != A) {
throw "invalid ImmConst"; throw OaknutException{ExceptionType::InvalidImmConst};
} }
} }
}; };
@ -233,7 +235,7 @@ struct ImmConstFZero {
constexpr /* implicit */ ImmConstFZero(double value) constexpr /* implicit */ ImmConstFZero(double value)
{ {
if (value != 0) { if (value != 0) {
throw "invalid ImmConstFZero"; throw OaknutException{ExceptionType::InvalidImmConstFZero};
} }
} }
}; };
@ -250,7 +252,7 @@ struct ImmChoice<A, B> {
} else if (value == B) { } else if (value == B) {
m_encoded = 1; m_encoded = 1;
} else { } else {
throw "invalid ImmChoice"; throw OaknutException{ExceptionType::InvalidImmChoice};
} }
} }
@ -273,7 +275,7 @@ struct ImmChoice<A, B, C, D> {
} else if (value == D) { } else if (value == D) {
m_encoded = 3; m_encoded = 3;
} else { } else {
throw "invalid ImmChoice"; throw OaknutException{ExceptionType::InvalidImmChoice};
} }
} }
@ -289,7 +291,7 @@ struct ImmRange {
: m_value(value_) : m_value(value_)
{ {
if (value_ < Start || value_ > End) { if (value_ < Start || value_ > End) {
throw "invalid ImmRange"; throw OaknutException{ExceptionType::InvalidImmRange};
} }
} }
@ -305,7 +307,7 @@ struct LslShift {
: m_encoded((((-amount) & (max_value - 1)) << 6) | (max_value - amount - 1)) : m_encoded((((-amount) & (max_value - 1)) << 6) | (max_value - amount - 1))
{ {
if (amount >= max_value) if (amount >= max_value)
throw "LslShift out of range"; throw OaknutException{ExceptionType::LslShiftOutOfRange};
} }
private: private:

View file

@ -7,6 +7,8 @@
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
#include "oaknut/oaknut_exception.hpp"
namespace oaknut { namespace oaknut {
struct Elem; struct Elem;
@ -40,7 +42,7 @@ struct List {
static_assert(std::is_base_of_v<VRegArranged, T> || std::is_base_of_v<Elem, T> || detail::is_instance_of_ElemSelector_v<T>); static_assert(std::is_base_of_v<VRegArranged, T> || std::is_base_of_v<Elem, T> || detail::is_instance_of_ElemSelector_v<T>);
if (!verify(std::index_sequence_for<U...>{}, args...)) if (!verify(std::index_sequence_for<U...>{}, args...))
throw "invalid List"; throw OaknutException{ExceptionType::InvalidList};
} }
constexpr auto operator[](unsigned elem_index) const constexpr auto operator[](unsigned elem_index) const

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
void SQRDMLAH(HReg rd, HReg rn, HElem em) void SQRDMLAH(HReg rd, HReg rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void SQRDMLAH(SReg rd, SReg rn, SElem em)
@ -14,13 +14,13 @@ void SQRDMLAH(SReg rd, SReg rn, SElem em)
void SQRDMLAH(VReg_4H rd, VReg_4H rn, HElem em) void SQRDMLAH(VReg_4H rd, VReg_4H rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void SQRDMLAH(VReg_8H rd, VReg_8H rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void SQRDMLAH(VReg_2S rd, VReg_2S rn, SElem em)
@ -58,7 +58,7 @@ void SQRDMLAH(VReg_4S rd, VReg_4S rn, VReg_4S rm)
void SQRDMLSH(HReg rd, HReg rn, HElem em) void SQRDMLSH(HReg rd, HReg rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void SQRDMLSH(SReg rd, SReg rn, SElem em)
@ -68,13 +68,13 @@ void SQRDMLSH(SReg rd, SReg rn, SElem em)
void SQRDMLSH(VReg_4H rd, VReg_4H rn, HElem em) void SQRDMLSH(VReg_4H rd, VReg_4H rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void SQRDMLSH(VReg_8H rd, VReg_8H rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void SQRDMLSH(VReg_2S rd, VReg_2S rn, SElem em)

View file

@ -412,19 +412,19 @@ void FMINV(HReg rd, VReg_8H rn)
void FMLA(HReg rd, HReg rn, HElem em) void FMLA(HReg rd, HReg rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLA(VReg_8B rd, VReg_8B rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLA(VReg_16B rd, VReg_16B rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLA(VReg_4H rd, VReg_4H rn, VReg_4H rm)
@ -438,25 +438,25 @@ void FMLA(VReg_8H rd, VReg_8H rn, VReg_8H rm)
void FMLAL(VReg_2S rd, VReg_2H rn, HElem em) void FMLAL(VReg_2S rd, VReg_2H rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLAL(VReg_4S rd, VReg_4H rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLAL2(VReg_2S rd, VReg_2H rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLAL2(VReg_4S rd, VReg_4H rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLAL(VReg_2S rd, VReg_2H rn, VReg_2H rm)
@ -478,19 +478,19 @@ void FMLAL2(VReg_4S rd, VReg_4H rn, VReg_4H rm)
void FMLS(HReg rd, HReg rn, HElem em) void FMLS(HReg rd, HReg rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLS(VReg_8B rd, VReg_8B rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLS(VReg_16B rd, VReg_16B rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLS(VReg_4H rd, VReg_4H rn, VReg_4H rm)
@ -504,25 +504,25 @@ void FMLS(VReg_8H rd, VReg_8H rn, VReg_8H rm)
void FMLSL(VReg_2S rd, VReg_2H rn, HElem em) void FMLSL(VReg_2S rd, VReg_2H rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLSL(VReg_4S rd, VReg_4H rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLSL2(VReg_2S rd, VReg_2H rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLSL2(VReg_4S rd, VReg_4H rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMLSL(VReg_2S rd, VReg_2H rn, VReg_2H rm)
@ -552,19 +552,19 @@ void FMOV(VReg_8H rd, FImm8 imm)
void FMUL(HReg rd, HReg rn, HElem em) void FMUL(HReg rd, HReg rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMUL(VReg_8B rd, VReg_8B rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMUL(VReg_16B rd, VReg_16B rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMUL(VReg_4H rd, VReg_4H rn, VReg_4H rm)
@ -590,19 +590,19 @@ void FMULX(VReg_8H rd, VReg_8H rn, VReg_8H rm)
void FMULX(HReg rd, HReg rn, HElem em) void FMULX(HReg rd, HReg rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMULX(VReg_8B rd, VReg_8B rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FMULX(VReg_16B rd, VReg_16B rn, HElem em)
{ {
if (em.reg_index() >= 16) if (em.reg_index() >= 16)
throw "InvalidCombination"; throw OaknutException{ExceptionType::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); 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) void FNEG(VReg_4H rd, VReg_4H rn)

View file

@ -166,13 +166,13 @@ void B(Cond cond, AddrOffset<21, 2> label)
void BFI(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width) void BFI(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width)
{ {
if (width.value() == 0 || width.value() > (32 - lsb.value())) if (width.value() == 0 || width.value() > (32 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"0011001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, (-lsb.value()) & 31, width.value() - 1); emit<"0011001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, (-lsb.value()) & 31, width.value() - 1);
} }
void BFI(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width) void BFI(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width)
{ {
if (width.value() == 0 || width.value() > (64 - lsb.value())) if (width.value() == 0 || width.value() > (64 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"1011001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, (-lsb.value()) & 63, width.value() - 1); emit<"1011001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, (-lsb.value()) & 63, width.value() - 1);
} }
void BFM(WReg wd, WReg wn, Imm<5> immr, Imm<5> imms) void BFM(WReg wd, WReg wn, Imm<5> immr, Imm<5> imms)
@ -186,13 +186,13 @@ void BFM(XReg xd, XReg xn, Imm<6> immr, Imm<6> imms)
void BFXIL(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width) void BFXIL(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width)
{ {
if (width.value() == 0 || width.value() > (32 - lsb.value())) if (width.value() == 0 || width.value() > (32 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"0011001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, lsb.value(), lsb.value() + width.value() - 1); emit<"0011001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, lsb.value(), lsb.value() + width.value() - 1);
} }
void BFXIL(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width) void BFXIL(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width)
{ {
if (width.value() == 0 || width.value() > (64 - lsb.value())) if (width.value() == 0 || width.value() > (64 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"1011001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, lsb.value(), lsb.value() + width.value() - 1); emit<"1011001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, lsb.value(), lsb.value() + width.value() - 1);
} }
void BIC(WReg wd, WReg wn, WReg wm, LogShift shift = LogShift::LSL, Imm<5> shift_amount = 0) void BIC(WReg wd, WReg wn, WReg wm, LogShift shift = LogShift::LSL, Imm<5> shift_amount = 0)
@ -278,25 +278,25 @@ void CCMP(XReg xn, XReg xm, Imm<4> nzcv, Cond cond)
void CINC(WReg wd, WReg wn, Cond cond) void CINC(WReg wd, WReg wn, Cond cond)
{ {
if (cond == Cond::AL || cond == Cond::NV) if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond"; throw OaknutException{ExceptionType::InvalidCond};
emit<"00011010100mmmmmcccc01nnnnnddddd", "d", "n", "m", "c">(wd, wn, wn, invert(cond)); emit<"00011010100mmmmmcccc01nnnnnddddd", "d", "n", "m", "c">(wd, wn, wn, invert(cond));
} }
void CINC(XReg xd, XReg xn, Cond cond) void CINC(XReg xd, XReg xn, Cond cond)
{ {
if (cond == Cond::AL || cond == Cond::NV) if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond"; throw OaknutException{ExceptionType::InvalidCond};
emit<"10011010100mmmmmcccc01nnnnnddddd", "d", "n", "m", "c">(xd, xn, xn, invert(cond)); emit<"10011010100mmmmmcccc01nnnnnddddd", "d", "n", "m", "c">(xd, xn, xn, invert(cond));
} }
void CINV(WReg wd, WReg wn, Cond cond) void CINV(WReg wd, WReg wn, Cond cond)
{ {
if (cond == Cond::AL || cond == Cond::NV) if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond"; throw OaknutException{ExceptionType::InvalidCond};
emit<"01011010100mmmmmcccc00nnnnnddddd", "d", "n", "m", "c">(wd, wn, wn, invert(cond)); emit<"01011010100mmmmmcccc00nnnnnddddd", "d", "n", "m", "c">(wd, wn, wn, invert(cond));
} }
void CINV(XReg xd, XReg xn, Cond cond) void CINV(XReg xd, XReg xn, Cond cond)
{ {
if (cond == Cond::AL || cond == Cond::NV) if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond"; throw OaknutException{ExceptionType::InvalidCond};
emit<"11011010100mmmmmcccc00nnnnnddddd", "d", "n", "m", "c">(xd, xn, xn, invert(cond)); emit<"11011010100mmmmmcccc00nnnnnddddd", "d", "n", "m", "c">(xd, xn, xn, invert(cond));
} }
void CLREX(Imm<4> imm = 15) void CLREX(Imm<4> imm = 15)
@ -392,13 +392,13 @@ void CMP(XReg xn, XReg xm, AddSubShift shift = AddSubShift::LSL, Imm<6> shift_am
void CNEG(WReg wd, WReg wn, Cond cond) void CNEG(WReg wd, WReg wn, Cond cond)
{ {
if (cond == Cond::AL || cond == Cond::NV) if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond"; throw OaknutException{ExceptionType::InvalidCond};
emit<"01011010100mmmmmcccc01nnnnnddddd", "d", "n", "m", "c">(wd, wn, wn, invert(cond)); emit<"01011010100mmmmmcccc01nnnnnddddd", "d", "n", "m", "c">(wd, wn, wn, invert(cond));
} }
void CNEG(XReg xd, XReg xn, Cond cond) void CNEG(XReg xd, XReg xn, Cond cond)
{ {
if (cond == Cond::AL || cond == Cond::NV) if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond"; throw OaknutException{ExceptionType::InvalidCond};
emit<"11011010100mmmmmcccc01nnnnnddddd", "d", "n", "m", "c">(xd, xn, xn, invert(cond)); emit<"11011010100mmmmmcccc01nnnnnddddd", "d", "n", "m", "c">(xd, xn, xn, invert(cond));
} }
void CRC32B(WReg wd, WReg wn, WReg wm) void CRC32B(WReg wd, WReg wn, WReg wm)
@ -448,25 +448,25 @@ void CSEL(XReg xd, XReg xn, XReg xm, Cond cond)
void CSET(WReg wd, Cond cond) void CSET(WReg wd, Cond cond)
{ {
if (cond == Cond::AL || cond == Cond::NV) if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond"; throw OaknutException{ExceptionType::InvalidCond};
emit<"0001101010011111cccc0111111ddddd", "d", "c">(wd, invert(cond)); emit<"0001101010011111cccc0111111ddddd", "d", "c">(wd, invert(cond));
} }
void CSET(XReg xd, Cond cond) void CSET(XReg xd, Cond cond)
{ {
if (cond == Cond::AL || cond == Cond::NV) if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond"; throw OaknutException{ExceptionType::InvalidCond};
emit<"1001101010011111cccc0111111ddddd", "d", "c">(xd, invert(cond)); emit<"1001101010011111cccc0111111ddddd", "d", "c">(xd, invert(cond));
} }
void CSETM(WReg wd, Cond cond) void CSETM(WReg wd, Cond cond)
{ {
if (cond == Cond::AL || cond == Cond::NV) if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond"; throw OaknutException{ExceptionType::InvalidCond};
emit<"0101101010011111cccc0011111ddddd", "d", "c">(wd, invert(cond)); emit<"0101101010011111cccc0011111ddddd", "d", "c">(wd, invert(cond));
} }
void CSETM(XReg xd, Cond cond) void CSETM(XReg xd, Cond cond)
{ {
if (cond == Cond::AL || cond == Cond::NV) if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond"; throw OaknutException{ExceptionType::InvalidCond};
emit<"1101101010011111cccc0011111ddddd", "d", "c">(xd, invert(cond)); emit<"1101101010011111cccc0011111ddddd", "d", "c">(xd, invert(cond));
} }
void CSINC(WReg wd, WReg wn, WReg wm, Cond cond) void CSINC(WReg wd, WReg wn, WReg wm, Cond cond)
@ -1230,13 +1230,13 @@ void SBCS(XReg xd, XReg xn, XReg xm)
void SBFIZ(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width) void SBFIZ(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width)
{ {
if (width.value() == 0 || width.value() > (32 - lsb.value())) if (width.value() == 0 || width.value() > (32 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"0001001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, (-lsb.value()) & 31, width.value() - 1); emit<"0001001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, (-lsb.value()) & 31, width.value() - 1);
} }
void SBFIZ(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width) void SBFIZ(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width)
{ {
if (width.value() == 0 || width.value() > (64 - lsb.value())) if (width.value() == 0 || width.value() > (64 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"1001001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, (-lsb.value()) & 63, width.value() - 1); emit<"1001001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, (-lsb.value()) & 63, width.value() - 1);
} }
void SBFM(WReg wd, WReg wn, Imm<5> immr, Imm<5> imms) void SBFM(WReg wd, WReg wn, Imm<5> immr, Imm<5> imms)
@ -1250,13 +1250,13 @@ void SBFM(XReg xd, XReg xn, Imm<6> immr, Imm<6> imms)
void SBFX(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width) void SBFX(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width)
{ {
if (width.value() == 0 || width.value() > (32 - lsb.value())) if (width.value() == 0 || width.value() > (32 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"0001001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, lsb.value(), lsb.value() + width.value() - 1); emit<"0001001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, lsb.value(), lsb.value() + width.value() - 1);
} }
void SBFX(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width) void SBFX(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width)
{ {
if (width.value() == 0 || width.value() > (64 - lsb.value())) if (width.value() == 0 || width.value() > (64 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"1001001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, lsb.value(), lsb.value() + width.value() - 1); emit<"1001001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, lsb.value(), lsb.value() + width.value() - 1);
} }
void SDIV(WReg wd, WReg wn, WReg wm) void SDIV(WReg wd, WReg wn, WReg wm)
@ -1626,13 +1626,13 @@ void TST(XReg xn, XReg xm, LogShift shift = LogShift::LSL, Imm<6> shift_amount =
void UBFIZ(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width) void UBFIZ(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width)
{ {
if (width.value() == 0 || width.value() > (32 - lsb.value())) if (width.value() == 0 || width.value() > (32 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"0101001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, (-lsb.value()) & 31, width.value() - 1); emit<"0101001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, (-lsb.value()) & 31, width.value() - 1);
} }
void UBFIZ(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width) void UBFIZ(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width)
{ {
if (width.value() == 0 || width.value() > (64 - lsb.value())) if (width.value() == 0 || width.value() > (64 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"1101001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, (-lsb.value()) & 63, width.value() - 1); emit<"1101001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, (-lsb.value()) & 63, width.value() - 1);
} }
void UBFM(WReg wd, WReg wn, Imm<5> immr, Imm<5> imms) void UBFM(WReg wd, WReg wn, Imm<5> immr, Imm<5> imms)
@ -1646,13 +1646,13 @@ void UBFM(XReg xd, XReg xn, Imm<6> immr, Imm<6> imms)
void UBFX(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width) void UBFX(WReg wd, WReg wn, Imm<5> lsb, Imm<5> width)
{ {
if (width.value() == 0 || width.value() > (32 - lsb.value())) if (width.value() == 0 || width.value() > (32 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"0101001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, lsb.value(), lsb.value() + width.value() - 1); emit<"0101001100rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(wd, wn, lsb.value(), lsb.value() + width.value() - 1);
} }
void UBFX(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width) void UBFX(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width)
{ {
if (width.value() == 0 || width.value() > (64 - lsb.value())) if (width.value() == 0 || width.value() > (64 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"1101001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, lsb.value(), lsb.value() + width.value() - 1); emit<"1101001101rrrrrrssssssnnnnnddddd", "d", "n", "r", "s">(xd, xn, lsb.value(), lsb.value() + width.value() - 1);
} }
void UDF(Imm<16> imm) void UDF(Imm<16> imm)

View file

@ -68,97 +68,97 @@ void CASLH(WReg ws, WReg wt, XRegSp xn)
void CASP(WReg ws, WReg ws2, WReg wt, WReg wt2, XRegSp xn) void CASP(WReg ws, WReg ws2, WReg wt, WReg wt2, XRegSp xn)
{ {
if (wt.index() + 1 != wt2.index()) if (wt.index() + 1 != wt2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (wt.index() & 1) if (wt.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
if (ws.index() + 1 != ws2.index()) if (ws.index() + 1 != ws2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (ws.index() & 1) if (ws.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
emit<"00001000001sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); emit<"00001000001sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn);
} }
void CASPA(WReg ws, WReg ws2, WReg wt, WReg wt2, XRegSp xn) void CASPA(WReg ws, WReg ws2, WReg wt, WReg wt2, XRegSp xn)
{ {
if (wt.index() + 1 != wt2.index()) if (wt.index() + 1 != wt2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (wt.index() & 1) if (wt.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
if (ws.index() + 1 != ws2.index()) if (ws.index() + 1 != ws2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (ws.index() & 1) if (ws.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
emit<"00001000011sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn); emit<"00001000011sssss011111nnnnnttttt", "s", "t", "n">(ws, wt, xn);
} }
void CASPAL(WReg ws, WReg ws2, WReg wt, WReg wt2, XRegSp xn) void CASPAL(WReg ws, WReg ws2, WReg wt, WReg wt2, XRegSp xn)
{ {
if (wt.index() + 1 != wt2.index()) if (wt.index() + 1 != wt2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (wt.index() & 1) if (wt.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
if (ws.index() + 1 != ws2.index()) if (ws.index() + 1 != ws2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (ws.index() & 1) if (ws.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
emit<"00001000011sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); emit<"00001000011sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn);
} }
void CASPL(WReg ws, WReg ws2, WReg wt, WReg wt2, XRegSp xn) void CASPL(WReg ws, WReg ws2, WReg wt, WReg wt2, XRegSp xn)
{ {
if (wt.index() + 1 != wt2.index()) if (wt.index() + 1 != wt2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (wt.index() & 1) if (wt.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
if (ws.index() + 1 != ws2.index()) if (ws.index() + 1 != ws2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (ws.index() & 1) if (ws.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
emit<"00001000001sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn); emit<"00001000001sssss111111nnnnnttttt", "s", "t", "n">(ws, wt, xn);
} }
void CASP(XReg xs, XReg xs2, XReg xt, XReg xt2, XRegSp xn) void CASP(XReg xs, XReg xs2, XReg xt, XReg xt2, XRegSp xn)
{ {
if (xt.index() + 1 != xt2.index()) if (xt.index() + 1 != xt2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (xt.index() & 1) if (xt.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
if (xs.index() + 1 != xs2.index()) if (xs.index() + 1 != xs2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (xs.index() & 1) if (xs.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
emit<"01001000001sssss011111nnnnnttttt", "s", "t", "n">(xs, xt, xn); emit<"01001000001sssss011111nnnnnttttt", "s", "t", "n">(xs, xt, xn);
} }
void CASPA(XReg xs, XReg xs2, XReg xt, XReg xt2, XRegSp xn) void CASPA(XReg xs, XReg xs2, XReg xt, XReg xt2, XRegSp xn)
{ {
if (xt.index() + 1 != xt2.index()) if (xt.index() + 1 != xt2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (xt.index() & 1) if (xt.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
if (xs.index() + 1 != xs2.index()) if (xs.index() + 1 != xs2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (xs.index() & 1) if (xs.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
emit<"01001000011sssss011111nnnnnttttt", "s", "t", "n">(xs, xt, xn); emit<"01001000011sssss011111nnnnnttttt", "s", "t", "n">(xs, xt, xn);
} }
void CASPAL(XReg xs, XReg xs2, XReg xt, XReg xt2, XRegSp xn) void CASPAL(XReg xs, XReg xs2, XReg xt, XReg xt2, XRegSp xn)
{ {
if (xt.index() + 1 != xt2.index()) if (xt.index() + 1 != xt2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (xt.index() & 1) if (xt.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
if (xs.index() + 1 != xs2.index()) if (xs.index() + 1 != xs2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (xs.index() & 1) if (xs.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
emit<"01001000011sssss111111nnnnnttttt", "s", "t", "n">(xs, xt, xn); emit<"01001000011sssss111111nnnnnttttt", "s", "t", "n">(xs, xt, xn);
} }
void CASPL(XReg xs, XReg xs2, XReg xt, XReg xt2, XRegSp xn) void CASPL(XReg xs, XReg xs2, XReg xt, XReg xt2, XRegSp xn)
{ {
if (xt.index() + 1 != xt2.index()) if (xt.index() + 1 != xt2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (xt.index() & 1) if (xt.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
if (xs.index() + 1 != xs2.index()) if (xs.index() + 1 != xs2.index())
throw "Invalid second register in pair"; throw OaknutException{ExceptionType::InvalidPairSecond};
if (xs.index() & 1) if (xs.index() & 1)
throw "Requires even register"; throw OaknutException{ExceptionType::InvalidPairFirst};
emit<"01001000001sssss111111nnnnnttttt", "s", "t", "n">(xs, xt, xn); emit<"01001000001sssss111111nnnnnttttt", "s", "t", "n">(xs, xt, xn);
} }
void LDADD(WReg ws, WReg wt, XRegSp xn) void LDADD(WReg ws, WReg wt, XRegSp xn)

View file

@ -4,13 +4,13 @@
void BFC(WReg wd, Imm<5> lsb, Imm<5> width) void BFC(WReg wd, Imm<5> lsb, Imm<5> width)
{ {
if (width.value() == 0 || width.value() > (32 - lsb.value())) if (width.value() == 0 || width.value() > (32 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"0011001100rrrrrrssssss11111ddddd", "d", "r", "s">(wd, (-lsb.value()) & 31, width.value() - 1); emit<"0011001100rrrrrrssssss11111ddddd", "d", "r", "s">(wd, (-lsb.value()) & 31, width.value() - 1);
} }
void BFC(XReg xd, Imm<6> lsb, Imm<6> width) void BFC(XReg xd, Imm<6> lsb, Imm<6> width)
{ {
if (width.value() == 0 || width.value() > (64 - lsb.value())) if (width.value() == 0 || width.value() > (64 - lsb.value()))
throw "invalid width"; throw OaknutException{ExceptionType::InvalidBitWidth};
emit<"1011001101rrrrrrssssss11111ddddd", "d", "r", "s">(xd, (-lsb.value()) & 63, width.value() - 1); emit<"1011001101rrrrrrssssss11111ddddd", "d", "r", "s">(xd, (-lsb.value()) & 63, width.value() - 1);
} }
void ESB() void ESB()

View file

@ -0,0 +1,42 @@
// SPDX-FileCopyrightText: Copyright (c) 2023 merryhime <https://mary.rs>
// SPDX-License-Identifier: MIT
// reg.hpp
OAKNUT_EXCEPTION(InvalidWSPConversion, "toW: cannot convert WSP to WReg")
OAKNUT_EXCEPTION(InvalidXSPConversion, "toX: cannot convert XSP to XReg")
OAKNUT_EXCEPTION(InvalidWZRConversion, "unexpected WZR passed into an WRegWsp")
OAKNUT_EXCEPTION(InvalidXZRConversion, "unexpected XZR passed into an XRegSp")
OAKNUT_EXCEPTION(InvalidDElem_1, "invalid DElem_1")
OAKNUT_EXCEPTION(InvalidElementIndex, "elem_index is out of range")
// imm.hpp / offset.hpp / list.hpp
OAKNUT_EXCEPTION(InvalidAddSubImm, "invalid AddSubImm")
OAKNUT_EXCEPTION(InvalidBitImm32, "invalid BitImm32")
OAKNUT_EXCEPTION(InvalidBitImm64, "invalid BitImm64")
OAKNUT_EXCEPTION(InvalidImmChoice, "invalid ImmChoice")
OAKNUT_EXCEPTION(InvalidImmConst, "invalid ImmConst")
OAKNUT_EXCEPTION(InvalidImmConstFZero, "invalid ImmConstFZero")
OAKNUT_EXCEPTION(InvalidImmRange, "invalid ImmRange")
OAKNUT_EXCEPTION(InvalidList, "invalid List")
OAKNUT_EXCEPTION(InvalidMovImm16, "invalid MovImm16")
OAKNUT_EXCEPTION(InvalidBitWidth, "invalid width")
OAKNUT_EXCEPTION(LslShiftOutOfRange, "LslShift out of range")
OAKNUT_EXCEPTION(OffsetMisaligned, "misalignment")
OAKNUT_EXCEPTION(OffsetOutOfRange, "out of range")
OAKNUT_EXCEPTION(ImmOutOfRange, "outsized Imm value")
// arm64_encode_helpers.inc.hpp
OAKNUT_EXCEPTION(InvalidAddSubExt, "invalid AddSubExt choice for rm size")
OAKNUT_EXCEPTION(InvalidIndexExt, "invalid IndexExt choice for rm size")
OAKNUT_EXCEPTION(BitPositionOutOfRange, "bit position exceeds size of rt")
// mnemonics_*.inc.hpp
OAKNUT_EXCEPTION(InvalidCombination, "InvalidCombination")
OAKNUT_EXCEPTION(InvalidCond, "Cond cannot be AL or NV here")
OAKNUT_EXCEPTION(InvalidPairFirst, "Requires even register")
OAKNUT_EXCEPTION(InvalidPairSecond, "Invalid second register in pair")
OAKNUT_EXCEPTION(InvalidOperandXZR, "xzr invalid here")
// oaknut.hpp
OAKNUT_EXCEPTION(InvalidAlignment, "invalid alignment")
OAKNUT_EXCEPTION(LabelRedefinition, "label already resolved")

View file

@ -7,6 +7,8 @@
#include <cstdint> #include <cstdint>
#include <variant> #include <variant>
#include "oaknut/oaknut_exception.hpp"
namespace oaknut { namespace oaknut {
struct Label; struct Label;
@ -51,9 +53,9 @@ struct AddrOffset {
{ {
const std::uint64_t diff_u64 = static_cast<std::uint64_t>(diff); const std::uint64_t diff_u64 = static_cast<std::uint64_t>(diff);
if (detail::sign_extend<bitsize>(diff_u64) != diff_u64) if (detail::sign_extend<bitsize>(diff_u64) != diff_u64)
throw "out of range"; throw OaknutException{ExceptionType::OffsetOutOfRange};
if (diff_u64 != (diff_u64 & detail::inverse_mask_from_size(alignment))) if (diff_u64 != (diff_u64 & detail::inverse_mask_from_size(alignment)))
throw "misalignment"; throw OaknutException{ExceptionType::OffsetMisaligned};
return static_cast<std::uint32_t>((diff_u64 & detail::mask_from_size(bitsize)) >> alignment); return static_cast<std::uint32_t>((diff_u64 & detail::mask_from_size(bitsize)) >> alignment);
} }
@ -78,7 +80,7 @@ struct PageOffset {
{ {
std::uint64_t diff = (static_cast<std::uint64_t>(target) >> shift_amount) - (static_cast<std::uint64_t>(current_addr) >> shift_amount); std::uint64_t diff = (static_cast<std::uint64_t>(target) >> shift_amount) - (static_cast<std::uint64_t>(current_addr) >> shift_amount);
if (detail::sign_extend<bitsize>(diff) != diff) if (detail::sign_extend<bitsize>(diff) != diff)
throw "out of range"; throw OaknutException{ExceptionType::OffsetOutOfRange};
diff &= detail::mask_from_size(bitsize); diff &= detail::mask_from_size(bitsize);
return static_cast<std::uint32_t>(((diff & 3) << (bitsize - 2)) | (diff >> 2)); return static_cast<std::uint32_t>(((diff & 3) << (bitsize - 2)) | (diff >> 2));
} }
@ -95,9 +97,9 @@ struct SOffset {
{ {
const std::uint64_t diff_u64 = static_cast<std::uint64_t>(offset); const std::uint64_t diff_u64 = static_cast<std::uint64_t>(offset);
if (detail::sign_extend<bitsize>(diff_u64) != diff_u64) if (detail::sign_extend<bitsize>(diff_u64) != diff_u64)
throw "out of range"; throw OaknutException{ExceptionType::OffsetOutOfRange};
if (diff_u64 != (diff_u64 & detail::inverse_mask_from_size(alignment))) if (diff_u64 != (diff_u64 & detail::inverse_mask_from_size(alignment)))
throw "misalignment"; throw OaknutException{ExceptionType::OffsetMisaligned};
m_encoded = static_cast<std::uint32_t>((diff_u64 & detail::mask_from_size(bitsize)) >> alignment); m_encoded = static_cast<std::uint32_t>((diff_u64 & detail::mask_from_size(bitsize)) >> alignment);
} }
@ -114,9 +116,9 @@ struct POffset {
{ {
const std::uint64_t diff_u64 = static_cast<std::uint64_t>(offset); const std::uint64_t diff_u64 = static_cast<std::uint64_t>(offset);
if (diff_u64 > detail::mask_from_size(bitsize)) if (diff_u64 > detail::mask_from_size(bitsize))
throw "out of range"; throw OaknutException{ExceptionType::OffsetOutOfRange};
if (diff_u64 != (diff_u64 & detail::inverse_mask_from_size(alignment))) if (diff_u64 != (diff_u64 & detail::inverse_mask_from_size(alignment)))
throw "misalignment"; throw OaknutException{ExceptionType::OffsetMisaligned};
m_encoded = static_cast<std::uint32_t>((diff_u64 & detail::mask_from_size(bitsize)) >> alignment); m_encoded = static_cast<std::uint32_t>((diff_u64 & detail::mask_from_size(bitsize)) >> alignment);
} }

View file

@ -7,6 +7,8 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include "oaknut/oaknut_exception.hpp"
namespace oaknut { namespace oaknut {
struct Reg; struct Reg;
@ -117,14 +119,14 @@ struct WReg : public RReg {
inline XReg RReg::toX() const inline XReg RReg::toX() const
{ {
if (index() == -1) if (index() == -1)
throw "cannot convert SP/WSP to XReg"; throw OaknutException{ExceptionType::InvalidXSPConversion};
return XReg{index()}; return XReg{index()};
} }
inline WReg RReg::toW() const inline WReg RReg::toW() const
{ {
if (index() == -1) if (index() == -1)
throw "cannot convert SP/WSP to WReg"; throw OaknutException{ExceptionType::InvalidWSPConversion};
return WReg{index()}; return WReg{index()};
} }
@ -146,7 +148,7 @@ struct XRegSp : public RReg {
: RReg(64, xr.index()) : RReg(64, xr.index())
{ {
if (xr.index() == 31) if (xr.index() == 31)
throw "unexpected ZR passed into an XRegSp"; throw OaknutException{ExceptionType::InvalidXZRConversion};
} }
template<typename Policy> template<typename Policy>
@ -161,7 +163,7 @@ struct WRegWsp : public RReg {
: RReg(32, wr.index()) : RReg(32, wr.index())
{ {
if (wr.index() == 31) if (wr.index() == 31)
throw "unexpected WZR passed into an WRegWsp"; throw OaknutException{ExceptionType::InvalidWZRConversion};
} }
template<typename Policy> template<typename Policy>
@ -296,7 +298,7 @@ struct Elem {
: m_esize(esize_), m_reg(reg_), m_elem_index(elem_index_) : m_esize(esize_), m_reg(reg_), m_elem_index(elem_index_)
{ {
if (elem_index_ >= 128 / esize_) if (elem_index_ >= 128 / esize_)
throw "invalid elem_index"; throw OaknutException{ExceptionType::InvalidElementIndex};
} }
constexpr unsigned esize() const { return m_esize; } constexpr unsigned esize() const { return m_esize; }
@ -338,7 +340,7 @@ struct DElem_1 : public DElem {
: DElem(inner) : DElem(inner)
{ {
if (inner.elem_index() != 1) if (inner.elem_index() != 1)
throw "invalid DElem_1"; throw OaknutException{ExceptionType::InvalidDElem_1};
} }
}; };

View file

@ -19,6 +19,7 @@
#include "oaknut/impl/offset.hpp" #include "oaknut/impl/offset.hpp"
#include "oaknut/impl/reg.hpp" #include "oaknut/impl/reg.hpp"
#include "oaknut/impl/string_literal.hpp" #include "oaknut/impl/string_literal.hpp"
#include "oaknut/oaknut_exception.hpp"
namespace oaknut { namespace oaknut {
@ -87,7 +88,7 @@ public:
void l(Label& label) void l(Label& label)
{ {
if (label.m_addr) if (label.m_addr)
throw "label already resolved"; throw OaknutException{ExceptionType::LabelRedefinition};
const auto target_addr = Policy::current_address(); const auto target_addr = Policy::current_address();
label.m_addr = target_addr; label.m_addr = target_addr;
@ -170,7 +171,8 @@ public:
} }
// Convenience function for moving pointers to registers // Convenience function for moving pointers to registers
void MOVP2R(XReg xd, const void* addr) { void MOVP2R(XReg xd, const void* addr)
{
int64_t diff = reinterpret_cast<uint64_t>(addr) - Policy::current_address(); int64_t diff = reinterpret_cast<uint64_t>(addr) - Policy::current_address();
if (diff >= -0xF'FFFF && diff <= 0xF'FFFF) { if (diff >= -0xF'FFFF && diff <= 0xF'FFFF) {
ADR(xd, addr); ADR(xd, addr);
@ -184,7 +186,7 @@ public:
void align(std::size_t alignment) void align(std::size_t alignment)
{ {
if (alignment < 4 || (alignment & (alignment - 1)) != 0) if (alignment < 4 || (alignment & (alignment - 1)) != 0)
throw "invalid alignment"; throw OaknutException{ExceptionType::InvalidAlignment};
while (Policy::template ptr<std::uintptr_t>() & (alignment - 1)) { while (Policy::template ptr<std::uintptr_t>() & (alignment - 1)) {
NOP(); NOP();

View file

@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: Copyright (c) 2023 merryhime <https://mary.rs>
// SPDX-License-Identifier: MIT
#pragma once
#include <exception>
namespace oaknut {
enum class ExceptionType {
#define OAKNUT_EXCEPTION(tag, str) tag,
#include "oaknut/impl/oaknut_exception.inc.hpp"
#undef OAKNUT_EXCEPTION
};
inline const char* to_string(ExceptionType et)
{
switch (et) {
#define OAKNUT_EXCEPTION(tag, str) \
case ExceptionType::tag: \
return str;
#include "oaknut/impl/oaknut_exception.inc.hpp"
#undef OAKNUT_EXCEPTION
default:
return "unknown ExceptionType";
}
}
class OaknutException : public std::exception {
public:
explicit OaknutException(ExceptionType et)
: type{et}
{}
const char* what() const noexcept override
{
return to_string(type);
}
private:
ExceptionType type;
};
} // namespace oaknut

View file

@ -187,8 +187,7 @@ TEST_CASE("MOVP2R")
{ {
CodeBlock mem{4096}; CodeBlock mem{4096};
for (int i = 0; i < 0x200'0000; i++) for (int i = 0; i < 0x200'0000; i++) {
{
const std::int64_t diff = RandInt<std::int64_t>(std::numeric_limits<std::int64_t>::min(), const std::int64_t diff = RandInt<std::int64_t>(std::numeric_limits<std::int64_t>::min(),
std::numeric_limits<std::int64_t>::max()); std::numeric_limits<std::int64_t>::max());
const std::intptr_t value = reinterpret_cast<std::intptr_t>(mem.ptr()) + diff; const std::intptr_t value = reinterpret_cast<std::intptr_t>(mem.ptr()) + diff;