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)
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)
# or if this is the master project.

View file

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

View file

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

View file

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

View file

@ -7,6 +7,8 @@
#include <tuple>
#include <type_traits>
#include "oaknut/oaknut_exception.hpp"
namespace oaknut {
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>);
if (!verify(std::index_sequence_for<U...>{}, args...))
throw "invalid List";
throw OaknutException{ExceptionType::InvalidList};
}
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)
{
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);
}
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)
{
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);
}
void SQRDMLAH(VReg_8H rd, VReg_8H rn, HElem em)
{
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);
}
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)
{
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);
}
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)
{
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);
}
void SQRDMLSH(VReg_8H rd, VReg_8H rn, HElem em)
{
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);
}
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)
{
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);
}
void FMLA(VReg_8B rd, VReg_8B rn, HElem em)
{
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);
}
void FMLA(VReg_16B rd, VReg_16B rn, HElem em)
{
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);
}
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)
{
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);
}
void FMLAL(VReg_4S rd, VReg_4H rn, HElem em)
{
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);
}
void FMLAL2(VReg_2S rd, VReg_2H rn, HElem em)
{
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);
}
void FMLAL2(VReg_4S rd, VReg_4H rn, HElem em)
{
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);
}
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)
{
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);
}
void FMLS(VReg_8B rd, VReg_8B rn, HElem em)
{
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);
}
void FMLS(VReg_16B rd, VReg_16B rn, HElem em)
{
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);
}
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)
{
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);
}
void FMLSL(VReg_4S rd, VReg_4H rn, HElem em)
{
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);
}
void FMLSL2(VReg_2S rd, VReg_2H rn, HElem em)
{
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);
}
void FMLSL2(VReg_4S rd, VReg_4H rn, HElem em)
{
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);
}
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)
{
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);
}
void FMUL(VReg_8B rd, VReg_8B rn, HElem em)
{
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);
}
void FMUL(VReg_16B rd, VReg_16B rn, HElem em)
{
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);
}
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)
{
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);
}
void FMULX(VReg_8B rd, VReg_8B rn, HElem em)
{
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);
}
void FMULX(VReg_16B rd, VReg_16B rn, HElem em)
{
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);
}
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)
{
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);
}
void BFI(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width)
{
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);
}
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)
{
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);
}
void BFXIL(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width)
{
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);
}
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)
{
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));
}
void CINC(XReg xd, XReg xn, Cond cond)
{
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));
}
void CINV(WReg wd, WReg wn, Cond cond)
{
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));
}
void CINV(XReg xd, XReg xn, Cond cond)
{
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));
}
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)
{
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));
}
void CNEG(XReg xd, XReg xn, Cond cond)
{
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));
}
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)
{
if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond";
throw OaknutException{ExceptionType::InvalidCond};
emit<"0001101010011111cccc0111111ddddd", "d", "c">(wd, invert(cond));
}
void CSET(XReg xd, Cond cond)
{
if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond";
throw OaknutException{ExceptionType::InvalidCond};
emit<"1001101010011111cccc0111111ddddd", "d", "c">(xd, invert(cond));
}
void CSETM(WReg wd, Cond cond)
{
if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond";
throw OaknutException{ExceptionType::InvalidCond};
emit<"0101101010011111cccc0011111ddddd", "d", "c">(wd, invert(cond));
}
void CSETM(XReg xd, Cond cond)
{
if (cond == Cond::AL || cond == Cond::NV)
throw "invalid Cond";
throw OaknutException{ExceptionType::InvalidCond};
emit<"1101101010011111cccc0011111ddddd", "d", "c">(xd, invert(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)
{
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);
}
void SBFIZ(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width)
{
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);
}
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)
{
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);
}
void SBFX(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width)
{
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);
}
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)
{
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);
}
void UBFIZ(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width)
{
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);
}
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)
{
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);
}
void UBFX(XReg xd, XReg xn, Imm<6> lsb, Imm<6> width)
{
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);
}
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)
{
if (wt.index() + 1 != wt2.index())
throw "Invalid second register in pair";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (wt.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
if (ws.index() + 1 != ws2.index())
throw "Invalid second register in pair";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (ws.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
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";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (wt.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
if (ws.index() + 1 != ws2.index())
throw "Invalid second register in pair";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (ws.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
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";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (wt.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
if (ws.index() + 1 != ws2.index())
throw "Invalid second register in pair";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (ws.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
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";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (wt.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
if (ws.index() + 1 != ws2.index())
throw "Invalid second register in pair";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (ws.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
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";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (xt.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
if (xs.index() + 1 != xs2.index())
throw "Invalid second register in pair";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (xs.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
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";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (xt.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
if (xs.index() + 1 != xs2.index())
throw "Invalid second register in pair";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (xs.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
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";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (xt.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
if (xs.index() + 1 != xs2.index())
throw "Invalid second register in pair";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (xs.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
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";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (xt.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
if (xs.index() + 1 != xs2.index())
throw "Invalid second register in pair";
throw OaknutException{ExceptionType::InvalidPairSecond};
if (xs.index() & 1)
throw "Requires even register";
throw OaknutException{ExceptionType::InvalidPairFirst};
emit<"01001000001sssss111111nnnnnttttt", "s", "t", "n">(xs, xt, 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)
{
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);
}
void BFC(XReg xd, Imm<6> lsb, Imm<6> width)
{
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);
}
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 <variant>
#include "oaknut/oaknut_exception.hpp"
namespace oaknut {
struct Label;
@ -51,9 +53,9 @@ struct AddrOffset {
{
const std::uint64_t diff_u64 = static_cast<std::uint64_t>(diff);
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)))
throw "misalignment";
throw OaknutException{ExceptionType::OffsetMisaligned};
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);
if (detail::sign_extend<bitsize>(diff) != diff)
throw "out of range";
throw OaknutException{ExceptionType::OffsetOutOfRange};
diff &= detail::mask_from_size(bitsize);
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);
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)))
throw "misalignment";
throw OaknutException{ExceptionType::OffsetMisaligned};
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);
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)))
throw "misalignment";
throw OaknutException{ExceptionType::OffsetMisaligned};
m_encoded = static_cast<std::uint32_t>((diff_u64 & detail::mask_from_size(bitsize)) >> alignment);
}

