qemu/tests/tcg/hexagon/load_align.c
<<
>>
Prefs
   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
  34int err;
  35
  36char buf[16] __attribute__((aligned(1 << 16)));
  37
  38void init_buf(void)
  39{
  40    int i;
  41    for (i = 0; i < 16; i++) {
  42        buf[i] = i + 1;
  43    }
  44}
  45
  46void __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
  57void __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) \
  82void 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
  95TEST_io(loadalignb_io, b, 1,
  96        0x01ffffffffffffffLL, 0x0201ffffffffffffLL,
  97        0x030201ffffffffffLL, 0x04030201ffffffffLL)
  98TEST_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) \
 117void 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
 130TEST_ur(loadalignb_ur, b, 1,
 131        0x01ffffffffffffffLL, 0x0301ffffffffffffLL,
 132        0x050301ffffffffffLL, 0x07050301ffffffffLL)
 133TEST_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) \
 151void 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
 169TEST_ap(loadalignb_ap, b, 1,
 170        0x01ffffffffffffffLL, 0x0201ffffffffffffLL,
 171        0x030201ffffffffffLL, 0x04030201ffffffffLL)
 172TEST_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) \
 193void 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
 211TEST_pr(loadalignb_pr, b, 1,
 212        0x01ffffffffffffffLL, 0x0201ffffffffffffLL,
 213        0x030201ffffffffffLL, 0x04030201ffffffffLL)
 214TEST_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) \
 236void 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
 250TEST_pbr(loadalignb_pbr, b,
 251    0x01ffffffffffffffLL, 0x0501ffffffffffffLL,
 252    0x030501ffffffffffLL, 0x07030501ffffffffLL)
 253TEST_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) \
 271void 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
 289TEST_pi(loadalignb_pi, b, 1,
 290        0x01ffffffffffffffLL, 0x0201ffffffffffffLL,
 291        0x030201ffffffffffLL, 0x04030201ffffffffLL)
 292TEST_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) \
 315void 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
 333TEST_pci(loadalignb_pci, b, 2, 1,
 334    0x01ffffffffffffffLL, 0x0201ffffffffffffLL,
 335    0x010201ffffffffffLL, 0x02010201ffffffffLL)
 336TEST_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) \
 360void 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
 378TEST_pcr(loadalignb_pcr, b, 1, 2, 1,
 379    0x01ffffffffffffffLL, 0x0201ffffffffffffLL,
 380    0x010201ffffffffffLL, 0x02010201ffffffffLL)
 381TEST_pcr(loadalignh_pcr, h, 2, 4, 1,
 382    0x0201ffffffffffffLL, 0x04030201ffffffffLL,
 383    0x020104030201ffffLL, 0x0403020104030201LL)
 384
 385int 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