i386.inc 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738
  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. { don't let libraries influence the FPU cw set by the host program }
  99. if IsLibrary then
  100. Default8087CW:=Get8087CW;
  101. end;
  102. function fpc_geteipasebx : pointer; [public, alias: 'fpc_geteipasebx'];assembler; nostackframe;
  103. asm
  104. movl (%esp),%ebx
  105. end;
  106. function fpc_geteipasecx : pointer; [public, alias: 'fpc_geteipasecx'];assembler; nostackframe;
  107. asm
  108. movl (%esp),%ecx
  109. end;
  110. {$ifndef FPC_SYSTEM_HAS_MOVE}
  111. {$define FPC_SYSTEM_HAS_MOVE}
  112. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE'];assembler;
  113. var
  114. saveesi,saveedi : longint;
  115. asm
  116. movl %edi,saveedi
  117. movl %esi,saveesi
  118. {$ifdef REGCALL}
  119. movl %eax,%esi
  120. movl %edx,%edi
  121. movl %ecx,%edx
  122. {$else}
  123. movl dest,%edi
  124. movl source,%esi
  125. movl count,%edx
  126. {$endif}
  127. movl %edi,%eax
  128. { check for zero or negative count }
  129. cmpl $0,%edx
  130. jle .LMoveEnd
  131. { Check for back or forward }
  132. sub %esi,%eax
  133. jz .LMoveEnd { Do nothing when source=dest }
  134. jc .LFMove { Do forward, dest<source }
  135. cmp %edx,%eax
  136. jb .LBMove { Dest is in range of move, do backward }
  137. { Forward Copy }
  138. .LFMove:
  139. cld
  140. cmpl $15,%edx
  141. jl .LFMove1
  142. movl %edi,%ecx { Align on 32bits }
  143. negl %ecx
  144. andl $3,%ecx
  145. subl %ecx,%edx
  146. rep
  147. movsb
  148. movl %edx,%ecx
  149. andl $3,%edx
  150. shrl $2,%ecx
  151. rep
  152. movsl
  153. .LFMove1:
  154. movl %edx,%ecx
  155. rep
  156. movsb
  157. jmp .LMoveEnd
  158. { Backward Copy }
  159. .LBMove:
  160. std
  161. addl %edx,%esi
  162. addl %edx,%edi
  163. movl %edi,%ecx
  164. decl %esi
  165. decl %edi
  166. cmpl $15,%edx
  167. jl .LBMove1
  168. negl %ecx { Align on 32bits }
  169. andl $3,%ecx
  170. subl %ecx,%edx
  171. rep
  172. movsb
  173. movl %edx,%ecx
  174. andl $3,%edx
  175. shrl $2,%ecx
  176. subl $3,%esi
  177. subl $3,%edi
  178. rep
  179. movsl
  180. addl $3,%esi
  181. addl $3,%edi
  182. .LBMove1:
  183. movl %edx,%ecx
  184. rep
  185. movsb
  186. cld
  187. .LMoveEnd:
  188. movl saveedi,%edi
  189. movl saveesi,%esi
  190. end;
  191. {$endif FPC_SYSTEM_HAS_MOVE}
  192. {$ifndef FPC_SYSTEM_HAS_FILLCHAR}
  193. {$define FPC_SYSTEM_HAS_FILLCHAR}
  194. Procedure FillChar(var x;count:SizeInt;value:byte);assembler; nostackframe;
  195. asm
  196. cmpl $22,%edx { empirically determined value on a Core 2 Duo Conroe }
  197. jg .LFillFull
  198. orl %edx,%edx
  199. jle .LFillZero
  200. .LFillLoop:
  201. movb %cl,(%eax)
  202. incl %eax
  203. decl %edx
  204. jne .LFillLoop
  205. .LFillZero:
  206. ret
  207. .LFillFull:
  208. cld
  209. push %edi
  210. movl %eax,%edi
  211. movzbl %cl,%eax
  212. movl %edx,%ecx
  213. imul $0x01010101,%eax { Expand al into a 4 subbytes of eax}
  214. shrl $2,%ecx
  215. andl $3,%edx
  216. rep
  217. stosl
  218. movl %edx,%ecx
  219. .LFill1:
  220. rep
  221. stosb
  222. .LFillEnd:
  223. pop %edi
  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; nostackframe;
  389. asm
  390. cmpl $57,%ecx { empirically determined value on a Core 2 Duo Conroe }
  391. jg .LCmpbyteFull
  392. testl %ecx,%ecx
  393. je .LCmpbyteZero
  394. pushl %ebx
  395. .LCmpbyteLoop:
  396. movb (%eax),%bl
  397. cmpb (%edx),%bl
  398. leal 1(%eax),%eax
  399. leal 1(%edx),%edx
  400. jne .LCmpbyteExitFast
  401. decl %ecx
  402. jne .LCmpbyteLoop
  403. .LCmpbyteExitFast:
  404. movzbl -1(%edx),%ecx { Compare last position }
  405. movzbl %bl,%eax
  406. subl %ecx,%eax
  407. popl %ebx
  408. ret
  409. .LCmpbyteZero:
  410. movl $0,%eax
  411. ret
  412. .LCmpbyteFull:
  413. pushl %esi
  414. pushl %edi
  415. cld
  416. movl %eax,%edi
  417. movl %edx,%esi
  418. movl %ecx,%eax
  419. movl %edi,%ecx { Align on 32bits }
  420. negl %ecx { calc bytes to align (%edi and 3) xor 3= -%edi and 3 }
  421. andl $3,%ecx
  422. subl %ecx,%eax { Subtract from number of bytes to go }
  423. orl %ecx,%ecx
  424. rep
  425. cmpsb { The actual 32-bit Aligning }
  426. jne .LCmpbyte3
  427. movl %eax,%ecx { bytes to do, divide by 4 }
  428. andl $3,%eax { remainder }
  429. shrl $2,%ecx { The actual division }
  430. orl %ecx,%ecx { Sets zero flag if ecx=0 -> no cmp }
  431. rep
  432. cmpsl
  433. je .LCmpbyte2 { All equal? then to the left over bytes }
  434. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise }
  435. subl %eax,%esi
  436. subl %eax,%edi
  437. .LCmpbyte2:
  438. movl %eax,%ecx { bytes still to (re)scan }
  439. orl %eax,%eax { prevent disaster in case %eax=0 }
  440. rep
  441. cmpsb
  442. .LCmpbyte3:
  443. movzbl -1(%esi),%ecx
  444. movzbl -1(%edi),%eax { Compare failing (or equal) position }
  445. subl %ecx,%eax
  446. .LCmpbyteExit:
  447. popl %edi
  448. popl %esi
  449. end;
  450. {$endif FPC_SYSTEM_HAS_COMPAREBYTE}
  451. {$ifndef FPC_SYSTEM_HAS_COMPAREWORD}
  452. {$define FPC_SYSTEM_HAS_COMPAREWORD}
  453. function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler; nostackframe;
  454. asm
  455. cmpl $32,%ecx { empirical average value, on a Athlon XP the
  456. break even is at 14, on a Core 2 Duo > 100 }
  457. jg .LCmpWordFull
  458. testl %ecx,%ecx
  459. je .LCmpWordZero
  460. pushl %ebx
  461. .LCmpWordLoop:
  462. movw (%eax),%bx
  463. cmpw (%edx),%bx
  464. leal 2(%eax),%eax
  465. leal 2(%edx),%edx
  466. jne .LCmpWordExitFast
  467. decl %ecx
  468. jne .LCmpWordLoop
  469. .LCmpWordExitFast:
  470. movzwl -2(%edx),%ecx { Compare last position }
  471. movzwl %bx,%eax
  472. subl %ecx,%eax
  473. popl %ebx
  474. ret
  475. .LCmpWordZero:
  476. movl $0,%eax
  477. ret
  478. .LCmpWordFull:
  479. pushl %esi
  480. pushl %edi
  481. pushl %ebx
  482. cld
  483. movl %eax,%edi
  484. movl %edx,%esi
  485. movl %ecx,%eax
  486. movl (%edi),%ebx // Compare alignment bytes.
  487. cmpl (%esi),%ebx
  488. jne .LCmpword2 // Aligning will go wrong already. Max 2 words will be scanned Branch NOW
  489. shll $1,%eax {Convert word count to bytes}
  490. movl %edi,%edx { Align comparing is already done, so simply add}
  491. negl %edx { calc bytes to align -%edi and 3}
  492. andl $3,%edx
  493. addl %edx,%esi { Skip max 3 bytes alignment}
  494. addl %edx,%edi
  495. subl %edx,%eax { Subtract from number of bytes to go}
  496. movl %eax,%ecx { Make copy of bytes to go}
  497. andl $3,%eax { Calc remainder (mod 4) }
  498. andl $1,%edx { %edx is 1 if array not 2-aligned, 0 otherwise}
  499. shrl $2,%ecx { divide bytes to go by 4, DWords to go}
  500. orl %ecx,%ecx { Sets zero flag if ecx=0 -> no cmp}
  501. rep { Compare entire DWords}
  502. cmpsl
  503. je .LCmpword2a { All equal? then to the left over bytes}
  504. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  505. subl %eax,%esi { Go back one DWord}
  506. subl %eax,%edi
  507. incl %eax {if not odd then this does nothing, else it makes
  508. sure that adding %edx increases from 2 to 3 words}
  509. .LCmpword2a:
  510. subl %edx,%esi { Subtract alignment}
  511. subl %edx,%edi
  512. addl %edx,%eax
  513. shrl $1,%eax
  514. .LCmpword2:
  515. movl %eax,%ecx {words still to (re)scan}
  516. orl %eax,%eax {prevent disaster in case %eax=0}
  517. rep
  518. cmpsw
  519. .LCmpword3:
  520. movzwl -2(%esi),%ecx
  521. movzwl -2(%edi),%eax // Compare failing (or equal) position
  522. subl %ecx,%eax // calculate end result.
  523. .LCmpwordExit:
  524. popl %ebx
  525. popl %edi
  526. popl %esi
  527. end;
  528. {$endif FPC_SYSTEM_HAS_COMPAREWORD}
  529. {$ifndef FPC_SYSTEM_HAS_COMPAREDWORD}
  530. {$define FPC_SYSTEM_HAS_COMPAREDWORD}
  531. function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler; nostackframe;
  532. asm
  533. cmpl $32,%ecx { empirical average value, on a Athlon XP the
  534. break even is at 12, on a Core 2 Duo > 100 }
  535. jg .LCmpDWordFull
  536. testl %ecx,%ecx
  537. je .LCmpDWordZero
  538. pushl %ebx
  539. .LCmpDWordLoop:
  540. movl (%eax),%ebx
  541. cmpl (%edx),%ebx
  542. leal 4(%eax),%eax
  543. leal 4(%edx),%edx
  544. jne .LCmpDWordExitFast
  545. decl %ecx
  546. jne .LCmpDWordLoop
  547. .LCmpDWordExitFast:
  548. xorl %eax,%eax
  549. movl -4(%edx),%edx // Compare failing (or equal) position
  550. subl %edx,%ebx // calculate end result.
  551. setb %dl
  552. seta %cl
  553. addb %cl,%al
  554. subb %dl,%al
  555. movsbl %al,%eax
  556. popl %ebx
  557. ret
  558. .LCmpDWordZero:
  559. movl $0,%eax
  560. ret
  561. .LCmpDWordFull:
  562. pushl %esi
  563. pushl %edi
  564. cld
  565. movl %eax,%edi
  566. movl %edx,%esi
  567. xorl %eax,%eax
  568. rep { Compare entire DWords}
  569. cmpsl
  570. movl -4(%edi),%edi // Compare failing (or equal) position
  571. subl -4(%esi),%edi // calculate end result.
  572. setb %dl
  573. seta %cl
  574. addb %cl,%al
  575. subb %dl,%al
  576. movsbl %al,%eax
  577. .LCmpDwordExit:
  578. popl %edi
  579. popl %esi
  580. end;
  581. {$endif FPC_SYSTEM_HAS_COMPAREDWORD}
  582. {$ifndef FPC_SYSTEM_HAS_INDEXCHAR0}
  583. {$define FPC_SYSTEM_HAS_INDEXCHAR0}
  584. function IndexChar0(Const buf;len:SizeInt;b:Char):SizeInt; assembler;
  585. var
  586. saveesi,saveebx : longint;
  587. asm
  588. movl %esi,saveesi
  589. movl %ebx,saveebx
  590. // Can't use scasb, or will have to do it twice, think this
  591. // is faster for small "len"
  592. {$ifdef REGCALL}
  593. movl %eax,%esi // Load address
  594. movzbl %cl,%ebx // Load searchpattern
  595. {$else}
  596. movl Buf,%esi // Load address
  597. movl len,%edx // load maximal searchdistance
  598. movzbl b,%ebx // Load searchpattern
  599. {$endif}
  600. testl %edx,%edx
  601. je .LFound
  602. xorl %ecx,%ecx // zero index in Buf
  603. xorl %eax,%eax // To make DWord compares possible
  604. .balign 4
  605. .LLoop:
  606. movb (%esi),%al // Load byte
  607. cmpb %al,%bl
  608. je .LFound // byte the same?
  609. incl %ecx
  610. incl %esi
  611. cmpl %edx,%ecx // Maximal distance reached?
  612. je .LNotFound
  613. testl %eax,%eax // Nullchar = end of search?
  614. jne .LLoop
  615. .LNotFound:
  616. movl $-1,%ecx // Not found return -1
  617. .LFound:
  618. movl %ecx,%eax
  619. movl saveesi,%esi
  620. movl saveebx,%ebx
  621. end;
  622. {$endif FPC_SYSTEM_HAS_INDEXCHAR0}
  623. {****************************************************************************
  624. String
  625. ****************************************************************************}
  626. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  627. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  628. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  629. function fpc_shortstr_to_shortstr(len:longint; const sstr: shortstring): shortstring; [public,alias: 'FPC_SHORTSTR_TO_SHORTSTR']; compilerproc;
  630. begin
  631. asm
  632. {$ifdef FPC_PROFILE}
  633. push %eax
  634. push %edx
  635. push %ecx
  636. call mcount
  637. pop %ecx
  638. pop %edx
  639. pop %eax
  640. {$endif FPC_PROFILE}
  641. cld
  642. movl __RESULT,%edi
  643. movl sstr,%esi
  644. xorl %eax,%eax
  645. movl len,%ecx
  646. lodsb
  647. cmpl %ecx,%eax
  648. jbe .LStrCopy1
  649. movl %ecx,%eax
  650. .LStrCopy1:
  651. stosb
  652. cmpl $7,%eax
  653. jl .LStrCopy2
  654. movl %edi,%ecx { Align on 32bits }
  655. negl %ecx
  656. andl $3,%ecx
  657. subl %ecx,%eax
  658. rep
  659. movsb
  660. movl %eax,%ecx
  661. andl $3,%eax
  662. shrl $2,%ecx
  663. rep
  664. movsl
  665. .LStrCopy2:
  666. movl %eax,%ecx
  667. rep
  668. movsb
  669. end ['ESI','EDI','EAX','ECX'];
  670. end;
  671. {$else FPC_STRTOSHORTSTRINGPROC}
  672. procedure fpc_shortstr_to_shortstr(out res:shortstring; const sstr: shortstring);assembler;[public,alias:'FPC_SHORTSTR_TO_SHORTSTR']; compilerproc;
  673. var
  674. saveesi,saveedi : longint;
  675. asm
  676. {$ifdef FPC_PROFILE}
  677. push %eax
  678. push %edx
  679. push %ecx
  680. call mcount
  681. pop %ecx
  682. pop %edx
  683. pop %eax
  684. {$endif FPC_PROFILE}
  685. movl %edi,saveedi
  686. movl %esi,saveesi
  687. cld
  688. movl res,%edi
  689. movl sstr,%esi
  690. {$ifdef regcall}
  691. movl %edx,%ecx
  692. {$else regcall}
  693. movl res+4,%ecx
  694. {$endif regcall}
  695. xorl %eax,%eax
  696. lodsb
  697. cmpl %ecx,%eax
  698. jbe .LStrCopy1
  699. movl %ecx,%eax
  700. .LStrCopy1:
  701. stosb
  702. cmpl $7,%eax
  703. jl .LStrCopy2
  704. movl %edi,%ecx { Align on 32bits }
  705. negl %ecx
  706. andl $3,%ecx
  707. subl %ecx,%eax
  708. rep
  709. movsb
  710. movl %eax,%ecx
  711. andl $3,%eax
  712. shrl $2,%ecx
  713. rep
  714. movsl
  715. .LStrCopy2:
  716. movl %eax,%ecx
  717. rep
  718. movsb
  719. movl saveedi,%edi
  720. movl saveesi,%esi
  721. end;
  722. {$endif FPC_STRTOSHORTSTRINGPROC}
  723. procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN'];
  724. begin
  725. asm
  726. {$ifdef FPC_PROFILE}
  727. push %eax
  728. push %edx
  729. push %ecx
  730. call mcount
  731. pop %ecx
  732. pop %edx
  733. pop %eax
  734. {$endif FPC_PROFILE}
  735. pushl %eax
  736. pushl %ecx
  737. cld
  738. movl dstr,%edi
  739. movl sstr,%esi
  740. xorl %eax,%eax
  741. movl len,%ecx
  742. lodsb
  743. cmpl %ecx,%eax
  744. jbe .LStrCopy1
  745. movl %ecx,%eax
  746. .LStrCopy1:
  747. stosb
  748. cmpl $7,%eax
  749. jl .LStrCopy2
  750. movl %edi,%ecx { Align on 32bits }
  751. negl %ecx
  752. andl $3,%ecx
  753. subl %ecx,%eax
  754. rep
  755. movsb
  756. movl %eax,%ecx
  757. andl $3,%eax
  758. shrl $2,%ecx
  759. rep
  760. movsl
  761. .LStrCopy2:
  762. movl %eax,%ecx
  763. rep
  764. movsb
  765. popl %ecx
  766. popl %eax
  767. end ['ESI','EDI'];
  768. end;
  769. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  770. {$ifndef STR_CONCAT_PROCS}
  771. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  772. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  773. function fpc_shortstr_concat(const s1,s2:shortstring):shortstring;compilerproc;
  774. begin
  775. asm
  776. {$ifdef FPC_PROFILE}
  777. push %eax
  778. push %edx
  779. push %ecx
  780. call mcount
  781. pop %ecx
  782. pop %edx
  783. pop %eax
  784. {$endif FPC_PROFILE}
  785. movl __RESULT,%edi
  786. movl %edi,%ebx
  787. movl s1,%esi { first string }
  788. lodsb
  789. andl $0x0ff,%eax
  790. stosb
  791. cmpl $7,%eax
  792. jl .LStrConcat1
  793. movl %edi,%ecx { Align on 32bits }
  794. negl %ecx
  795. andl $3,%ecx
  796. subl %ecx,%eax
  797. rep
  798. movsb
  799. movl %eax,%ecx
  800. andl $3,%eax
  801. shrl $2,%ecx
  802. rep
  803. movsl
  804. .LStrConcat1:
  805. movl %eax,%ecx
  806. rep
  807. movsb
  808. movl s2,%esi { second string }
  809. movzbl (%ebx),%ecx
  810. negl %ecx
  811. addl $0x0ff,%ecx
  812. lodsb
  813. cmpl %ecx,%eax
  814. jbe .LStrConcat2
  815. movl %ecx,%eax
  816. .LStrConcat2:
  817. addb %al,(%ebx)
  818. cmpl $7,%eax
  819. jl .LStrConcat3
  820. movl %edi,%ecx { Align on 32bits }
  821. negl %ecx
  822. andl $3,%ecx
  823. subl %ecx,%eax
  824. rep
  825. movsb
  826. movl %eax,%ecx
  827. andl $3,%eax
  828. shrl $2,%ecx
  829. rep
  830. movsl
  831. .LStrConcat3:
  832. movl %eax,%ecx
  833. rep
  834. movsb
  835. end ['EBX','ECX','EAX','ESI','EDI'];
  836. end;
  837. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  838. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  839. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  840. procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring);compilerproc;
  841. [public,alias:'FPC_SHORTSTR_APPEND_SHORTSTR'];
  842. begin
  843. asm
  844. {$ifdef FPC_PROFILE}
  845. push %eax
  846. push %edx
  847. push %ecx
  848. call mcount
  849. pop %ecx
  850. pop %edx
  851. pop %eax
  852. {$endif FPC_PROFILE}
  853. movl s1,%edi
  854. movl s2,%esi
  855. movl %edi,%ebx
  856. movzbl (%edi),%ecx
  857. movl __HIGH(s1),%eax
  858. lea 1(%edi,%ecx),%edi
  859. negl %ecx
  860. addl %eax,%ecx
  861. // no need to zero eax, high(s1) <= 255
  862. lodsb
  863. cmpl %ecx,%eax
  864. jbe .LStrConcat1
  865. movl %ecx,%eax
  866. .LStrConcat1:
  867. addb %al,(%ebx)
  868. cmpl $7,%eax
  869. jl .LStrConcat2
  870. movl %edi,%ecx { Align on 32bits }
  871. negl %ecx
  872. andl $3,%ecx
  873. subl %ecx,%eax
  874. rep
  875. movsb
  876. movl %eax,%ecx
  877. andl $3,%eax
  878. shrl $2,%ecx
  879. rep
  880. movsl
  881. .LStrConcat2:
  882. movl %eax,%ecx
  883. rep
  884. movsb
  885. end ['EBX','ECX','EAX','ESI','EDI'];
  886. end;
  887. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  888. {$endif STR_CONCAT_PROCS}
  889. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  890. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  891. function fpc_shortstr_compare(const left,right:shortstring): longint;assembler; [public,alias:'FPC_SHORTSTR_COMPARE']; compilerproc;
  892. var
  893. saveesi,saveedi,saveebx : longint;
  894. asm
  895. {$ifdef FPC_PROFILE}
  896. push %eax
  897. push %edx
  898. push %ecx
  899. call mcount
  900. pop %ecx
  901. pop %edx
  902. pop %eax
  903. {$endif FPC_PROFILE}
  904. movl %edi,saveedi
  905. movl %esi,saveesi
  906. movl %ebx,saveebx
  907. cld
  908. movl right,%esi
  909. movl left,%edi
  910. movzbl (%esi),%eax
  911. movzbl (%edi),%ebx
  912. movl %eax,%edx
  913. incl %esi
  914. incl %edi
  915. cmpl %ebx,%eax
  916. jbe .LStrCmp1
  917. movl %ebx,%eax
  918. .LStrCmp1:
  919. cmpl $7,%eax
  920. jl .LStrCmp2
  921. movl %edi,%ecx { Align on 32bits }
  922. negl %ecx
  923. andl $3,%ecx
  924. subl %ecx,%eax
  925. orl %ecx,%ecx
  926. rep
  927. cmpsb
  928. jne .LStrCmp3
  929. movl %eax,%ecx
  930. andl $3,%eax
  931. shrl $2,%ecx
  932. orl %ecx,%ecx
  933. rep
  934. cmpsl
  935. je .LStrCmp2
  936. movl $4,%eax
  937. subl %eax,%esi
  938. subl %eax,%edi
  939. .LStrCmp2:
  940. movl %eax,%ecx
  941. orl %eax,%eax
  942. rep
  943. cmpsb
  944. je .LStrCmp4
  945. .LStrCmp3:
  946. movzbl -1(%esi),%edx // Compare failing (or equal) position
  947. movzbl -1(%edi),%ebx
  948. .LStrCmp4:
  949. movl %ebx,%eax // Compare length or position
  950. subl %edx,%eax
  951. movl saveedi,%edi
  952. movl saveesi,%esi
  953. movl saveebx,%ebx
  954. end;
  955. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  956. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  957. {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  958. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  959. function fpc_pchar_to_shortstr(p:pchar):shortstring;assembler;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; compilerproc;
  960. {$include strpas.inc}
  961. {$else FPC_STRTOSHORTSTRINGPROC}
  962. procedure fpc_pchar_to_shortstr(out res : shortstring;p:pchar);assembler;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; compilerproc;
  963. var
  964. saveres,saveebx,saveesi,saveedi : longint;
  965. asm
  966. {$ifdef FPC_PROFILE}
  967. push %eax
  968. push %edx
  969. push %ecx
  970. call mcount
  971. pop %ecx
  972. pop %edx
  973. pop %eax
  974. {$endif FPC_PROFILE}
  975. movl %ebx,saveebx
  976. movl %esi,saveesi
  977. movl %edi,saveedi
  978. {$ifdef regcall}
  979. movl %ecx,%esi
  980. movl %eax,%edi
  981. movl %edi,saveres
  982. {$else}
  983. movl p,%esi
  984. {$endif}
  985. movl $1,%ecx
  986. testl %esi,%esi
  987. movl %esi,%eax
  988. jz .LStrPasDone
  989. {$ifndef REGCALL}
  990. movl res,%edi
  991. {$endif}
  992. leal 3(%esi),%edx
  993. andl $-4,%edx
  994. // skip length byte
  995. incl %edi
  996. subl %esi,%edx
  997. jz .LStrPasAligned
  998. // align source to multiple of 4 (not dest, because we can't read past
  999. // the end of the source, since that may be past the end of the heap
  1000. // -> sigsegv!!)
  1001. .LStrPasAlignLoop:
  1002. movb (%esi),%al
  1003. incl %esi
  1004. testb %al,%al
  1005. jz .LStrPasDone
  1006. incl %edi
  1007. incb %cl
  1008. decb %dl
  1009. movb %al,-1(%edi)
  1010. jne .LStrPasAlignLoop
  1011. .balign 16
  1012. .LStrPasAligned:
  1013. movl (%esi),%ebx
  1014. addl $4,%edi
  1015. leal 0x0fefefeff(%ebx),%eax
  1016. movl %ebx,%edx
  1017. addl $4,%esi
  1018. notl %edx
  1019. andl %edx,%eax
  1020. addl $4,%ecx
  1021. andl $0x080808080,%eax
  1022. movl %ebx,-4(%edi)
  1023. jnz .LStrPasEndFound
  1024. cmpl $252,%ecx
  1025. ja .LStrPasPreEndLoop
  1026. jmp .LStrPasAligned
  1027. .LStrPasEndFound:
  1028. subl $4,%ecx
  1029. // this won't overwrite data since the result = 255 char string
  1030. // and we never process more than the first 255 chars of p
  1031. shrl $8,%eax
  1032. jc .LStrPasDone
  1033. incl %ecx
  1034. shrl $8,%eax
  1035. jc .LStrPasDone
  1036. incl %ecx
  1037. shrl $8,%eax
  1038. jc .LStrPasDone
  1039. incl %ecx
  1040. jmp .LStrPasDone
  1041. .LStrPasPreEndLoop:
  1042. testb %cl,%cl
  1043. jz .LStrPasDone
  1044. movl (%esi),%eax
  1045. .LStrPasEndLoop:
  1046. testb %al,%al
  1047. jz .LStrPasDone
  1048. movb %al,(%edi)
  1049. shrl $8,%eax
  1050. incl %edi
  1051. incb %cl
  1052. jnz .LStrPasEndLoop
  1053. .LStrPasDone:
  1054. {$ifdef REGCALL}
  1055. movl saveres,%edi
  1056. {$else}
  1057. movl res,%edi
  1058. {$endif}
  1059. addb $255,%cl
  1060. movb %cl,(%edi)
  1061. movl saveesi,%esi
  1062. movl saveedi,%edi
  1063. movl saveebx,%ebx
  1064. end;
  1065. {$endif FPC_STRTOSHORTSTRINGPROC}
  1066. {$endif FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  1067. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  1068. {$define FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  1069. function fpc_pchar_length(p:pchar):longint;assembler;[public,alias:'FPC_PCHAR_LENGTH']; compilerproc;
  1070. var
  1071. saveedi : longint;
  1072. asm
  1073. {$ifdef FPC_PROFILE}
  1074. push %eax
  1075. push %edx
  1076. push %ecx
  1077. call mcount
  1078. pop %ecx
  1079. pop %edx
  1080. pop %eax
  1081. {$endif FPC_PROFILE}
  1082. movl %edi,saveedi
  1083. {$ifdef REGCALL}
  1084. movl %eax,%edi
  1085. {$else}
  1086. movl p,%edi
  1087. {$endif}
  1088. movl $0xffffffff,%ecx
  1089. xorl %eax,%eax
  1090. test %edi,%edi
  1091. jz .LStrLenDone
  1092. cld
  1093. repne
  1094. scasb
  1095. movl $0xfffffffe,%eax
  1096. subl %ecx,%eax
  1097. movl saveedi,%edi
  1098. .LStrLenDone:
  1099. end;
  1100. {$endif FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  1101. {$IFNDEF INTERNAL_BACKTRACE}
  1102. {$define FPC_SYSTEM_HAS_GET_FRAME}
  1103. function get_frame:pointer;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  1104. asm
  1105. movl %ebp,%eax
  1106. end;
  1107. {$ENDIF not INTERNAL_BACKTRACE}
  1108. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  1109. function get_caller_addr(framebp:pointer):pointer;nostackframe;assembler;
  1110. asm
  1111. {$ifndef REGCALL}
  1112. movl framebp,%eax
  1113. {$endif}
  1114. orl %eax,%eax
  1115. jz .Lg_a_null
  1116. movl 4(%eax),%eax
  1117. .Lg_a_null:
  1118. end;
  1119. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  1120. function get_caller_frame(framebp:pointer):pointer;nostackframe;assembler;
  1121. asm
  1122. {$ifndef REGCALL}
  1123. movl framebp,%eax
  1124. {$endif}
  1125. orl %eax,%eax
  1126. jz .Lgnf_null
  1127. movl (%eax),%eax
  1128. .Lgnf_null:
  1129. end;
  1130. {$define FPC_SYSTEM_HAS_SPTR}
  1131. Function Sptr : Pointer;assembler;nostackframe;
  1132. asm
  1133. movl %esp,%eax
  1134. end;
  1135. {****************************************************************************
  1136. Str()
  1137. ****************************************************************************}
  1138. {$if defined(disabled) and defined(regcall) }
  1139. {$define FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  1140. {$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
  1141. label str_int_shortcut;
  1142. procedure int_str(l:longword;out s:string);assembler;nostackframe;
  1143. asm
  1144. pushl %esi
  1145. pushl %edi
  1146. pushl %ebx
  1147. mov %edx,%edi
  1148. xor %edx,%edx
  1149. jmp str_int_shortcut
  1150. end;
  1151. procedure int_str(l:longint;out s:string);assembler;nostackframe;
  1152. {Optimized for speed, but balanced with size.}
  1153. const digits:array[0..9] of cardinal=(0,10,100,1000,10000,
  1154. 100000,1000000,10000000,
  1155. 100000000,1000000000);
  1156. asm
  1157. {$ifdef FPC_PROFILE}
  1158. push %eax
  1159. push %edx
  1160. push %ecx
  1161. call mcount
  1162. pop %ecx
  1163. pop %edx
  1164. pop %eax
  1165. {$endif FPC_PROFILE}
  1166. push %esi
  1167. push %edi
  1168. push %ebx
  1169. movl %edx,%edi
  1170. { Calculate absolute value and put sign in edx}
  1171. cltd
  1172. xorl %edx,%eax
  1173. subl %edx,%eax
  1174. negl %edx
  1175. str_int_shortcut:
  1176. movl %ecx,%esi
  1177. {Calculate amount of digits in ecx.}
  1178. xorl %ecx,%ecx
  1179. bsrl %eax,%ecx
  1180. incl %ecx
  1181. imul $1233,%ecx
  1182. shr $12,%ecx
  1183. {$ifdef FPC_PIC}
  1184. call fpc_geteipasebx
  1185. {$ifdef darwin}
  1186. movl digits-.Lpic(%ebx),%ebx
  1187. {$else}
  1188. addl $_GLOBAL_OFFSET_TABLE_,%ebx
  1189. movl digits@GOT(%ebx),%ebx
  1190. {$endif}
  1191. cmpl (%ebx,%ecx,4),%eax
  1192. {$else}
  1193. cmpl digits(,%ecx,4),%eax
  1194. {$endif}
  1195. cmc
  1196. adcl $0,%ecx {Nr. digits ready in ecx.}
  1197. {Write length & sign.}
  1198. lea (%edx,%ecx),%ebx
  1199. movb $45,%bh {movb $'-,%bh Not supported by our ATT reader.}
  1200. movw %bx,(%edi)
  1201. addl %edx,%edi
  1202. subl %edx,%esi
  1203. {Skip digits beyond string length.}
  1204. movl %eax,%edx
  1205. subl %ecx,%esi
  1206. jae .Lloop_write
  1207. .balign 4
  1208. .Lloop_skip:
  1209. movl $0xcccccccd,%eax {Divide by 10 using mul+shr}
  1210. mull %edx
  1211. shrl $3,%edx
  1212. decl %ecx
  1213. jz .Ldone {If (l<0) and (high(s)=1) this jump is taken.}
  1214. incl %esi
  1215. jnz .Lloop_skip
  1216. {Write out digits.}
  1217. .balign 4
  1218. .Lloop_write:
  1219. movl $0xcccccccd,%eax {Divide by 10 using mul+shr}
  1220. {Pre-add '0'}
  1221. leal 48(%edx),%ebx {leal $'0(,%edx),%ebx Not supported by our ATT reader.}
  1222. mull %edx
  1223. shrl $3,%edx
  1224. leal (%edx,%edx,8),%eax {x mod 10 = x-10*(x div 10)}
  1225. subl %edx,%ebx
  1226. subl %eax,%ebx
  1227. movb %bl,(%edi,%ecx)
  1228. decl %ecx
  1229. jnz .Lloop_write
  1230. .Ldone:
  1231. popl %ebx
  1232. popl %edi
  1233. popl %esi
  1234. end;
  1235. {$endif}
  1236. {****************************************************************************
  1237. Bounds Check
  1238. ****************************************************************************}
  1239. { do a thread-safe inc/dec }
  1240. {$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  1241. function cpudeclocked(var l : longint) : boolean;assembler;nostackframe;
  1242. asm
  1243. {$ifndef REGCALL}
  1244. movl l,%eax
  1245. {$endif}
  1246. { this check should be done because a lock takes a lot }
  1247. { of time! }
  1248. lock
  1249. decl (%eax)
  1250. setzb %al
  1251. end;
  1252. {$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  1253. procedure cpuinclocked(var l : longint);assembler;nostackframe;
  1254. asm
  1255. {$ifndef REGCALL}
  1256. movl l,%eax
  1257. {$endif}
  1258. lock
  1259. incl (%eax)
  1260. end;
  1261. // inline SMP check and normal lock.
  1262. // the locked one is so slow, inlining doesn't matter.
  1263. function declocked(var l : longint) : boolean; inline;
  1264. begin
  1265. if not ismultithread then
  1266. begin
  1267. dec(l);
  1268. declocked:=l=0;
  1269. end
  1270. else
  1271. declocked:=cpudeclocked(l);
  1272. end;
  1273. procedure inclocked(var l : longint); inline;
  1274. begin
  1275. if not ismultithread then
  1276. inc(l)
  1277. else
  1278. cpuinclocked(l);
  1279. end;
  1280. function InterLockedDecrement (var Target: longint) : longint; assembler;
  1281. asm
  1282. {$ifdef REGCALL}
  1283. movl $-1,%edx
  1284. xchgl %edx,%eax
  1285. {$else}
  1286. movl Target, %edx
  1287. movl $-1, %eax
  1288. {$endif}
  1289. lock
  1290. xaddl %eax, (%edx)
  1291. decl %eax
  1292. end;
  1293. function InterLockedIncrement (var Target: longint) : longint; assembler;
  1294. asm
  1295. {$ifdef REGCALL}
  1296. movl $1,%edx
  1297. xchgl %edx,%eax
  1298. {$else}
  1299. movl Target, %edx
  1300. movl $1, %eax
  1301. {$endif}
  1302. lock
  1303. xaddl %eax, (%edx)
  1304. incl %eax
  1305. end;
  1306. function InterLockedExchange (var Target: longint;Source : longint) : longint; assembler;
  1307. asm
  1308. {$ifdef REGCALL}
  1309. xchgl (%eax),%edx
  1310. movl %edx,%eax
  1311. {$else}
  1312. movl Target,%ecx
  1313. movl Source,%eax
  1314. xchgl (%ecx),%eax
  1315. {$endif}
  1316. end;
  1317. function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint; assembler;
  1318. asm
  1319. {$ifdef REGCALL}
  1320. xchgl %eax,%edx
  1321. {$else}
  1322. movl Target,%edx
  1323. movl Source,%eax
  1324. {$endif}
  1325. lock
  1326. xaddl %eax, (%edx)
  1327. end;
  1328. function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint; assembler;
  1329. asm
  1330. {$ifdef REGCALL}
  1331. xchgl %eax,%ecx
  1332. {$else}
  1333. movl Target,%ecx
  1334. movl NewValue,%edx
  1335. movl Comperand,%eax
  1336. {$endif}
  1337. lock
  1338. cmpxchgl %edx, (%ecx)
  1339. end;
  1340. function InterlockedCompareExchange64(var Target: int64; NewValue: int64; Comperand: int64): int64; assembler;
  1341. asm
  1342. pushl %ebx
  1343. pushl %edi
  1344. {$ifdef REGCALL}
  1345. movl %eax,%edi
  1346. {$else}
  1347. movl Target,%edi
  1348. {$endif}
  1349. movl Comperand+4,%edx
  1350. movl Comperand+0,%eax
  1351. movl NewValue+4,%ecx
  1352. movl NewValue+0,%ebx
  1353. lock cmpxchg8b (%edi)
  1354. pop %edi
  1355. pop %ebx
  1356. end;
  1357. {****************************************************************************
  1358. FPU
  1359. ****************************************************************************}
  1360. const
  1361. { Internal constants for use in system unit }
  1362. FPU_Invalid = 1;
  1363. FPU_Denormal = 2;
  1364. FPU_DivisionByZero = 4;
  1365. FPU_Overflow = 8;
  1366. FPU_Underflow = $10;
  1367. FPU_StackUnderflow = $20;
  1368. FPU_StackOverflow = $40;
  1369. FPU_ExceptionMask = $ff;
  1370. { use Default8087CW instead
  1371. fpucw : word = $1300 or FPU_StackUnderflow or FPU_Underflow or FPU_Denormal;
  1372. }
  1373. MM_MaskInvalidOp = %0000000010000000;
  1374. MM_MaskDenorm = %0000000100000000;
  1375. MM_MaskDivZero = %0000001000000000;
  1376. MM_MaskOverflow = %0000010000000000;
  1377. MM_MaskUnderflow = %0000100000000000;
  1378. MM_MaskPrecision = %0001000000000000;
  1379. mxcsr : dword = MM_MaskUnderflow or MM_MaskPrecision or MM_MaskDenorm;
  1380. {$define FPC_SYSTEM_HAS_SYSINITFPU}
  1381. Procedure SysInitFPU;
  1382. var
  1383. { these locals are so we don't have to hack pic code in the assembler }
  1384. localmxcsr: dword;
  1385. localfpucw: word;
  1386. begin
  1387. localfpucw:=Default8087CW;
  1388. asm
  1389. fninit
  1390. fldcw localfpucw
  1391. fwait
  1392. end;
  1393. if has_sse_support then
  1394. begin
  1395. localmxcsr:=mxcsr;
  1396. asm
  1397. { setup sse exceptions }
  1398. ldmxcsr localmxcsr
  1399. end;
  1400. end;
  1401. softfloat_exception_mask:=float_flag_underflow or float_flag_inexact or float_flag_denormal;
  1402. end;
  1403. {$define FPC_SYSTEM_HAS_SYSRESETFPU}
  1404. Procedure SysResetFPU;
  1405. var
  1406. { these locals are so we don't have to hack pic code in the assembler }
  1407. localmxcsr: dword;
  1408. localfpucw: word;
  1409. begin
  1410. localfpucw:=Default8087CW;
  1411. asm
  1412. fninit
  1413. fwait
  1414. fldcw localfpucw
  1415. end;
  1416. if has_sse_support then
  1417. begin
  1418. localmxcsr:=mxcsr;
  1419. asm
  1420. { setup sse exceptions }
  1421. ldmxcsr localmxcsr
  1422. end;
  1423. end;
  1424. softfloat_exception_flags:=0;
  1425. end;
  1426. { because of the brain dead sse detection on x86, this test is post poned }
  1427. procedure fpc_cpucodeinit;
  1428. begin
  1429. os_supports_sse:=true;
  1430. os_supports_sse:=sse_support;
  1431. if os_supports_sse then
  1432. begin
  1433. sse_check:=true;
  1434. asm
  1435. { force an sse exception if no sse is supported, the exception handler sets
  1436. os_supports_sse to false then }
  1437. { don't change this instruction, the code above depends on its size }
  1438. movaps %xmm7, %xmm6
  1439. end;
  1440. sse_check:=false;
  1441. end;
  1442. has_sse_support:=os_supports_sse;
  1443. { don't let libraries influence the FPU cw set by the host program }
  1444. if has_sse_support and
  1445. IsLibrary then
  1446. mxcsr:=GetSSECSR;
  1447. has_mmx_support:=mmx_support;
  1448. SysResetFPU;
  1449. if not(IsLibrary) then
  1450. SysInitFPU;
  1451. {$ifdef USE_FASTMOVE}
  1452. setup_fastmove;
  1453. {$endif}
  1454. end;
  1455. {$if not defined(darwin) and defined(regcall) }
  1456. { darwin requires that the stack is aligned to 16 bytes when calling another function }
  1457. {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
  1458. {$define FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
  1459. function fpc_freemem_x(p:pointer):ptrint; [external name 'FPC_FREEMEM_X'];
  1460. Procedure fpc_AnsiStr_Decr_Ref (Var S : Pointer); [Public,Alias:'FPC_ANSISTR_DECR_REF']; compilerproc; nostackframe; assembler;
  1461. asm
  1462. cmpl $0,(%eax)
  1463. jne .Ldecr_ref_continue
  1464. ret
  1465. .Ldecr_ref_continue:
  1466. // Temps allocated between ebp-24 and ebp+0
  1467. subl $4,%esp
  1468. // Var S located in register
  1469. // Var l located in register
  1470. movl %eax,(%esp)
  1471. // [101] l:=@PAnsiRec(S-FirstOff)^.Ref;
  1472. movl (%eax),%edx
  1473. subl $8,%edx
  1474. // [102] If l^<0 then exit;
  1475. cmpl $0,(%edx)
  1476. jl .Lj3596
  1477. .Lj3603:
  1478. // [104] If declocked(l^) then
  1479. {$ifdef FPC_PIC}
  1480. pushl %ebx
  1481. call fpc_geteipasebx
  1482. addl $_GLOBAL_OFFSET_TABLE_,%ebx
  1483. movl ismultithread@GOT(%ebx),%ebx
  1484. movl (%ebx),%ebx
  1485. cmp $0, %ebx
  1486. popl %ebx
  1487. {$else FPC_PIC}
  1488. cmpl $0,ismultithread
  1489. {$endif FPC_PIC}
  1490. jne .Lj3610
  1491. decl (%edx)
  1492. je .Lj3620
  1493. addl $4,%esp
  1494. ret
  1495. .Lj3610:
  1496. movl %edx,%eax
  1497. call cpudeclocked
  1498. testb %al,%al
  1499. je .Lj3605
  1500. .Lj3620:
  1501. movl (%esp),%eax
  1502. movl (%eax),%eax
  1503. subl $8,%eax
  1504. call FPC_FREEMEM_X
  1505. movl (%esp),%eax
  1506. movl $0,(%eax)
  1507. .Lj3618:
  1508. .Lj3605:
  1509. .Lj3596:
  1510. // [107] end;
  1511. addl $4,%esp
  1512. end;
  1513. function fpc_truely_ansistr_unique(Var S : Pointer): Pointer; forward;
  1514. {$define FPC_SYSTEM_HAS_ANSISTR_UNIQUE}
  1515. Function fpc_ansistr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_ANSISTR_UNIQUE']; compilerproc; nostackframe;assembler;
  1516. asm
  1517. // Var S located in register
  1518. // Var $result located in register
  1519. movl %eax,%edx
  1520. // [437] pointer(result) := pointer(s);
  1521. movl (%eax),%eax
  1522. // [438] If Pointer(S)=Nil then
  1523. testl %eax,%eax
  1524. je .Lj4031
  1525. .Lj4036:
  1526. // [440] if PAnsiRec(Pointer(S)-Firstoff)^.Ref<>1 then
  1527. movl -8(%eax),%ecx
  1528. cmpl $1,%ecx
  1529. je .Lj4038
  1530. // [441] result:=fpc_truely_ansistr_unique(s);
  1531. movl %edx,%eax
  1532. call fpc_truely_ansistr_unique
  1533. .Lj4038:
  1534. .Lj4031:
  1535. // [442] end;
  1536. end;
  1537. {$endif FPC_HAS_FEATURE_ANSISTRINGS}
  1538. {$endif ndef darwin and defined(regcall) }
  1539. {$ifndef FPC_SYSTEM_HAS_MEM_BARRIER}
  1540. {$define FPC_SYSTEM_HAS_MEM_BARRIER}
  1541. procedure ReadBarrier;assembler;nostackframe;
  1542. asm
  1543. lock
  1544. addl $0,0(%esp)
  1545. { alternative: lfence on SSE capable CPUs }
  1546. end;
  1547. procedure ReadDependencyBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  1548. begin
  1549. { reads imply barrier on earlier reads depended on }
  1550. end;
  1551. procedure ReadWriteBarrier;assembler;nostackframe;
  1552. asm
  1553. lock
  1554. addl $0,0(%esp)
  1555. { alternative: mfence on SSE capable CPUs }
  1556. end;
  1557. procedure WriteBarrier;assembler;nostackframe;
  1558. asm
  1559. { no write reordering on intel CPUs (yet) }
  1560. end;
  1561. {$endif}
  1562. {$ifndef FPC_SYSTEM_HAS_BSX_QWORD}
  1563. {$define FPC_SYSTEM_HAS_BSX_QWORD}
  1564. function BsfQWord(Const AValue : QWord): cardinal; assembler; nostackframe;
  1565. asm
  1566. bsfl 4(%esp),%eax
  1567. jnz .L2
  1568. .L1: bsfl 8(%esp),%eax
  1569. add $32,%eax
  1570. .L2:
  1571. end;
  1572. function BsrQWord(Const AValue : QWord): cardinal; assembler; nostackframe;
  1573. asm
  1574. bsrl 8(%esp),%eax
  1575. jz .L1
  1576. add $32,%eax
  1577. jmp .L2
  1578. .L1: bsrl 4(%esp),%eax
  1579. .L2:
  1580. end;
  1581. {$endif}