2
0

i386.inc 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678
  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. {$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. {$ifdef FPC_PROFILE}
  594. push %eax
  595. push %edx
  596. push %ecx
  597. call mcount
  598. pop %ecx
  599. pop %edx
  600. pop %eax
  601. {$endif FPC_PROFILE}
  602. cld
  603. movl __RESULT,%edi
  604. movl sstr,%esi
  605. xorl %eax,%eax
  606. movl len,%ecx
  607. lodsb
  608. cmpl %ecx,%eax
  609. jbe .LStrCopy1
  610. movl %ecx,%eax
  611. .LStrCopy1:
  612. stosb
  613. cmpl $7,%eax
  614. jl .LStrCopy2
  615. movl %edi,%ecx { Align on 32bits }
  616. negl %ecx
  617. andl $3,%ecx
  618. subl %ecx,%eax
  619. rep
  620. movsb
  621. movl %eax,%ecx
  622. andl $3,%eax
  623. shrl $2,%ecx
  624. rep
  625. movsl
  626. .LStrCopy2:
  627. movl %eax,%ecx
  628. rep
  629. movsb
  630. end ['ESI','EDI','EAX','ECX'];
  631. end;
  632. {$else FPC_STRTOSHORTSTRINGPROC}
  633. procedure fpc_shortstr_to_shortstr(out res:shortstring; const sstr: shortstring);assembler;[public,alias:'FPC_SHORTSTR_TO_SHORTSTR']; compilerproc;
  634. var
  635. saveesi,saveedi : longint;
  636. asm
  637. {$ifdef FPC_PROFILE}
  638. push %eax
  639. push %edx
  640. push %ecx
  641. call mcount
  642. pop %ecx
  643. pop %edx
  644. pop %eax
  645. {$endif FPC_PROFILE}
  646. movl %edi,saveedi
  647. movl %esi,saveesi
  648. cld
  649. movl res,%edi
  650. movl sstr,%esi
  651. {$ifdef regcall}
  652. movl %edx,%ecx
  653. {$else regcall}
  654. movl res+4,%ecx
  655. {$endif regcall}
  656. xorl %eax,%eax
  657. lodsb
  658. cmpl %ecx,%eax
  659. jbe .LStrCopy1
  660. movl %ecx,%eax
  661. .LStrCopy1:
  662. stosb
  663. cmpl $7,%eax
  664. jl .LStrCopy2
  665. movl %edi,%ecx { Align on 32bits }
  666. negl %ecx
  667. andl $3,%ecx
  668. subl %ecx,%eax
  669. rep
  670. movsb
  671. movl %eax,%ecx
  672. andl $3,%eax
  673. shrl $2,%ecx
  674. rep
  675. movsl
  676. .LStrCopy2:
  677. movl %eax,%ecx
  678. rep
  679. movsb
  680. movl saveedi,%edi
  681. movl saveesi,%esi
  682. end;
  683. {$endif FPC_STRTOSHORTSTRINGPROC}
  684. procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN'];
  685. begin
  686. asm
  687. {$ifdef FPC_PROFILE}
  688. push %eax
  689. push %edx
  690. push %ecx
  691. call mcount
  692. pop %ecx
  693. pop %edx
  694. pop %eax
  695. {$endif FPC_PROFILE}
  696. pushl %eax
  697. pushl %ecx
  698. cld
  699. movl dstr,%edi
  700. movl sstr,%esi
  701. xorl %eax,%eax
  702. movl len,%ecx
  703. lodsb
  704. cmpl %ecx,%eax
  705. jbe .LStrCopy1
  706. movl %ecx,%eax
  707. .LStrCopy1:
  708. stosb
  709. cmpl $7,%eax
  710. jl .LStrCopy2
  711. movl %edi,%ecx { Align on 32bits }
  712. negl %ecx
  713. andl $3,%ecx
  714. subl %ecx,%eax
  715. rep
  716. movsb
  717. movl %eax,%ecx
  718. andl $3,%eax
  719. shrl $2,%ecx
  720. rep
  721. movsl
  722. .LStrCopy2:
  723. movl %eax,%ecx
  724. rep
  725. movsb
  726. popl %ecx
  727. popl %eax
  728. end ['ESI','EDI'];
  729. end;
  730. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  731. {$ifndef STR_CONCAT_PROCS}
  732. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  733. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  734. function fpc_shortstr_concat(const s1,s2:shortstring):shortstring;compilerproc;
  735. begin
  736. asm
  737. {$ifdef FPC_PROFILE}
  738. push %eax
  739. push %edx
  740. push %ecx
  741. call mcount
  742. pop %ecx
  743. pop %edx
  744. pop %eax
  745. {$endif FPC_PROFILE}
  746. movl __RESULT,%edi
  747. movl %edi,%ebx
  748. movl s1,%esi { first string }
  749. lodsb
  750. andl $0x0ff,%eax
  751. stosb
  752. cmpl $7,%eax
  753. jl .LStrConcat1
  754. movl %edi,%ecx { Align on 32bits }
  755. negl %ecx
  756. andl $3,%ecx
  757. subl %ecx,%eax
  758. rep
  759. movsb
  760. movl %eax,%ecx
  761. andl $3,%eax
  762. shrl $2,%ecx
  763. rep
  764. movsl
  765. .LStrConcat1:
  766. movl %eax,%ecx
  767. rep
  768. movsb
  769. movl s2,%esi { second string }
  770. movzbl (%ebx),%ecx
  771. negl %ecx
  772. addl $0x0ff,%ecx
  773. lodsb
  774. cmpl %ecx,%eax
  775. jbe .LStrConcat2
  776. movl %ecx,%eax
  777. .LStrConcat2:
  778. addb %al,(%ebx)
  779. cmpl $7,%eax
  780. jl .LStrConcat3
  781. movl %edi,%ecx { Align on 32bits }
  782. negl %ecx
  783. andl $3,%ecx
  784. subl %ecx,%eax
  785. rep
  786. movsb
  787. movl %eax,%ecx
  788. andl $3,%eax
  789. shrl $2,%ecx
  790. rep
  791. movsl
  792. .LStrConcat3:
  793. movl %eax,%ecx
  794. rep
  795. movsb
  796. end ['EBX','ECX','EAX','ESI','EDI'];
  797. end;
  798. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  799. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  800. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  801. procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring);compilerproc;
  802. [public,alias:'FPC_SHORTSTR_APPEND_SHORTSTR'];
  803. begin
  804. asm
  805. {$ifdef FPC_PROFILE}
  806. push %eax
  807. push %edx
  808. push %ecx
  809. call mcount
  810. pop %ecx
  811. pop %edx
  812. pop %eax
  813. {$endif FPC_PROFILE}
  814. movl s1,%edi
  815. movl s2,%esi
  816. movl %edi,%ebx
  817. movzbl (%edi),%ecx
  818. movl __HIGH(s1),%eax
  819. lea 1(%edi,%ecx),%edi
  820. negl %ecx
  821. addl %eax,%ecx
  822. // no need to zero eax, high(s1) <= 255
  823. lodsb
  824. cmpl %ecx,%eax
  825. jbe .LStrConcat1
  826. movl %ecx,%eax
  827. .LStrConcat1:
  828. addb %al,(%ebx)
  829. cmpl $7,%eax
  830. jl .LStrConcat2
  831. movl %edi,%ecx { Align on 32bits }
  832. negl %ecx
  833. andl $3,%ecx
  834. subl %ecx,%eax
  835. rep
  836. movsb
  837. movl %eax,%ecx
  838. andl $3,%eax
  839. shrl $2,%ecx
  840. rep
  841. movsl
  842. .LStrConcat2:
  843. movl %eax,%ecx
  844. rep
  845. movsb
  846. end ['EBX','ECX','EAX','ESI','EDI'];
  847. end;
  848. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  849. {$endif STR_CONCAT_PROCS}
  850. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  851. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  852. function fpc_shortstr_compare(const left,right:shortstring): longint;assembler; [public,alias:'FPC_SHORTSTR_COMPARE']; compilerproc;
  853. var
  854. saveesi,saveedi,saveebx : longint;
  855. asm
  856. {$ifdef FPC_PROFILE}
  857. push %eax
  858. push %edx
  859. push %ecx
  860. call mcount
  861. pop %ecx
  862. pop %edx
  863. pop %eax
  864. {$endif FPC_PROFILE}
  865. movl %edi,saveedi
  866. movl %esi,saveesi
  867. movl %ebx,saveebx
  868. cld
  869. movl right,%esi
  870. movl left,%edi
  871. movzbl (%esi),%eax
  872. movzbl (%edi),%ebx
  873. movl %eax,%edx
  874. incl %esi
  875. incl %edi
  876. cmpl %ebx,%eax
  877. jbe .LStrCmp1
  878. movl %ebx,%eax
  879. .LStrCmp1:
  880. cmpl $7,%eax
  881. jl .LStrCmp2
  882. movl %edi,%ecx { Align on 32bits }
  883. negl %ecx
  884. andl $3,%ecx
  885. subl %ecx,%eax
  886. orl %ecx,%ecx
  887. rep
  888. cmpsb
  889. jne .LStrCmp3
  890. movl %eax,%ecx
  891. andl $3,%eax
  892. shrl $2,%ecx
  893. orl %ecx,%ecx
  894. rep
  895. cmpsl
  896. je .LStrCmp2
  897. movl $4,%eax
  898. subl %eax,%esi
  899. subl %eax,%edi
  900. .LStrCmp2:
  901. movl %eax,%ecx
  902. orl %eax,%eax
  903. rep
  904. cmpsb
  905. je .LStrCmp4
  906. .LStrCmp3:
  907. movzbl -1(%esi),%edx // Compare failing (or equal) position
  908. movzbl -1(%edi),%ebx
  909. .LStrCmp4:
  910. movl %ebx,%eax // Compare length or position
  911. subl %edx,%eax
  912. movl saveedi,%edi
  913. movl saveesi,%esi
  914. movl saveebx,%ebx
  915. end;
  916. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  917. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  918. {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  919. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  920. function fpc_pchar_to_shortstr(p:pchar):shortstring;assembler;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; compilerproc;
  921. {$include strpas.inc}
  922. {$else FPC_STRTOSHORTSTRINGPROC}
  923. procedure fpc_pchar_to_shortstr(out res : shortstring;p:pchar);assembler;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; compilerproc;
  924. var
  925. saveres,saveebx,saveesi,saveedi : longint;
  926. asm
  927. {$ifdef FPC_PROFILE}
  928. push %eax
  929. push %edx
  930. push %ecx
  931. call mcount
  932. pop %ecx
  933. pop %edx
  934. pop %eax
  935. {$endif FPC_PROFILE}
  936. movl %ebx,saveebx
  937. movl %esi,saveesi
  938. movl %edi,saveedi
  939. {$ifdef regcall}
  940. movl %ecx,%esi
  941. movl %eax,%edi
  942. movl %edi,saveres
  943. {$else}
  944. movl p,%esi
  945. {$endif}
  946. movl $1,%ecx
  947. testl %esi,%esi
  948. movl %esi,%eax
  949. jz .LStrPasDone
  950. {$ifndef REGCALL}
  951. movl res,%edi
  952. {$endif}
  953. leal 3(%esi),%edx
  954. andl $-4,%edx
  955. // skip length byte
  956. incl %edi
  957. subl %esi,%edx
  958. jz .LStrPasAligned
  959. // align source to multiple of 4 (not dest, because we can't read past
  960. // the end of the source, since that may be past the end of the heap
  961. // -> sigsegv!!)
  962. .LStrPasAlignLoop:
  963. movb (%esi),%al
  964. incl %esi
  965. testb %al,%al
  966. jz .LStrPasDone
  967. incl %edi
  968. incb %cl
  969. decb %dl
  970. movb %al,-1(%edi)
  971. jne .LStrPasAlignLoop
  972. .balign 16
  973. .LStrPasAligned:
  974. movl (%esi),%ebx
  975. addl $4,%edi
  976. leal 0x0fefefeff(%ebx),%eax
  977. movl %ebx,%edx
  978. addl $4,%esi
  979. notl %edx
  980. andl %edx,%eax
  981. addl $4,%ecx
  982. andl $0x080808080,%eax
  983. movl %ebx,-4(%edi)
  984. jnz .LStrPasEndFound
  985. cmpl $252,%ecx
  986. ja .LStrPasPreEndLoop
  987. jmp .LStrPasAligned
  988. .LStrPasEndFound:
  989. subl $4,%ecx
  990. // this won't overwrite data since the result = 255 char string
  991. // and we never process more than the first 255 chars of p
  992. shrl $8,%eax
  993. jc .LStrPasDone
  994. incl %ecx
  995. shrl $8,%eax
  996. jc .LStrPasDone
  997. incl %ecx
  998. shrl $8,%eax
  999. jc .LStrPasDone
  1000. incl %ecx
  1001. jmp .LStrPasDone
  1002. .LStrPasPreEndLoop:
  1003. testb %cl,%cl
  1004. jz .LStrPasDone
  1005. movl (%esi),%eax
  1006. .LStrPasEndLoop:
  1007. testb %al,%al
  1008. jz .LStrPasDone
  1009. movb %al,(%edi)
  1010. shrl $8,%eax
  1011. incl %edi
  1012. incb %cl
  1013. jnz .LStrPasEndLoop
  1014. .LStrPasDone:
  1015. {$ifdef REGCALL}
  1016. movl saveres,%edi
  1017. {$else}
  1018. movl res,%edi
  1019. {$endif}
  1020. addb $255,%cl
  1021. movb %cl,(%edi)
  1022. movl saveesi,%esi
  1023. movl saveedi,%edi
  1024. movl saveebx,%ebx
  1025. end;
  1026. {$endif FPC_STRTOSHORTSTRINGPROC}
  1027. {$endif FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  1028. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  1029. {$define FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  1030. function fpc_pchar_length(p:pchar):longint;assembler;[public,alias:'FPC_PCHAR_LENGTH']; compilerproc;
  1031. var
  1032. saveedi : longint;
  1033. asm
  1034. {$ifdef FPC_PROFILE}
  1035. push %eax
  1036. push %edx
  1037. push %ecx
  1038. call mcount
  1039. pop %ecx
  1040. pop %edx
  1041. pop %eax
  1042. {$endif FPC_PROFILE}
  1043. movl %edi,saveedi
  1044. {$ifdef REGCALL}
  1045. movl %eax,%edi
  1046. {$else}
  1047. movl p,%edi
  1048. {$endif}
  1049. movl $0xffffffff,%ecx
  1050. xorl %eax,%eax
  1051. test %edi,%edi
  1052. jz .LStrLenDone
  1053. cld
  1054. repne
  1055. scasb
  1056. movl $0xfffffffe,%eax
  1057. subl %ecx,%eax
  1058. movl saveedi,%edi
  1059. .LStrLenDone:
  1060. end;
  1061. {$endif FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  1062. {$IFNDEF INTERNAL_BACKTRACE}
  1063. {$define FPC_SYSTEM_HAS_GET_FRAME}
  1064. function get_frame:pointer;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  1065. asm
  1066. movl %ebp,%eax
  1067. end;
  1068. {$ENDIF not INTERNAL_BACKTRACE}
  1069. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  1070. function get_caller_addr(framebp:pointer):pointer;nostackframe;assembler;
  1071. asm
  1072. {$ifndef REGCALL}
  1073. movl framebp,%eax
  1074. {$endif}
  1075. orl %eax,%eax
  1076. jz .Lg_a_null
  1077. movl 4(%eax),%eax
  1078. .Lg_a_null:
  1079. end;
  1080. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  1081. function get_caller_frame(framebp:pointer):pointer;nostackframe;assembler;
  1082. asm
  1083. {$ifndef REGCALL}
  1084. movl framebp,%eax
  1085. {$endif}
  1086. orl %eax,%eax
  1087. jz .Lgnf_null
  1088. movl (%eax),%eax
  1089. .Lgnf_null:
  1090. end;
  1091. {$define FPC_SYSTEM_HAS_SPTR}
  1092. Function Sptr : Pointer;assembler;nostackframe;
  1093. asm
  1094. movl %esp,%eax
  1095. end;
  1096. {****************************************************************************
  1097. Str()
  1098. ****************************************************************************}
  1099. {$if defined(disabled) and defined(regcall) }
  1100. {$define FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  1101. {$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
  1102. label str_int_shortcut;
  1103. procedure int_str(l:longword;out s:string);assembler;nostackframe;
  1104. asm
  1105. pushl %esi
  1106. pushl %edi
  1107. pushl %ebx
  1108. mov %edx,%edi
  1109. xor %edx,%edx
  1110. jmp str_int_shortcut
  1111. end;
  1112. procedure int_str(l:longint;out s:string);assembler;nostackframe;
  1113. {Optimized for speed, but balanced with size.}
  1114. const digits:array[0..9] of cardinal=(0,10,100,1000,10000,
  1115. 100000,1000000,10000000,
  1116. 100000000,1000000000);
  1117. asm
  1118. {$ifdef FPC_PROFILE}
  1119. push %eax
  1120. push %edx
  1121. push %ecx
  1122. call mcount
  1123. pop %ecx
  1124. pop %edx
  1125. pop %eax
  1126. {$endif FPC_PROFILE}
  1127. push %esi
  1128. push %edi
  1129. push %ebx
  1130. movl %edx,%edi
  1131. { Calculate absolute value and put sign in edx}
  1132. cltd
  1133. xorl %edx,%eax
  1134. subl %edx,%eax
  1135. negl %edx
  1136. str_int_shortcut:
  1137. movl %ecx,%esi
  1138. {Calculate amount of digits in ecx.}
  1139. xorl %ecx,%ecx
  1140. bsrl %eax,%ecx
  1141. incl %ecx
  1142. imul $1233,%ecx
  1143. shr $12,%ecx
  1144. {$ifdef FPC_PIC}
  1145. call fpc_geteipasebx
  1146. {$ifdef darwin}
  1147. movl digits-.Lpic(%ebx),%ebx
  1148. {$else}
  1149. addl $_GLOBAL_OFFSET_TABLE_,%ebx
  1150. movl digits@GOT(%ebx),%ebx
  1151. {$endif}
  1152. cmpl (%ebx,%ecx,4),%eax
  1153. {$else}
  1154. cmpl digits(,%ecx,4),%eax
  1155. {$endif}
  1156. cmc
  1157. adcl $0,%ecx {Nr. digits ready in ecx.}
  1158. {Write length & sign.}
  1159. lea (%edx,%ecx),%ebx
  1160. movb $45,%bh {movb $'-,%bh Not supported by our ATT reader.}
  1161. movw %bx,(%edi)
  1162. addl %edx,%edi
  1163. subl %edx,%esi
  1164. {Skip digits beyond string length.}
  1165. movl %eax,%edx
  1166. subl %ecx,%esi
  1167. jae .Lloop_write
  1168. .balign 4
  1169. .Lloop_skip:
  1170. movl $0xcccccccd,%eax {Divide by 10 using mul+shr}
  1171. mull %edx
  1172. shrl $3,%edx
  1173. decl %ecx
  1174. jz .Ldone {If (l<0) and (high(s)=1) this jump is taken.}
  1175. incl %esi
  1176. jnz .Lloop_skip
  1177. {Write out digits.}
  1178. .balign 4
  1179. .Lloop_write:
  1180. movl $0xcccccccd,%eax {Divide by 10 using mul+shr}
  1181. {Pre-add '0'}
  1182. leal 48(%edx),%ebx {leal $'0(,%edx),%ebx Not supported by our ATT reader.}
  1183. mull %edx
  1184. shrl $3,%edx
  1185. leal (%edx,%edx,8),%eax {x mod 10 = x-10*(x div 10)}
  1186. subl %edx,%ebx
  1187. subl %eax,%ebx
  1188. movb %bl,(%edi,%ecx)
  1189. decl %ecx
  1190. jnz .Lloop_write
  1191. .Ldone:
  1192. popl %ebx
  1193. popl %edi
  1194. popl %esi
  1195. end;
  1196. {$endif}
  1197. {****************************************************************************
  1198. Bounds Check
  1199. ****************************************************************************}
  1200. { do a thread-safe inc/dec }
  1201. {$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  1202. function cpudeclocked(var l : longint) : boolean;assembler;nostackframe;
  1203. asm
  1204. {$ifndef REGCALL}
  1205. movl l,%eax
  1206. {$endif}
  1207. { this check should be done because a lock takes a lot }
  1208. { of time! }
  1209. lock
  1210. decl (%eax)
  1211. setzb %al
  1212. end;
  1213. {$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  1214. procedure cpuinclocked(var l : longint);assembler;nostackframe;
  1215. asm
  1216. {$ifndef REGCALL}
  1217. movl l,%eax
  1218. {$endif}
  1219. lock
  1220. incl (%eax)
  1221. end;
  1222. // inline SMP check and normal lock.
  1223. // the locked one is so slow, inlining doesn't matter.
  1224. function declocked(var l : longint) : boolean; inline;
  1225. begin
  1226. if not ismultithread then
  1227. begin
  1228. dec(l);
  1229. declocked:=l=0;
  1230. end
  1231. else
  1232. declocked:=cpudeclocked(l);
  1233. end;
  1234. procedure inclocked(var l : longint); inline;
  1235. begin
  1236. if not ismultithread then
  1237. inc(l)
  1238. else
  1239. cpuinclocked(l);
  1240. end;
  1241. function InterLockedDecrement (var Target: longint) : longint; assembler;
  1242. asm
  1243. {$ifdef REGCALL}
  1244. movl $-1,%edx
  1245. xchgl %edx,%eax
  1246. {$else}
  1247. movl Target, %edx
  1248. movl $-1, %eax
  1249. {$endif}
  1250. lock
  1251. xaddl %eax, (%edx)
  1252. decl %eax
  1253. end;
  1254. function InterLockedIncrement (var Target: longint) : longint; assembler;
  1255. asm
  1256. {$ifdef REGCALL}
  1257. movl $1,%edx
  1258. xchgl %edx,%eax
  1259. {$else}
  1260. movl Target, %edx
  1261. movl $1, %eax
  1262. {$endif}
  1263. lock
  1264. xaddl %eax, (%edx)
  1265. incl %eax
  1266. end;
  1267. function InterLockedExchange (var Target: longint;Source : longint) : longint; assembler;
  1268. asm
  1269. {$ifdef REGCALL}
  1270. xchgl (%eax),%edx
  1271. movl %edx,%eax
  1272. {$else}
  1273. movl Target,%ecx
  1274. movl Source,%eax
  1275. xchgl (%ecx),%eax
  1276. {$endif}
  1277. end;
  1278. function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint; assembler;
  1279. asm
  1280. {$ifdef REGCALL}
  1281. xchgl %eax,%edx
  1282. {$else}
  1283. movl Target,%edx
  1284. movl Source,%eax
  1285. {$endif}
  1286. lock
  1287. xaddl %eax, (%edx)
  1288. end;
  1289. function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint; assembler;
  1290. asm
  1291. {$ifdef REGCALL}
  1292. xchgl %eax,%ecx
  1293. {$else}
  1294. movl Target,%ecx
  1295. movl NewValue,%edx
  1296. movl Comperand,%eax
  1297. {$endif}
  1298. lock
  1299. cmpxchgl %edx, (%ecx)
  1300. end;
  1301. function InterlockedCompareExchange64(var Target: int64; NewValue: int64; Comperand: int64): int64; assembler;
  1302. asm
  1303. pushl %ebx
  1304. pushl %edi
  1305. {$ifdef REGCALL}
  1306. movl %eax,%edi
  1307. {$else}
  1308. movl Target,%edi
  1309. {$endif}
  1310. movl Comperand+4,%edx
  1311. movl Comperand+0,%eax
  1312. movl NewValue+4,%ecx
  1313. movl NewValue+0,%ebx
  1314. lock cmpxchg8b (%edi)
  1315. pop %edi
  1316. pop %ebx
  1317. end;
  1318. {****************************************************************************
  1319. FPU
  1320. ****************************************************************************}
  1321. const
  1322. { Internal constants for use in system unit }
  1323. FPU_Invalid = 1;
  1324. FPU_Denormal = 2;
  1325. FPU_DivisionByZero = 4;
  1326. FPU_Overflow = 8;
  1327. FPU_Underflow = $10;
  1328. FPU_StackUnderflow = $20;
  1329. FPU_StackOverflow = $40;
  1330. FPU_ExceptionMask = $ff;
  1331. { use Default8087CW instead
  1332. fpucw : word = $1300 or FPU_StackUnderflow or FPU_Underflow or FPU_Denormal;
  1333. }
  1334. MM_MaskInvalidOp = %0000000010000000;
  1335. MM_MaskDenorm = %0000000100000000;
  1336. MM_MaskDivZero = %0000001000000000;
  1337. MM_MaskOverflow = %0000010000000000;
  1338. MM_MaskUnderflow = %0000100000000000;
  1339. MM_MaskPrecision = %0001000000000000;
  1340. mxcsr : dword = MM_MaskUnderflow or MM_MaskPrecision or MM_MaskDenorm;
  1341. {$define FPC_SYSTEM_HAS_SYSINITFPU}
  1342. Procedure SysInitFPU;
  1343. var
  1344. { these locals are so we don't have to hack pic code in the assembler }
  1345. localmxcsr: dword;
  1346. localfpucw: word;
  1347. begin
  1348. localfpucw:=Default8087CW;
  1349. asm
  1350. fninit
  1351. fldcw localfpucw
  1352. fwait
  1353. end;
  1354. if has_sse_support then
  1355. begin
  1356. localmxcsr:=mxcsr;
  1357. asm
  1358. { setup sse exceptions }
  1359. ldmxcsr localmxcsr
  1360. end;
  1361. end;
  1362. softfloat_exception_mask:=float_flag_underflow or float_flag_inexact or float_flag_denormal;
  1363. end;
  1364. {$define FPC_SYSTEM_HAS_SYSRESETFPU}
  1365. Procedure SysResetFPU;
  1366. var
  1367. { these locals are so we don't have to hack pic code in the assembler }
  1368. localmxcsr: dword;
  1369. localfpucw: word;
  1370. begin
  1371. localfpucw:=Default8087CW;
  1372. asm
  1373. fninit
  1374. fwait
  1375. fldcw localfpucw
  1376. end;
  1377. if has_sse_support then
  1378. begin
  1379. localmxcsr:=mxcsr;
  1380. asm
  1381. { setup sse exceptions }
  1382. ldmxcsr localmxcsr
  1383. end;
  1384. end;
  1385. softfloat_exception_flags:=0;
  1386. end;
  1387. { because of the brain dead sse detection on x86, this test is post poned }
  1388. procedure fpc_cpucodeinit;
  1389. begin
  1390. os_supports_sse:=true;
  1391. os_supports_sse:=sse_support;
  1392. if os_supports_sse then
  1393. begin
  1394. sse_check:=true;
  1395. asm
  1396. { force an sse exception if no sse is supported, the exception handler sets
  1397. os_supports_sse to false then }
  1398. { don't change this instruction, the code above depends on its size }
  1399. movaps %xmm7, %xmm6
  1400. end;
  1401. sse_check:=false;
  1402. end;
  1403. has_sse_support:=os_supports_sse;
  1404. has_mmx_support:=mmx_support;
  1405. SysResetFPU;
  1406. if not(IsLibrary) then
  1407. SysInitFPU;
  1408. {$ifdef USE_FASTMOVE}
  1409. setup_fastmove;
  1410. {$endif}
  1411. end;
  1412. {$if not defined(darwin) and defined(regcall) }
  1413. { darwin requires that the stack is aligned to 16 bytes when calling another function }
  1414. {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
  1415. {$define FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
  1416. function fpc_freemem_x(p:pointer):ptrint; [external name 'FPC_FREEMEM_X'];
  1417. Procedure fpc_AnsiStr_Decr_Ref (Var S : Pointer); [Public,Alias:'FPC_ANSISTR_DECR_REF']; compilerproc; nostackframe; assembler;
  1418. asm
  1419. cmpl $0,(%eax)
  1420. jne .Ldecr_ref_continue
  1421. ret
  1422. .Ldecr_ref_continue:
  1423. // Temps allocated between ebp-24 and ebp+0
  1424. subl $4,%esp
  1425. // Var S located in register
  1426. // Var l located in register
  1427. movl %eax,(%esp)
  1428. // [101] l:=@PAnsiRec(S-FirstOff)^.Ref;
  1429. movl (%eax),%edx
  1430. subl $8,%edx
  1431. // [102] If l^<0 then exit;
  1432. cmpl $0,(%edx)
  1433. jl .Lj3596
  1434. .Lj3603:
  1435. // [104] If declocked(l^) then
  1436. {$ifdef FPC_PIC}
  1437. pushl %ebx
  1438. call fpc_geteipasebx
  1439. addl $_GLOBAL_OFFSET_TABLE_,%ebx
  1440. movl ismultithread@GOT(%ebx),%ebx
  1441. movl (%ebx),%ebx
  1442. cmp $0, %ebx
  1443. popl %ebx
  1444. {$else FPC_PIC}
  1445. cmpl $0,ismultithread
  1446. {$endif FPC_PIC}
  1447. jne .Lj3610
  1448. decl (%edx)
  1449. je .Lj3620
  1450. addl $4,%esp
  1451. ret
  1452. .Lj3610:
  1453. movl %edx,%eax
  1454. call cpudeclocked
  1455. testb %al,%al
  1456. je .Lj3605
  1457. .Lj3620:
  1458. movl (%esp),%eax
  1459. movl (%eax),%eax
  1460. subl $8,%eax
  1461. call FPC_FREEMEM_X
  1462. movl (%esp),%eax
  1463. movl $0,(%eax)
  1464. .Lj3618:
  1465. .Lj3605:
  1466. .Lj3596:
  1467. // [107] end;
  1468. addl $4,%esp
  1469. end;
  1470. function fpc_truely_ansistr_unique(Var S : Pointer): Pointer; forward;
  1471. {$define FPC_SYSTEM_HAS_ANSISTR_UNIQUE}
  1472. Function fpc_ansistr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_ANSISTR_UNIQUE']; compilerproc; nostackframe;assembler;
  1473. asm
  1474. // Var S located in register
  1475. // Var $result located in register
  1476. movl %eax,%edx
  1477. // [437] pointer(result) := pointer(s);
  1478. movl (%eax),%eax
  1479. // [438] If Pointer(S)=Nil then
  1480. testl %eax,%eax
  1481. je .Lj4031
  1482. .Lj4036:
  1483. // [440] if PAnsiRec(Pointer(S)-Firstoff)^.Ref<>1 then
  1484. movl -8(%eax),%ecx
  1485. cmpl $1,%ecx
  1486. je .Lj4038
  1487. // [441] result:=fpc_truely_ansistr_unique(s);
  1488. movl %edx,%eax
  1489. call fpc_truely_ansistr_unique
  1490. .Lj4038:
  1491. .Lj4031:
  1492. // [442] end;
  1493. end;
  1494. {$endif FPC_HAS_FEATURE_ANSISTRINGS}
  1495. {$endif ndef darwin and defined(regcall) }
  1496. {$ifndef FPC_SYSTEM_HAS_MEM_BARRIER}
  1497. {$define FPC_SYSTEM_HAS_MEM_BARRIER}
  1498. procedure ReadBarrier;assembler;nostackframe;
  1499. asm
  1500. lock
  1501. addl $0,0(%esp)
  1502. { alternative: lfence on SSE capable CPUs }
  1503. end;
  1504. procedure ReadDependencyBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  1505. begin
  1506. { reads imply barrier on earlier reads depended on }
  1507. end;
  1508. procedure ReadWriteBarrier;assembler;nostackframe;
  1509. asm
  1510. lock
  1511. addl $0,0(%esp)
  1512. { alternative: mfence on SSE capable CPUs }
  1513. end;
  1514. procedure WriteBarrier;assembler;nostackframe;
  1515. asm
  1516. { no write reordering on intel CPUs (yet) }
  1517. end;
  1518. {$endif}
  1519. {$ifndef FPC_SYSTEM_HAS_BSX_QWORD}
  1520. {$define FPC_SYSTEM_HAS_BSX_QWORD}
  1521. function BsfQWord(Const AValue : QWord): cardinal; assembler; nostackframe;
  1522. asm
  1523. bsfl 4(%esp),%eax
  1524. jnz .L2
  1525. .L1: bsfl 8(%esp),%eax
  1526. add $32,%eax
  1527. .L2:
  1528. end;
  1529. function BsrQWord(Const AValue : QWord): cardinal; assembler; nostackframe;
  1530. asm
  1531. bsrl 8(%esp),%eax
  1532. jz .L1
  1533. add $32,%eax
  1534. jmp .L2
  1535. .L1: bsrl 4(%esp),%eax
  1536. .L2:
  1537. end;
  1538. {$endif}