2016-04-18 16 views
1

Ich portiere eine Routine geschrieben mit Intel SSE2 intrinsics auf Microsoft 32-Bit-Plattformen. Es funktioniert gut unter GCC, Clang und 64-Bit Windows. Der ursprüngliche Code führt effektiv die folgenden:Laden Sie __m64 von einem 64-Bit-Integer-Typ?

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 nicht _mm_set_epi64x auf 32-Bit-Plattformen zur Verfügung stellt, so mag ich _mm_set_epi64 verwenden.

Nun ist die Probleme ... Zuerst

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

Ergebnisse in:

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)' 

Zweitens versucht, das potenzielle Problem umgehen mit word64 und verwendet unsigned __int64* direkt:

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

Ergebnisse auf dem gleichen:

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) 

Drittens sah ich durch <mmintrin.h> und fand _m_from_int:

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

Es ergibt sich:

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

Ich bin mir nicht sicher, was sonst an dieser Stelle zu versuchen.

Wie lade ich eine __m64 von einem 64-Bit-Integer-Typ?


Im Folgenden finden Sie Erklärung Microsoft von __m64, aber wir sollen sie als undurchsichtig behandeln:

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: // Stapelüberlauf.com/fragen/27258261/msvc-avx-code-zusammenstellung-mm256-setr-epi64x/27267287 # 27267287 –

Antwort

1

Zuerst habe ich feststellen, dass Ihre Eingabe ist ein Byte-Array. Bei der Konvertierung von einem Byte-Array in eine Multi-Byte-Binärdatei (wie Int64) müssen Sie möglicherweise die Byte-Reihenfolge berücksichtigen. Für die Zwecke dieser Frage werde ich dieses Problem ignorieren, aber wenn Sie etwas bekommen, das "falsch aussieht", ist es etwas zu beachten.

Im ersten Fehler hat der Compiler der Compiler ein Problem von Ihrem dereferenzierten Zeiger auf ein Word64 konvertieren (unsigned __int64). Ich habe keinen schnellen Zugriff auf die Header, aber ich vermute, dass das mit dem "const" zu tun haben könnte. Sie möchten einen Kopieroperator, aber ich glaube, Sie erhalten den Zuweisungsoperator. Gleiches Problem für Ihren zweiten Compiler-Fehler (m0 = (unsigned __int64) (Eingang + 0);)

Ihre dritten Fehler angezeigt durch _m_to_int erwartete ein signiertes int64 und erhalte eine unsigned int64 verursacht werden.

Ich frage mich, ob so etwas wie:

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

oder

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

funktionieren könnte?

+0

Dank Dweeberly. Bei Interesse steht die Datei unter ['blake2.cpp'] (http://www.cryptop.com/docs/ref/blake2_8cpp_source.html) zur Verfügung. Die Funktion von Interesse ist "BLAKE2_SSE2_Compress64". Blake2 ist Little Endian. Es muss an einigen Stellen vorsichtig vorgegangen werden, aber nicht in diesem Bereich, da IBM unter Verwendung der systemeigenen Byte-Reihenfolge schnell auf IBM-kompatiblen Systemen ausgeführt werden sollte. – jww