tvectorcall1.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. { %CPU=x86_64 }
  2. program vectorcall_hva_test1;
  3. {$IFNDEF CPUX86_64}
  4. {$FATAL This test program can only be compiled on Windows or Linux 64-bit with an Intel processor }
  5. {$ENDIF}
  6. {$ASMMODE Intel}
  7. {$PUSH}
  8. {$CODEALIGN RECORDMIN=16}
  9. {$PACKRECORDS C}
  10. type
  11. TM128 = record
  12. case Byte of
  13. 0: (M128_F32: array[0..3] of Single);
  14. 1: (M128_F64: array[0..1] of Double);
  15. end;
  16. {$POP}
  17. { HFA test: field style. }
  18. { NOTE: if the record falls on a 16-byte boundary, the 4-component entries will
  19. turned into vectors rather than HFAs. }
  20. THFA1_SF = packed record
  21. F1: Single;
  22. end;
  23. {$IFDEF WIN64}
  24. THFA2_SF = packed record
  25. F1, F2: Single;
  26. end;
  27. THFA3_SF = packed record
  28. F1, F2, F3: Single;
  29. end;
  30. THFA4_SF = packed record
  31. F1, F2, F3, F4: Single;
  32. end;
  33. {$ENDIF}
  34. THFA1_DF = packed record
  35. F1: Double;
  36. end;
  37. {$IFDEF WIN64}
  38. THFA2_DF = packed record
  39. F1, F2: Double;
  40. end;
  41. THFA3_DF = packed record
  42. F1, F2, F3: Double;
  43. end;
  44. THFA4_DF = packed record
  45. F1, F2, F3, F4: Double;
  46. end;
  47. {$ENDIF}
  48. { HFA test - array style }
  49. { NOTE: if the record falls on a 16-byte boundary, the 4-component entries will
  50. turned into vectors rather than HFAs. }
  51. THFA1_SA = packed record
  52. F: array[0..0] of Single;
  53. end;
  54. {$IFDEF WIN64}
  55. THFA2_SA = packed record
  56. F: array[0..1] of Single;
  57. end;
  58. THFA3_SA = packed record
  59. F: array[0..2] of Single;
  60. end;
  61. THFA4_SA = packed record
  62. F: array[0..3] of Single;
  63. end;
  64. {$ENDIF}
  65. THFA1_DA = packed record
  66. F: array[0..0] of Double;
  67. end;
  68. {$IFDEF WIN64}
  69. THFA2_DA = packed record
  70. F: array[0..1] of Double;
  71. end;
  72. THFA3_DA = packed record
  73. F: array[0..2] of Double;
  74. end;
  75. THFA4_DA = packed record
  76. F: array[0..3] of Double;
  77. end;
  78. {$ENDIF}
  79. { Single-type vector }
  80. function HorizontalAddSingle(V: TM128): Single; vectorcall;
  81. begin
  82. HorizontalAddSingle := V.M128_F32[0] + V.M128_F32[1] + V.M128_F32[2] + V.M128_F32[3];
  83. end;
  84. function HorizontalAddSingle_ASM(V: TM128): Single; vectorcall; assembler; nostackframe;
  85. asm
  86. HADDPS XMM0, XMM0
  87. HADDPS XMM0, XMM0
  88. end;
  89. { Double-type vector }
  90. function HorizontalAddDouble(V: TM128): Double; vectorcall;
  91. begin
  92. HorizontalAddDouble := V.M128_F64[0] + V.M128_F64[1];
  93. end;
  94. function HorizontalAddDouble_ASM(V: TM128): Double; vectorcall; assembler; nostackframe;
  95. asm
  96. HADDPD XMM0, XMM0
  97. end;
  98. { 3-element aggregate }
  99. function AddSingles1F(HFA: THFA1_SF): Single; vectorcall;
  100. begin
  101. AddSingles1F := HFA.F1;
  102. end;
  103. function AddSingles1F_ASM(HFA: THFA1_SF): Single; vectorcall; assembler; nostackframe;
  104. asm
  105. { Do absolutely nothing! }
  106. end;
  107. function AddDoubles1F(HFA: THFA1_DF): Double; vectorcall;
  108. begin
  109. AddDoubles1F := HFA.F1;
  110. end;
  111. function AddDoubles1F_ASM(HFA: THFA1_DF): Double; vectorcall; assembler; nostackframe;
  112. asm
  113. { Do absolutely nothing! }
  114. end;
  115. function AddSingles1A(HFA: THFA1_SA): Single; vectorcall;
  116. begin
  117. AddSingles1A := HFA.F[0];
  118. end;
  119. function AddSingles1A_ASM(HFA: THFA1_SA): Single; vectorcall; assembler; nostackframe;
  120. asm
  121. { Do absolutely nothing! }
  122. end;
  123. function AddDoubles1A(HFA: THFA1_DA): Double; vectorcall;
  124. begin
  125. AddDoubles1A := HFA.F[0];
  126. end;
  127. function AddDoubles1A_ASM(HFA: THFA1_DA): Double; vectorcall; assembler; nostackframe;
  128. asm
  129. { Do absolutely nothing! }
  130. end;
  131. {$IFDEF WIN64}
  132. { 2-element aggregate }
  133. function AddSingles2F(HFA: THFA2_SF): Single; vectorcall;
  134. begin
  135. AddSingles2F := HFA.F1 + HFA.F2;
  136. end;
  137. function AddSingles2F_ASM(HFA: THFA2_SF): Single; vectorcall; assembler; nostackframe;
  138. asm
  139. ADDSS XMM0, XMM1
  140. end;
  141. function AddDoubles2F(HFA: THFA2_DF): Double; vectorcall;
  142. begin
  143. AddDoubles2F := HFA.F1 + HFA.F2;
  144. end;
  145. function AddDoubles2F_ASM(HFA: THFA2_DF): Double; vectorcall; assembler; nostackframe;
  146. asm
  147. ADDSD XMM0, XMM1
  148. end;
  149. function AddSingles2A(HFA: THFA2_SA): Single; vectorcall;
  150. begin
  151. AddSingles2A := HFA.F[0] + HFA.F[1];
  152. end;
  153. function AddSingles2A_ASM(HFA: THFA2_SA): Single; vectorcall; assembler; nostackframe;
  154. asm
  155. ADDSS XMM0, XMM1
  156. end;
  157. function AddDoubles2A(HFA: THFA2_DA): Double; vectorcall;
  158. begin
  159. AddDoubles2A := HFA.F[0] + HFA.F[1];
  160. end;
  161. function AddDoubles2A_ASM(HFA: THFA2_DA): Double; vectorcall; assembler; nostackframe;
  162. asm
  163. ADDSD XMM0, XMM1
  164. end;
  165. { 3-element aggregate }
  166. function AddSingles3F(HFA: THFA3_SF): Single; vectorcall;
  167. begin
  168. AddSingles3F := HFA.F1 + HFA.F2 + HFA.F3;
  169. end;
  170. function AddSingles3F_ASM(HFA: THFA3_SF): Single; vectorcall; assembler; nostackframe;
  171. asm
  172. ADDSS XMM0, XMM1
  173. ADDSS XMM0, XMM2
  174. end;
  175. function AddDoubles3F(HFA: THFA3_DF): Double; vectorcall;
  176. begin
  177. AddDoubles3F := HFA.F1 + HFA.F2 + HFA.F3;
  178. end;
  179. function AddDoubles3F_ASM(HFA: THFA3_DF): Double; vectorcall; assembler; nostackframe;
  180. asm
  181. ADDSD XMM0, XMM1
  182. ADDSD XMM0, XMM2
  183. end;
  184. function AddSingles3A(HFA: THFA3_SA): Single; vectorcall;
  185. begin
  186. AddSingles3A := HFA.F[0] + HFA.F[1] + HFA.F[2];
  187. end;
  188. function AddSingles3A_ASM(HFA: THFA3_SA): Single; vectorcall; assembler; nostackframe;
  189. asm
  190. ADDSS XMM0, XMM1
  191. ADDSS XMM0, XMM2
  192. end;
  193. function AddDoubles3A(HFA: THFA3_DA): Double; vectorcall;
  194. begin
  195. AddDoubles3A := HFA.F[0] + HFA.F[1] + HFA.F[2];
  196. end;
  197. function AddDoubles3A_ASM(HFA: THFA3_DA): Double; vectorcall; assembler; nostackframe;
  198. asm
  199. ADDSD XMM0, XMM1
  200. ADDSD XMM0, XMM2
  201. end;
  202. { 4-element aggregate }
  203. function AddSingles4F(HFA: THFA4_SF): Single; vectorcall;
  204. begin
  205. AddSingles4F := HFA.F1 + HFA.F2 + HFA.F3 + HFA.F4;
  206. end;
  207. function AddSingles4F_ASM(HFA: THFA4_SF): Single; vectorcall; assembler; nostackframe;
  208. asm
  209. ADDSS XMM0, XMM1
  210. ADDSS XMM0, XMM2
  211. ADDSS XMM0, XMM3
  212. end;
  213. function AddDoubles4F(HFA: THFA4_DF): Double; vectorcall;
  214. begin
  215. AddDoubles4F := HFA.F1 + HFA.F2 + HFA.F3 + HFA.F4;
  216. end;
  217. function AddDoubles4F_ASM(HFA: THFA4_DF): Double; vectorcall; assembler; nostackframe;
  218. asm
  219. ADDSD XMM0, XMM1
  220. ADDSD XMM0, XMM2
  221. ADDSD XMM0, XMM3
  222. end;
  223. function AddSingles4A(HFA: THFA4_SA): Single; vectorcall;
  224. begin
  225. AddSingles4A := HFA.F[0] + HFA.F[1] + HFA.F[2] + HFA.F[3];
  226. end;
  227. function AddSingles4A_ASM(HFA: THFA4_SA): Single; vectorcall; assembler; nostackframe;
  228. asm
  229. ADDSS XMM0, XMM1
  230. ADDSS XMM0, XMM2
  231. ADDSS XMM0, XMM3
  232. end;
  233. function AddDoubles4A(HFA: THFA4_DA): Double; vectorcall;
  234. begin
  235. AddDoubles4A := HFA.F[0] + HFA.F[1] + HFA.F[2] + HFA.F[3];
  236. end;
  237. function AddDoubles4A_ASM(HFA: THFA4_DA): Double; vectorcall; assembler; nostackframe;
  238. asm
  239. ADDSD XMM0, XMM1
  240. ADDSD XMM0, XMM2
  241. ADDSD XMM0, XMM3
  242. end;
  243. {$ENDIF}
  244. var
  245. HVA: TM128;
  246. HFA1_SF: THFA1_SF;
  247. HFA1_DF: THFA1_DF;
  248. HFA1_SA: THFA1_SA;
  249. HFA1_DA: THFA1_DA;
  250. {$IFDEF WIN64}
  251. HFA2_SF: THFA2_SF;
  252. HFA2_DF: THFA2_DF;
  253. HFA2_SA: THFA2_SA;
  254. HFA2_DA: THFA2_DA;
  255. HFA3_SF: THFA3_SF;
  256. HFA3_DF: THFA3_DF;
  257. HFA3_SA: THFA3_SA;
  258. HFA3_DA: THFA3_DA;
  259. HFA4_SF: THFA4_SF;
  260. HFA4_DF: THFA4_DF;
  261. HFA4_SA: THFA4_SA;
  262. HFA4_DA: THFA4_DA;
  263. {$ENDIF}
  264. TestPointer: PtrUInt;
  265. I, J: Integer;
  266. ResS, ResSA: Single;
  267. ResD, ResDA: Double;
  268. Addresses: array[0..3] of Pointer;
  269. FieldAddresses: array[0..3, 0..3] of Pointer;
  270. const
  271. AddressNames1: array[0..3] of ShortString = ('HFA1_SF', 'HFA1_DF', 'HFA1_SA', 'HFA1_DA');
  272. {$IFDEF WIN64}
  273. AddressNames2: array[0..3] of ShortString = ('HFA2_SF', 'HFA2_DF', 'HFA2_SA', 'HFA2_DA');
  274. AddressNames3: array[0..3] of ShortString = ('HFA3_SF', 'HFA3_DF', 'HFA3_SA', 'HFA3_DA');
  275. AddressNames4: array[0..3] of ShortString = ('HFA4_SF', 'HFA4_DF', 'HFA4_SA', 'HFA4_DA');
  276. {$ENDIF}
  277. FieldAddressNames: array[0..3] of ShortString = ('F1', 'F2', 'F3', 'F4');
  278. ExpS1: Single = 5.0;
  279. {$IFDEF WIN64}
  280. ExpS2: Single = -5.0;
  281. ExpS3: Single = 10.0;
  282. {$ENDIF}
  283. ExpS4: Single = -10.0;
  284. ExpD1: Double = 5.0;
  285. ExpD2: Double = -5.0;
  286. {$IFDEF WIN64}
  287. ExpD3: Double = 10.0;
  288. ExpD4: Double = -10.0;
  289. {$ENDIF}
  290. begin
  291. if (PtrUInt(@HVA) and $F) <> 0 then
  292. begin
  293. WriteLn('FAIL: HVA is not correctly aligned.');
  294. Halt(1);
  295. end;
  296. { array of singles }
  297. WriteLn('- horizontal add (4 singles)');
  298. HVA.M128_F32[0] := 5.0;
  299. HVA.M128_F32[1] := -10.0;
  300. HVA.M128_F32[2] := 15.0;
  301. HVA.M128_F32[3] := -20.0;
  302. ResS := HorizontalAddSingle(HVA);
  303. ResSA := HorizontalAddSingle_ASM(HVA);
  304. if (ResS <> ResSA) then
  305. begin
  306. WriteLn('FAIL: HorizontalAddSingle(HVA) has the vector in the wrong register.');
  307. Halt(1);
  308. end else
  309. begin
  310. if ResS <> ExpS4 then
  311. begin
  312. WriteLn('FAIL: HorizontalAddSingle(HVA) returned ', ResS, ' instead of ', ExpS4);
  313. Halt(1);
  314. end;
  315. end;
  316. { array of doubles }
  317. WriteLn('- horizontal add (2 doubles)');
  318. HVA.M128_F64[0] := 5.0;
  319. HVA.M128_F64[1] := -10.0;
  320. ResD := HorizontalAddDouble(HVA);
  321. ResDA := HorizontalAddDouble_ASM(HVA);
  322. if (ResD <> ResDA) then
  323. begin
  324. WriteLn('FAIL: HorizontalAddDouble(HVA) has the vector in the wrong register.');
  325. Halt(1);
  326. end else
  327. begin
  328. if ResD <> ExpD2 then
  329. begin
  330. WriteLn('FAIL: HorizontalAddDouble(HVA) returned ', ResD, ' instead of ', ExpD2);
  331. Halt(1);
  332. end;
  333. end;
  334. { 1-field aggregates }
  335. WriteLn('- 1-field aggregates');
  336. Addresses[0] := @HFA1_SF;
  337. Addresses[1] := @HFA1_SA;
  338. Addresses[2] := @HFA1_DF;
  339. Addresses[3] := @HFA1_DA;
  340. FieldAddresses[0][0] := @(HFA1_SF.F1);
  341. FieldAddresses[1][0] := @(HFA1_SA.F[0]);
  342. FieldAddresses[2][0] := @(HFA1_DF.F1);
  343. FieldAddresses[3][0] := @(HFA1_DA.F[0]);
  344. { Check alignment }
  345. for I := 0 to 1 do
  346. begin
  347. TestPointer := PtrUInt(Addresses[I]);
  348. if Pointer(TestPointer) <> FieldAddresses[I][0] then
  349. begin
  350. WriteLn('FAIL: ', AddressNames1[I], ' is not correctly packed; field F1 is not in the expected place.');
  351. Halt(1);
  352. end;
  353. end;
  354. HFA1_SF.F1 := 5.0;
  355. ResS := AddSingles1F(HFA1_SF);
  356. ResSA := AddSingles1F_ASM(HFA1_SF);
  357. if (ResS <> ResSA) then
  358. begin
  359. WriteLn('FAIL: AddSingles1F(', AddressNames1[I], ') is not passing the aggregate correctly.');
  360. Halt(1);
  361. end else
  362. begin
  363. if ResS <> ExpS1 then
  364. begin
  365. WriteLn('FAIL: AddSingles1F(', AddressNames1[I], ') returned ', ResS, ' instead of ', ExpS1);
  366. Halt(1);
  367. end;
  368. end;
  369. HFA1_DF.F1 := 5.0;
  370. ResD := AddDoubles1F(HFA1_DF);
  371. ResDA := AddDoubles1F_ASM(HFA1_DF);
  372. if (ResD <> ResDA) then
  373. begin
  374. WriteLn('FAIL: AddDoubles1F(', AddressNames1[I], ') is not passing the aggregate correctly.');
  375. Halt(1);
  376. end else
  377. begin
  378. if ResD <> ExpD1 then
  379. begin
  380. WriteLn('FAIL: AddDoubles1F(', AddressNames1[I], ') returned ', ResD, ' instead of ', ExpD1);
  381. Halt(1);
  382. end;
  383. end;
  384. HFA1_SA.F[0] := 5.0;
  385. ResS := AddSingles1A(HFA1_SA);
  386. ResSA := AddSingles1A_ASM(HFA1_SA);
  387. if (ResS <> ResSA) then
  388. begin
  389. WriteLn('FAIL: AddSingles1A(', AddressNames1[I], ') is not passing the aggregate correctly.');
  390. Halt(1);
  391. end else
  392. begin
  393. if ResS <> ExpS1 then
  394. begin
  395. WriteLn('FAIL: AddSingles1A(', AddressNames1[I], ') returned ', ResS, ' instead of ', ExpS1);
  396. Halt(1);
  397. end;
  398. end;
  399. HFA1_DA.F[0] := 5.0;
  400. ResD := AddDoubles1A(HFA1_DA);
  401. ResDA := AddDoubles1A_ASM(HFA1_DA);
  402. if (ResD <> ResDA) then
  403. begin
  404. WriteLn('FAIL: AddDoubles1A(', AddressNames1[I], ') is not passing the aggregate correctly.');
  405. Halt(1);
  406. end else
  407. begin
  408. if ResD <> ExpD1 then
  409. begin
  410. WriteLn('FAIL: AddDoubles1A(', AddressNames1[I], ') returned ', ResD, ' instead of ', ExpD1);
  411. Halt(1);
  412. end;
  413. end;
  414. {$IFDEF WIN64}
  415. { 2-field aggregates }
  416. WriteLn('- 2-field aggregates');
  417. Addresses[0] := @HFA2_SF;
  418. Addresses[1] := @HFA2_SA;
  419. FieldAddresses[0][0] := @(HFA2_SF.F1);
  420. FieldAddresses[0][1] := @(HFA2_SF.F2);
  421. FieldAddresses[1][0] := @(HFA2_SA.F[0]);
  422. FieldAddresses[1][1] := @(HFA2_SA.F[1]);
  423. { Check alignment of Singles }
  424. for I := 0 to 1 do
  425. begin
  426. TestPointer := PtrUInt(Addresses[I]);
  427. for J := 0 to 1 do
  428. begin
  429. if Pointer(TestPointer) <> FieldAddresses[I][J] then
  430. begin
  431. WriteLn('FAIL: ', AddressNames2[I], ' is not correctly packed; field ', FieldAddressNames[J], ' is not in the expected place.');
  432. Halt(1);
  433. end;
  434. Inc(TestPointer, $4);
  435. end;
  436. end;
  437. Addresses[2] := @HFA2_DF;
  438. Addresses[3] := @HFA2_DA;
  439. FieldAddresses[2][0] := @(HFA2_DF.F1);
  440. FieldAddresses[2][1] := @(HFA2_DF.F2);
  441. FieldAddresses[3][0] := @(HFA2_DA.F[0]);
  442. FieldAddresses[3][1] := @(HFA2_DA.F[1]);
  443. { Check alignment of Doubles }
  444. for I := 2 to 3 do
  445. begin
  446. TestPointer := PtrUInt(Addresses[I]);
  447. for J := 0 to 1 do
  448. begin
  449. if Pointer(TestPointer) <> FieldAddresses[I][J] then
  450. begin
  451. WriteLn('FAIL: ', AddressNames2[I], ' is not correctly packed; field ', FieldAddressNames[J], ' is not in the expected place.');
  452. Halt(1);
  453. end;
  454. Inc(TestPointer, $8);
  455. end;
  456. end;
  457. HFA2_SF.F1 := 5.0;
  458. HFA2_SF.F2 := -10.0;
  459. ResS := AddSingles2F(HFA2_SF);
  460. ResSA := AddSingles2F_ASM(HFA2_SF);
  461. if (ResS <> ResSA) then
  462. begin
  463. WriteLn('FAIL: AddSingles2F(HFA2_SF) is not passing the aggregate correctly.');
  464. Halt(1);
  465. end else
  466. begin
  467. if ResS <> ExpS2 then
  468. begin
  469. WriteLn('FAIL: AddSingles2F(HFA2_SF) returned ', ResS, ' instead of ', ExpS2);
  470. Halt(1);
  471. end;
  472. end;
  473. HFA2_DF.F1 := 5.0;
  474. HFA2_DF.F2 := -10.0;
  475. ResD := AddDoubles2F(HFA2_DF);
  476. ResDA := AddDoubles2F_ASM(HFA2_DF);
  477. if (ResD <> ResDA) then
  478. begin
  479. WriteLn('FAIL: AddDoubles2F(HFA2_DF) is not passing the aggregate correctly.');
  480. Halt(1);
  481. end else
  482. begin
  483. if ResD <> ExpD2 then
  484. begin
  485. WriteLn('FAIL: AddDoubles2F(HFA2_DF) returned ', ResD, ' instead of ', ExpD2);
  486. Halt(1);
  487. end;
  488. end;
  489. HFA2_SA.F[0] := 5.0;
  490. HFA2_SA.F[1] := -10.0;
  491. ResS := AddSingles2A(HFA2_SA);
  492. ResSA := AddSingles2A_ASM(HFA2_SA);
  493. if (ResS <> ResSA) then
  494. begin
  495. WriteLn('FAIL: AddSingles2A(HFA2_SA) is not passing the aggregate correctly.');
  496. Halt(1);
  497. end else
  498. begin
  499. if ResS <> ExpS2 then
  500. begin
  501. WriteLn('FAIL: AddSingles2A(HFA2_SA) returned ', ResS, ' instead of ', ExpS2);
  502. Halt(1);
  503. end;
  504. end;
  505. HFA2_DA.F[0] := 5.0;
  506. HFA2_DA.F[1] := -10.0;
  507. ResD := AddDoubles2A(HFA2_DA);
  508. ResDA := AddDoubles2A_ASM(HFA2_DA);
  509. if (ResD <> ResDA) then
  510. begin
  511. WriteLn('FAIL: AddDoubles2A(HFA2_DA) is not passing the aggregate correctly.');
  512. Halt(1);
  513. end else
  514. begin
  515. if ResD <> ExpD2 then
  516. begin
  517. WriteLn('FAIL: AddDoubles2A(HFA2_DA) returned ', ResD, ' instead of ', ExpD2);
  518. Halt(1);
  519. end;
  520. end;
  521. { 3-field aggregates }
  522. WriteLn('- 3-field aggregates');
  523. Addresses[0] := @HFA3_SF;
  524. Addresses[1] := @HFA3_SA;
  525. FieldAddresses[0][0] := @(HFA3_SF.F1);
  526. FieldAddresses[0][1] := @(HFA3_SF.F2);
  527. FieldAddresses[0][2] := @(HFA3_SF.F3);
  528. FieldAddresses[1][0] := @(HFA3_SA.F[0]);
  529. FieldAddresses[1][1] := @(HFA3_SA.F[1]);
  530. FieldAddresses[1][2] := @(HFA3_SA.F[2]);
  531. { Check alignment of Singles }
  532. for I := 0 to 1 do
  533. begin
  534. TestPointer := PtrUInt(Addresses[I]);
  535. for J := 0 to 2 do
  536. begin
  537. if Pointer(TestPointer) <> FieldAddresses[I][J] then
  538. begin
  539. WriteLn('FAIL: ', AddressNames3[I], ' is not correctly packed; field ', FieldAddressNames[J], ' is not in the expected place.');
  540. Halt(1);
  541. end;
  542. Inc(TestPointer, $4);
  543. end;
  544. end;
  545. Addresses[2] := @HFA3_DF;
  546. Addresses[3] := @HFA3_DA;
  547. FieldAddresses[2][0] := @(HFA3_DF.F1);
  548. FieldAddresses[2][1] := @(HFA3_DF.F2);
  549. FieldAddresses[2][2] := @(HFA3_DF.F3);
  550. FieldAddresses[3][0] := @(HFA3_DA.F[0]);
  551. FieldAddresses[3][1] := @(HFA3_DA.F[1]);
  552. FieldAddresses[3][2] := @(HFA3_DA.F[2]);
  553. { Check alignment of Doubles }
  554. for I := 2 to 3 do
  555. begin
  556. TestPointer := PtrUInt(Addresses[I]);
  557. for J := 0 to 2 do
  558. begin
  559. if Pointer(TestPointer) <> FieldAddresses[I][J] then
  560. begin
  561. WriteLn('FAIL: ', AddressNames3[I], ' is not correctly packed; field ', FieldAddressNames[J], ' is not in the expected place.');
  562. Halt(1);
  563. end;
  564. Inc(TestPointer, $8);
  565. end;
  566. end;
  567. HFA3_SF.F1 := 5.0;
  568. HFA3_SF.F2 := -10.0;
  569. HFA3_SF.F3 := 15.0;
  570. ResS := AddSingles3F(HFA3_SF);
  571. ResSA := AddSingles3F_ASM(HFA3_SF);
  572. if (ResS <> ResSA) then
  573. begin
  574. WriteLn('FAIL: AddSingles3F(HFA3_SF) is not passing the aggregate correctly.');
  575. Halt(1);
  576. end else
  577. begin
  578. if ResS <> ExpS3 then
  579. begin
  580. WriteLn('FAIL: AddSingles3F(HFA3_SF) returned ', ResS, ' instead of ', ExpS3);
  581. Halt(1);
  582. end;
  583. end;
  584. HFA3_DF.F1 := 5.0;
  585. HFA3_DF.F2 := -10.0;
  586. HFA3_DF.F3 := 15.0;
  587. ResD := AddDoubles3F(HFA3_DF);
  588. ResDA := AddDoubles3F_ASM(HFA3_DF);
  589. if (ResD <> ResDA) then
  590. begin
  591. WriteLn('FAIL: AddDoubles3F(HFA3_DF) is not passing the aggregate correctly.');
  592. Halt(1);
  593. end else
  594. begin
  595. if ResD <> ExpD3 then
  596. begin
  597. WriteLn('FAIL: AddDoubles3F(HFA3_DF) returned ', ResD, ' instead of ', ExpD3);
  598. Halt(1);
  599. end;
  600. end;
  601. HFA3_SA.F[0] := 5.0;
  602. HFA3_SA.F[1] := -10.0;
  603. HFA3_SA.F[2] := 15.0;
  604. ResS := AddSingles3A(HFA3_SA);
  605. ResSA := AddSingles3A_ASM(HFA3_SA);
  606. if (ResS <> ResSA) then
  607. begin
  608. WriteLn('FAIL: AddSingles3A(HFA3_SA) is not passing the aggregate correctly.');
  609. Halt(1);
  610. end else
  611. begin
  612. if ResS <> ExpS3 then
  613. begin
  614. WriteLn('FAIL: AddSingles3A(HFA3_SA) returned ', ResS, ' instead of ', ExpS3);
  615. Halt(1);
  616. end;
  617. end;
  618. HFA3_DA.F[0] := 5.0;
  619. HFA3_DA.F[1] := -10.0;
  620. HFA3_DA.F[2] := 15.0;
  621. ResD := AddDoubles3A(HFA3_DA);
  622. ResDA := AddDoubles3A_ASM(HFA3_DA);
  623. if (ResD <> ResDA) then
  624. begin
  625. WriteLn('FAIL: AddDoubles3A(HFA3_DA) is not passing the aggregate correctly.');
  626. Halt(1);
  627. end else
  628. begin
  629. if ResD <> ExpD3 then
  630. begin
  631. WriteLn('FAIL: AddDoubles3A(HFA3_DA) returned ', ResD, ' instead of ', ExpD3);
  632. Halt(1);
  633. end;
  634. end;
  635. { 4-field aggregates }
  636. WriteLn('- 4-field aggregates');
  637. Addresses[0] := @HFA4_SF;
  638. Addresses[1] := @HFA4_SA;
  639. FieldAddresses[0][0] := @(HFA4_SF.F1);
  640. FieldAddresses[0][1] := @(HFA4_SF.F2);
  641. FieldAddresses[0][2] := @(HFA4_SF.F3);
  642. FieldAddresses[0][3] := @(HFA4_SF.F4);
  643. FieldAddresses[1][0] := @(HFA4_SA.F[0]);
  644. FieldAddresses[1][1] := @(HFA4_SA.F[1]);
  645. FieldAddresses[1][2] := @(HFA4_SA.F[2]);
  646. FieldAddresses[1][3] := @(HFA4_SA.F[3]);
  647. { Check alignment of Singles }
  648. for I := 0 to 1 do
  649. begin
  650. TestPointer := PtrUInt(Addresses[I]);
  651. for J := 0 to 3 do
  652. begin
  653. if Pointer(TestPointer) <> FieldAddresses[I][J] then
  654. begin
  655. WriteLn('FAIL: ', AddressNames4[I], ' is not correctly packed; field ', FieldAddressNames[J], ' is not in the expected place.');
  656. Halt(1);
  657. end;
  658. Inc(TestPointer, $4);
  659. end;
  660. end;
  661. Addresses[2] := @HFA4_DF;
  662. Addresses[3] := @HFA4_DA;
  663. FieldAddresses[2][0] := @(HFA4_DF.F1);
  664. FieldAddresses[2][1] := @(HFA4_DF.F2);
  665. FieldAddresses[2][2] := @(HFA4_DF.F3);
  666. FieldAddresses[2][3] := @(HFA4_DF.F4);
  667. FieldAddresses[3][0] := @(HFA4_DA.F[0]);
  668. FieldAddresses[3][1] := @(HFA4_DA.F[1]);
  669. FieldAddresses[3][2] := @(HFA4_DA.F[2]);
  670. FieldAddresses[3][3] := @(HFA4_DA.F[3]);
  671. { Check alignment of Doubles }
  672. for I := 2 to 3 do
  673. begin
  674. TestPointer := PtrUInt(Addresses[I]);
  675. for J := 0 to 3 do
  676. begin
  677. if Pointer(TestPointer) <> FieldAddresses[I][J] then
  678. begin
  679. WriteLn('FAIL: ', AddressNames4[I], ' is not correctly packed; field ', FieldAddressNames[J], ' is not in the expected place.');
  680. Halt(1);
  681. end;
  682. Inc(TestPointer, $8);
  683. end;
  684. end;
  685. HFA4_SF.F1 := 5.0;
  686. HFA4_SF.F2 := -10.0;
  687. HFA4_SF.F3 := 15.0;
  688. HFA4_SF.F4 := -20.0;
  689. ResS := AddSingles4F(HFA4_SF);
  690. ResSA := AddSingles4F_ASM(HFA4_SF);
  691. if (ResS <> ResSA) then
  692. begin
  693. WriteLn('FAIL: AddSingles4F(HFA4_SF) is not passing the aggregate correctly.');
  694. Halt(1);
  695. end else
  696. begin
  697. if ResS <> ExpS4 then
  698. begin
  699. WriteLn('FAIL: AddSingles4F(HFA4_SF) returned ', ResS, ' instead of ', ExpS4);
  700. Halt(1);
  701. end;
  702. end;
  703. HFA4_DF.F1 := 5.0;
  704. HFA4_DF.F2 := -10.0;
  705. HFA4_DF.F3 := 15.0;
  706. HFA4_DF.F4 := -20.0;
  707. ResD := AddDoubles4F(HFA4_DF);
  708. ResDA := AddDoubles4F_ASM(HFA4_DF);
  709. if (ResD <> ResDA) then
  710. begin
  711. WriteLn('FAIL: AddDoubles4F(HFA4_DF) is not passing the aggregate correctly.');
  712. Halt(1);
  713. end else
  714. begin
  715. if ResD <> ExpD4 then
  716. begin
  717. WriteLn('FAIL: AddDoubles4F(HFA4_DF) returned ', ResD, ' instead of ', ExpD4);
  718. Halt(1);
  719. end;
  720. end;
  721. HFA4_SA.F[0] := 5.0;
  722. HFA4_SA.F[1] := -10.0;
  723. HFA4_SA.F[2] := 15.0;
  724. HFA4_SA.F[3] := -20.0;
  725. ResS := AddSingles4A(HFA4_SA);
  726. ResSA := AddSingles4A_ASM(HFA4_SA);
  727. if (ResS <> ResSA) then
  728. begin
  729. WriteLn('FAIL: AddSingles4A(HFA4_SA) is not passing the aggregate correctly.');
  730. Halt(1);
  731. end else
  732. begin
  733. if ResS <> ExpS4 then
  734. begin
  735. WriteLn('FAIL: AddSingles4A(HFA4_SA) returned ', ResS, ' instead of ', ExpS4);
  736. Halt(1);
  737. end;
  738. end;
  739. HFA4_DA.F[0] := 5.0;
  740. HFA4_DA.F[1] := -10.0;
  741. HFA4_DA.F[2] := 15.0;
  742. HFA4_DA.F[3] := -20.0;
  743. ResD := AddDoubles4A(HFA4_DA);
  744. ResDA := AddDoubles4A_ASM(HFA4_DA);
  745. if (ResD <> ResDA) then
  746. begin
  747. WriteLn('FAIL: AddDoubles4A(HFA4_DF) is not passing the aggregate correctly.');
  748. Halt(1);
  749. end else
  750. begin
  751. if ResD <> ExpD4 then
  752. begin
  753. WriteLn('FAIL: AddDoubles4A(HFA4_DF) returned ', ResD, ' instead of ', ExpD4);
  754. Halt(1);
  755. end;
  756. end;
  757. {$ENDIF}
  758. WriteLn('ok');
  759. end.