aboutsummaryrefslogtreecommitdiff
path: root/externals/oaknut/tests/vector_code_gen.cpp
blob: 5ede9e565cbd6152eddd76eb015b4f34a59a21e7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// SPDX-FileCopyrightText: Copyright (c) 2023 merryhime <https://mary.rs>
// SPDX-License-Identifier: MIT

#include <cstdint>
#include <cstdio>
#include <cstring>
#include <limits>
#include <vector>

#include <catch2/catch_test_macros.hpp>

#include "architecture.hpp"

#ifdef ON_ARM64

#    include "oaknut/code_block.hpp"
#    include "oaknut/oaknut.hpp"
#    include "rand_int.hpp"

using namespace oaknut;
using namespace oaknut::util;

TEST_CASE("Basic Test (VectorCodeGenerator)")
{
    std::vector<std::uint32_t> vec;
    VectorCodeGenerator code{vec};

    code.MOV(W0, 42);
    code.RET();

    CodeBlock mem{4096};

    mem.unprotect();
    std::memcpy(mem.ptr(), vec.data(), vec.size() * sizeof(std::uint32_t));
    mem.protect();
    mem.invalidate_all();

    int result = ((int (*)())mem.ptr())();
    REQUIRE(result == 42);
}

TEST_CASE("Fibonacci (VectorCodeGenerator)")
{
    std::vector<std::uint32_t> vec;
    VectorCodeGenerator code{vec};

    Label start, end, zero, recurse;

    code.l(start);
    code.STP(X29, X30, SP, PRE_INDEXED, -32);
    code.STP(X20, X19, SP, 16);
    code.MOV(X29, SP);
    code.MOV(W19, W0);
    code.SUBS(W0, W0, 1);
    code.B(LT, zero);
    code.B(NE, recurse);
    code.MOV(W0, 1);
    code.B(end);

    code.l(zero);
    code.MOV(W0, WZR);
    code.B(end);

    code.l(recurse);
    code.BL(start);
    code.MOV(W20, W0);
    code.SUB(W0, W19, 2);
    code.BL(start);
    code.ADD(W0, W0, W20);

    code.l(end);
    code.LDP(X20, X19, SP, 16);
    code.LDP(X29, X30, SP, POST_INDEXED, 32);
    code.RET();

    CodeBlock mem{4096};

    mem.unprotect();
    std::memcpy(mem.ptr(), vec.data(), vec.size() * sizeof(std::uint32_t));
    mem.protect();
    mem.invalidate_all();

    auto fib = (int (*)(int))mem.ptr();

    REQUIRE(fib(0) == 0);
    REQUIRE(fib(1) == 1);
    REQUIRE(fib(5) == 5);
    REQUIRE(fib(9) == 34);
}

#endif