xref: /openbmc/qemu/tests/tcg/hexagon/brev.c (revision d0bf492f)
1 /*
2  *  Copyright(c) 2019-2023 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 #include <stdint.h>
21 
22 int err;
23 
24 #include "hex_test.h"
25 
26 #define NBITS          8
27 #define SIZE           (1 << NBITS)
28 
29 int64_t       dbuf[SIZE] __attribute__((aligned(1 << 16))) = {0};
30 int32_t       wbuf[SIZE] __attribute__((aligned(1 << 16))) = {0};
31 int16_t       hbuf[SIZE] __attribute__((aligned(1 << 16))) = {0};
32 uint8_t       bbuf[SIZE] __attribute__((aligned(1 << 16))) = {0};
33 
34 /*
35  * We use the C preporcessor to deal with the combinations of types
36  */
37 
38 #define BREV_LOAD(SZ, RES, ADDR, INC) \
39     __asm__( \
40         "m0 = %2\n\t" \
41         "%0 = mem" #SZ "(%1++m0:brev)\n\t" \
42         : "=r"(RES), "+r"(ADDR) \
43         : "r"(INC) \
44         : "m0")
45 
46 #define BREV_LOAD_b(RES, ADDR, INC) \
47     BREV_LOAD(b, RES, ADDR, INC)
48 #define BREV_LOAD_ub(RES, ADDR, INC) \
49     BREV_LOAD(ub, RES, ADDR, INC)
50 #define BREV_LOAD_h(RES, ADDR, INC) \
51     BREV_LOAD(h, RES, ADDR, INC)
52 #define BREV_LOAD_uh(RES, ADDR, INC) \
53     BREV_LOAD(uh, RES, ADDR, INC)
54 #define BREV_LOAD_w(RES, ADDR, INC) \
55     BREV_LOAD(w, RES, ADDR, INC)
56 #define BREV_LOAD_d(RES, ADDR, INC) \
57     BREV_LOAD(d, RES, ADDR, INC)
58 
59 #define BREV_STORE(SZ, PART, ADDR, VAL, INC) \
60     __asm__( \
61         "m0 = %2\n\t" \
62         "mem" #SZ "(%0++m0:brev) = %1" PART "\n\t" \
63         : "+r"(ADDR) \
64         : "r"(VAL), "r"(INC) \
65         : "m0", "memory")
66 
67 #define BREV_STORE_b(ADDR, VAL, INC) \
68     BREV_STORE(b, "", ADDR, VAL, INC)
69 #define BREV_STORE_h(ADDR, VAL, INC) \
70     BREV_STORE(h, "", ADDR, VAL, INC)
71 #define BREV_STORE_f(ADDR, VAL, INC) \
72     BREV_STORE(h, ".H", ADDR, VAL, INC)
73 #define BREV_STORE_w(ADDR, VAL, INC) \
74     BREV_STORE(w, "", ADDR, VAL, INC)
75 #define BREV_STORE_d(ADDR, VAL, INC) \
76     BREV_STORE(d, "", ADDR, VAL, INC)
77 
78 #define BREV_STORE_NEW(SZ, ADDR, VAL, INC) \
79     __asm__( \
80         "m0 = %2\n\t" \
81         "{\n\t" \
82         "    r5 = %1\n\t" \
83         "    mem" #SZ "(%0++m0:brev) = r5.new\n\t" \
84         "}\n\t" \
85         : "+r"(ADDR) \
86         : "r"(VAL), "r"(INC) \
87         : "r5", "m0", "memory")
88 
89 #define BREV_STORE_bnew(ADDR, VAL, INC) \
90     BREV_STORE_NEW(b, ADDR, VAL, INC)
91 #define BREV_STORE_hnew(ADDR, VAL, INC) \
92     BREV_STORE_NEW(h, ADDR, VAL, INC)
93 #define BREV_STORE_wnew(ADDR, VAL, INC) \
94     BREV_STORE_NEW(w, ADDR, VAL, INC)
95 
96 uint32_t bitreverse(uint32_t x)
97 {
98     uint32_t result = 0;
99     for (int i = 0; i < NBITS; i++) {
100         result <<= 1;
101         result |= x & 1;
102         x >>= 1;
103     }
104     return result;
105 }
106 
107 int32_t sext8(int32_t x)
108 {
109     return (x << 24) >> 24;
110 }
111 
112 #define TEST_BREV_LOAD(SZ, TYPE, BUF, SHIFT, EXP) \
113     do { \
114         p = BUF; \
115         for (int i = 0; i < SIZE; i++) { \
116             TYPE result; \
117             BREV_LOAD_##SZ(result, p, 1 << (SHIFT - NBITS)); \
118             check32(result, EXP); \
119         } \
120     } while (0)
121 
122 #define TEST_BREV_STORE(SZ, TYPE, BUF, VAL, SHIFT) \
123     do { \
124         p = BUF; \
125         memset(BUF, 0xff, sizeof(BUF)); \
126         for (int i = 0; i < SIZE; i++) { \
127             BREV_STORE_##SZ(p, (TYPE)(VAL), 1 << (SHIFT - NBITS)); \
128         } \
129         for (int i = 0; i < SIZE; i++) { \
130             check32(BUF[i], bitreverse(i)); \
131         } \
132     } while (0)
133 
134 #define TEST_BREV_STORE_NEW(SZ, BUF, SHIFT) \
135     do { \
136         p = BUF; \
137         memset(BUF, 0xff, sizeof(BUF)); \
138         for (int i = 0; i < SIZE; i++) { \
139             BREV_STORE_##SZ(p, i, 1 << (SHIFT - NBITS)); \
140         } \
141         for (int i = 0; i < SIZE; i++) { \
142             check32(BUF[i], bitreverse(i)); \
143         } \
144     } while (0)
145 
146 /*
147  * We'll set high_half[i] = i << 16 for use in the .H form of store
148  * which stores from the high half of the word.
149  */
150 int high_half[SIZE];
151 
152 int main()
153 {
154     void *p;
155 
156     for (int i = 0; i < SIZE; i++) {
157         bbuf[i] = bitreverse(i);
158         hbuf[i] = bitreverse(i);
159         wbuf[i] = bitreverse(i);
160         dbuf[i] = bitreverse(i);
161         high_half[i] = i << 16;
162     }
163 
164     TEST_BREV_LOAD(b,  int32_t,   bbuf, 16, sext8(i));
165     TEST_BREV_LOAD(ub, int32_t,   bbuf, 16, i);
166     TEST_BREV_LOAD(h,  int32_t,   hbuf, 15, i);
167     TEST_BREV_LOAD(uh, int32_t,   hbuf, 15, i);
168     TEST_BREV_LOAD(w,  int32_t,   wbuf, 14, i);
169     TEST_BREV_LOAD(d,  int64_t,   dbuf, 13, i);
170 
171     TEST_BREV_STORE(b, int32_t,   bbuf, i,            16);
172     TEST_BREV_STORE(h, int32_t,   hbuf, i,            15);
173     TEST_BREV_STORE(f, int32_t,   hbuf, high_half[i], 15);
174     TEST_BREV_STORE(w, int32_t,   wbuf, i,            14);
175     TEST_BREV_STORE(d, int64_t,   dbuf, i,            13);
176 
177     TEST_BREV_STORE_NEW(bnew, bbuf, 16);
178     TEST_BREV_STORE_NEW(hnew, hbuf, 15);
179     TEST_BREV_STORE_NEW(wnew, wbuf, 14);
180 
181     puts(err ? "FAIL" : "PASS");
182     return err ? 1 : 0;
183 }
184