diff --git a/VERSION b/VERSION index 74087a5..f64b756 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -ecomp.version : ecomp.r29.143635 +ecomp.version : ecomp.r29.143691 diff --git a/tools/lccrt_s/src/lccrt_vec.c b/tools/lccrt_s/src/lccrt_vec.c index 8f596e8..6a47b0b 100644 --- a/tools/lccrt_s/src/lccrt_vec.c +++ b/tools/lccrt_s/src/lccrt_vec.c @@ -10,6 +10,82 @@ #include #include +static uint64_t +__lccrt_get_bits( uint64_t u, int off, int bits) { + int lshift = 64 - off - bits; + int rshift = 64 - bits; + uint64_t r = (bits > 0) ? ((u << lshift) >> rshift) : 0; + + return (r); +} /* __lccrt_get_bits */ + +static uint64_t +__lccrt_set_bits( uint64_t u, int off, int bits, uint64_t v) { + uint64_t r = u; + + if ( bits > 0 ) { + int lshift = 64 - bits; + int rshift = 64 - bits - off; + uint64_t bitmask = ((~0ULL) << lshift) >> rshift; + + r = (u & ~bitmask) | ((v << off) & bitmask); + } + + return (r); +} /* __lccrt_set_bits */ + +/** + * В каждом из параметров u0/u1 хранится по ubytes байт данных. Нужно склеить + * данные и по битовому смещению eoff прочитать значение размером ebits бит. + */ +static uint64_t +__lccrt_get_pair_bits( uint64_t u0, uint64_t u1, int ubytes, int eoff, int ebits) { + uint64_t r = 0; + int ubits = 8*ubytes; + + assert( (0 <= eoff) && (0 <= ebits)); + assert( (eoff + ebits <= 2*ubits) && (ebits <= 64)); + if ( eoff + ebits <= ubits ) { + r = __lccrt_get_bits( u0, eoff, ebits); + } else if ( eoff >= ubits ) { + r = __lccrt_get_bits( u1, eoff - ubits, ebits); + } else { + int lo_len = ubits - eoff; + uint64_t lo = __lccrt_get_bits( u0, eoff, lo_len); + uint64_t hi = __lccrt_get_bits( u1, 0, ebits - lo_len); + + r = (hi << lo_len) | lo; + } + + return (r); +} /* __lccrt_get_pair_bits */ + +/** + * В каждом из параметров u0/u1 хранится по ubytes байт данных. Нужно + * логически склеить данные и по битовому смещению eoff записать значение v + * размером ebits бит. + */ +static void +__lccrt_set_pair_bits( uint64_t *u0, uint64_t *u1, int ubytes, int eoff, int ebits, uint64_t v) { + uint64_t r = 0; + int ubits = 8*ubytes; + + assert( (0 <= eoff) && (0 <= ebits)); + assert( (eoff + ebits <= 2*ubits) && (ebits <= 64)); + if ( eoff + ebits <= ubits ) { + u0[0] = __lccrt_set_bits( u0[0], eoff, ebits, v); + } else if ( eoff >= ubits ) { + u1[0] = __lccrt_set_bits( u1[0], eoff - ubits, ebits, v); + } else { + int lo_len = ubits - eoff; + + u0[0] = __lccrt_set_bits( u0[0], eoff, lo_len, v); + u1[0] = __lccrt_set_bits( u1[0], 0, ebits - lo_len, v >> lo_len); + } + + return; +} /* __lccrt_set_pair_bits */ + static int __lccrt_bitwidth_bytesize( int bitsize) { int r = 0; @@ -75,50 +151,63 @@ __lccrt_load_bytes( void *src, int64_t bytesize) { /** * Упаковка битов вектора нестандартных целых в (нестандартное) целое значение. - * Суммарное количество значимых бит не должно превышать 64. * Пример: <3 x i6> -> i18. */ void __lccrt_vecbitpack( void *dst, void *src, int64_t veclen, int64_t elembitsize) { - uint64_t r = 0; int ebytes = __lccrt_bitwidth_bytesize( elembitsize); - int maskshift = 64 - elembitsize; - int totalbitsize = veclen*elembitsize; + int lcnt = 0; + int uoff = 0; + uint64_t u0 = 0; + uint64_t u1 = 0; - assert( (0 <= veclen) && (0 < elembitsize) && (totalbitsize <= 64)); - for ( int i = veclen - 1; i >= 0; --i ) { - uint64_t si = 0; + assert( (0 <= veclen) && (0 < elembitsize) && (elembitsize <= 64)); + for ( int i = 0; i < veclen; ++i ) { + uint64_t v = __lccrt_load_bytes( (char *)src + i*ebytes, ebytes); - si = __lccrt_load_bytes( (char *)src + i*ebytes, ebytes); - si = (si << maskshift) >> maskshift; - r = (r << elembitsize) | si; + __lccrt_set_pair_bits( &u0, &u1, ebytes, uoff, elembitsize, v); + uoff = uoff + elembitsize; + if ( uoff >= 8*ebytes ) { + __lccrt_store_bytes( (char *)dst + lcnt, u0, ebytes); + u0 = u1; + u1 = 0; + lcnt += ebytes; + uoff = uoff - 8*ebytes; + } } - __lccrt_store_bytes( dst, r, __lccrt_bitwidth_bytesize( totalbitsize)); + if ( uoff > 0 ) { + __lccrt_store_bytes( (char *)dst + lcnt, u0, ebytes); + } return; } /** * Распаковка битов (нестандартного) целого в вектор нестандартных целых. - * Суммарное количество значимых бит не должно превышать 64. * Пример: i18 -> <3 x i6>. */ void __lccrt_vecbitunpack( void *dst, void *src, int64_t veclen, int64_t elembitsize) { int ebytes = __lccrt_bitwidth_bytesize( elembitsize); - int maskshift = 64 - elembitsize; - int totalbitsize = veclen*elembitsize; - uint64_t v0 = __lccrt_load_bytes( src, __lccrt_bitwidth_bytesize( totalbitsize)); - uint64_t v = v0; + int lcnt = ebytes; + int uoff = 8*ebytes; + uint64_t u0 = 0; + uint64_t u1 = __lccrt_load_bytes( src, ebytes); - assert( (0 <= veclen) && (0 < elembitsize) && (totalbitsize <= 64)); + assert( (0 <= veclen) && (0 < elembitsize) && (elembitsize <= 64)); for ( int i = 0; i < veclen; ++i ) { - uint64_t si = 0; + uint64_t v = __lccrt_get_pair_bits( u0, u1, ebytes, uoff, elembitsize); - si = (v << maskshift) >> maskshift; - v = v >> elembitsize; - __lccrt_store_bytes( (char *)dst + i*ebytes, si, ebytes); + __lccrt_store_bytes( (char *)dst + i*ebytes, v, ebytes); + + uoff = uoff + elembitsize; + if ( uoff + elembitsize > 2*8*ebytes ) { + u0 = u1; + u1 = __lccrt_load_bytes( (char *)src + lcnt, ebytes); + lcnt += ebytes; + uoff = uoff - 8*ebytes; + } } return;