i386.inc 36 KB

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