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