2016-04-18 7 views
1

Я портирую рутину, написанную с встроенными функциями Intel SSE2 для 32-разрядных платформ Microsoft. Он отлично работает под GCC, Clang и 64-bit Windows. Исходный код эффективно выполняет следующее:Загрузить __m64 из 64-разрядного целочисленного типа?

typedef unsigned __int64 word64; 

// input is aligned on 16-byte boundary 
void (const byte* input) 
{ 
    const word64 m0 = ((const word64*)input)[ 0]; 
    const word64 m1 = ((const word64*)input)[ 8]; 
    ... 

    __m128 t0 = _mm_set_epi64x(m0, m1); 
} 

Microsoft не предоставляет _mm_set_epi64x на 32-битных платформах, так что я хочу использовать _mm_set_epi64.

Теперь проблемы ... Во-первых,

__m64 m0, m1; 
m0 = *(word64*)(input+0); 

Результаты в:

1> error C2679: binary '=' : no operator found which takes a right-hand operand 
of type 'word64' (or there is no acceptable conversion) 
1> c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\mmintrin.h(42): 
could be '__m64 &__m64::operator =(const __m64 &)' 
1> while trying to match the argument list '(__m64, word64)' 

Во-вторых, пытаясь обойти потенциальную проблему с word64 и использовать unsigned __int64* непосредственно:

m0 = *(unsigned __int64*)(input+0); 

Результаты схожие:

1> blake2.cpp(530): error C2679: binary '=' : no operator found which takes a right-hand 
operand of type 'unsigned __int64' (or there is no acceptable conversion) 

В-третьих, я посмотрел через <mmintrin.h> и нашел _m_from_int:

m0 = _m_from_int(*(word64*)(input+0)); 

Это приводит к:

1> blake2.cpp(529): warning C4244: 'argument' : conversion from 'word64' 
to 'int', possible loss of data 

Я не уверен, что еще попробовать в этой точке.

Как загрузить __m64 из 64-разрядного целочисленного типа?


Ниже заявление Microsoft о __m64, но мы должны рассматривать его как непрозрачный:

typedef union __declspec(intrin_type) _CRT_ALIGN(8) __m64 
{ 
    unsigned __int64 m64_u64; 
    float    m64_f32[2]; 
    __int8    m64_i8[8]; 
    __int16    m64_i16[4]; 
    __int32    m64_i32[2];  
    __int64    m64_i64; 
    unsigned __int8  m64_u8[8]; 
    unsigned __int16 m64_u16[4]; 
    unsigned __int32 m64_u32[2]; 
} __m64; 
+0

http: // stackoverflow.com/questions/27258261/msvc-avx-code-compilation-mm256-setr-epi64x/27267287 # 27267287 –

ответ

1

Сначала я заметил, что ваш вход массив байтов. При преобразовании из массива байтов в многобайтовый двоичный файл (например, int64) вам может потребоваться рассмотреть порядок байтов. Для целей этого вопроса я собираюсь игнорировать эту проблему, но если вы получите что-то, что «выглядит неправильно», это то, что нужно учитывать.

В первой ошибке у компилятора возникает проблема с преобразованием с вашего разыменованного указателя на word64 (без знака __int64). У меня нет готового доступа к заголовкам, но я подозреваю, что это может иметь отношение к «const'ing». Вам нужен оператор копирования, но я считаю, что вы получаете оператора назначения. Тот же вопрос для второй ошибки компилятора (m0 = (без знака __int64) (вход + 0);)

Ваша третья ошибка, как представляется, вызвана _m_to_int ожидая подписанную int64 и получить неподписанный int64.

Интересно, если что-то вроде:

const word64 *m0 = ((const word64*)input)[ 0]; 

или

const word64 m0 = &((const word64*)input); 

может работать?

+0

Спасибо, Dweeberly. Если интересно, файл доступен в ['blake2.cpp'] (http://www.cryptopp.com/docs/ref/blake2_8cpp_source.html). Интересующая функция - 'BLAKE2_SSE2_Compress64'. BLAKE2 мало ориентирован. Следует проявлять осторожность в некоторых местах, но не в этой области, поскольку она предназначена для быстрого использования совместимых продуктов IBM, используя собственный порядок байтов. – jww