Erreur: utilisation non valide du registre de vecteur sur l’opérande 1

J’apprends l’assembleur en ligne GCC sous ARM sur un périphérique Aarch64 64 bits. Je vois un message d’erreur que je ne comprends pas bien. Le message d’erreur de l’assembleur en ligne de GCC:

$ gcc -DNDEBUG -g3 -O1 -march=armv8-a+crc+crypto test.cc -o test.exe /tmp/ccCHOWrn.s: Assembler messages: /tmp/ccCHOWrn.s:19: Error: invalid use of vector register at operand 1 -- `pmull v0,v0,v0' 

Le programme exemple tente simplement d’exercer la multiplication polynomiale:

 $ cat test.cc #include  int main(int argc, char* argv[]) { uint64x2_t r = {0,0}, a = {2,4}; __asm__ __volatile__ ( "pmull %0, %1, %1;" : "=w" (r) : "w" (a), "w" (a) : "cc" ); return (int)r[0]; } 

Le "w" est une contrainte de machine Aarch64 . Dans ce cas, il est décrit comme “Registre à virgule flottante ou SIMD” , qui semble être ce que je veux.

Le type uint64x2_t est généralement utilisé avec les éléments insortingnsèques ARM. Mais c’est un type 128 bits et aligné pour le coprocesseur SIMD, donc cela semblait être un bon choix pour l’échantillon.

Le périphérique est une LeMaker HiKey avec une image Linaro et un compilateur GCC 4.9.2. On dirait que ce bogue a été corrigé il y a quelques années, mais je ne sais pas si c’est lié: fbb ftbfs sur arm64 .

J’ai deux questions:

  • Que signifie l’erreur et comment puis-je la réparer?
  • Existe-t-il un pmull insortingnsèque pour pmull et pmull2 ?

J’ai essayé d’append les spécificateurs d’arrangement, mais je ne suis pas surpris que cela ne fonctionne pas car je ne connais pas la syntaxe:

 $ gcc -DNDEBUG -g3 -O1 -march=armv8-a+crc+crypto test.cc -o test.exe test.cc: In function 'int main(int, char**)': test.cc:8:15: error: expected ')' before numeric constant : "=w" (r.1q) ^ test.cc:8:15: error: expected ')' before numeric constant test.cc:9:6: error: expected ';' before ':' token : "w" (a.1d), "w" (a.1d) ^ test.cc:9:6: error: expected primary-expression before ':' token 

J’ai également essayé d’append des signes de pourcentage double ( %%0 et %%1 ), car l’assembleur avait des problèmes avec .att_stntax et .intel_syntax :

 $ gcc -DNDEBUG -g3 -O1 -march=armv8-a+crc+crypto test.cc -o test.exe /tmp/ccPpnvUP.s: Assembler messages: /tmp/ccPpnvUP.s:19: Error: operand 1 should be a SIMD vector register -- `pmull %0,%1,%1' 

Que signifie l’erreur et comment puis-je la réparer?

Je suppose que l’erreur signifie qu’une violation de contrainte s’est produite. Il semblerait que ce qui suit fasse l’affaire:

 $ cat test.cc #include  #include  int main(int argc, char* argv[]) { uint64x2_t r = {0,0}, a = {2,4}; __asm__ __volatile__ ( "pmull %0.1q, %1.1d, %1.1d;" : "=w" (r) : "w" (a[0]), "w" (a[1]) : "cc" ); fprintf(stdout, "%d, %d\n", r[0], r[1]); return 0; } 

Et:

 $ gcc -march=armv8-a+crc+crypto test.cc -o test.exe $ ./test.exe 4, 0 

Et :

 $ gdb -batch -ex 'disassemble main' ./test.exe Dump of assembler code for function main: 0x00000000004005f0 <+0>: stp x29, x30, [sp,#-64]! 0x00000000004005f4 <+4>: mov x29, sp 0x00000000004005f8 <+8>: str w0, [x29,#28] 0x00000000004005fc <+12>: str x1, [x29,#16] 0x0000000000400600 <+16>: movi v0.4s, #0x0 0x0000000000400604 <+20>: mov x0, v0.d[0] 0x0000000000400608 <+24>: mov x1, v0.d[1] 0x000000000040060c <+28>: fmov d0, x0 0x0000000000400610 <+32>: mov v0.d[1], x1 0x0000000000400614 <+36>: str q0, [x29,#48] 0x0000000000400618 <+40>: ldr q0, 0x4006a0 0x000000000040061c <+44>: mov x0, v0.d[0] 0x0000000000400620 <+48>: mov x1, v0.d[1] 0x0000000000400624 <+52>: fmov d0, x0 0x0000000000400628 <+56>: mov v0.d[1], x1 0x000000000040062c <+60>: str q0, [x29,#32] 0x0000000000400630 <+64>: ldr x0, [x29,#32] 0x0000000000400634 <+68>: ldr x1, [x29,#40] 0x0000000000400638 <+72>: fmov d0, x0 0x000000000040063c <+76>: fmov d1, x1 0x0000000000400640 <+80>: pmull v0.1q, v0.1d, v0.1d 0x0000000000400644 <+84>: mov x0, v0.d[0] 0x0000000000400648 <+88>: mov x1, v0.d[1] 0x000000000040064c <+92>: fmov d0, x0 0x0000000000400650 <+96>: mov v0.d[1], x1 0x0000000000400654 <+100>: str q0, [x29,#48] 0x0000000000400658 <+104>: adrp x0, 0x410000 0x000000000040065c <+108>: add x0, x0, #0x9f0 0x0000000000400660 <+112>: ldr x4, [x0] 0x0000000000400664 <+116>: ldr x1, [x29,#48] 0x0000000000400668 <+120>: ldr x2, [x29,#56] 0x000000000040066c <+124>: adrp x0, 0x400000 0x0000000000400670 <+128>: add x0, x0, #0x748 0x0000000000400674 <+132>: mov x3, x2 0x0000000000400678 <+136>: mov x2, x1 0x000000000040067c <+140>: mov x1, x0 0x0000000000400680 <+144>: mov x0, x4 0x0000000000400684 <+148>: bl 0x4004a0  0x0000000000400688 <+152>: mov w0, #0x0 // #0 0x000000000040068c <+156>: ldp x29, x30, [sp],#64 0x0000000000400690 <+160>: ret End of assembler dump. 

Existe-t-il un élément insortingnsèque pour pmull et pmull2?

Il semble y avoir des éléments insortingnsèques:

 $ gcc -march=armv8-a+crc+crypto -E test.cc | grep -B 4 pmull __extension__ static __inline poly16x8_t __atsortingbute__ ((__always_inline__)) vmull_high_p8 (poly8x16_t a, poly8x16_t b) { poly16x8_t result; __asm__ ("pmull2 %0.8h,%1.16b,%2.16b" -- __extension__ static __inline poly16x8_t __atsortingbute__ ((__always_inline__)) vmull_p8 (poly8x8_t a, poly8x8_t b) { poly16x8_t result; __asm__ ("pmull %0.8h, %1.8b, %2.8b" -- static __inline poly128_t vmull_p64 (poly64_t a, poly64_t b) { return __builtin_aarch64_crypto_pmulldi_ppp (a, b); -- static __inline poly128_t vmull_high_p64 (poly64x2_t a, poly64x2_t b) { return __builtin_aarch64_crypto_pmullv2di_ppp (a, b);