1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <stdio.h>
19
20#define DEBUG 0
21#define DEBUG_PRINTF(...) \
22 do { \
23 if (DEBUG) { \
24 printf(__VA_ARGS__); \
25 } \
26 } while (0)
27
28
29#define NBYTES (1 << 8)
30#define NHALFS (NBYTES / sizeof(short))
31#define NWORDS (NBYTES / sizeof(int))
32#define NDOBLS (NBYTES / sizeof(long long))
33
34long long dbuf[NDOBLS] __attribute__((aligned(1 << 12))) = {0};
35int wbuf[NWORDS] __attribute__((aligned(1 << 12))) = {0};
36short hbuf[NHALFS] __attribute__((aligned(1 << 12))) = {0};
37unsigned char bbuf[NBYTES] __attribute__((aligned(1 << 12))) = {0};
38
39
40
41
42
43#define INIT(BUF, N) \
44 void init_##BUF(void) \
45 { \
46 int i; \
47 for (i = 0; i < N; i++) { \
48 BUF[i] = i; \
49 } \
50 } \
51
52INIT(bbuf, NBYTES)
53INIT(hbuf, NHALFS)
54INIT(wbuf, NWORDS)
55INIT(dbuf, NDOBLS)
56
57
58
59
60
61
62
63
64
65#define CIRC_LOAD_IMM(SIZE, RES, ADDR, START, LEN, INC) \
66 __asm__( \
67 "r4 = %3\n\t" \
68 "m0 = r4\n\t" \
69 "cs0 = %2\n\t" \
70 "%0 = mem" #SIZE "(%1++#" #INC ":circ(M0))\n\t" \
71 : "=r"(RES), "+r"(ADDR) \
72 : "r"(START), "r"(LEN) \
73 : "r4", "m0", "cs0")
74#define CIRC_LOAD_IMM_b(RES, ADDR, START, LEN, INC) \
75 CIRC_LOAD_IMM(b, RES, ADDR, START, LEN, INC)
76#define CIRC_LOAD_IMM_ub(RES, ADDR, START, LEN, INC) \
77 CIRC_LOAD_IMM(ub, RES, ADDR, START, LEN, INC)
78#define CIRC_LOAD_IMM_h(RES, ADDR, START, LEN, INC) \
79 CIRC_LOAD_IMM(h, RES, ADDR, START, LEN, INC)
80#define CIRC_LOAD_IMM_uh(RES, ADDR, START, LEN, INC) \
81 CIRC_LOAD_IMM(uh, RES, ADDR, START, LEN, INC)
82#define CIRC_LOAD_IMM_w(RES, ADDR, START, LEN, INC) \
83 CIRC_LOAD_IMM(w, RES, ADDR, START, LEN, INC)
84#define CIRC_LOAD_IMM_d(RES, ADDR, START, LEN, INC) \
85 CIRC_LOAD_IMM(d, RES, ADDR, START, LEN, INC)
86
87
88
89
90
91
92
93
94static int build_mreg(int inc, int K, int len)
95{
96 return ((inc & 0x780) << 21) |
97 ((K & 0xf) << 24) |
98 ((inc & 0x7f) << 17) |
99 (len & 0x1ffff);
100}
101
102#define CIRC_LOAD_REG(SIZE, RES, ADDR, START, LEN, INC) \
103 __asm__( \
104 "r4 = %2\n\t" \
105 "m1 = r4\n\t" \
106 "cs1 = %3\n\t" \
107 "%0 = mem" #SIZE "(%1++I:circ(M1))\n\t" \
108 : "=r"(RES), "+r"(ADDR) \
109 : "r"(build_mreg((INC), 0, (LEN))), \
110 "r"(START) \
111 : "r4", "m1", "cs1")
112#define CIRC_LOAD_REG_b(RES, ADDR, START, LEN, INC) \
113 CIRC_LOAD_REG(b, RES, ADDR, START, LEN, INC)
114#define CIRC_LOAD_REG_ub(RES, ADDR, START, LEN, INC) \
115 CIRC_LOAD_REG(ub, RES, ADDR, START, LEN, INC)
116#define CIRC_LOAD_REG_h(RES, ADDR, START, LEN, INC) \
117 CIRC_LOAD_REG(h, RES, ADDR, START, LEN, INC)
118#define CIRC_LOAD_REG_uh(RES, ADDR, START, LEN, INC) \
119 CIRC_LOAD_REG(uh, RES, ADDR, START, LEN, INC)
120#define CIRC_LOAD_REG_w(RES, ADDR, START, LEN, INC) \
121 CIRC_LOAD_REG(w, RES, ADDR, START, LEN, INC)
122#define CIRC_LOAD_REG_d(RES, ADDR, START, LEN, INC) \
123 CIRC_LOAD_REG(d, RES, ADDR, START, LEN, INC)
124
125
126
127
128
129
130
131
132
133#define CIRC_STORE_IMM(SIZE, PART, VAL, ADDR, START, LEN, INC) \
134 __asm__( \
135 "r4 = %3\n\t" \
136 "m0 = r4\n\t" \
137 "cs0 = %1\n\t" \
138 "mem" #SIZE "(%0++#" #INC ":circ(M0)) = %2" PART "\n\t" \
139 : "+r"(ADDR) \
140 : "r"(START), "r"(VAL), "r"(LEN) \
141 : "r4", "m0", "cs0", "memory")
142#define CIRC_STORE_IMM_b(VAL, ADDR, START, LEN, INC) \
143 CIRC_STORE_IMM(b, "", VAL, ADDR, START, LEN, INC)
144#define CIRC_STORE_IMM_h(VAL, ADDR, START, LEN, INC) \
145 CIRC_STORE_IMM(h, "", VAL, ADDR, START, LEN, INC)
146#define CIRC_STORE_IMM_f(VAL, ADDR, START, LEN, INC) \
147 CIRC_STORE_IMM(h, ".H", VAL, ADDR, START, LEN, INC)
148#define CIRC_STORE_IMM_w(VAL, ADDR, START, LEN, INC) \
149 CIRC_STORE_IMM(w, "", VAL, ADDR, START, LEN, INC)
150#define CIRC_STORE_IMM_d(VAL, ADDR, START, LEN, INC) \
151 CIRC_STORE_IMM(d, "", VAL, ADDR, START, LEN, INC)
152
153#define CIRC_STORE_NEW_IMM(SIZE, VAL, ADDR, START, LEN, INC) \
154 __asm__( \
155 "r4 = %3\n\t" \
156 "m0 = r4\n\t" \
157 "cs0 = %1\n\t" \
158 "{\n\t" \
159 " r5 = %2\n\t" \
160 " mem" #SIZE "(%0++#" #INC ":circ(M0)) = r5.new\n\t" \
161 "}\n\t" \
162 : "+r"(ADDR) \
163 : "r"(START), "r"(VAL), "r"(LEN) \
164 : "r4", "r5", "m0", "cs0", "memory")
165#define CIRC_STORE_IMM_bnew(VAL, ADDR, START, LEN, INC) \
166 CIRC_STORE_NEW_IMM(b, VAL, ADDR, START, LEN, INC)
167#define CIRC_STORE_IMM_hnew(VAL, ADDR, START, LEN, INC) \
168 CIRC_STORE_NEW_IMM(h, VAL, ADDR, START, LEN, INC)
169#define CIRC_STORE_IMM_wnew(VAL, ADDR, START, LEN, INC) \
170 CIRC_STORE_NEW_IMM(w, VAL, ADDR, START, LEN, INC)
171
172#define CIRC_STORE_REG(SIZE, PART, VAL, ADDR, START, LEN, INC) \
173 __asm__( \
174 "r4 = %1\n\t" \
175 "m1 = r4\n\t" \
176 "cs1 = %2\n\t" \
177 "mem" #SIZE "(%0++I:circ(M1)) = %3" PART "\n\t" \
178 : "+r"(ADDR) \
179 : "r"(build_mreg((INC), 0, (LEN))), \
180 "r"(START), \
181 "r"(VAL) \
182 : "r4", "m1", "cs1", "memory")
183#define CIRC_STORE_REG_b(VAL, ADDR, START, LEN, INC) \
184 CIRC_STORE_REG(b, "", VAL, ADDR, START, LEN, INC)
185#define CIRC_STORE_REG_h(VAL, ADDR, START, LEN, INC) \
186 CIRC_STORE_REG(h, "", VAL, ADDR, START, LEN, INC)
187#define CIRC_STORE_REG_f(VAL, ADDR, START, LEN, INC) \
188 CIRC_STORE_REG(h, ".H", VAL, ADDR, START, LEN, INC)
189#define CIRC_STORE_REG_w(VAL, ADDR, START, LEN, INC) \
190 CIRC_STORE_REG(w, "", VAL, ADDR, START, LEN, INC)
191#define CIRC_STORE_REG_d(VAL, ADDR, START, LEN, INC) \
192 CIRC_STORE_REG(d, "", VAL, ADDR, START, LEN, INC)
193
194#define CIRC_STORE_NEW_REG(SIZE, VAL, ADDR, START, LEN, INC) \
195 __asm__( \
196 "r4 = %1\n\t" \
197 "m1 = r4\n\t" \
198 "cs1 = %2\n\t" \
199 "{\n\t" \
200 " r5 = %3\n\t" \
201 " mem" #SIZE "(%0++I:circ(M1)) = r5.new\n\t" \
202 "}\n\t" \
203 : "+r"(ADDR) \
204 : "r"(build_mreg((INC), 0, (LEN))), \
205 "r"(START), \
206 "r"(VAL) \
207 : "r4", "r5", "m1", "cs1", "memory")
208#define CIRC_STORE_REG_bnew(VAL, ADDR, START, LEN, INC) \
209 CIRC_STORE_NEW_REG(b, VAL, ADDR, START, LEN, INC)
210#define CIRC_STORE_REG_hnew(VAL, ADDR, START, LEN, INC) \
211 CIRC_STORE_NEW_REG(h, VAL, ADDR, START, LEN, INC)
212#define CIRC_STORE_REG_wnew(VAL, ADDR, START, LEN, INC) \
213 CIRC_STORE_NEW_REG(w, VAL, ADDR, START, LEN, INC)
214
215
216int err;
217
218
219void check_load(int i, long long result, int inc, int size)
220{
221 int expect = (i * inc);
222 while (expect >= size) {
223 expect -= size;
224 }
225 while (expect < 0) {
226 expect += size;
227 }
228 if (result != expect) {
229 printf("ERROR(%d): %lld != %d\n", i, result, expect);
230 err++;
231 }
232}
233
234#define TEST_LOAD_IMM(SZ, TYPE, BUF, BUFSIZE, INC, FMT) \
235void circ_test_load_imm_##SZ(void) \
236{ \
237 TYPE *p = (TYPE *)BUF; \
238 int size = 10; \
239 int i; \
240 for (i = 0; i < BUFSIZE; i++) { \
241 TYPE element; \
242 CIRC_LOAD_IMM_##SZ(element, p, BUF, size * sizeof(TYPE), (INC)); \
243 DEBUG_PRINTF("i = %2d, p = 0x%p, element = %2" #FMT "\n", \
244 i, p, element); \
245 check_load(i, element, ((INC) / (int)sizeof(TYPE)), size); \
246 } \
247 p = (TYPE *)BUF; \
248 for (i = 0; i < BUFSIZE; i++) { \
249 TYPE element; \
250 CIRC_LOAD_IMM_##SZ(element, p, BUF, size * sizeof(TYPE), -(INC)); \
251 DEBUG_PRINTF("i = %2d, p = 0x%p, element = %2" #FMT "\n", \
252 i, p, element); \
253 check_load(i, element, (-(INC) / (int)sizeof(TYPE)), size); \
254 } \
255}
256
257TEST_LOAD_IMM(b, char, bbuf, NBYTES, 1, d)
258TEST_LOAD_IMM(ub, unsigned char, bbuf, NBYTES, 1, d)
259TEST_LOAD_IMM(h, short, hbuf, NHALFS, 2, d)
260TEST_LOAD_IMM(uh, unsigned short, hbuf, NHALFS, 2, d)
261TEST_LOAD_IMM(w, int, wbuf, NWORDS, 4, d)
262TEST_LOAD_IMM(d, long long, dbuf, NDOBLS, 8, lld)
263
264#define TEST_LOAD_REG(SZ, TYPE, BUF, BUFSIZE, FMT) \
265void circ_test_load_reg_##SZ(void) \
266{ \
267 TYPE *p = (TYPE *)BUF; \
268 int size = 13; \
269 int i; \
270 for (i = 0; i < BUFSIZE; i++) { \
271 TYPE element; \
272 CIRC_LOAD_REG_##SZ(element, p, BUF, size * sizeof(TYPE), 1); \
273 DEBUG_PRINTF("i = %2d, p = 0x%p, element = %2" #FMT "\n", \
274 i, p, element); \
275 check_load(i, element, 1, size); \
276 } \
277 p = (TYPE *)BUF; \
278 for (i = 0; i < BUFSIZE; i++) { \
279 TYPE element; \
280 CIRC_LOAD_REG_##SZ(element, p, BUF, size * sizeof(TYPE), -1); \
281 DEBUG_PRINTF("i = %2d, p = 0x%p, element = %2" #FMT "\n", \
282 i, p, element); \
283 check_load(i, element, -1, size); \
284 } \
285}
286
287TEST_LOAD_REG(b, char, bbuf, NBYTES, d)
288TEST_LOAD_REG(ub, unsigned char, bbuf, NBYTES, d)
289TEST_LOAD_REG(h, short, hbuf, NHALFS, d)
290TEST_LOAD_REG(uh, unsigned short, hbuf, NHALFS, d)
291TEST_LOAD_REG(w, int, wbuf, NWORDS, d)
292TEST_LOAD_REG(d, long long, dbuf, NDOBLS, lld)
293
294
295#define CIRC_VAL(SZ, TYPE, BUFSIZE) \
296TYPE circ_val_##SZ(int i, int inc, int size) \
297{ \
298 int mod = BUFSIZE % size; \
299 int elem = i * inc; \
300 if (elem < 0) { \
301 if (-elem <= size - mod) { \
302 return (elem + BUFSIZE - mod); \
303 } else { \
304 return (elem + BUFSIZE + size - mod); \
305 } \
306 } else if (elem < mod) {\
307 return (elem + BUFSIZE - mod); \
308 } else { \
309 return (elem + BUFSIZE - size - mod); \
310 } \
311}
312
313CIRC_VAL(b, unsigned char, NBYTES)
314CIRC_VAL(h, short, NHALFS)
315CIRC_VAL(w, int, NWORDS)
316CIRC_VAL(d, long long, NDOBLS)
317
318
319
320
321
322#define CHECK_STORE(SZ, BUF, BUFSIZE, FMT) \
323void check_store_##SZ(int inc, int size) \
324{ \
325 int i; \
326 for (i = 0; i < size; i++) { \
327 DEBUG_PRINTF(#BUF "[%3d] = 0x%02" #FMT ", guess = 0x%02" #FMT "\n", \
328 i, BUF[i], circ_val_##SZ(i, inc, size)); \
329 if (BUF[i] != circ_val_##SZ(i, inc, size)) { \
330 printf("ERROR(%3d): 0x%02" #FMT " != 0x%02" #FMT "\n", \
331 i, BUF[i], circ_val_##SZ(i, inc, size)); \
332 err++; \
333 } \
334 } \
335 for (i = size; i < BUFSIZE; i++) { \
336 if (BUF[i] != i) { \
337 printf("ERROR(%3d): 0x%02" #FMT " != 0x%02x\n", i, BUF[i], i); \
338 err++; \
339 } \
340 } \
341}
342
343CHECK_STORE(b, bbuf, NBYTES, x)
344CHECK_STORE(h, hbuf, NHALFS, x)
345CHECK_STORE(w, wbuf, NWORDS, x)
346CHECK_STORE(d, dbuf, NDOBLS, llx)
347
348#define CIRC_TEST_STORE_IMM(SZ, CHK, TYPE, BUF, BUFSIZE, SHIFT, INC) \
349void circ_test_store_imm_##SZ(void) \
350{ \
351 unsigned int size = 27; \
352 TYPE *p = BUF; \
353 TYPE val = 0; \
354 int i; \
355 init_##BUF(); \
356 for (i = 0; i < BUFSIZE; i++) { \
357 CIRC_STORE_IMM_##SZ(val << SHIFT, p, BUF, size * sizeof(TYPE), INC); \
358 val++; \
359 } \
360 check_store_##CHK(((INC) / (int)sizeof(TYPE)), size); \
361 p = BUF; \
362 val = 0; \
363 init_##BUF(); \
364 for (i = 0; i < BUFSIZE; i++) { \
365 CIRC_STORE_IMM_##SZ(val << SHIFT, p, BUF, size * sizeof(TYPE), \
366 -(INC)); \
367 val++; \
368 } \
369 check_store_##CHK((-(INC) / (int)sizeof(TYPE)), size); \
370}
371
372CIRC_TEST_STORE_IMM(b, b, unsigned char, bbuf, NBYTES, 0, 1)
373CIRC_TEST_STORE_IMM(h, h, short, hbuf, NHALFS, 0, 2)
374CIRC_TEST_STORE_IMM(f, h, short, hbuf, NHALFS, 16, 2)
375CIRC_TEST_STORE_IMM(w, w, int, wbuf, NWORDS, 0, 4)
376CIRC_TEST_STORE_IMM(d, d, long long, dbuf, NDOBLS, 0, 8)
377CIRC_TEST_STORE_IMM(bnew, b, unsigned char, bbuf, NBYTES, 0, 1)
378CIRC_TEST_STORE_IMM(hnew, h, short, hbuf, NHALFS, 0, 2)
379CIRC_TEST_STORE_IMM(wnew, w, int, wbuf, NWORDS, 0, 4)
380
381#define CIRC_TEST_STORE_REG(SZ, CHK, TYPE, BUF, BUFSIZE, SHIFT) \
382void circ_test_store_reg_##SZ(void) \
383{ \
384 TYPE *p = BUF; \
385 unsigned int size = 19; \
386 TYPE val = 0; \
387 int i; \
388 init_##BUF(); \
389 for (i = 0; i < BUFSIZE; i++) { \
390 CIRC_STORE_REG_##SZ(val << SHIFT, p, BUF, size * sizeof(TYPE), 1); \
391 val++; \
392 } \
393 check_store_##CHK(1, size); \
394 p = BUF; \
395 val = 0; \
396 init_##BUF(); \
397 for (i = 0; i < BUFSIZE; i++) { \
398 CIRC_STORE_REG_##SZ(val << SHIFT, p, BUF, size * sizeof(TYPE), -1); \
399 val++; \
400 } \
401 check_store_##CHK(-1, size); \
402}
403
404CIRC_TEST_STORE_REG(b, b, unsigned char, bbuf, NBYTES, 0)
405CIRC_TEST_STORE_REG(h, h, short, hbuf, NHALFS, 0)
406CIRC_TEST_STORE_REG(f, h, short, hbuf, NHALFS, 16)
407CIRC_TEST_STORE_REG(w, w, int, wbuf, NWORDS, 0)
408CIRC_TEST_STORE_REG(d, d, long long, dbuf, NDOBLS, 0)
409CIRC_TEST_STORE_REG(bnew, b, unsigned char, bbuf, NBYTES, 0)
410CIRC_TEST_STORE_REG(hnew, h, short, hbuf, NHALFS, 0)
411CIRC_TEST_STORE_REG(wnew, w, int, wbuf, NWORDS, 0)
412
413
414static void circ_test_v3(void)
415{
416 int *p = wbuf;
417 int size = 15;
418 int K = 4;
419 int element;
420 int i;
421
422 init_wbuf();
423
424 for (i = 0; i < NWORDS; i++) {
425 __asm__(
426 "r4 = %2\n\t"
427 "m1 = r4\n\t"
428 "%0 = memw(%1++I:circ(M1))\n\t"
429 : "=r"(element), "+r"(p)
430 : "r"(build_mreg(1, K, size * sizeof(int)))
431 : "r4", "m1");
432 DEBUG_PRINTF("i = %2d, p = 0x%p, element = %2d\n", i, p, element);
433 check_load(i, element, 1, size);
434 }
435}
436
437int main()
438{
439 init_bbuf();
440 init_hbuf();
441 init_wbuf();
442 init_dbuf();
443
444 DEBUG_PRINTF("NBYTES = %d\n", NBYTES);
445 DEBUG_PRINTF("Address of dbuf = 0x%p\n", dbuf);
446 DEBUG_PRINTF("Address of wbuf = 0x%p\n", wbuf);
447 DEBUG_PRINTF("Address of hbuf = 0x%p\n", hbuf);
448 DEBUG_PRINTF("Address of bbuf = 0x%p\n", bbuf);
449
450 circ_test_load_imm_b();
451 circ_test_load_imm_ub();
452 circ_test_load_imm_h();
453 circ_test_load_imm_uh();
454 circ_test_load_imm_w();
455 circ_test_load_imm_d();
456
457 circ_test_load_reg_b();
458 circ_test_load_reg_ub();
459 circ_test_load_reg_h();
460 circ_test_load_reg_uh();
461 circ_test_load_reg_w();
462 circ_test_load_reg_d();
463
464 circ_test_store_imm_b();
465 circ_test_store_imm_h();
466 circ_test_store_imm_f();
467 circ_test_store_imm_w();
468 circ_test_store_imm_d();
469 circ_test_store_imm_bnew();
470 circ_test_store_imm_hnew();
471 circ_test_store_imm_wnew();
472
473 circ_test_store_reg_b();
474 circ_test_store_reg_h();
475 circ_test_store_reg_f();
476 circ_test_store_reg_w();
477 circ_test_store_reg_d();
478 circ_test_store_reg_bnew();
479 circ_test_store_reg_hnew();
480 circ_test_store_reg_wnew();
481
482 circ_test_v3();
483
484 puts(err ? "FAIL" : "PASS");
485 return err ? 1 : 0;
486}
487