i386.inc 39 KB

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