1 /* 2 * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include <stdio.h> 19 #include <string.h> 20 21 int err; 22 23 #define NBITS 8 24 #define SIZE (1 << NBITS) 25 26 long long dbuf[SIZE] __attribute__((aligned(1 << 16))) = {0}; 27 int wbuf[SIZE] __attribute__((aligned(1 << 16))) = {0}; 28 short hbuf[SIZE] __attribute__((aligned(1 << 16))) = {0}; 29 unsigned char bbuf[SIZE] __attribute__((aligned(1 << 16))) = {0}; 30 31 /* 32 * We use the C preporcessor to deal with the combinations of types 33 */ 34 35 #define BREV_LOAD(SZ, RES, ADDR, INC) \ 36 __asm__( \ 37 "m0 = %2\n\t" \ 38 "%0 = mem" #SZ "(%1++m0:brev)\n\t" \ 39 : "=r"(RES), "+r"(ADDR) \ 40 : "r"(INC) \ 41 : "m0") 42 43 #define BREV_LOAD_b(RES, ADDR, INC) \ 44 BREV_LOAD(b, RES, ADDR, INC) 45 #define BREV_LOAD_ub(RES, ADDR, INC) \ 46 BREV_LOAD(ub, RES, ADDR, INC) 47 #define BREV_LOAD_h(RES, ADDR, INC) \ 48 BREV_LOAD(h, RES, ADDR, INC) 49 #define BREV_LOAD_uh(RES, ADDR, INC) \ 50 BREV_LOAD(uh, RES, ADDR, INC) 51 #define BREV_LOAD_w(RES, ADDR, INC) \ 52 BREV_LOAD(w, RES, ADDR, INC) 53 #define BREV_LOAD_d(RES, ADDR, INC) \ 54 BREV_LOAD(d, RES, ADDR, INC) 55 56 #define BREV_STORE(SZ, PART, ADDR, VAL, INC) \ 57 __asm__( \ 58 "m0 = %2\n\t" \ 59 "mem" #SZ "(%0++m0:brev) = %1" PART "\n\t" \ 60 : "+r"(ADDR) \ 61 : "r"(VAL), "r"(INC) \ 62 : "m0", "memory") 63 64 #define BREV_STORE_b(ADDR, VAL, INC) \ 65 BREV_STORE(b, "", ADDR, VAL, INC) 66 #define BREV_STORE_h(ADDR, VAL, INC) \ 67 BREV_STORE(h, "", ADDR, VAL, INC) 68 #define BREV_STORE_f(ADDR, VAL, INC) \ 69 BREV_STORE(h, ".H", ADDR, VAL, INC) 70 #define BREV_STORE_w(ADDR, VAL, INC) \ 71 BREV_STORE(w, "", ADDR, VAL, INC) 72 #define BREV_STORE_d(ADDR, VAL, INC) \ 73 BREV_STORE(d, "", ADDR, VAL, INC) 74 75 #define BREV_STORE_NEW(SZ, ADDR, VAL, INC) \ 76 __asm__( \ 77 "m0 = %2\n\t" \ 78 "{\n\t" \ 79 " r5 = %1\n\t" \ 80 " mem" #SZ "(%0++m0:brev) = r5.new\n\t" \ 81 "}\n\t" \ 82 : "+r"(ADDR) \ 83 : "r"(VAL), "r"(INC) \ 84 : "r5", "m0", "memory") 85 86 #define BREV_STORE_bnew(ADDR, VAL, INC) \ 87 BREV_STORE_NEW(b, ADDR, VAL, INC) 88 #define BREV_STORE_hnew(ADDR, VAL, INC) \ 89 BREV_STORE_NEW(h, ADDR, VAL, INC) 90 #define BREV_STORE_wnew(ADDR, VAL, INC) \ 91 BREV_STORE_NEW(w, ADDR, VAL, INC) 92 93 int bitreverse(int x) 94 { 95 int result = 0; 96 int i; 97 for (i = 0; i < NBITS; i++) { 98 result <<= 1; 99 result |= x & 1; 100 x >>= 1; 101 } 102 return result; 103 } 104 105 int sext8(int x) 106 { 107 return (x << 24) >> 24; 108 } 109 110 void check(int i, long long result, long long expect) 111 { 112 if (result != expect) { 113 printf("ERROR(%d): 0x%04llx != 0x%04llx\n", i, result, expect); 114 err++; 115 } 116 } 117 118 #define TEST_BREV_LOAD(SZ, TYPE, BUF, SHIFT, EXP) \ 119 do { \ 120 p = BUF; \ 121 for (i = 0; i < SIZE; i++) { \ 122 TYPE result; \ 123 BREV_LOAD_##SZ(result, p, 1 << (SHIFT - NBITS)); \ 124 check(i, result, EXP); \ 125 } \ 126 } while (0) 127 128 #define TEST_BREV_STORE(SZ, TYPE, BUF, VAL, SHIFT) \ 129 do { \ 130 p = BUF; \ 131 memset(BUF, 0xff, sizeof(BUF)); \ 132 for (i = 0; i < SIZE; i++) { \ 133 BREV_STORE_##SZ(p, (TYPE)(VAL), 1 << (SHIFT - NBITS)); \ 134 } \ 135 for (i = 0; i < SIZE; i++) { \ 136 check(i, BUF[i], bitreverse(i)); \ 137 } \ 138 } while (0) 139 140 #define TEST_BREV_STORE_NEW(SZ, BUF, SHIFT) \ 141 do { \ 142 p = BUF; \ 143 memset(BUF, 0xff, sizeof(BUF)); \ 144 for (i = 0; i < SIZE; i++) { \ 145 BREV_STORE_##SZ(p, i, 1 << (SHIFT - NBITS)); \ 146 } \ 147 for (i = 0; i < SIZE; i++) { \ 148 check(i, BUF[i], bitreverse(i)); \ 149 } \ 150 } while (0) 151 152 /* 153 * We'll set high_half[i] = i << 16 for use in the .H form of store 154 * which stores from the high half of the word. 155 */ 156 int high_half[SIZE]; 157 158 int main() 159 { 160 void *p; 161 int i; 162 163 for (i = 0; i < SIZE; i++) { 164 bbuf[i] = bitreverse(i); 165 hbuf[i] = bitreverse(i); 166 wbuf[i] = bitreverse(i); 167 dbuf[i] = bitreverse(i); 168 high_half[i] = i << 16; 169 } 170 171 TEST_BREV_LOAD(b, int, bbuf, 16, sext8(i)); 172 TEST_BREV_LOAD(ub, int, bbuf, 16, i); 173 TEST_BREV_LOAD(h, int, hbuf, 15, i); 174 TEST_BREV_LOAD(uh, int, hbuf, 15, i); 175 TEST_BREV_LOAD(w, int, wbuf, 14, i); 176 TEST_BREV_LOAD(d, long long, dbuf, 13, i); 177 178 TEST_BREV_STORE(b, int, bbuf, i, 16); 179 TEST_BREV_STORE(h, int, hbuf, i, 15); 180 TEST_BREV_STORE(f, int, hbuf, high_half[i], 15); 181 TEST_BREV_STORE(w, int, wbuf, i, 14); 182 TEST_BREV_STORE(d, long long, dbuf, i, 13); 183 184 TEST_BREV_STORE_NEW(bnew, bbuf, 16); 185 TEST_BREV_STORE_NEW(hnew, hbuf, 15); 186 TEST_BREV_STORE_NEW(wnew, wbuf, 14); 187 188 puts(err ? "FAIL" : "PASS"); 189 return err ? 1 : 0; 190 } 191