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