qemu

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

multi_result.c (7386B)


      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 
     20 static int sfrecipa(int Rs, int Rt, int *pred_result)
     21 {
     22   int result;
     23   int predval;
     24 
     25   asm volatile("%0,p0 = sfrecipa(%2, %3)\n\t"
     26                "%1 = p0\n\t"
     27                : "+r"(result), "=r"(predval)
     28                : "r"(Rs), "r"(Rt)
     29                : "p0");
     30   *pred_result = predval;
     31   return result;
     32 }
     33 
     34 static int sfinvsqrta(int Rs, int *pred_result)
     35 {
     36   int result;
     37   int predval;
     38 
     39   asm volatile("%0,p0 = sfinvsqrta(%2)\n\t"
     40                "%1 = p0\n\t"
     41                : "+r"(result), "=r"(predval)
     42                : "r"(Rs)
     43                : "p0");
     44   *pred_result = predval;
     45   return result;
     46 }
     47 
     48 static long long vacsh(long long Rxx, long long Rss, long long Rtt,
     49                        int *pred_result, int *ovf_result)
     50 {
     51   long long result = Rxx;
     52   int predval;
     53   int usr;
     54 
     55   /*
     56    * This instruction can set bit 0 (OVF/overflow) in usr
     57    * Clear the bit first, then return that bit to the caller
     58    */
     59   asm volatile("r2 = usr\n\t"
     60                "r2 = clrbit(r2, #0)\n\t"        /* clear overflow bit */
     61                "usr = r2\n\t"
     62                "%0,p0 = vacsh(%3, %4)\n\t"
     63                "%1 = p0\n\t"
     64                "%2 = usr\n\t"
     65                : "+r"(result), "=r"(predval), "=r"(usr)
     66                : "r"(Rss), "r"(Rtt)
     67                : "r2", "p0", "usr");
     68   *pred_result = predval;
     69   *ovf_result = (usr & 1);
     70   return result;
     71 }
     72 
     73 static long long vminub(long long Rtt, long long Rss,
     74                         int *pred_result)
     75 {
     76   long long result;
     77   int predval;
     78 
     79   asm volatile("%0,p0 = vminub(%2, %3)\n\t"
     80                "%1 = p0\n\t"
     81                : "=r"(result), "=r"(predval)
     82                : "r"(Rtt), "r"(Rss)
     83                : "p0");
     84   *pred_result = predval;
     85   return result;
     86 }
     87 
     88 static long long add_carry(long long Rss, long long Rtt,
     89                            int pred_in, int *pred_result)
     90 {
     91   long long result;
     92   int predval = pred_in;
     93 
     94   asm volatile("p0 = %1\n\t"
     95                "%0 = add(%2, %3, p0):carry\n\t"
     96                "%1 = p0\n\t"
     97                : "=r"(result), "+r"(predval)
     98                : "r"(Rss), "r"(Rtt)
     99                : "p0");
    100   *pred_result = predval;
    101   return result;
    102 }
    103 
    104 static long long sub_carry(long long Rss, long long Rtt,
    105                            int pred_in, int *pred_result)
    106 {
    107   long long result;
    108   int predval = pred_in;
    109 
    110   asm volatile("p0 = !cmp.eq(%1, #0)\n\t"
    111                "%0 = sub(%2, %3, p0):carry\n\t"
    112                "%1 = p0\n\t"
    113                : "=r"(result), "+r"(predval)
    114                : "r"(Rss), "r"(Rtt)
    115                : "p0");
    116   *pred_result = predval;
    117   return result;
    118 }
    119 
    120 int err;
    121 
    122 static void check_ll(long long val, long long expect)
    123 {
    124     if (val != expect) {
    125         printf("ERROR: 0x%016llx != 0x%016llx\n", val, expect);
    126         err++;
    127     }
    128 }
    129 
    130 static void check(int val, int expect)
    131 {
    132     if (val != expect) {
    133         printf("ERROR: 0x%08x != 0x%08x\n", val, expect);
    134         err++;
    135     }
    136 }
    137 
    138 static void check_p(int val, int expect)
    139 {
    140     if (val != expect) {
    141         printf("ERROR: 0x%02x != 0x%02x\n", val, expect);
    142         err++;
    143     }
    144 }
    145 
    146 static void test_sfrecipa()
    147 {
    148     int res;
    149     int pred_result;
    150 
    151     res = sfrecipa(0x04030201, 0x05060708, &pred_result);
    152     check(res, 0x59f38001);
    153     check_p(pred_result, 0x00);
    154 }
    155 
    156 static void test_sfinvsqrta()
    157 {
    158     int res;
    159     int pred_result;
    160 
    161     res = sfinvsqrta(0x04030201, &pred_result);
    162     check(res, 0x4d330000);
    163     check_p(pred_result, 0xe0);
    164 
    165     res = sfinvsqrta(0x0, &pred_result);
    166     check(res, 0x3f800000);
    167     check_p(pred_result, 0x0);
    168 }
    169 
    170 static void test_vacsh()
    171 {
    172     long long res64;
    173     int pred_result;
    174     int ovf_result;
    175 
    176     res64 = vacsh(0x0004000300020001LL,
    177                   0x0001000200030004LL,
    178                   0x0000000000000000LL, &pred_result, &ovf_result);
    179     check_ll(res64, 0x0004000300030004LL);
    180     check_p(pred_result, 0xf0);
    181     check(ovf_result, 0);
    182 
    183     res64 = vacsh(0x0004000300020001LL,
    184                   0x0001000200030004LL,
    185                   0x000affff000d0000LL, &pred_result, &ovf_result);
    186     check_ll(res64, 0x000e0003000f0004LL);
    187     check_p(pred_result, 0xcc);
    188     check(ovf_result, 0);
    189 
    190     res64 = vacsh(0x00047fff00020001LL,
    191                   0x00017fff00030004LL,
    192                   0x000a0fff000d0000LL, &pred_result, &ovf_result);
    193     check_ll(res64, 0x000e7fff000f0004LL);
    194     check_p(pred_result, 0xfc);
    195     check(ovf_result, 1);
    196 
    197     res64 = vacsh(0x0004000300020001LL,
    198                   0x0001000200030009LL,
    199                   0x000affff000d0001LL, &pred_result, &ovf_result);
    200     check_ll(res64, 0x000e0003000f0008LL);
    201     check_p(pred_result, 0xcc);
    202     check(ovf_result, 0);
    203 }
    204 
    205 static void test_vminub()
    206 {
    207     long long res64;
    208     int pred_result;
    209 
    210     res64 = vminub(0x0807060504030201LL,
    211                    0x0102030405060708LL,
    212                    &pred_result);
    213     check_ll(res64, 0x0102030404030201LL);
    214     check_p(pred_result, 0xf0);
    215 
    216     res64 = vminub(0x0802060405030701LL,
    217                    0x0107030504060208LL,
    218                    &pred_result);
    219     check_ll(res64, 0x0102030404030201LL);
    220     check_p(pred_result, 0xaa);
    221 }
    222 
    223 static void test_add_carry()
    224 {
    225     long long res64;
    226     int pred_result;
    227 
    228     res64 = add_carry(0x0000000000000000LL,
    229                       0xffffffffffffffffLL,
    230                       1, &pred_result);
    231     check_ll(res64, 0x0000000000000000LL);
    232     check_p(pred_result, 0xff);
    233 
    234     res64 = add_carry(0x0000000100000000LL,
    235                       0xffffffffffffffffLL,
    236                       0, &pred_result);
    237     check_ll(res64, 0x00000000ffffffffLL);
    238     check_p(pred_result, 0xff);
    239 
    240     res64 = add_carry(0x0000000100000000LL,
    241                       0xffffffffffffffffLL,
    242                       0, &pred_result);
    243     check_ll(res64, 0x00000000ffffffffLL);
    244     check_p(pred_result, 0xff);
    245 }
    246 
    247 static void test_sub_carry()
    248 {
    249     long long res64;
    250     int pred_result;
    251 
    252     res64 = sub_carry(0x0000000000000000LL,
    253                       0x0000000000000000LL,
    254                       1, &pred_result);
    255     check_ll(res64, 0x0000000000000000LL);
    256     check_p(pred_result, 0xff);
    257 
    258     res64 = sub_carry(0x0000000100000000LL,
    259                       0x0000000000000000LL,
    260                       0, &pred_result);
    261     check_ll(res64, 0x00000000ffffffffLL);
    262     check_p(pred_result, 0xff);
    263 
    264     res64 = sub_carry(0x0000000100000000LL,
    265                       0x0000000000000000LL,
    266                       0, &pred_result);
    267     check_ll(res64, 0x00000000ffffffffLL);
    268     check_p(pred_result, 0xff);
    269 }
    270 
    271 int main()
    272 {
    273     test_sfrecipa();
    274     test_sfinvsqrta();
    275     test_vacsh();
    276     test_vminub();
    277     test_add_carry();
    278     test_sub_carry();
    279 
    280     puts(err ? "FAIL" : "PASS");
    281     return err;
    282 }