2017-02-07 2 views
0

je type de données appelé TVector comme suit:Pourquoi Free Pascal transmet automatiquement les données d'enregistrement aux registres xmm?

type 
    TVector = record 
     x,y,z,w : single; 
    end; 

et j'ai variables nommées v1 et v2 qui contiennent données suivantes:

v1.x:=1; 
v1.y:=2; 
v1.z:=3; 
v1.w:=4; 

v2.x:=5; 
v2.y:=6; 
v2.z:=7; 
v2.w:=8; 

Les deux variables sont passées à la méthode comme suit:

function TSSEVectorOperation.add(const vect1: TVector; const vect2: TVector): TVector; assembler; 
asm 
    ... 
    addps xmm1, xmm2 
    movaps xmm0, xmm1 
    ... 
end; 

Lorsque je débogue et passe à la méthode add() en utilisant Lazarus IDE (dans Ubuntu), j'ai appris que dans un premier xmm0 - xmm3 registres contiennent des valeurs de v1 et v2 dans l'ordre suivant

xmm0 = {1,2,0,0} 
xmm1 = {3,4,0,0} 
xmm2 = {5,6,0,0} 
xmm3 = {7,8,0,0} 

Ma question est pourquoi Free Pascal, il fait comme ça? Pourquoi pas dans l'ordre comme suit?

xmm0 = {1,2,3,4} 
xmm1 = {5,6,7,8} 

ou pourquoi ne pas me laisser attribuer manuellement une valeur aux registres xmm? Quelque chose comme:

movaps xmm0, vect1 
movaps xmm1, vect2 
+0

C'est la convention d'appel de plateforme qui détermine cela. –

+0

Cela a du sens. La convention d'appel par défaut est 'register' qui essaie de transmettre des données pour s'enregistrer autant que possible. –

+0

Non. Sur x64, la plate-forme définit la convention d'appel et le registre, stdcall, cdecl etc. sont tous ignorés. –

Répondre

1

Comme l'a souligné Michael Petch dans le commentaire et après avoir creusé le document System V ABI. FreePascal suit la convention d'appel ABI x86-64 (mon ubuntu est 14.04 LTS 64 bits) qui transmettra les paramètres à virgule flottante aux registres xmm dans l'ordre indiqué dans ma question.

Ainsi, afin de combiner faible quadword de xmm0 et xmm1 registres dans xmm0 registre, je dois utiliser movlhps instruction

movlhps xmm0, xmm1 

Même chose avec xmm2 et xmm3 registres.

La fonction qui renvoie une valeur à virgule flottante doit stocker son résultat dans le registre xmm0. Si le résultat est supérieur à 64 bits en virgule flottante, alors 64 bits restants vont au registre xmm1. Donc, pour mon cas, cela devrait être

xmm0 = {result.x, result.y, (not used), (not used)} 
xmm1 = {result.z, result.w, (not used), (not used)}