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 #include <stdio.h> 19 #include <string.h> 20 21 typedef unsigned char uint8_t; 22 typedef unsigned short uint16_t; 23 typedef unsigned int uint32_t; 24 25 26 static inline void S4_storerhnew_rr(void *p, int index, uint16_t v) 27 { 28 asm volatile("{\n\t" 29 " r0 = %0\n\n" 30 " memh(%1+%2<<#2) = r0.new\n\t" 31 "}\n" 32 :: "r"(v), "r"(p), "r"(index) 33 : "r0", "memory"); 34 } 35 36 static uint32_t data; 37 static inline void *S4_storerbnew_ap(uint8_t v) 38 { 39 void *ret; 40 asm volatile("{\n\t" 41 " r0 = %1\n\n" 42 " memb(%0 = ##data) = r0.new\n\t" 43 "}\n" 44 : "=r"(ret) 45 : "r"(v) 46 : "r0", "memory"); 47 return ret; 48 } 49 50 static inline void *S4_storerhnew_ap(uint16_t v) 51 { 52 void *ret; 53 asm volatile("{\n\t" 54 " r0 = %1\n\n" 55 " memh(%0 = ##data) = r0.new\n\t" 56 "}\n" 57 : "=r"(ret) 58 : "r"(v) 59 : "r0", "memory"); 60 return ret; 61 } 62 63 static inline void *S4_storerinew_ap(uint32_t v) 64 { 65 void *ret; 66 asm volatile("{\n\t" 67 " r0 = %1\n\n" 68 " memw(%0 = ##data) = r0.new\n\t" 69 "}\n" 70 : "=r"(ret) 71 : "r"(v) 72 : "r0", "memory"); 73 return ret; 74 } 75 76 static inline void S4_storeirbt_io(void *p, int pred) 77 { 78 asm volatile("p0 = cmp.eq(%0, #1)\n\t" 79 "if (p0) memb(%1+#4)=#27\n\t" 80 :: "r"(pred), "r"(p) 81 : "p0", "memory"); 82 } 83 84 static inline void S4_storeirbf_io(void *p, int pred) 85 { 86 asm volatile("p0 = cmp.eq(%0, #1)\n\t" 87 "if (!p0) memb(%1+#4)=#27\n\t" 88 :: "r"(pred), "r"(p) 89 : "p0", "memory"); 90 } 91 92 static inline void S4_storeirbtnew_io(void *p, int pred) 93 { 94 asm volatile("{\n\t" 95 " p0 = cmp.eq(%0, #1)\n\t" 96 " if (p0.new) memb(%1+#4)=#27\n\t" 97 "}\n\t" 98 :: "r"(pred), "r"(p) 99 : "p0", "memory"); 100 } 101 102 static inline void S4_storeirbfnew_io(void *p, int pred) 103 { 104 asm volatile("{\n\t" 105 " p0 = cmp.eq(%0, #1)\n\t" 106 " if (!p0.new) memb(%1+#4)=#27\n\t" 107 "}\n\t" 108 :: "r"(pred), "r"(p) 109 : "p0", "memory"); 110 } 111 112 static inline void S4_storeirht_io(void *p, int pred) 113 { 114 asm volatile("p0 = cmp.eq(%0, #1)\n\t" 115 "if (p0) memh(%1+#4)=#27\n\t" 116 :: "r"(pred), "r"(p) 117 : "p0", "memory"); 118 } 119 120 static inline void S4_storeirhf_io(void *p, int pred) 121 { 122 asm volatile("p0 = cmp.eq(%0, #1)\n\t" 123 "if (!p0) memh(%1+#4)=#27\n\t" 124 :: "r"(pred), "r"(p) 125 : "p0", "memory"); 126 } 127 128 static inline void S4_storeirhtnew_io(void *p, int pred) 129 { 130 asm volatile("{\n\t" 131 " p0 = cmp.eq(%0, #1)\n\t" 132 " if (p0.new) memh(%1+#4)=#27\n\t" 133 "}\n\t" 134 :: "r"(pred), "r"(p) 135 : "p0", "memory"); 136 } 137 138 static inline void S4_storeirhfnew_io(void *p, int pred) 139 { 140 asm volatile("{\n\t" 141 " p0 = cmp.eq(%0, #1)\n\t" 142 " if (!p0.new) memh(%1+#4)=#27\n\t" 143 "}\n\t" 144 :: "r"(pred), "r"(p) 145 : "p0", "memory"); 146 } 147 148 static inline void S4_storeirit_io(void *p, int pred) 149 { 150 asm volatile("p0 = cmp.eq(%0, #1)\n\t" 151 "if (p0) memw(%1+#4)=#27\n\t" 152 :: "r"(pred), "r"(p) 153 : "p0", "memory"); 154 } 155 156 static inline void S4_storeirif_io(void *p, int pred) 157 { 158 asm volatile("p0 = cmp.eq(%0, #1)\n\t" 159 "if (!p0) memw(%1+#4)=#27\n\t" 160 :: "r"(pred), "r"(p) 161 : "p0", "memory"); 162 } 163 164 static inline void S4_storeiritnew_io(void *p, int pred) 165 { 166 asm volatile("{\n\t" 167 " p0 = cmp.eq(%0, #1)\n\t" 168 " if (p0.new) memw(%1+#4)=#27\n\t" 169 "}\n\t" 170 :: "r"(pred), "r"(p) 171 : "p0", "memory"); 172 } 173 174 static inline void S4_storeirifnew_io(void *p, int pred) 175 { 176 asm volatile("{\n\t" 177 " p0 = cmp.eq(%0, #1)\n\t" 178 " if (!p0.new) memw(%1+#4)=#27\n\t" 179 "}\n\t" 180 :: "r"(pred), "r"(p) 181 : "p0", "memory"); 182 } 183 184 /* 185 * Test that compound-compare-jump is executed in 2 parts 186 * First we have to do all the compares in the packet and 187 * account for auto-anding. Then, we can do the predicated 188 * jump. 189 */ 190 static inline int cmpnd_cmp_jump(void) 191 { 192 int retval; 193 asm ("r5 = #7\n\t" 194 "r6 = #9\n\t" 195 "{\n\t" 196 " p0 = cmp.eq(r5, #7)\n\t" 197 " if (p0.new) jump:nt 1f\n\t" 198 " p0 = cmp.eq(r6, #7)\n\t" 199 "}\n\t" 200 "%0 = #12\n\t" 201 "jump 2f\n\t" 202 "1:\n\t" 203 "%0 = #13\n\t" 204 "2:\n\t" 205 : "=r"(retval) :: "r5", "r6", "p0"); 206 return retval; 207 } 208 209 static inline int test_clrtnew(int arg1, int old_val) 210 { 211 int ret; 212 asm volatile("r5 = %2\n\t" 213 "{\n\t" 214 "p0 = cmp.eq(%1, #1)\n\t" 215 "if (p0.new) r5=#0\n\t" 216 "}\n\t" 217 "%0 = r5\n\t" 218 : "=r"(ret) 219 : "r"(arg1), "r"(old_val) 220 : "p0", "r5"); 221 return ret; 222 } 223 224 int err; 225 226 static void check(int val, int expect) 227 { 228 if (val != expect) { 229 printf("ERROR: 0x%04x != 0x%04x\n", val, expect); 230 err++; 231 } 232 } 233 234 static void check64(long long val, long long expect) 235 { 236 if (val != expect) { 237 printf("ERROR: 0x%016llx != 0x%016llx\n", val, expect); 238 err++; 239 } 240 } 241 242 uint32_t init[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 243 uint32_t array[10]; 244 245 uint32_t early_exit; 246 247 /* 248 * Write this as a function because we can't guarantee the compiler will 249 * allocate a frame with just the SL2_return_tnew packet. 250 */ 251 static void SL2_return_tnew(int x); 252 asm ("SL2_return_tnew:\n\t" 253 " allocframe(#0)\n\t" 254 " r1 = #1\n\t" 255 " memw(##early_exit) = r1\n\t" 256 " {\n\t" 257 " p0 = cmp.eq(r0, #1)\n\t" 258 " if (p0.new) dealloc_return:nt\n\t" /* SL2_return_tnew */ 259 " }\n\t" 260 " r1 = #0\n\t" 261 " memw(##early_exit) = r1\n\t" 262 " dealloc_return\n\t" 263 ); 264 265 static long long creg_pair(int x, int y) 266 { 267 long long retval; 268 asm ("m0 = %1\n\t" 269 "m1 = %2\n\t" 270 "%0 = c7:6\n\t" 271 : "=r"(retval) : "r"(x), "r"(y) : "m0", "m1"); 272 return retval; 273 } 274 275 static long long decbin(long long x, long long y, int *pred) 276 { 277 long long retval; 278 asm ("%0 = decbin(%2, %3)\n\t" 279 "%1 = p0\n\t" 280 : "=r"(retval), "=r"(*pred) 281 : "r"(x), "r"(y)); 282 return retval; 283 } 284 285 /* Check that predicates are auto-and'ed in a packet */ 286 static int auto_and(void) 287 { 288 int retval; 289 asm ("r5 = #1\n\t" 290 "{\n\t" 291 " p0 = cmp.eq(r1, #1)\n\t" 292 " p0 = cmp.eq(r1, #2)\n\t" 293 "}\n\t" 294 "%0 = p0\n\t" 295 : "=r"(retval) 296 : 297 : "r5", "p0"); 298 return retval; 299 } 300 301 int main() 302 { 303 long long res64; 304 int pred; 305 306 memcpy(array, init, sizeof(array)); 307 S4_storerhnew_rr(array, 4, 0xffff); 308 check(array[4], 0xffff); 309 310 data = ~0; 311 check((uint32_t)S4_storerbnew_ap(0x12), (uint32_t)&data); 312 check(data, 0xffffff12); 313 314 data = ~0; 315 check((uint32_t)S4_storerhnew_ap(0x1234), (uint32_t)&data); 316 check(data, 0xffff1234); 317 318 data = ~0; 319 check((uint32_t)S4_storerinew_ap(0x12345678), (uint32_t)&data); 320 check(data, 0x12345678); 321 322 /* Byte */ 323 memcpy(array, init, sizeof(array)); 324 S4_storeirbt_io(&array[1], 1); 325 check(array[2], 27); 326 S4_storeirbt_io(&array[2], 0); 327 check(array[3], 3); 328 329 memcpy(array, init, sizeof(array)); 330 S4_storeirbf_io(&array[3], 0); 331 check(array[4], 27); 332 S4_storeirbf_io(&array[4], 1); 333 check(array[5], 5); 334 335 memcpy(array, init, sizeof(array)); 336 S4_storeirbtnew_io(&array[5], 1); 337 check(array[6], 27); 338 S4_storeirbtnew_io(&array[6], 0); 339 check(array[7], 7); 340 341 memcpy(array, init, sizeof(array)); 342 S4_storeirbfnew_io(&array[7], 0); 343 check(array[8], 27); 344 S4_storeirbfnew_io(&array[8], 1); 345 check(array[9], 9); 346 347 /* Half word */ 348 memcpy(array, init, sizeof(array)); 349 S4_storeirht_io(&array[1], 1); 350 check(array[2], 27); 351 S4_storeirht_io(&array[2], 0); 352 check(array[3], 3); 353 354 memcpy(array, init, sizeof(array)); 355 S4_storeirhf_io(&array[3], 0); 356 check(array[4], 27); 357 S4_storeirhf_io(&array[4], 1); 358 check(array[5], 5); 359 360 memcpy(array, init, sizeof(array)); 361 S4_storeirhtnew_io(&array[5], 1); 362 check(array[6], 27); 363 S4_storeirhtnew_io(&array[6], 0); 364 check(array[7], 7); 365 366 memcpy(array, init, sizeof(array)); 367 S4_storeirhfnew_io(&array[7], 0); 368 check(array[8], 27); 369 S4_storeirhfnew_io(&array[8], 1); 370 check(array[9], 9); 371 372 /* Word */ 373 memcpy(array, init, sizeof(array)); 374 S4_storeirit_io(&array[1], 1); 375 check(array[2], 27); 376 S4_storeirit_io(&array[2], 0); 377 check(array[3], 3); 378 379 memcpy(array, init, sizeof(array)); 380 S4_storeirif_io(&array[3], 0); 381 check(array[4], 27); 382 S4_storeirif_io(&array[4], 1); 383 check(array[5], 5); 384 385 memcpy(array, init, sizeof(array)); 386 S4_storeiritnew_io(&array[5], 1); 387 check(array[6], 27); 388 S4_storeiritnew_io(&array[6], 0); 389 check(array[7], 7); 390 391 memcpy(array, init, sizeof(array)); 392 S4_storeirifnew_io(&array[7], 0); 393 check(array[8], 27); 394 S4_storeirifnew_io(&array[8], 1); 395 check(array[9], 9); 396 397 int x = cmpnd_cmp_jump(); 398 check(x, 12); 399 400 SL2_return_tnew(0); 401 check(early_exit, 0); 402 SL2_return_tnew(1); 403 check(early_exit, 1); 404 405 long long pair = creg_pair(5, 7); 406 check((int)pair, 5); 407 check((int)(pair >> 32), 7); 408 409 int res = test_clrtnew(1, 7); 410 check(res, 0); 411 res = test_clrtnew(2, 7); 412 check(res, 7); 413 414 res64 = decbin(0xf0f1f2f3f4f5f6f7LL, 0x7f6f5f4f3f2f1f0fLL, &pred); 415 check64(res64, 0x357980003700010cLL); 416 check(pred, 0); 417 418 res64 = decbin(0xfLL, 0x1bLL, &pred); 419 check64(res64, 0x78000100LL); 420 check(pred, 1); 421 422 res = auto_and(); 423 check(res, 0); 424 425 puts(err ? "FAIL" : "PASS"); 426 return err; 427 } 428