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 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 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