Revision 6046c620 include/qemu/int128.h

b/include/qemu/int128.h
1 1
#ifndef INT128_H
2 2
#define INT128_H
3 3

  
4
#include <assert.h>
5
#include <stdint.h>
6
#include <stdbool.h>
7

  
4 8
typedef struct Int128 Int128;
5 9

  
6 10
struct Int128 {
......
55 59

  
56 60
static inline Int128 int128_add(Int128 a, Int128 b)
57 61
{
58
    Int128 r = { a.lo + b.lo, a.hi + b.hi };
59
    r.hi += (r.lo < a.lo) || (r.lo < b.lo);
60
    return r;
62
    uint64_t lo = a.lo + b.lo;
63

  
64
    /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64).  Hence,
65
     * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
66
     * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
67
     *
68
     * So the carry is lo < a.lo.
69
     */
70
    return (Int128) { lo, (uint64_t)a.hi + b.hi + (lo < a.lo) };
61 71
}
62 72

  
63 73
static inline Int128 int128_neg(Int128 a)
64 74
{
65
    a.lo = ~a.lo;
66
    a.hi = ~a.hi;
67
    return int128_add(a, int128_one());
75
    uint64_t lo = -a.lo;
76
    return (Int128) { lo, ~(uint64_t)a.hi + !lo };
68 77
}
69 78

  
70 79
static inline Int128 int128_sub(Int128 a, Int128 b)
71 80
{
72
    return int128_add(a, int128_neg(b));
81
    return (Int128){ a.lo - b.lo, a.hi - b.hi - (a.lo < b.lo) };
73 82
}
74 83

  
75 84
static inline bool int128_nonneg(Int128 a)
......
89 98

  
90 99
static inline bool int128_ge(Int128 a, Int128 b)
91 100
{
92
    return int128_nonneg(int128_sub(a, b));
101
    return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
93 102
}
94 103

  
95 104
static inline bool int128_lt(Int128 a, Int128 b)

Also available in: Unified diff