Bonsoir, je suis entrain de porter ma bibliothèques sur les vecteurs, matrices ect... réalisée avec Lazarus vers Delphi. Je suis confronté à un problème.

Par exemple :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
function get_mxcsr:dword;
var _flags:dword;
begin
     asm    stmxcsr _flags end;
     get_mxcsr:=_flags;
end;
 
procedure set_mxcsr(flags:dword);
var _flags:dword;
begin
     _flags:=flags;
     asm    ldmxcsr _flags end;
end;
Ces deux méthodes fonctionnent parfaitement sous Lazarus que ce soit en 32 ou 64 bits

Sous Delphi elles fonctionnent en 32 bits
Mais en 64 bits le compilateur me renvoie l'erreur suivante : [dcc64 Erreur] beanz.vectormath.pas(3274): E1025 Fonctionnalité de langage non supportée : 'ASM'

En 64 bits il semblerai que l'utilisation d'un bloc assembleur dans une méthode, qui n'est pas codée 100% en assembleur soit impossible. Savez vous si il existe une directive ou options de compilation à déclarer ou est ce une limitation due Delphi lui même.

Au pire je pense arriver à me passer de ces deux méthodes en faisant autrement.

dans le même style
j'ai en 32 bits cette fonction

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
function TBZVector4f.AngleBetween(Const A, ACenterPoint : TBZVector4f): Single;
Var
  vResult  :  Single;
begin
  asm
    movups xmm0, [EAX]
    mov    ecx,  [A]            // A is a pointer on the stack
    movups xmm1, [ecx]
    mov    ecx,  [ACenterPoint] // ACenterPoint is a pointer on the stack
    movups xmm2, [ecx]
    subps  xmm0, xmm2
    subps  xmm1, xmm2
    // Normalize xmm0 result in xmm2
    movups xmm3, xmm0
    andps  xmm3, [cSSE_MASK_ONLY_W]
    andps  xmm0, [cSSE_MASK_NO_W]
    movups xmm2, xmm0
    {$IFDEF USE_ASM_SSE_3}
      mulps  xmm0, xmm0
      haddps xmm0, xmm0
      haddps xmm0, xmm0
    {$ELSE}
      mulps  xmm0, xmm0
      movups xmm5, xmm0
      shufps xmm0, xmm5, $4e
      addps  xmm0, xmm5
      movups xmm5, xmm0
      shufps xmm5, xmm5, $11
      addps  xmm0, xmm5
    {$ENDIF}
    {$IFDEF USE_ASM_SIMD_HIGHPRECISION}
      // High Precision
      sqrtps xmm0, xmm0
      divps  xmm2, xmm0
    {$ELSE}
      // Low precision
      rsqrtps xmm0, xmm0       //approximate reciprocal
      mulps   xmm2, xmm0
    {$ENDIF}
    addps  xmm2, xmm3
    // Normalize xmm1 result in xmm4
    movups xmm3, xmm1
    andps  xmm3, [cSSE_MASK_ONLY_W]
    andps  xmm1, [cSSE_MASK_NO_W]
    movups xmm4, xmm1
    {$IFDEF USE_ASM_SSE_3}
      mulps  xmm1, xmm1
      haddps xmm1, xmm1
      haddps xmm1, xmm1
    {$ELSE}
      mulps  xmm1, xmm1
      movups xmm5, xmm1
      shufps xmm1, xmm5, $4e
      addps  xmm1, xmm5
      movups xmm5, xmm1
      shufps xmm5, xmm5, $11
      addps  xmm1, xmm5
    {$ENDIF}
    {$IFDEF USE_ASM_SIMD_HIGHPRECISION}
      // High Precision
      sqrtps xmm1, xmm1
      divps  xmm4, xmm1
    {$ELSE}
      // Low precision
      rsqrtps xmm1, xmm1       //approximate reciprocal
      mulps   xmm4, xmm1
    {$ENDIF}
    addps xmm4,xmm3
 
    // AngleCosine
    movups xmm1, xmm4
    movups xmm0, xmm2 // Copy A
 
    // DotProd  xmm0/xmm1 Result in xmm3
    {$IFDEF USE_ASM_SSE_4}
      dpps   xmm0, xmm1, 01110001b //or $F1
      movups xmm3, xmm0
    {$ELSE}
      {$IFDEF USE_ASM_SSE_3}
        andps  xmm0, [cSSE_MASK_NO_W]
        mulps  xmm1, xmm0
        haddps xmm1, xmm1
        haddps xmm1, xmm1
        movups xmm3, xmm1
      {$ELSE}
        mulps   xmm1, xmm0
        movhlps xmm0, xmm1
        addps   xmm0, xmm1
        shufps  xmm1, xmm1, 00000001b
        addps   xmm1, xmm0
        movups  xmm3, xmm1
     {$ENDIF}
   {$ENDIF}
    // Length xmm2 result in xmm2
    andps xmm2, [cSSE_MASK_NO_W]
    {$IFDEF USE_ASM_SSE_4}
      dpps   xmm2, xmm2, $FF;
      sqrtss xmm2, xmm2
    {$ELSE}
      mulps   xmm2, xmm2
      {$IFDEF USE_ASM_SSE_3}
        haddps xmm2, xmm2
        haddps xmm2, xmm2
        sqrtss xmm2, xmm2
      {$ELSE}
        movhlps xmm1, xmm2
        addss   xmm1, xmm2
        shufps  xmm2, xmm2, $55
        addss   xmm1, xmm2
        sqrtss  xmm2, xmm1
      {$ENDIF}
    {$ENDIF}
    // Lenght  xmm4 result in xmm4
    andps xmm4, [cSSE_MASK_NO_W]
    {$IFDEF USE_ASM_SSE_4}
      dpps   xmm4, xmm4, $FF;
      sqrtss xmm4, xmm4
    {$ELSE}
      mulps   xmm4, xmm4
      {$IFDEF USE_ASM_SSE_3}
        haddps xmm4, xmm4
        haddps xmm4, xmm4
        sqrtss xmm4, xmm4
      {$ELSE}
        movhlps xmm1, xmm4
        addss   xmm1, xmm4
        shufps  xmm4, xmm4, $55
        addss   xmm1, xmm4
        sqrtss  xmm4, xmm1
      {$ENDIF}
    {$ENDIF}
    mulps xmm2, xmm4
    divps xmm3, xmm2
    movss [vResult], xmm3
  end;
  Result := ArcCos(vResult);
