i386.inc 41 KB

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