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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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;
}
|