i386.inc 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108
  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. has_sse_support,has_mmx_support,os_supports_sse : boolean;
  17. {$asmmode intel}
  18. function cpuid_support : boolean;assembler;
  19. {
  20. Check if the ID-flag can be changed, if changed then CpuID is supported.
  21. Tested under go32v1 and Linux on c6x86 with CpuID enabled and disabled (PFV)
  22. }
  23. asm
  24. push ebx
  25. pushf
  26. pushf
  27. pop eax
  28. mov ebx,eax
  29. xor eax,200000h
  30. push eax
  31. popf
  32. pushf
  33. pop eax
  34. popf
  35. and eax,200000h
  36. and ebx,200000h
  37. cmp eax,ebx
  38. setnz al
  39. pop ebx
  40. end;
  41. {$asmmode ATT}
  42. function sse_support : boolean;
  43. var
  44. _edx : longint;
  45. begin
  46. if cpuid_support then
  47. begin
  48. asm
  49. pushl %ebx
  50. movl $1,%eax
  51. cpuid
  52. movl %edx,_edx
  53. popl %ebx
  54. end;
  55. sse_support:=((_edx and $2000000)<>0) and os_supports_sse;
  56. end
  57. else
  58. { a cpu with without cpuid instruction supports never sse }
  59. sse_support:=false;
  60. end;
  61. { returns true, if the processor supports the mmx instructions }
  62. function mmx_support : boolean;
  63. var
  64. _edx : longint;
  65. begin
  66. if cpuid_support then
  67. begin
  68. asm
  69. pushl %ebx
  70. movl $1,%eax
  71. cpuid
  72. movl %edx,_edx
  73. popl %ebx
  74. end;
  75. mmx_support:=(_edx and $800000)<>0;
  76. end
  77. else
  78. { a cpu with without cpuid instruction supports never mmx }
  79. mmx_support:=false;
  80. end;
  81. {$define USE_FASTMOVE}
  82. {$i fastmove.inc}
  83. procedure fpc_cpuinit;
  84. begin
  85. { because of the brain dead sse detection on x86, this test is post poned to fpc_cpucodeinit which
  86. must be implemented OS dependend (FK)
  87. has_sse_support:=sse_support;
  88. has_mmx_support:=mmx_support;
  89. setup_fastmove;
  90. }
  91. os_supports_sse:=false;
  92. end;
  93. {$ifndef FPC_SYSTEM_HAS_MOVE}
  94. {$define FPC_SYSTEM_HAS_MOVE}
  95. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE'];assembler;
  96. var
  97. saveesi,saveedi : longint;
  98. asm
  99. movl %edi,saveedi
  100. movl %esi,saveesi
  101. {$ifdef REGCALL}
  102. movl %eax,%esi
  103. movl %edx,%edi
  104. movl %ecx,%edx
  105. {$else}
  106. movl dest,%edi
  107. movl source,%esi
  108. movl count,%edx
  109. {$endif}
  110. movl %edi,%eax
  111. { check for zero or negative count }
  112. cmpl $0,%edx
  113. jle .LMoveEnd
  114. { Check for back or forward }
  115. sub %esi,%eax
  116. jz .LMoveEnd { Do nothing when source=dest }
  117. jc .LFMove { Do forward, dest<source }
  118. cmp %edx,%eax
  119. jb .LBMove { Dest is in range of move, do backward }
  120. { Forward Copy }
  121. .LFMove:
  122. cld
  123. cmpl $15,%edx
  124. jl .LFMove1
  125. movl %edi,%ecx { Align on 32bits }
  126. negl %ecx
  127. andl $3,%ecx
  128. subl %ecx,%edx
  129. rep
  130. movsb
  131. movl %edx,%ecx
  132. andl $3,%edx
  133. shrl $2,%ecx
  134. rep
  135. movsl
  136. .LFMove1:
  137. movl %edx,%ecx
  138. rep
  139. movsb
  140. jmp .LMoveEnd
  141. { Backward Copy }
  142. .LBMove:
  143. std
  144. addl %edx,%esi
  145. addl %edx,%edi
  146. movl %edi,%ecx
  147. decl %esi
  148. decl %edi
  149. cmpl $15,%edx
  150. jl .LBMove1
  151. negl %ecx { Align on 32bits }
  152. andl $3,%ecx
  153. subl %ecx,%edx
  154. rep
  155. movsb
  156. movl %edx,%ecx
  157. andl $3,%edx
  158. shrl $2,%ecx
  159. subl $3,%esi
  160. subl $3,%edi
  161. rep
  162. movsl
  163. addl $3,%esi
  164. addl $3,%edi
  165. .LBMove1:
  166. movl %edx,%ecx
  167. rep
  168. movsb
  169. cld
  170. .LMoveEnd:
  171. movl saveedi,%edi
  172. movl saveesi,%esi
  173. end;
  174. {$endif FPC_SYSTEM_HAS_MOVE}
  175. {$ifndef FPC_SYSTEM_HAS_FILLCHAR}
  176. {$define FPC_SYSTEM_HAS_FILLCHAR}
  177. Procedure FillChar(var x;count:SizeInt;value:byte);assembler;
  178. asm
  179. {A push is prefered over a local variable because a local
  180. variable causes the compiler to generate a stackframe.}
  181. cld
  182. {$ifdef REGCALL}
  183. push %edi
  184. movl %eax,%edi
  185. movzbl %cl,%eax
  186. movl %edx,%ecx
  187. {$else}
  188. movl x,%edi
  189. movl count,%ecx
  190. movzbl value,%eax
  191. movl %ecx,%edx
  192. {$endif}
  193. { check for zero or negative count }
  194. or %ecx,%ecx
  195. jle .LFillEnd
  196. cmpl $7,%ecx
  197. jl .LFill1
  198. imul $0x01010101,%eax { Expand al into a 4 subbytes of eax}
  199. shrl $2,%ecx
  200. andl $3,%edx
  201. rep
  202. stosl
  203. movl %edx,%ecx
  204. .LFill1:
  205. rep
  206. stosb
  207. .LFillEnd:
  208. {$ifdef REGCALL}
  209. pop %edi
  210. {$endif}
  211. end;
  212. {$endif FPC_SYSTEM_HAS_FILLCHAR}
  213. {$ifndef FPC_SYSTEM_HAS_FILLWORD}
  214. {$define FPC_SYSTEM_HAS_FILLWORD}
  215. procedure fillword(var x;count : SizeInt;value : word);assembler;
  216. var
  217. saveedi : longint;
  218. asm
  219. movl %edi,saveedi
  220. {$ifdef REGCALL}
  221. movl %eax,%edi
  222. movzwl %cx,%eax
  223. movl %edx,%ecx
  224. {$else}
  225. movl x,%edi
  226. movl count,%ecx
  227. movzwl value,%eax
  228. {$endif}
  229. { check for zero or negative count }
  230. cmpl $0,%ecx
  231. jle .LFillWordEnd
  232. movl %eax,%edx
  233. shll $16,%eax
  234. orl %edx,%eax
  235. movl %ecx,%edx
  236. shrl $1,%ecx
  237. cld
  238. rep
  239. stosl
  240. movl %edx,%ecx
  241. andl $1,%ecx
  242. rep
  243. stosw
  244. .LFillWordEnd:
  245. movl saveedi,%edi
  246. end;
  247. {$endif FPC_SYSTEM_HAS_FILLWORD}
  248. {$ifndef FPC_SYSTEM_HAS_FILLDWORD}
  249. {$define FPC_SYSTEM_HAS_FILLDWORD}
  250. procedure filldword(var x;count : SizeInt;value : dword);assembler;
  251. var
  252. saveedi : longint;
  253. asm
  254. movl %edi,saveedi
  255. {$ifdef REGCALL}
  256. movl %eax,%edi
  257. movl %ecx,%eax
  258. movl %edx,%ecx
  259. {$else}
  260. movl x,%edi
  261. movl count,%ecx
  262. movl value,%eax
  263. {$endif}
  264. { check for zero or negative count }
  265. cmpl $0,%ecx
  266. jle .LFillDWordEnd
  267. cld
  268. rep
  269. stosl
  270. .LFillDWordEnd:
  271. movl saveedi,%edi
  272. end;
  273. {$endif FPC_SYSTEM_HAS_FILLDWORD}
  274. {$ifndef FPC_SYSTEM_HAS_INDEXBYTE}
  275. {$define FPC_SYSTEM_HAS_INDEXBYTE}
  276. function IndexByte(Const buf;len:SizeInt;b:byte):SizeInt; assembler;
  277. var
  278. saveedi,saveebx : longint;
  279. asm
  280. movl %edi,saveedi
  281. movl %ebx,saveebx
  282. movl buf,%edi // Load String
  283. movb b,%bl
  284. movl len,%ecx // Load len
  285. xorl %eax,%eax
  286. testl %ecx,%ecx
  287. jz .Lcharposnotfound
  288. cld
  289. movl %ecx,%edx // Copy for easy manipulation
  290. movb %bl,%al
  291. repne
  292. scasb
  293. jne .Lcharposnotfound
  294. incl %ecx
  295. subl %ecx,%edx
  296. movl %edx,%eax
  297. jmp .Lready
  298. .Lcharposnotfound:
  299. movl $-1,%eax
  300. .Lready:
  301. movl saveedi,%edi
  302. movl saveebx,%ebx
  303. end;
  304. {$endif FPC_SYSTEM_HAS_FILLDWORD}
  305. {$ifndef FPC_SYSTEM_HAS_INDEXWORD}
  306. {$define FPC_SYSTEM_HAS_INDEXWORD}
  307. function Indexword(Const buf;len:SizeInt;b:word):SizeInt; assembler;
  308. var
  309. saveedi,saveebx : longint;
  310. asm
  311. movl %edi,saveedi
  312. movl %ebx,saveebx
  313. movl Buf,%edi // Load String
  314. movw b,%bx
  315. movl Len,%ecx // Load len
  316. xorl %eax,%eax
  317. testl %ecx,%ecx
  318. jz .Lcharposnotfound
  319. cld
  320. movl %ecx,%edx // Copy for easy manipulation
  321. movw %bx,%ax
  322. repne
  323. scasw
  324. jne .Lcharposnotfound
  325. incl %ecx
  326. subl %ecx,%edx
  327. movl %edx,%eax
  328. jmp .Lready
  329. .Lcharposnotfound:
  330. movl $-1,%eax
  331. .Lready:
  332. movl saveedi,%edi
  333. movl saveebx,%ebx
  334. end;
  335. {$endif FPC_SYSTEM_HAS_INDEXWORD}
  336. {$ifndef FPC_SYSTEM_HAS_INDEXDWORD}
  337. {$define FPC_SYSTEM_HAS_INDEXDWORD}
  338. function IndexDWord(Const buf;len:SizeInt;b:DWord):SizeInt; assembler;
  339. var
  340. saveedi,saveebx : longint;
  341. asm
  342. movl %edi,saveedi
  343. movl %ebx,saveebx
  344. {$ifdef REGCALL}
  345. movl %eax,%edi
  346. movl %ecx,%ebx
  347. movl %edx,%ecx
  348. {$else}
  349. movl Len,%ecx // Load len
  350. movl Buf,%edi // Load String
  351. movl b,%ebx
  352. {$endif}
  353. xorl %eax,%eax
  354. testl %ecx,%ecx
  355. jz .Lcharposnotfound
  356. cld
  357. movl %ecx,%edx // Copy for easy manipulation
  358. movl %ebx,%eax
  359. repne
  360. scasl
  361. jne .Lcharposnotfound
  362. incl %ecx
  363. subl %ecx,%edx
  364. movl %edx,%eax
  365. jmp .Lready
  366. .Lcharposnotfound:
  367. movl $-1,%eax
  368. .Lready:
  369. movl saveedi,%edi
  370. movl saveebx,%ebx
  371. end;
  372. {$endif FPC_SYSTEM_HAS_INDEXDWORD}
  373. {$ifndef FPC_SYSTEM_HAS_COMPAREBYTE}
  374. {$define FPC_SYSTEM_HAS_COMPAREBYTE}
  375. function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt; assembler;
  376. var
  377. saveesi,saveedi : longint;
  378. asm
  379. movl %edi,saveedi
  380. movl %esi,saveesi
  381. cld
  382. {$ifdef REGCALL}
  383. movl %eax,%edi
  384. movl %edx,%esi
  385. movl %ecx,%eax
  386. {$else}
  387. movl len,%eax
  388. movl buf2,%esi { Load params}
  389. movl buf1,%edi
  390. {$endif}
  391. testl %eax,%eax {We address -1(%esi), so we have to deal with len=0}
  392. je .LCmpbyteExit
  393. cmpl $7,%eax {<7 not worth aligning and go through all trouble}
  394. jl .LCmpbyte2
  395. movl %edi,%ecx { Align on 32bits }
  396. negl %ecx { calc bytes to align (%edi and 3) xor 3= -%edi and 3}
  397. andl $3,%ecx
  398. subl %ecx,%eax { Subtract from number of bytes to go}
  399. orl %ecx,%ecx
  400. rep
  401. cmpsb {The actual 32-bit Aligning}
  402. jne .LCmpbyte3
  403. movl %eax,%ecx {bytes to do, divide by 4}
  404. andl $3,%eax {remainder}
  405. shrl $2,%ecx {The actual division}
  406. orl %ecx,%ecx {Sets zero flag if ecx=0 -> no cmp}
  407. rep
  408. cmpsl
  409. je .LCmpbyte2 { All equal? then to the left over bytes}
  410. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  411. subl %eax,%esi
  412. subl %eax,%edi
  413. .LCmpbyte2:
  414. movl %eax,%ecx {bytes still to (re)scan}
  415. orl %eax,%eax {prevent disaster in case %eax=0}
  416. rep
  417. cmpsb
  418. .LCmpbyte3:
  419. movzbl -1(%esi),%ecx
  420. movzbl -1(%edi),%eax // Compare failing (or equal) position
  421. subl %ecx,%eax
  422. .LCmpbyteExit:
  423. movl saveedi,%edi
  424. movl saveesi,%esi
  425. end;
  426. {$endif FPC_SYSTEM_HAS_COMPAREBYTE}
  427. {$ifndef FPC_SYSTEM_HAS_COMPAREWORD}
  428. {$define FPC_SYSTEM_HAS_COMPAREWORD}
  429. function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler;
  430. var
  431. saveesi,saveedi,saveebx : longint;
  432. asm
  433. movl %edi,saveedi
  434. movl %esi,saveesi
  435. movl %ebx,saveebx
  436. cld
  437. {$ifdef REGCALL}
  438. movl %eax,%edi
  439. movl %edx,%esi
  440. movl %ecx,%eax
  441. {$else}
  442. movl len,%eax
  443. movl buf2,%esi { Load params}
  444. movl buf1,%edi
  445. {$endif}
  446. testl %eax,%eax {We address -2(%esi), so we have to deal with len=0}
  447. je .LCmpwordExit
  448. cmpl $5,%eax {<5 (3 bytes align + 4 bytes cmpsl = 4 words}
  449. jl .LCmpword2 { not worth aligning and go through all trouble}
  450. movl (%edi),%ebx // Compare alignment bytes.
  451. cmpl (%esi),%ebx
  452. jne .LCmpword2 // Aligning will go wrong already. Max 2 words will be scanned Branch NOW
  453. shll $1,%eax {Convert word count to bytes}
  454. movl %edi,%edx { Align comparing is already done, so simply add}
  455. negl %edx { calc bytes to align -%edi and 3}
  456. andl $3,%edx
  457. addl %edx,%esi { Skip max 3 bytes alignment}
  458. addl %edx,%edi
  459. subl %edx,%eax { Subtract from number of bytes to go}
  460. movl %eax,%ecx { Make copy of bytes to go}
  461. andl $3,%eax { Calc remainder (mod 4) }
  462. andl $1,%edx { %edx is 1 if array not 2-aligned, 0 otherwise}
  463. shrl $2,%ecx { divide bytes to go by 4, DWords to go}
  464. orl %ecx,%ecx { Sets zero flag if ecx=0 -> no cmp}
  465. rep { Compare entire DWords}
  466. cmpsl
  467. je .LCmpword2a { All equal? then to the left over bytes}
  468. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  469. subl %eax,%esi { Go back one DWord}
  470. subl %eax,%edi
  471. incl %eax {if not odd then this does nothing, else it makes
  472. sure that adding %edx increases from 2 to 3 words}
  473. .LCmpword2a:
  474. subl %edx,%esi { Subtract alignment}
  475. subl %edx,%edi
  476. addl %edx,%eax
  477. shrl $1,%eax
  478. .LCmpword2:
  479. movl %eax,%ecx {words still to (re)scan}
  480. orl %eax,%eax {prevent disaster in case %eax=0}
  481. rep
  482. cmpsw
  483. .LCmpword3:
  484. movzwl -2(%esi),%ecx
  485. movzwl -2(%edi),%eax // Compare failing (or equal) position
  486. subl %ecx,%eax // calculate end result.
  487. .LCmpwordExit:
  488. movl saveedi,%edi
  489. movl saveesi,%esi
  490. movl saveebx,%ebx
  491. end;
  492. {$endif FPC_SYSTEM_HAS_COMPAREWORD}
  493. {$ifndef FPC_SYSTEM_HAS_COMPAREDWORD}
  494. {$define FPC_SYSTEM_HAS_COMPAREDWORD}
  495. function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler;
  496. var
  497. saveesi,saveedi,saveebx : longint;
  498. asm
  499. movl %edi,saveedi
  500. movl %esi,saveesi
  501. cld
  502. {$ifdef REGCALL}
  503. movl %eax,%edi
  504. movl %edx,%esi
  505. {$else}
  506. movl len,%ecx
  507. movl buf2,%esi { Load params}
  508. movl buf1,%edi
  509. {$endif}
  510. testl %ecx,%ecx
  511. je .LCmpDwordExit
  512. xorl %eax,%eax
  513. rep { Compare entire DWords}
  514. cmpsl
  515. movl -4(%edi),%edi // Compare failing (or equal) position
  516. subl -4(%esi),%edi // calculate end result.
  517. setb %dl
  518. seta %cl
  519. addb %cl,%al
  520. subb %dl,%al
  521. movsbl %al,%eax
  522. .LCmpDwordExit:
  523. movl saveedi,%edi
  524. movl saveesi,%esi
  525. end;
  526. {$endif FPC_SYSTEM_HAS_COMPAREDWORD}
  527. {$ifndef FPC_SYSTEM_HAS_INDEXCHAR0}
  528. {$define FPC_SYSTEM_HAS_INDEXCHAR0}
  529. function IndexChar0(Const buf;len:SizeInt;b:Char):SizeInt; assembler;
  530. var
  531. saveesi,saveebx : longint;
  532. asm
  533. movl %esi,saveesi
  534. movl %ebx,saveebx
  535. // Can't use scasb, or will have to do it twice, think this
  536. // is faster for small "len"
  537. {$ifdef REGCALL}
  538. movl %eax,%esi // Load address
  539. movzbl %cl,%ebx // Load searchpattern
  540. {$else}
  541. movl Buf,%esi // Load address
  542. movl len,%edx // load maximal searchdistance
  543. movzbl b,%ebx // Load searchpattern
  544. {$endif}
  545. testl %edx,%edx
  546. je .LFound
  547. xorl %ecx,%ecx // zero index in Buf
  548. xorl %eax,%eax // To make DWord compares possible
  549. .LLoop:
  550. movb (%esi),%al // Load byte
  551. cmpb %al,%bl
  552. je .LFound // byte the same?
  553. incl %ecx
  554. incl %esi
  555. cmpl %edx,%ecx // Maximal distance reached?
  556. je .LNotFound
  557. testl %eax,%eax // Nullchar = end of search?
  558. jne .LLoop
  559. .LNotFound:
  560. movl $-1,%ecx // Not found return -1
  561. .LFound:
  562. movl %ecx,%eax
  563. movl saveesi,%esi
  564. movl saveebx,%ebx
  565. end;
  566. {$endif FPC_SYSTEM_HAS_INDEXCHAR0}
  567. {****************************************************************************
  568. String
  569. ****************************************************************************}
  570. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  571. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  572. function fpc_shortstr_to_shortstr(len:longint; const sstr: shortstring): shortstring; [public,alias: 'FPC_SHORTSTR_TO_SHORTSTR']; compilerproc;
  573. begin
  574. asm
  575. cld
  576. movl __RESULT,%edi
  577. movl sstr,%esi
  578. xorl %eax,%eax
  579. movl len,%ecx
  580. lodsb
  581. cmpl %ecx,%eax
  582. jbe .LStrCopy1
  583. movl %ecx,%eax
  584. .LStrCopy1:
  585. stosb
  586. cmpl $7,%eax
  587. jl .LStrCopy2
  588. movl %edi,%ecx { Align on 32bits }
  589. negl %ecx
  590. andl $3,%ecx
  591. subl %ecx,%eax
  592. rep
  593. movsb
  594. movl %eax,%ecx
  595. andl $3,%eax
  596. shrl $2,%ecx
  597. rep
  598. movsl
  599. .LStrCopy2:
  600. movl %eax,%ecx
  601. rep
  602. movsb
  603. end ['ESI','EDI','EAX','ECX'];
  604. end;
  605. procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN'];
  606. begin
  607. asm
  608. pushl %eax
  609. pushl %ecx
  610. cld
  611. movl dstr,%edi
  612. movl sstr,%esi
  613. xorl %eax,%eax
  614. movl len,%ecx
  615. lodsb
  616. cmpl %ecx,%eax
  617. jbe .LStrCopy1
  618. movl %ecx,%eax
  619. .LStrCopy1:
  620. stosb
  621. cmpl $7,%eax
  622. jl .LStrCopy2
  623. movl %edi,%ecx { Align on 32bits }
  624. negl %ecx
  625. andl $3,%ecx
  626. subl %ecx,%eax
  627. rep
  628. movsb
  629. movl %eax,%ecx
  630. andl $3,%eax
  631. shrl $2,%ecx
  632. rep
  633. movsl
  634. .LStrCopy2:
  635. movl %eax,%ecx
  636. rep
  637. movsb
  638. popl %ecx
  639. popl %eax
  640. end ['ESI','EDI'];
  641. end;
  642. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  643. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  644. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  645. function fpc_shortstr_concat(const s1,s2:shortstring):shortstring;compilerproc;
  646. begin
  647. asm
  648. movl __RESULT,%edi
  649. movl %edi,%ebx
  650. movl s1,%esi { first string }
  651. lodsb
  652. andl $0x0ff,%eax
  653. stosb
  654. cmpl $7,%eax
  655. jl .LStrConcat1
  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. .LStrConcat1:
  668. movl %eax,%ecx
  669. rep
  670. movsb
  671. movl s2,%esi { second string }
  672. movzbl (%ebx),%ecx
  673. negl %ecx
  674. addl $0x0ff,%ecx
  675. lodsb
  676. cmpl %ecx,%eax
  677. jbe .LStrConcat2
  678. movl %ecx,%eax
  679. .LStrConcat2:
  680. addb %al,(%ebx)
  681. cmpl $7,%eax
  682. jl .LStrConcat3
  683. movl %edi,%ecx { Align on 32bits }
  684. negl %ecx
  685. andl $3,%ecx
  686. subl %ecx,%eax
  687. rep
  688. movsb
  689. movl %eax,%ecx
  690. andl $3,%eax
  691. shrl $2,%ecx
  692. rep
  693. movsl
  694. .LStrConcat3:
  695. movl %eax,%ecx
  696. rep
  697. movsb
  698. end ['EBX','ECX','EAX','ESI','EDI'];
  699. end;
  700. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  701. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  702. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  703. procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring);compilerproc;
  704. [public,alias:'FPC_SHORTSTR_APPEND_SHORTSTR'];
  705. begin
  706. asm
  707. movl s1,%edi
  708. movl s2,%esi
  709. movl %edi,%ebx
  710. movzbl (%edi),%ecx
  711. movl __HIGH(s1),%eax
  712. lea 1(%edi,%ecx),%edi
  713. negl %ecx
  714. addl %eax,%ecx
  715. // no need to zero eax, high(s1) <= 255
  716. lodsb
  717. cmpl %ecx,%eax
  718. jbe .LStrConcat1
  719. movl %ecx,%eax
  720. .LStrConcat1:
  721. addb %al,(%ebx)
  722. cmpl $7,%eax
  723. jl .LStrConcat2
  724. movl %edi,%ecx { Align on 32bits }
  725. negl %ecx
  726. andl $3,%ecx
  727. subl %ecx,%eax
  728. rep
  729. movsb
  730. movl %eax,%ecx
  731. andl $3,%eax
  732. shrl $2,%ecx
  733. rep
  734. movsl
  735. .LStrConcat2:
  736. movl %eax,%ecx
  737. rep
  738. movsb
  739. end ['EBX','ECX','EAX','ESI','EDI'];
  740. end;
  741. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  742. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  743. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  744. function fpc_shortstr_compare(const left,right:shortstring): longint;assembler; [public,alias:'FPC_SHORTSTR_COMPARE']; compilerproc;
  745. var
  746. saveesi,saveedi,saveebx : longint;
  747. asm
  748. movl %edi,saveedi
  749. movl %esi,saveesi
  750. movl %ebx,saveebx
  751. cld
  752. movl right,%esi
  753. movl left,%edi
  754. movzbl (%esi),%eax
  755. movzbl (%edi),%ebx
  756. movl %eax,%edx
  757. incl %esi
  758. incl %edi
  759. cmpl %ebx,%eax
  760. jbe .LStrCmp1
  761. movl %ebx,%eax
  762. .LStrCmp1:
  763. cmpl $7,%eax
  764. jl .LStrCmp2
  765. movl %edi,%ecx { Align on 32bits }
  766. negl %ecx
  767. andl $3,%ecx
  768. subl %ecx,%eax
  769. orl %ecx,%ecx
  770. rep
  771. cmpsb
  772. jne .LStrCmp3
  773. movl %eax,%ecx
  774. andl $3,%eax
  775. shrl $2,%ecx
  776. orl %ecx,%ecx
  777. rep
  778. cmpsl
  779. je .LStrCmp2
  780. movl $4,%eax
  781. subl %eax,%esi
  782. subl %eax,%edi
  783. .LStrCmp2:
  784. movl %eax,%ecx
  785. orl %eax,%eax
  786. rep
  787. cmpsb
  788. je .LStrCmp4
  789. .LStrCmp3:
  790. movzbl -1(%esi),%edx // Compare failing (or equal) position
  791. movzbl -1(%edi),%ebx
  792. .LStrCmp4:
  793. movl %ebx,%eax // Compare length or position
  794. subl %edx,%eax
  795. movl saveedi,%edi
  796. movl saveesi,%esi
  797. movl saveebx,%ebx
  798. end;
  799. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  800. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  801. {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  802. function fpc_pchar_to_shortstr(p:pchar):shortstring;assembler;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; compilerproc;
  803. {$include strpas.inc}
  804. {$endif FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  805. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  806. {$define FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  807. function fpc_pchar_length(p:pchar):longint;assembler;[public,alias:'FPC_PCHAR_LENGTH']; compilerproc;
  808. {$include strlen.inc}
  809. {$endif FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  810. {$define FPC_SYSTEM_HAS_GET_FRAME}
  811. function get_frame:pointer;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  812. asm
  813. movl %ebp,%eax
  814. end ['EAX'];
  815. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  816. function get_caller_addr(framebp:pointer):pointer;nostackframe;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  817. asm
  818. {$ifndef REGCALL}
  819. movl framebp,%eax
  820. {$endif}
  821. orl %eax,%eax
  822. jz .Lg_a_null
  823. movl 4(%eax),%eax
  824. .Lg_a_null:
  825. end ['EAX'];
  826. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  827. function get_caller_frame(framebp:pointer):pointer;nostackframe;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  828. asm
  829. {$ifndef REGCALL}
  830. movl framebp,%eax
  831. {$endif}
  832. orl %eax,%eax
  833. jz .Lgnf_null
  834. movl (%eax),%eax
  835. .Lgnf_null:
  836. end ['EAX'];
  837. {****************************************************************************
  838. Math
  839. ****************************************************************************}
  840. {$define FPC_SYSTEM_HAS_ABS_LONGINT}
  841. function abs(l:longint):longint; assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  842. asm
  843. {$ifndef REGCALL}
  844. movl l,%eax
  845. {$endif}
  846. cltd
  847. xorl %edx,%eax
  848. subl %edx,%eax
  849. end ['EAX','EDX'];
  850. {$define FPC_SYSTEM_HAS_ODD_LONGINT}
  851. function odd(l:longint):boolean;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  852. asm
  853. {$ifdef SYSTEMINLINE}
  854. movl l,%eax
  855. {$else}
  856. {$ifndef REGCALL}
  857. movl l,%eax
  858. {$endif}
  859. {$endif}
  860. andl $1,%eax
  861. setnz %al
  862. end ['EAX'];
  863. {$define FPC_SYSTEM_HAS_SQR_LONGINT}
  864. function sqr(l:longint):longint;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  865. asm
  866. {$ifdef SYSTEMINLINE}
  867. movl l,%eax
  868. {$else}
  869. {$ifndef REGCALL}
  870. movl l,%eax
  871. {$endif}
  872. {$endif}
  873. imull %eax,%eax
  874. end ['EAX'];
  875. {$define FPC_SYSTEM_HAS_SPTR}
  876. Function Sptr : Pointer;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  877. asm
  878. movl %esp,%eax
  879. end;
  880. {****************************************************************************
  881. Bounds Check
  882. ****************************************************************************}
  883. { do a thread-safe inc/dec }
  884. {$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  885. function cpudeclocked(var l : longint) : boolean;assembler;nostackframe;
  886. asm
  887. {$ifndef REGCALL}
  888. movl l,%eax
  889. {$endif}
  890. { this check should be done because a lock takes a lot }
  891. { of time! }
  892. lock
  893. decl (%eax)
  894. setzb %al
  895. end;
  896. {$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  897. procedure cpuinclocked(var l : longint);assembler;nostackframe;
  898. asm
  899. {$ifndef REGCALL}
  900. movl l,%eax
  901. {$endif}
  902. lock
  903. incl (%eax)
  904. end;
  905. // inline SMP check and normal lock.
  906. // the locked one is so slow, inlining doesn't matter.
  907. function declocked(var l : longint) : boolean; inline;
  908. begin
  909. if not ismultithread then
  910. begin
  911. dec(l);
  912. declocked:=l=0;
  913. end
  914. else
  915. declocked:=cpudeclocked(l);
  916. end;
  917. procedure inclocked(var l : longint); inline;
  918. begin
  919. if not ismultithread then
  920. inc(l)
  921. else
  922. cpuinclocked(l);
  923. end;
  924. {****************************************************************************
  925. FPU
  926. ****************************************************************************}
  927. const
  928. fpucw : word = $1332;
  929. { Internal constants for use in system unit }
  930. FPU_Invalid = 1;
  931. FPU_Denormal = 2;
  932. FPU_DivisionByZero = 4;
  933. FPU_Overflow = 8;
  934. FPU_Underflow = $10;
  935. FPU_StackUnderflow = $20;
  936. FPU_StackOverflow = $40;
  937. FPU_ExceptionMask = $ff;
  938. {$define FPC_SYSTEM_HAS_SYSRESETFPU}
  939. Procedure SysResetFPU;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  940. asm
  941. fninit
  942. fldcw fpucw
  943. fwait
  944. end;
  945. {$define FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
  946. function fpc_freemem_x(p:pointer):ptrint; [external name 'FPC_FREEMEM_X'];
  947. Procedure fpc_AnsiStr_Decr_Ref (Var S : Pointer); [Public,Alias:'FPC_ANSISTR_DECR_REF']; compilerproc; nostackframe; assembler;
  948. asm
  949. cmpl $0,(%eax)
  950. jne .Ldecr_ref_continue
  951. ret
  952. .Ldecr_ref_continue:
  953. // Temps allocated between ebp-24 and ebp+0
  954. subl $4,%esp
  955. // Var S located in register
  956. // Var l located in register
  957. movl %eax,(%esp)
  958. // [101] l:=@PAnsiRec(S-FirstOff)^.Ref;
  959. movl (%eax),%edx
  960. subl $8,%edx
  961. // [102] If l^<0 then exit;
  962. cmpl $0,(%edx)
  963. jl .Lj3596
  964. .Lj3603:
  965. // [104] If declocked(l^) then
  966. cmpb $0,ismultithread
  967. jne .Lj3610
  968. decl (%edx)
  969. je .Lj3620
  970. addl $4,%esp
  971. ret
  972. .Lj3610:
  973. movl %edx,%eax
  974. call cpudeclocked
  975. testb %al,%al
  976. je .Lj3605
  977. .Lj3620:
  978. movl (%esp),%eax
  979. movl (%eax),%eax
  980. subl $8,%eax
  981. call FPC_FREEMEM_X
  982. movl (%esp),%eax
  983. movl $0,(%eax)
  984. .Lj3618:
  985. .Lj3605:
  986. .Lj3596:
  987. // [107] end;
  988. addl $4,%esp
  989. end;
  990. function fpc_truely_ansistr_unique(Var S : Pointer): Pointer; forward;
  991. {$define FPC_SYSTEM_HAS_ANSISTR_UNIQUE}
  992. Function fpc_ansistr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_ANSISTR_UNIQUE']; compilerproc; nostackframe;assembler;
  993. asm
  994. // Var S located in register
  995. // Var $result located in register
  996. movl %eax,%edx
  997. // [437] pointer(result) := pointer(s);
  998. movl (%eax),%eax
  999. // [438] If Pointer(S)=Nil then
  1000. testl %eax,%eax
  1001. je .Lj4031
  1002. .Lj4036:
  1003. // [440] if PAnsiRec(Pointer(S)-Firstoff)^.Ref<>1 then
  1004. movl -8(%eax),%ecx
  1005. cmpl $1,%ecx
  1006. je .Lj4038
  1007. // [441] result:=fpc_truely_ansistr_unique(s);
  1008. movl %edx,%eax
  1009. call fpc_truely_ansistr_unique
  1010. .Lj4038:
  1011. .Lj4031:
  1012. // [442] end;
  1013. end;