/* * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see <http://www.gnu.org/licenses/>. */ #include <stdio.h> #include <string.h> int err; #define NBITS 8 #define SIZE (1 << NBITS) long long dbuf[SIZE] __attribute__((aligned(1 << 16))) = {0}; int wbuf[SIZE] __attribute__((aligned(1 << 16))) = {0}; short hbuf[SIZE] __attribute__((aligned(1 << 16))) = {0}; unsigned char bbuf[SIZE] __attribute__((aligned(1 << 16))) = {0}; /* * We use the C preporcessor to deal with the combinations of types */ #define BREV_LOAD(SZ, RES, ADDR, INC) \ __asm__( \ "m0 = %2\n\t" \ "%0 = mem" #SZ "(%1++m0:brev)\n\t" \ : "=r"(RES), "+r"(ADDR) \ : "r"(INC) \ : "m0") #define BREV_LOAD_b(RES, ADDR, INC) \ BREV_LOAD(b, RES, ADDR, INC) #define BREV_LOAD_ub(RES, ADDR, INC) \ BREV_LOAD(ub, RES, ADDR, INC) #define BREV_LOAD_h(RES, ADDR, INC) \ BREV_LOAD(h, RES, ADDR, INC) #define BREV_LOAD_uh(RES, ADDR, INC) \ BREV_LOAD(uh, RES, ADDR, INC) #define BREV_LOAD_w(RES, ADDR, INC) \ BREV_LOAD(w, RES, ADDR, INC) #define BREV_LOAD_d(RES, ADDR, INC) \ BREV_LOAD(d, RES, ADDR, INC) #define BREV_STORE(SZ, PART, ADDR, VAL, INC) \ __asm__( \ "m0 = %2\n\t" \ "mem" #SZ "(%0++m0:brev) = %1" PART "\n\t" \ : "+r"(ADDR) \ : "r"(VAL), "r"(INC) \ : "m0", "memory") #define BREV_STORE_b(ADDR, VAL, INC) \ BREV_STORE(b, "", ADDR, VAL, INC) #define BREV_STORE_h(ADDR, VAL, INC) \ BREV_STORE(h, "", ADDR, VAL, INC) #define BREV_STORE_f(ADDR, VAL, INC) \ BREV_STORE(h, ".H", ADDR, VAL, INC) #define BREV_STORE_w(ADDR, VAL, INC) \ BREV_STORE(w, "", ADDR, VAL, INC) #define BREV_STORE_d(ADDR, VAL, INC) \ BREV_STORE(d, "", ADDR, VAL, INC) #define BREV_STORE_NEW(SZ, ADDR, VAL, INC) \ __asm__( \ "m0 = %2\n\t" \ "{\n\t" \ " r5 = %1\n\t" \ " mem" #SZ "(%0++m0:brev) = r5.new\n\t" \ "}\n\t" \ : "+r"(ADDR) \ : "r"(VAL), "r"(INC) \ : "r5", "m0", "memory") #define BREV_STORE_bnew(ADDR, VAL, INC) \ BREV_STORE_NEW(b, ADDR, VAL, INC) #define BREV_STORE_hnew(ADDR, VAL, INC) \ BREV_STORE_NEW(h, ADDR, VAL, INC) #define BREV_STORE_wnew(ADDR, VAL, INC) \ BREV_STORE_NEW(w, ADDR, VAL, INC) int bitreverse(int x) { int result = 0; int i; for (i = 0; i < NBITS; i++) { result <<= 1; result |= x & 1; x >>= 1; } return result; } int sext8(int x) { return (x << 24) >> 24; } void check(int i, long long result, long long expect) { if (result != expect) { printf("ERROR(%d): 0x%04llx != 0x%04llx\n", i, result, expect); err++; } } #define TEST_BREV_LOAD(SZ, TYPE, BUF, SHIFT, EXP) \ do { \ p = BUF; \ for (i = 0; i < SIZE; i++) { \ TYPE result; \ BREV_LOAD_##SZ(result, p, 1 << (SHIFT - NBITS)); \ check(i, result, EXP); \ } \ } while (0) #define TEST_BREV_STORE(SZ, TYPE, BUF, VAL, SHIFT) \ do { \ p = BUF; \ memset(BUF, 0xff, sizeof(BUF)); \ for (i = 0; i < SIZE; i++) { \ BREV_STORE_##SZ(p, (TYPE)(VAL), 1 << (SHIFT - NBITS)); \ } \ for (i = 0; i < SIZE; i++) { \ check(i, BUF[i], bitreverse(i)); \ } \ } while (0) #define TEST_BREV_STORE_NEW(SZ, BUF, SHIFT) \ do { \ p = BUF; \ memset(BUF, 0xff, sizeof(BUF)); \ for (i = 0; i < SIZE; i++) { \ BREV_STORE_##SZ(p, i, 1 << (SHIFT - NBITS)); \ } \ for (i = 0; i < SIZE; i++) { \ check(i, BUF[i], bitreverse(i)); \ } \ } while (0) /* * We'll set high_half[i] = i << 16 for use in the .H form of store * which stores from the high half of the word. */ int high_half[SIZE]; int main() { void *p; int i; for (i = 0; i < SIZE; i++) { bbuf[i] = bitreverse(i); hbuf[i] = bitreverse(i); wbuf[i] = bitreverse(i); dbuf[i] = bitreverse(i); high_half[i] = i << 16; } TEST_BREV_LOAD(b, int, bbuf, 16, sext8(i)); TEST_BREV_LOAD(ub, int, bbuf, 16, i); TEST_BREV_LOAD(h, int, hbuf, 15, i); TEST_BREV_LOAD(uh, int, hbuf, 15, i); TEST_BREV_LOAD(w, int, wbuf, 14, i); TEST_BREV_LOAD(d, long long, dbuf, 13, i); TEST_BREV_STORE(b, int, bbuf, i, 16); TEST_BREV_STORE(h, int, hbuf, i, 15); TEST_BREV_STORE(f, int, hbuf, high_half[i], 15); TEST_BREV_STORE(w, int, wbuf, i, 14); TEST_BREV_STORE(d, long long, dbuf, i, 13); TEST_BREV_STORE_NEW(bnew, bbuf, 16); TEST_BREV_STORE_NEW(hnew, hbuf, 15); TEST_BREV_STORE_NEW(wnew, wbuf, 14); puts(err ? "FAIL" : "PASS"); return err ? 1 : 0; }