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

qnum.c (5165B)


      1/*
      2 * QNum Module
      3 *
      4 * Copyright (C) 2009 Red Hat Inc.
      5 *
      6 * Authors:
      7 *  Luiz Capitulino <lcapitulino@redhat.com>
      8 *  Anthony Liguori <aliguori@us.ibm.com>
      9 *  Marc-André Lureau <marcandre.lureau@redhat.com>
     10 *
     11 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
     12 * See the COPYING.LIB file in the top-level directory.
     13 */
     14
     15#include "qemu/osdep.h"
     16#include "qapi/qmp/qnum.h"
     17#include "qobject-internal.h"
     18
     19/**
     20 * qnum_from_int(): Create a new QNum from an int64_t
     21 *
     22 * Return strong reference.
     23 */
     24QNum *qnum_from_int(int64_t value)
     25{
     26    QNum *qn = g_new(QNum, 1);
     27
     28    qobject_init(QOBJECT(qn), QTYPE_QNUM);
     29    qn->kind = QNUM_I64;
     30    qn->u.i64 = value;
     31
     32    return qn;
     33}
     34
     35/**
     36 * qnum_from_uint(): Create a new QNum from an uint64_t
     37 *
     38 * Return strong reference.
     39 */
     40QNum *qnum_from_uint(uint64_t value)
     41{
     42    QNum *qn = g_new(QNum, 1);
     43
     44    qobject_init(QOBJECT(qn), QTYPE_QNUM);
     45    qn->kind = QNUM_U64;
     46    qn->u.u64 = value;
     47
     48    return qn;
     49}
     50
     51/**
     52 * qnum_from_double(): Create a new QNum from a double
     53 *
     54 * Return strong reference.
     55 */
     56QNum *qnum_from_double(double value)
     57{
     58    QNum *qn = g_new(QNum, 1);
     59
     60    qobject_init(QOBJECT(qn), QTYPE_QNUM);
     61    qn->kind = QNUM_DOUBLE;
     62    qn->u.dbl = value;
     63
     64    return qn;
     65}
     66
     67/**
     68 * qnum_get_try_int(): Get an integer representation of the number
     69 *
     70 * Return true on success.
     71 */
     72bool qnum_get_try_int(const QNum *qn, int64_t *val)
     73{
     74    switch (qn->kind) {
     75    case QNUM_I64:
     76        *val = qn->u.i64;
     77        return true;
     78    case QNUM_U64:
     79        if (qn->u.u64 > INT64_MAX) {
     80            return false;
     81        }
     82        *val = qn->u.u64;
     83        return true;
     84    case QNUM_DOUBLE:
     85        return false;
     86    }
     87
     88    assert(0);
     89    return false;
     90}
     91
     92/**
     93 * qnum_get_int(): Get an integer representation of the number
     94 *
     95 * assert() on failure.
     96 */
     97int64_t qnum_get_int(const QNum *qn)
     98{
     99    int64_t val;
    100    bool success = qnum_get_try_int(qn, &val);
    101    assert(success);
    102    return val;
    103}
    104
    105/**
    106 * qnum_get_uint(): Get an unsigned integer from the number
    107 *
    108 * Return true on success.
    109 */
    110bool qnum_get_try_uint(const QNum *qn, uint64_t *val)
    111{
    112    switch (qn->kind) {
    113    case QNUM_I64:
    114        if (qn->u.i64 < 0) {
    115            return false;
    116        }
    117        *val = qn->u.i64;
    118        return true;
    119    case QNUM_U64:
    120        *val = qn->u.u64;
    121        return true;
    122    case QNUM_DOUBLE:
    123        return false;
    124    }
    125
    126    assert(0);
    127    return false;
    128}
    129
    130/**
    131 * qnum_get_uint(): Get an unsigned integer from the number
    132 *
    133 * assert() on failure.
    134 */
    135uint64_t qnum_get_uint(const QNum *qn)
    136{
    137    uint64_t val;
    138    bool success = qnum_get_try_uint(qn, &val);
    139    assert(success);
    140    return val;
    141}
    142
    143/**
    144 * qnum_get_double(): Get a float representation of the number
    145 *
    146 * qnum_get_double() loses precision for integers beyond 53 bits.
    147 */
    148double qnum_get_double(QNum *qn)
    149{
    150    switch (qn->kind) {
    151    case QNUM_I64:
    152        return qn->u.i64;
    153    case QNUM_U64:
    154        return qn->u.u64;
    155    case QNUM_DOUBLE:
    156        return qn->u.dbl;
    157    }
    158
    159    assert(0);
    160    return 0.0;
    161}
    162
    163char *qnum_to_string(QNum *qn)
    164{
    165    switch (qn->kind) {
    166    case QNUM_I64:
    167        return g_strdup_printf("%" PRId64, qn->u.i64);
    168    case QNUM_U64:
    169        return g_strdup_printf("%" PRIu64, qn->u.u64);
    170    case QNUM_DOUBLE:
    171        /* 17 digits suffice for IEEE double */
    172        return g_strdup_printf("%.17g", qn->u.dbl);
    173    }
    174
    175    assert(0);
    176    return NULL;
    177}
    178
    179/**
    180 * qnum_is_equal(): Test whether the two QNums are equal
    181 *
    182 * Negative integers are never considered equal to unsigned integers,
    183 * but positive integers in the range [0, INT64_MAX] are considered
    184 * equal independently of whether the QNum's kind is i64 or u64.
    185 *
    186 * Doubles are never considered equal to integers.
    187 */
    188bool qnum_is_equal(const QObject *x, const QObject *y)
    189{
    190    QNum *num_x = qobject_to(QNum, x);
    191    QNum *num_y = qobject_to(QNum, y);
    192
    193    switch (num_x->kind) {
    194    case QNUM_I64:
    195        switch (num_y->kind) {
    196        case QNUM_I64:
    197            /* Comparison in native int64_t type */
    198            return num_x->u.i64 == num_y->u.i64;
    199        case QNUM_U64:
    200            /* Implicit conversion of x to uin64_t, so we have to
    201             * check its sign before */
    202            return num_x->u.i64 >= 0 && num_x->u.i64 == num_y->u.u64;
    203        case QNUM_DOUBLE:
    204            return false;
    205        }
    206        abort();
    207    case QNUM_U64:
    208        switch (num_y->kind) {
    209        case QNUM_I64:
    210            return qnum_is_equal(y, x);
    211        case QNUM_U64:
    212            /* Comparison in native uint64_t type */
    213            return num_x->u.u64 == num_y->u.u64;
    214        case QNUM_DOUBLE:
    215            return false;
    216        }
    217        abort();
    218    case QNUM_DOUBLE:
    219        switch (num_y->kind) {
    220        case QNUM_I64:
    221        case QNUM_U64:
    222            return false;
    223        case QNUM_DOUBLE:
    224            /* Comparison in native double type */
    225            return num_x->u.dbl == num_y->u.dbl;
    226        }
    227        abort();
    228    }
    229
    230    abort();
    231}
    232
    233/**
    234 * qnum_destroy_obj(): Free all memory allocated by a
    235 * QNum object
    236 */
    237void qnum_destroy_obj(QObject *obj)
    238{
    239    assert(obj != NULL);
    240    g_free(qobject_to(QNum, obj));
    241}