diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-03-07 18:50:34 +0200 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-03-07 18:52:54 +0200 |
commit | ba9145b0b7af2a82c62f8dfa28807958af5d0c8d (patch) | |
tree | 52e14e07d82d57a305334f1300293d6b0af75aca /examples/matrix_mult.c | |
parent | 6d00dddef440590eaba9acdc9bbd093653d46519 (diff) | |
download | ejit-ba9145b0b7af2a82c62f8dfa28807958af5d0c8d.tar.gz ejit-ba9145b0b7af2a82c62f8dfa28807958af5d0c8d.zip |
make code a bit more robust
+ Should be more difficult to make mistakes in the future, ejit can now
automatically keep track of how many register slots are used and if 64
bit mode is required. Slight runtime overhead, but not too bad.
Diffstat (limited to 'examples/matrix_mult.c')
-rw-r--r-- | examples/matrix_mult.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/examples/matrix_mult.c b/examples/matrix_mult.c new file mode 100644 index 0000000..04ebb9d --- /dev/null +++ b/examples/matrix_mult.c @@ -0,0 +1,133 @@ +#include <stdio.h> +#include "../include/ejit/ejit.h" + +#define X 400 +int A[X][X]; +int B[X][X]; +int C[X][X]; + +static void init_matrices(int A[X][X], int B[X][X]) +{ + int counter = 0; + for (size_t i = 0; i < X; ++i) + for (size_t j = 0; j < X; ++j) { + A[i][j] = counter; + B[i][j] = counter; + C[i][j] = 0; + + counter++; + } +} + +static int hash(int C[X][X]) +{ + int h = 0; + for (size_t i = 0; i < X; ++i) + for (size_t j = 0; j < X; ++j) { + h += C[i][j]; + } + + return h; +} + +static struct ejit_func *compile() +{ +#define IR EJIT_GPR(0) +#define JR EJIT_GPR(1) +#define KR EJIT_GPR(2) +#define AR EJIT_GPR(3) +#define BR EJIT_GPR(4) +#define CR EJIT_GPR(5) +#define AX EJIT_GPR(6) +#define BX EJIT_GPR(7) +#define CX EJIT_GPR(8) +#define TMP EJIT_GPR(9) + + struct ejit_operand args[3] = { + EJIT_OPERAND_GPR(3, EJIT_TYPE(int *)), + EJIT_OPERAND_GPR(4, EJIT_TYPE(int *)), + EJIT_OPERAND_GPR(5, EJIT_TYPE(int *)) + }; + struct ejit_func *f = ejit_create_func(EJIT_VOID, 3, args); + + ejit_movi(f, IR, 0); + struct ejit_label out = ejit_label(f); + struct ejit_reloc outer = ejit_bgei(f, IR, X); + + ejit_movi(f, JR, 0); + struct ejit_label mid = ejit_label(f); + struct ejit_reloc midder = ejit_bgei(f, JR, X); + + ejit_movi(f, KR, 0); + struct ejit_label in = ejit_label(f); + struct ejit_reloc inner = ejit_bgei(f, KR, X); + + /* A[i][k] at addr 4 * (i * 400 + k) */ + ejit_movi(f, TMP, 400); + ejit_mulr(f, AX, IR, TMP); + ejit_addr(f, AX, AX, KR); + ejit_movi(f, TMP, 4); + ejit_lshi(f, AX, AX, 2); + EJIT_LDXR(f, int, AX, AR, AX); + + /* B[k][j] at addr 4 * (k * 400 + j) */ + ejit_movi(f, TMP, 400); + ejit_mulr(f, BX, KR, TMP); + ejit_addr(f, BX, BX, JR); + ejit_movi(f, TMP, 4); + ejit_lshi(f, BX, BX, 2); + EJIT_LDXR(f, int, BX, BR, BX); + + /* C[i][j] at addr 4 * (i * 400 + j) */ + ejit_movi(f, TMP, 400); + ejit_mulr(f, CX, IR, TMP); + ejit_addr(f, CX, CX, JR); + ejit_movi(f, TMP, 4); + /* reuse address */ + ejit_lshi(f, TMP, CX, 2); + EJIT_LDXR(f, int, CX, CR, TMP); + + ejit_mulr(f, AX, AX, BX); + ejit_addr(f, CX, CX, AX); + + /* store result */ + EJIT_STXR(f, int, CX, CR, TMP); + + /* increment inner */ + ejit_addi(f, KR, KR, 1); + ejit_patch(f, ejit_jmp(f), in); + /* end of inner */ + ejit_patch(f, inner, ejit_label(f)); + + /* increment midder */ + ejit_addi(f, JR, JR, 1); + ejit_patch(f, ejit_jmp(f), mid); + /* end of midder */ + ejit_patch(f, midder, ejit_label(f)); + + /* increment outer */ + ejit_addi(f, IR, IR, 1); + ejit_patch(f, ejit_jmp(f), out); + /* end of outer */ + ejit_patch(f, outer, ejit_label(f)); + + /* return */ + ejit_ret(f); + ejit_compile_func(f); + return f; +} + +int main() +{ + init_matrices(A, B); + struct ejit_func *f = compile(); + struct ejit_arg args[3] = { + EJIT_ARG(A, int *), + EJIT_ARG(B, int *), + EJIT_ARG(C, int *) + }; + ejit_run_func(f, 3, args); + printf("%d\n", hash(C)); + ejit_destroy_func(f); + return 0; +} |