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