qemu

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

misc.c (11938B)


      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 static int L2_ploadrifnew_pi(void *p, int pred)
    185 {
    186   int result;
    187   asm volatile("%0 = #31\n\t"
    188                "{\n\t"
    189                "    p0 = cmp.eq(%1, #1)\n\t"
    190                "    if (!p0.new) %0 = memw(%2++#4)\n\t"
    191                "}\n\t"
    192                : "=r"(result) : "r"(pred), "r"(p)
    193                : "p0");
    194   return result;
    195 }
    196 
    197 /*
    198  * Test that compound-compare-jump is executed in 2 parts
    199  * First we have to do all the compares in the packet and
    200  * account for auto-anding.  Then, we can do the predicated
    201  * jump.
    202  */
    203 static inline int cmpnd_cmp_jump(void)
    204 {
    205     int retval;
    206     asm ("r5 = #7\n\t"
    207          "r6 = #9\n\t"
    208          "{\n\t"
    209          "    p0 = cmp.eq(r5, #7)\n\t"
    210          "    if (p0.new) jump:nt 1f\n\t"
    211          "    p0 = cmp.eq(r6, #7)\n\t"
    212          "}\n\t"
    213          "%0 = #12\n\t"
    214          "jump 2f\n\t"
    215          "1:\n\t"
    216          "%0 = #13\n\t"
    217          "2:\n\t"
    218          : "=r"(retval) :: "r5", "r6", "p0");
    219     return retval;
    220 }
    221 
    222 static inline int test_clrtnew(int arg1, int old_val)
    223 {
    224   int ret;
    225   asm volatile("r5 = %2\n\t"
    226                "{\n\t"
    227                    "p0 = cmp.eq(%1, #1)\n\t"
    228                    "if (p0.new) r5=#0\n\t"
    229                "}\n\t"
    230                "%0 = r5\n\t"
    231                : "=r"(ret)
    232                : "r"(arg1), "r"(old_val)
    233                : "p0", "r5");
    234   return ret;
    235 }
    236 
    237 int err;
    238 
    239 static void check(int val, int expect)
    240 {
    241     if (val != expect) {
    242         printf("ERROR: 0x%04x != 0x%04x\n", val, expect);
    243         err++;
    244     }
    245 }
    246 
    247 static void check64(long long val, long long expect)
    248 {
    249     if (val != expect) {
    250         printf("ERROR: 0x%016llx != 0x%016llx\n", val, expect);
    251         err++;
    252     }
    253 }
    254 
    255 uint32_t init[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    256 uint32_t array[10];
    257 
    258 uint32_t early_exit;
    259 
    260 /*
    261  * Write this as a function because we can't guarantee the compiler will
    262  * allocate a frame with just the SL2_return_tnew packet.
    263  */
    264 static void SL2_return_tnew(int x);
    265 asm ("SL2_return_tnew:\n\t"
    266      "   allocframe(#0)\n\t"
    267      "   r1 = #1\n\t"
    268      "   memw(##early_exit) = r1\n\t"
    269      "   {\n\t"
    270      "       p0 = cmp.eq(r0, #1)\n\t"
    271      "       if (p0.new) dealloc_return:nt\n\t"    /* SL2_return_tnew */
    272      "   }\n\t"
    273      "   r1 = #0\n\t"
    274      "   memw(##early_exit) = r1\n\t"
    275      "   dealloc_return\n\t"
    276     );
    277 
    278 static long long creg_pair(int x, int y)
    279 {
    280     long long retval;
    281     asm ("m0 = %1\n\t"
    282          "m1 = %2\n\t"
    283          "%0 = c7:6\n\t"
    284          : "=r"(retval) : "r"(x), "r"(y) : "m0", "m1");
    285     return retval;
    286 }
    287 
    288 static long long decbin(long long x, long long y, int *pred)
    289 {
    290     long long retval;
    291     asm ("%0 = decbin(%2, %3)\n\t"
    292          "%1 = p0\n\t"
    293          : "=r"(retval), "=r"(*pred)
    294          : "r"(x), "r"(y));
    295     return retval;
    296 }
    297 
    298 /* Check that predicates are auto-and'ed in a packet */
    299 static int auto_and(void)
    300 {
    301     int retval;
    302     asm ("r5 = #1\n\t"
    303          "{\n\t"
    304          "    p0 = cmp.eq(r1, #1)\n\t"
    305          "    p0 = cmp.eq(r1, #2)\n\t"
    306          "}\n\t"
    307          "%0 = p0\n\t"
    308          : "=r"(retval)
    309          :
    310          : "r5", "p0");
    311     return retval;
    312 }
    313 
    314 void test_lsbnew(void)
    315 {
    316     int result;
    317 
    318     asm("r0 = #2\n\t"
    319         "r1 = #5\n\t"
    320         "{\n\t"
    321         "    p0 = r0\n\t"
    322         "    if (p0.new) r1 = #3\n\t"
    323         "}\n\t"
    324         "%0 = r1\n\t"
    325         : "=r"(result) :: "r0", "r1", "p0");
    326     check(result, 5);
    327 }
    328 
    329 void test_l2fetch(void)
    330 {
    331     /* These don't do anything in qemu, just make sure they don't assert */
    332     asm volatile ("l2fetch(r0, r1)\n\t"
    333                   "l2fetch(r0, r3:2)\n\t");
    334 }
    335 
    336 int main()
    337 {
    338     int res;
    339     long long res64;
    340     int pred;
    341 
    342     memcpy(array, init, sizeof(array));
    343     S4_storerhnew_rr(array, 4, 0xffff);
    344     check(array[4], 0xffff);
    345 
    346     data = ~0;
    347     check((uint32_t)S4_storerbnew_ap(0x12), (uint32_t)&data);
    348     check(data, 0xffffff12);
    349 
    350     data = ~0;
    351     check((uint32_t)S4_storerhnew_ap(0x1234), (uint32_t)&data);
    352     check(data, 0xffff1234);
    353 
    354     data = ~0;
    355     check((uint32_t)S4_storerinew_ap(0x12345678), (uint32_t)&data);
    356     check(data, 0x12345678);
    357 
    358     /* Byte */
    359     memcpy(array, init, sizeof(array));
    360     S4_storeirbt_io(&array[1], 1);
    361     check(array[2], 27);
    362     S4_storeirbt_io(&array[2], 0);
    363     check(array[3], 3);
    364 
    365     memcpy(array, init, sizeof(array));
    366     S4_storeirbf_io(&array[3], 0);
    367     check(array[4], 27);
    368     S4_storeirbf_io(&array[4], 1);
    369     check(array[5], 5);
    370 
    371     memcpy(array, init, sizeof(array));
    372     S4_storeirbtnew_io(&array[5], 1);
    373     check(array[6], 27);
    374     S4_storeirbtnew_io(&array[6], 0);
    375     check(array[7], 7);
    376 
    377     memcpy(array, init, sizeof(array));
    378     S4_storeirbfnew_io(&array[7], 0);
    379     check(array[8], 27);
    380     S4_storeirbfnew_io(&array[8], 1);
    381     check(array[9], 9);
    382 
    383     /* Half word */
    384     memcpy(array, init, sizeof(array));
    385     S4_storeirht_io(&array[1], 1);
    386     check(array[2], 27);
    387     S4_storeirht_io(&array[2], 0);
    388     check(array[3], 3);
    389 
    390     memcpy(array, init, sizeof(array));
    391     S4_storeirhf_io(&array[3], 0);
    392     check(array[4], 27);
    393     S4_storeirhf_io(&array[4], 1);
    394     check(array[5], 5);
    395 
    396     memcpy(array, init, sizeof(array));
    397     S4_storeirhtnew_io(&array[5], 1);
    398     check(array[6], 27);
    399     S4_storeirhtnew_io(&array[6], 0);
    400     check(array[7], 7);
    401 
    402     memcpy(array, init, sizeof(array));
    403     S4_storeirhfnew_io(&array[7], 0);
    404     check(array[8], 27);
    405     S4_storeirhfnew_io(&array[8], 1);
    406     check(array[9], 9);
    407 
    408     /* Word */
    409     memcpy(array, init, sizeof(array));
    410     S4_storeirit_io(&array[1], 1);
    411     check(array[2], 27);
    412     S4_storeirit_io(&array[2], 0);
    413     check(array[3], 3);
    414 
    415     memcpy(array, init, sizeof(array));
    416     S4_storeirif_io(&array[3], 0);
    417     check(array[4], 27);
    418     S4_storeirif_io(&array[4], 1);
    419     check(array[5], 5);
    420 
    421     memcpy(array, init, sizeof(array));
    422     S4_storeiritnew_io(&array[5], 1);
    423     check(array[6], 27);
    424     S4_storeiritnew_io(&array[6], 0);
    425     check(array[7], 7);
    426 
    427     memcpy(array, init, sizeof(array));
    428     S4_storeirifnew_io(&array[7], 0);
    429     check(array[8], 27);
    430     S4_storeirifnew_io(&array[8], 1);
    431     check(array[9], 9);
    432 
    433     memcpy(array, init, sizeof(array));
    434     res = L2_ploadrifnew_pi(&array[6], 0);
    435     check(res, 6);
    436     res = L2_ploadrifnew_pi(&array[7], 1);
    437     check(res, 31);
    438 
    439     int x = cmpnd_cmp_jump();
    440     check(x, 12);
    441 
    442     SL2_return_tnew(0);
    443     check(early_exit, 0);
    444     SL2_return_tnew(1);
    445     check(early_exit, 1);
    446 
    447     long long pair = creg_pair(5, 7);
    448     check((int)pair, 5);
    449     check((int)(pair >> 32), 7);
    450 
    451     res = test_clrtnew(1, 7);
    452     check(res, 0);
    453     res = test_clrtnew(2, 7);
    454     check(res, 7);
    455 
    456     res64 = decbin(0xf0f1f2f3f4f5f6f7LL, 0x7f6f5f4f3f2f1f0fLL, &pred);
    457     check64(res64, 0x357980003700010cLL);
    458     check(pred, 0);
    459 
    460     res64 = decbin(0xfLL, 0x1bLL, &pred);
    461     check64(res64, 0x78000100LL);
    462     check(pred, 1);
    463 
    464     res = auto_and();
    465     check(res, 0);
    466 
    467     test_lsbnew();
    468 
    469     test_l2fetch();
    470 
    471     puts(err ? "FAIL" : "PASS");
    472     return err;
    473 }