cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

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
     20static 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
     34static 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
     48static 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
     73static 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
     88static 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
    104static 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
    120int err;
    121
    122static 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
    130static 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
    138static 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
    146static 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
    156static 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
    170static 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
    205static 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
    223static 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
    247static 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
    271int 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}