i386.inc 42 KB

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