2017-02-23 4 views
0

Ich habe eine 16-Byte-Permutation uint8_t[16] Maske und ein 16-Byte-Datenfeld uint32_t[4]. Ich möchte "shuffle" diese Arraydaten vtbl wie die Verwendung von:Endianness Verwechslung mit ARM Neon vtbx

  0 1 2 3 4 5 6 7 8 9 A B C D E F 
    Data ||0x0,0x0,0x1,0x2|0x0,0x3,0x0,0x4||0x5,0x6, 0x7, 0x8| 0x0, 0x0, 0x0, 0x9|| 

SMask ||0x2,0x3,0x5,0x6|0x7,0x8,0x9,0xA||0xB,0xF,0x10,0x10|0x10,0x10,0x10,0x10|| 

Result ||0x1,0x2,0x3,0x0|0x4,0x5,0x6,0x7||0x8,0x9, 0x0, 0x0| 0x0, 0x0, 0x0, 0x0|| 

Dies ist mein Code so weit:

#include <iostream> 
#include <arm_neon.h> 

inline uint8x16_t Shuffle(const uint8x16_t & src, const uint8x16_t & shuffle) { 
    return vcombine_u8(
      vtbl2_u8(
      (const uint8x8x2_t &)src, 
      vget_low_u8(shuffle) 
     ), 
      vtbl2_u8(
      (const uint8x8x2_t &)src, 
      vget_high_u8(shuffle) 
     ) 
     ); 
} 

int main() { 
    uint32_t* data32 = new uint32_t[4]; 
    data32[0] = 258;    // [0x00 0x00 0x01 0x02] 
    data32[1] = 196612;   // [0x00 0x03 0x00 0x04] 
    data32[2] = 84281096;  // [0x05 0x06 0x07 0x08] 
    data32[3] = 9;    // [0x00 0x00 0x00 0x09]  
    /*load structure*/ 
    uint32x4_t data32Vec = vld1q_u32(data32); 

    uint8_t* sMask = new uint8_t[16]; 
    sMask[0] = 2; 
    sMask[1] = 3; 
    sMask[2] = 5; 
    sMask[3] = 6; 
    sMask[4] = 7; 
    sMask[5] = 8; 
    sMask[6] = 9; 
    sMask[7] = 10; 
    sMask[8] = 11; 
    sMask[9] = 15; 
    sMask[10] = 16; 
    sMask[11] = 16; 
    sMask[12] = 16; 
    sMask[13] = 16; 
    sMask[14] = 16; 
    sMask[15] = 16; 
    /*load permutationmask into vector register*/ 
    uint8x16_t shuffleMask = vld1q_u8(sMask); 

    uint8_t* comprData = new uint8_t[16]; 
    /*shuffle the data with the mask and store it into an uint8_t[16]*/ 
    vst1q_u8(comprData, Shuffle(vreinterpretq_u8_u32(data32Vec),shuffleMask)); 
    for(int i = 0; i < 16; ++i) { 
     std::cout << (unsigned)comprData[i] << " " ; 
    } 
    std::cout << std::endl; 
    delete[] comprData; 
    delete[] sMask; 
    delete[] data32; 
    return 0; 
} 

Die Ausgabe sieht wie folgt aus:

0 0 0 3 0 8 7 6 5 0 0 0 0 0 0 0 

Es sollte so sein:

1 2 3 0 4 5 6 7 8 9 0 0 0 0 0 0 

Ich denke, es hat etwas mit Endianness zu tun, aber sehe das Problem einfach nicht. Hat jemand einen Hinweis?

ich den Code in Bezug auf die Antwort von ErmIg aktualisiert. Das Hauptproblem war, dass ich vtbx und vtbl durcheinander brachte.

Mit freundlichen Grüßen

Antwort

1

Vielleicht hilft es Ihnen (ich diese Funktionen verwendet Bytes innerhalb Vektor mischen für Arm NEON):

inline uint8x16_t Shuffle(const uint8x16_t & src, const uint8x16_t & shuffle) 
    { 
     return vcombine_u8(
      vtbl2_u8((const uint8x8x2_t &)src, vget_low_u8(shuffle)), 
      vtbl2_u8((const uint8x8x2_t &)src, vget_high_u8(shuffle))); 
    } 

    inline uint8x16_t Shuffle(const uint8x16x2_t & src, const uint8x16_t & shuffle) 
    { 
     return vcombine_u8(
      vtbl4_u8((const uint8x8x4_t &)src, vget_low_u8(shuffle)), 
      vtbl4_u8((const uint8x8x4_t &)src, vget_high_u8(shuffle))); 
    } 
+0

Ich dachte vtbl2 ein Zielregister auf den ersten Parameter muss? Aber das sieht gut aus. In der Tat glaube ich, dass ich das Verhalten von vtbl und vtbx verwechselt habe. Vtbl ist was ich brauche, daher wird NULL eingefügt, wenn der Index außerhalb des Bereichs liegt. Ich dachte ursprünglich, dass vtbx dieses Verhalten haben würde :( – Hymir