qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

load_align.c (12559B)


      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 }