Squashed 'externals/oaknut/' changes from d0488d932..9d091109d
9d091109d oaknut: 2.0.1 7f3e9f600 oaknut: Support single argument constructor for CodeGenerator again git-subtree-dir: externals/oaknut git-subtree-split: 9d091109deb445bc6e9289c6195a282b7c993d49
This commit is contained in:
parent
99c0a73f91
commit
a37f3673f8
7 changed files with 58 additions and 43 deletions
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.8)
|
cmake_minimum_required(VERSION 3.8)
|
||||||
project(oaknut LANGUAGES CXX VERSION 2.0.0)
|
project(oaknut LANGUAGES CXX VERSION 2.0.1)
|
||||||
|
|
||||||
# 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.
|
||||||
|
|
|
@ -32,7 +32,7 @@ EmittedFunction EmitExample(oaknut::CodeGenerator& code, int value)
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
oaknut::CodeBlock mem{4096};
|
oaknut::CodeBlock mem{4096};
|
||||||
oaknut::CodeGenerator code{mem.ptr(), mem.ptr()};
|
oaknut::CodeGenerator code{mem.ptr()};
|
||||||
|
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ int main()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
CodeGenerator takes two pointers. The first pointer is the memory address to write to, and the second pointer is the memory address that the code will be executing from. This allows you to write to a buffer before copying to the final destination for execution, or to have to use dual-mapped memory blocks to avoid memory protection overhead.
|
CodeGenerator also has a constructor taking two pointers. The first pointer is the memory address to write to, and the second pointer is the memory address that the code will be executing from. This allows you to write to a buffer before copying to the final destination for execution, or to have to use dual-mapped memory blocks to avoid memory protection overhead.
|
||||||
|
|
||||||
Below is an example of using the oaknut-provided utility header for dual-mapped memory blocks:
|
Below is an example of using the oaknut-provided utility header for dual-mapped memory blocks:
|
||||||
|
|
||||||
|
|
|
@ -300,8 +300,21 @@ private:
|
||||||
std::uint32_t* const m_xmem;
|
std::uint32_t* const m_xmem;
|
||||||
};
|
};
|
||||||
|
|
||||||
using CodeGenerator = BasicCodeGenerator<PointerCodeGeneratorPolicy>;
|
struct CodeGenerator : BasicCodeGenerator<PointerCodeGeneratorPolicy> {
|
||||||
using VectorCodeGenerator = BasicCodeGenerator<VectorCodeGeneratorPolicy>;
|
public:
|
||||||
|
CodeGenerator(std::uint32_t* mem)
|
||||||
|
: BasicCodeGenerator<PointerCodeGeneratorPolicy>(mem, mem) {}
|
||||||
|
CodeGenerator(std::uint32_t* wmem, std::uint32_t* xmem)
|
||||||
|
: BasicCodeGenerator<PointerCodeGeneratorPolicy>(wmem, xmem) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VectorCodeGenerator : BasicCodeGenerator<VectorCodeGeneratorPolicy> {
|
||||||
|
public:
|
||||||
|
VectorCodeGenerator(std::vector<std::uint32_t>& mem)
|
||||||
|
: BasicCodeGenerator<VectorCodeGeneratorPolicy>(mem, nullptr) {}
|
||||||
|
VectorCodeGenerator(std::vector<std::uint32_t>& wmem, std::uint32_t* xmem)
|
||||||
|
: BasicCodeGenerator<VectorCodeGeneratorPolicy>(wmem, xmem) {}
|
||||||
|
};
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ using namespace oaknut::util;
|
||||||
TEST_CASE("Basic Test")
|
TEST_CASE("Basic Test")
|
||||||
{
|
{
|
||||||
CodeBlock mem{4096};
|
CodeBlock mem{4096};
|
||||||
CodeGenerator code{mem.ptr(), mem.ptr()};
|
CodeGenerator code{mem.ptr()};
|
||||||
|
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ TEST_CASE("Basic Test (Dual)")
|
||||||
TEST_CASE("Fibonacci")
|
TEST_CASE("Fibonacci")
|
||||||
{
|
{
|
||||||
CodeBlock mem{4096};
|
CodeBlock mem{4096};
|
||||||
CodeGenerator code{mem.ptr(), mem.ptr()};
|
CodeGenerator code{mem.ptr()};
|
||||||
|
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ TEST_CASE("Immediate generation (32-bit)", "[slow]")
|
||||||
for (int i = 0; i < 0x100000; i++) {
|
for (int i = 0; i < 0x100000; i++) {
|
||||||
const std::uint32_t value = RandInt<std::uint32_t>(0, 0xffffffff);
|
const std::uint32_t value = RandInt<std::uint32_t>(0, 0xffffffff);
|
||||||
|
|
||||||
CodeGenerator code{mem.ptr(), mem.ptr()};
|
CodeGenerator code{mem.ptr()};
|
||||||
|
|
||||||
auto f = code.xptr<std::uint64_t (*)()>();
|
auto f = code.xptr<std::uint64_t (*)()>();
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
|
@ -162,7 +162,7 @@ TEST_CASE("Immediate generation (64-bit)", "[slow]")
|
||||||
for (int i = 0; i < 0x100000; i++) {
|
for (int i = 0; i < 0x100000; i++) {
|
||||||
const std::uint64_t value = RandInt<std::uint64_t>(0, 0xffffffff'ffffffff);
|
const std::uint64_t value = RandInt<std::uint64_t>(0, 0xffffffff'ffffffff);
|
||||||
|
|
||||||
CodeGenerator code{mem.ptr(), mem.ptr()};
|
CodeGenerator code{mem.ptr()};
|
||||||
|
|
||||||
auto f = code.xptr<std::uint64_t (*)()>();
|
auto f = code.xptr<std::uint64_t (*)()>();
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
|
@ -182,7 +182,7 @@ TEST_CASE("ADR", "[slow]")
|
||||||
for (std::int64_t i = -1048576; i < 1048576; i++) {
|
for (std::int64_t i = -1048576; i < 1048576; i++) {
|
||||||
const std::intptr_t value = reinterpret_cast<std::intptr_t>(mem.ptr()) + i;
|
const std::intptr_t value = reinterpret_cast<std::intptr_t>(mem.ptr()) + i;
|
||||||
|
|
||||||
CodeGenerator code{mem.ptr(), mem.ptr()};
|
CodeGenerator code{mem.ptr()};
|
||||||
|
|
||||||
auto f = code.xptr<std::intptr_t (*)()>();
|
auto f = code.xptr<std::intptr_t (*)()>();
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
|
@ -218,7 +218,7 @@ TEST_CASE("ADRP", "[slow]")
|
||||||
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;
|
||||||
const std::uint64_t expect = static_cast<std::uint64_t>(value) & ~static_cast<std::uint64_t>(0xfff);
|
const std::uint64_t expect = static_cast<std::uint64_t>(value) & ~static_cast<std::uint64_t>(0xfff);
|
||||||
|
|
||||||
CodeGenerator code{mem.ptr(), mem.ptr()};
|
CodeGenerator code{mem.ptr()};
|
||||||
|
|
||||||
auto f = code.xptr<std::uint64_t (*)()>();
|
auto f = code.xptr<std::uint64_t (*)()>();
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
|
@ -241,7 +241,7 @@ TEST_CASE("ADRL (near)")
|
||||||
const std::int64_t diff = i;
|
const std::int64_t diff = i;
|
||||||
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;
|
||||||
|
|
||||||
CodeGenerator code{mem_ptr, mem_ptr};
|
CodeGenerator code{mem_ptr};
|
||||||
|
|
||||||
auto f = code.xptr<std::uint64_t (*)()>();
|
auto f = code.xptr<std::uint64_t (*)()>();
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
|
@ -264,7 +264,7 @@ TEST_CASE("ADRL (far)", "[slow]")
|
||||||
const std::int64_t diff = RandInt<std::int64_t>(-4294967296 + 100, 4294967295 - 100);
|
const std::int64_t diff = RandInt<std::int64_t>(-4294967296 + 100, 4294967295 - 100);
|
||||||
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;
|
||||||
|
|
||||||
CodeGenerator code{mem_ptr, mem_ptr};
|
CodeGenerator code{mem_ptr};
|
||||||
|
|
||||||
auto f = code.xptr<std::uint64_t (*)()>();
|
auto f = code.xptr<std::uint64_t (*)()>();
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
|
@ -288,7 +288,7 @@ TEST_CASE("MOVP2R (far)", "[slow]")
|
||||||
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;
|
||||||
|
|
||||||
CodeGenerator code{mem_ptr, mem_ptr};
|
CodeGenerator code{mem_ptr};
|
||||||
|
|
||||||
auto f = code.xptr<std::uint64_t (*)()>();
|
auto f = code.xptr<std::uint64_t (*)()>();
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
|
@ -310,7 +310,7 @@ TEST_CASE("MOVP2R (4GiB boundary)")
|
||||||
const auto test = [&](std::int64_t diff) {
|
const auto test = [&](std::int64_t diff) {
|
||||||
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;
|
||||||
|
|
||||||
CodeGenerator code{mem_ptr, mem_ptr};
|
CodeGenerator code{mem_ptr};
|
||||||
|
|
||||||
auto f = code.xptr<std::uint64_t (*)()>();
|
auto f = code.xptr<std::uint64_t (*)()>();
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
|
|
|
@ -8,18 +8,18 @@
|
||||||
|
|
||||||
#include "oaknut/oaknut.hpp"
|
#include "oaknut/oaknut.hpp"
|
||||||
|
|
||||||
#define T(HEX, CMD) \
|
#define T(HEX, CMD) \
|
||||||
TEST_CASE(#CMD) \
|
TEST_CASE(#CMD) \
|
||||||
{ \
|
{ \
|
||||||
using namespace oaknut; \
|
using namespace oaknut; \
|
||||||
using namespace oaknut::util; \
|
using namespace oaknut::util; \
|
||||||
\
|
\
|
||||||
std::uint32_t result; \
|
std::uint32_t result; \
|
||||||
CodeGenerator code{&result, &result}; \
|
CodeGenerator code{&result}; \
|
||||||
\
|
\
|
||||||
code.CMD; \
|
code.CMD; \
|
||||||
\
|
\
|
||||||
REQUIRE(result == HEX); \
|
REQUIRE(result == HEX); \
|
||||||
}
|
}
|
||||||
|
|
||||||
T(0x5ee0bb61, ABS(D1, D27))
|
T(0x5ee0bb61, ABS(D1, D27))
|
||||||
|
|
|
@ -8,18 +8,18 @@
|
||||||
|
|
||||||
#include "oaknut/oaknut.hpp"
|
#include "oaknut/oaknut.hpp"
|
||||||
|
|
||||||
#define T(HEX, CMD) \
|
#define T(HEX, CMD) \
|
||||||
TEST_CASE(#CMD) \
|
TEST_CASE(#CMD) \
|
||||||
{ \
|
{ \
|
||||||
using namespace oaknut; \
|
using namespace oaknut; \
|
||||||
using namespace oaknut::util; \
|
using namespace oaknut::util; \
|
||||||
\
|
\
|
||||||
std::uint32_t result; \
|
std::uint32_t result; \
|
||||||
CodeGenerator code{&result, &result}; \
|
CodeGenerator code{&result}; \
|
||||||
\
|
\
|
||||||
code.CMD; \
|
code.CMD; \
|
||||||
\
|
\
|
||||||
REQUIRE(result == HEX); \
|
REQUIRE(result == HEX); \
|
||||||
}
|
}
|
||||||
|
|
||||||
T(0x1a0f01c3, ADC(W3, W14, W15))
|
T(0x1a0f01c3, ADC(W3, W14, W15))
|
||||||
|
|
|
@ -18,13 +18,14 @@ using namespace oaknut::util;
|
||||||
|
|
||||||
TEST_CASE("Basic Test (VectorCodeGenerator)")
|
TEST_CASE("Basic Test (VectorCodeGenerator)")
|
||||||
{
|
{
|
||||||
CodeBlock mem{4096};
|
|
||||||
std::vector<std::uint32_t> vec;
|
std::vector<std::uint32_t> vec;
|
||||||
VectorCodeGenerator code{vec, mem.ptr()};
|
VectorCodeGenerator code{vec};
|
||||||
|
|
||||||
code.MOV(W0, 42);
|
code.MOV(W0, 42);
|
||||||
code.RET();
|
code.RET();
|
||||||
|
|
||||||
|
CodeBlock mem{4096};
|
||||||
|
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
std::memcpy(mem.ptr(), vec.data(), vec.size() * sizeof(std::uint32_t));
|
std::memcpy(mem.ptr(), vec.data(), vec.size() * sizeof(std::uint32_t));
|
||||||
mem.protect();
|
mem.protect();
|
||||||
|
@ -36,9 +37,8 @@ TEST_CASE("Basic Test (VectorCodeGenerator)")
|
||||||
|
|
||||||
TEST_CASE("Fibonacci (VectorCodeGenerator)")
|
TEST_CASE("Fibonacci (VectorCodeGenerator)")
|
||||||
{
|
{
|
||||||
CodeBlock mem{4096};
|
|
||||||
std::vector<std::uint32_t> vec;
|
std::vector<std::uint32_t> vec;
|
||||||
VectorCodeGenerator code{vec, mem.ptr()};
|
VectorCodeGenerator code{vec};
|
||||||
|
|
||||||
Label start, end, zero, recurse;
|
Label start, end, zero, recurse;
|
||||||
|
|
||||||
|
@ -69,6 +69,8 @@ TEST_CASE("Fibonacci (VectorCodeGenerator)")
|
||||||
code.LDP(X29, X30, SP, POST_INDEXED, 32);
|
code.LDP(X29, X30, SP, POST_INDEXED, 32);
|
||||||
code.RET();
|
code.RET();
|
||||||
|
|
||||||
|
CodeBlock mem{4096};
|
||||||
|
|
||||||
mem.unprotect();
|
mem.unprotect();
|
||||||
std::memcpy(mem.ptr(), vec.data(), vec.size() * sizeof(std::uint32_t));
|
std::memcpy(mem.ptr(), vec.data(), vec.size() * sizeof(std::uint32_t));
|
||||||
mem.protect();
|
mem.protect();
|
||||||
|
|
Loading…
Reference in a new issue