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 /* 19 * Test load align instructions 20 * 21 * Example 22 * r1:0 = memh_fifo(r1+#0) 23 * loads a half word from memory, shifts the destination register 24 * right by one half word and inserts the loaded value into the high 25 * half word of the destination. 26 * 27 * There are 8 addressing modes and byte and half word variants, for a 28 * total of 16 instructions to test 29 */ 30 31 #include <stdio.h> 32 #include <string.h> 33 34 int err; 35 36 char buf[16] __attribute__((aligned(1 << 16))); 37 38 void init_buf(void) 39 { 40 int i; 41 for (i = 0; i < 16; i++) { 42 buf[i] = i + 1; 43 } 44 } 45 46 void __check(int line, long long result, long long expect) 47 { 48 if (result != expect) { 49 printf("ERROR at line %d: 0x%016llx != 0x%016llx\n", 50 line, result, expect); 51 err++; 52 } 53 } 54 55 #define check(RES, EXP) __check(__LINE__, RES, EXP) 56 57 void __checkp(int line, void *p, void *expect) 58 { 59 if (p != expect) { 60 printf("ERROR at line %d: 0x%p != 0x%p\n", line, p, expect); 61 err++; 62 } 63 } 64 65 #define checkp(RES, EXP) __checkp(__LINE__, RES, EXP) 66 67 /* 68 **************************************************************************** 69 * _io addressing mode (addr + offset) 70 */ 71 #define LOAD_io(SZ, RES, ADDR, OFF) \ 72 __asm__( \ 73 "%0 = mem" #SZ "_fifo(%1+#" #OFF ")\n\t" \ 74 : "+r"(RES) \ 75 : "r"(ADDR)) 76 #define LOAD_io_b(RES, ADDR, OFF) \ 77 LOAD_io(b, RES, ADDR, OFF) 78 #define LOAD_io_h(RES, ADDR, OFF) \ 79 LOAD_io(h, RES, ADDR, OFF) 80 81 #define TEST_io(NAME, SZ, SIZE, EXP1, EXP2, EXP3, EXP4) \ 82 void test_##NAME(void) \ 83 { \ 84 long long result = ~0LL; \ 85 LOAD_io_##SZ(result, buf, 0 * (SIZE)); \ 86 check(result, (EXP1)); \ 87 LOAD_io_##SZ(result, buf, 1 * (SIZE)); \ 88 check(result, (EXP2)); \ 89 LOAD_io_##SZ(result, buf, 2 * (SIZE)); \ 90 check(result, (EXP3)); \ 91 LOAD_io_##SZ(result, buf, 3 * (SIZE)); \ 92 check(result, (EXP4)); \ 93 } 94 95 TEST_io(loadalignb_io, b, 1, 96 0x01ffffffffffffffLL, 0x0201ffffffffffffLL, 97 0x030201ffffffffffLL, 0x04030201ffffffffLL) 98 TEST_io(loadalignh_io, h, 2, 99 0x0201ffffffffffffLL, 0x04030201ffffffffLL, 100 0x060504030201ffffLL, 0x0807060504030201LL) 101 102 /* 103 **************************************************************************** 104 * _ur addressing mode (index << offset + base) 105 */ 106 #define LOAD_ur(SZ, RES, SHIFT, IDX) \ 107 __asm__( \ 108 "%0 = mem" #SZ "_fifo(%1<<#" #SHIFT " + ##buf)\n\t" \ 109 : "+r"(RES) \ 110 : "r"(IDX)) 111 #define LOAD_ur_b(RES, SHIFT, IDX) \ 112 LOAD_ur(b, RES, SHIFT, IDX) 113 #define LOAD_ur_h(RES, SHIFT, IDX) \ 114 LOAD_ur(h, RES, SHIFT, IDX) 115 116 #define TEST_ur(NAME, SZ, SHIFT, RES1, RES2, RES3, RES4) \ 117 void test_##NAME(void) \ 118 { \ 119 long long result = ~0LL; \ 120 LOAD_ur_##SZ(result, (SHIFT), 0); \ 121 check(result, (RES1)); \ 122 LOAD_ur_##SZ(result, (SHIFT), 1); \ 123 check(result, (RES2)); \ 124 LOAD_ur_##SZ(result, (SHIFT), 2); \ 125 check(result, (RES3)); \ 126 LOAD_ur_##SZ(result, (SHIFT), 3); \ 127 check(result, (RES4)); \ 128 } 129 130 TEST_ur(loadalignb_ur, b, 1, 131 0x01ffffffffffffffLL, 0x0301ffffffffffffLL, 132 0x050301ffffffffffLL, 0x07050301ffffffffLL) 133 TEST_ur(loadalignh_ur, h, 1, 134 0x0201ffffffffffffLL, 0x04030201ffffffffLL, 135 0x060504030201ffffLL, 0x0807060504030201LL) 136 137 /* 138 **************************************************************************** 139 * _ap addressing mode (addr = base) 140 */ 141 #define LOAD_ap(SZ, RES, PTR, ADDR) \ 142 __asm__( \ 143 "%0 = mem" #SZ "_fifo(%1 = ##" #ADDR ")\n\t" \ 144 : "+r"(RES), "=r"(PTR)) 145 #define LOAD_ap_b(RES, PTR, ADDR) \ 146 LOAD_ap(b, RES, PTR, ADDR) 147 #define LOAD_ap_h(RES, PTR, ADDR) \ 148 LOAD_ap(h, RES, PTR, ADDR) 149 150 #define TEST_ap(NAME, SZ, SIZE, RES1, RES2, RES3, RES4) \ 151 void test_##NAME(void) \ 152 { \ 153 long long result = ~0LL; \ 154 void *ptr; \ 155 LOAD_ap_##SZ(result, ptr, (buf + 0 * (SIZE))); \ 156 check(result, (RES1)); \ 157 checkp(ptr, &buf[0 * (SIZE)]); \ 158 LOAD_ap_##SZ(result, ptr, (buf + 1 * (SIZE))); \ 159 check(result, (RES2)); \ 160 checkp(ptr, &buf[1 * (SIZE)]); \ 161 LOAD_ap_##SZ(result, ptr, (buf + 2 * (SIZE))); \ 162 check(result, (RES3)); \ 163 checkp(ptr, &buf[2 * (SIZE)]); \ 164 LOAD_ap_##SZ(result, ptr, (buf + 3 * (SIZE))); \ 165 check(result, (RES4)); \ 166 checkp(ptr, &buf[3 * (SIZE)]); \ 167 } 168 169 TEST_ap(loadalignb_ap, b, 1, 170 0x01ffffffffffffffLL, 0x0201ffffffffffffLL, 171 0x030201ffffffffffLL, 0x04030201ffffffffLL) 172 TEST_ap(loadalignh_ap, h, 2, 173 0x0201ffffffffffffLL, 0x04030201ffffffffLL, 174 0x060504030201ffffLL, 0x0807060504030201LL) 175 176 /* 177 **************************************************************************** 178 * _rp addressing mode (addr ++ modifer-reg) 179 */ 180 #define LOAD_pr(SZ, RES, PTR, INC) \ 181 __asm__( \ 182 "m0 = %2\n\t" \ 183 "%0 = mem" #SZ "_fifo(%1++m0)\n\t" \ 184 : "+r"(RES), "+r"(PTR) \ 185 : "r"(INC) \ 186 : "m0") 187 #define LOAD_pr_b(RES, PTR, INC) \ 188 LOAD_pr(b, RES, PTR, INC) 189 #define LOAD_pr_h(RES, PTR, INC) \ 190 LOAD_pr(h, RES, PTR, INC) 191 192 #define TEST_pr(NAME, SZ, SIZE, RES1, RES2, RES3, RES4) \ 193 void test_##NAME(void) \ 194 { \ 195 long long result = ~0LL; \ 196 void *ptr = buf; \ 197 LOAD_pr_##SZ(result, ptr, (SIZE)); \ 198 check(result, (RES1)); \ 199 checkp(ptr, &buf[1 * (SIZE)]); \ 200 LOAD_pr_##SZ(result, ptr, (SIZE)); \ 201 check(result, (RES2)); \ 202 checkp(ptr, &buf[2 * (SIZE)]); \ 203 LOAD_pr_##SZ(result, ptr, (SIZE)); \ 204 check(result, (RES3)); \ 205 checkp(ptr, &buf[3 * (SIZE)]); \ 206 LOAD_pr_##SZ(result, ptr, (SIZE)); \ 207 check(result, (RES4)); \ 208 checkp(ptr, &buf[4 * (SIZE)]); \ 209 } 210 211 TEST_pr(loadalignb_pr, b, 1, 212 0x01ffffffffffffffLL, 0x0201ffffffffffffLL, 213 0x030201ffffffffffLL, 0x04030201ffffffffLL) 214 TEST_pr(loadalignh_pr, h, 2, 215 0x0201ffffffffffffLL, 0x04030201ffffffffLL, 216 0x060504030201ffffLL, 0x0807060504030201LL) 217 218 /* 219 **************************************************************************** 220 * _pbr addressing mode (addr ++ modifer-reg:brev) 221 */ 222 #define LOAD_pbr(SZ, RES, PTR) \ 223 __asm__( \ 224 "r4 = #(1 << (16 - 3))\n\t" \ 225 "m0 = r4\n\t" \ 226 "%0 = mem" #SZ "_fifo(%1++m0:brev)\n\t" \ 227 : "+r"(RES), "+r"(PTR) \ 228 : \ 229 : "r4", "m0") 230 #define LOAD_pbr_b(RES, PTR) \ 231 LOAD_pbr(b, RES, PTR) 232 #define LOAD_pbr_h(RES, PTR) \ 233 LOAD_pbr(h, RES, PTR) 234 235 #define TEST_pbr(NAME, SZ, RES1, RES2, RES3, RES4) \ 236 void test_##NAME(void) \ 237 { \ 238 long long result = ~0LL; \ 239 void *ptr = buf; \ 240 LOAD_pbr_##SZ(result, ptr); \ 241 check(result, (RES1)); \ 242 LOAD_pbr_##SZ(result, ptr); \ 243 check(result, (RES2)); \ 244 LOAD_pbr_##SZ(result, ptr); \ 245 check(result, (RES3)); \ 246 LOAD_pbr_##SZ(result, ptr); \ 247 check(result, (RES4)); \ 248 } 249 250 TEST_pbr(loadalignb_pbr, b, 251 0x01ffffffffffffffLL, 0x0501ffffffffffffLL, 252 0x030501ffffffffffLL, 0x07030501ffffffffLL) 253 TEST_pbr(loadalignh_pbr, h, 254 0x0201ffffffffffffLL, 0x06050201ffffffffLL, 255 0x040306050201ffffLL, 0x0807040306050201LL) 256 257 /* 258 **************************************************************************** 259 * _pi addressing mode (addr ++ inc) 260 */ 261 #define LOAD_pi(SZ, RES, PTR, INC) \ 262 __asm__( \ 263 "%0 = mem" #SZ "_fifo(%1++#" #INC ")\n\t" \ 264 : "+r"(RES), "+r"(PTR)) 265 #define LOAD_pi_b(RES, PTR, INC) \ 266 LOAD_pi(b, RES, PTR, INC) 267 #define LOAD_pi_h(RES, PTR, INC) \ 268 LOAD_pi(h, RES, PTR, INC) 269 270 #define TEST_pi(NAME, SZ, INC, RES1, RES2, RES3, RES4) \ 271 void test_##NAME(void) \ 272 { \ 273 long long result = ~0LL; \ 274 void *ptr = buf; \ 275 LOAD_pi_##SZ(result, ptr, (INC)); \ 276 check(result, (RES1)); \ 277 checkp(ptr, &buf[1 * (INC)]); \ 278 LOAD_pi_##SZ(result, ptr, (INC)); \ 279 check(result, (RES2)); \ 280 checkp(ptr, &buf[2 * (INC)]); \ 281 LOAD_pi_##SZ(result, ptr, (INC)); \ 282 check(result, (RES3)); \ 283 checkp(ptr, &buf[3 * (INC)]); \ 284 LOAD_pi_##SZ(result, ptr, (INC)); \ 285 check(result, (RES4)); \ 286 checkp(ptr, &buf[4 * (INC)]); \ 287 } 288 289 TEST_pi(loadalignb_pi, b, 1, 290 0x01ffffffffffffffLL, 0x0201ffffffffffffLL, 291 0x030201ffffffffffLL, 0x04030201ffffffffLL) 292 TEST_pi(loadalignh_pi, h, 2, 293 0x0201ffffffffffffLL, 0x04030201ffffffffLL, 294 0x060504030201ffffLL, 0x0807060504030201LL) 295 296 /* 297 **************************************************************************** 298 * _pci addressing mode (addr ++ inc:circ) 299 */ 300 #define LOAD_pci(SZ, RES, PTR, START, LEN, INC) \ 301 __asm__( \ 302 "r4 = %3\n\t" \ 303 "m0 = r4\n\t" \ 304 "cs0 = %2\n\t" \ 305 "%0 = mem" #SZ "_fifo(%1++#" #INC ":circ(m0))\n\t" \ 306 : "+r"(RES), "+r"(PTR) \ 307 : "r"(START), "r"(LEN) \ 308 : "r4", "m0", "cs0") 309 #define LOAD_pci_b(RES, PTR, START, LEN, INC) \ 310 LOAD_pci(b, RES, PTR, START, LEN, INC) 311 #define LOAD_pci_h(RES, PTR, START, LEN, INC) \ 312 LOAD_pci(h, RES, PTR, START, LEN, INC) 313 314 #define TEST_pci(NAME, SZ, LEN, INC, RES1, RES2, RES3, RES4) \ 315 void test_##NAME(void) \ 316 { \ 317 long long result = ~0LL; \ 318 void *ptr = buf; \ 319 LOAD_pci_##SZ(result, ptr, buf, (LEN), (INC)); \ 320 check(result, (RES1)); \ 321 checkp(ptr, &buf[(1 * (INC)) % (LEN)]); \ 322 LOAD_pci_##SZ(result, ptr, buf, (LEN), (INC)); \ 323 check(result, (RES2)); \ 324 checkp(ptr, &buf[(2 * (INC)) % (LEN)]); \ 325 LOAD_pci_##SZ(result, ptr, buf, (LEN), (INC)); \ 326 check(result, (RES3)); \ 327 checkp(ptr, &buf[(3 * (INC)) % (LEN)]); \ 328 LOAD_pci_##SZ(result, ptr, buf, (LEN), (INC)); \ 329 check(result, (RES4)); \ 330 checkp(ptr, &buf[(4 * (INC)) % (LEN)]); \ 331 } 332 333 TEST_pci(loadalignb_pci, b, 2, 1, 334 0x01ffffffffffffffLL, 0x0201ffffffffffffLL, 335 0x010201ffffffffffLL, 0x02010201ffffffffLL) 336 TEST_pci(loadalignh_pci, h, 4, 2, 337 0x0201ffffffffffffLL, 0x04030201ffffffffLL, 338 0x020104030201ffffLL, 0x0403020104030201LL) 339 340 /* 341 **************************************************************************** 342 * _pcr addressing mode (addr ++ I:circ(modifier-reg)) 343 */ 344 #define LOAD_pcr(SZ, RES, PTR, START, LEN, INC) \ 345 __asm__( \ 346 "r4 = %2\n\t" \ 347 "m1 = r4\n\t" \ 348 "cs1 = %3\n\t" \ 349 "%0 = mem" #SZ "_fifo(%1++I:circ(m1))\n\t" \ 350 : "+r"(RES), "+r"(PTR) \ 351 : "r"((((INC) & 0x7f) << 17) | ((LEN) & 0x1ffff)), \ 352 "r"(START) \ 353 : "r4", "m1", "cs1") 354 #define LOAD_pcr_b(RES, PTR, START, LEN, INC) \ 355 LOAD_pcr(b, RES, PTR, START, LEN, INC) 356 #define LOAD_pcr_h(RES, PTR, START, LEN, INC) \ 357 LOAD_pcr(h, RES, PTR, START, LEN, INC) 358 359 #define TEST_pcr(NAME, SZ, SIZE, LEN, INC, RES1, RES2, RES3, RES4) \ 360 void test_##NAME(void) \ 361 { \ 362 long long result = ~0LL; \ 363 void *ptr = buf; \ 364 LOAD_pcr_##SZ(result, ptr, buf, (LEN), (INC)); \ 365 check(result, (RES1)); \ 366 checkp(ptr, &buf[(1 * (INC) * (SIZE)) % (LEN)]); \ 367 LOAD_pcr_##SZ(result, ptr, buf, (LEN), (INC)); \ 368 check(result, (RES2)); \ 369 checkp(ptr, &buf[(2 * (INC) * (SIZE)) % (LEN)]); \ 370 LOAD_pcr_##SZ(result, ptr, buf, (LEN), (INC)); \ 371 check(result, (RES3)); \ 372 checkp(ptr, &buf[(3 * (INC) * (SIZE)) % (LEN)]); \ 373 LOAD_pcr_##SZ(result, ptr, buf, (LEN), (INC)); \ 374 check(result, (RES4)); \ 375 checkp(ptr, &buf[(4 * (INC) * (SIZE)) % (LEN)]); \ 376 } 377 378 TEST_pcr(loadalignb_pcr, b, 1, 2, 1, 379 0x01ffffffffffffffLL, 0x0201ffffffffffffLL, 380 0x010201ffffffffffLL, 0x02010201ffffffffLL) 381 TEST_pcr(loadalignh_pcr, h, 2, 4, 1, 382 0x0201ffffffffffffLL, 0x04030201ffffffffLL, 383 0x020104030201ffffLL, 0x0403020104030201LL) 384 385 int main() 386 { 387 init_buf(); 388 389 test_loadalignb_io(); 390 test_loadalignh_io(); 391 392 test_loadalignb_ur(); 393 test_loadalignh_ur(); 394 395 test_loadalignb_ap(); 396 test_loadalignh_ap(); 397 398 test_loadalignb_pr(); 399 test_loadalignh_pr(); 400 401 test_loadalignb_pbr(); 402 test_loadalignh_pbr(); 403 404 test_loadalignb_pi(); 405 test_loadalignh_pi(); 406 407 test_loadalignb_pci(); 408 test_loadalignh_pci(); 409 410 test_loadalignb_pcr(); 411 test_loadalignh_pcr(); 412 413 puts(err ? "FAIL" : "PASS"); 414 return err ? 1 : 0; 415 } 416