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

bcdsub.c (2933B)


      1#include <assert.h>
      2#include <unistd.h>
      3#include <signal.h>
      4
      5#define CRF_LT  (1 << 3)
      6#define CRF_GT  (1 << 2)
      7#define CRF_EQ  (1 << 1)
      8#define CRF_SO  (1 << 0)
      9#define UNDEF   0
     10
     11#define BCDSUB(vra, vrb, ps)                    \
     12    asm ("bcdsub. %1,%2,%3,%4;"                 \
     13         "mfocrf %0,0b10;"                      \
     14         : "=r" (cr), "=v" (vrt)                \
     15         : "v" (vra), "v" (vrb), "i" (ps)       \
     16         : );
     17
     18#define TEST(vra, vrb, ps, exp_res, exp_cr6)    \
     19    do {                                        \
     20        __int128 vrt = 0;                       \
     21        int cr = 0;                             \
     22        BCDSUB(vra, vrb, ps);                   \
     23        if (exp_res)                            \
     24            assert(vrt == exp_res);             \
     25        assert((cr >> 4) == exp_cr6);           \
     26    } while (0)
     27
     28
     29/*
     30 * Unbounded result is equal to zero:
     31 *   sign = (PS) ? 0b1111 : 0b1100
     32 *   CR6 = 0b0010
     33 */
     34void test_bcdsub_eq(void)
     35{
     36    __int128 a, b;
     37
     38    /* maximum positive BCD value */
     39    a = b = (((__int128) 0x9999999999999999) << 64 | 0x999999999999999c);
     40
     41    TEST(a, b, 0, 0xc, CRF_EQ);
     42    TEST(a, b, 1, 0xf, CRF_EQ);
     43}
     44
     45/*
     46 * Unbounded result is greater than zero:
     47 *   sign = (PS) ? 0b1111 : 0b1100
     48 *   CR6 = (overflow) ? 0b0101 : 0b0100
     49 */
     50void test_bcdsub_gt(void)
     51{
     52    __int128 a, b, c;
     53
     54    /* maximum positive BCD value */
     55    a = (((__int128) 0x9999999999999999) << 64 | 0x999999999999999c);
     56
     57    /* negative one BCD value */
     58    b = (__int128) 0x1d;
     59
     60    TEST(a, b, 0, 0xc, (CRF_GT | CRF_SO));
     61    TEST(a, b, 1, 0xf, (CRF_GT | CRF_SO));
     62
     63    c = (((__int128) 0x9999999999999999) << 64 | 0x999999999999998c);
     64
     65    TEST(c, b, 0, a, CRF_GT);
     66    TEST(c, b, 1, (a | 0x3), CRF_GT);
     67}
     68
     69/*
     70 * Unbounded result is less than zero:
     71 *   sign = 0b1101
     72 *   CR6 = (overflow) ? 0b1001 : 0b1000
     73 */
     74void test_bcdsub_lt(void)
     75{
     76    __int128 a, b;
     77
     78    /* positive zero BCD value */
     79    a = (__int128) 0xc;
     80
     81    /* positive one BCD value */
     82    b = (__int128) 0x1c;
     83
     84    TEST(a, b, 0, 0x1d, CRF_LT);
     85    TEST(a, b, 1, 0x1d, CRF_LT);
     86
     87    /* maximum negative BCD value */
     88    a = (((__int128) 0x9999999999999999) << 64 | 0x999999999999999d);
     89
     90    /* positive one BCD value */
     91    b = (__int128) 0x1c;
     92
     93    TEST(a, b, 0, 0xd, (CRF_LT | CRF_SO));
     94    TEST(a, b, 1, 0xd, (CRF_LT | CRF_SO));
     95}
     96
     97void test_bcdsub_invalid(void)
     98{
     99    __int128 a, b;
    100
    101    /* positive one BCD value */
    102    a = (__int128) 0x1c;
    103    b = 0xf00;
    104
    105    TEST(a, b, 0, UNDEF, CRF_SO);
    106    TEST(a, b, 1, UNDEF, CRF_SO);
    107
    108    TEST(b, a, 0, UNDEF, CRF_SO);
    109    TEST(b, a, 1, UNDEF, CRF_SO);
    110
    111    a = 0xbad;
    112
    113    TEST(a, b, 0, UNDEF, CRF_SO);
    114    TEST(a, b, 1, UNDEF, CRF_SO);
    115}
    116
    117int main(void)
    118{
    119    struct sigaction action;
    120
    121    action.sa_handler = _exit;
    122    sigaction(SIGABRT, &action, NULL);
    123
    124    test_bcdsub_eq();
    125    test_bcdsub_gt();
    126    test_bcdsub_lt();
    127    test_bcdsub_invalid();
    128
    129    return 0;
    130}