// inline functions
#ifndef INLINES_HH
#define INLINES_HH
inline int unpack2(byte* s) {
return (s[0] << 8) + s[1];
}
inline int unpack4(byte* s) {
return (((((s[0] << 8) + s[1]) << 8) + s[2]) << 8) + s[3];
}
inline int unpack2_le(byte* s) {
return (s[1] << 8) + s[0];
}
inline int unpack4_le(byte* s) {
return (((((s[3] << 8) + s[2]) << 8) + s[1]) << 8) + s[0];
}
//
// Some bit support functions
//
inline int first_set_bit(int4 val)
{
if (val == 0) {
return 32;
}
int n = 0;
while (!(val & 1)) {
n += 1;
val >>= 1;
}
return n;
}
inline int last_set_bit(nat4 val)
{
int n = 0;
if (val == 0) {
return -1;
}
while ((val >>= 1) != 0) {
n += 1;
}
return n;
}
inline int minimum(int4 x, int4 y) { return x < y ? x : y; }
inline int maximum(int4 x, int4 y) { return x > y ? x : y; }
inline int4 make_mask(int shift) {
return shift < 0 ? ALL_BITS : shift >= 32 ? 0 : ALL_BITS << shift;
}
inline int4 make_mask(int high_bit, int low_bit)
{
int4 mask = (high_bit >= 31) ? ALL_BITS : ((1 << (high_bit+1)) - 1);
if (low_bit < 32) mask &= ~((1 << low_bit) - 1);
return mask;
}
inline int4 make_lshift_mask(int4 mask, int min_shift, int max_shift) {
if (unsigned(max_shift - min_shift) >= 32) {
return ALL_BITS;
}
int4 result = 0;
while (min_shift <= max_shift) {
result |= mask << (min_shift & 31);
min_shift += 1;
}
return result;
}
inline int4 make_rshift_mask(int4 mask, int min_shift, int max_shift) {
if (unsigned(max_shift - min_shift) >= 32) {
return ALL_BITS;
}
int4 result = 0;
while (min_shift <= max_shift) {
result |= mask >> (min_shift & 31);
min_shift += 1;
}
return result;
}
inline int4 make_rushift_mask(nat4 mask, int min_shift, int max_shift) {
if (unsigned(max_shift - min_shift) >= 32) {
return ALL_BITS;
}
int4 result = 0;
while (min_shift <= max_shift) {
result |= mask >> (min_shift & 31);
min_shift += 1;
}
return result;
}
inline bool calculate_multiply_range(vbm_operand& z,
vbm_operand& x, vbm_operand& y)
{
// z = x*y
if (x.max < 0 && y.max < 0) {
z.min = x.max*y.max;
z.max = x.min*y.min;
return (z.max > 0 && z.max/x.min == y.min);// no overflow
} else if (x.max < 0 && y.min < 0 && y.max >= 0) {
z.min = x.min*y.max;
z.max = x.min*y.min;
return (z.max > 0 && z.min/x.min == y.max && z.max/x.min == y.min);
} else if (x.max < 0 && y.min >= 0) {
z.min = x.min*y.max;
z.max = x.max*y.min;
return (z.min/x.min == y.max && z.max/x.max == y.min); // no overflow
} else if (x.min < 0 && x.max >= 0 && y.max < 0) {
z.min = x.max*y.min;
z.max = x.min*y.min;
return (z.max > 0 && z.min/y.min == x.max && z.max/y.min == x.min);
} else if (x.min < 0 && x.max >= 0 && y.min < 0 && y.max >= 0) {
int4 m1, m2;
m1 = x.min*y.max;
m2 = x.max*y.min;
if (m1/x.min != y.max || m2/y.min != x.max) return false;
z.min = minimum(m1, m2);
m1 = x.max*y.max;
m2 = x.min*y.min;
if (m2 <= 0 || (x.max != 0 && m1/x.max != y.max) || m2/y.min != x.min)
return false;
z.max = maximum(m1, m2);
return true;
} else if (x.min < 0 && x.max >= 0 && y.min >= 0) {
z.min = x.min*y.max;
z.max = x.max*y.max;
return z.min/x.min == y.max && (x.max == 0 || z.max/x.max == y.max);
} else if (x.min >= 0 && y.max < 0) {
z.min = x.max*y.min;
z.max = x.min*y.max;
return z.min/y.min == x.max && z.max/y.max == x.min;
} else if (x.min >= 0 && y.min < 0 && y.max >= 0) {
z.min = x.max*y.min;
z.max = x.max*y.max;
return z.min/y.min == x.max && (x.max == 0 || z.max/x.max == y.max);
} else {
assert(x.min >= 0 && y.min >= 0);
z.min = x.min*y.min;
z.max = x.max*y.max;
return x.max == 0 || z.max/x.max == y.max;
}
}
#ifdef INT8_DEFINED
inline int first_set_bit(int8 val)
{
if (val == 0) {
return 64;
}
int n = 0;
while (!(val & 1)) {
n += 1;
val >>= 1;
}
return n;
}
inline int8 make_int8_mask(int shift) {
return shift < 0 ? INT8_ALL_BITS : shift >= 64
? INT8_ZERO : INT8_ALL_BITS << shift;
}
inline int8 make_int8_lshift_mask(int8 mask, int min_shift, int max_shift) {
if (unsigned(max_shift - min_shift) >= 64) {
return INT8_ALL_BITS;
}
int8 result = 0;
while (min_shift <= max_shift) {
result |= mask << (min_shift & 63);
min_shift += 1;
}
return result;
}
inline int8 make_int8_rshift_mask(int8 mask, int min_shift, int max_shift) {
if (unsigned(max_shift - min_shift) >= 64) {
return INT8_ALL_BITS;
}
int8 result = 0;
while (min_shift <= max_shift) {
result |= mask >> (min_shift & 63);
min_shift += 1;
}
return result;
}
inline int8 make_int8_rushift_mask(nat8 mask, int min_shift, int max_shift) {
if (unsigned(max_shift - min_shift) >= 64) {
return INT8_ALL_BITS;
}
int8 result = 0;
while (min_shift <= max_shift) {
result |= mask >> (min_shift & 63);
min_shift += 1;
}
return result;
}
inline bool calculate_int8_multiply_range(vbm_operand* x, vbm_operand* y)
{
// x *= y
int8 x_min = LOAD_INT8(x, min);
int8 x_max = LOAD_INT8(x, max);
int8 y_min = LOAD_INT8(y, min);
int8 y_max = LOAD_INT8(y, max);
int8 z_min, z_max;
if (x_max < 0 && y_max < 0) {
z_min = x_max*y_max;
z_max = x_min*y_min;
STORE_INT8(x, min, z_min);
STORE_INT8(x, max, z_max);
return (z_min > 0 && z_max/x_min == y_min); // no overflow
} else if (x_max < 0 && y_min < 0 && y_max >= 0) {
z_min = x_min*y_max;
z_max = x_min*y_min;
STORE_INT8(x, min, z_min);
STORE_INT8(x, max, z_max);
return (z_max > 0 && z_min/x_min == y_max && z_max/x_min == y_min);
} else if (x_max < 0 && y_min >= 0) {
z_min = x_min*y_max;
z_max = x_max*y_min;
STORE_INT8(x, min, z_min);
STORE_INT8(x, max, z_max);
return (z_min/x_min == y_max && z_max/x_max == y_min); // no overflow
} else if (x_min < 0 && x_max >= 0 && y_max < 0) {
z_min = x_max*y_min;
z_max = x_min*y_min;
STORE_INT8(x, min, z_min);
STORE_INT8(x, max, z_max);
return (z_max > 0 && z_min/y_min == x_max && z_max/y_min == x_min);
} else if (x_min < 0 && x_max >= 0 && y_min < 0 && y_max >= 0) {
int8 m1, m2;
m1 = x_min*y_max;
m2 = x_max*y_min;
if (m1/x_min != y_max || m2/y_min != x_max) return false;
z_min = m1 < m2 ? m1 : m2;
m1 = x_max*y_max;
m2 = x_min*y_min;
if (m2 <= 0 || (x_max != 0 && m1/x_max != y_max) || m2/y_min != x_min)
return false;
z_max = m1 > m2 ? m1 : m2;
STORE_INT8(x, min, z_min);
STORE_INT8(x, max, z_max);
return true;
} else if (x_min < 0 && x_max >= 0 && y_min >= 0) {
z_min = x_min*y_max;
z_max = x_max*y_max;
STORE_INT8(x, min, z_min);
STORE_INT8(x, max, z_max);
return z_min/x_min == y_max && (x_max == 0 || z_max/x_max == y_max);
} else if (x_min >= 0 && y_max < 0) {
z_min = x_max*y_min;
z_max = x_min*y_max;
STORE_INT8(x, min, z_min);
STORE_INT8(x, max, z_max);
return z_min/y_min == x_max && z_max/y_max == x_min;
} else if (x_min >= 0 && y_min < 0 && y_max >= 0) {
z_min = x_max*y_min;
z_max = x_max*y_max;
STORE_INT8(x, min, z_min);
STORE_INT8(x, max, z_max);
return z_min/y_min == x_max && (x_max == 0 || z_max/x_max == y_max);
} else {
assert(x_min >= 0 && y_min >= 0);
z_min = x_min*y_min;
z_max = x_max*y_max;
STORE_INT8(x, min, z_min);
STORE_INT8(x, max, z_max);
return x_max == 0 || z_max/x_max == y_max;
}
}
#endif
#endif