2012-08-08 13 views

Odpowiedz

0

po kilku testach wygląda na to następujący kod działa popraw:

int32_t _mm_movemask_epi8_neon(uint8x16_t input) 
{ 
    const int8_t __attribute__ ((aligned (16))) xr[8] = {-7,-6,-5,-4,-3,-2,-1,0}; 
    uint8x8_t mask_and = vdup_n_u8(0x80); 
    int8x8_t mask_shift = vld1_s8(xr); 

    uint8x8_t lo = vget_low_u8(input); 
    uint8x8_t hi = vget_high_u8(input); 

    lo = vand_u8(lo, mask_and); 
    lo = vshl_u8(lo, mask_shift); 

    hi = vand_u8(hi, mask_and); 
    hi = vshl_u8(hi, mask_shift); 

    lo = vpadd_u8(lo,lo); 
    lo = vpadd_u8(lo,lo); 
    lo = vpadd_u8(lo,lo); 

    hi = vpadd_u8(hi,hi); 
    hi = vpadd_u8(hi,hi); 
    hi = vpadd_u8(hi,hi); 

    return ((hi[0] << 8) | (lo[0] & 0xFF)); 
} 
0

Zauważ, że nie testowałem żadnej z tego, ale coś takiego może działać:

X := the vector that you want to create the mask from 
A := 0x808080808080... 
B := 0x00FFFEFDFCFB... (i.e. 0,-1,-2,-3,...) 

X = vand_u8(X, A); // Keep d7 of each byte in X 
X = vshl_u8(X, B); // X[7]>>=0; X[6]>>=1; X[5]>>=2; ... 
// Each byte of X now contains its msb shifted 7-N bits to the right, where N 
// is the byte index. 
// Do 3 pairwise adds in order to pack all these into X[0] 
X = vpadd_u8(X, X); 
X = vpadd_u8(X, X); 
X = vpadd_u8(X, X); 
// X[0] should now contain the mask. Clear the remaining bytes if necessary 

To musiałyby być powtarzane raz przetworzyć 128-bitowy wektor, ponieważ vpadd działa tylko na 64 lat -bitowe wektory.

+0

Witam @Michael thanx na przykład. czy możesz wyjaśnić, w jaki sposób mogę wypełnić wektor B wymaganymi bajtami? dla A mogę używać vdup_n_u8 (0x80), ale jak mam to zrobić dla A? również piszesz vshl_u8, ale w komentarzu jest odpowiednia zmiana? – inspirit

+0

Aby zainicjować wektor B: 'vld1' z tablicy stałej (?). O prawej zmianie: dokumentacja ARM stwierdza _ "Jeśli wartość przesunięcia jest dodatnia, operacja jest przesunięciem w lewo, w przeciwnym razie jest to przesunięcie w prawo." _. Nie jestem do końca pewien, czy tak jest w przypadku, gdy przenoszone dane to 'u8', czy też musisz użyć' s8'. – Michael

+0

Tak, rozumiem, że muszę załadować B z tablicy i zastanawiałem się nad dostarczonymi wartościami w tym wektorze. możesz być bardziej konkretny na ten temat? powinno być tylko [0, -1, -2, -3, -4, -5, -6, -7]? i tak, potrzebuję go do wektora danych u8 w tej chwili – inspirit

5

Znam ten post jest dość przestarzały, ale uważam, że warto dać (zatwierdzone) rozwiązanie mojego. Przyjmuje wszystkie zera/wszystkie zera na każdym z pasm argumentu Input.

const uint8_t __attribute__ ((aligned (16))) _Powers[16]= 
    { 1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128 }; 

// Set the powers of 2 (do it once for all, if applicable) 
uint8x16_t Powers= vld1q_u8(_Powers); 

// Compute the mask from the input 
uint64x2_t Mask= vpaddlq_u32(vpaddlq_u16(vpaddlq_u8(vandq_u8(Input, Powers)))); 

// Get the resulting bytes 
uint16_t Output; 
vst1q_lane_u8((uint8_t*)&Output + 0, (uint8x16_t)Mask, 0); 
vst1q_lane_u8((uint8_t*)&Output + 1, (uint8x16_t)Mask, 8); 

(umysł http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47553, w każdym razie).

Podobnie jak Michael, sztuką jest stworzenie uprawnienia indeksów tych wpisów niż null i podsumować je parami trzy razy. Należy to zrobić, zwiększając rozmiar danych, aby podwoić krok przy każdym dodaniu. Zmniejszasz z 2 8 8-bitowych wpisów do 2 x 4 16-bitowych, a następnie 2 x 2 32-bitowych i 2 x 1 64-bitowych. Niski bajt tych dwóch liczb daje rozwiązanie. Nie sądzę, że istnieje prosty sposób na spakowanie ich w jedną krótką wartość za pomocą NEON.

Wykonuje 6 instrukcji NEON, jeśli wejście jest w odpowiedniej formie, a moce mogą być wstępnie ładowane.

Powiązane problemy