Question

Ceci est la première fois que je suis poster une question sur StackOverflow, donc s'il vous plaît essayer de fermer les yeux sur les erreurs j'ai fait dans le formatage ma question / code. Mais s'il vous plaît faire le point même à moi afin que je puisse être plus prudent.

Je tente d'écrire quelques simples routines pour l'ajout intrinsèques de deux nombres de 128 bits (contenant 4 variables float). J'ai trouvé un code sur le net et ai essayé de le faire fonctionner sur mon système. Le code est le suivant:

 //this is a sample Intrinsics program to add two vectors.

    #include <iostream>  
    #include <iomanip>      
    #include <xmmintrin.h>  
    #include <stdio.h>

    using namespace std;

    struct vector4 {  
        float x, y, z, w;    };   

    //functions to operate on them.  
    vector4 set_vector(float x, float y, float z, float w = 0) {     
        vector4 temp;  
        temp.x = x;   
        temp.y = y;   
        temp.z = z;  
        temp.w = w;  
        return temp;  
    }    


    void print_vector(const vector4& v) {   
        cout << " This is the contents of vector: " << endl;  
        cout << " > vector.x = " << v.x << endl;  
        cout << " vector.y = " << v.y << endl;  
        cout << " vector.z = " << v.z << endl;  
        cout << " vector.w = " << v.w << endl;  
    }

    vector4 sse_vector4_add(const vector4&a, const vector4& b) {  
        vector4 result;  

        asm volatile (  
          "movl $a, %eax" //move operands into registers.  
          "\n\tmovl $b, %ebx"  
          "\n\tmovups  (%eax), xmm0"  //move register contents into SSE registers.  
          "\n\tmovups (%ebx), xmm1"  
          "\n\taddps xmm0, xmm1" //add the elements. addps operates on single-precision vectors.    
          "\n\t movups xmm0, result" //move result into vector4 type data.  
        );
        return result;  
    }

    int main() {     
        vector4 a, b, result;  
        a = set_vector(1.1, 2.1, 3.2, 4.5);   
        b = set_vector(2.2, 4.2, 5.6);    
        result = sse_vector4_add(a, b);    
        print_vector(a);  
        print_vector(b);    
        print_vector(result);
        return 0;
    }

Le g ++ paramètres que j'utilise sont:

g++ -Wall -pedantic -g -march=i386 -msse intrinsics_SSE_example.C -o h

Les erreurs que je reçois sont les suivantes:

intrinsics_SSE_example.C: Assembler messages:  
intrinsics_SSE_example.C:45: Error: too many memory references for movups  
intrinsics_SSE_example.C:46: Error: too many memory references for movups  
intrinsics_SSE_example.C:47: Error: too many memory references for addps  
intrinsics_SSE_example.C:48: Error: too many memory references for movups  

J'ai passé beaucoup de temps à essayer de déboguer ces erreurs, les googlé et ainsi de suite. Je suis un noob complet à Intrinsics et ainsi peut-être négligé des choses importantes.

Toute aide est appréciée,
Merci,
Sriram.

Était-ce utile?

La solution

Vous utilisez des blocs ASM, pas intrinsèque.

Étant donné que les registres sont XMMX, vous devez les préfixe avec un %:

      "\n\tmovups  (%eax), %xmm0"
      // etc.

Et votre ASM est a plusieurs erreurs.

  1. vous ne devriez pas modifier le registre de ebx.
  2. $a etc est considéré comme un symbole mondial de l'assembleur, qui n'est pas.
  3. addps %xmm0, %xmm1 va stocker le résultat dans XMM1. Rappelez-vous dans la syntaxe AT & T la destination se trouve à droite.

Le bloc ASM corrigé serait comme

    asm volatile (  
      "movl %1, %%eax"
      "\n\tmovl %2, %%ecx"  
      "\n\tmovups  (%%eax), %%xmm0"
      "\n\tmovups (%%ecx), %%xmm1"  
      "\n\taddps %%xmm0, %%xmm1"
      "\n\tmovups %%xmm0, %0"
      : "=m"(result)
      : "r"(&a), "r"(&b)
      : "eax", "ecx");

Fondamentalement,% 0 sera remplacé par l'adresse de result,% 1% et 2 sont remplacés par &a et &b. Voir http://www.ibiblio.org/gferg/ldp /GCC-Inline-Assembly-HOWTO.html pour une explication détaillée. Les "eax", "ecx" empêche ces 2 registres d'être utilisés en remplacement de ceux% n.

Mais les 2 premières années de movl sont inutiles ...

    asm volatile(  
      "\n\tmovups (%1), %%xmm0"
      "\n\tmovups (%2), %%xmm1"  
      "\n\taddps %%xmm1, %%xmm0"
      "\n\tmovups %%xmm0, %0"
      : "=m"(result)
      : "r"(&a), "r"(&b));

Puisque vous avez mentionné intrinsèque, pourquoi ne pas utiliser __builtin_ia32_addps?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top