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 /*
19 * Test load unpack instructions
20 *
21 * Example
22 * r0 = memubh(r1+#0)
23 * loads a half word from memory and zero-extends the 2 bytes to form a word
24 *
25 * For each addressing mode, there are 4 tests
26 * bzw2 unsigned 2 elements
27 * bsw2 signed 2 elements
28 * bzw4 unsigned 4 elements
29 * bsw4 signed 4 elements
30 * There are 8 addressing modes, for a total of 32 instructions to test
31 */
32
33 #include <stdio.h>
34 #include <stdint.h>
35 #include <string.h>
36
37 int err;
38
39 #include "hex_test.h"
40
41 int8_t buf[16] __attribute__((aligned(1 << 16)));
42
init_buf(void)43 void init_buf(void)
44 {
45 for (int i = 0; i < 16; i++) {
46 int sign = i % 2 == 0 ? 0x80 : 0;
47 buf[i] = sign | (i + 1);
48 }
49 }
50
51 /*
52 ****************************************************************************
53 * _io addressing mode (addr + offset)
54 */
55 #define BxW_LOAD_io(SZ, RES, ADDR, OFF) \
56 __asm__( \
57 "%0 = mem" #SZ "(%1+#" #OFF ")\n\t" \
58 : "=r"(RES) \
59 : "r"(ADDR))
60 #define BxW_LOAD_io_Z(RES, ADDR, OFF) \
61 BxW_LOAD_io(ubh, RES, ADDR, OFF)
62 #define BxW_LOAD_io_S(RES, ADDR, OFF) \
63 BxW_LOAD_io(bh, RES, ADDR, OFF)
64
65 #define TEST_io(NAME, TYPE, SIGN, SIZE, EXT, EXP1, EXP2, EXP3, EXP4) \
66 void test_##NAME(void) \
67 { \
68 TYPE result; \
69 init_buf(); \
70 BxW_LOAD_io_##SIGN(result, buf, 0 * (SIZE)); \
71 check64(result, (EXP1) | (EXT)); \
72 BxW_LOAD_io_##SIGN(result, buf, 1 * (SIZE)); \
73 check64(result, (EXP2) | (EXT)); \
74 BxW_LOAD_io_##SIGN(result, buf, 2 * (SIZE)); \
75 check64(result, (EXP3) | (EXT)); \
76 BxW_LOAD_io_##SIGN(result, buf, 3 * (SIZE)); \
77 check64(result, (EXP4) | (EXT)); \
78 }
79
80
81 TEST_io(loadbzw2_io, int32_t, Z, 2, 0x00000000,
82 0x00020081, 0x00040083, 0x00060085, 0x00080087)
83 TEST_io(loadbsw2_io, int32_t, S, 2, 0x0000ff00,
84 0x00020081, 0x00040083, 0x00060085, 0x00080087)
85 TEST_io(loadbzw4_io, int64_t, Z, 4, 0x0000000000000000LL,
86 0x0004008300020081LL, 0x0008008700060085LL,
87 0x000c008b000a0089LL, 0x0010008f000e008dLL)
88 TEST_io(loadbsw4_io, int64_t, S, 4, 0x0000ff000000ff00LL,
89 0x0004008300020081LL, 0x0008008700060085LL,
90 0x000c008b000a0089LL, 0x0010008f000e008dLL)
91
92 /*
93 ****************************************************************************
94 * _ur addressing mode (index << offset + base)
95 */
96 #define BxW_LOAD_ur(SZ, RES, SHIFT, IDX) \
97 __asm__( \
98 "%0 = mem" #SZ "(%1<<#" #SHIFT " + ##buf)\n\t" \
99 : "=r"(RES) \
100 : "r"(IDX))
101 #define BxW_LOAD_ur_Z(RES, SHIFT, IDX) \
102 BxW_LOAD_ur(ubh, RES, SHIFT, IDX)
103 #define BxW_LOAD_ur_S(RES, SHIFT, IDX) \
104 BxW_LOAD_ur(bh, RES, SHIFT, IDX)
105
106 #define TEST_ur(NAME, TYPE, SIGN, SHIFT, EXT, RES1, RES2, RES3, RES4) \
107 void test_##NAME(void) \
108 { \
109 TYPE result; \
110 init_buf(); \
111 BxW_LOAD_ur_##SIGN(result, (SHIFT), 0); \
112 check64(result, (RES1) | (EXT)); \
113 BxW_LOAD_ur_##SIGN(result, (SHIFT), 1); \
114 check64(result, (RES2) | (EXT)); \
115 BxW_LOAD_ur_##SIGN(result, (SHIFT), 2); \
116 check64(result, (RES3) | (EXT)); \
117 BxW_LOAD_ur_##SIGN(result, (SHIFT), 3); \
118 check64(result, (RES4) | (EXT)); \
119 } \
120
121 TEST_ur(loadbzw2_ur, int32_t, Z, 1, 0x00000000,
122 0x00020081, 0x00040083, 0x00060085, 0x00080087)
123 TEST_ur(loadbsw2_ur, int32_t, S, 1, 0x0000ff00,
124 0x00020081, 0x00040083, 0x00060085, 0x00080087)
125 TEST_ur(loadbzw4_ur, int64_t, Z, 2, 0x0000000000000000LL,
126 0x0004008300020081LL, 0x0008008700060085LL,
127 0x000c008b000a0089LL, 0x0010008f000e008dLL)
128 TEST_ur(loadbsw4_ur, int64_t, S, 2, 0x0000ff000000ff00LL,
129 0x0004008300020081LL, 0x0008008700060085LL,
130 0x000c008b000a0089LL, 0x0010008f000e008dLL)
131
132 /*
133 ****************************************************************************
134 * _ap addressing mode (addr = base)
135 */
136 #define BxW_LOAD_ap(SZ, RES, PTR, ADDR) \
137 __asm__( \
138 "%0 = mem" #SZ "(%1 = ##" #ADDR ")\n\t" \
139 : "=r"(RES), "=r"(PTR))
140 #define BxW_LOAD_ap_Z(RES, PTR, ADDR) \
141 BxW_LOAD_ap(ubh, RES, PTR, ADDR)
142 #define BxW_LOAD_ap_S(RES, PTR, ADDR) \
143 BxW_LOAD_ap(bh, RES, PTR, ADDR)
144
145 #define TEST_ap(NAME, TYPE, SIGN, SIZE, EXT, RES1, RES2, RES3, RES4) \
146 void test_##NAME(void) \
147 { \
148 TYPE result; \
149 void *ptr; \
150 init_buf(); \
151 BxW_LOAD_ap_##SIGN(result, ptr, (buf + 0 * (SIZE))); \
152 check64(result, (RES1) | (EXT)); \
153 checkp(ptr, &buf[0 * (SIZE)]); \
154 BxW_LOAD_ap_##SIGN(result, ptr, (buf + 1 * (SIZE))); \
155 check64(result, (RES2) | (EXT)); \
156 checkp(ptr, &buf[1 * (SIZE)]); \
157 BxW_LOAD_ap_##SIGN(result, ptr, (buf + 2 * (SIZE))); \
158 check64(result, (RES3) | (EXT)); \
159 checkp(ptr, &buf[2 * (SIZE)]); \
160 BxW_LOAD_ap_##SIGN(result, ptr, (buf + 3 * (SIZE))); \
161 check64(result, (RES4) | (EXT)); \
162 checkp(ptr, &buf[3 * (SIZE)]); \
163 }
164
165 TEST_ap(loadbzw2_ap, int32_t, Z, 2, 0x00000000,
166 0x00020081, 0x00040083, 0x00060085, 0x00080087)
167 TEST_ap(loadbsw2_ap, int32_t, S, 2, 0x0000ff00,
168 0x00020081, 0x00040083, 0x00060085, 0x00080087)
169 TEST_ap(loadbzw4_ap, int64_t, Z, 4, 0x0000000000000000LL,
170 0x0004008300020081LL, 0x0008008700060085LL,
171 0x000c008b000a0089LL, 0x0010008f000e008dLL)
172 TEST_ap(loadbsw4_ap, int64_t, S, 4, 0x0000ff000000ff00LL,
173 0x0004008300020081LL, 0x0008008700060085LL,
174 0x000c008b000a0089LL, 0x0010008f000e008dLL)
175
176 /*
177 ****************************************************************************
178 * _rp addressing mode (addr ++ modifer-reg)
179 */
180 #define BxW_LOAD_pr(SZ, RES, PTR, INC) \
181 __asm__( \
182 "m0 = %2\n\t" \
183 "%0 = mem" #SZ "(%1++m0)\n\t" \
184 : "=r"(RES), "+r"(PTR) \
185 : "r"(INC) \
186 : "m0")
187 #define BxW_LOAD_pr_Z(RES, PTR, INC) \
188 BxW_LOAD_pr(ubh, RES, PTR, INC)
189 #define BxW_LOAD_pr_S(RES, PTR, INC) \
190 BxW_LOAD_pr(bh, RES, PTR, INC)
191
192 #define TEST_pr(NAME, TYPE, SIGN, SIZE, EXT, RES1, RES2, RES3, RES4) \
193 void test_##NAME(void) \
194 { \
195 TYPE result; \
196 void *ptr = buf; \
197 init_buf(); \
198 BxW_LOAD_pr_##SIGN(result, ptr, (SIZE)); \
199 check64(result, (RES1) | (EXT)); \
200 checkp(ptr, &buf[1 * (SIZE)]); \
201 BxW_LOAD_pr_##SIGN(result, ptr, (SIZE)); \
202 check64(result, (RES2) | (EXT)); \
203 checkp(ptr, &buf[2 * (SIZE)]); \
204 BxW_LOAD_pr_##SIGN(result, ptr, (SIZE)); \
205 check64(result, (RES3) | (EXT)); \
206 checkp(ptr, &buf[3 * (SIZE)]); \
207 BxW_LOAD_pr_##SIGN(result, ptr, (SIZE)); \
208 check64(result, (RES4) | (EXT)); \
209 checkp(ptr, &buf[4 * (SIZE)]); \
210 }
211
212 TEST_pr(loadbzw2_pr, int32_t, Z, 2, 0x00000000,
213 0x00020081, 0x0040083, 0x00060085, 0x00080087)
214 TEST_pr(loadbsw2_pr, int32_t, S, 2, 0x0000ff00,
215 0x00020081, 0x0040083, 0x00060085, 0x00080087)
216 TEST_pr(loadbzw4_pr, int64_t, Z, 4, 0x0000000000000000LL,
217 0x0004008300020081LL, 0x0008008700060085LL,
218 0x000c008b000a0089LL, 0x0010008f000e008dLL)
219 TEST_pr(loadbsw4_pr, int64_t, S, 4, 0x0000ff000000ff00LL,
220 0x0004008300020081LL, 0x0008008700060085LL,
221 0x000c008b000a0089LL, 0x0010008f000e008dLL)
222
223 /*
224 ****************************************************************************
225 * _pbr addressing mode (addr ++ modifer-reg:brev)
226 */
227 #define BxW_LOAD_pbr(SZ, RES, PTR) \
228 __asm__( \
229 "r4 = #(1 << (16 - 4))\n\t" \
230 "m0 = r4\n\t" \
231 "%0 = mem" #SZ "(%1++m0:brev)\n\t" \
232 : "=r"(RES), "+r"(PTR) \
233 : \
234 : "r4", "m0")
235 #define BxW_LOAD_pbr_Z(RES, PTR) \
236 BxW_LOAD_pbr(ubh, RES, PTR)
237 #define BxW_LOAD_pbr_S(RES, PTR) \
238 BxW_LOAD_pbr(bh, RES, PTR)
239
240 #define TEST_pbr(NAME, TYPE, SIGN, EXT, RES1, RES2, RES3, RES4) \
241 void test_##NAME(void) \
242 { \
243 TYPE result; \
244 void *ptr = buf; \
245 init_buf(); \
246 BxW_LOAD_pbr_##SIGN(result, ptr); \
247 check64(result, (RES1) | (EXT)); \
248 BxW_LOAD_pbr_##SIGN(result, ptr); \
249 check64(result, (RES2) | (EXT)); \
250 BxW_LOAD_pbr_##SIGN(result, ptr); \
251 check64(result, (RES3) | (EXT)); \
252 BxW_LOAD_pbr_##SIGN(result, ptr); \
253 check64(result, (RES4) | (EXT)); \
254 }
255
256 TEST_pbr(loadbzw2_pbr, int32_t, Z, 0x00000000,
257 0x00020081, 0x000a0089, 0x00060085, 0x000e008d)
258 TEST_pbr(loadbsw2_pbr, int32_t, S, 0x0000ff00,
259 0x00020081, 0x000aff89, 0x0006ff85, 0x000eff8d)
260 TEST_pbr(loadbzw4_pbr, int64_t, Z, 0x0000000000000000LL,
261 0x0004008300020081LL, 0x000c008b000a0089LL,
262 0x0008008700060085LL, 0x0010008f000e008dLL)
263 TEST_pbr(loadbsw4_pbr, int64_t, S, 0x0000ff000000ff00LL,
264 0x0004008300020081LL, 0x000cff8b000aff89LL,
265 0x0008ff870006ff85LL, 0x0010ff8f000eff8dLL)
266
267 /*
268 ****************************************************************************
269 * _pi addressing mode (addr ++ inc)
270 */
271 #define BxW_LOAD_pi(SZ, RES, PTR, INC) \
272 __asm__( \
273 "%0 = mem" #SZ "(%1++#" #INC ")\n\t" \
274 : "=r"(RES), "+r"(PTR))
275 #define BxW_LOAD_pi_Z(RES, PTR, INC) \
276 BxW_LOAD_pi(ubh, RES, PTR, INC)
277 #define BxW_LOAD_pi_S(RES, PTR, INC) \
278 BxW_LOAD_pi(bh, RES, PTR, INC)
279
280 #define TEST_pi(NAME, TYPE, SIGN, INC, EXT, RES1, RES2, RES3, RES4) \
281 void test_##NAME(void) \
282 { \
283 TYPE result; \
284 void *ptr = buf; \
285 init_buf(); \
286 BxW_LOAD_pi_##SIGN(result, ptr, (INC)); \
287 check64(result, (RES1) | (EXT)); \
288 checkp(ptr, &buf[1 * (INC)]); \
289 BxW_LOAD_pi_##SIGN(result, ptr, (INC)); \
290 check64(result, (RES2) | (EXT)); \
291 checkp(ptr, &buf[2 * (INC)]); \
292 BxW_LOAD_pi_##SIGN(result, ptr, (INC)); \
293 check64(result, (RES3) | (EXT)); \
294 checkp(ptr, &buf[3 * (INC)]); \
295 BxW_LOAD_pi_##SIGN(result, ptr, (INC)); \
296 check64(result, (RES4) | (EXT)); \
297 checkp(ptr, &buf[4 * (INC)]); \
298 }
299
300 TEST_pi(loadbzw2_pi, int32_t, Z, 2, 0x00000000,
301 0x00020081, 0x00040083, 0x00060085, 0x00080087)
302 TEST_pi(loadbsw2_pi, int32_t, S, 2, 0x0000ff00,
303 0x00020081, 0x00040083, 0x00060085, 0x00080087)
304 TEST_pi(loadbzw4_pi, int64_t, Z, 4, 0x0000000000000000LL,
305 0x0004008300020081LL, 0x0008008700060085LL,
306 0x000c008b000a0089LL, 0x0010008f000e008dLL)
307 TEST_pi(loadbsw4_pi, int64_t, S, 4, 0x0000ff000000ff00LL,
308 0x0004008300020081LL, 0x0008008700060085LL,
309 0x000c008b000a0089LL, 0x0010008f000e008dLL)
310
311 /*
312 ****************************************************************************
313 * _pci addressing mode (addr ++ inc:circ)
314 */
315 #define BxW_LOAD_pci(SZ, RES, PTR, START, LEN, INC) \
316 __asm__( \
317 "r4 = %3\n\t" \
318 "m0 = r4\n\t" \
319 "cs0 = %2\n\t" \
320 "%0 = mem" #SZ "(%1++#" #INC ":circ(m0))\n\t" \
321 : "=r"(RES), "+r"(PTR) \
322 : "r"(START), "r"(LEN) \
323 : "r4", "m0", "cs0")
324 #define BxW_LOAD_pci_Z(RES, PTR, START, LEN, INC) \
325 BxW_LOAD_pci(ubh, RES, PTR, START, LEN, INC)
326 #define BxW_LOAD_pci_S(RES, PTR, START, LEN, INC) \
327 BxW_LOAD_pci(bh, RES, PTR, START, LEN, INC)
328
329 #define TEST_pci(NAME, TYPE, SIGN, LEN, INC, EXT, RES1, RES2, RES3, RES4) \
330 void test_##NAME(void) \
331 { \
332 TYPE result; \
333 void *ptr = buf; \
334 init_buf(); \
335 BxW_LOAD_pci_##SIGN(result, ptr, buf, (LEN), (INC)); \
336 check64(result, (RES1) | (EXT)); \
337 checkp(ptr, &buf[(1 * (INC)) % (LEN)]); \
338 BxW_LOAD_pci_##SIGN(result, ptr, buf, (LEN), (INC)); \
339 check64(result, (RES2) | (EXT)); \
340 checkp(ptr, &buf[(2 * (INC)) % (LEN)]); \
341 BxW_LOAD_pci_##SIGN(result, ptr, buf, (LEN), (INC)); \
342 check64(result, (RES3) | (EXT)); \
343 checkp(ptr, &buf[(3 * (INC)) % (LEN)]); \
344 BxW_LOAD_pci_##SIGN(result, ptr, buf, (LEN), (INC)); \
345 check64(result, (RES4) | (EXT)); \
346 checkp(ptr, &buf[(4 * (INC)) % (LEN)]); \
347 }
348
349 TEST_pci(loadbzw2_pci, int32_t, Z, 6, 2, 0x00000000,
350 0x00020081, 0x00040083, 0x00060085, 0x00020081)
351 TEST_pci(loadbsw2_pci, int32_t, S, 6, 2, 0x0000ff00,
352 0x00020081, 0x00040083, 0x00060085, 0x00020081)
353 TEST_pci(loadbzw4_pci, int64_t, Z, 8, 4, 0x0000000000000000LL,
354 0x0004008300020081LL, 0x0008008700060085LL,
355 0x0004008300020081LL, 0x0008008700060085LL)
356 TEST_pci(loadbsw4_pci, int64_t, S, 8, 4, 0x0000ff000000ff00LL,
357 0x0004008300020081LL, 0x0008008700060085LL,
358 0x0004008300020081LL, 0x0008008700060085LL)
359
360 /*
361 ****************************************************************************
362 * _pcr addressing mode (addr ++ I:circ(modifier-reg))
363 */
364 #define BxW_LOAD_pcr(SZ, RES, PTR, START, LEN, INC) \
365 __asm__( \
366 "r4 = %2\n\t" \
367 "m1 = r4\n\t" \
368 "cs1 = %3\n\t" \
369 "%0 = mem" #SZ "(%1++I:circ(m1))\n\t" \
370 : "=r"(RES), "+r"(PTR) \
371 : "r"((((INC) & 0x7f) << 17) | ((LEN) & 0x1ffff)), \
372 "r"(START) \
373 : "r4", "m1", "cs1")
374 #define BxW_LOAD_pcr_Z(RES, PTR, START, LEN, INC) \
375 BxW_LOAD_pcr(ubh, RES, PTR, START, LEN, INC)
376 #define BxW_LOAD_pcr_S(RES, PTR, START, LEN, INC) \
377 BxW_LOAD_pcr(bh, RES, PTR, START, LEN, INC)
378
379 #define TEST_pcr(NAME, TYPE, SIGN, SIZE, LEN, INC, \
380 EXT, RES1, RES2, RES3, RES4) \
381 void test_##NAME(void) \
382 { \
383 TYPE result; \
384 void *ptr = buf; \
385 init_buf(); \
386 BxW_LOAD_pcr_##SIGN(result, ptr, buf, (LEN), (INC)); \
387 check64(result, (RES1) | (EXT)); \
388 checkp(ptr, &buf[(1 * (INC) * (SIZE)) % (LEN)]); \
389 BxW_LOAD_pcr_##SIGN(result, ptr, buf, (LEN), (INC)); \
390 check64(result, (RES2) | (EXT)); \
391 checkp(ptr, &buf[(2 * (INC) * (SIZE)) % (LEN)]); \
392 BxW_LOAD_pcr_##SIGN(result, ptr, buf, (LEN), (INC)); \
393 check64(result, (RES3) | (EXT)); \
394 checkp(ptr, &buf[(3 * (INC) * (SIZE)) % (LEN)]); \
395 BxW_LOAD_pcr_##SIGN(result, ptr, buf, (LEN), (INC)); \
396 check64(result, (RES4) | (EXT)); \
397 checkp(ptr, &buf[(4 * (INC) * (SIZE)) % (LEN)]); \
398 }
399
400 TEST_pcr(loadbzw2_pcr, int32_t, Z, 2, 8, 2, 0x00000000,
401 0x00020081, 0x00060085, 0x00020081, 0x00060085)
402 TEST_pcr(loadbsw2_pcr, int32_t, S, 2, 8, 2, 0x0000ff00,
403 0x00020081, 0x00060085, 0x00020081, 0x00060085)
404 TEST_pcr(loadbzw4_pcr, int64_t, Z, 4, 8, 1, 0x0000000000000000LL,
405 0x0004008300020081LL, 0x0008008700060085LL,
406 0x0004008300020081LL, 0x0008008700060085LL)
407 TEST_pcr(loadbsw4_pcr, int64_t, S, 4, 8, 1, 0x0000ff000000ff00LL,
408 0x0004008300020081LL, 0x0008008700060085LL,
409 0x0004008300020081LL, 0x0008008700060085LL)
410
main()411 int main()
412 {
413 test_loadbzw2_io();
414 test_loadbsw2_io();
415 test_loadbzw4_io();
416 test_loadbsw4_io();
417
418 test_loadbzw2_ur();
419 test_loadbsw2_ur();
420 test_loadbzw4_ur();
421 test_loadbsw4_ur();
422
423 test_loadbzw2_ap();
424 test_loadbsw2_ap();
425 test_loadbzw4_ap();
426 test_loadbsw4_ap();
427
428 test_loadbzw2_pr();
429 test_loadbsw2_pr();
430 test_loadbzw4_pr();
431 test_loadbsw4_pr();
432
433 test_loadbzw2_pbr();
434 test_loadbsw2_pbr();
435 test_loadbzw4_pbr();
436 test_loadbsw4_pbr();
437
438 test_loadbzw2_pi();
439 test_loadbsw2_pi();
440 test_loadbzw4_pi();
441 test_loadbsw4_pi();
442
443 test_loadbzw2_pci();
444 test_loadbsw2_pci();
445 test_loadbzw4_pci();
446 test_loadbsw4_pci();
447
448 test_loadbzw2_pcr();
449 test_loadbsw2_pcr();
450 test_loadbzw4_pcr();
451 test_loadbsw4_pcr();
452
453 puts(err ? "FAIL" : "PASS");
454 return err ? 1 : 0;
455 }
456