2 * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
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.
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.
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/>.
19 * Test load unpack instructions
23 * loads a half word from memory and zero-extends the 2 bytes to form a word
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
38 char buf
[16] __attribute__((aligned(1 << 16)));
43 for (i
= 0; i
< 16; i
++) {
44 int sign
= i
% 2 == 0 ? 0x80 : 0;
45 buf
[i
] = sign
| (i
+ 1);
49 void __check(int line
, long long result
, long long expect
)
51 if (result
!= expect
) {
52 printf("ERROR at line %d: 0x%08llx != 0x%08llx\n",
53 line
, result
, expect
);
58 #define check(RES, EXP) __check(__LINE__, RES, EXP)
60 void __checkp(int line
, void *p
, void *expect
)
63 printf("ERROR at line %d: 0x%p != 0x%p\n", line
, p
, expect
);
68 #define checkp(RES, EXP) __checkp(__LINE__, RES, EXP)
71 ****************************************************************************
72 * _io addressing mode (addr + offset)
74 #define BxW_LOAD_io(SZ, RES, ADDR, OFF) \
76 "%0 = mem" #SZ "(%1+#" #OFF ")\n\t" \
79 #define BxW_LOAD_io_Z(RES, ADDR, OFF) \
80 BxW_LOAD_io(ubh, RES, ADDR, OFF)
81 #define BxW_LOAD_io_S(RES, ADDR, OFF) \
82 BxW_LOAD_io(bh, RES, ADDR, OFF)
84 #define TEST_io(NAME, TYPE, SIGN, SIZE, EXT, EXP1, EXP2, EXP3, EXP4) \
85 void test_##NAME(void) \
89 BxW_LOAD_io_##SIGN(result, buf, 0 * (SIZE)); \
90 check(result, (EXP1) | (EXT)); \
91 BxW_LOAD_io_##SIGN(result, buf, 1 * (SIZE)); \
92 check(result, (EXP2) | (EXT)); \
93 BxW_LOAD_io_##SIGN(result, buf, 2 * (SIZE)); \
94 check(result, (EXP3) | (EXT)); \
95 BxW_LOAD_io_##SIGN(result, buf, 3 * (SIZE)); \
96 check(result, (EXP4) | (EXT)); \
100 TEST_io(loadbzw2_io
, int, Z
, 2, 0x00000000,
101 0x00020081, 0x00040083, 0x00060085, 0x00080087)
102 TEST_io(loadbsw2_io
, int, S
, 2, 0x0000ff00,
103 0x00020081, 0x00040083, 0x00060085, 0x00080087)
104 TEST_io(loadbzw4_io
, long long, Z
, 4, 0x0000000000000000LL
,
105 0x0004008300020081LL
, 0x0008008700060085LL
,
106 0x000c008b000a0089LL
, 0x0010008f000e008dLL
)
107 TEST_io(loadbsw4_io
, long long, S
, 4, 0x0000ff000000ff00LL
,
108 0x0004008300020081LL
, 0x0008008700060085LL
,
109 0x000c008b000a0089LL
, 0x0010008f000e008dLL
)
112 ****************************************************************************
113 * _ur addressing mode (index << offset + base)
115 #define BxW_LOAD_ur(SZ, RES, SHIFT, IDX) \
117 "%0 = mem" #SZ "(%1<<#" #SHIFT " + ##buf)\n\t" \
120 #define BxW_LOAD_ur_Z(RES, SHIFT, IDX) \
121 BxW_LOAD_ur(ubh, RES, SHIFT, IDX)
122 #define BxW_LOAD_ur_S(RES, SHIFT, IDX) \
123 BxW_LOAD_ur(bh, RES, SHIFT, IDX)
125 #define TEST_ur(NAME, TYPE, SIGN, SHIFT, EXT, RES1, RES2, RES3, RES4) \
126 void test_##NAME(void) \
130 BxW_LOAD_ur_##SIGN(result, (SHIFT), 0); \
131 check(result, (RES1) | (EXT)); \
132 BxW_LOAD_ur_##SIGN(result, (SHIFT), 1); \
133 check(result, (RES2) | (EXT)); \
134 BxW_LOAD_ur_##SIGN(result, (SHIFT), 2); \
135 check(result, (RES3) | (EXT)); \
136 BxW_LOAD_ur_##SIGN(result, (SHIFT), 3); \
137 check(result, (RES4) | (EXT)); \
140 TEST_ur(loadbzw2_ur, int, Z, 1, 0x00000000,
141 0x00020081, 0x00040083, 0x00060085, 0x00080087)
142 TEST_ur(loadbsw2_ur
, int, S
, 1, 0x0000ff00,
143 0x00020081, 0x00040083, 0x00060085, 0x00080087)
144 TEST_ur(loadbzw4_ur
, long long, Z
, 2, 0x0000000000000000LL
,
145 0x0004008300020081LL
, 0x0008008700060085LL
,
146 0x000c008b000a0089LL
, 0x0010008f000e008dLL
)
147 TEST_ur(loadbsw4_ur
, long long, S
, 2, 0x0000ff000000ff00LL
,
148 0x0004008300020081LL
, 0x0008008700060085LL
,
149 0x000c008b000a0089LL
, 0x0010008f000e008dLL
)
152 ****************************************************************************
153 * _ap addressing mode (addr = base)
155 #define BxW_LOAD_ap(SZ, RES, PTR, ADDR) \
157 "%0 = mem" #SZ "(%1 = ##" #ADDR ")\n\t" \
158 : "=r"(RES), "=r"(PTR))
159 #define BxW_LOAD_ap_Z(RES, PTR, ADDR) \
160 BxW_LOAD_ap(ubh, RES, PTR, ADDR)
161 #define BxW_LOAD_ap_S(RES, PTR, ADDR) \
162 BxW_LOAD_ap(bh, RES, PTR, ADDR)
164 #define TEST_ap(NAME, TYPE, SIGN, SIZE, EXT, RES1, RES2, RES3, RES4) \
165 void test_##NAME(void) \
170 BxW_LOAD_ap_##SIGN(result, ptr, (buf + 0 * (SIZE))); \
171 check(result, (RES1) | (EXT)); \
172 checkp(ptr, &buf[0 * (SIZE)]); \
173 BxW_LOAD_ap_##SIGN(result, ptr, (buf + 1 * (SIZE))); \
174 check(result, (RES2) | (EXT)); \
175 checkp(ptr, &buf[1 * (SIZE)]); \
176 BxW_LOAD_ap_##SIGN(result, ptr, (buf + 2 * (SIZE))); \
177 check(result, (RES3) | (EXT)); \
178 checkp(ptr, &buf[2 * (SIZE)]); \
179 BxW_LOAD_ap_##SIGN(result, ptr, (buf + 3 * (SIZE))); \
180 check(result, (RES4) | (EXT)); \
181 checkp(ptr, &buf[3 * (SIZE)]); \
184 TEST_ap(loadbzw2_ap
, int, Z
, 2, 0x00000000,
185 0x00020081, 0x00040083, 0x00060085, 0x00080087)
186 TEST_ap(loadbsw2_ap
, int, S
, 2, 0x0000ff00,
187 0x00020081, 0x00040083, 0x00060085, 0x00080087)
188 TEST_ap(loadbzw4_ap
, long long, Z
, 4, 0x0000000000000000LL
,
189 0x0004008300020081LL
, 0x0008008700060085LL
,
190 0x000c008b000a0089LL
, 0x0010008f000e008dLL
)
191 TEST_ap(loadbsw4_ap
, long long, S
, 4, 0x0000ff000000ff00LL
,
192 0x0004008300020081LL
, 0x0008008700060085LL
,
193 0x000c008b000a0089LL
, 0x0010008f000e008dLL
)
196 ****************************************************************************
197 * _rp addressing mode (addr ++ modifer-reg)
199 #define BxW_LOAD_pr(SZ, RES, PTR, INC) \
202 "%0 = mem" #SZ "(%1++m0)\n\t" \
203 : "=r"(RES), "+r"(PTR) \
206 #define BxW_LOAD_pr_Z(RES, PTR, INC) \
207 BxW_LOAD_pr(ubh, RES, PTR, INC)
208 #define BxW_LOAD_pr_S(RES, PTR, INC) \
209 BxW_LOAD_pr(bh, RES, PTR, INC)
211 #define TEST_pr(NAME, TYPE, SIGN, SIZE, EXT, RES1, RES2, RES3, RES4) \
212 void test_##NAME(void) \
217 BxW_LOAD_pr_##SIGN(result, ptr, (SIZE)); \
218 check(result, (RES1) | (EXT)); \
219 checkp(ptr, &buf[1 * (SIZE)]); \
220 BxW_LOAD_pr_##SIGN(result, ptr, (SIZE)); \
221 check(result, (RES2) | (EXT)); \
222 checkp(ptr, &buf[2 * (SIZE)]); \
223 BxW_LOAD_pr_##SIGN(result, ptr, (SIZE)); \
224 check(result, (RES3) | (EXT)); \
225 checkp(ptr, &buf[3 * (SIZE)]); \
226 BxW_LOAD_pr_##SIGN(result, ptr, (SIZE)); \
227 check(result, (RES4) | (EXT)); \
228 checkp(ptr, &buf[4 * (SIZE)]); \
231 TEST_pr(loadbzw2_pr
, int, Z
, 2, 0x00000000,
232 0x00020081, 0x0040083, 0x00060085, 0x00080087)
233 TEST_pr(loadbsw2_pr
, int, S
, 2, 0x0000ff00,
234 0x00020081, 0x0040083, 0x00060085, 0x00080087)
235 TEST_pr(loadbzw4_pr
, long long, Z
, 4, 0x0000000000000000LL
,
236 0x0004008300020081LL
, 0x0008008700060085LL
,
237 0x000c008b000a0089LL
, 0x0010008f000e008dLL
)
238 TEST_pr(loadbsw4_pr
, long long, S
, 4, 0x0000ff000000ff00LL
,
239 0x0004008300020081LL
, 0x0008008700060085LL
,
240 0x000c008b000a0089LL
, 0x0010008f000e008dLL
)
243 ****************************************************************************
244 * _pbr addressing mode (addr ++ modifer-reg:brev)
246 #define BxW_LOAD_pbr(SZ, RES, PTR) \
248 "r4 = #(1 << (16 - 3))\n\t" \
250 "%0 = mem" #SZ "(%1++m0:brev)\n\t" \
251 : "=r"(RES), "+r"(PTR) \
254 #define BxW_LOAD_pbr_Z(RES, PTR) \
255 BxW_LOAD_pbr(ubh, RES, PTR)
256 #define BxW_LOAD_pbr_S(RES, PTR) \
257 BxW_LOAD_pbr(bh, RES, PTR)
259 #define TEST_pbr(NAME, TYPE, SIGN, EXT, RES1, RES2, RES3, RES4) \
260 void test_##NAME(void) \
265 BxW_LOAD_pbr_##SIGN(result, ptr); \
266 check(result, (RES1) | (EXT)); \
267 BxW_LOAD_pbr_##SIGN(result, ptr); \
268 check(result, (RES2) | (EXT)); \
269 BxW_LOAD_pbr_##SIGN(result, ptr); \
270 check(result, (RES3) | (EXT)); \
271 BxW_LOAD_pbr_##SIGN(result, ptr); \
272 check(result, (RES4) | (EXT)); \
275 TEST_pbr(loadbzw2_pbr
, int, Z
, 0x00000000,
276 0x00020081, 0x00060085, 0x00040083, 0x00080087)
277 TEST_pbr(loadbsw2_pbr
, int, S
, 0x0000ff00,
278 0x00020081, 0x00060085, 0x00040083, 0x00080087)
279 TEST_pbr(loadbzw4_pbr
, long long, Z
, 0x0000000000000000LL
,
280 0x0004008300020081LL
, 0x0008008700060085LL
,
281 0x0006008500040083LL
, 0x000a008900080087LL
)
282 TEST_pbr(loadbsw4_pbr
, long long, S
, 0x0000ff000000ff00LL
,
283 0x0004008300020081LL
, 0x0008008700060085LL
,
284 0x0006008500040083LL
, 0x000a008900080087LL
)
287 ****************************************************************************
288 * _pi addressing mode (addr ++ inc)
290 #define BxW_LOAD_pi(SZ, RES, PTR, INC) \
292 "%0 = mem" #SZ "(%1++#" #INC ")\n\t" \
293 : "=r"(RES), "+r"(PTR))
294 #define BxW_LOAD_pi_Z(RES, PTR, INC) \
295 BxW_LOAD_pi(ubh, RES, PTR, INC)
296 #define BxW_LOAD_pi_S(RES, PTR, INC) \
297 BxW_LOAD_pi(bh, RES, PTR, INC)
299 #define TEST_pi(NAME, TYPE, SIGN, INC, EXT, RES1, RES2, RES3, RES4) \
300 void test_##NAME(void) \
305 BxW_LOAD_pi_##SIGN(result, ptr, (INC)); \
306 check(result, (RES1) | (EXT)); \
307 checkp(ptr, &buf[1 * (INC)]); \
308 BxW_LOAD_pi_##SIGN(result, ptr, (INC)); \
309 check(result, (RES2) | (EXT)); \
310 checkp(ptr, &buf[2 * (INC)]); \
311 BxW_LOAD_pi_##SIGN(result, ptr, (INC)); \
312 check(result, (RES3) | (EXT)); \
313 checkp(ptr, &buf[3 * (INC)]); \
314 BxW_LOAD_pi_##SIGN(result, ptr, (INC)); \
315 check(result, (RES4) | (EXT)); \
316 checkp(ptr, &buf[4 * (INC)]); \
319 TEST_pi(loadbzw2_pi
, int, Z
, 2, 0x00000000,
320 0x00020081, 0x00040083, 0x00060085, 0x00080087)
321 TEST_pi(loadbsw2_pi
, int, S
, 2, 0x0000ff00,
322 0x00020081, 0x00040083, 0x00060085, 0x00080087)
323 TEST_pi(loadbzw4_pi
, long long, Z
, 4, 0x0000000000000000LL
,
324 0x0004008300020081LL
, 0x0008008700060085LL
,
325 0x000c008b000a0089LL
, 0x0010008f000e008dLL
)
326 TEST_pi(loadbsw4_pi
, long long, S
, 4, 0x0000ff000000ff00LL
,
327 0x0004008300020081LL
, 0x0008008700060085LL
,
328 0x000c008b000a0089LL
, 0x0010008f000e008dLL
)
331 ****************************************************************************
332 * _pci addressing mode (addr ++ inc:circ)
334 #define BxW_LOAD_pci(SZ, RES, PTR, START, LEN, INC) \
339 "%0 = mem" #SZ "(%1++#" #INC ":circ(m0))\n\t" \
340 : "=r"(RES), "+r"(PTR) \
341 : "r"(START), "r"(LEN) \
343 #define BxW_LOAD_pci_Z(RES, PTR, START, LEN, INC) \
344 BxW_LOAD_pci(ubh, RES, PTR, START, LEN, INC)
345 #define BxW_LOAD_pci_S(RES, PTR, START, LEN, INC) \
346 BxW_LOAD_pci(bh, RES, PTR, START, LEN, INC)
348 #define TEST_pci(NAME, TYPE, SIGN, LEN, INC, EXT, RES1, RES2, RES3, RES4) \
349 void test_##NAME(void) \
354 BxW_LOAD_pci_##SIGN(result, ptr, buf, (LEN), (INC)); \
355 check(result, (RES1) | (EXT)); \
356 checkp(ptr, &buf[(1 * (INC)) % (LEN)]); \
357 BxW_LOAD_pci_##SIGN(result, ptr, buf, (LEN), (INC)); \
358 check(result, (RES2) | (EXT)); \
359 checkp(ptr, &buf[(2 * (INC)) % (LEN)]); \
360 BxW_LOAD_pci_##SIGN(result, ptr, buf, (LEN), (INC)); \
361 check(result, (RES3) | (EXT)); \
362 checkp(ptr, &buf[(3 * (INC)) % (LEN)]); \
363 BxW_LOAD_pci_##SIGN(result, ptr, buf, (LEN), (INC)); \
364 check(result, (RES4) | (EXT)); \
365 checkp(ptr, &buf[(4 * (INC)) % (LEN)]); \
368 TEST_pci(loadbzw2_pci
, int, Z
, 6, 2, 0x00000000,
369 0x00020081, 0x00040083, 0x00060085, 0x00020081)
370 TEST_pci(loadbsw2_pci
, int, S
, 6, 2, 0x0000ff00,
371 0x00020081, 0x00040083, 0x00060085, 0x00020081)
372 TEST_pci(loadbzw4_pci
, long long, Z
, 8, 4, 0x0000000000000000LL
,
373 0x0004008300020081LL
, 0x0008008700060085LL
,
374 0x0004008300020081LL
, 0x0008008700060085LL
)
375 TEST_pci(loadbsw4_pci
, long long, S
, 8, 4, 0x0000ff000000ff00LL
,
376 0x0004008300020081LL
, 0x0008008700060085LL
,
377 0x0004008300020081LL
, 0x0008008700060085LL
)
380 ****************************************************************************
381 * _pcr addressing mode (addr ++ I:circ(modifier-reg))
383 #define BxW_LOAD_pcr(SZ, RES, PTR, START, LEN, INC) \
388 "%0 = mem" #SZ "(%1++I:circ(m1))\n\t" \
389 : "=r"(RES), "+r"(PTR) \
390 : "r"((((INC) & 0x7f) << 17) | ((LEN) & 0x1ffff)), \
393 #define BxW_LOAD_pcr_Z(RES, PTR, START, LEN, INC) \
394 BxW_LOAD_pcr(ubh, RES, PTR, START, LEN, INC)
395 #define BxW_LOAD_pcr_S(RES, PTR, START, LEN, INC) \
396 BxW_LOAD_pcr(bh, RES, PTR, START, LEN, INC)
398 #define TEST_pcr(NAME, TYPE, SIGN, SIZE, LEN, INC, \
399 EXT, RES1, RES2, RES3, RES4) \
400 void test_##NAME(void) \
405 BxW_LOAD_pcr_##SIGN(result, ptr, buf, (LEN), (INC)); \
406 check(result, (RES1) | (EXT)); \
407 checkp(ptr, &buf[(1 * (INC) * (SIZE)) % (LEN)]); \
408 BxW_LOAD_pcr_##SIGN(result, ptr, buf, (LEN), (INC)); \
409 check(result, (RES2) | (EXT)); \
410 checkp(ptr, &buf[(2 * (INC) * (SIZE)) % (LEN)]); \
411 BxW_LOAD_pcr_##SIGN(result, ptr, buf, (LEN), (INC)); \
412 check(result, (RES3) | (EXT)); \
413 checkp(ptr, &buf[(3 * (INC) * (SIZE)) % (LEN)]); \
414 BxW_LOAD_pcr_##SIGN(result, ptr, buf, (LEN), (INC)); \
415 check(result, (RES4) | (EXT)); \
416 checkp(ptr, &buf[(4 * (INC) * (SIZE)) % (LEN)]); \
419 TEST_pcr(loadbzw2_pcr
, int, Z
, 2, 8, 2, 0x00000000,
420 0x00020081, 0x00060085, 0x00020081, 0x00060085)
421 TEST_pcr(loadbsw2_pcr
, int, S
, 2, 8, 2, 0x0000ff00,
422 0x00020081, 0x00060085, 0x00020081, 0x00060085)
423 TEST_pcr(loadbzw4_pcr
, long long, Z
, 4, 8, 1, 0x0000000000000000LL
,
424 0x0004008300020081LL
, 0x0008008700060085LL
,
425 0x0004008300020081LL
, 0x0008008700060085LL
)
426 TEST_pcr(loadbsw4_pcr
, long long, S
, 4, 8, 1, 0x0000ff000000ff00LL
,
427 0x0004008300020081LL
, 0x0008008700060085LL
,
428 0x0004008300020081LL
, 0x0008008700060085LL
)
472 puts(err
? "FAIL" : "PASS");