xref: /openbmc/qemu/tests/tcg/hexagon/circ.c (revision 58ff2981667262f77d57219fc9cef2a43a740159)
146ef47e2STaylor Simpson /*
2*58ff2981SMichael Lambert  *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
346ef47e2STaylor Simpson  *
446ef47e2STaylor Simpson  *  This program is free software; you can redistribute it and/or modify
546ef47e2STaylor Simpson  *  it under the terms of the GNU General Public License as published by
646ef47e2STaylor Simpson  *  the Free Software Foundation; either version 2 of the License, or
746ef47e2STaylor Simpson  *  (at your option) any later version.
846ef47e2STaylor Simpson  *
946ef47e2STaylor Simpson  *  This program is distributed in the hope that it will be useful,
1046ef47e2STaylor Simpson  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1146ef47e2STaylor Simpson  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1246ef47e2STaylor Simpson  *  GNU General Public License for more details.
1346ef47e2STaylor Simpson  *
1446ef47e2STaylor Simpson  *  You should have received a copy of the GNU General Public License
1546ef47e2STaylor Simpson  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
1646ef47e2STaylor Simpson  */
1746ef47e2STaylor Simpson 
1846ef47e2STaylor Simpson #include <stdio.h>
1946ef47e2STaylor Simpson 
2046ef47e2STaylor Simpson #define DEBUG          0
2146ef47e2STaylor Simpson #define DEBUG_PRINTF(...) \
2246ef47e2STaylor Simpson     do { \
2346ef47e2STaylor Simpson         if (DEBUG) { \
2446ef47e2STaylor Simpson             printf(__VA_ARGS__); \
2546ef47e2STaylor Simpson         } \
2646ef47e2STaylor Simpson     } while (0)
2746ef47e2STaylor Simpson 
2846ef47e2STaylor Simpson 
2946ef47e2STaylor Simpson #define NBYTES         (1 << 8)
3046ef47e2STaylor Simpson #define NHALFS         (NBYTES / sizeof(short))
3146ef47e2STaylor Simpson #define NWORDS         (NBYTES / sizeof(int))
3246ef47e2STaylor Simpson #define NDOBLS         (NBYTES / sizeof(long long))
3346ef47e2STaylor Simpson 
3446ef47e2STaylor Simpson long long     dbuf[NDOBLS] __attribute__((aligned(1 << 12))) = {0};
3546ef47e2STaylor Simpson int           wbuf[NWORDS] __attribute__((aligned(1 << 12))) = {0};
3646ef47e2STaylor Simpson short         hbuf[NHALFS] __attribute__((aligned(1 << 12))) = {0};
3746ef47e2STaylor Simpson unsigned char bbuf[NBYTES] __attribute__((aligned(1 << 12))) = {0};
3846ef47e2STaylor Simpson 
3946ef47e2STaylor Simpson /*
4046ef47e2STaylor Simpson  * We use the C preporcessor to deal with the combinations of types
4146ef47e2STaylor Simpson  */
4246ef47e2STaylor Simpson 
4346ef47e2STaylor Simpson #define INIT(BUF, N) \
4446ef47e2STaylor Simpson     void init_##BUF(void) \
4546ef47e2STaylor Simpson     { \
4646ef47e2STaylor Simpson         int i; \
4746ef47e2STaylor Simpson         for (i = 0; i < N; i++) { \
4846ef47e2STaylor Simpson             BUF[i] = i; \
4946ef47e2STaylor Simpson         } \
5046ef47e2STaylor Simpson     } \
5146ef47e2STaylor Simpson 
5246ef47e2STaylor Simpson INIT(bbuf, NBYTES)
5346ef47e2STaylor Simpson INIT(hbuf, NHALFS)
5446ef47e2STaylor Simpson INIT(wbuf, NWORDS)
5546ef47e2STaylor Simpson INIT(dbuf, NDOBLS)
5646ef47e2STaylor Simpson 
5746ef47e2STaylor Simpson /*
5846ef47e2STaylor Simpson  * Macros for performing circular load
5946ef47e2STaylor Simpson  *     RES         result
6046ef47e2STaylor Simpson  *     ADDR        address
6146ef47e2STaylor Simpson  *     START       start address of buffer
6246ef47e2STaylor Simpson  *     LEN         length of buffer (in bytes)
6346ef47e2STaylor Simpson  *     INC         address increment (in bytes for IMM, elements for REG)
6446ef47e2STaylor Simpson  */
6546ef47e2STaylor Simpson #define CIRC_LOAD_IMM(SIZE, RES, ADDR, START, LEN, INC) \
6646ef47e2STaylor Simpson     __asm__( \
6746ef47e2STaylor Simpson         "r4 = %3\n\t" \
6846ef47e2STaylor Simpson         "m0 = r4\n\t" \
6946ef47e2STaylor Simpson         "cs0 = %2\n\t" \
7046ef47e2STaylor Simpson         "%0 = mem" #SIZE "(%1++#" #INC ":circ(M0))\n\t" \
7146ef47e2STaylor Simpson         : "=r"(RES), "+r"(ADDR) \
7246ef47e2STaylor Simpson         : "r"(START), "r"(LEN) \
7346ef47e2STaylor Simpson         : "r4", "m0", "cs0")
7446ef47e2STaylor Simpson #define CIRC_LOAD_IMM_b(RES, ADDR, START, LEN, INC) \
7546ef47e2STaylor Simpson     CIRC_LOAD_IMM(b, RES, ADDR, START, LEN, INC)
7646ef47e2STaylor Simpson #define CIRC_LOAD_IMM_ub(RES, ADDR, START, LEN, INC) \
7746ef47e2STaylor Simpson     CIRC_LOAD_IMM(ub, RES, ADDR, START, LEN, INC)
7846ef47e2STaylor Simpson #define CIRC_LOAD_IMM_h(RES, ADDR, START, LEN, INC) \
7946ef47e2STaylor Simpson     CIRC_LOAD_IMM(h, RES, ADDR, START, LEN, INC)
8046ef47e2STaylor Simpson #define CIRC_LOAD_IMM_uh(RES, ADDR, START, LEN, INC) \
8146ef47e2STaylor Simpson     CIRC_LOAD_IMM(uh, RES, ADDR, START, LEN, INC)
8246ef47e2STaylor Simpson #define CIRC_LOAD_IMM_w(RES, ADDR, START, LEN, INC) \
8346ef47e2STaylor Simpson     CIRC_LOAD_IMM(w, RES, ADDR, START, LEN, INC)
8446ef47e2STaylor Simpson #define CIRC_LOAD_IMM_d(RES, ADDR, START, LEN, INC) \
8546ef47e2STaylor Simpson     CIRC_LOAD_IMM(d, RES, ADDR, START, LEN, INC)
8646ef47e2STaylor Simpson 
8746ef47e2STaylor Simpson /*
8846ef47e2STaylor Simpson  * The mreg has the following pieces
8946ef47e2STaylor Simpson  *     mreg[31:28]              increment[10:7]
9046ef47e2STaylor Simpson  *     mreg[27:24]              K value (used Hexagon v3 and earlier)
9146ef47e2STaylor Simpson  *     mreg[23:17]              increment[6:0]
9246ef47e2STaylor Simpson  *     mreg[16:0]               circular buffer length
9346ef47e2STaylor Simpson  */
9446ef47e2STaylor Simpson static int build_mreg(int inc, int K, int len)
9546ef47e2STaylor Simpson {
9646ef47e2STaylor Simpson     return ((inc & 0x780) << 21) |
9746ef47e2STaylor Simpson            ((K & 0xf) << 24) |
9846ef47e2STaylor Simpson            ((inc & 0x7f) << 17) |
9946ef47e2STaylor Simpson            (len & 0x1ffff);
10046ef47e2STaylor Simpson }
10146ef47e2STaylor Simpson 
10246ef47e2STaylor Simpson #define CIRC_LOAD_REG(SIZE, RES, ADDR, START, LEN, INC) \
10346ef47e2STaylor Simpson     __asm__( \
10446ef47e2STaylor Simpson         "r4 = %2\n\t" \
10546ef47e2STaylor Simpson         "m1 = r4\n\t" \
10646ef47e2STaylor Simpson         "cs1 = %3\n\t" \
10746ef47e2STaylor Simpson         "%0 = mem" #SIZE "(%1++I:circ(M1))\n\t" \
10846ef47e2STaylor Simpson         : "=r"(RES), "+r"(ADDR) \
10946ef47e2STaylor Simpson         : "r"(build_mreg((INC), 0, (LEN))), \
11046ef47e2STaylor Simpson           "r"(START) \
11146ef47e2STaylor Simpson         : "r4", "m1", "cs1")
11246ef47e2STaylor Simpson #define CIRC_LOAD_REG_b(RES, ADDR, START, LEN, INC) \
11346ef47e2STaylor Simpson     CIRC_LOAD_REG(b, RES, ADDR, START, LEN, INC)
11446ef47e2STaylor Simpson #define CIRC_LOAD_REG_ub(RES, ADDR, START, LEN, INC) \
11546ef47e2STaylor Simpson     CIRC_LOAD_REG(ub, RES, ADDR, START, LEN, INC)
11646ef47e2STaylor Simpson #define CIRC_LOAD_REG_h(RES, ADDR, START, LEN, INC) \
11746ef47e2STaylor Simpson     CIRC_LOAD_REG(h, RES, ADDR, START, LEN, INC)
11846ef47e2STaylor Simpson #define CIRC_LOAD_REG_uh(RES, ADDR, START, LEN, INC) \
11946ef47e2STaylor Simpson     CIRC_LOAD_REG(uh, RES, ADDR, START, LEN, INC)
12046ef47e2STaylor Simpson #define CIRC_LOAD_REG_w(RES, ADDR, START, LEN, INC) \
12146ef47e2STaylor Simpson     CIRC_LOAD_REG(w, RES, ADDR, START, LEN, INC)
12246ef47e2STaylor Simpson #define CIRC_LOAD_REG_d(RES, ADDR, START, LEN, INC) \
12346ef47e2STaylor Simpson     CIRC_LOAD_REG(d, RES, ADDR, START, LEN, INC)
12446ef47e2STaylor Simpson 
12546ef47e2STaylor Simpson /*
12646ef47e2STaylor Simpson  * Macros for performing circular store
12746ef47e2STaylor Simpson  *     VAL         value to store
12846ef47e2STaylor Simpson  *     ADDR        address
12946ef47e2STaylor Simpson  *     START       start address of buffer
13046ef47e2STaylor Simpson  *     LEN         length of buffer (in bytes)
13146ef47e2STaylor Simpson  *     INC         address increment (in bytes for IMM, elements for REG)
13246ef47e2STaylor Simpson  */
13346ef47e2STaylor Simpson #define CIRC_STORE_IMM(SIZE, PART, VAL, ADDR, START, LEN, INC) \
13446ef47e2STaylor Simpson     __asm__( \
13546ef47e2STaylor Simpson         "r4 = %3\n\t" \
13646ef47e2STaylor Simpson         "m0 = r4\n\t" \
13746ef47e2STaylor Simpson         "cs0 = %1\n\t" \
13846ef47e2STaylor Simpson         "mem" #SIZE "(%0++#" #INC ":circ(M0)) = %2" PART "\n\t" \
13946ef47e2STaylor Simpson         : "+r"(ADDR) \
14046ef47e2STaylor Simpson         : "r"(START), "r"(VAL), "r"(LEN) \
14146ef47e2STaylor Simpson         : "r4", "m0", "cs0", "memory")
14246ef47e2STaylor Simpson #define CIRC_STORE_IMM_b(VAL, ADDR, START, LEN, INC) \
14346ef47e2STaylor Simpson     CIRC_STORE_IMM(b, "", VAL, ADDR, START, LEN, INC)
14446ef47e2STaylor Simpson #define CIRC_STORE_IMM_h(VAL, ADDR, START, LEN, INC) \
14546ef47e2STaylor Simpson     CIRC_STORE_IMM(h, "", VAL, ADDR, START, LEN, INC)
14646ef47e2STaylor Simpson #define CIRC_STORE_IMM_f(VAL, ADDR, START, LEN, INC) \
14746ef47e2STaylor Simpson     CIRC_STORE_IMM(h, ".H", VAL, ADDR, START, LEN, INC)
14846ef47e2STaylor Simpson #define CIRC_STORE_IMM_w(VAL, ADDR, START, LEN, INC) \
14946ef47e2STaylor Simpson     CIRC_STORE_IMM(w, "", VAL, ADDR, START, LEN, INC)
15046ef47e2STaylor Simpson #define CIRC_STORE_IMM_d(VAL, ADDR, START, LEN, INC) \
15146ef47e2STaylor Simpson     CIRC_STORE_IMM(d, "", VAL, ADDR, START, LEN, INC)
15246ef47e2STaylor Simpson 
15346ef47e2STaylor Simpson #define CIRC_STORE_NEW_IMM(SIZE, VAL, ADDR, START, LEN, INC) \
15446ef47e2STaylor Simpson     __asm__( \
15546ef47e2STaylor Simpson         "r4 = %3\n\t" \
15646ef47e2STaylor Simpson         "m0 = r4\n\t" \
15746ef47e2STaylor Simpson         "cs0 = %1\n\t" \
15846ef47e2STaylor Simpson         "{\n\t" \
15946ef47e2STaylor Simpson         "    r5 = %2\n\t" \
16046ef47e2STaylor Simpson         "    mem" #SIZE "(%0++#" #INC ":circ(M0)) = r5.new\n\t" \
16146ef47e2STaylor Simpson         "}\n\t" \
16246ef47e2STaylor Simpson         : "+r"(ADDR) \
16346ef47e2STaylor Simpson         : "r"(START), "r"(VAL), "r"(LEN) \
16446ef47e2STaylor Simpson         : "r4", "r5", "m0", "cs0", "memory")
16546ef47e2STaylor Simpson #define CIRC_STORE_IMM_bnew(VAL, ADDR, START, LEN, INC) \
16646ef47e2STaylor Simpson     CIRC_STORE_NEW_IMM(b, VAL, ADDR, START, LEN, INC)
16746ef47e2STaylor Simpson #define CIRC_STORE_IMM_hnew(VAL, ADDR, START, LEN, INC) \
16846ef47e2STaylor Simpson     CIRC_STORE_NEW_IMM(h, VAL, ADDR, START, LEN, INC)
16946ef47e2STaylor Simpson #define CIRC_STORE_IMM_wnew(VAL, ADDR, START, LEN, INC) \
17046ef47e2STaylor Simpson     CIRC_STORE_NEW_IMM(w, VAL, ADDR, START, LEN, INC)
17146ef47e2STaylor Simpson 
17246ef47e2STaylor Simpson #define CIRC_STORE_REG(SIZE, PART, VAL, ADDR, START, LEN, INC) \
17346ef47e2STaylor Simpson     __asm__( \
17446ef47e2STaylor Simpson         "r4 = %1\n\t" \
17546ef47e2STaylor Simpson         "m1 = r4\n\t" \
17646ef47e2STaylor Simpson         "cs1 = %2\n\t" \
17746ef47e2STaylor Simpson         "mem" #SIZE "(%0++I:circ(M1)) = %3" PART "\n\t" \
17846ef47e2STaylor Simpson         : "+r"(ADDR) \
17946ef47e2STaylor Simpson         : "r"(build_mreg((INC), 0, (LEN))), \
18046ef47e2STaylor Simpson           "r"(START), \
18146ef47e2STaylor Simpson           "r"(VAL) \
18246ef47e2STaylor Simpson         : "r4", "m1", "cs1", "memory")
18346ef47e2STaylor Simpson #define CIRC_STORE_REG_b(VAL, ADDR, START, LEN, INC) \
18446ef47e2STaylor Simpson     CIRC_STORE_REG(b, "", VAL, ADDR, START, LEN, INC)
18546ef47e2STaylor Simpson #define CIRC_STORE_REG_h(VAL, ADDR, START, LEN, INC) \
18646ef47e2STaylor Simpson     CIRC_STORE_REG(h, "", VAL, ADDR, START, LEN, INC)
18746ef47e2STaylor Simpson #define CIRC_STORE_REG_f(VAL, ADDR, START, LEN, INC) \
18846ef47e2STaylor Simpson     CIRC_STORE_REG(h, ".H", VAL, ADDR, START, LEN, INC)
18946ef47e2STaylor Simpson #define CIRC_STORE_REG_w(VAL, ADDR, START, LEN, INC) \
19046ef47e2STaylor Simpson     CIRC_STORE_REG(w, "", VAL, ADDR, START, LEN, INC)
19146ef47e2STaylor Simpson #define CIRC_STORE_REG_d(VAL, ADDR, START, LEN, INC) \
19246ef47e2STaylor Simpson     CIRC_STORE_REG(d, "", VAL, ADDR, START, LEN, INC)
19346ef47e2STaylor Simpson 
19446ef47e2STaylor Simpson #define CIRC_STORE_NEW_REG(SIZE, VAL, ADDR, START, LEN, INC) \
19546ef47e2STaylor Simpson     __asm__( \
19646ef47e2STaylor Simpson         "r4 = %1\n\t" \
19746ef47e2STaylor Simpson         "m1 = r4\n\t" \
19846ef47e2STaylor Simpson         "cs1 = %2\n\t" \
19946ef47e2STaylor Simpson         "{\n\t" \
20046ef47e2STaylor Simpson         "    r5 = %3\n\t" \
20146ef47e2STaylor Simpson         "    mem" #SIZE "(%0++I:circ(M1)) = r5.new\n\t" \
20246ef47e2STaylor Simpson         "}\n\t" \
20346ef47e2STaylor Simpson         : "+r"(ADDR) \
20446ef47e2STaylor Simpson         : "r"(build_mreg((INC), 0, (LEN))), \
20546ef47e2STaylor Simpson           "r"(START), \
20646ef47e2STaylor Simpson           "r"(VAL) \
20746ef47e2STaylor Simpson         : "r4", "r5", "m1", "cs1", "memory")
20846ef47e2STaylor Simpson #define CIRC_STORE_REG_bnew(VAL, ADDR, START, LEN, INC) \
20946ef47e2STaylor Simpson     CIRC_STORE_NEW_REG(b, VAL, ADDR, START, LEN, INC)
21046ef47e2STaylor Simpson #define CIRC_STORE_REG_hnew(VAL, ADDR, START, LEN, INC) \
21146ef47e2STaylor Simpson     CIRC_STORE_NEW_REG(h, VAL, ADDR, START, LEN, INC)
21246ef47e2STaylor Simpson #define CIRC_STORE_REG_wnew(VAL, ADDR, START, LEN, INC) \
21346ef47e2STaylor Simpson     CIRC_STORE_NEW_REG(w, VAL, ADDR, START, LEN, INC)
21446ef47e2STaylor Simpson 
21546ef47e2STaylor Simpson 
21646ef47e2STaylor Simpson int err;
21746ef47e2STaylor Simpson 
21846ef47e2STaylor Simpson /* We'll test increments +1 and -1 */
21946ef47e2STaylor Simpson void check_load(int i, long long result, int inc, int size)
22046ef47e2STaylor Simpson {
22146ef47e2STaylor Simpson     int expect = (i * inc);
22246ef47e2STaylor Simpson     while (expect >= size) {
22346ef47e2STaylor Simpson         expect -= size;
22446ef47e2STaylor Simpson     }
22546ef47e2STaylor Simpson     while (expect < 0) {
22646ef47e2STaylor Simpson         expect += size;
22746ef47e2STaylor Simpson     }
22846ef47e2STaylor Simpson     if (result != expect) {
22946ef47e2STaylor Simpson         printf("ERROR(%d): %lld != %d\n", i, result, expect);
23046ef47e2STaylor Simpson         err++;
23146ef47e2STaylor Simpson     }
23246ef47e2STaylor Simpson }
23346ef47e2STaylor Simpson 
23446ef47e2STaylor Simpson #define TEST_LOAD_IMM(SZ, TYPE, BUF, BUFSIZE, INC, FMT) \
23546ef47e2STaylor Simpson void circ_test_load_imm_##SZ(void) \
23646ef47e2STaylor Simpson { \
23746ef47e2STaylor Simpson     TYPE *p = (TYPE *)BUF; \
23846ef47e2STaylor Simpson     int size = 10; \
23946ef47e2STaylor Simpson     int i; \
24046ef47e2STaylor Simpson     for (i = 0; i < BUFSIZE; i++) { \
24146ef47e2STaylor Simpson         TYPE element; \
24246ef47e2STaylor Simpson         CIRC_LOAD_IMM_##SZ(element, p, BUF, size * sizeof(TYPE), (INC)); \
24346ef47e2STaylor Simpson         DEBUG_PRINTF("i = %2d, p = 0x%p, element = %2" #FMT "\n", \
24446ef47e2STaylor Simpson                      i, p, element); \
24546ef47e2STaylor Simpson         check_load(i, element, ((INC) / (int)sizeof(TYPE)), size); \
24646ef47e2STaylor Simpson     } \
24746ef47e2STaylor Simpson     p = (TYPE *)BUF; \
24846ef47e2STaylor Simpson     for (i = 0; i < BUFSIZE; i++) { \
24946ef47e2STaylor Simpson         TYPE element; \
25046ef47e2STaylor Simpson         CIRC_LOAD_IMM_##SZ(element, p, BUF, size * sizeof(TYPE), -(INC)); \
25146ef47e2STaylor Simpson         DEBUG_PRINTF("i = %2d, p = 0x%p, element = %2" #FMT "\n", \
25246ef47e2STaylor Simpson                      i, p, element); \
25346ef47e2STaylor Simpson         check_load(i, element, (-(INC) / (int)sizeof(TYPE)), size); \
25446ef47e2STaylor Simpson     } \
25546ef47e2STaylor Simpson }
25646ef47e2STaylor Simpson 
25746ef47e2STaylor Simpson TEST_LOAD_IMM(b,  char,           bbuf, NBYTES, 1, d)
25846ef47e2STaylor Simpson TEST_LOAD_IMM(ub, unsigned char,  bbuf, NBYTES, 1, d)
25946ef47e2STaylor Simpson TEST_LOAD_IMM(h,  short,          hbuf, NHALFS, 2, d)
26046ef47e2STaylor Simpson TEST_LOAD_IMM(uh, unsigned short, hbuf, NHALFS, 2, d)
26146ef47e2STaylor Simpson TEST_LOAD_IMM(w,  int,            wbuf, NWORDS, 4, d)
26246ef47e2STaylor Simpson TEST_LOAD_IMM(d,  long long,      dbuf, NDOBLS, 8, lld)
26346ef47e2STaylor Simpson 
26446ef47e2STaylor Simpson #define TEST_LOAD_REG(SZ, TYPE, BUF, BUFSIZE, FMT) \
26546ef47e2STaylor Simpson void circ_test_load_reg_##SZ(void) \
26646ef47e2STaylor Simpson { \
26746ef47e2STaylor Simpson     TYPE *p = (TYPE *)BUF; \
26846ef47e2STaylor Simpson     int size = 13; \
26946ef47e2STaylor Simpson     int i; \
27046ef47e2STaylor Simpson     for (i = 0; i < BUFSIZE; i++) { \
27146ef47e2STaylor Simpson         TYPE element; \
27246ef47e2STaylor Simpson         CIRC_LOAD_REG_##SZ(element, p, BUF, size * sizeof(TYPE), 1); \
27346ef47e2STaylor Simpson         DEBUG_PRINTF("i = %2d, p = 0x%p, element = %2" #FMT "\n", \
27446ef47e2STaylor Simpson                      i, p, element); \
27546ef47e2STaylor Simpson         check_load(i, element, 1, size); \
27646ef47e2STaylor Simpson     } \
27746ef47e2STaylor Simpson     p = (TYPE *)BUF; \
27846ef47e2STaylor Simpson     for (i = 0; i < BUFSIZE; i++) { \
27946ef47e2STaylor Simpson         TYPE element; \
28046ef47e2STaylor Simpson         CIRC_LOAD_REG_##SZ(element, p, BUF, size * sizeof(TYPE), -1); \
28146ef47e2STaylor Simpson         DEBUG_PRINTF("i = %2d, p = 0x%p, element = %2" #FMT "\n", \
28246ef47e2STaylor Simpson                      i, p, element); \
28346ef47e2STaylor Simpson         check_load(i, element, -1, size); \
28446ef47e2STaylor Simpson     } \
28546ef47e2STaylor Simpson }
28646ef47e2STaylor Simpson 
28746ef47e2STaylor Simpson TEST_LOAD_REG(b,  char,           bbuf, NBYTES, d)
28846ef47e2STaylor Simpson TEST_LOAD_REG(ub, unsigned char,  bbuf, NBYTES, d)
28946ef47e2STaylor Simpson TEST_LOAD_REG(h,  short,          hbuf, NHALFS, d)
29046ef47e2STaylor Simpson TEST_LOAD_REG(uh, unsigned short, hbuf, NHALFS, d)
29146ef47e2STaylor Simpson TEST_LOAD_REG(w,  int,            wbuf, NWORDS, d)
29246ef47e2STaylor Simpson TEST_LOAD_REG(d,  long long,      dbuf, NDOBLS, lld)
29346ef47e2STaylor Simpson 
29446ef47e2STaylor Simpson /* The circular stores will wrap around somewhere inside the buffer */
29546ef47e2STaylor Simpson #define CIRC_VAL(SZ, TYPE, BUFSIZE) \
29646ef47e2STaylor Simpson TYPE circ_val_##SZ(int i, int inc, int size) \
29746ef47e2STaylor Simpson { \
29846ef47e2STaylor Simpson     int mod = BUFSIZE % size; \
29946ef47e2STaylor Simpson     int elem = i * inc; \
30046ef47e2STaylor Simpson     if (elem < 0) { \
30146ef47e2STaylor Simpson         if (-elem <= size - mod) { \
30246ef47e2STaylor Simpson             return (elem + BUFSIZE - mod); \
30346ef47e2STaylor Simpson         } else { \
30446ef47e2STaylor Simpson             return (elem + BUFSIZE + size - mod); \
30546ef47e2STaylor Simpson         } \
30646ef47e2STaylor Simpson     } else if (elem < mod) {\
30746ef47e2STaylor Simpson         return (elem + BUFSIZE - mod); \
30846ef47e2STaylor Simpson     } else { \
30946ef47e2STaylor Simpson         return (elem + BUFSIZE - size - mod); \
31046ef47e2STaylor Simpson     } \
31146ef47e2STaylor Simpson }
31246ef47e2STaylor Simpson 
31346ef47e2STaylor Simpson CIRC_VAL(b, unsigned char, NBYTES)
31446ef47e2STaylor Simpson CIRC_VAL(h, short,         NHALFS)
31546ef47e2STaylor Simpson CIRC_VAL(w, int,           NWORDS)
31646ef47e2STaylor Simpson CIRC_VAL(d, long long,     NDOBLS)
31746ef47e2STaylor Simpson 
31846ef47e2STaylor Simpson /*
31946ef47e2STaylor Simpson  * Circular stores should only write to the first "size" elements of the buffer
32046ef47e2STaylor Simpson  * the remainder of the elements should have BUF[i] == i
32146ef47e2STaylor Simpson  */
32246ef47e2STaylor Simpson #define CHECK_STORE(SZ, BUF, BUFSIZE, FMT) \
32346ef47e2STaylor Simpson void check_store_##SZ(int inc, int size) \
32446ef47e2STaylor Simpson { \
32546ef47e2STaylor Simpson     int i; \
32646ef47e2STaylor Simpson     for (i = 0; i < size; i++) { \
32746ef47e2STaylor Simpson         DEBUG_PRINTF(#BUF "[%3d] = 0x%02" #FMT ", guess = 0x%02" #FMT "\n", \
32846ef47e2STaylor Simpson                      i, BUF[i], circ_val_##SZ(i, inc, size)); \
32946ef47e2STaylor Simpson         if (BUF[i] != circ_val_##SZ(i, inc, size)) { \
33046ef47e2STaylor Simpson             printf("ERROR(%3d): 0x%02" #FMT " != 0x%02" #FMT "\n", \
33146ef47e2STaylor Simpson                    i, BUF[i], circ_val_##SZ(i, inc, size)); \
33246ef47e2STaylor Simpson             err++; \
33346ef47e2STaylor Simpson         } \
33446ef47e2STaylor Simpson     } \
33546ef47e2STaylor Simpson     for (i = size; i < BUFSIZE; i++) { \
33646ef47e2STaylor Simpson         if (BUF[i] != i) { \
33746ef47e2STaylor Simpson             printf("ERROR(%3d): 0x%02" #FMT " != 0x%02x\n", i, BUF[i], i); \
33846ef47e2STaylor Simpson             err++; \
33946ef47e2STaylor Simpson         } \
34046ef47e2STaylor Simpson     } \
34146ef47e2STaylor Simpson }
34246ef47e2STaylor Simpson 
34346ef47e2STaylor Simpson CHECK_STORE(b, bbuf, NBYTES, x)
34446ef47e2STaylor Simpson CHECK_STORE(h, hbuf, NHALFS, x)
34546ef47e2STaylor Simpson CHECK_STORE(w, wbuf, NWORDS, x)
34646ef47e2STaylor Simpson CHECK_STORE(d, dbuf, NDOBLS, llx)
34746ef47e2STaylor Simpson 
34846ef47e2STaylor Simpson #define CIRC_TEST_STORE_IMM(SZ, CHK, TYPE, BUF, BUFSIZE, SHIFT, INC) \
34946ef47e2STaylor Simpson void circ_test_store_imm_##SZ(void) \
35046ef47e2STaylor Simpson { \
35146ef47e2STaylor Simpson     unsigned int size = 27; \
35246ef47e2STaylor Simpson     TYPE *p = BUF; \
35346ef47e2STaylor Simpson     TYPE val = 0; \
35446ef47e2STaylor Simpson     int i; \
35546ef47e2STaylor Simpson     init_##BUF(); \
35646ef47e2STaylor Simpson     for (i = 0; i < BUFSIZE; i++) { \
35746ef47e2STaylor Simpson         CIRC_STORE_IMM_##SZ(val << SHIFT, p, BUF, size * sizeof(TYPE), INC); \
35846ef47e2STaylor Simpson         val++; \
35946ef47e2STaylor Simpson     } \
36046ef47e2STaylor Simpson     check_store_##CHK(((INC) / (int)sizeof(TYPE)), size); \
36146ef47e2STaylor Simpson     p = BUF; \
36246ef47e2STaylor Simpson     val = 0; \
36346ef47e2STaylor Simpson     init_##BUF(); \
36446ef47e2STaylor Simpson     for (i = 0; i < BUFSIZE; i++) { \
36546ef47e2STaylor Simpson         CIRC_STORE_IMM_##SZ(val << SHIFT, p, BUF, size * sizeof(TYPE), \
36646ef47e2STaylor Simpson                             -(INC)); \
36746ef47e2STaylor Simpson         val++; \
36846ef47e2STaylor Simpson     } \
36946ef47e2STaylor Simpson     check_store_##CHK((-(INC) / (int)sizeof(TYPE)), size); \
37046ef47e2STaylor Simpson }
37146ef47e2STaylor Simpson 
37246ef47e2STaylor Simpson CIRC_TEST_STORE_IMM(b,    b, unsigned char, bbuf, NBYTES, 0,  1)
37346ef47e2STaylor Simpson CIRC_TEST_STORE_IMM(h,    h, short,         hbuf, NHALFS, 0,  2)
37446ef47e2STaylor Simpson CIRC_TEST_STORE_IMM(f,    h, short,         hbuf, NHALFS, 16, 2)
37546ef47e2STaylor Simpson CIRC_TEST_STORE_IMM(w,    w, int,           wbuf, NWORDS, 0,  4)
37646ef47e2STaylor Simpson CIRC_TEST_STORE_IMM(d,    d, long long,     dbuf, NDOBLS, 0,  8)
37746ef47e2STaylor Simpson CIRC_TEST_STORE_IMM(bnew, b, unsigned char, bbuf, NBYTES, 0,  1)
37846ef47e2STaylor Simpson CIRC_TEST_STORE_IMM(hnew, h, short,         hbuf, NHALFS, 0,  2)
37946ef47e2STaylor Simpson CIRC_TEST_STORE_IMM(wnew, w, int,           wbuf, NWORDS, 0,  4)
38046ef47e2STaylor Simpson 
38146ef47e2STaylor Simpson #define CIRC_TEST_STORE_REG(SZ, CHK, TYPE, BUF, BUFSIZE, SHIFT) \
38246ef47e2STaylor Simpson void circ_test_store_reg_##SZ(void) \
38346ef47e2STaylor Simpson { \
38446ef47e2STaylor Simpson     TYPE *p = BUF; \
38546ef47e2STaylor Simpson     unsigned int size = 19; \
38646ef47e2STaylor Simpson     TYPE val = 0; \
38746ef47e2STaylor Simpson     int i; \
38846ef47e2STaylor Simpson     init_##BUF(); \
38946ef47e2STaylor Simpson     for (i = 0; i < BUFSIZE; i++) { \
39046ef47e2STaylor Simpson         CIRC_STORE_REG_##SZ(val << SHIFT, p, BUF, size * sizeof(TYPE), 1); \
39146ef47e2STaylor Simpson         val++; \
39246ef47e2STaylor Simpson     } \
39346ef47e2STaylor Simpson     check_store_##CHK(1, size); \
39446ef47e2STaylor Simpson     p = BUF; \
39546ef47e2STaylor Simpson     val = 0; \
39646ef47e2STaylor Simpson     init_##BUF(); \
39746ef47e2STaylor Simpson     for (i = 0; i < BUFSIZE; i++) { \
39846ef47e2STaylor Simpson         CIRC_STORE_REG_##SZ(val << SHIFT, p, BUF, size * sizeof(TYPE), -1); \
39946ef47e2STaylor Simpson         val++; \
40046ef47e2STaylor Simpson     } \
40146ef47e2STaylor Simpson     check_store_##CHK(-1, size); \
40246ef47e2STaylor Simpson }
40346ef47e2STaylor Simpson 
40446ef47e2STaylor Simpson CIRC_TEST_STORE_REG(b,    b, unsigned char, bbuf, NBYTES, 0)
40546ef47e2STaylor Simpson CIRC_TEST_STORE_REG(h,    h, short,         hbuf, NHALFS, 0)
40646ef47e2STaylor Simpson CIRC_TEST_STORE_REG(f,    h, short,         hbuf, NHALFS, 16)
40746ef47e2STaylor Simpson CIRC_TEST_STORE_REG(w,    w, int,           wbuf, NWORDS, 0)
40846ef47e2STaylor Simpson CIRC_TEST_STORE_REG(d,    d, long long,     dbuf, NDOBLS, 0)
40946ef47e2STaylor Simpson CIRC_TEST_STORE_REG(bnew, b, unsigned char, bbuf, NBYTES, 0)
41046ef47e2STaylor Simpson CIRC_TEST_STORE_REG(hnew, h, short,         hbuf, NHALFS, 0)
41146ef47e2STaylor Simpson CIRC_TEST_STORE_REG(wnew, w, int,           wbuf, NWORDS, 0)
41246ef47e2STaylor Simpson 
41346ef47e2STaylor Simpson /* Test the old scheme used in Hexagon V3 */
41446ef47e2STaylor Simpson static void circ_test_v3(void)
41546ef47e2STaylor Simpson {
41646ef47e2STaylor Simpson     int *p = wbuf;
41746ef47e2STaylor Simpson     int size = 15;
418*58ff2981SMichael Lambert     /* set high bit in K to test unsigned extract in fcirc */
419*58ff2981SMichael Lambert     int K = 8;      /* 1024 bytes */
42046ef47e2STaylor Simpson     int element;
42146ef47e2STaylor Simpson     int i;
42246ef47e2STaylor Simpson 
42346ef47e2STaylor Simpson     init_wbuf();
42446ef47e2STaylor Simpson 
42546ef47e2STaylor Simpson     for (i = 0; i < NWORDS; i++) {
42646ef47e2STaylor Simpson         __asm__(
42746ef47e2STaylor Simpson             "r4 = %2\n\t"
42846ef47e2STaylor Simpson             "m1 = r4\n\t"
42946ef47e2STaylor Simpson             "%0 = memw(%1++I:circ(M1))\n\t"
43046ef47e2STaylor Simpson             : "=r"(element), "+r"(p)
43146ef47e2STaylor Simpson             : "r"(build_mreg(1, K, size * sizeof(int)))
43246ef47e2STaylor Simpson             : "r4", "m1");
43346ef47e2STaylor Simpson         DEBUG_PRINTF("i = %2d, p = 0x%p, element = %2d\n", i, p, element);
43446ef47e2STaylor Simpson         check_load(i, element, 1, size);
43546ef47e2STaylor Simpson     }
43646ef47e2STaylor Simpson }
43746ef47e2STaylor Simpson 
43846ef47e2STaylor Simpson int main()
43946ef47e2STaylor Simpson {
44046ef47e2STaylor Simpson     init_bbuf();
44146ef47e2STaylor Simpson     init_hbuf();
44246ef47e2STaylor Simpson     init_wbuf();
44346ef47e2STaylor Simpson     init_dbuf();
44446ef47e2STaylor Simpson 
44546ef47e2STaylor Simpson     DEBUG_PRINTF("NBYTES = %d\n", NBYTES);
44646ef47e2STaylor Simpson     DEBUG_PRINTF("Address of dbuf = 0x%p\n", dbuf);
44746ef47e2STaylor Simpson     DEBUG_PRINTF("Address of wbuf = 0x%p\n", wbuf);
44846ef47e2STaylor Simpson     DEBUG_PRINTF("Address of hbuf = 0x%p\n", hbuf);
44946ef47e2STaylor Simpson     DEBUG_PRINTF("Address of bbuf = 0x%p\n", bbuf);
45046ef47e2STaylor Simpson 
45146ef47e2STaylor Simpson     circ_test_load_imm_b();
45246ef47e2STaylor Simpson     circ_test_load_imm_ub();
45346ef47e2STaylor Simpson     circ_test_load_imm_h();
45446ef47e2STaylor Simpson     circ_test_load_imm_uh();
45546ef47e2STaylor Simpson     circ_test_load_imm_w();
45646ef47e2STaylor Simpson     circ_test_load_imm_d();
45746ef47e2STaylor Simpson 
45846ef47e2STaylor Simpson     circ_test_load_reg_b();
45946ef47e2STaylor Simpson     circ_test_load_reg_ub();
46046ef47e2STaylor Simpson     circ_test_load_reg_h();
46146ef47e2STaylor Simpson     circ_test_load_reg_uh();
46246ef47e2STaylor Simpson     circ_test_load_reg_w();
46346ef47e2STaylor Simpson     circ_test_load_reg_d();
46446ef47e2STaylor Simpson 
46546ef47e2STaylor Simpson     circ_test_store_imm_b();
46646ef47e2STaylor Simpson     circ_test_store_imm_h();
46746ef47e2STaylor Simpson     circ_test_store_imm_f();
46846ef47e2STaylor Simpson     circ_test_store_imm_w();
46946ef47e2STaylor Simpson     circ_test_store_imm_d();
47046ef47e2STaylor Simpson     circ_test_store_imm_bnew();
47146ef47e2STaylor Simpson     circ_test_store_imm_hnew();
47246ef47e2STaylor Simpson     circ_test_store_imm_wnew();
47346ef47e2STaylor Simpson 
47446ef47e2STaylor Simpson     circ_test_store_reg_b();
47546ef47e2STaylor Simpson     circ_test_store_reg_h();
47646ef47e2STaylor Simpson     circ_test_store_reg_f();
47746ef47e2STaylor Simpson     circ_test_store_reg_w();
47846ef47e2STaylor Simpson     circ_test_store_reg_d();
47946ef47e2STaylor Simpson     circ_test_store_reg_bnew();
48046ef47e2STaylor Simpson     circ_test_store_reg_hnew();
48146ef47e2STaylor Simpson     circ_test_store_reg_wnew();
48246ef47e2STaylor Simpson 
48346ef47e2STaylor Simpson     circ_test_v3();
48446ef47e2STaylor Simpson 
48546ef47e2STaylor Simpson     puts(err ? "FAIL" : "PASS");
48646ef47e2STaylor Simpson     return err ? 1 : 0;
48746ef47e2STaylor Simpson }
488