end;
que j'ai du séparer en deux pour qu'elle fonctionne en 64bits :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
function PreComputeAngleBetween(Const A, ACenterPoint : TBZVector4f): Single; register;
 asm
    movaps xmm0,[RCX]       //self is still in rcx
   //-------- LAZARUS CODE --------------
   // mov rax, DWORD [A]            // A is a pointer on the stack
   // movups xmm1, [RAX]
  //--------------------------------
    movaps xmm1, [A] // DWORD PTR [RAX]
         //mov rax, [ACenterPoint] // ACenterPoint is a pointer on the stack --> Lazarus
    movaps xmm2, [ACenterPoint] //DWORD PTR  [RAX]
    subps xmm0, xmm2
    subps xmm1, xmm2
 
    // Normalize xmm0 result in xmm2
    movaps xmm3,xmm0
    andps  xmm3, DQWORD PTR [RIP+cSSE_MASK_ONLY_W]
    andps  xmm0, DQWORD PTR [RIP+cSSE_MASK_NO_W]
    movaps xmm2, xmm0
    {$IFDEF USE_ASM_SSE_3}
      mulps  xmm0, xmm0
      //haddps xmm0, xmm0
      //haddps xmm0, xmm0
      movshdup    xmm4, xmm0
      addps       xmm0, xmm1
      movhlps     xmm4, xmm0
      addss       xmm0, xmm4
    {$ELSE}
      mulps xmm0, xmm0
      movaps xmm5, xmm0
      shufps xmm0, xmm5, $4e
      addps xmm0, xmm5
      movaps xmm5, xmm0
      shufps xmm5, xmm5, $11
      addps xmm0, xmm5
    {$ENDIF}
    {$IFDEF USE_ASM_SIMD_HIGHPRECISION}
      // High Precision
      sqrtps xmm0, xmm0
      divps xmm2, xmm0
    {$ELSE}
      // Low precision
      rsqrtps xmm0, xmm0       //approximate reciprocal
      mulps xmm2, xmm0
    {$ENDIF}
    addps xmm2,xmm3
    // Normalize xmm1 result in xmm4
    movaps xmm3,xmm1
    andps  xmm3, DQWORD PTR [RIP+cSSE_MASK_ONLY_W]
    andps  xmm1, DQWORD PTR [RIP+cSSE_MASK_NO_W]
    movaps xmm4, xmm1
    {$IFDEF USE_ASM_SSE_3}
      mulps  xmm1, xmm1
      //haddps xmm1, xmm1
      //haddps xmm1, xmm1
      movshdup    xmm5, xmm1
      addps       xmm1, xmm5
      movhlps     xmm5, xmm1
      addss       xmm1, xmm5
    {$ELSE}
      mulps xmm1, xmm1
      movaps xmm5, xmm1
      shufps xmm1, xmm5, $4e
      addps xmm1, xmm5
      movaps xmm5, xmm1
      shufps xmm5, xmm5, $11
      addps xmm1, xmm5
    {$ENDIF}
    {$IFDEF USE_ASM_SIMD_HIGHPRECISION}
      // High Precision
      sqrtps xmm1, xmm1
      divps xmm4, xmm1
    {$ELSE}
      // Low precision
      rsqrtps xmm1, xmm1       //approximate reciprocal
      mulps xmm4, xmm1
    {$ENDIF}
    addps xmm4,xmm3
 
    // AngleCosine
    movaps xmm1, xmm4
    movaps xmm0, xmm2 // Copy A
 
   // DotProd  xmm0/xmm1 Result in xmm3
   {$IFDEF USE_ASM_SSE_4}
      dpps xmm0, xmm1, 01110001b //or $F1
      movaps xmm3,xmm0
   {$ELSE}
     {$IFDEF USE_ASM_SSE_3}
       andps xmm0, DQWORD PTR [RIP+cSSE_MASK_NO_W]
       mulps xmm1, xmm0
       //haddps xmm1, xmm1
       //haddps xmm1, xmm1
       movshdup    xmm0, xmm1
       addps       xmm1, xmm0
       movhlps     xmm0, xmm1
       addss       xmm1, xmm0
       movaps xmm3,xmm1
     {$ELSE}
       mulps  xmm1, xmm0
       movhlps xmm0, xmm1
       addps xmm0, xmm1
       shufps xmm1, xmm1, 00000001b
       addps xmm1, xmm0
       movaps xmm3, xmm1
     {$ENDIF}
   {$ENDIF}
    // Length xmm2 result in xmm2
    andps xmm5, DQWORD PTR [RIP+cSSE_MASK_NO_W]
    {$IFDEF USE_ASM_SSE_4}
      dpps xmm2, xmm2, $FF;
      sqrtss xmm2, xmm2
    {$ELSE}
      mulps   xmm2, xmm2
      {$IFDEF USE_ASM_SSE_3}
        //haddps xmm2, xmm2
        //haddps xmm2, xmm2
        movshdup    xmm5, xmm2
        addps       xmm2, xmm5
        movhlps     xmm5, xmm2
        addss       xmm2, xmm5
        sqrtss xmm2, xmm2
      {$ELSE}
        movhlps xmm1, xmm2
        addss xmm1, xmm2
        shufps xmm2, xmm2, $55
        addss xmm1, xmm2
        sqrtss xmm2, xmm1
      {$ENDIF}
    {$ENDIF}
    // Lenght  xmm4 result in xmm4
    andps xmm4, DQWORD PTR [RIP+cSSE_MASK_NO_W]
    {$IFDEF USE_ASM_SSE_4}
      dpps xmm4, xmm4, $FF;
      sqrtss xmm4, xmm4
    {$ELSE}
      mulps   xmm4, xmm4
      {$IFDEF USE_ASM_SSE_3}
        //haddps xmm4, xmm4
        //haddps xmm4, xmm4
        movshdup    xmm5, xmm4
        addps       xmm4, xmm5
        movhlps     xmm5, xmm4
        addss       xmm4, xmm5
        sqrtss xmm4, xmm4
      {$ELSE}
        movhlps xmm1, xmm4
        addss xmm1, xmm4
        shufps xmm4, xmm4, $55
        addss xmm1, xmm4
        sqrtss xmm4, xmm1
      {$ENDIF}
    {$ENDIF}
    mulps xmm2,xmm4
    divps xmm3, xmm2
    movss [Result], xmm3
  end;
 
function TBZVector4f.AngleBetween(Const A, ACenterPoint : TBZVector4f): Single;
Var
  vResult  :  Single;
begin
  vResult := PreComputeAngleBetween(A, ACenterPoint);
  Result := Beanz.Math.ArcCos(vResult);
end;
Sinon me restera la solution de faire une DLL avec Lazarus et de l'importer dans Delphi au pire, mais j'aurais souhaiter éviter.

Avez vous une explication sur ce phénomène ? c'est tout de même très étrange, je trouve.


Note : Je n'ai pas encore fais de test donc ces exemples ne sont par encore viables. Les registres utilisés par Delphi ne sont peut-être (surement) pas tout à fait les mêmes qu'avec Lazarus. Il faut que je trouve un peu de doc sur comment Delphi gère l' ABI.


Merci

Bonne fin de soirée