1 /* 2 * Copyright(c) 2019-2022 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 20 /* 21 * Make sure that the :mem_noshuf packet attribute is honored. 22 * This is important when the addresses overlap. 23 * The store instruction in slot 1 effectively executes first, 24 * followed by the load instruction in slot 0. 25 */ 26 27 #define MEM_NOSHUF32(NAME, ST_TYPE, LD_TYPE, ST_OP, LD_OP) \ 28 static inline unsigned int NAME(ST_TYPE * p, LD_TYPE * q, ST_TYPE x) \ 29 { \ 30 unsigned int ret; \ 31 asm volatile("{\n\t" \ 32 " " #ST_OP "(%1) = %3\n\t" \ 33 " %0 = " #LD_OP "(%2)\n\t" \ 34 "}:mem_noshuf\n" \ 35 : "=r"(ret) \ 36 : "r"(p), "r"(q), "r"(x) \ 37 : "memory"); \ 38 return ret; \ 39 } 40 41 #define MEM_NOSHUF64(NAME, ST_TYPE, LD_TYPE, ST_OP, LD_OP) \ 42 static inline unsigned long long NAME(ST_TYPE * p, LD_TYPE * q, ST_TYPE x) \ 43 { \ 44 unsigned long long ret; \ 45 asm volatile("{\n\t" \ 46 " " #ST_OP "(%1) = %3\n\t" \ 47 " %0 = " #LD_OP "(%2)\n\t" \ 48 "}:mem_noshuf\n" \ 49 : "=r"(ret) \ 50 : "r"(p), "r"(q), "r"(x) \ 51 : "memory"); \ 52 return ret; \ 53 } 54 55 /* Store byte combinations */ 56 MEM_NOSHUF32(mem_noshuf_sb_lb, signed char, signed char, memb, memb) 57 MEM_NOSHUF32(mem_noshuf_sb_lub, signed char, unsigned char, memb, memub) 58 MEM_NOSHUF32(mem_noshuf_sb_lh, signed char, signed short, memb, memh) 59 MEM_NOSHUF32(mem_noshuf_sb_luh, signed char, unsigned short, memb, memuh) 60 MEM_NOSHUF32(mem_noshuf_sb_lw, signed char, signed int, memb, memw) 61 MEM_NOSHUF64(mem_noshuf_sb_ld, signed char, signed long long, memb, memd) 62 63 /* Store half combinations */ 64 MEM_NOSHUF32(mem_noshuf_sh_lb, signed short, signed char, memh, memb) 65 MEM_NOSHUF32(mem_noshuf_sh_lub, signed short, unsigned char, memh, memub) 66 MEM_NOSHUF32(mem_noshuf_sh_lh, signed short, signed short, memh, memh) 67 MEM_NOSHUF32(mem_noshuf_sh_luh, signed short, unsigned short, memh, memuh) 68 MEM_NOSHUF32(mem_noshuf_sh_lw, signed short, signed int, memh, memw) 69 MEM_NOSHUF64(mem_noshuf_sh_ld, signed short, signed long long, memh, memd) 70 71 /* Store word combinations */ 72 MEM_NOSHUF32(mem_noshuf_sw_lb, signed int, signed char, memw, memb) 73 MEM_NOSHUF32(mem_noshuf_sw_lub, signed int, unsigned char, memw, memub) 74 MEM_NOSHUF32(mem_noshuf_sw_lh, signed int, signed short, memw, memh) 75 MEM_NOSHUF32(mem_noshuf_sw_luh, signed int, unsigned short, memw, memuh) 76 MEM_NOSHUF32(mem_noshuf_sw_lw, signed int, signed int, memw, memw) 77 MEM_NOSHUF64(mem_noshuf_sw_ld, signed int, signed long long, memw, memd) 78 79 /* Store double combinations */ 80 MEM_NOSHUF32(mem_noshuf_sd_lb, long long, signed char, memd, memb) 81 MEM_NOSHUF32(mem_noshuf_sd_lub, long long, unsigned char, memd, memub) 82 MEM_NOSHUF32(mem_noshuf_sd_lh, long long, signed short, memd, memh) 83 MEM_NOSHUF32(mem_noshuf_sd_luh, long long, unsigned short, memd, memuh) 84 MEM_NOSHUF32(mem_noshuf_sd_lw, long long, signed int, memd, memw) 85 MEM_NOSHUF64(mem_noshuf_sd_ld, long long, signed long long, memd, memd) 86 87 static inline int pred_lw_sw(int pred, int *p, int *q, int x, int y) 88 { 89 int ret; 90 asm volatile("p0 = cmp.eq(%5, #0)\n\t" 91 "%0 = %3\n\t" 92 "{\n\t" 93 " memw(%1) = %4\n\t" 94 " if (!p0) %0 = memw(%2)\n\t" 95 "}:mem_noshuf\n" 96 : "=&r"(ret) 97 : "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred) 98 : "p0", "memory"); 99 return ret; 100 } 101 102 static inline int pred_lw_sw_pi(int pred, int *p, int *q, int x, int y) 103 { 104 int ret; 105 asm volatile("p0 = cmp.eq(%5, #0)\n\t" 106 "%0 = %3\n\t" 107 "r7 = %2\n\t" 108 "{\n\t" 109 " memw(%1) = %4\n\t" 110 " if (!p0) %0 = memw(r7++#4)\n\t" 111 "}:mem_noshuf\n" 112 : "=&r"(ret) 113 : "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred) 114 : "r7", "p0", "memory"); 115 return ret; 116 } 117 118 static inline long long pred_ld_sd(int pred, long long *p, long long *q, 119 long long x, long long y) 120 { 121 unsigned long long ret; 122 asm volatile("p0 = cmp.eq(%5, #0)\n\t" 123 "%0 = %3\n\t" 124 "{\n\t" 125 " memd(%1) = %4\n\t" 126 " if (!p0) %0 = memd(%2)\n\t" 127 "}:mem_noshuf\n" 128 : "=&r"(ret) 129 : "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred) 130 : "p0", "memory"); 131 return ret; 132 } 133 134 static inline long long pred_ld_sd_pi(int pred, long long *p, long long *q, 135 long long x, long long y) 136 { 137 long long ret; 138 asm volatile("p0 = cmp.eq(%5, #0)\n\t" 139 "%0 = %3\n\t" 140 "r7 = %2\n\t" 141 "{\n\t" 142 " memd(%1) = %4\n\t" 143 " if (!p0) %0 = memd(r7++#8)\n\t" 144 "}:mem_noshuf\n" 145 : "=&r"(ret) 146 : "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred) 147 : "p0", "memory"); 148 return ret; 149 } 150 151 static inline unsigned int cancel_sw_lb(int pred, int *p, signed char *q, int x) 152 { 153 unsigned int ret; 154 asm volatile("p0 = cmp.eq(%4, #0)\n\t" 155 "{\n\t" 156 " if (!p0) memw(%1) = %3\n\t" 157 " %0 = memb(%2)\n\t" 158 "}:mem_noshuf\n" 159 : "=r"(ret) 160 : "r"(p), "r"(q), "r"(x), "r"(pred) 161 : "p0", "memory"); 162 return ret; 163 } 164 165 static inline 166 unsigned long long cancel_sw_ld(int pred, int *p, long long *q, int x) 167 { 168 long long ret; 169 asm volatile("p0 = cmp.eq(%4, #0)\n\t" 170 "{\n\t" 171 " if (!p0) memw(%1) = %3\n\t" 172 " %0 = memd(%2)\n\t" 173 "}:mem_noshuf\n" 174 : "=r"(ret) 175 : "r"(p), "r"(q), "r"(x), "r"(pred) 176 : "p0", "memory"); 177 return ret; 178 } 179 180 typedef union { 181 signed long long d[2]; 182 unsigned long long ud[2]; 183 signed int w[4]; 184 unsigned int uw[4]; 185 signed short h[8]; 186 unsigned short uh[8]; 187 signed char b[16]; 188 unsigned char ub[16]; 189 } Memory; 190 191 int err; 192 193 #define check32(n, expect) check32_(n, expect, __LINE__) 194 195 static void check32_(int n, int expect, int line) 196 { 197 if (n != expect) { 198 printf("ERROR: 0x%08x != 0x%08x, line %d\n", n, expect, line); 199 err++; 200 } 201 } 202 203 #define check64(n, expect) check64_(n, expect, __LINE__) 204 205 static void check64_(long long n, long long expect, int line) 206 { 207 if (n != expect) { 208 printf("ERROR: 0x%08llx != 0x%08llx, line %d\n", n, expect, line); 209 err++; 210 } 211 } 212 213 int main() 214 { 215 Memory n; 216 unsigned int res32; 217 unsigned long long res64; 218 219 /* 220 * Store byte combinations 221 */ 222 n.w[0] = ~0; 223 res32 = mem_noshuf_sb_lb(&n.b[0], &n.b[0], 0x87); 224 check32(res32, 0xffffff87); 225 226 n.w[0] = ~0; 227 res32 = mem_noshuf_sb_lub(&n.b[0], &n.ub[0], 0x87); 228 check32(res32, 0x00000087); 229 230 n.w[0] = ~0; 231 res32 = mem_noshuf_sb_lh(&n.b[0], &n.h[0], 0x87); 232 check32(res32, 0xffffff87); 233 234 n.w[0] = ~0; 235 res32 = mem_noshuf_sb_luh(&n.b[0], &n.uh[0], 0x87); 236 check32(res32, 0x0000ff87); 237 238 n.w[0] = ~0; 239 res32 = mem_noshuf_sb_lw(&n.b[0], &n.w[0], 0x87); 240 check32(res32, 0xffffff87); 241 242 n.d[0] = ~0LL; 243 res64 = mem_noshuf_sb_ld(&n.b[0], &n.d[0], 0x87); 244 check64(res64, 0xffffffffffffff87LL); 245 246 /* 247 * Store half combinations 248 */ 249 n.w[0] = ~0; 250 res32 = mem_noshuf_sh_lb(&n.h[0], &n.b[0], 0x8787); 251 check32(res32, 0xffffff87); 252 253 n.w[0] = ~0; 254 res32 = mem_noshuf_sh_lub(&n.h[0], &n.ub[1], 0x8f87); 255 check32(res32, 0x0000008f); 256 257 n.w[0] = ~0; 258 res32 = mem_noshuf_sh_lh(&n.h[0], &n.h[0], 0x8a87); 259 check32(res32, 0xffff8a87); 260 261 n.w[0] = ~0; 262 res32 = mem_noshuf_sh_luh(&n.h[0], &n.uh[0], 0x8a87); 263 check32(res32, 0x8a87); 264 265 n.w[0] = ~0; 266 res32 = mem_noshuf_sh_lw(&n.h[1], &n.w[0], 0x8a87); 267 check32(res32, 0x8a87ffff); 268 269 n.w[0] = ~0; 270 res64 = mem_noshuf_sh_ld(&n.h[1], &n.d[0], 0x8a87); 271 check64(res64, 0xffffffff8a87ffffLL); 272 273 /* 274 * Store word combinations 275 */ 276 n.w[0] = ~0; 277 res32 = mem_noshuf_sw_lb(&n.w[0], &n.b[0], 0x12345687); 278 check32(res32, 0xffffff87); 279 280 n.w[0] = ~0; 281 res32 = mem_noshuf_sw_lub(&n.w[0], &n.ub[0], 0x12345687); 282 check32(res32, 0x00000087); 283 284 n.w[0] = ~0; 285 res32 = mem_noshuf_sw_lh(&n.w[0], &n.h[0], 0x1234f678); 286 check32(res32, 0xfffff678); 287 288 n.w[0] = ~0; 289 res32 = mem_noshuf_sw_luh(&n.w[0], &n.uh[0], 0x12345678); 290 check32(res32, 0x00005678); 291 292 n.w[0] = ~0; 293 res32 = mem_noshuf_sw_lw(&n.w[0], &n.w[0], 0x12345678); 294 check32(res32, 0x12345678); 295 296 n.d[0] = ~0LL; 297 res64 = mem_noshuf_sw_ld(&n.w[0], &n.d[0], 0x12345678); 298 check64(res64, 0xffffffff12345678LL); 299 300 /* 301 * Store double combinations 302 */ 303 n.d[0] = ~0LL; 304 res32 = mem_noshuf_sd_lb(&n.d[0], &n.b[1], 0x123456789abcdef0); 305 check32(res32, 0xffffffde); 306 307 n.d[0] = ~0LL; 308 res32 = mem_noshuf_sd_lub(&n.d[0], &n.ub[1], 0x123456789abcdef0); 309 check32(res32, 0x000000de); 310 311 n.d[0] = ~0LL; 312 res32 = mem_noshuf_sd_lh(&n.d[0], &n.h[1], 0x123456789abcdef0); 313 check32(res32, 0xffff9abc); 314 315 n.d[0] = ~0LL; 316 res32 = mem_noshuf_sd_luh(&n.d[0], &n.uh[1], 0x123456789abcdef0); 317 check32(res32, 0x00009abc); 318 319 n.d[0] = ~0LL; 320 res32 = mem_noshuf_sd_lw(&n.d[0], &n.w[1], 0x123456789abcdef0); 321 check32(res32, 0x12345678); 322 323 n.d[0] = ~0LL; 324 res64 = mem_noshuf_sd_ld(&n.d[0], &n.d[0], 0x123456789abcdef0); 325 check64(res64, 0x123456789abcdef0LL); 326 327 /* 328 * Predicated word stores 329 */ 330 n.w[0] = ~0; 331 res32 = cancel_sw_lb(0, &n.w[0], &n.b[0], 0x12345678); 332 check32(res32, 0xffffffff); 333 334 n.w[0] = ~0; 335 res32 = cancel_sw_lb(1, &n.w[0], &n.b[0], 0x12345687); 336 check32(res32, 0xffffff87); 337 338 /* 339 * Predicated double stores 340 */ 341 n.d[0] = ~0LL; 342 res64 = cancel_sw_ld(0, &n.w[0], &n.d[0], 0x12345678); 343 check64(res64, 0xffffffffffffffffLL); 344 345 n.d[0] = ~0LL; 346 res64 = cancel_sw_ld(1, &n.w[0], &n.d[0], 0x12345678); 347 check64(res64, 0xffffffff12345678LL); 348 349 n.d[0] = ~0LL; 350 res64 = cancel_sw_ld(0, &n.w[1], &n.d[0], 0x12345678); 351 check64(res64, 0xffffffffffffffffLL); 352 353 n.d[0] = ~0LL; 354 res64 = cancel_sw_ld(1, &n.w[1], &n.d[0], 0x12345678); 355 check64(res64, 0x12345678ffffffffLL); 356 357 /* 358 * No overlap tests 359 */ 360 n.w[0] = ~0; 361 res32 = mem_noshuf_sb_lb(&n.b[1], &n.b[0], 0x87); 362 check32(res32, 0xffffffff); 363 364 n.w[0] = ~0; 365 res32 = mem_noshuf_sb_lb(&n.b[0], &n.b[1], 0x87); 366 check32(res32, 0xffffffff); 367 368 n.w[0] = ~0; 369 res32 = mem_noshuf_sh_lh(&n.h[1], &n.h[0], 0x8787); 370 check32(res32, 0xffffffff); 371 372 n.w[0] = ~0; 373 res32 = mem_noshuf_sh_lh(&n.h[0], &n.h[1], 0x8787); 374 check32(res32, 0xffffffff); 375 376 n.d[0] = ~0LL; 377 res32 = mem_noshuf_sw_lw(&n.w[0], &n.w[1], 0x12345678); 378 check32(res32, 0xffffffff); 379 380 n.d[0] = ~0LL; 381 res32 = mem_noshuf_sw_lw(&n.w[1], &n.w[0], 0x12345678); 382 check32(res32, 0xffffffff); 383 384 n.d[0] = ~0LL; 385 n.d[1] = ~0LL; 386 res64 = mem_noshuf_sd_ld(&n.d[1], &n.d[0], 0x123456789abcdef0LL); 387 check64(res64, 0xffffffffffffffffLL); 388 389 n.d[0] = ~0LL; 390 n.d[1] = ~0LL; 391 res64 = mem_noshuf_sd_ld(&n.d[0], &n.d[1], 0x123456789abcdef0LL); 392 check64(res64, 0xffffffffffffffffLL); 393 394 n.w[0] = ~0; 395 res32 = pred_lw_sw(0, &n.w[0], &n.w[0], 0x12345678, 0xc0ffeeda); 396 check32(res32, 0x12345678); 397 check32(n.w[0], 0xc0ffeeda); 398 399 n.w[0] = ~0; 400 res32 = pred_lw_sw(1, &n.w[0], &n.w[0], 0x12345678, 0xc0ffeeda); 401 check32(res32, 0xc0ffeeda); 402 check32(n.w[0], 0xc0ffeeda); 403 404 n.w[0] = ~0; 405 res32 = pred_lw_sw_pi(0, &n.w[0], &n.w[0], 0x12345678, 0xc0ffeeda); 406 check32(res32, 0x12345678); 407 check32(n.w[0], 0xc0ffeeda); 408 409 n.w[0] = ~0; 410 res32 = pred_lw_sw_pi(1, &n.w[0], &n.w[0], 0x12345678, 0xc0ffeeda); 411 check32(res32, 0xc0ffeeda); 412 check32(n.w[0], 0xc0ffeeda); 413 414 n.d[0] = ~0LL; 415 res64 = pred_ld_sd(0, &n.d[0], &n.d[0], 416 0x1234567812345678LL, 0xc0ffeedac0ffeedaLL); 417 check64(res64, 0x1234567812345678LL); 418 check64(n.d[0], 0xc0ffeedac0ffeedaLL); 419 420 n.d[0] = ~0LL; 421 res64 = pred_ld_sd(1, &n.d[0], &n.d[0], 422 0x1234567812345678LL, 0xc0ffeedac0ffeedaLL); 423 check64(res64, 0xc0ffeedac0ffeedaLL); 424 check64(n.d[0], 0xc0ffeedac0ffeedaLL); 425 426 n.d[0] = ~0LL; 427 res64 = pred_ld_sd_pi(0, &n.d[0], &n.d[0], 428 0x1234567812345678LL, 0xc0ffeedac0ffeedaLL); 429 check64(res64, 0x1234567812345678LL); 430 check64(n.d[0], 0xc0ffeedac0ffeedaLL); 431 432 n.d[0] = ~0LL; 433 res64 = pred_ld_sd_pi(1, &n.d[0], &n.d[0], 434 0x1234567812345678LL, 0xc0ffeedac0ffeedaLL); 435 check64(res64, 0xc0ffeedac0ffeedaLL); 436 check64(n.d[0], 0xc0ffeedac0ffeedaLL); 437 438 puts(err ? "FAIL" : "PASS"); 439 return err; 440 } 441