i386.inc 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team.
  4. Processor dependent implementation for the system unit for
  5. intel i386+
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {****************************************************************************
  13. Primitives
  14. ****************************************************************************}
  15. var
  16. os_supports_sse : boolean;
  17. { this variable is set to true, if currently an sse check is executed and no sig ill should be generated }
  18. sse_check : boolean;
  19. {$asmmode ATT}
  20. function cpuid_support : boolean;assembler;nostackframe;
  21. {
  22. Check if the ID-flag can be changed, if changed then CpuID is supported.
  23. Tested under go32v1 and Linux on c6x86 with CpuID enabled and disabled (PFV)
  24. }
  25. asm
  26. pushfl
  27. movl (%esp),%eax
  28. xorl $0x200000,%eax
  29. pushl %eax
  30. popfl
  31. pushfl
  32. popl %eax
  33. xorl (%esp),%eax
  34. popfl
  35. testl $0x200000,%eax
  36. setnz %al
  37. end;
  38. {$ifndef FPC_PIC}
  39. {$ifndef FPC_SYSTEM_HAS_MOVE}
  40. {$ifndef OLD_ASSEMBLER}
  41. {$define USE_FASTMOVE}
  42. {$i fastmove.inc}
  43. {$endif not OLD_ASSEMBLER}
  44. {$endif FPC_SYSTEM_HAS_MOVE}
  45. {$endif FPC_PIC}
  46. procedure fpc_cpuinit;
  47. begin
  48. { because of the brain dead sse detection on x86, this test is post poned to fpc_cpucodeinit which
  49. must be implemented OS dependend (FK)
  50. has_sse_support:=sse_support;
  51. has_mmx_support:=mmx_support;
  52. setup_fastmove;
  53. }
  54. end;
  55. {$ifndef darwin}
  56. function fpc_geteipasebx : pointer; [public, alias: 'fpc_geteipasebx'];assembler; nostackframe;
  57. asm
  58. movl (%esp),%ebx
  59. end;
  60. function fpc_geteipasecx : pointer; [public, alias: 'fpc_geteipasecx'];assembler; nostackframe;
  61. asm
  62. movl (%esp),%ecx
  63. end;
  64. {$endif}
  65. {$ifndef FPC_SYSTEM_HAS_MOVE}
  66. {$define FPC_SYSTEM_HAS_MOVE}
  67. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE'];assembler;
  68. var
  69. saveesi,saveedi : longint;
  70. asm
  71. movl %edi,saveedi
  72. movl %esi,saveesi
  73. movl %eax,%esi
  74. movl %edx,%edi
  75. movl %ecx,%edx
  76. movl %edi,%eax
  77. { check for zero or negative count }
  78. cmpl $0,%edx
  79. jle .LMoveEnd
  80. { Check for back or forward }
  81. sub %esi,%eax
  82. jz .LMoveEnd { Do nothing when source=dest }
  83. jc .LFMove { Do forward, dest<source }
  84. cmp %edx,%eax
  85. jb .LBMove { Dest is in range of move, do backward }
  86. { Forward Copy }
  87. .LFMove:
  88. {$ifdef FPC_ENABLED_CLD}
  89. cld
  90. {$endif FPC_ENABLED_CLD}
  91. cmpl $15,%edx
  92. jl .LFMove1
  93. movl %edi,%ecx { Align on 32bits }
  94. negl %ecx
  95. andl $3,%ecx
  96. subl %ecx,%edx
  97. rep
  98. movsb
  99. movl %edx,%ecx
  100. andl $3,%edx
  101. shrl $2,%ecx
  102. rep
  103. movsl
  104. .LFMove1:
  105. movl %edx,%ecx
  106. rep
  107. movsb
  108. jmp .LMoveEnd
  109. { Backward Copy }
  110. .LBMove:
  111. std
  112. addl %edx,%esi
  113. addl %edx,%edi
  114. movl %edi,%ecx
  115. decl %esi
  116. decl %edi
  117. cmpl $15,%edx
  118. jl .LBMove1
  119. negl %ecx { Align on 32bits }
  120. andl $3,%ecx
  121. subl %ecx,%edx
  122. rep
  123. movsb
  124. movl %edx,%ecx
  125. andl $3,%edx
  126. shrl $2,%ecx
  127. subl $3,%esi
  128. subl $3,%edi
  129. rep
  130. movsl
  131. addl $3,%esi
  132. addl $3,%edi
  133. .LBMove1:
  134. movl %edx,%ecx
  135. rep
  136. movsb
  137. cld
  138. .LMoveEnd:
  139. movl saveedi,%edi
  140. movl saveesi,%esi
  141. end;
  142. {$endif FPC_SYSTEM_HAS_MOVE}
  143. {$ifndef FPC_SYSTEM_HAS_FILLCHAR}
  144. {$define FPC_SYSTEM_HAS_FILLCHAR}
  145. Procedure FillChar(var x;count:SizeInt;value:byte);assembler; nostackframe;
  146. asm
  147. cmpl $22,%edx { empirically determined value on a Core 2 Duo Conroe }
  148. jg .LFillFull
  149. orl %edx,%edx
  150. jle .LFillZero
  151. .LFillLoop:
  152. movb %cl,(%eax)
  153. incl %eax
  154. decl %edx
  155. jne .LFillLoop
  156. .LFillZero:
  157. ret
  158. .LFillFull:
  159. {$ifdef FPC_ENABLED_CLD}
  160. cld
  161. {$endif FPC_ENABLED_CLD}
  162. push %edi
  163. movl %eax,%edi
  164. movzbl %cl,%eax
  165. movl %edx,%ecx
  166. imul $0x01010101,%eax { Expand al into a 4 subbytes of eax}
  167. shrl $2,%ecx
  168. andl $3,%edx
  169. rep
  170. stosl
  171. movl %edx,%ecx
  172. .LFill1:
  173. rep
  174. stosb
  175. .LFillEnd:
  176. pop %edi
  177. end;
  178. {$endif FPC_SYSTEM_HAS_FILLCHAR}
  179. {$ifndef FPC_SYSTEM_HAS_FILLWORD}
  180. {$define FPC_SYSTEM_HAS_FILLWORD}
  181. procedure fillword(var x;count : SizeInt;value : word);assembler;
  182. var
  183. saveedi : longint;
  184. asm
  185. movl %edi,saveedi
  186. movl %eax,%edi
  187. movzwl %cx,%eax
  188. movl %edx,%ecx
  189. { check for zero or negative count }
  190. cmpl $0,%ecx
  191. jle .LFillWordEnd
  192. movl %eax,%edx
  193. shll $16,%eax
  194. orl %edx,%eax
  195. movl %ecx,%edx
  196. shrl $1,%ecx
  197. {$ifdef FPC_ENABLED_CLD}
  198. cld
  199. {$endif FPC_ENABLED_CLD}
  200. rep
  201. stosl
  202. movl %edx,%ecx
  203. andl $1,%ecx
  204. rep
  205. stosw
  206. .LFillWordEnd:
  207. movl saveedi,%edi
  208. end;
  209. {$endif FPC_SYSTEM_HAS_FILLWORD}
  210. {$ifndef FPC_SYSTEM_HAS_FILLDWORD}
  211. {$define FPC_SYSTEM_HAS_FILLDWORD}
  212. procedure filldword(var x;count : SizeInt;value : dword);assembler;
  213. var
  214. saveedi : longint;
  215. asm
  216. movl %edi,saveedi
  217. movl %eax,%edi
  218. movl %ecx,%eax
  219. movl %edx,%ecx
  220. { check for zero or negative count }
  221. cmpl $0,%ecx
  222. jle .LFillDWordEnd
  223. {$ifdef FPC_ENABLED_CLD}
  224. cld
  225. {$endif FPC_ENABLED_CLD}
  226. rep
  227. stosl
  228. .LFillDWordEnd:
  229. movl saveedi,%edi
  230. end;
  231. {$endif FPC_SYSTEM_HAS_FILLDWORD}
  232. {$ifndef FPC_SYSTEM_HAS_INDEXBYTE}
  233. {$define FPC_SYSTEM_HAS_INDEXBYTE}
  234. function IndexByte(Const buf;len:SizeInt;b:byte):SizeInt; assembler; nostackframe;
  235. asm
  236. push %esi
  237. push %edi
  238. push %eax { save initial value of 'buf' }
  239. cmp $4,%edx { less than 4 bytes, just test byte by byte. }
  240. jb .Ltail
  241. mov %cl,%ch { prepare pattern }
  242. movzwl %cx,%esi
  243. shl $16,%ecx
  244. or %esi,%ecx
  245. .Lalignloop:
  246. test $3,%al { align to 4 bytes if necessary }
  247. je .Laligned
  248. cmp %cl,(%eax)
  249. je .Lexit
  250. inc %eax
  251. dec %edx
  252. jmp .Lalignloop
  253. .balign 16 { Main loop, unrolled 4 times for speed }
  254. .Lloop:
  255. mov (%eax),%esi { load dword }
  256. xor %ecx,%esi { XOR with pattern, bytes equal to target are now 0 }
  257. lea -0x01010101(%esi),%edi
  258. xor %esi,%edi { (x-0x01010101) xor x }
  259. not %esi
  260. and $0x80808080,%esi
  261. and %edi,%esi { ((x-0x01010101) xor x) and (not x) and 0x80808080 }
  262. jnz .Lfound { one of the bytes matches }
  263. mov 4(%eax),%esi
  264. xor %ecx,%esi
  265. lea -0x01010101(%esi),%edi
  266. xor %esi,%edi
  267. not %esi
  268. and $0x80808080,%esi
  269. and %edi,%esi
  270. jnz .Lfound4
  271. mov 8(%eax),%esi
  272. xor %ecx,%esi
  273. lea -0x01010101(%esi),%edi
  274. xor %esi,%edi
  275. not %esi
  276. and $0x80808080,%esi
  277. and %edi,%esi
  278. jnz .Lfound8
  279. mov 12(%eax),%esi
  280. xor %ecx,%esi
  281. lea -0x01010101(%esi),%edi
  282. xor %esi,%edi
  283. not %esi
  284. and $0x80808080,%esi
  285. and %edi,%esi
  286. jnz .Lfound12
  287. add $16,%eax
  288. .Laligned:
  289. sub $16,%edx
  290. jae .Lloop { Still more than 16 bytes remaining }
  291. { Process remaining bytes (<16 left at this point) }
  292. { length is offset by -16 at this point }
  293. .Lloop2:
  294. cmp $4-16,%edx { < 4 bytes left? }
  295. jb .Ltail
  296. mov (%eax),%esi
  297. xor %ecx,%esi
  298. lea -0x01010101(%esi),%edi
  299. xor %esi,%edi
  300. not %esi
  301. and $0x80808080,%esi
  302. and %edi,%esi
  303. jne .Lfound
  304. add $4,%eax
  305. sub $4,%edx
  306. jmp .Lloop2
  307. .Ltail: { Less than 4 bytes remaining, check one by one }
  308. and $3, %edx
  309. jz .Lnotfound
  310. .Lloop3:
  311. cmp %cl,(%eax)
  312. je .Lexit
  313. inc %eax
  314. dec %edx
  315. jnz .Lloop3
  316. .Lnotfound:
  317. or $-1,%eax
  318. jmp .Lexit1
  319. { add missing source pointer increments }
  320. .Lfound12:
  321. add $4,%eax
  322. .Lfound8:
  323. add $4,%eax
  324. .Lfound4:
  325. add $4,%eax
  326. .Lfound:
  327. test $0xff,%esi
  328. jnz .Lexit
  329. inc %eax
  330. test $0xff00,%esi
  331. jnz .Lexit
  332. inc %eax
  333. test $0xff0000,%esi
  334. jnz .Lexit
  335. inc %eax
  336. .Lexit:
  337. sub (%esp),%eax
  338. .Lexit1:
  339. pop %ecx { removes initial 'buf' value }
  340. pop %edi
  341. pop %esi
  342. end;
  343. {$endif FPC_SYSTEM_HAS_INDEXBYTE}
  344. {$ifndef FPC_SYSTEM_HAS_INDEXWORD}
  345. {$define FPC_SYSTEM_HAS_INDEXWORD}
  346. function Indexword(Const buf;len:SizeInt;b:word):SizeInt; assembler;
  347. var
  348. saveedi,saveebx : longint;
  349. asm
  350. movl %edi,saveedi
  351. movl %ebx,saveebx
  352. movl Buf,%edi // Load String
  353. movw b,%bx
  354. movl Len,%ecx // Load len
  355. xorl %eax,%eax
  356. testl %ecx,%ecx
  357. jz .Lcharposnotfound
  358. {$ifdef FPC_ENABLED_CLD}
  359. cld
  360. {$endif FPC_ENABLED_CLD}
  361. movl %ecx,%edx // Copy for easy manipulation
  362. movw %bx,%ax
  363. repne
  364. scasw
  365. jne .Lcharposnotfound
  366. incl %ecx
  367. subl %ecx,%edx
  368. movl %edx,%eax
  369. jmp .Lready
  370. .Lcharposnotfound:
  371. movl $-1,%eax
  372. .Lready:
  373. movl saveedi,%edi
  374. movl saveebx,%ebx
  375. end;
  376. {$endif FPC_SYSTEM_HAS_INDEXWORD}
  377. {$ifndef FPC_SYSTEM_HAS_INDEXDWORD}
  378. {$define FPC_SYSTEM_HAS_INDEXDWORD}
  379. function IndexDWord(Const buf;len:SizeInt;b:DWord):SizeInt; assembler;
  380. var
  381. saveedi,saveebx : longint;
  382. asm
  383. movl %edi,saveedi
  384. movl %ebx,saveebx
  385. movl %eax,%edi
  386. movl %ecx,%ebx
  387. movl %edx,%ecx
  388. xorl %eax,%eax
  389. testl %ecx,%ecx
  390. jz .Lcharposnotfound
  391. {$ifdef FPC_ENABLED_CLD}
  392. cld
  393. {$endif FPC_ENABLED_CLD}
  394. movl %ecx,%edx // Copy for easy manipulation
  395. movl %ebx,%eax
  396. repne
  397. scasl
  398. jne .Lcharposnotfound
  399. incl %ecx
  400. subl %ecx,%edx
  401. movl %edx,%eax
  402. jmp .Lready
  403. .Lcharposnotfound:
  404. movl $-1,%eax
  405. .Lready:
  406. movl saveedi,%edi
  407. movl saveebx,%ebx
  408. end;
  409. {$endif FPC_SYSTEM_HAS_INDEXDWORD}
  410. {$ifndef FPC_SYSTEM_HAS_COMPAREBYTE}
  411. {$define FPC_SYSTEM_HAS_COMPAREBYTE}
  412. function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt; assembler; nostackframe;
  413. asm
  414. cmpl $57,%ecx { empirically determined value on a Core 2 Duo Conroe }
  415. jg .LCmpbyteFull
  416. testl %ecx,%ecx
  417. je .LCmpbyteZero
  418. pushl %ebx
  419. .LCmpbyteLoop:
  420. movb (%eax),%bl
  421. cmpb (%edx),%bl
  422. leal 1(%eax),%eax
  423. leal 1(%edx),%edx
  424. jne .LCmpbyteExitFast
  425. decl %ecx
  426. jne .LCmpbyteLoop
  427. .LCmpbyteExitFast:
  428. movzbl -1(%edx),%ecx { Compare last position }
  429. movzbl %bl,%eax
  430. subl %ecx,%eax
  431. popl %ebx
  432. ret
  433. .LCmpbyteZero:
  434. movl $0,%eax
  435. ret
  436. .LCmpbyteFull:
  437. pushl %esi
  438. pushl %edi
  439. {$ifdef FPC_ENABLED_CLD}
  440. cld
  441. {$endif FPC_ENABLED_CLD}
  442. movl %eax,%edi
  443. movl %edx,%esi
  444. movl %ecx,%eax
  445. movl %edi,%ecx { Align on 32bits }
  446. negl %ecx { calc bytes to align (%edi and 3) xor 3= -%edi and 3 }
  447. andl $3,%ecx
  448. subl %ecx,%eax { Subtract from number of bytes to go }
  449. orl %ecx,%ecx
  450. repe
  451. cmpsb { The actual 32-bit Aligning }
  452. jne .LCmpbyte3
  453. movl %eax,%ecx { bytes to do, divide by 4 }
  454. andl $3,%eax { remainder }
  455. shrl $2,%ecx { The actual division }
  456. orl %ecx,%ecx { Sets zero flag if ecx=0 -> no cmp }
  457. repe
  458. cmpsl
  459. je .LCmpbyte2 { All equal? then to the left over bytes }
  460. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise }
  461. subl %eax,%esi
  462. subl %eax,%edi
  463. .LCmpbyte2:
  464. movl %eax,%ecx { bytes still to (re)scan }
  465. orl %eax,%eax { prevent disaster in case %eax=0 }
  466. repe
  467. cmpsb
  468. .LCmpbyte3:
  469. movzbl -1(%esi),%ecx
  470. movzbl -1(%edi),%eax { Compare failing (or equal) position }
  471. subl %ecx,%eax
  472. .LCmpbyteExit:
  473. popl %edi
  474. popl %esi
  475. end;
  476. {$endif FPC_SYSTEM_HAS_COMPAREBYTE}
  477. {$ifndef FPC_SYSTEM_HAS_COMPAREWORD}
  478. {$define FPC_SYSTEM_HAS_COMPAREWORD}
  479. function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler; nostackframe;
  480. asm
  481. cmpl $32,%ecx { empirical average value, on a Athlon XP the
  482. break even is at 14, on a Core 2 Duo > 100 }
  483. jg .LCmpWordFull
  484. testl %ecx,%ecx
  485. je .LCmpWordZero
  486. pushl %ebx
  487. .LCmpWordLoop:
  488. movw (%eax),%bx
  489. cmpw (%edx),%bx
  490. leal 2(%eax),%eax
  491. leal 2(%edx),%edx
  492. jne .LCmpWordExitFast
  493. decl %ecx
  494. jne .LCmpWordLoop
  495. .LCmpWordExitFast:
  496. movzwl -2(%edx),%ecx { Compare last position }
  497. movzwl %bx,%eax
  498. subl %ecx,%eax
  499. popl %ebx
  500. ret
  501. .LCmpWordZero:
  502. movl $0,%eax
  503. ret
  504. .LCmpWordFull:
  505. pushl %esi
  506. pushl %edi
  507. pushl %ebx
  508. {$ifdef FPC_ENABLED_CLD}
  509. cld
  510. {$endif FPC_ENABLED_CLD}
  511. movl %eax,%edi
  512. movl %edx,%esi
  513. movl %ecx,%eax
  514. movl (%edi),%ebx // Compare alignment bytes.
  515. cmpl (%esi),%ebx
  516. jne .LCmpword2 // Aligning will go wrong already. Max 2 words will be scanned Branch NOW
  517. shll $1,%eax {Convert word count to bytes}
  518. movl %edi,%edx { Align comparing is already done, so simply add}
  519. negl %edx { calc bytes to align -%edi and 3}
  520. andl $3,%edx
  521. addl %edx,%esi { Skip max 3 bytes alignment}
  522. addl %edx,%edi
  523. subl %edx,%eax { Subtract from number of bytes to go}
  524. movl %eax,%ecx { Make copy of bytes to go}
  525. andl $3,%eax { Calc remainder (mod 4) }
  526. andl $1,%edx { %edx is 1 if array not 2-aligned, 0 otherwise}
  527. shrl $2,%ecx { divide bytes to go by 4, DWords to go}
  528. orl %ecx,%ecx { Sets zero flag if ecx=0 -> no cmp}
  529. repe { Compare entire DWords}
  530. cmpsl
  531. je .LCmpword2a { All equal? then to the left over bytes}
  532. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  533. subl %eax,%esi { Go back one DWord}
  534. subl %eax,%edi
  535. incl %eax {if not odd then this does nothing, else it makes
  536. sure that adding %edx increases from 2 to 3 words}
  537. .LCmpword2a:
  538. subl %edx,%esi { Subtract alignment}
  539. subl %edx,%edi
  540. addl %edx,%eax
  541. shrl $1,%eax
  542. .LCmpword2:
  543. movl %eax,%ecx {words still to (re)scan}
  544. orl %eax,%eax {prevent disaster in case %eax=0}
  545. repe
  546. cmpsw
  547. .LCmpword3:
  548. movzwl -2(%esi),%ecx
  549. movzwl -2(%edi),%eax // Compare failing (or equal) position
  550. subl %ecx,%eax // calculate end result.
  551. .LCmpwordExit:
  552. popl %ebx
  553. popl %edi
  554. popl %esi
  555. end;
  556. {$endif FPC_SYSTEM_HAS_COMPAREWORD}
  557. {$ifndef FPC_SYSTEM_HAS_COMPAREDWORD}
  558. {$define FPC_SYSTEM_HAS_COMPAREDWORD}
  559. function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler; nostackframe;
  560. asm
  561. cmpl $32,%ecx { empirical average value, on a Athlon XP the
  562. break even is at 12, on a Core 2 Duo > 100 }
  563. jg .LCmpDWordFull
  564. testl %ecx,%ecx
  565. je .LCmpDWordZero
  566. pushl %ebx
  567. .LCmpDWordLoop:
  568. movl (%eax),%ebx
  569. cmpl (%edx),%ebx
  570. leal 4(%eax),%eax
  571. leal 4(%edx),%edx
  572. jne .LCmpDWordExitFast
  573. decl %ecx
  574. jne .LCmpDWordLoop
  575. .LCmpDWordExitFast:
  576. xorl %eax,%eax
  577. movl -4(%edx),%edx // Compare failing (or equal) position
  578. subl %edx,%ebx // calculate end result.
  579. setb %dl
  580. seta %cl
  581. addb %cl,%al
  582. subb %dl,%al
  583. movsbl %al,%eax
  584. popl %ebx
  585. ret
  586. .LCmpDWordZero:
  587. movl $0,%eax
  588. ret
  589. .LCmpDWordFull:
  590. pushl %esi
  591. pushl %edi
  592. {$ifdef FPC_ENABLED_CLD}
  593. cld
  594. {$endif FPC_ENABLED_CLD}
  595. movl %eax,%edi
  596. movl %edx,%esi
  597. xorl %eax,%eax
  598. repe { Compare entire DWords}
  599. cmpsl
  600. movl -4(%edi),%edi // Compare failing (or equal) position
  601. subl -4(%esi),%edi // calculate end result.
  602. setb %dl
  603. seta %cl
  604. addb %cl,%al
  605. subb %dl,%al
  606. movsbl %al,%eax
  607. .LCmpDwordExit:
  608. popl %edi
  609. popl %esi
  610. end;
  611. {$endif FPC_SYSTEM_HAS_COMPAREDWORD}
  612. {$ifndef FPC_SYSTEM_HAS_INDEXCHAR0}
  613. {$define FPC_SYSTEM_HAS_INDEXCHAR0}
  614. function IndexChar0(Const buf;len:SizeInt;b:Char):SizeInt; assembler;
  615. var
  616. saveesi,saveebx : longint;
  617. asm
  618. movl %esi,saveesi
  619. movl %ebx,saveebx
  620. // Can't use scasb, or will have to do it twice, think this
  621. // is faster for small "len"
  622. movl %eax,%esi // Load address
  623. movzbl %cl,%ebx // Load searchpattern
  624. testl %edx,%edx
  625. je .LFound
  626. xorl %ecx,%ecx // zero index in Buf
  627. xorl %eax,%eax // To make DWord compares possible
  628. .balign 4
  629. .LLoop:
  630. movb (%esi),%al // Load byte
  631. cmpb %al,%bl
  632. je .LFound // byte the same?
  633. incl %ecx
  634. incl %esi
  635. cmpl %edx,%ecx // Maximal distance reached?
  636. je .LNotFound
  637. testl %eax,%eax // Nullchar = end of search?
  638. jne .LLoop
  639. .LNotFound:
  640. movl $-1,%ecx // Not found return -1
  641. .LFound:
  642. movl %ecx,%eax
  643. movl saveesi,%esi
  644. movl saveebx,%ebx
  645. end;
  646. {$endif FPC_SYSTEM_HAS_INDEXCHAR0}
  647. {****************************************************************************
  648. String
  649. ****************************************************************************}
  650. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  651. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  652. procedure fpc_shortstr_to_shortstr(out res:shortstring; const sstr: shortstring);assembler;[public,alias:'FPC_SHORTSTR_TO_SHORTSTR']; compilerproc;
  653. var
  654. saveesi,saveedi : longint;
  655. asm
  656. {$ifdef FPC_PROFILE}
  657. push %eax
  658. push %edx
  659. push %ecx
  660. call mcount
  661. pop %ecx
  662. pop %edx
  663. pop %eax
  664. {$endif FPC_PROFILE}
  665. movl %edi,saveedi
  666. movl %esi,saveesi
  667. {$ifdef FPC_ENABLED_CLD}
  668. cld
  669. {$endif FPC_ENABLED_CLD}
  670. movl res,%edi
  671. movl sstr,%esi
  672. movl %edx,%ecx
  673. xorl %eax,%eax
  674. lodsb
  675. cmpl %ecx,%eax
  676. jbe .LStrCopy1
  677. movl %ecx,%eax
  678. .LStrCopy1:
  679. stosb
  680. cmpl $7,%eax
  681. jl .LStrCopy2
  682. movl %edi,%ecx { Align on 32bits }
  683. negl %ecx
  684. andl $3,%ecx
  685. subl %ecx,%eax
  686. rep
  687. movsb
  688. movl %eax,%ecx
  689. andl $3,%eax
  690. shrl $2,%ecx
  691. rep
  692. movsl
  693. .LStrCopy2:
  694. movl %eax,%ecx
  695. rep
  696. movsb
  697. movl saveedi,%edi
  698. movl saveesi,%esi
  699. end;
  700. procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN'];
  701. begin
  702. asm
  703. {$ifdef FPC_PROFILE}
  704. push %eax
  705. push %edx
  706. push %ecx
  707. call mcount
  708. pop %ecx
  709. pop %edx
  710. pop %eax
  711. {$endif FPC_PROFILE}
  712. pushl %eax
  713. pushl %ecx
  714. {$ifdef FPC_ENABLED_CLD}
  715. cld
  716. {$endif FPC_ENABLED_CLD}
  717. movl dstr,%edi
  718. movl sstr,%esi
  719. xorl %eax,%eax
  720. movl len,%ecx
  721. lodsb
  722. cmpl %ecx,%eax
  723. jbe .LStrCopy1
  724. movl %ecx,%eax
  725. .LStrCopy1:
  726. stosb
  727. cmpl $7,%eax
  728. jl .LStrCopy2
  729. movl %edi,%ecx { Align on 32bits }
  730. negl %ecx
  731. andl $3,%ecx
  732. subl %ecx,%eax
  733. rep
  734. movsb
  735. movl %eax,%ecx
  736. andl $3,%eax
  737. shrl $2,%ecx
  738. rep
  739. movsl
  740. .LStrCopy2:
  741. movl %eax,%ecx
  742. rep
  743. movsb
  744. popl %ecx
  745. popl %eax
  746. end ['ESI','EDI'];
  747. end;
  748. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  749. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  750. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  751. function fpc_shortstr_compare(const left,right:shortstring): longint;assembler; [public,alias:'FPC_SHORTSTR_COMPARE']; compilerproc;
  752. var
  753. saveesi,saveedi,saveebx : longint;
  754. asm
  755. {$ifdef FPC_PROFILE}
  756. push %eax
  757. push %edx
  758. push %ecx
  759. call mcount
  760. pop %ecx
  761. pop %edx
  762. pop %eax
  763. {$endif FPC_PROFILE}
  764. movl %edi,saveedi
  765. movl %esi,saveesi
  766. movl %ebx,saveebx
  767. {$ifdef FPC_ENABLED_CLD}
  768. cld
  769. {$endif FPC_ENABLED_CLD}
  770. movl right,%esi
  771. movl left,%edi
  772. movzbl (%esi),%eax
  773. movzbl (%edi),%ebx
  774. movl %eax,%edx
  775. incl %esi
  776. incl %edi
  777. cmpl %ebx,%eax
  778. jbe .LStrCmp1
  779. movl %ebx,%eax
  780. .LStrCmp1:
  781. cmpl $7,%eax
  782. jl .LStrCmp2
  783. movl %edi,%ecx { Align on 32bits }
  784. negl %ecx
  785. andl $3,%ecx
  786. subl %ecx,%eax
  787. orl %ecx,%ecx
  788. repe
  789. cmpsb
  790. jne .LStrCmp3
  791. movl %eax,%ecx
  792. andl $3,%eax
  793. shrl $2,%ecx
  794. orl %ecx,%ecx
  795. repe
  796. cmpsl
  797. je .LStrCmp2
  798. movl $4,%eax
  799. subl %eax,%esi
  800. subl %eax,%edi
  801. .LStrCmp2:
  802. movl %eax,%ecx
  803. orl %eax,%eax
  804. repe
  805. cmpsb
  806. je .LStrCmp4
  807. .LStrCmp3:
  808. movzbl -1(%esi),%edx // Compare failing (or equal) position
  809. movzbl -1(%edi),%ebx
  810. .LStrCmp4:
  811. movl %ebx,%eax // Compare length or position
  812. subl %edx,%eax
  813. movl saveedi,%edi
  814. movl saveesi,%esi
  815. movl saveebx,%ebx
  816. end;
  817. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  818. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  819. {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  820. procedure fpc_pchar_to_shortstr(out res : shortstring;p:pchar);assembler;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; compilerproc;
  821. var
  822. saveres,saveebx,saveesi,saveedi : longint;
  823. asm
  824. {$ifdef FPC_PROFILE}
  825. push %eax
  826. push %edx
  827. push %ecx
  828. call mcount
  829. pop %ecx
  830. pop %edx
  831. pop %eax
  832. {$endif FPC_PROFILE}
  833. movl %ebx,saveebx
  834. movl %esi,saveesi
  835. movl %edi,saveedi
  836. movl %ecx,%esi
  837. movl %eax,%edi
  838. movl %edi,saveres
  839. movl $1,%ecx
  840. testl %esi,%esi
  841. movl %esi,%eax
  842. jz .LStrPasDone
  843. leal 3(%esi),%edx
  844. andl $-4,%edx
  845. // skip length byte
  846. incl %edi
  847. subl %esi,%edx
  848. jz .LStrPasAligned
  849. // align source to multiple of 4 (not dest, because we can't read past
  850. // the end of the source, since that may be past the end of the heap
  851. // -> sigsegv!!)
  852. .LStrPasAlignLoop:
  853. movb (%esi),%al
  854. incl %esi
  855. testb %al,%al
  856. jz .LStrPasDone
  857. incl %edi
  858. incb %cl
  859. decb %dl
  860. movb %al,-1(%edi)
  861. jne .LStrPasAlignLoop
  862. .balign 16
  863. .LStrPasAligned:
  864. movl (%esi),%ebx
  865. addl $4,%edi
  866. leal 0x0fefefeff(%ebx),%eax
  867. movl %ebx,%edx
  868. addl $4,%esi
  869. notl %edx
  870. andl %edx,%eax
  871. addl $4,%ecx
  872. andl $0x080808080,%eax
  873. movl %ebx,-4(%edi)
  874. jnz .LStrPasEndFound
  875. cmpl $252,%ecx
  876. ja .LStrPasPreEndLoop
  877. jmp .LStrPasAligned
  878. .LStrPasEndFound:
  879. subl $4,%ecx
  880. // this won't overwrite data since the result = 255 char string
  881. // and we never process more than the first 255 chars of p
  882. shrl $8,%eax
  883. jc .LStrPasDone
  884. incl %ecx
  885. shrl $8,%eax
  886. jc .LStrPasDone
  887. incl %ecx
  888. shrl $8,%eax
  889. jc .LStrPasDone
  890. incl %ecx
  891. jmp .LStrPasDone
  892. .LStrPasPreEndLoop:
  893. testb %cl,%cl
  894. jz .LStrPasDone
  895. movl (%esi),%eax
  896. .LStrPasEndLoop:
  897. testb %al,%al
  898. jz .LStrPasDone
  899. movb %al,(%edi)
  900. shrl $8,%eax
  901. incl %edi
  902. incb %cl
  903. jnz .LStrPasEndLoop
  904. .LStrPasDone:
  905. movl saveres,%edi
  906. addb $255,%cl
  907. movb %cl,(%edi)
  908. movl saveesi,%esi
  909. movl saveedi,%edi
  910. movl saveebx,%ebx
  911. end;
  912. {$endif FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  913. {$IFNDEF INTERNAL_BACKTRACE}
  914. {$define FPC_SYSTEM_HAS_GET_FRAME}
  915. function get_frame:pointer;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  916. asm
  917. movl %ebp,%eax
  918. end;
  919. {$ENDIF not INTERNAL_BACKTRACE}
  920. {$define FPC_SYSTEM_HAS_GET_PC_ADDR}
  921. Function Get_pc_addr : Pointer;assembler;nostackframe;
  922. asm
  923. movl (%esp),%eax
  924. end;
  925. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  926. function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;
  927. {$if defined(win32)}
  928. { Windows has StackTop always properly set }
  929. begin
  930. if assigned(framebp) and (framebp<=StackTop) and (framebp>=Sptr) then
  931. Result:=PPointer(framebp+4)^
  932. else
  933. Result:=nil;
  934. end;
  935. {$else defined(win32)}
  936. nostackframe;assembler;
  937. asm
  938. orl %eax,%eax
  939. jz .Lg_a_null
  940. movl 4(%eax),%eax
  941. .Lg_a_null:
  942. end;
  943. {$endif defined(win32)}
  944. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  945. function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;
  946. {$if defined(win32)}
  947. { Windows has StackTop always properly set }
  948. begin
  949. if assigned(framebp) and (framebp<=StackTop) and (framebp>=Sptr) then
  950. Result:=PPointer(framebp)^
  951. else
  952. Result:=nil;
  953. end;
  954. {$else defined(win32)}
  955. nostackframe;assembler;
  956. asm
  957. orl %eax,%eax
  958. jz .Lgnf_null
  959. movl (%eax),%eax
  960. .Lgnf_null:
  961. end;
  962. {$endif defined(win32)}
  963. {$define FPC_SYSTEM_HAS_SPTR}
  964. Function Sptr : Pointer;assembler;nostackframe;
  965. asm
  966. movl %esp,%eax
  967. end;
  968. {****************************************************************************
  969. Str()
  970. ****************************************************************************}
  971. {$if defined(disabled) and defined(regcall) }
  972. {$define FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  973. {$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
  974. label str_int_shortcut;
  975. procedure int_str(l:longword;out s:string);assembler;nostackframe;
  976. asm
  977. pushl %esi
  978. pushl %edi
  979. pushl %ebx
  980. mov %edx,%edi
  981. xor %edx,%edx
  982. jmp str_int_shortcut
  983. end;
  984. procedure int_str(l:longint;out s:string);assembler;nostackframe;
  985. {Optimized for speed, but balanced with size.}
  986. const digits:array[0..9] of cardinal=(0,10,100,1000,10000,
  987. 100000,1000000,10000000,
  988. 100000000,1000000000);
  989. asm
  990. {$ifdef FPC_PROFILE}
  991. push %eax
  992. push %edx
  993. push %ecx
  994. call mcount
  995. pop %ecx
  996. pop %edx
  997. pop %eax
  998. {$endif FPC_PROFILE}
  999. push %esi
  1000. push %edi
  1001. push %ebx
  1002. movl %edx,%edi
  1003. { Calculate absolute value and put sign in edx}
  1004. cltd
  1005. xorl %edx,%eax
  1006. subl %edx,%eax
  1007. negl %edx
  1008. str_int_shortcut:
  1009. movl %ecx,%esi
  1010. {Calculate amount of digits in ecx.}
  1011. xorl %ecx,%ecx
  1012. bsrl %eax,%ecx
  1013. incl %ecx
  1014. imul $1233,%ecx
  1015. shr $12,%ecx
  1016. {$ifdef FPC_PIC}
  1017. call fpc_geteipasebx
  1018. {$ifdef darwin}
  1019. movl digits-.Lpic(%ebx),%ebx
  1020. {$else}
  1021. addl $_GLOBAL_OFFSET_TABLE_,%ebx
  1022. movl digits@GOT(%ebx),%ebx
  1023. {$endif}
  1024. cmpl (%ebx,%ecx,4),%eax
  1025. {$else}
  1026. cmpl digits(,%ecx,4),%eax
  1027. {$endif}
  1028. cmc
  1029. adcl $0,%ecx {Nr. digits ready in ecx.}
  1030. {Write length & sign.}
  1031. lea (%edx,%ecx),%ebx
  1032. movb $45,%bh {movb $'-,%bh Not supported by our ATT reader.}
  1033. movw %bx,(%edi)
  1034. addl %edx,%edi
  1035. subl %edx,%esi
  1036. {Skip digits beyond string length.}
  1037. movl %eax,%edx
  1038. subl %ecx,%esi
  1039. jae .Lloop_write
  1040. .balign 4
  1041. .Lloop_skip:
  1042. movl $0xcccccccd,%eax {Divide by 10 using mul+shr}
  1043. mull %edx
  1044. shrl $3,%edx
  1045. decl %ecx
  1046. jz .Ldone {If (l<0) and (high(s)=1) this jump is taken.}
  1047. incl %esi
  1048. jnz .Lloop_skip
  1049. {Write out digits.}
  1050. .balign 4
  1051. .Lloop_write:
  1052. movl $0xcccccccd,%eax {Divide by 10 using mul+shr}
  1053. {Pre-add '0'}
  1054. leal 48(%edx),%ebx {leal $'0(,%edx),%ebx Not supported by our ATT reader.}
  1055. mull %edx
  1056. shrl $3,%edx
  1057. leal (%edx,%edx,8),%eax {x mod 10 = x-10*(x div 10)}
  1058. subl %edx,%ebx
  1059. subl %eax,%ebx
  1060. movb %bl,(%edi,%ecx)
  1061. decl %ecx
  1062. jnz .Lloop_write
  1063. .Ldone:
  1064. popl %ebx
  1065. popl %edi
  1066. popl %esi
  1067. end;
  1068. {$endif}
  1069. {****************************************************************************
  1070. Bounds Check
  1071. ****************************************************************************}
  1072. { do a thread-safe inc/dec }
  1073. {$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  1074. function cpudeclocked(var l : longint) : boolean;assembler;nostackframe;
  1075. asm
  1076. { this check should be done because a lock takes a lot }
  1077. { of time! }
  1078. lock
  1079. decl (%eax)
  1080. setzb %al
  1081. end;
  1082. {$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  1083. procedure cpuinclocked(var l : longint);assembler;nostackframe;
  1084. asm
  1085. lock
  1086. incl (%eax)
  1087. end;
  1088. // inline SMP check and normal lock.
  1089. // the locked one is so slow, inlining doesn't matter.
  1090. function declocked(var l : longint) : boolean; inline;
  1091. begin
  1092. if not ismultithread then
  1093. begin
  1094. dec(l);
  1095. declocked:=l=0;
  1096. end
  1097. else
  1098. declocked:=cpudeclocked(l);
  1099. end;
  1100. procedure inclocked(var l : longint); inline;
  1101. begin
  1102. if not ismultithread then
  1103. inc(l)
  1104. else
  1105. cpuinclocked(l);
  1106. end;
  1107. function InterLockedDecrement (var Target: longint) : longint; assembler;
  1108. asm
  1109. movl $-1,%edx
  1110. xchgl %edx,%eax
  1111. lock
  1112. xaddl %eax, (%edx)
  1113. decl %eax
  1114. end;
  1115. function InterLockedIncrement (var Target: longint) : longint; assembler;
  1116. asm
  1117. movl $1,%edx
  1118. xchgl %edx,%eax
  1119. lock
  1120. xaddl %eax, (%edx)
  1121. incl %eax
  1122. end;
  1123. function InterLockedExchange (var Target: longint;Source : longint) : longint; assembler;
  1124. asm
  1125. xchgl (%eax),%edx
  1126. movl %edx,%eax
  1127. end;
  1128. function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint; assembler;
  1129. asm
  1130. xchgl %eax,%edx
  1131. lock
  1132. xaddl %eax, (%edx)
  1133. end;
  1134. function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint; assembler;
  1135. asm
  1136. xchgl %eax,%ecx
  1137. lock
  1138. cmpxchgl %edx, (%ecx)
  1139. end;
  1140. function InterlockedCompareExchange64(var Target: int64; NewValue: int64; Comperand: int64): int64; assembler;
  1141. asm
  1142. pushl %ebx
  1143. pushl %edi
  1144. movl %eax,%edi
  1145. movl Comperand+4,%edx
  1146. movl Comperand+0,%eax
  1147. movl NewValue+4,%ecx
  1148. movl NewValue+0,%ebx
  1149. lock cmpxchg8b (%edi)
  1150. pop %edi
  1151. pop %ebx
  1152. end;
  1153. {****************************************************************************
  1154. FPU
  1155. ****************************************************************************}
  1156. const
  1157. { Internal constants for use in system unit }
  1158. FPU_Invalid = 1;
  1159. FPU_Denormal = 2;
  1160. FPU_DivisionByZero = 4;
  1161. FPU_Overflow = 8;
  1162. FPU_Underflow = $10;
  1163. FPU_StackUnderflow = $20;
  1164. FPU_StackOverflow = $40;
  1165. FPU_ExceptionMask = $ff;
  1166. MM_MaskInvalidOp = %0000000010000000;
  1167. MM_MaskDenorm = %0000000100000000;
  1168. MM_MaskDivZero = %0000001000000000;
  1169. MM_MaskOverflow = %0000010000000000;
  1170. MM_MaskUnderflow = %0000100000000000;
  1171. MM_MaskPrecision = %0001000000000000;
  1172. {$define FPC_SYSTEM_HAS_SYSINITFPU}
  1173. Procedure SysInitFPU;
  1174. begin
  1175. end;
  1176. {$define FPC_SYSTEM_HAS_SYSRESETFPU}
  1177. Procedure SysResetFPU;
  1178. var
  1179. { these locals are so we don't have to hack pic code in the assembler }
  1180. localmxcsr: dword;
  1181. localfpucw: word;
  1182. begin
  1183. localfpucw:=Default8087CW;
  1184. asm
  1185. fninit
  1186. fwait
  1187. fldcw localfpucw
  1188. end;
  1189. if has_sse_support then
  1190. begin
  1191. localmxcsr:=DefaultMXCSR;
  1192. asm
  1193. { setup sse exceptions }
  1194. {$ifndef OLD_ASSEMBLER}
  1195. ldmxcsr localmxcsr
  1196. {$else OLD_ASSEMBLER}
  1197. mov localmxcsr,%eax
  1198. subl $4,%esp
  1199. mov %eax,(%esp)
  1200. //ldmxcsr (%esp)
  1201. .byte 0x0f,0xae,0x14,0x24
  1202. addl $4,%esp
  1203. {$endif OLD_ASSEMBLER}
  1204. end;
  1205. end;
  1206. end;
  1207. { because of the brain dead sse detection on x86, this test is post poned }
  1208. procedure fpc_cpucodeinit;
  1209. var
  1210. _ecx,_edx : longint;
  1211. begin
  1212. if cpuid_support then
  1213. begin
  1214. asm
  1215. movl $1,%eax
  1216. cpuid
  1217. movl %edx,_edx
  1218. movl %ecx,_ecx
  1219. end ['ebx'];
  1220. has_mmx_support:=(_edx and $800000)<>0;
  1221. if ((_edx and $2000000)<>0) then
  1222. begin
  1223. os_supports_sse:=true;
  1224. sse_check:=true;
  1225. asm
  1226. { force an sse exception if no sse is supported, the exception handler sets
  1227. os_supports_sse to false then }
  1228. { don't change this instruction, the code above depends on its size }
  1229. {$ifdef OLD_ASSEMBLER}
  1230. .byte 0x0f,0x28,0xf7
  1231. {$else}
  1232. movaps %xmm7, %xmm6
  1233. {$endif not EMX}
  1234. end;
  1235. sse_check:=false;
  1236. has_sse_support:=os_supports_sse;
  1237. end;
  1238. if has_sse_support then
  1239. begin
  1240. has_sse2_support:=((_edx and $4000000)<>0);
  1241. has_sse3_support:=((_ecx and $200)<>0);
  1242. end;
  1243. end;
  1244. { don't let libraries influence the FPU cw set by the host program }
  1245. if IsLibrary then
  1246. begin
  1247. Default8087CW:=Get8087CW;
  1248. if has_sse_support then
  1249. DefaultMXCSR:=GetMXCSR;
  1250. end;
  1251. SysResetFPU;
  1252. {$ifdef USE_FASTMOVE}
  1253. setup_fastmove;
  1254. {$endif}
  1255. end;
  1256. {$if not defined(darwin) and defined(regcall) }
  1257. { darwin requires that the stack is aligned to 16 bytes when calling another function }
  1258. {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
  1259. {$define FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
  1260. Procedure fpc_AnsiStr_Decr_Ref (Var S : Pointer); [Public,Alias:'FPC_ANSISTR_DECR_REF']; compilerproc; nostackframe; assembler;
  1261. asm
  1262. cmpl $0,(%eax)
  1263. je .Lquit
  1264. pushl %esi
  1265. movl (%eax),%esi
  1266. subl $12,%esi // points to start of allocation
  1267. movl $0,(%eax) // s:=nil
  1268. cmpl $0,4(%esi) // exit if refcount<0
  1269. jl .Lj3596
  1270. {$ifdef FPC_PIC}
  1271. pushl %ebx
  1272. call fpc_geteipasebx
  1273. addl $_GLOBAL_OFFSET_TABLE_,%ebx
  1274. movl ismultithread@GOT(%ebx),%ebx
  1275. movl (%ebx),%ebx
  1276. cmp $0, %ebx
  1277. popl %ebx
  1278. {$else FPC_PIC}
  1279. cmpl $0,ismultithread
  1280. {$endif FPC_PIC}
  1281. jne .Lj3610
  1282. decl 4(%esi)
  1283. je .Lj3620
  1284. jmp .Lj3596
  1285. .Lj3610:
  1286. leal 4(%esi),%eax
  1287. call cpudeclocked
  1288. testb %al,%al
  1289. je .Lj3596
  1290. .Lj3620:
  1291. movl %esi,%eax
  1292. call FPC_FREEMEM
  1293. .Lj3596:
  1294. popl %esi
  1295. .Lquit:
  1296. end;
  1297. function fpc_truely_ansistr_unique(Var S : Pointer): Pointer; forward;
  1298. {$define FPC_SYSTEM_HAS_ANSISTR_UNIQUE}
  1299. Function fpc_ansistr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_ANSISTR_UNIQUE']; compilerproc; nostackframe;assembler;
  1300. asm
  1301. // Var S located in register
  1302. // Var $result located in register
  1303. movl %eax,%edx
  1304. // [437] pointer(result) := pointer(s);
  1305. movl (%eax),%eax
  1306. // [438] If Pointer(S)=Nil then
  1307. testl %eax,%eax
  1308. je .Lj4031
  1309. .Lj4036:
  1310. // [440] if PAnsiRec(Pointer(S)-Firstoff)^.Ref<>1 then
  1311. movl -8(%eax),%ecx
  1312. cmpl $1,%ecx
  1313. je .Lj4038
  1314. // [441] result:=fpc_truely_ansistr_unique(s);
  1315. movl %edx,%eax
  1316. call fpc_truely_ansistr_unique
  1317. .Lj4038:
  1318. .Lj4031:
  1319. // [442] end;
  1320. end;
  1321. {$endif FPC_HAS_FEATURE_ANSISTRINGS}
  1322. {$endif ndef darwin and defined(regcall) }
  1323. {$ifndef FPC_SYSTEM_HAS_MEM_BARRIER}
  1324. {$define FPC_SYSTEM_HAS_MEM_BARRIER}
  1325. procedure ReadBarrier;assembler;nostackframe;
  1326. asm
  1327. lock
  1328. addl $0,0(%esp)
  1329. { alternative: lfence on SSE capable CPUs }
  1330. end;
  1331. procedure ReadDependencyBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  1332. begin
  1333. { reads imply barrier on earlier reads depended on }
  1334. end;
  1335. procedure ReadWriteBarrier;assembler;nostackframe;
  1336. asm
  1337. lock
  1338. addl $0,0(%esp)
  1339. { alternative: mfence on SSE capable CPUs }
  1340. end;
  1341. procedure WriteBarrier;assembler;nostackframe;
  1342. asm
  1343. { no write reordering on intel CPUs (yet) }
  1344. end;
  1345. {$endif}
  1346. {$ifndef FPC_SYSTEM_HAS_BSF_QWORD}
  1347. {$define FPC_SYSTEM_HAS_BSF_QWORD}
  1348. function BsfQWord(Const AValue : QWord): cardinal; assembler; nostackframe;
  1349. asm
  1350. bsfl 4(%esp),%eax
  1351. jnz .L2
  1352. .L1:
  1353. bsfl 8(%esp),%eax
  1354. jnz .L3
  1355. movl $223,%eax
  1356. .L3:
  1357. addl $32,%eax
  1358. .L2:
  1359. end;
  1360. {$endif FPC_SYSTEM_HAS_BSF_QWORD}
  1361. {$ifndef FPC_SYSTEM_HAS_BSR_QWORD}
  1362. {$define FPC_SYSTEM_HAS_BSR_QWORD}
  1363. function BsrQWord(Const AValue : QWord): cardinal; assembler; nostackframe;
  1364. asm
  1365. bsrl 8(%esp),%eax
  1366. jz .L1
  1367. add $32,%eax
  1368. jmp .L2
  1369. .L1:
  1370. bsrl 4(%esp),%eax
  1371. jnz .L2
  1372. movl $255,%eax
  1373. .L2:
  1374. end;
  1375. {$endif FPC_SYSTEM_HAS_BSR_QWORD}
  1376. {$ifndef FPC_SYSTEM_HAS_SAR_QWORD}
  1377. {$define FPC_SYSTEM_HAS_SAR_QWORD}
  1378. function fpc_SarInt64(Const AValue : Int64;const Shift : Byte): Int64; [Public,Alias:'FPC_SARINT64']; compilerproc; assembler; nostackframe;
  1379. asm
  1380. movb %al,%cl
  1381. movl 8(%esp),%edx
  1382. movl 4(%esp),%eax
  1383. andb $63,%cl
  1384. cmpb $32,%cl
  1385. jnb .L1
  1386. shrdl %cl,%edx,%eax
  1387. sarl %cl,%edx
  1388. jmp .Lexit
  1389. .L1:
  1390. movl %edx,%eax
  1391. sarl $31,%edx
  1392. andb $31,%cl
  1393. sarl %cl,%eax
  1394. .Lexit:
  1395. end;
  1396. {$endif FPC_SYSTEM_HAS_SAR_QWORD}