diff --git a/src/fdr/fdr_loadval.h b/src/fdr/fdr_loadval.h index 37baf823..86c39c7f 100644 --- a/src/fdr/fdr_loadval.h +++ b/src/fdr/fdr_loadval.h @@ -29,13 +29,12 @@ #ifndef FDR_LOADVAL_H #define FDR_LOADVAL_H -#include "fdr_internal.h" #include "ue2common.h" #include "util/unaligned.h" -#include "util/simd_utils.h" -#define MAKE_LOADVAL(type, name) \ - static really_inline type name (const u8 * ptr, UNUSED const u8 * lo, UNUSED const u8 * hi) +#define MAKE_LOADVAL(type, name) \ + static really_inline \ + type name(const u8 *ptr, UNUSED const u8 *lo, UNUSED const u8 *hi) #define NORMAL_SAFE(type) \ do { \ @@ -43,179 +42,30 @@ assert(ptr + sizeof(type) - 1 < hi); \ } while(0) -#define ALIGNED_SAFE(type) NORMAL_SAFE(type); assert(((size_t)ptr % sizeof(type)) == 0); -// these ones need asserts to test the property that we're not handling dynamically -#define CAUTIOUS_FORWARD_SAFE(type) assert(ptr >= lo) -#define CAUTIOUS_BACKWARD_SAFE(type) assert((ptr + sizeof(type) - 1) < hi) - -#define CF_INDEX_CHECK (ptr + i < hi) -#define CB_INDEX_CHECK (lo <= ptr + i) -#define CE_INDEX_CHECK (lo <= ptr + i) && (ptr + i < hi) - -#define MAKE_LOOP(TYPE, COND, SHIFT_FIDDLE) \ - TYPE v = 0; \ - for (TYPE i = 0; i < sizeof(TYPE); i++) { \ - if (COND) { \ - v += (TYPE)ptr[i] << ((SHIFT_FIDDLE)*8); \ - } \ - } \ +#define MAKE_LOOP_CE(TYPE) \ + TYPE v = 0; \ + for (TYPE i = 0; i < sizeof(TYPE); i++) { \ + if ((lo <= ptr + i) && (ptr + i < hi)) { \ + v += (TYPE)ptr[i] << (i*8); \ + } \ + } \ return v; -#define MAKE_LOOP_BE(TYPE, COND) \ - MAKE_LOOP(TYPE, COND, sizeof(TYPE)-i-1) - -#define MAKE_LOOP_LE(TYPE, COND) \ - MAKE_LOOP(TYPE, COND, i) - - -#define MAKE_LOOP_BE_CF(TYPE) CAUTIOUS_FORWARD_SAFE(TYPE); MAKE_LOOP_BE(TYPE, CF_INDEX_CHECK) -#define MAKE_LOOP_BE_CB(TYPE) CAUTIOUS_BACKWARD_SAFE(TYPE); MAKE_LOOP_BE(TYPE, CB_INDEX_CHECK) -#define MAKE_LOOP_BE_CE(TYPE) MAKE_LOOP_BE(TYPE, CE_INDEX_CHECK) -#define MAKE_LOOP_LE_CF(TYPE) CAUTIOUS_FORWARD_SAFE(TYPE); MAKE_LOOP_LE(TYPE, CF_INDEX_CHECK) -#define MAKE_LOOP_LE_CB(TYPE) CAUTIOUS_BACKWARD_SAFE(TYPE); MAKE_LOOP_LE(TYPE, CB_INDEX_CHECK) -#define MAKE_LOOP_LE_CE(TYPE) MAKE_LOOP_LE(TYPE, CE_INDEX_CHECK) - // no suffix = normal (unaligned) -// _a = aligned -// _cf = cautious forwards, base is always in bounds, but may read over the end of the buffer (test against hi) -// _cb = cautious backwards, final byte is always in bounds, but may read over the start of the buffer (test against lo) // _ce = cautious everywhere (in both directions); test against hi and lo -// u8 loadvals -MAKE_LOADVAL(u8, lv_u8) { - NORMAL_SAFE(u8); - return *ptr; -} - -MAKE_LOADVAL(u8, lv_u8_cf) { - CAUTIOUS_FORWARD_SAFE(u8); - if (ptr < hi) { - return *ptr; - } else { - return 0; - } -} - -MAKE_LOADVAL(u8, lv_u8_cb) { - CAUTIOUS_BACKWARD_SAFE(u8); - if (lo <= ptr) { - return *ptr; - } else { - return 0; - } -} - -MAKE_LOADVAL(u8, lv_u8_ce) { - if ((lo <= ptr) && (ptr < hi)) { - return *ptr; - } else { - return 0; - } -} - MAKE_LOADVAL(u16, lv_u16) { NORMAL_SAFE(u16); return unaligned_load_u16(ptr); } -MAKE_LOADVAL(u16, lv_u16_a) { - ALIGNED_SAFE(u16); - return *(const u16 *)ptr; -} - -MAKE_LOADVAL(u32, lv_u32) { - NORMAL_SAFE(u32); - return unaligned_load_u32(ptr); -} - -MAKE_LOADVAL(u32, lv_u32_a) { - ALIGNED_SAFE(u32); - return *(const u32 *)ptr; -} - MAKE_LOADVAL(u64a, lv_u64a) { NORMAL_SAFE(u32); return unaligned_load_u64a(ptr); } -MAKE_LOADVAL(u64a, lv_u64a_a) { - ALIGNED_SAFE(u64a); - return *(const u64a *)ptr; -} +MAKE_LOADVAL(u16, lv_u16_ce) { MAKE_LOOP_CE(u16); } -MAKE_LOADVAL(u16, lv_u16_cf) { MAKE_LOOP_LE_CF(u16); } -MAKE_LOADVAL(u16, lv_u16_cb) { MAKE_LOOP_LE_CB(u16); } -MAKE_LOADVAL(u16, lv_u16_ce) { MAKE_LOOP_LE_CE(u16); } - -MAKE_LOADVAL(u32, lv_u32_cf) { MAKE_LOOP_LE_CF(u32); } -MAKE_LOADVAL(u32, lv_u32_cb) { MAKE_LOOP_LE_CB(u32); } -MAKE_LOADVAL(u32, lv_u32_ce) { MAKE_LOOP_LE_CE(u32); } - -MAKE_LOADVAL(u64a, lv_u64a_cf) { MAKE_LOOP_LE_CF(u64a); } -MAKE_LOADVAL(u64a, lv_u64a_cb) { MAKE_LOOP_LE_CB(u64a); } -MAKE_LOADVAL(u64a, lv_u64a_ce) { MAKE_LOOP_LE_CE(u64a); } - -MAKE_LOADVAL(m128, lv_m128) { - NORMAL_SAFE(m128); - return loadu128(ptr); -} - -MAKE_LOADVAL(m128, lv_m128_a) { - ALIGNED_SAFE(m128); - assert((size_t)ptr % sizeof(m128) == 0); - return *(const m128 *)ptr; -} - -// m128 cases need to be manually created - -MAKE_LOADVAL(m128, lv_m128_cf) { - CAUTIOUS_FORWARD_SAFE(m128); - union { - u8 val8[16]; - m128 val128; - } u; - - for (u32 i = 0; i < 16; i++) { - if (ptr + i < hi) { - u.val8[i] = ptr[i]; - } else { - u.val8[i] = 0; - } - } - return u.val128; -} - -MAKE_LOADVAL(m128, lv_m128_cb) { - CAUTIOUS_BACKWARD_SAFE(m128); - union { - u8 val8[16]; - m128 val128; - } u; - - for (u32 i = 0; i < 16; i++) { - if (lo <= ptr + i) { - u.val8[i] = ptr[i]; - } else { - u.val8[i] = 0; - } - } - return u.val128; -} - -MAKE_LOADVAL(m128, lv_m128_ce) { - union { - u8 val8[16]; - m128 val128; - } u; - - for (u32 i = 0; i < 16; i++) { - if ((lo <= ptr + i) && (ptr + i < hi)) { - u.val8[i] = ptr[i]; - } else { - u.val8[i] = 0; - } - } - return u.val128; -} +MAKE_LOADVAL(u64a, lv_u64a_ce) { MAKE_LOOP_CE(u64a); } #endif diff --git a/unit/internal/fdr_loadval.cpp b/unit/internal/fdr_loadval.cpp index ba5ae692..22fee770 100644 --- a/unit/internal/fdr_loadval.cpp +++ b/unit/internal/fdr_loadval.cpp @@ -39,55 +39,26 @@ using namespace ue2; // Normal (unaligned) load. template T lv(const u8 *ptr, const u8 *lo, const u8 *hi); -// Aligned load. -template T lv_a(const u8 *ptr, const u8 *lo, const u8 *hi); - -// Cautious forward load. -template T lv_cf(const u8 *ptr, const u8 *lo, const u8 *hi); - -// Cautious backward load. -template T lv_cb(const u8 *ptr, const u8 *lo, const u8 *hi); - // Cautious everywhere load. template T lv_ce(const u8 *ptr, const u8 *lo, const u8 *hi); -// Special case: there is no specific _a "aligned load" func for u8. We proxy -// that to the normal load. -static u8 lv_u8_a(const u8 *ptr, const u8 *lo, const u8 *hi) { - return lv_u8(ptr, lo, hi); -} - #define BUILD_LOADVALS(vtype) \ template <> vtype lv(const u8 *ptr, const u8 *lo, const u8 *hi) { \ return lv_##vtype(ptr, lo, hi); \ } \ - template <> vtype lv_a(const u8 *ptr, const u8 *lo, const u8 *hi) { \ - return lv_##vtype##_a(ptr, lo, hi); \ - } \ - template <> \ - vtype lv_cf(const u8 *ptr, const u8 *lo, const u8 *hi) { \ - return lv_##vtype##_cf(ptr, lo, hi); \ - } \ - template <> \ - vtype lv_cb(const u8 *ptr, const u8 *lo, const u8 *hi) { \ - return lv_##vtype##_cb(ptr, lo, hi); \ - } \ template <> \ vtype lv_ce(const u8 *ptr, const u8 *lo, const u8 *hi) { \ return lv_##vtype##_ce(ptr, lo, hi); \ } -BUILD_LOADVALS(u8) BUILD_LOADVALS(u16) -BUILD_LOADVALS(u32) BUILD_LOADVALS(u64a) -BUILD_LOADVALS(m128) template class FDR_Loadval : public testing::Test { // empty }; -typedef ::testing::Types LoadvalTypes; +typedef ::testing::Types LoadvalTypes; TYPED_TEST_CASE(FDR_Loadval, LoadvalTypes); @@ -114,73 +85,6 @@ TYPED_TEST(FDR_Loadval, Normal) { } } -TYPED_TEST(FDR_Loadval, Aligned) { - const size_t len = sizeof(TypeParam); - aligned_unique_ptr mem_p = aligned_zmalloc_unique(len); // 16 aligned - u8 * mem = mem_p.get(); - ASSERT_TRUE(ISALIGNED_16(mem)); - fillWithBytes(mem, len); - - TypeParam val = lv_a(mem, mem, mem + len); - - // Should be identical to 'mem' in byte order. - ASSERT_EQ(0, memcmp(&val, mem, len)); -} - -TYPED_TEST(FDR_Loadval, CautiousForward) { - // For a cautious forward load, we will get zeroes for all bytes after the - // 'hi' ptr. - const size_t len = sizeof(TypeParam); - - aligned_unique_ptr mem_p = aligned_zmalloc_unique(len + 1); - u8 *mem = mem_p.get() + 1; // force unaligned - fillWithBytes(mem, len); - - for (size_t i = 1; i <= len; i++) { - const u8 *ptr = mem; - const u8 *lo = ptr; - const u8 *hi = ptr + i; - union { - TypeParam val; - u8 bytes[sizeof(TypeParam)]; - } x; - - x.val = lv_cf(ptr, lo, hi); - - // Low bytes will be correct, bytes >= hi will be zero. - for (size_t j = 0; j < len; j++) { - ASSERT_EQ(j < i ? mem[j] : 0, x.bytes[j]); - } - } -} - -TYPED_TEST(FDR_Loadval, CautiousBackward) { - // For a cautious backwards load, we will get zeroes for all bytes before - // the 'lo' ptr. - const size_t len = sizeof(TypeParam); - - aligned_unique_ptr mem_p = aligned_zmalloc_unique(len + 1); - u8 *mem = mem_p.get() + 1; // force unaligned - fillWithBytes(mem, len); - - for (size_t i = 1; i <= len; i++) { - const u8 *ptr = mem; - const u8 *lo = ptr + sizeof(TypeParam) - i; - const u8 *hi = ptr + sizeof(TypeParam); - union { - TypeParam val; - u8 bytes[sizeof(TypeParam)]; - } x; - - x.val = lv_cb(ptr, lo, hi); - - // Low bytes will be zero, bytes >= lo will be correct. - for (size_t j = 0; j < len; j++) { - ASSERT_EQ(j < sizeof(TypeParam) - i ? 0 : mem[j], x.bytes[j]); - } - } -} - TYPED_TEST(FDR_Loadval, CautiousEverywhere) { // For a cautious backwards load, we will get zeroes for all bytes before // the 'lo' ptr or after the 'hi' ptr.