qemu/include/qemu/host-utils.h
<<
>>
Prefs
   1/*
   2 * Utility compute operations used by translated code.
   3 *
   4 * Copyright (c) 2007 Thiemo Seufer
   5 * Copyright (c) 2007 Jocelyn Mayer
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25#ifndef HOST_UTILS_H
  26#define HOST_UTILS_H 1
  27
  28#include "qemu/compiler.h"   /* QEMU_GNUC_PREREQ */
  29
  30#if defined(__x86_64__)
  31#define __HAVE_FAST_MULU64__
  32static inline void mulu64(uint64_t *plow, uint64_t *phigh,
  33                          uint64_t a, uint64_t b)
  34{
  35    __asm__ ("mul %0\n\t"
  36             : "=d" (*phigh), "=a" (*plow)
  37             : "a" (a), "0" (b));
  38}
  39#define __HAVE_FAST_MULS64__
  40static inline void muls64(uint64_t *plow, uint64_t *phigh,
  41                          int64_t a, int64_t b)
  42{
  43    __asm__ ("imul %0\n\t"
  44             : "=d" (*phigh), "=a" (*plow)
  45             : "a" (a), "0" (b));
  46}
  47#else
  48void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
  49void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
  50#endif
  51
  52/* Binary search for leading zeros.  */
  53
  54static inline int clz32(uint32_t val)
  55{
  56#if QEMU_GNUC_PREREQ(3, 4)
  57    if (val)
  58        return __builtin_clz(val);
  59    else
  60        return 32;
  61#else
  62    int cnt = 0;
  63
  64    if (!(val & 0xFFFF0000U)) {
  65        cnt += 16;
  66        val <<= 16;
  67    }
  68    if (!(val & 0xFF000000U)) {
  69        cnt += 8;
  70        val <<= 8;
  71    }
  72    if (!(val & 0xF0000000U)) {
  73        cnt += 4;
  74        val <<= 4;
  75    }
  76    if (!(val & 0xC0000000U)) {
  77        cnt += 2;
  78        val <<= 2;
  79    }
  80    if (!(val & 0x80000000U)) {
  81        cnt++;
  82        val <<= 1;
  83    }
  84    if (!(val & 0x80000000U)) {
  85        cnt++;
  86    }
  87    return cnt;
  88#endif
  89}
  90
  91static inline int clo32(uint32_t val)
  92{
  93    return clz32(~val);
  94}
  95
  96static inline int clz64(uint64_t val)
  97{
  98#if QEMU_GNUC_PREREQ(3, 4)
  99    if (val)
 100        return __builtin_clzll(val);
 101    else
 102        return 64;
 103#else
 104    int cnt = 0;
 105
 106    if (!(val >> 32)) {
 107        cnt += 32;
 108    } else {
 109        val >>= 32;
 110    }
 111
 112    return cnt + clz32(val);
 113#endif
 114}
 115
 116static inline int clo64(uint64_t val)
 117{
 118    return clz64(~val);
 119}
 120
 121static inline int ctz32(uint32_t val)
 122{
 123#if QEMU_GNUC_PREREQ(3, 4)
 124    if (val)
 125        return __builtin_ctz(val);
 126    else
 127        return 32;
 128#else
 129    int cnt;
 130
 131    cnt = 0;
 132    if (!(val & 0x0000FFFFUL)) {
 133        cnt += 16;
 134        val >>= 16;
 135    }
 136    if (!(val & 0x000000FFUL)) {
 137        cnt += 8;
 138        val >>= 8;
 139    }
 140    if (!(val & 0x0000000FUL)) {
 141        cnt += 4;
 142        val >>= 4;
 143    }
 144    if (!(val & 0x00000003UL)) {
 145        cnt += 2;
 146        val >>= 2;
 147    }
 148    if (!(val & 0x00000001UL)) {
 149        cnt++;
 150        val >>= 1;
 151    }
 152    if (!(val & 0x00000001UL)) {
 153        cnt++;
 154    }
 155
 156    return cnt;
 157#endif
 158}
 159
 160static inline int cto32(uint32_t val)
 161{
 162    return ctz32(~val);
 163}
 164
 165static inline int ctz64(uint64_t val)
 166{
 167#if QEMU_GNUC_PREREQ(3, 4)
 168    if (val)
 169        return __builtin_ctzll(val);
 170    else
 171        return 64;
 172#else
 173    int cnt;
 174
 175    cnt = 0;
 176    if (!((uint32_t)val)) {
 177        cnt += 32;
 178        val >>= 32;
 179    }
 180
 181    return cnt + ctz32(val);
 182#endif
 183}
 184
 185static inline int cto64(uint64_t val)
 186{
 187    return ctz64(~val);
 188}
 189
 190static inline int ctpop8(uint8_t val)
 191{
 192    val = (val & 0x55) + ((val >> 1) & 0x55);
 193    val = (val & 0x33) + ((val >> 2) & 0x33);
 194    val = (val & 0x0f) + ((val >> 4) & 0x0f);
 195
 196    return val;
 197}
 198
 199static inline int ctpop16(uint16_t val)
 200{
 201    val = (val & 0x5555) + ((val >> 1) & 0x5555);
 202    val = (val & 0x3333) + ((val >> 2) & 0x3333);
 203    val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f);
 204    val = (val & 0x00ff) + ((val >> 8) & 0x00ff);
 205
 206    return val;
 207}
 208
 209static inline int ctpop32(uint32_t val)
 210{
 211#if QEMU_GNUC_PREREQ(3, 4)
 212    return __builtin_popcount(val);
 213#else
 214    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
 215    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
 216    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
 217    val = (val & 0x00ff00ff) + ((val >>  8) & 0x00ff00ff);
 218    val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
 219
 220    return val;
 221#endif
 222}
 223
 224static inline int ctpop64(uint64_t val)
 225{
 226#if QEMU_GNUC_PREREQ(3, 4)
 227    return __builtin_popcountll(val);
 228#else
 229    val = (val & 0x5555555555555555ULL) + ((val >>  1) & 0x5555555555555555ULL);
 230    val = (val & 0x3333333333333333ULL) + ((val >>  2) & 0x3333333333333333ULL);
 231    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) & 0x0f0f0f0f0f0f0f0fULL);
 232    val = (val & 0x00ff00ff00ff00ffULL) + ((val >>  8) & 0x00ff00ff00ff00ffULL);
 233    val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 0x0000ffff0000ffffULL);
 234    val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL);
 235
 236    return val;
 237#endif
 238}
 239
 240#endif
 241