2
0

i386.inc 38 KB

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