Squashed 'externals/oaknut/' changes from 72f7ccd94..816481f10
816481f10 oaknut: 1.1.4 a75c1144e cmake: add export rules ff4d78861 oaknut: CI: Add msvc-arm64 build d0c317831 oaknut: CI: Pin catch2 version to v3.2.0 caf9cbbdc oaknut: Implement ADRL and MOVP2R pseudo instructions (#2) git-subtree-dir: externals/oaknut git-subtree-split: 816481f1036fb4177455ffa0c7b71e6ac9193d6c
This commit is contained in:
parent
cb8abc3ae5
commit
b65b07d566
5 changed files with 113 additions and 5 deletions
37
.github/workflows/build-and-test.yml
vendored
37
.github/workflows/build-and-test.yml
vendored
|
@ -18,7 +18,11 @@ jobs:
|
||||||
qemu-user
|
qemu-user
|
||||||
|
|
||||||
- name: Checkout Catch2 v3 repo
|
- name: Checkout Catch2 v3 repo
|
||||||
run: git clone https://github.com/catchorg/Catch2.git externals/catch
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
repository: catchorg/Catch2
|
||||||
|
ref: v3.2.0
|
||||||
|
path: externals/catch
|
||||||
|
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
env:
|
env:
|
||||||
|
@ -38,3 +42,34 @@ jobs:
|
||||||
- name: Test
|
- name: Test
|
||||||
working-directory: ${{github.workspace}}/build
|
working-directory: ${{github.workspace}}/build
|
||||||
run: qemu-aarch64 -L /usr/aarch64-linux-gnu ./oaknut-tests -d yes
|
run: qemu-aarch64 -L /usr/aarch64-linux-gnu ./oaknut-tests -d yes
|
||||||
|
|
||||||
|
test_on_windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
name: msvc-arm64
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout oaknut repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Checkout Catch2 v3 repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
repository: catchorg/Catch2
|
||||||
|
ref: v3.2.0
|
||||||
|
path: externals/catch
|
||||||
|
|
||||||
|
- name: Setup msvc-arm64 environment
|
||||||
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
with:
|
||||||
|
arch: amd64_arm64
|
||||||
|
|
||||||
|
- name: Configure CMake
|
||||||
|
run: >
|
||||||
|
cmake
|
||||||
|
-B ${{github.workspace}}/build
|
||||||
|
-GNinja
|
||||||
|
-DOAKNUT_USE_BUNDLED_CATCH=ON
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
working-directory: ${{github.workspace}}/build
|
||||||
|
run: cmake --build . --config Release
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.8)
|
cmake_minimum_required(VERSION 3.8)
|
||||||
project(oaknut LANGUAGES CXX VERSION 1.1.3)
|
project(oaknut LANGUAGES CXX VERSION 1.1.4)
|
||||||
|
|
||||||
# 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.
|
||||||
|
@ -85,3 +85,12 @@ if (MASTER_PROJECT)
|
||||||
target_compile_options(oaknut-tests PRIVATE -Wall -Wextra -Wcast-qual -pedantic -pedantic-errors -Wfatal-errors -Wno-missing-braces)
|
target_compile_options(oaknut-tests PRIVATE -Wall -Wextra -Wcast-qual -pedantic -pedantic-errors -Wfatal-errors -Wno-missing-braces)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Export
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
install(TARGETS oaknut EXPORT oaknutTargets)
|
||||||
|
install(EXPORT oaknutTargets
|
||||||
|
NAMESPACE merry::
|
||||||
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/oaknut"
|
||||||
|
)
|
||||||
|
|
|
@ -66,7 +66,7 @@ private:
|
||||||
|
|
||||||
template<std::size_t bitsize, std::size_t shift_amount>
|
template<std::size_t bitsize, std::size_t shift_amount>
|
||||||
struct PageOffset {
|
struct PageOffset {
|
||||||
PageOffset(void* ptr)
|
PageOffset(const void* ptr)
|
||||||
: m_payload(ptr)
|
: m_payload(ptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ struct PageOffset {
|
||||||
private:
|
private:
|
||||||
template<typename Policy>
|
template<typename Policy>
|
||||||
friend class BasicCodeGenerator;
|
friend class BasicCodeGenerator;
|
||||||
std::variant<Label*, void*> m_payload;
|
std::variant<Label*, const void*> m_payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<std::size_t bitsize, std::size_t alignment>
|
template<std::size_t bitsize, std::size_t alignment>
|
||||||
|
|
|
@ -110,6 +110,12 @@ public:
|
||||||
return RET(XReg{30});
|
return RET(XReg{30});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ADRL(XReg xd, const void* addr)
|
||||||
|
{
|
||||||
|
ADRP(xd, addr);
|
||||||
|
ADD(xd, xd, reinterpret_cast<uint64_t>(addr) & 0xFFF);
|
||||||
|
}
|
||||||
|
|
||||||
void MOV(WReg wd, uint32_t imm)
|
void MOV(WReg wd, uint32_t imm)
|
||||||
{
|
{
|
||||||
if (wd.index() == 31)
|
if (wd.index() == 31)
|
||||||
|
@ -163,6 +169,18 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convenience function for moving pointers to registers
|
||||||
|
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);
|
||||||
|
} else if (diff >= -int64_t{0xFFFF'FFFF} && diff <= int64_t{0xFFFF'FFFF}) {
|
||||||
|
ADRL(xd, addr);
|
||||||
|
} else {
|
||||||
|
MOV(xd, reinterpret_cast<uint64_t>(addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -242,7 +260,7 @@ private:
|
||||||
label->m_wbs.emplace_back(Label::Writeback{Policy::current_address(), ~splat, static_cast<Label::EmitFunctionType>(encode_fn)});
|
label->m_wbs.emplace_back(Label::Writeback{Policy::current_address(), ~splat, static_cast<Label::EmitFunctionType>(encode_fn)});
|
||||||
return 0u;
|
return 0u;
|
||||||
},
|
},
|
||||||
[&](void* p) {
|
[&](const void* p) {
|
||||||
return encode_fn(Policy::current_address(), reinterpret_cast<std::uintptr_t>(p));
|
return encode_fn(Policy::current_address(), reinterpret_cast<std::uintptr_t>(p));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
@ -159,3 +160,48 @@ TEST_CASE("ADRP")
|
||||||
REQUIRE(f() == expect);
|
REQUIRE(f() == expect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ADRL")
|
||||||
|
{
|
||||||
|
CodeBlock mem{4096};
|
||||||
|
|
||||||
|
for (int i = 0; i < 0x200000; i++) {
|
||||||
|
const std::int64_t diff = RandInt<std::int64_t>(-4294967296, 4294967295);
|
||||||
|
const std::intptr_t value = reinterpret_cast<std::intptr_t>(mem.ptr()) + diff;
|
||||||
|
|
||||||
|
CodeGenerator code{mem.ptr()};
|
||||||
|
|
||||||
|
auto f = code.ptr<std::uint64_t (*)()>();
|
||||||
|
mem.unprotect();
|
||||||
|
code.ADRL(X0, reinterpret_cast<void*>(value));
|
||||||
|
code.RET();
|
||||||
|
mem.protect();
|
||||||
|
mem.invalidate_all();
|
||||||
|
|
||||||
|
INFO(i);
|
||||||
|
REQUIRE(f() == static_cast<std::uint64_t>(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("MOVP2R")
|
||||||
|
{
|
||||||
|
CodeBlock mem{4096};
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
CodeGenerator code{mem.ptr()};
|
||||||
|
|
||||||
|
auto f = code.ptr<std::uint64_t (*)()>();
|
||||||
|
mem.unprotect();
|
||||||
|
code.MOVP2R(X0, reinterpret_cast<void*>(value));
|
||||||
|
code.RET();
|
||||||
|
mem.protect();
|
||||||
|
mem.invalidate_all();
|
||||||
|
|
||||||
|
REQUIRE(f() == static_cast<std::uint64_t>(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue