i386.inc 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574
  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_PIC}
  84. {$if not defined(FPC_SYSTEM_HAS_MOVE) and defined(REGCALL) }
  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. end;
  99. {$ifndef FPC_SYSTEM_HAS_MOVE}
  100. {$define FPC_SYSTEM_HAS_MOVE}
  101. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE'];assembler;
  102. var
  103. saveesi,saveedi : longint;
  104. asm
  105. movl %edi,saveedi
  106. movl %esi,saveesi
  107. {$ifdef REGCALL}
  108. movl %eax,%esi
  109. movl %edx,%edi
  110. movl %ecx,%edx
  111. {$else}
  112. movl dest,%edi
  113. movl source,%esi
  114. movl count,%edx
  115. {$endif}
  116. movl %edi,%eax
  117. { check for zero or negative count }
  118. cmpl $0,%edx
  119. jle .LMoveEnd
  120. { Check for back or forward }
  121. sub %esi,%eax
  122. jz .LMoveEnd { Do nothing when source=dest }
  123. jc .LFMove { Do forward, dest<source }
  124. cmp %edx,%eax
  125. jb .LBMove { Dest is in range of move, do backward }
  126. { Forward Copy }
  127. .LFMove:
  128. cld
  129. cmpl $15,%edx
  130. jl .LFMove1
  131. movl %edi,%ecx { Align on 32bits }
  132. negl %ecx
  133. andl $3,%ecx
  134. subl %ecx,%edx
  135. rep
  136. movsb
  137. movl %edx,%ecx
  138. andl $3,%edx
  139. shrl $2,%ecx
  140. rep
  141. movsl
  142. .LFMove1:
  143. movl %edx,%ecx
  144. rep
  145. movsb
  146. jmp .LMoveEnd
  147. { Backward Copy }
  148. .LBMove:
  149. std
  150. addl %edx,%esi
  151. addl %edx,%edi
  152. movl %edi,%ecx
  153. decl %esi
  154. decl %edi
  155. cmpl $15,%edx
  156. jl .LBMove1
  157. negl %ecx { Align on 32bits }
  158. andl $3,%ecx
  159. subl %ecx,%edx
  160. rep
  161. movsb
  162. movl %edx,%ecx
  163. andl $3,%edx
  164. shrl $2,%ecx
  165. subl $3,%esi
  166. subl $3,%edi
  167. rep
  168. movsl
  169. addl $3,%esi
  170. addl $3,%edi
  171. .LBMove1:
  172. movl %edx,%ecx
  173. rep
  174. movsb
  175. cld
  176. .LMoveEnd:
  177. movl saveedi,%edi
  178. movl saveesi,%esi
  179. end;
  180. {$endif FPC_SYSTEM_HAS_MOVE}
  181. {$ifndef FPC_SYSTEM_HAS_FILLCHAR}
  182. {$define FPC_SYSTEM_HAS_FILLCHAR}
  183. Procedure FillChar(var x;count:SizeInt;value:byte);assembler;
  184. {$ifndef regcall}
  185. var
  186. saveedi: longint;
  187. {$endif}
  188. asm
  189. {A push is prefered over a local variable because a local
  190. variable causes the compiler to generate a stackframe.}
  191. cld
  192. {$ifdef REGCALL}
  193. push %edi
  194. movl %eax,%edi
  195. movzbl %cl,%eax
  196. movl %edx,%ecx
  197. {$else}
  198. movl %edi, saveedi
  199. movl x,%edi
  200. movl count,%ecx
  201. movzbl value,%eax
  202. movl %ecx,%edx
  203. {$endif}
  204. { check for zero or negative count }
  205. or %ecx,%ecx
  206. jle .LFillEnd
  207. cmpl $7,%ecx
  208. jl .LFill1
  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. {$ifdef REGCALL}
  220. pop %edi
  221. {$else}
  222. movl saveedi,%edi
  223. {$endif}
  224. end;
  225. {$endif FPC_SYSTEM_HAS_FILLCHAR}
  226. {$ifndef FPC_SYSTEM_HAS_FILLWORD}
  227. {$define FPC_SYSTEM_HAS_FILLWORD}
  228. procedure fillword(var x;count : SizeInt;value : word);assembler;
  229. var
  230. saveedi : longint;
  231. asm
  232. movl %edi,saveedi
  233. {$ifdef REGCALL}
  234. movl %eax,%edi
  235. movzwl %cx,%eax
  236. movl %edx,%ecx
  237. {$else}
  238. movl x,%edi
  239. movl count,%ecx
  240. movzwl value,%eax
  241. {$endif}
  242. { check for zero or negative count }
  243. cmpl $0,%ecx
  244. jle .LFillWordEnd
  245. movl %eax,%edx
  246. shll $16,%eax
  247. orl %edx,%eax
  248. movl %ecx,%edx
  249. shrl $1,%ecx
  250. cld
  251. rep
  252. stosl
  253. movl %edx,%ecx
  254. andl $1,%ecx
  255. rep
  256. stosw
  257. .LFillWordEnd:
  258. movl saveedi,%edi
  259. end;
  260. {$endif FPC_SYSTEM_HAS_FILLWORD}
  261. {$ifndef FPC_SYSTEM_HAS_FILLDWORD}
  262. {$define FPC_SYSTEM_HAS_FILLDWORD}
  263. procedure filldword(var x;count : SizeInt;value : dword);assembler;
  264. var
  265. saveedi : longint;
  266. asm
  267. movl %edi,saveedi
  268. {$ifdef REGCALL}
  269. movl %eax,%edi
  270. movl %ecx,%eax
  271. movl %edx,%ecx
  272. {$else}
  273. movl x,%edi
  274. movl count,%ecx
  275. movl value,%eax
  276. {$endif}
  277. { check for zero or negative count }
  278. cmpl $0,%ecx
  279. jle .LFillDWordEnd
  280. cld
  281. rep
  282. stosl
  283. .LFillDWordEnd:
  284. movl saveedi,%edi
  285. end;
  286. {$endif FPC_SYSTEM_HAS_FILLDWORD}
  287. {$ifndef FPC_SYSTEM_HAS_INDEXBYTE}
  288. {$define FPC_SYSTEM_HAS_INDEXBYTE}
  289. function IndexByte(Const buf;len:SizeInt;b:byte):SizeInt; assembler;
  290. var
  291. saveedi,saveebx : longint;
  292. asm
  293. movl %edi,saveedi
  294. movl %ebx,saveebx
  295. movl buf,%edi // Load String
  296. movb b,%bl
  297. movl len,%ecx // Load len
  298. xorl %eax,%eax
  299. testl %ecx,%ecx
  300. jz .Lcharposnotfound
  301. cld
  302. movl %ecx,%edx // Copy for easy manipulation
  303. movb %bl,%al
  304. repne
  305. scasb
  306. jne .Lcharposnotfound
  307. incl %ecx
  308. subl %ecx,%edx
  309. movl %edx,%eax
  310. jmp .Lready
  311. .Lcharposnotfound:
  312. movl $-1,%eax
  313. .Lready:
  314. movl saveedi,%edi
  315. movl saveebx,%ebx
  316. end;
  317. {$endif FPC_SYSTEM_HAS_FILLDWORD}
  318. {$ifndef FPC_SYSTEM_HAS_INDEXWORD}
  319. {$define FPC_SYSTEM_HAS_INDEXWORD}
  320. function Indexword(Const buf;len:SizeInt;b:word):SizeInt; assembler;
  321. var
  322. saveedi,saveebx : longint;
  323. asm
  324. movl %edi,saveedi
  325. movl %ebx,saveebx
  326. movl Buf,%edi // Load String
  327. movw b,%bx
  328. movl Len,%ecx // Load len
  329. xorl %eax,%eax
  330. testl %ecx,%ecx
  331. jz .Lcharposnotfound
  332. cld
  333. movl %ecx,%edx // Copy for easy manipulation
  334. movw %bx,%ax
  335. repne
  336. scasw
  337. jne .Lcharposnotfound
  338. incl %ecx
  339. subl %ecx,%edx
  340. movl %edx,%eax
  341. jmp .Lready
  342. .Lcharposnotfound:
  343. movl $-1,%eax
  344. .Lready:
  345. movl saveedi,%edi
  346. movl saveebx,%ebx
  347. end;
  348. {$endif FPC_SYSTEM_HAS_INDEXWORD}
  349. {$ifndef FPC_SYSTEM_HAS_INDEXDWORD}
  350. {$define FPC_SYSTEM_HAS_INDEXDWORD}
  351. function IndexDWord(Const buf;len:SizeInt;b:DWord):SizeInt; assembler;
  352. var
  353. saveedi,saveebx : longint;
  354. asm
  355. movl %edi,saveedi
  356. movl %ebx,saveebx
  357. {$ifdef REGCALL}
  358. movl %eax,%edi
  359. movl %ecx,%ebx
  360. movl %edx,%ecx
  361. {$else}
  362. movl Len,%ecx // Load len
  363. movl Buf,%edi // Load String
  364. movl b,%ebx
  365. {$endif}
  366. xorl %eax,%eax
  367. testl %ecx,%ecx
  368. jz .Lcharposnotfound
  369. cld
  370. movl %ecx,%edx // Copy for easy manipulation
  371. movl %ebx,%eax
  372. repne
  373. scasl
  374. jne .Lcharposnotfound
  375. incl %ecx
  376. subl %ecx,%edx
  377. movl %edx,%eax
  378. jmp .Lready
  379. .Lcharposnotfound:
  380. movl $-1,%eax
  381. .Lready:
  382. movl saveedi,%edi
  383. movl saveebx,%ebx
  384. end;
  385. {$endif FPC_SYSTEM_HAS_INDEXDWORD}
  386. {$ifndef FPC_SYSTEM_HAS_COMPAREBYTE}
  387. {$define FPC_SYSTEM_HAS_COMPAREBYTE}
  388. function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt; assembler;
  389. var
  390. saveesi,saveedi : longint;
  391. asm
  392. movl %edi,saveedi
  393. movl %esi,saveesi
  394. cld
  395. {$ifdef REGCALL}
  396. movl %eax,%edi
  397. movl %edx,%esi
  398. movl %ecx,%eax
  399. {$else}
  400. movl buf2,%esi { Load params}
  401. movl buf1,%edi
  402. movl len,%eax
  403. {$endif}
  404. testl %eax,%eax {We address -1(%esi), so we have to deal with len=0}
  405. je .LCmpbyteExit
  406. cmpl $7,%eax {<7 not worth aligning and go through all trouble}
  407. jl .LCmpbyte2
  408. movl %edi,%ecx { Align on 32bits }
  409. negl %ecx { calc bytes to align (%edi and 3) xor 3= -%edi and 3}
  410. andl $3,%ecx
  411. subl %ecx,%eax { Subtract from number of bytes to go}
  412. orl %ecx,%ecx
  413. rep
  414. cmpsb {The actual 32-bit Aligning}
  415. jne .LCmpbyte3
  416. movl %eax,%ecx {bytes to do, divide by 4}
  417. andl $3,%eax {remainder}
  418. shrl $2,%ecx {The actual division}
  419. orl %ecx,%ecx {Sets zero flag if ecx=0 -> no cmp}
  420. rep
  421. cmpsl
  422. je .LCmpbyte2 { All equal? then to the left over bytes}
  423. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  424. subl %eax,%esi
  425. subl %eax,%edi
  426. .LCmpbyte2:
  427. movl %eax,%ecx {bytes still to (re)scan}
  428. orl %eax,%eax {prevent disaster in case %eax=0}
  429. rep
  430. cmpsb
  431. .LCmpbyte3:
  432. movzbl -1(%esi),%ecx
  433. movzbl -1(%edi),%eax // Compare failing (or equal) position
  434. subl %ecx,%eax
  435. .LCmpbyteExit:
  436. movl saveedi,%edi
  437. movl saveesi,%esi
  438. end;
  439. {$endif FPC_SYSTEM_HAS_COMPAREBYTE}
  440. {$ifndef FPC_SYSTEM_HAS_COMPAREWORD}
  441. {$define FPC_SYSTEM_HAS_COMPAREWORD}
  442. function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler;
  443. var
  444. saveesi,saveedi,saveebx : longint;
  445. asm
  446. movl %edi,saveedi
  447. movl %esi,saveesi
  448. movl %ebx,saveebx
  449. cld
  450. {$ifdef REGCALL}
  451. movl %eax,%edi
  452. movl %edx,%esi
  453. movl %ecx,%eax
  454. {$else}
  455. movl buf2,%esi { Load params}
  456. movl buf1,%edi
  457. movl len,%eax
  458. {$endif}
  459. testl %eax,%eax {We address -2(%esi), so we have to deal with len=0}
  460. je .LCmpwordExit
  461. cmpl $5,%eax {<5 (3 bytes align + 4 bytes cmpsl = 4 words}
  462. jl .LCmpword2 { not worth aligning and go through all trouble}
  463. movl (%edi),%ebx // Compare alignment bytes.
  464. cmpl (%esi),%ebx
  465. jne .LCmpword2 // Aligning will go wrong already. Max 2 words will be scanned Branch NOW
  466. shll $1,%eax {Convert word count to bytes}
  467. movl %edi,%edx { Align comparing is already done, so simply add}
  468. negl %edx { calc bytes to align -%edi and 3}
  469. andl $3,%edx
  470. addl %edx,%esi { Skip max 3 bytes alignment}
  471. addl %edx,%edi
  472. subl %edx,%eax { Subtract from number of bytes to go}
  473. movl %eax,%ecx { Make copy of bytes to go}
  474. andl $3,%eax { Calc remainder (mod 4) }
  475. andl $1,%edx { %edx is 1 if array not 2-aligned, 0 otherwise}
  476. shrl $2,%ecx { divide bytes to go by 4, DWords to go}
  477. orl %ecx,%ecx { Sets zero flag if ecx=0 -> no cmp}
  478. rep { Compare entire DWords}
  479. cmpsl
  480. je .LCmpword2a { All equal? then to the left over bytes}
  481. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  482. subl %eax,%esi { Go back one DWord}
  483. subl %eax,%edi
  484. incl %eax {if not odd then this does nothing, else it makes
  485. sure that adding %edx increases from 2 to 3 words}
  486. .LCmpword2a:
  487. subl %edx,%esi { Subtract alignment}
  488. subl %edx,%edi
  489. addl %edx,%eax
  490. shrl $1,%eax
  491. .LCmpword2:
  492. movl %eax,%ecx {words still to (re)scan}
  493. orl %eax,%eax {prevent disaster in case %eax=0}
  494. rep
  495. cmpsw
  496. .LCmpword3:
  497. movzwl -2(%esi),%ecx
  498. movzwl -2(%edi),%eax // Compare failing (or equal) position
  499. subl %ecx,%eax // calculate end result.
  500. .LCmpwordExit:
  501. movl saveedi,%edi
  502. movl saveesi,%esi
  503. movl saveebx,%ebx
  504. end;
  505. {$endif FPC_SYSTEM_HAS_COMPAREWORD}
  506. {$ifndef FPC_SYSTEM_HAS_COMPAREDWORD}
  507. {$define FPC_SYSTEM_HAS_COMPAREDWORD}
  508. function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler;
  509. var
  510. saveesi,saveedi,saveebx : longint;
  511. asm
  512. movl %edi,saveedi
  513. movl %esi,saveesi
  514. cld
  515. {$ifdef REGCALL}
  516. movl %eax,%edi
  517. movl %edx,%esi
  518. movl %ecx,%eax
  519. {$else}
  520. movl buf2,%esi { Load params}
  521. movl buf1,%edi
  522. movl len,%eax
  523. movl %eax,%ecx
  524. {$endif}
  525. testl %eax,%eax
  526. je .LCmpDwordExit
  527. movl %eax,%ecx
  528. xorl %eax,%eax
  529. rep { Compare entire DWords}
  530. cmpsl
  531. movl -4(%edi),%edi // Compare failing (or equal) position
  532. subl -4(%esi),%edi // calculate end result.
  533. setb %dl
  534. seta %cl
  535. addb %cl,%al
  536. subb %dl,%al
  537. movsbl %al,%eax
  538. .LCmpDwordExit:
  539. movl saveedi,%edi
  540. movl saveesi,%esi
  541. end;
  542. {$endif FPC_SYSTEM_HAS_COMPAREDWORD}
  543. {$ifndef FPC_SYSTEM_HAS_INDEXCHAR0}
  544. {$define FPC_SYSTEM_HAS_INDEXCHAR0}
  545. function IndexChar0(Const buf;len:SizeInt;b:Char):SizeInt; assembler;
  546. var
  547. saveesi,saveebx : longint;
  548. asm
  549. movl %esi,saveesi
  550. movl %ebx,saveebx
  551. // Can't use scasb, or will have to do it twice, think this
  552. // is faster for small "len"
  553. {$ifdef REGCALL}
  554. movl %eax,%esi // Load address
  555. movzbl %cl,%ebx // Load searchpattern
  556. {$else}
  557. movl Buf,%esi // Load address
  558. movl len,%edx // load maximal searchdistance
  559. movzbl b,%ebx // Load searchpattern
  560. {$endif}
  561. testl %edx,%edx
  562. je .LFound
  563. xorl %ecx,%ecx // zero index in Buf
  564. xorl %eax,%eax // To make DWord compares possible
  565. .balign 4
  566. .LLoop:
  567. movb (%esi),%al // Load byte
  568. cmpb %al,%bl
  569. je .LFound // byte the same?
  570. incl %ecx
  571. incl %esi
  572. cmpl %edx,%ecx // Maximal distance reached?
  573. je .LNotFound
  574. testl %eax,%eax // Nullchar = end of search?
  575. jne .LLoop
  576. .LNotFound:
  577. movl $-1,%ecx // Not found return -1
  578. .LFound:
  579. movl %ecx,%eax
  580. movl saveesi,%esi
  581. movl saveebx,%ebx
  582. end;
  583. {$endif FPC_SYSTEM_HAS_INDEXCHAR0}
  584. {****************************************************************************
  585. String
  586. ****************************************************************************}
  587. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  588. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  589. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  590. function fpc_shortstr_to_shortstr(len:longint; const sstr: shortstring): shortstring; [public,alias: 'FPC_SHORTSTR_TO_SHORTSTR']; compilerproc;
  591. begin
  592. asm
  593. cld
  594. movl __RESULT,%edi
  595. movl sstr,%esi
  596. xorl %eax,%eax
  597. movl len,%ecx
  598. lodsb
  599. cmpl %ecx,%eax
  600. jbe .LStrCopy1
  601. movl %ecx,%eax
  602. .LStrCopy1:
  603. stosb
  604. cmpl $7,%eax
  605. jl .LStrCopy2
  606. movl %edi,%ecx { Align on 32bits }
  607. negl %ecx
  608. andl $3,%ecx
  609. subl %ecx,%eax
  610. rep
  611. movsb
  612. movl %eax,%ecx
  613. andl $3,%eax
  614. shrl $2,%ecx
  615. rep
  616. movsl
  617. .LStrCopy2:
  618. movl %eax,%ecx
  619. rep
  620. movsb
  621. end ['ESI','EDI','EAX','ECX'];
  622. end;
  623. {$else FPC_STRTOSHORTSTRINGPROC}
  624. procedure fpc_shortstr_to_shortstr(out res:shortstring; const sstr: shortstring);assembler;[public,alias:'FPC_SHORTSTR_TO_SHORTSTR']; compilerproc;
  625. var
  626. saveesi,saveedi : longint;
  627. asm
  628. movl %edi,saveedi
  629. movl %esi,saveesi
  630. cld
  631. movl res,%edi
  632. movl sstr,%esi
  633. {$ifdef regcall}
  634. movl %edx,%ecx
  635. {$else regcall}
  636. movl res+4,%ecx
  637. {$endif regcall}
  638. xorl %eax,%eax
  639. lodsb
  640. cmpl %ecx,%eax
  641. jbe .LStrCopy1
  642. movl %ecx,%eax
  643. .LStrCopy1:
  644. stosb
  645. cmpl $7,%eax
  646. jl .LStrCopy2
  647. movl %edi,%ecx { Align on 32bits }
  648. negl %ecx
  649. andl $3,%ecx
  650. subl %ecx,%eax
  651. rep
  652. movsb
  653. movl %eax,%ecx
  654. andl $3,%eax
  655. shrl $2,%ecx
  656. rep
  657. movsl
  658. .LStrCopy2:
  659. movl %eax,%ecx
  660. rep
  661. movsb
  662. movl saveedi,%edi
  663. movl saveesi,%esi
  664. end;
  665. {$endif FPC_STRTOSHORTSTRINGPROC}
  666. procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN'];
  667. begin
  668. asm
  669. pushl %eax
  670. pushl %ecx
  671. cld
  672. movl dstr,%edi
  673. movl sstr,%esi
  674. xorl %eax,%eax
  675. movl len,%ecx
  676. lodsb
  677. cmpl %ecx,%eax
  678. jbe .LStrCopy1
  679. movl %ecx,%eax
  680. .LStrCopy1:
  681. stosb
  682. cmpl $7,%eax
  683. jl .LStrCopy2
  684. movl %edi,%ecx { Align on 32bits }
  685. negl %ecx
  686. andl $3,%ecx
  687. subl %ecx,%eax
  688. rep
  689. movsb
  690. movl %eax,%ecx
  691. andl $3,%eax
  692. shrl $2,%ecx
  693. rep
  694. movsl
  695. .LStrCopy2:
  696. movl %eax,%ecx
  697. rep
  698. movsb
  699. popl %ecx
  700. popl %eax
  701. end ['ESI','EDI'];
  702. end;
  703. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  704. {$ifndef STR_CONCAT_PROCS}
  705. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  706. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  707. function fpc_shortstr_concat(const s1,s2:shortstring):shortstring;compilerproc;
  708. begin
  709. asm
  710. movl __RESULT,%edi
  711. movl %edi,%ebx
  712. movl s1,%esi { first string }
  713. lodsb
  714. andl $0x0ff,%eax
  715. stosb
  716. cmpl $7,%eax
  717. jl .LStrConcat1
  718. movl %edi,%ecx { Align on 32bits }
  719. negl %ecx
  720. andl $3,%ecx
  721. subl %ecx,%eax
  722. rep
  723. movsb
  724. movl %eax,%ecx
  725. andl $3,%eax
  726. shrl $2,%ecx
  727. rep
  728. movsl
  729. .LStrConcat1:
  730. movl %eax,%ecx
  731. rep
  732. movsb
  733. movl s2,%esi { second string }
  734. movzbl (%ebx),%ecx
  735. negl %ecx
  736. addl $0x0ff,%ecx
  737. lodsb
  738. cmpl %ecx,%eax
  739. jbe .LStrConcat2
  740. movl %ecx,%eax
  741. .LStrConcat2:
  742. addb %al,(%ebx)
  743. cmpl $7,%eax
  744. jl .LStrConcat3
  745. movl %edi,%ecx { Align on 32bits }
  746. negl %ecx
  747. andl $3,%ecx
  748. subl %ecx,%eax
  749. rep
  750. movsb
  751. movl %eax,%ecx
  752. andl $3,%eax
  753. shrl $2,%ecx
  754. rep
  755. movsl
  756. .LStrConcat3:
  757. movl %eax,%ecx
  758. rep
  759. movsb
  760. end ['EBX','ECX','EAX','ESI','EDI'];
  761. end;
  762. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  763. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  764. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  765. procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring);compilerproc;
  766. [public,alias:'FPC_SHORTSTR_APPEND_SHORTSTR'];
  767. begin
  768. asm
  769. movl s1,%edi
  770. movl s2,%esi
  771. movl %edi,%ebx
  772. movzbl (%edi),%ecx
  773. movl __HIGH(s1),%eax
  774. lea 1(%edi,%ecx),%edi
  775. negl %ecx
  776. addl %eax,%ecx
  777. // no need to zero eax, high(s1) <= 255
  778. lodsb
  779. cmpl %ecx,%eax
  780. jbe .LStrConcat1
  781. movl %ecx,%eax
  782. .LStrConcat1:
  783. addb %al,(%ebx)
  784. cmpl $7,%eax
  785. jl .LStrConcat2
  786. movl %edi,%ecx { Align on 32bits }
  787. negl %ecx
  788. andl $3,%ecx
  789. subl %ecx,%eax
  790. rep
  791. movsb
  792. movl %eax,%ecx
  793. andl $3,%eax
  794. shrl $2,%ecx
  795. rep
  796. movsl
  797. .LStrConcat2:
  798. movl %eax,%ecx
  799. rep
  800. movsb
  801. end ['EBX','ECX','EAX','ESI','EDI'];
  802. end;
  803. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  804. {$endif STR_CONCAT_PROCS}
  805. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  806. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  807. function fpc_shortstr_compare(const left,right:shortstring): longint;assembler; [public,alias:'FPC_SHORTSTR_COMPARE']; compilerproc;
  808. var
  809. saveesi,saveedi,saveebx : longint;
  810. asm
  811. movl %edi,saveedi
  812. movl %esi,saveesi
  813. movl %ebx,saveebx
  814. cld
  815. movl right,%esi
  816. movl left,%edi
  817. movzbl (%esi),%eax
  818. movzbl (%edi),%ebx
  819. movl %eax,%edx
  820. incl %esi
  821. incl %edi
  822. cmpl %ebx,%eax
  823. jbe .LStrCmp1
  824. movl %ebx,%eax
  825. .LStrCmp1:
  826. cmpl $7,%eax
  827. jl .LStrCmp2
  828. movl %edi,%ecx { Align on 32bits }
  829. negl %ecx
  830. andl $3,%ecx
  831. subl %ecx,%eax
  832. orl %ecx,%ecx
  833. rep
  834. cmpsb
  835. jne .LStrCmp3
  836. movl %eax,%ecx
  837. andl $3,%eax
  838. shrl $2,%ecx
  839. orl %ecx,%ecx
  840. rep
  841. cmpsl
  842. je .LStrCmp2
  843. movl $4,%eax
  844. subl %eax,%esi
  845. subl %eax,%edi
  846. .LStrCmp2:
  847. movl %eax,%ecx
  848. orl %eax,%eax
  849. rep
  850. cmpsb
  851. je .LStrCmp4
  852. .LStrCmp3:
  853. movzbl -1(%esi),%edx // Compare failing (or equal) position
  854. movzbl -1(%edi),%ebx
  855. .LStrCmp4:
  856. movl %ebx,%eax // Compare length or position
  857. subl %edx,%eax
  858. movl saveedi,%edi
  859. movl saveesi,%esi
  860. movl saveebx,%ebx
  861. end;
  862. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  863. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  864. {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  865. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  866. function fpc_pchar_to_shortstr(p:pchar):shortstring;assembler;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; compilerproc;
  867. {$include strpas.inc}
  868. {$else FPC_STRTOSHORTSTRINGPROC}
  869. procedure fpc_pchar_to_shortstr(out res : shortstring;p:pchar);assembler;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; compilerproc;
  870. var
  871. saveres,saveebx,saveesi,saveedi : longint;
  872. asm
  873. movl %ebx,saveebx
  874. movl %esi,saveesi
  875. movl %edi,saveedi
  876. {$ifdef regcall}
  877. movl %ecx,%esi
  878. movl %eax,%edi
  879. movl %edi,saveres
  880. {$else}
  881. movl p,%esi
  882. {$endif}
  883. movl $1,%ecx
  884. testl %esi,%esi
  885. movl %esi,%eax
  886. jz .LStrPasDone
  887. {$ifndef REGCALL}
  888. movl res,%edi
  889. {$endif}
  890. leal 3(%esi),%edx
  891. andl $-4,%edx
  892. // skip length byte
  893. incl %edi
  894. subl %esi,%edx
  895. jz .LStrPasAligned
  896. // align source to multiple of 4 (not dest, because we can't read past
  897. // the end of the source, since that may be past the end of the heap
  898. // -> sigsegv!!)
  899. .LStrPasAlignLoop:
  900. movb (%esi),%al
  901. incl %esi
  902. testb %al,%al
  903. jz .LStrPasDone
  904. incl %edi
  905. incb %cl
  906. decb %dl
  907. movb %al,-1(%edi)
  908. jne .LStrPasAlignLoop
  909. .balign 16
  910. .LStrPasAligned:
  911. movl (%esi),%ebx
  912. addl $4,%edi
  913. leal 0x0fefefeff(%ebx),%eax
  914. movl %ebx,%edx
  915. addl $4,%esi
  916. notl %edx
  917. andl %edx,%eax
  918. addl $4,%ecx
  919. andl $0x080808080,%eax
  920. movl %ebx,-4(%edi)
  921. jnz .LStrPasEndFound
  922. cmpl $252,%ecx
  923. ja .LStrPasPreEndLoop
  924. jmp .LStrPasAligned
  925. .LStrPasEndFound:
  926. subl $4,%ecx
  927. // this won't overwrite data since the result = 255 char string
  928. // and we never process more than the first 255 chars of p
  929. shrl $8,%eax
  930. jc .LStrPasDone
  931. incl %ecx
  932. shrl $8,%eax
  933. jc .LStrPasDone
  934. incl %ecx
  935. shrl $8,%eax
  936. jc .LStrPasDone
  937. incl %ecx
  938. jmp .LStrPasDone
  939. .LStrPasPreEndLoop:
  940. testb %cl,%cl
  941. jz .LStrPasDone
  942. movl (%esi),%eax
  943. .LStrPasEndLoop:
  944. testb %al,%al
  945. jz .LStrPasDone
  946. movb %al,(%edi)
  947. shrl $8,%eax
  948. incl %edi
  949. incb %cl
  950. jnz .LStrPasEndLoop
  951. .LStrPasDone:
  952. {$ifdef REGCALL}
  953. movl saveres,%edi
  954. {$else}
  955. movl res,%edi
  956. {$endif}
  957. addb $255,%cl
  958. movb %cl,(%edi)
  959. movl saveesi,%esi
  960. movl saveedi,%edi
  961. movl saveebx,%ebx
  962. end;
  963. {$endif FPC_STRTOSHORTSTRINGPROC}
  964. {$endif FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  965. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  966. {$define FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  967. function fpc_pchar_length(p:pchar):longint;assembler;[public,alias:'FPC_PCHAR_LENGTH']; compilerproc;
  968. var
  969. saveedi : longint;
  970. asm
  971. movl %edi,saveedi
  972. {$ifdef REGCALL}
  973. movl %eax,%edi
  974. {$else}
  975. movl p,%edi
  976. {$endif}
  977. movl $0xffffffff,%ecx
  978. xorl %eax,%eax
  979. test %edi,%edi
  980. jz .LStrLenDone
  981. cld
  982. repne
  983. scasb
  984. movl $0xfffffffe,%eax
  985. subl %ecx,%eax
  986. movl saveedi,%edi
  987. .LStrLenDone:
  988. end;
  989. {$endif FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  990. {$IFNDEF INTERNAL_BACKTRACE}
  991. {$define FPC_SYSTEM_HAS_GET_FRAME}
  992. function get_frame:pointer;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  993. asm
  994. movl %ebp,%eax
  995. end;
  996. {$ENDIF not INTERNAL_BACKTRACE}
  997. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  998. function get_caller_addr(framebp:pointer):pointer;nostackframe;assembler;
  999. asm
  1000. {$ifndef REGCALL}
  1001. movl framebp,%eax
  1002. {$endif}
  1003. orl %eax,%eax
  1004. jz .Lg_a_null
  1005. movl 4(%eax),%eax
  1006. .Lg_a_null:
  1007. end;
  1008. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  1009. function get_caller_frame(framebp:pointer):pointer;nostackframe;assembler;
  1010. asm
  1011. {$ifndef REGCALL}
  1012. movl framebp,%eax
  1013. {$endif}
  1014. orl %eax,%eax
  1015. jz .Lgnf_null
  1016. movl (%eax),%eax
  1017. .Lgnf_null:
  1018. end;
  1019. {$define FPC_SYSTEM_HAS_SPTR}
  1020. Function Sptr : Pointer;assembler;nostackframe;
  1021. asm
  1022. movl %esp,%eax
  1023. end;
  1024. {****************************************************************************
  1025. Str()
  1026. ****************************************************************************}
  1027. {$if defined(disabled) and defined(regcall) }
  1028. {$define FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  1029. {$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
  1030. label str_int_shortcut;
  1031. procedure int_str(l:longword;out s:string);assembler;nostackframe;
  1032. asm
  1033. pushl %esi
  1034. pushl %edi
  1035. pushl %ebx
  1036. mov %edx,%edi
  1037. xor %edx,%edx
  1038. jmp str_int_shortcut
  1039. end;
  1040. procedure int_str(l:longint;out s:string);assembler;nostackframe;
  1041. {Optimized for speed, but balanced with size.}
  1042. const digits:array[0..9] of cardinal=(0,10,100,1000,10000,
  1043. 100000,1000000,10000000,
  1044. 100000000,1000000000);
  1045. asm
  1046. push %esi
  1047. push %edi
  1048. push %ebx
  1049. movl %edx,%edi
  1050. { Calculate absolute value and put sign in edx}
  1051. cltd
  1052. xorl %edx,%eax
  1053. subl %edx,%eax
  1054. negl %edx
  1055. str_int_shortcut:
  1056. movl %ecx,%esi
  1057. {Calculate amount of digits in ecx.}
  1058. xorl %ecx,%ecx
  1059. bsrl %eax,%ecx
  1060. incl %ecx
  1061. imul $1233,%ecx
  1062. shr $12,%ecx
  1063. {$ifdef FPC_PIC}
  1064. call fpc_geteipasebx
  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. .balign 4
  1088. .Lloop_skip:
  1089. movl $0xcccccccd,%eax {Divide by 10 using mul+shr}
  1090. mull %edx
  1091. shrl $3,%edx
  1092. decl %ecx
  1093. jz .Ldone {If (l<0) and (high(s)=1) this jump is taken.}
  1094. incl %esi
  1095. jnz .Lloop_skip
  1096. {Write out digits.}
  1097. .balign 4
  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}
  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 Comperand,%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;
  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. fninit
  1270. fldcw localfpucw
  1271. fwait
  1272. end;
  1273. if has_sse_support then
  1274. begin
  1275. localmxcsr:=mxcsr;
  1276. asm
  1277. { setup sse exceptions }
  1278. ldmxcsr localmxcsr
  1279. end;
  1280. end;
  1281. softfloat_exception_mask:=float_flag_underflow or float_flag_inexact or float_flag_denormal;
  1282. end;
  1283. {$define FPC_SYSTEM_HAS_SYSRESETFPU}
  1284. Procedure SysResetFPU;
  1285. var
  1286. { these locals are so we don't have to hack pic code in the assembler }
  1287. localmxcsr: dword;
  1288. localfpucw: word;
  1289. begin
  1290. localfpucw:=Default8087CW;
  1291. asm
  1292. fninit
  1293. fwait
  1294. fldcw localfpucw
  1295. end;
  1296. if has_sse_support then
  1297. begin
  1298. localmxcsr:=mxcsr;
  1299. asm
  1300. { setup sse exceptions }
  1301. ldmxcsr localmxcsr
  1302. end;
  1303. end;
  1304. softfloat_exception_flags:=0;
  1305. end;
  1306. { because of the brain dead sse detection on x86, this test is post poned }
  1307. procedure fpc_cpucodeinit;
  1308. begin
  1309. os_supports_sse:=true;
  1310. os_supports_sse:=sse_support;
  1311. if os_supports_sse then
  1312. begin
  1313. sse_check:=true;
  1314. asm
  1315. { force an sse exception if no sse is supported, the exception handler sets
  1316. os_supports_sse to false then }
  1317. { don't change this instruction, the code above depends on its size }
  1318. movaps %xmm7, %xmm6
  1319. end;
  1320. sse_check:=false;
  1321. end;
  1322. has_sse_support:=os_supports_sse;
  1323. has_mmx_support:=mmx_support;
  1324. SysResetFPU;
  1325. if not(IsLibrary) then
  1326. SysInitFPU;
  1327. {$ifdef USE_FASTMOVE}
  1328. setup_fastmove;
  1329. {$endif}
  1330. end;
  1331. {$if not defined(darwin) and defined(regcall) }
  1332. { darwin requires that the stack is aligned to 16 bytes when calling another function }
  1333. {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
  1334. {$define FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
  1335. function fpc_freemem_x(p:pointer):ptrint; [external name 'FPC_FREEMEM_X'];
  1336. Procedure fpc_AnsiStr_Decr_Ref (Var S : Pointer); [Public,Alias:'FPC_ANSISTR_DECR_REF']; compilerproc; nostackframe; assembler;
  1337. asm
  1338. cmpl $0,(%eax)
  1339. jne .Ldecr_ref_continue
  1340. ret
  1341. .Ldecr_ref_continue:
  1342. // Temps allocated between ebp-24 and ebp+0
  1343. subl $4,%esp
  1344. // Var S located in register
  1345. // Var l located in register
  1346. movl %eax,(%esp)
  1347. // [101] l:=@PAnsiRec(S-FirstOff)^.Ref;
  1348. movl (%eax),%edx
  1349. subl $8,%edx
  1350. // [102] If l^<0 then exit;
  1351. cmpl $0,(%edx)
  1352. jl .Lj3596
  1353. .Lj3603:
  1354. // [104] If declocked(l^) then
  1355. {$ifdef FPC_PIC}
  1356. pushl %ebx
  1357. call fpc_geteipasebx
  1358. addl $_GLOBAL_OFFSET_TABLE_,%ebx
  1359. movl ismultithread@GOT(%ebx),%ebx
  1360. movl (%ebx),%ebx
  1361. cmp $0, %ebx
  1362. popl %ebx
  1363. {$else FPC_PIC}
  1364. cmpl $0,ismultithread
  1365. {$endif FPC_PIC}
  1366. jne .Lj3610
  1367. decl (%edx)
  1368. je .Lj3620
  1369. addl $4,%esp
  1370. ret
  1371. .Lj3610:
  1372. movl %edx,%eax
  1373. call cpudeclocked
  1374. testb %al,%al
  1375. je .Lj3605
  1376. .Lj3620:
  1377. movl (%esp),%eax
  1378. movl (%eax),%eax
  1379. subl $8,%eax
  1380. call FPC_FREEMEM_X
  1381. movl (%esp),%eax
  1382. movl $0,(%eax)
  1383. .Lj3618:
  1384. .Lj3605:
  1385. .Lj3596:
  1386. // [107] end;
  1387. addl $4,%esp
  1388. end;
  1389. function fpc_truely_ansistr_unique(Var S : Pointer): Pointer; forward;
  1390. {$define FPC_SYSTEM_HAS_ANSISTR_UNIQUE}
  1391. Function fpc_ansistr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_ANSISTR_UNIQUE']; compilerproc; nostackframe;assembler;
  1392. asm
  1393. // Var S located in register
  1394. // Var $result located in register
  1395. movl %eax,%edx
  1396. // [437] pointer(result) := pointer(s);
  1397. movl (%eax),%eax
  1398. // [438] If Pointer(S)=Nil then
  1399. testl %eax,%eax
  1400. je .Lj4031
  1401. .Lj4036:
  1402. // [440] if PAnsiRec(Pointer(S)-Firstoff)^.Ref<>1 then
  1403. movl -8(%eax),%ecx
  1404. cmpl $1,%ecx
  1405. je .Lj4038
  1406. // [441] result:=fpc_truely_ansistr_unique(s);
  1407. movl %edx,%eax
  1408. call fpc_truely_ansistr_unique
  1409. .Lj4038:
  1410. .Lj4031:
  1411. // [442] end;
  1412. end;
  1413. {$endif FPC_HAS_FEATURE_ANSISTRINGS}
  1414. {$endif ndef darwin and defined(regcall) }
  1415. {$ifndef FPC_SYSTEM_HAS_MEM_BARRIER}
  1416. {$define FPC_SYSTEM_HAS_MEM_BARRIER}
  1417. procedure ReadBarrier;assembler;nostackframe;
  1418. asm
  1419. lock
  1420. addl $0,0(%esp)
  1421. { alternative: lfence on SSE capable CPUs }
  1422. end;
  1423. procedure ReadDependencyBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  1424. begin
  1425. { reads imply barrier on earlier reads depended on }
  1426. end;
  1427. procedure ReadWriteBarrier;assembler;nostackframe;
  1428. asm
  1429. lock
  1430. addl $0,0(%esp)
  1431. { alternative: mfence on SSE capable CPUs }
  1432. end;
  1433. procedure WriteBarrier;assembler;nostackframe;
  1434. asm
  1435. { no write reordering on intel CPUs (yet) }
  1436. end;
  1437. {$endif}