View file

@ -7,6 +7,8 @@
#include <cstddef>
#include <cstdint>
#include "oaknut/oaknut_exception.hpp"
namespace oaknut {
struct Reg;
@ -117,14 +119,14 @@ struct WReg : public RReg {
inline XReg RReg::toX() const
{
if (index() == -1)
throw "cannot convert SP/WSP to XReg";
throw OaknutException{ExceptionType::InvalidXSPConversion};
return XReg{index()};
}
inline WReg RReg::toW() const
{
if (index() == -1)
throw "cannot convert SP/WSP to WReg";
throw OaknutException{ExceptionType::InvalidWSPConversion};
return WReg{index()};
}
@ -146,7 +148,7 @@ struct XRegSp : public RReg {
: RReg(64, xr.index())
{
if (xr.index() == 31)
throw "unexpected ZR passed into an XRegSp";
throw OaknutException{ExceptionType::InvalidXZRConversion};
}
template<typename Policy>
@ -161,7 +163,7 @@ struct WRegWsp : public RReg {
: RReg(32, wr.index())
{
if (wr.index() == 31)
throw "unexpected WZR passed into an WRegWsp";
throw OaknutException{ExceptionType::InvalidWZRConversion};
}
template<typename Policy>
@ -296,7 +298,7 @@ struct Elem {
: m_esize(esize_), m_reg(reg_), m_elem_index(elem_index_)
{
if (elem_index_ >= 128 / esize_)
throw "invalid elem_index";
throw OaknutException{ExceptionType::InvalidElementIndex};
}
constexpr unsigned esize() const { return m_esize; }
@ -338,7 +340,7 @@ struct DElem_1 : public DElem {
: DElem(inner)
{
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/reg.hpp"
#include "oaknut/impl/string_literal.hpp"
#include "oaknut/oaknut_exception.hpp"
namespace oaknut {
@ -87,7 +88,7 @@ public:
void l(Label& label)
{
if (label.m_addr)
throw "label already resolved";
throw OaknutException{ExceptionType::LabelRedefinition};
const auto target_addr = Policy::current_address();
label.m_addr = target_addr;
@ -170,7 +171,8 @@ public:
}
// 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();
if (diff >= -0xF'FFFF && diff <= 0xF'FFFF) {
ADR(xd, addr);
@ -184,7 +186,7 @@ public:
void align(std::size_t alignment)
{
if (alignment < 4 || (alignment & (alignment - 1)) != 0)
throw "invalid alignment";
throw OaknutException{ExceptionType::InvalidAlignment};
while (Policy::template ptr<std::uintptr_t>() & (alignment - 1)) {
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};
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(),
std::numeric_limits<std::int64_t>::max());
const std::intptr_t value = reinterpret_cast<std::intptr_t>(mem.ptr()) + diff;