xref: /openbmc/qemu/tests/tcg/hexagon/brev.c (revision b4b9a0e3)
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