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