ConstantDivision.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "ConstantDivision.h"
00011
00012 #include "klee/util/Bits.h"
00013
00014 #include <algorithm>
00015 #include <cassert>
00016
00017 namespace klee {
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #define TWO_TO_THE_32_U64 (1ULL << 32)
00029
00030
00031 #define TWO_TO_THE_31_S64 (1LL << 31)
00032
00033
00034 #define ABS(x) ( ((x)>0)?x:-(x) )
00035
00036
00037 #define XSIGN(x) ( (x) >> 31 )
00038
00039
00040 #define LOG2_CEIL(x) ( 32 - ldz(x - 1) )
00041
00042
00043 static uint32_t ones( register uint32_t x ) {
00044 x -= ((x >> 1) & 0x55555555);
00045 x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
00046 x = (((x >> 4) + x) & 0x0f0f0f0f);
00047 x += (x >> 8);
00048 x += (x >> 16);
00049
00050 return( x & 0x0000003f );
00051 }
00052
00053
00054 static uint32_t ldz( register uint32_t x ) {
00055 x |= (x >> 1);
00056 x |= (x >> 2);
00057 x |= (x >> 4);
00058 x |= (x >> 8);
00059 x |= (x >> 16);
00060
00061 return 32 - ones(x);
00062 }
00063
00064
00065 static uint32_t exp_base_2( register int32_t n ) {
00066 register uint32_t x = ~n & (n - 32);
00067 x = x >> 31;
00068 return( x << n );
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 void ComputeMultConstants64(uint64_t multiplicand,
00083 uint64_t &add, uint64_t &sub) {
00084 uint64_t x = multiplicand;
00085 add = sub = 0;
00086
00087 while (x) {
00088
00089 unsigned low = bits64::indexOfRightmostBit(x);
00090 uint64_t lowbit = 1LL << low;
00091 uint64_t p = x + lowbit;
00092 uint64_t q = bits64::isolateRightmostBit(p);
00093 unsigned high = q ? bits64::indexOfSingleBit(q) : 64;
00094
00095 if (high==low+1) {
00096 add |= lowbit;
00097 } else {
00098
00099
00100
00101 if (low && (add & (lowbit>>1))) {
00102 add ^= lowbit>>1;
00103 sub ^= lowbit>>1;
00104 } else {
00105 sub |= lowbit;
00106 }
00107
00108 if (high!=64)
00109 add |= 1LL << high;
00110 }
00111
00112 x = p ^ q;
00113 }
00114
00115 assert(multiplicand == add - sub);
00116 }
00117
00118 void ComputeUDivConstants32(uint32_t d, uint32_t &mprime, uint32_t &sh1,
00119 uint32_t &sh2) {
00120 int32_t l = LOG2_CEIL( d );
00121 uint32_t mid = exp_base_2(l) - d;
00122
00123 mprime = (TWO_TO_THE_32_U64 * mid / d) + 1;
00124 sh1 = std::min( l, 1 );
00125 sh2 = std::max( l-1, 0 );
00126 }
00127
00128 void ComputeSDivConstants32(int32_t d, int32_t &mprime, int32_t &dsign,
00129 int32_t &shpost ) {
00130 uint64_t abs_d = ABS( (int64_t)d );
00131
00132
00133
00134
00135 int32_t l = std::max( 1U, LOG2_CEIL((uint32_t)abs_d) );
00136 if( abs_d == TWO_TO_THE_31_S64 ) l = 31;
00137
00138 uint32_t mid = exp_base_2( l - 1 );
00139 uint64_t m = TWO_TO_THE_32_U64 * mid / abs_d + 1ULL;
00140
00141 mprime = m - TWO_TO_THE_32_U64;
00142 dsign = XSIGN( d );
00143 shpost = l - 1;
00144 }
00145
00146 }