i386.inc 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team.
  5. Processor dependent implementation for the system unit for
  6. intel i386+
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. {****************************************************************************
  14. Primitives
  15. ****************************************************************************}
  16. var
  17. has_sse_support,has_mmx_support : boolean;
  18. {$asmmode intel}
  19. function cpuid_support : boolean;assembler;
  20. {
  21. Check if the ID-flag can be changed, if changed then CpuID is supported.
  22. Tested under go32v1 and Linux on c6x86 with CpuID enabled and disabled (PFV)
  23. }
  24. asm
  25. pushf
  26. pushf
  27. pop eax
  28. mov ebx,eax
  29. xor eax,200000h
  30. push eax
  31. popf
  32. pushf
  33. pop eax
  34. popf
  35. and eax,200000h
  36. and ebx,200000h
  37. cmp eax,ebx
  38. setnz al
  39. end;
  40. {$asmmode ATT}
  41. function sse_support : boolean;
  42. var
  43. _edx : longint;
  44. begin
  45. if cpuid_support then
  46. begin
  47. asm
  48. movl $1,%eax
  49. cpuid
  50. movl %edx,_edx
  51. end;
  52. sse_support:=(_edx and $2000000)<>0;
  53. end
  54. else
  55. { a cpu with without cpuid instruction supports never sse }
  56. sse_support:=false;
  57. end;
  58. { returns true, if the processor supports the mmx instructions }
  59. function mmx_support : boolean;
  60. var
  61. _edx : longint;
  62. begin
  63. if cpuid_support then
  64. begin
  65. asm
  66. movl $1,%eax
  67. cpuid
  68. movl %edx,_edx
  69. end;
  70. mmx_support:=(_edx and $800000)<>0;
  71. end
  72. else
  73. { a cpu with without cpuid instruction supports never mmx }
  74. mmx_support:=false;
  75. end;
  76. {$i fastmove.inc}
  77. procedure fpc_cpuinit;
  78. begin
  79. has_sse_support:=sse_support;
  80. has_mmx_support:=mmx_support;
  81. setup_fastmove;
  82. end;
  83. function geteipasebx : pointer;assembler;[public,alias:'FPC_GETEIPINEBX'];
  84. asm
  85. movl (%esp),%ebx
  86. ret
  87. end;
  88. {$ifndef FPC_SYSTEM_HAS_MOVE}
  89. {$define FPC_SYSTEM_HAS_MOVE}
  90. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE'];assembler;
  91. var
  92. saveesi,saveedi : longint;
  93. asm
  94. movl %edi,saveedi
  95. movl %esi,saveesi
  96. {$ifdef REGCALL}
  97. movl %eax,%esi
  98. movl %edx,%edi
  99. movl %ecx,%edx
  100. {$else}
  101. movl dest,%edi
  102. movl source,%esi
  103. movl count,%edx
  104. {$endif}
  105. movl %edi,%eax
  106. { check for zero or negative count }
  107. cmpl $0,%edx
  108. jle .LMoveEnd
  109. { Check for back or forward }
  110. sub %esi,%eax
  111. jz .LMoveEnd { Do nothing when source=dest }
  112. jc .LFMove { Do forward, dest<source }
  113. cmp %edx,%eax
  114. jb .LBMove { Dest is in range of move, do backward }
  115. { Forward Copy }
  116. .LFMove:
  117. cld
  118. cmpl $15,%edx
  119. jl .LFMove1
  120. movl %edi,%ecx { Align on 32bits }
  121. negl %ecx
  122. andl $3,%ecx
  123. subl %ecx,%edx
  124. rep
  125. movsb
  126. movl %edx,%ecx
  127. andl $3,%edx
  128. shrl $2,%ecx
  129. rep
  130. movsl
  131. .LFMove1:
  132. movl %edx,%ecx
  133. rep
  134. movsb
  135. jmp .LMoveEnd
  136. { Backward Copy }
  137. .LBMove:
  138. std
  139. addl %edx,%esi
  140. addl %edx,%edi
  141. movl %edi,%ecx
  142. decl %esi
  143. decl %edi
  144. cmpl $15,%edx
  145. jl .LBMove1
  146. negl %ecx { Align on 32bits }
  147. andl $3,%ecx
  148. subl %ecx,%edx
  149. rep
  150. movsb
  151. movl %edx,%ecx
  152. andl $3,%edx
  153. shrl $2,%ecx
  154. subl $3,%esi
  155. subl $3,%edi
  156. rep
  157. movsl
  158. addl $3,%esi
  159. addl $3,%edi
  160. .LBMove1:
  161. movl %edx,%ecx
  162. rep
  163. movsb
  164. cld
  165. .LMoveEnd:
  166. movl saveedi,%edi
  167. movl saveesi,%esi
  168. end;
  169. {$endif FPC_SYSTEM_HAS_MOVE}
  170. {$ifndef FPC_SYSTEM_HAS_FILLCHAR}
  171. {$define FPC_SYSTEM_HAS_FILLCHAR}
  172. Procedure FillChar(var x;count:SizeInt;value:byte);assembler;
  173. asm
  174. {A push is prefered over a local variable because a local
  175. variable causes the compiler to generate a stackframe.}
  176. cld
  177. {$ifdef REGCALL}
  178. push %edi
  179. movl %eax,%edi
  180. movzbl %cl,%eax
  181. movl %edx,%ecx
  182. {$else}
  183. movl x,%edi
  184. movl count,%ecx
  185. movzbl value,%eax
  186. movl %ecx,%edx
  187. {$endif}
  188. { check for zero or negative count }
  189. or %ecx,%ecx
  190. jle .LFillEnd
  191. cmpl $7,%ecx
  192. jl .LFill1
  193. imul $0x01010101,%eax { Expand al into a 4 subbytes of eax}
  194. shrl $2,%ecx
  195. andl $3,%edx
  196. rep
  197. stosl
  198. movl %edx,%ecx
  199. .LFill1:
  200. rep
  201. stosb
  202. .LFillEnd:
  203. {$ifdef REGCALL}
  204. pop %edi
  205. {$endif}
  206. end;
  207. {$endif FPC_SYSTEM_HAS_FILLCHAR}
  208. {$ifndef FPC_SYSTEM_HAS_FILLWORD}
  209. {$define FPC_SYSTEM_HAS_FILLWORD}
  210. procedure fillword(var x;count : SizeInt;value : word);assembler;
  211. var
  212. saveedi : longint;
  213. asm
  214. movl %edi,saveedi
  215. {$ifdef REGCALL}
  216. movl %eax,%edi
  217. movzwl %cx,%eax
  218. movl %edx,%ecx
  219. {$else}
  220. movl x,%edi
  221. movl count,%ecx
  222. movzwl value,%eax
  223. {$endif}
  224. { check for zero or negative count }
  225. cmpl $0,%ecx
  226. jle .LFillWordEnd
  227. movl %eax,%edx
  228. shll $16,%eax
  229. orl %edx,%eax
  230. movl %ecx,%edx
  231. shrl $1,%ecx
  232. cld
  233. rep
  234. stosl
  235. movl %edx,%ecx
  236. andl $1,%ecx
  237. rep
  238. stosw
  239. .LFillWordEnd:
  240. movl saveedi,%edi
  241. end;
  242. {$endif FPC_SYSTEM_HAS_FILLWORD}
  243. {$ifndef FPC_SYSTEM_HAS_FILLDWORD}
  244. {$define FPC_SYSTEM_HAS_FILLDWORD}
  245. procedure filldword(var x;count : SizeInt;value : dword);assembler;
  246. var
  247. saveedi : longint;
  248. asm
  249. movl %edi,saveedi
  250. {$ifdef REGCALL}
  251. movl %eax,%edi
  252. movl %ecx,%eax
  253. movl %edx,%ecx
  254. {$else}
  255. movl x,%edi
  256. movl count,%ecx
  257. movl value,%eax
  258. {$endif}
  259. { check for zero or negative count }
  260. cmpl $0,%ecx
  261. jle .LFillDWordEnd
  262. cld
  263. rep
  264. stosl
  265. .LFillDWordEnd:
  266. movl saveedi,%edi
  267. end;
  268. {$endif FPC_SYSTEM_HAS_FILLDWORD}
  269. {$ifndef FPC_SYSTEM_HAS_INDEXBYTE}
  270. {$define FPC_SYSTEM_HAS_INDEXBYTE}
  271. function IndexByte(Const buf;len:SizeInt;b:byte):SizeInt; assembler;
  272. var
  273. saveedi,saveebx : longint;
  274. asm
  275. movl %edi,saveedi
  276. movl %ebx,saveebx
  277. movl buf,%edi // Load String
  278. movb b,%bl
  279. movl len,%ecx // Load len
  280. xorl %eax,%eax
  281. testl %ecx,%ecx
  282. jz .Lcharposnotfound
  283. cld
  284. movl %ecx,%edx // Copy for easy manipulation
  285. movb %bl,%al
  286. repne
  287. scasb
  288. jne .Lcharposnotfound
  289. incl %ecx
  290. subl %ecx,%edx
  291. movl %edx,%eax
  292. jmp .Lready
  293. .Lcharposnotfound:
  294. movl $-1,%eax
  295. .Lready:
  296. movl saveedi,%edi
  297. movl saveebx,%ebx
  298. end;
  299. {$endif FPC_SYSTEM_HAS_FILLDWORD}
  300. {$ifndef FPC_SYSTEM_HAS_INDEXWORD}
  301. {$define FPC_SYSTEM_HAS_INDEXWORD}
  302. function Indexword(Const buf;len:SizeInt;b:word):SizeInt; assembler;
  303. var
  304. saveedi,saveebx : longint;
  305. asm
  306. movl %edi,saveedi
  307. movl %ebx,saveebx
  308. movl Buf,%edi // Load String
  309. movw b,%bx
  310. movl Len,%ecx // Load len
  311. xorl %eax,%eax
  312. testl %ecx,%ecx
  313. jz .Lcharposnotfound
  314. cld
  315. movl %ecx,%edx // Copy for easy manipulation
  316. movw %bx,%ax
  317. repne
  318. scasw
  319. jne .Lcharposnotfound
  320. incl %ecx
  321. subl %ecx,%edx
  322. movl %edx,%eax
  323. jmp .Lready
  324. .Lcharposnotfound:
  325. movl $-1,%eax
  326. .Lready:
  327. movl saveedi,%edi
  328. movl saveebx,%ebx
  329. end;
  330. {$endif FPC_SYSTEM_HAS_INDEXWORD}
  331. {$ifndef FPC_SYSTEM_HAS_INDEXDWORD}
  332. {$define FPC_SYSTEM_HAS_INDEXDWORD}
  333. function IndexDWord(Const buf;len:SizeInt;b:DWord):SizeInt; assembler;
  334. var
  335. saveedi,saveebx : longint;
  336. asm
  337. movl %edi,saveedi
  338. movl %ebx,saveebx
  339. {$ifdef REGCALL}
  340. movl %eax,%edi
  341. movl %ecx,%ebx
  342. movl %edx,%ecx
  343. {$else}
  344. movl Len,%ecx // Load len
  345. movl Buf,%edi // Load String
  346. movl b,%ebx
  347. {$endif}
  348. xorl %eax,%eax
  349. testl %ecx,%ecx
  350. jz .Lcharposnotfound
  351. cld
  352. movl %ecx,%edx // Copy for easy manipulation
  353. movl %ebx,%eax
  354. repne
  355. scasl
  356. jne .Lcharposnotfound
  357. incl %ecx
  358. subl %ecx,%edx
  359. movl %edx,%eax
  360. jmp .Lready
  361. .Lcharposnotfound:
  362. movl $-1,%eax
  363. .Lready:
  364. movl saveedi,%edi
  365. movl saveebx,%ebx
  366. end;
  367. {$endif FPC_SYSTEM_HAS_INDEXDWORD}
  368. {$ifndef FPC_SYSTEM_HAS_COMPAREBYTE}
  369. {$define FPC_SYSTEM_HAS_COMPAREBYTE}
  370. function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt; assembler;
  371. var
  372. saveesi,saveedi : longint;
  373. asm
  374. movl %edi,saveedi
  375. movl %esi,saveesi
  376. cld
  377. {$ifdef REGCALL}
  378. movl %eax,%edi
  379. movl %edx,%esi
  380. movl %ecx,%eax
  381. {$else}
  382. movl len,%eax
  383. movl buf2,%esi { Load params}
  384. movl buf1,%edi
  385. {$endif}
  386. testl %eax,%eax {We address -1(%esi), so we have to deal with len=0}
  387. je .LCmpbyteExit
  388. cmpl $7,%eax {<7 not worth aligning and go through all trouble}
  389. jl .LCmpbyte2
  390. movl %edi,%ecx { Align on 32bits }
  391. negl %ecx { calc bytes to align (%edi and 3) xor 3= -%edi and 3}
  392. andl $3,%ecx
  393. subl %ecx,%eax { Subtract from number of bytes to go}
  394. orl %ecx,%ecx
  395. rep
  396. cmpsb {The actual 32-bit Aligning}
  397. jne .LCmpbyte3
  398. movl %eax,%ecx {bytes to do, divide by 4}
  399. andl $3,%eax {remainder}
  400. shrl $2,%ecx {The actual division}
  401. orl %ecx,%ecx {Sets zero flag if ecx=0 -> no cmp}
  402. rep
  403. cmpsl
  404. je .LCmpbyte2 { All equal? then to the left over bytes}
  405. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  406. subl %eax,%esi
  407. subl %eax,%edi
  408. .LCmpbyte2:
  409. movl %eax,%ecx {bytes still to (re)scan}
  410. orl %eax,%eax {prevent disaster in case %eax=0}
  411. rep
  412. cmpsb
  413. .LCmpbyte3:
  414. movzbl -1(%esi),%ecx
  415. movzbl -1(%edi),%eax // Compare failing (or equal) position
  416. subl %ecx,%eax
  417. .LCmpbyteExit:
  418. movl saveedi,%edi
  419. movl saveesi,%esi
  420. end;
  421. {$endif FPC_SYSTEM_HAS_COMPAREBYTE}
  422. {$ifndef FPC_SYSTEM_HAS_COMPAREWORD}
  423. {$define FPC_SYSTEM_HAS_COMPAREWORD}
  424. function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler;
  425. var
  426. saveesi,saveedi,saveebx : longint;
  427. asm
  428. movl %edi,saveedi
  429. movl %esi,saveesi
  430. movl %ebx,saveebx
  431. cld
  432. {$ifdef REGCALL}
  433. movl %eax,%edi
  434. movl %edx,%esi
  435. movl %ecx,%eax
  436. {$else}
  437. movl len,%eax
  438. movl buf2,%esi { Load params}
  439. movl buf1,%edi
  440. {$endif}
  441. testl %eax,%eax {We address -2(%esi), so we have to deal with len=0}
  442. je .LCmpwordExit
  443. cmpl $5,%eax {<5 (3 bytes align + 4 bytes cmpsl = 4 words}
  444. jl .LCmpword2 { not worth aligning and go through all trouble}
  445. movl (%edi),%ebx // Compare alignment bytes.
  446. cmpl (%esi),%ebx
  447. jne .LCmpword2 // Aligning will go wrong already. Max 2 words will be scanned Branch NOW
  448. shll $1,%eax {Convert word count to bytes}
  449. movl %edi,%edx { Align comparing is already done, so simply add}
  450. negl %edx { calc bytes to align -%edi and 3}
  451. andl $3,%edx
  452. addl %edx,%esi { Skip max 3 bytes alignment}
  453. addl %edx,%edi
  454. subl %edx,%eax { Subtract from number of bytes to go}
  455. movl %eax,%ecx { Make copy of bytes to go}
  456. andl $3,%eax { Calc remainder (mod 4) }
  457. andl $1,%edx { %edx is 1 if array not 2-aligned, 0 otherwise}
  458. shrl $2,%ecx { divide bytes to go by 4, DWords to go}
  459. orl %ecx,%ecx { Sets zero flag if ecx=0 -> no cmp}
  460. rep { Compare entire DWords}
  461. cmpsl
  462. je .LCmpword2a { All equal? then to the left over bytes}
  463. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  464. subl %eax,%esi { Go back one DWord}
  465. subl %eax,%edi
  466. incl %eax {if not odd then this does nothing, else it makes
  467. sure that adding %edx increases from 2 to 3 words}
  468. .LCmpword2a:
  469. subl %edx,%esi { Subtract alignment}
  470. subl %edx,%edi
  471. addl %edx,%eax
  472. shrl $1,%eax
  473. .LCmpword2:
  474. movl %eax,%ecx {words still to (re)scan}
  475. orl %eax,%eax {prevent disaster in case %eax=0}
  476. rep
  477. cmpsw
  478. .LCmpword3:
  479. movzwl -2(%esi),%ecx
  480. movzwl -2(%edi),%eax // Compare failing (or equal) position
  481. subl %ecx,%eax // calculate end result.
  482. .LCmpwordExit:
  483. movl saveedi,%edi
  484. movl saveesi,%esi
  485. movl saveebx,%ebx
  486. end;
  487. {$endif FPC_SYSTEM_HAS_COMPAREWORD}
  488. {$ifndef FPC_SYSTEM_HAS_COMPAREDWORD}
  489. {$define FPC_SYSTEM_HAS_COMPAREDWORD}
  490. function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler;
  491. var
  492. saveesi,saveedi,saveebx : longint;
  493. asm
  494. movl %edi,saveedi
  495. movl %esi,saveesi
  496. movl %ebx,saveebx
  497. cld
  498. {$ifdef REGCALL}
  499. movl %eax,%edi
  500. movl %edx,%esi
  501. movl %ecx,%eax
  502. {$else}
  503. movl len,%eax
  504. movl buf2,%esi { Load params}
  505. movl buf1,%edi
  506. {$endif}
  507. testl %eax,%eax {We address -2(%esi), so we have to deal with len=0}
  508. je .LCmpDwordExit
  509. cmpl $3,%eax {<3 (3 bytes align + 4 bytes cmpsl) = 2 DWords}
  510. jl .LCmpDword2 { not worth aligning and go through all trouble}
  511. movl (%edi),%ebx // Compare alignment bytes.
  512. cmpl (%esi),%ebx
  513. jne .LCmpDword2 // Aligning will go wrong already. Max 2 words will be scanned Branch NOW
  514. shll $2,%eax {Convert word count to bytes}
  515. movl %edi,%edx { Align comparing is already done, so simply add}
  516. negl %edx { calc bytes to align -%edi and 3}
  517. andl $3,%edx
  518. addl %edx,%esi { Skip max 3 bytes alignment}
  519. addl %edx,%edi
  520. subl %edx,%eax { Subtract from number of bytes to go}
  521. movl %eax,%ecx { Make copy of bytes to go}
  522. andl $3,%eax { Calc remainder (mod 4) }
  523. shrl $2,%ecx { divide bytes to go by 4, DWords to go}
  524. orl %ecx,%ecx { Sets zero flag if ecx=0 -> no cmp}
  525. rep { Compare entire DWords}
  526. cmpsl
  527. je .LCmpDword2a { All equal? then to the left over bytes}
  528. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  529. subl %eax,%esi { Go back one DWord}
  530. subl %eax,%edi
  531. addl $3,%eax {if align<>0 this causes repcount to be 2}
  532. .LCmpDword2a:
  533. subl %edx,%esi { Subtract alignment}
  534. subl %edx,%edi
  535. addl %edx,%eax
  536. shrl $2,%eax
  537. .LCmpDword2:
  538. movl %eax,%ecx {words still to (re)scan}
  539. orl %eax,%eax {prevent disaster in case %eax=0}
  540. rep
  541. cmpsl
  542. .LCmpDword3:
  543. movzwl -4(%esi),%ecx
  544. movzwl -4(%edi),%eax // Compare failing (or equal) position
  545. subl %ecx,%eax // calculate end result.
  546. .LCmpDwordExit:
  547. movl saveedi,%edi
  548. movl saveesi,%esi
  549. movl saveebx,%ebx
  550. end;
  551. {$endif FPC_SYSTEM_HAS_COMPAREDWORD}
  552. {$ifndef FPC_SYSTEM_HAS_INDEXCHAR0}
  553. {$define FPC_SYSTEM_HAS_INDEXCHAR0}
  554. function IndexChar0(Const buf;len:SizeInt;b:Char):SizeInt; assembler;
  555. var
  556. saveesi,saveebx : longint;
  557. asm
  558. movl %esi,saveesi
  559. movl %ebx,saveebx
  560. // Can't use scasb, or will have to do it twice, think this
  561. // is faster for small "len"
  562. {$ifdef REGCALL}
  563. movl %eax,%esi // Load address
  564. movzbl %cl,%ebx // Load searchpattern
  565. {$else}
  566. movl Buf,%esi // Load address
  567. movl len,%edx // load maximal searchdistance
  568. movzbl b,%ebx // Load searchpattern
  569. {$endif}
  570. testl %edx,%edx
  571. je .LFound
  572. xorl %ecx,%ecx // zero index in Buf
  573. xorl %eax,%eax // To make DWord compares possible
  574. .LLoop:
  575. movb (%esi),%al // Load byte
  576. cmpb %al,%bl
  577. je .LFound // byte the same?
  578. incl %ecx
  579. incl %esi
  580. cmpl %edx,%ecx // Maximal distance reached?
  581. je .LNotFound
  582. testl %eax,%eax // Nullchar = end of search?
  583. jne .LLoop
  584. .LNotFound:
  585. movl $-1,%ecx // Not found return -1
  586. .LFound:
  587. movl %ecx,%eax
  588. movl saveesi,%esi
  589. movl saveebx,%ebx
  590. end;
  591. {$endif FPC_SYSTEM_HAS_INDEXCHAR0}
  592. {****************************************************************************
  593. Object Helpers
  594. ****************************************************************************}
  595. {$ifndef HAS_GENERICCONSTRUCTOR}
  596. {$define FPC_SYSTEM_HAS_FPC_HELP_CONSTRUCTOR}
  597. procedure fpc_help_constructor; assembler; [public,alias:'FPC_HELP_CONSTRUCTOR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  598. asm
  599. { Entry without preamble, since we need the ESP of the constructor
  600. Stack (relative to %ebp):
  601. 12 Self
  602. 8 VMT-Address
  603. 4 main programm-Addr
  604. 0 %ebp
  605. edi contains the vmt position
  606. }
  607. { eax isn't touched anywhere, so it doesn't have to reloaded }
  608. movl 8(%ebp),%eax
  609. { initialise self ? }
  610. orl %esi,%esi
  611. jne .LHC_4
  612. { get memory, but save register first temporary variable }
  613. subl $4,%esp
  614. movl %esp,%esi
  615. { Save Register}
  616. pushal
  617. {$ifdef valuegetmem}
  618. { esi can be destroyed in fpc_getmem!!! (JM) }
  619. pushl %esi
  620. {$endif valuegetmem}
  621. { Memory size }
  622. pushl (%eax)
  623. {$ifdef valuegetmem}
  624. call fpc_getmem
  625. popl %esi
  626. movl %eax,(%esi)
  627. {$else valuegetmem}
  628. pushl %esi
  629. call AsmGetMem
  630. {$endif valuegetmem}
  631. movl $-1,8(%ebp)
  632. popal
  633. { Avoid 80386DX bug }
  634. nop
  635. { Memory position to %esi }
  636. movl (%esi),%esi
  637. addl $4,%esp
  638. { If no memory available : fail() }
  639. orl %esi,%esi
  640. jz .LHC_5
  641. { init self for the constructor }
  642. movl %esi,12(%ebp)
  643. { jmp not necessary anymore because next instruction is disabled (JM)
  644. jmp .LHC_6 }
  645. { Why was the VMT reset to zero here ????
  646. I need it fail to know if I should
  647. zero the VMT field in static objects PM }
  648. .LHC_4:
  649. { movl $0,8(%ebp) }
  650. .LHC_6:
  651. { is there a VMT address ? }
  652. orl %eax,%eax
  653. jnz .LHC_7
  654. { In case the constructor doesn't do anything, the Zero-Flag }
  655. { can't be put, because this calls Fail() }
  656. incl %eax
  657. ret
  658. .LHC_7:
  659. { set zero inside the object }
  660. pushal
  661. cld
  662. movl (%eax),%ecx
  663. movl %esi,%edi
  664. movl %ecx,%ebx
  665. xorl %eax,%eax
  666. shrl $2,%ecx
  667. andl $3,%ebx
  668. rep
  669. stosl
  670. movl %ebx,%ecx
  671. rep
  672. stosb
  673. popal
  674. { avoid the 80386DX bug }
  675. nop
  676. { set the VMT address for the new created object }
  677. { the offset is in %edi since the calling and has not been changed !! }
  678. movl %eax,(%esi,%edi,1)
  679. testl %eax,%eax
  680. .LHC_5:
  681. end;
  682. {$define FPC_SYSTEM_HAS_FPC_HELP_FAIL}
  683. procedure fpc_help_fail;assembler;[public,alias:'FPC_HELP_FAIL']; {$ifdef hascompilerproc} compilerproc; {$endif}
  684. { should be called with a object that needs to be
  685. freed if VMT field is at -1
  686. %edi contains VMT offset in object again }
  687. asm
  688. testl %esi,%esi
  689. je .LHF_1
  690. cmpl $-1,8(%ebp)
  691. je .LHF_2
  692. { reset vmt field to zero for static instances }
  693. cmpl $0,8(%ebp)
  694. je .LHF_3
  695. { main constructor, we can zero the VMT field now }
  696. movl $0,(%esi,%edi,1)
  697. .LHF_3:
  698. { we zero esi to indicate failure }
  699. xorl %esi,%esi
  700. jmp .LHF_1
  701. .LHF_2:
  702. { get vmt address in eax }
  703. movl (%esi,%edi,1),%eax
  704. movl %esi,12(%ebp)
  705. { push object position }
  706. {$ifdef valuefreemem}
  707. pushl %esi
  708. call fpc_freemem
  709. {$else valuefreemem}
  710. leal 12(%ebp),%eax
  711. pushl %eax
  712. call AsmFreeMem
  713. {$endif valuefreemem}
  714. { set both object places to zero }
  715. xorl %esi,%esi
  716. movl %esi,12(%ebp)
  717. .LHF_1:
  718. end;
  719. {$define FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  720. procedure fpc_help_destructor;assembler;[public,alias:'FPC_HELP_DESTRUCTOR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  721. asm
  722. { Stack (relative to %ebp):
  723. 12 Self
  724. 8 VMT-Address
  725. 4 Main program-Addr
  726. 0 %ebp
  727. edi contains the vmt position
  728. }
  729. pushal
  730. { Should the object be resolved ? }
  731. movl 8(%ebp),%eax
  732. orl %eax,%eax
  733. jz .LHD_3
  734. { Yes, get size from SELF! }
  735. movl 12(%ebp),%eax
  736. { get VMT-pointer (from Self) to %ebx }
  737. { the offset is in %edi since the calling and has not been changed !! }
  738. movl (%eax,%edi,1),%ebx
  739. { I think for precaution }
  740. { that we should clear the VMT here }
  741. movl $0,(%eax,%edi,1)
  742. {$ifdef valuefreemem}
  743. { Freemem }
  744. pushl %eax
  745. call fpc_freemem
  746. {$else valuefreemem}
  747. { temporary Variable }
  748. subl $4,%esp
  749. movl %esp,%edi
  750. { SELF }
  751. movl %eax,(%edi)
  752. pushl %edi
  753. call AsmFreeMem
  754. addl $4,%esp
  755. {$endif valuefreemem}
  756. .LHD_3:
  757. popal
  758. { avoid the 80386DX bug }
  759. nop
  760. end;
  761. {$define FPC_SYSTEM_HAS_FPC_NEW_CLASS}
  762. procedure fpc_new_class;assembler;[public,alias:'FPC_NEW_CLASS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  763. asm
  764. { to be sure in the future, we save also edit }
  765. pushl %edi
  766. { create class ? }
  767. movl 8(%ebp),%edi
  768. { if we test eax later without calling newinstance }
  769. { it must have a value <>0 }
  770. movl $1,%eax
  771. testl %edi,%edi
  772. jz .LNEW_CLASS1
  773. { save registers !! }
  774. pushl %ebx
  775. pushl %ecx
  776. pushl %edx
  777. { esi contains the vmt }
  778. pushl %esi
  779. { call newinstance (class method!) }
  780. call *52{vmtNewInstance}(%esi)
  781. popl %edx
  782. popl %ecx
  783. popl %ebx
  784. { newinstance returns a pointer to the new created }
  785. { instance in eax }
  786. { load esi and insert self }
  787. movl %eax,%esi
  788. .LNEW_CLASS1:
  789. movl %esi,8(%ebp)
  790. testl %eax,%eax
  791. popl %edi
  792. end;
  793. { Internal alias that can be reference from asm code }
  794. procedure int_dispose_class;external name 'FPC_DISPOSE_CLASS';
  795. {$define FPC_SYSTEM_HAS_FPC_DISPOSE_CLASS}
  796. procedure fpc_dispose_class;assembler;[public,alias:'FPC_DISPOSE_CLASS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  797. asm
  798. { to be sure in the future, we save also edit }
  799. pushl %edi
  800. { destroy class ? }
  801. movl 12(%ebp),%edi
  802. testl %edi,%edi
  803. jz .LDISPOSE_CLASS1
  804. { no inherited call }
  805. movl (%esi),%edi
  806. { save registers !! }
  807. pushl %eax
  808. pushl %ebx
  809. pushl %ecx
  810. pushl %edx
  811. { push self }
  812. pushl %esi
  813. { call freeinstance }
  814. call *56{vmtFreeInstance}(%edi)
  815. popl %edx
  816. popl %ecx
  817. popl %ebx
  818. popl %eax
  819. .LDISPOSE_CLASS1:
  820. popl %edi
  821. end;
  822. {$define FPC_SYSTEM_HAS_FPC_HELP_FAIL_CLASS}
  823. procedure fpc_help_fail_class;assembler;[public,alias:'FPC_HELP_FAIL_CLASS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  824. { a non zero class must allways be disposed
  825. VMT is allways at pos 0 }
  826. asm
  827. testl %esi,%esi
  828. je .LHFC_1
  829. { can't use the compilerproc version as that will generate a
  830. reference instead of a symbol }
  831. call int_dispose_class
  832. { set both object places to zero }
  833. xorl %esi,%esi
  834. movl %esi,8(%ebp)
  835. .LHFC_1:
  836. end;
  837. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  838. { we want the stack for debugging !! PM }
  839. procedure fpc_check_object(obj : pointer);[public,alias:'FPC_CHECK_OBJECT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  840. begin
  841. asm
  842. pushl %edi
  843. movl obj,%edi
  844. pushl %eax
  845. { Here we must check if the VMT pointer is nil before }
  846. { accessing it... }
  847. testl %edi,%edi
  848. jz .Lco_re
  849. movl (%edi),%eax
  850. addl 4(%edi),%eax
  851. jz .Lco_ok
  852. .Lco_re:
  853. pushl $210
  854. call HandleError
  855. .Lco_ok:
  856. popl %eax
  857. popl %edi
  858. { the adress is pushed : it needs to be removed from stack !! PM }
  859. end;{ of asm }
  860. end;
  861. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  862. procedure fpc_check_object_ext;assembler;[public,alias:'FPC_CHECK_OBJECT_EXT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  863. { checks for a correct vmt pointer }
  864. { deeper check to see if the current object is }
  865. { really related to the true }
  866. asm
  867. pushl %ebp
  868. movl %esp,%ebp
  869. pushl %edi
  870. movl 8(%ebp),%edi
  871. pushl %ebx
  872. movl 12(%ebp),%ebx
  873. pushl %eax
  874. { Here we must check if the VMT pointer is nil before }
  875. { accessing it... }
  876. .Lcoext_obj:
  877. testl %edi,%edi
  878. jz .Lcoext_re
  879. movl (%edi),%eax
  880. addl 4(%edi),%eax
  881. jnz .Lcoext_re
  882. cmpl %edi,%ebx
  883. je .Lcoext_ok
  884. .Lcoext_vmt:
  885. movl 8(%edi),%eax
  886. cmpl %ebx,%eax
  887. je .Lcoext_ok
  888. movl %eax,%edi
  889. jmp .Lcoext_obj
  890. .Lcoext_re:
  891. pushl $219
  892. call HandleError
  893. .Lcoext_ok:
  894. popl %eax
  895. popl %ebx
  896. popl %edi
  897. { the adress and vmt were pushed : it needs to be removed from stack !! PM }
  898. popl %ebp
  899. ret $8
  900. end;
  901. {$endif HAS_GENERICCONSTRUCTOR}
  902. {****************************************************************************
  903. String
  904. ****************************************************************************}
  905. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  906. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  907. function fpc_shortstr_to_shortstr(len:longint; const sstr: shortstring): shortstring; [public,alias: 'FPC_SHORTSTR_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  908. begin
  909. asm
  910. cld
  911. movl __RESULT,%edi
  912. movl sstr,%esi
  913. xorl %eax,%eax
  914. movl len,%ecx
  915. lodsb
  916. cmpl %ecx,%eax
  917. jbe .LStrCopy1
  918. movl %ecx,%eax
  919. .LStrCopy1:
  920. stosb
  921. cmpl $7,%eax
  922. jl .LStrCopy2
  923. movl %edi,%ecx { Align on 32bits }
  924. negl %ecx
  925. andl $3,%ecx
  926. subl %ecx,%eax
  927. rep
  928. movsb
  929. movl %eax,%ecx
  930. andl $3,%eax
  931. shrl $2,%ecx
  932. rep
  933. movsl
  934. .LStrCopy2:
  935. movl %eax,%ecx
  936. rep
  937. movsb
  938. end ['ESI','EDI','EAX','ECX'];
  939. end;
  940. {$ifdef interncopy}
  941. procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN'];
  942. {$else}
  943. procedure fpc_shortstr_copy(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_COPY'];
  944. {$endif}
  945. begin
  946. asm
  947. pushl %eax
  948. pushl %ecx
  949. cld
  950. movl dstr,%edi
  951. movl sstr,%esi
  952. xorl %eax,%eax
  953. movl len,%ecx
  954. lodsb
  955. cmpl %ecx,%eax
  956. jbe .LStrCopy1
  957. movl %ecx,%eax
  958. .LStrCopy1:
  959. stosb
  960. cmpl $7,%eax
  961. jl .LStrCopy2
  962. movl %edi,%ecx { Align on 32bits }
  963. negl %ecx
  964. andl $3,%ecx
  965. subl %ecx,%eax
  966. rep
  967. movsb
  968. movl %eax,%ecx
  969. andl $3,%eax
  970. shrl $2,%ecx
  971. rep
  972. movsl
  973. .LStrCopy2:
  974. movl %eax,%ecx
  975. rep
  976. movsb
  977. popl %ecx
  978. popl %eax
  979. end ['ESI','EDI'];
  980. end;
  981. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  982. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  983. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  984. function fpc_shortstr_concat(const s1,s2:shortstring):shortstring;{$ifdef hascompilerproc}compilerproc;{$endif}
  985. begin
  986. asm
  987. movl __RESULT,%edi
  988. movl %edi,%ebx
  989. movl s1,%esi { first string }
  990. lodsb
  991. andl $0x0ff,%eax
  992. stosb
  993. cmpl $7,%eax
  994. jl .LStrConcat1
  995. movl %edi,%ecx { Align on 32bits }
  996. negl %ecx
  997. andl $3,%ecx
  998. subl %ecx,%eax
  999. rep
  1000. movsb
  1001. movl %eax,%ecx
  1002. andl $3,%eax
  1003. shrl $2,%ecx
  1004. rep
  1005. movsl
  1006. .LStrConcat1:
  1007. movl %eax,%ecx
  1008. rep
  1009. movsb
  1010. movl s2,%esi { second string }
  1011. movzbl (%ebx),%ecx
  1012. negl %ecx
  1013. addl $0x0ff,%ecx
  1014. lodsb
  1015. cmpl %ecx,%eax
  1016. jbe .LStrConcat2
  1017. movl %ecx,%eax
  1018. .LStrConcat2:
  1019. addb %al,(%ebx)
  1020. cmpl $7,%eax
  1021. jl .LStrConcat3
  1022. movl %edi,%ecx { Align on 32bits }
  1023. negl %ecx
  1024. andl $3,%ecx
  1025. subl %ecx,%eax
  1026. rep
  1027. movsb
  1028. movl %eax,%ecx
  1029. andl $3,%eax
  1030. shrl $2,%ecx
  1031. rep
  1032. movsl
  1033. .LStrConcat3:
  1034. movl %eax,%ecx
  1035. rep
  1036. movsb
  1037. end ['EBX','ECX','EAX','ESI','EDI'];
  1038. end;
  1039. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  1040. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  1041. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  1042. {$ifdef hascompilerproc}
  1043. procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring);compilerproc;
  1044. [public,alias:'FPC_SHORTSTR_APPEND_SHORTSTR'];
  1045. begin
  1046. asm
  1047. movl s1,%edi
  1048. movl s2,%esi
  1049. movl %edi,%ebx
  1050. movzbl (%edi),%ecx
  1051. movl __HIGH(s1),%eax
  1052. lea 1(%edi,%ecx),%edi
  1053. negl %ecx
  1054. addl %eax,%ecx
  1055. // no need to zero eax, high(s1) <= 255
  1056. lodsb
  1057. cmpl %ecx,%eax
  1058. jbe .LStrConcat1
  1059. movl %ecx,%eax
  1060. .LStrConcat1:
  1061. addb %al,(%ebx)
  1062. cmpl $7,%eax
  1063. jl .LStrConcat2
  1064. movl %edi,%ecx { Align on 32bits }
  1065. negl %ecx
  1066. andl $3,%ecx
  1067. subl %ecx,%eax
  1068. rep
  1069. movsb
  1070. movl %eax,%ecx
  1071. andl $3,%eax
  1072. shrl $2,%ecx
  1073. rep
  1074. movsl
  1075. .LStrConcat2:
  1076. movl %eax,%ecx
  1077. rep
  1078. movsb
  1079. end ['EBX','ECX','EAX','ESI','EDI'];
  1080. end;
  1081. {$else hascompilerproc}
  1082. procedure fpc_shortstr_concat_int(const s1,s2:shortstring);[public,alias:'FPC_SHORTSTR_CONCAT'];
  1083. begin
  1084. asm
  1085. movl s1,%esi
  1086. movl s2,%edi
  1087. movl %edi,%ebx
  1088. movzbl (%edi),%ecx
  1089. xor %eax,%eax
  1090. lea 1(%edi,%ecx),%edi
  1091. negl %ecx
  1092. addl $0x0ff,%ecx
  1093. lodsb
  1094. cmpl %ecx,%eax
  1095. jbe .LStrConcat1
  1096. movl %ecx,%eax
  1097. .LStrConcat1:
  1098. addb %al,(%ebx)
  1099. cmpl $7,%eax
  1100. jl .LStrConcat2
  1101. movl %edi,%ecx { Align on 32bits }
  1102. negl %ecx
  1103. andl $3,%ecx
  1104. subl %ecx,%eax
  1105. rep
  1106. movsb
  1107. movl %eax,%ecx
  1108. andl $3,%eax
  1109. shrl $2,%ecx
  1110. rep
  1111. movsl
  1112. .LStrConcat2:
  1113. movl %eax,%ecx
  1114. rep
  1115. movsb
  1116. end ['EBX','ECX','EAX','ESI','EDI'];
  1117. end;
  1118. {$endif hascompilerproc}
  1119. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  1120. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  1121. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  1122. {$ifdef SHORTSTRCOMPAREINREG}
  1123. function fpc_shortstr_compare(const left,right:shortstring): longint;assembler; [public,alias:'FPC_SHORTSTR_COMPARE']; compilerproc;
  1124. var
  1125. saveesi,saveedi,saveebx : longint;
  1126. asm
  1127. movl %edi,saveedi
  1128. movl %esi,saveesi
  1129. movl %ebx,saveebx
  1130. cld
  1131. movl right,%esi
  1132. movl left,%edi
  1133. movzbl (%esi),%eax
  1134. movzbl (%edi),%ebx
  1135. movl %eax,%edx
  1136. incl %esi
  1137. incl %edi
  1138. cmpl %ebx,%eax
  1139. jbe .LStrCmp1
  1140. movl %ebx,%eax
  1141. .LStrCmp1:
  1142. cmpl $7,%eax
  1143. jl .LStrCmp2
  1144. movl %edi,%ecx { Align on 32bits }
  1145. negl %ecx
  1146. andl $3,%ecx
  1147. subl %ecx,%eax
  1148. orl %ecx,%ecx
  1149. rep
  1150. cmpsb
  1151. jne .LStrCmp3
  1152. movl %eax,%ecx
  1153. andl $3,%eax
  1154. shrl $2,%ecx
  1155. orl %ecx,%ecx
  1156. rep
  1157. cmpsl
  1158. je .LStrCmp2
  1159. movl $4,%eax
  1160. subl %eax,%esi
  1161. subl %eax,%edi
  1162. .LStrCmp2:
  1163. movl %eax,%ecx
  1164. orl %eax,%eax
  1165. rep
  1166. cmpsb
  1167. je .LStrCmp4
  1168. .LStrCmp3:
  1169. movzbl -1(%esi),%edx // Compare failing (or equal) position
  1170. movzbl -1(%edi),%ebx
  1171. .LStrCmp4:
  1172. movl %ebx,%eax // Compare length or position
  1173. subl %edx,%eax
  1174. movl saveedi,%edi
  1175. movl saveesi,%esi
  1176. movl saveebx,%ebx
  1177. end;
  1178. {$else SHORTSTRCOMPAREINREG}
  1179. function fpc_shortstr_compare(const left,right:shortstring): longint; [public,alias:'FPC_SHORTSTR_COMPARE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  1180. begin
  1181. asm
  1182. cld
  1183. xorl %ebx,%ebx
  1184. xorl %eax,%eax
  1185. movl right,%esi
  1186. movl left,%edi
  1187. movb (%esi),%al
  1188. movb (%edi),%bl
  1189. movl %eax,%edx
  1190. incl %esi
  1191. incl %edi
  1192. cmpl %ebx,%eax
  1193. jbe .LStrCmp1
  1194. movl %ebx,%eax
  1195. .LStrCmp1:
  1196. cmpl $7,%eax
  1197. jl .LStrCmp2
  1198. movl %edi,%ecx { Align on 32bits }
  1199. negl %ecx
  1200. andl $3,%ecx
  1201. subl %ecx,%eax
  1202. orl %ecx,%ecx
  1203. rep
  1204. cmpsb
  1205. jne .LStrCmp3
  1206. movl %eax,%ecx
  1207. andl $3,%eax
  1208. shrl $2,%ecx
  1209. orl %ecx,%ecx
  1210. rep
  1211. cmpsl
  1212. je .LStrCmp2
  1213. movl $4,%eax
  1214. sub %eax,%esi
  1215. sub %eax,%edi
  1216. .LStrCmp2:
  1217. movl %eax,%ecx
  1218. orl %eax,%eax
  1219. rep
  1220. cmpsb
  1221. jne .LStrCmp3
  1222. cmp %ebx,%edx
  1223. .LStrCmp3:
  1224. end ['EDX','ECX','EBX','EAX','ESI','EDI'];
  1225. end;
  1226. {$endif SHORTSTRCOMPAREINREG}
  1227. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  1228. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  1229. {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  1230. function fpc_pchar_to_shortstr(p:pchar):shortstring;assembler;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  1231. {$include strpas.inc}
  1232. {$endif FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  1233. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  1234. {$define FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  1235. function fpc_pchar_length(p:pchar):longint;assembler;[public,alias:'FPC_PCHAR_LENGTH']; {$ifdef hascompilerproc} compilerproc; {$endif}
  1236. {$include strlen.inc}
  1237. {$endif FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  1238. {$define FPC_SYSTEM_HAS_GET_FRAME}
  1239. function get_frame:pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  1240. asm
  1241. movl %ebp,%eax
  1242. end ['EAX'];
  1243. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  1244. function get_caller_addr(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  1245. asm
  1246. {$ifndef REGCALL}
  1247. movl framebp,%eax
  1248. {$endif}
  1249. orl %eax,%eax
  1250. jz .Lg_a_null
  1251. movl 4(%eax),%eax
  1252. .Lg_a_null:
  1253. end ['EAX'];
  1254. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  1255. function get_caller_frame(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  1256. asm
  1257. {$ifndef REGCALL}
  1258. movl framebp,%eax
  1259. {$endif}
  1260. orl %eax,%eax
  1261. jz .Lgnf_null
  1262. movl (%eax),%eax
  1263. .Lgnf_null:
  1264. end ['EAX'];
  1265. {****************************************************************************
  1266. Math
  1267. ****************************************************************************}
  1268. {$define FPC_SYSTEM_HAS_ABS_LONGINT}
  1269. function abs(l:longint):longint; assembler;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_abs];{$endif}
  1270. asm
  1271. {$ifndef REGCALL}
  1272. movl l,%eax
  1273. {$endif}
  1274. cltd
  1275. xorl %edx,%eax
  1276. subl %edx,%eax
  1277. end ['EAX','EDX'];
  1278. {$define FPC_SYSTEM_HAS_ODD_LONGINT}
  1279. function odd(l:longint):boolean;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_odd];{$endif}
  1280. asm
  1281. {$ifdef SYSTEMINLINE}
  1282. movl l,%eax
  1283. {$else}
  1284. {$ifndef REGCALL}
  1285. movl l,%eax
  1286. {$endif}
  1287. {$endif}
  1288. andl $1,%eax
  1289. setnz %al
  1290. end ['EAX'];
  1291. {$define FPC_SYSTEM_HAS_SQR_LONGINT}
  1292. function sqr(l:longint):longint;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_sqr];{$endif}
  1293. asm
  1294. {$ifdef SYSTEMINLINE}
  1295. movl l,%eax
  1296. {$else}
  1297. {$ifndef REGCALL}
  1298. movl l,%eax
  1299. {$endif}
  1300. {$endif}
  1301. imull %eax,%eax
  1302. end ['EAX'];
  1303. {$define FPC_SYSTEM_HAS_SPTR}
  1304. Function Sptr : Pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  1305. asm
  1306. movl %esp,%eax
  1307. end;
  1308. {****************************************************************************
  1309. Str()
  1310. ****************************************************************************}
  1311. {$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
  1312. procedure int_str(l : longint;var s : string);
  1313. var
  1314. buffer : array[0..15] of byte;
  1315. isneg : byte;
  1316. begin
  1317. { Workaround: }
  1318. if l=longint($80000000) then
  1319. begin
  1320. s:='-2147483648';
  1321. exit;
  1322. end;
  1323. asm
  1324. movl l,%eax // load Integer
  1325. xorl %ecx,%ecx // String length=0
  1326. leal buffer,%ebx
  1327. movl $0x0a,%esi // load 10 as dividing constant.
  1328. movb $0,isneg
  1329. orl %eax,%eax // Sign ?
  1330. jns .LM2
  1331. movb $1,isneg
  1332. negl %eax
  1333. .LM2:
  1334. cltd
  1335. idivl %esi
  1336. addb $0x30,%dl // convert Rest to ASCII.
  1337. movb %dl,(%ebx)
  1338. incl %ecx
  1339. incl %ebx
  1340. cmpl $0,%eax
  1341. jnz .LM2
  1342. { now copy the string }
  1343. movl s,%edi // Load String address
  1344. cmpb $0,isneg
  1345. je .LM3
  1346. movb $0x2d,(%ebx)
  1347. incl %ecx
  1348. incl %ebx
  1349. .LM3:
  1350. movb %cl,(%edi) // Copy String length
  1351. incl %edi
  1352. .LM4:
  1353. decl %ebx
  1354. movb (%ebx),%al
  1355. stosb
  1356. decl %ecx
  1357. jnz .LM4
  1358. end ['eax','ecx','edx','ebx','esi','edi'];
  1359. end;
  1360. {$define FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  1361. procedure int_str(c : longword;var s : string);
  1362. var
  1363. buffer : array[0..15] of byte;
  1364. begin
  1365. asm
  1366. movl c,%eax // load CARDINAL
  1367. xorl %ecx,%ecx // String length=0
  1368. leal buffer,%ebx
  1369. movl $0x0a,%esi // load 10 as dividing constant.
  1370. .LM4:
  1371. xorl %edx,%edx
  1372. divl %esi
  1373. addb $0x30,%dl // convert Rest to ASCII.
  1374. movb %dl,(%ebx)
  1375. incl %ecx
  1376. incl %ebx
  1377. cmpl $0,%eax
  1378. jnz .LM4
  1379. { now copy the string }
  1380. movl s,%edi // Load String address
  1381. movb %cl,(%edi) // Copy String length
  1382. incl %edi
  1383. .LM5:
  1384. decl %ebx
  1385. movb (%ebx),%al
  1386. stosb
  1387. decl %ecx
  1388. jnz .LM5
  1389. end ['eax','ecx','edx','ebx','esi','edi'];
  1390. end;
  1391. {****************************************************************************
  1392. Bounds Check
  1393. ****************************************************************************}
  1394. {$ifndef NOBOUNDCHECK}
  1395. procedure int_boundcheck;assembler;[public,alias: 'FPC_BOUNDCHECK'];
  1396. var dummy_to_force_stackframe_generation_for_trace: Longint;
  1397. {
  1398. called with:
  1399. %ecx - value
  1400. %edi - pointer to the ranges
  1401. }
  1402. asm
  1403. cmpl (%edi),%ecx
  1404. jl .Lbc_err
  1405. cmpl 4(%edi),%ecx
  1406. jle .Lbc_ok
  1407. .Lbc_err:
  1408. pushl %ebp
  1409. pushl $201
  1410. call HandleErrorFrame
  1411. .Lbc_ok:
  1412. end;
  1413. {$endif NOBOUNDCHECK}
  1414. { do a thread save inc/dec }
  1415. {$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  1416. function declocked(var l : longint) : boolean;assembler;
  1417. asm
  1418. {$ifndef REGCALL}
  1419. movl l,%eax
  1420. {$endif}
  1421. { this check should be done because a lock takes a lot }
  1422. { of time! }
  1423. cmpb $0,IsMultithread
  1424. jz .Ldeclockednolock
  1425. lock
  1426. decl (%eax)
  1427. jmp .Ldeclockedend
  1428. .Ldeclockednolock:
  1429. decl (%eax);
  1430. .Ldeclockedend:
  1431. setzb %al
  1432. end;
  1433. {$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  1434. procedure inclocked(var l : longint);assembler;
  1435. asm
  1436. {$ifndef REGCALL}
  1437. movl l,%eax
  1438. {$endif}
  1439. { this check should be done because a lock takes a lot }
  1440. { of time! }
  1441. cmpb $0,IsMultithread
  1442. jz .Linclockednolock
  1443. lock
  1444. incl (%eax)
  1445. jmp .Linclockedend
  1446. .Linclockednolock:
  1447. incl (%eax)
  1448. .Linclockedend:
  1449. end;
  1450. {****************************************************************************
  1451. FPU
  1452. ****************************************************************************}
  1453. const
  1454. fpucw : word = $1332;
  1455. { Internal constants for use in system unit }
  1456. FPU_Invalid = 1;
  1457. FPU_Denormal = 2;
  1458. FPU_DivisionByZero = 4;
  1459. FPU_Overflow = 8;
  1460. FPU_Underflow = $10;
  1461. FPU_StackUnderflow = $20;
  1462. FPU_StackOverflow = $40;
  1463. FPU_ExceptionMask = $ff;
  1464. {$define FPC_SYSTEM_HAS_SYSRESETFPU}
  1465. Procedure SysResetFPU;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  1466. asm
  1467. fninit
  1468. fldcw fpucw
  1469. end;
  1470. {
  1471. $Log$
  1472. Revision 1.67 2005-01-23 20:03:23 florian
  1473. + fastmove from John O'Harrow integrated
  1474. Revision 1.66 2004/11/17 22:19:04 peter
  1475. internconst, internproc and some external declarations moved to interface
  1476. Revision 1.65 2004/11/01 12:43:29 peter
  1477. * shortstr compare with empty string fixed
  1478. * removed special i386 code
  1479. Revision 1.64 2004/07/18 20:21:44 florian
  1480. + several unicode (to/from utf-8 conversion) stuff added
  1481. * some longint -> SizeInt changes
  1482. Revision 1.63 2004/07/18 16:40:08 jonas
  1483. * fixed indexbyte/word/dword when length is 0 (return -1 instead of 0)
  1484. Revision 1.62 2004/07/07 17:38:58 daniel
  1485. * Aligment code in fillchar proved to slow down stuff seriously instead of
  1486. speeding it up. This is logical, the compiler aligns everything very well,
  1487. it is possible that fillchar gets called on misaligned data, but it seems
  1488. this never happens.
  1489. Revision 1.61 2004/04/29 20:00:47 peter
  1490. * inclocked_longint ifdef fixed
  1491. Revision 1.60 2004/04/26 15:55:01 peter
  1492. * FPC_MOVE alias
  1493. Revision 1.59 2004/02/05 01:16:12 florian
  1494. + completed x86-64/linux system unit
  1495. Revision 1.58 2004/01/11 11:10:07 jonas
  1496. + cgeneric.inc: implementations of rtl routines based on libc
  1497. * system.inc: include cgeneric.inc before powerpc.inc/i386.inc/... if
  1498. FPC_USE_LIBC is defined
  1499. * powerpc.inc, i386.inc: check whether the routines they implement aren't
  1500. implemented yet in another include file (cgeneric.inc)
  1501. Revision 1.57 2004/01/02 17:22:14 jonas
  1502. + fpc_cpuinit procedure to allow cpu/fpu initialisation before any unit
  1503. initialises
  1504. + fpu exceptions for invalid operations and division by zero enabled for
  1505. ppc
  1506. Revision 1.56 2003/12/24 23:07:28 peter
  1507. * fixed indexbyte for regcall
  1508. Revision 1.55 2003/12/04 21:44:39 peter
  1509. * fix warning in gas
  1510. Revision 1.54 2003/11/19 16:58:44 peter
  1511. * make strpas assembler function
  1512. Revision 1.53 2003/11/11 21:08:17 peter
  1513. * REGCALL define added
  1514. Revision 1.52 2003/11/03 09:42:27 marco
  1515. * Peter's Cardinal<->Longint fixes patch
  1516. Revision 1.51 2003/10/27 09:16:57 marco
  1517. * fix from peter i386.inc to circumvent ebx destroying
  1518. Revision 1.50 2003/10/23 17:01:27 peter
  1519. * save edi,ebx,esi in int_str
  1520. Revision 1.49 2003/10/16 21:28:40 peter
  1521. * use __HIGH()
  1522. Revision 1.48 2003/10/14 00:57:48 florian
  1523. + some code for PIC support added
  1524. Revision 1.47 2003/09/14 11:34:13 peter
  1525. * moved int64 asm code to int64p.inc
  1526. * save ebx,esi
  1527. Revision 1.46 2003/09/08 18:21:37 peter
  1528. * save edi,esi,ebx
  1529. Revision 1.45 2003/06/01 14:50:17 jonas
  1530. * fpc_shortstr_append_shortstr has to use high(s1) instead of 255 as
  1531. maxlen
  1532. + ppc version of fpc_shortstr_append_shortstr
  1533. Revision 1.44 2003/05/26 21:18:13 peter
  1534. * FPC_SHORTSTR_APPEND_SHORTSTR public added
  1535. Revision 1.43 2003/05/26 19:36:46 peter
  1536. * fpc_shortstr_concat is now the same for all targets
  1537. * fpc_shortstr_append_shortstr added for optimized code generation
  1538. Revision 1.42 2003/05/16 22:40:11 florian
  1539. * fixed generic shortstr_compare
  1540. Revision 1.41 2003/03/26 00:19:10 peter
  1541. * ifdef HAS_GENERICCONSTRUCTOR
  1542. Revision 1.40 2003/03/17 14:30:11 peter
  1543. * changed address parameter/return values to pointer instead
  1544. of longint
  1545. Revision 1.39 2003/02/18 17:56:06 jonas
  1546. - removed buggy i386-specific FPC_CHARARRAY_TO_SHORTSTR
  1547. * fixed generic FPC_CHARARRAY_TO_SHORTSTR (web bug 2382)
  1548. * fixed some potential range errors in indexchar/word/dword
  1549. Revision 1.38 2003/01/06 23:03:13 mazen
  1550. + defining FPC_SYSTEM_HAS_DECLOCKED and FPC_SYSTEM_HAS_INCLOCKED to avoid
  1551. compilation error on generic.inc
  1552. Revision 1.37 2003/01/03 17:14:54 peter
  1553. * fix possible overflow when array len > 255 when converting to
  1554. shortstring
  1555. Revision 1.36 2002/12/15 22:32:25 peter
  1556. * fixed return value when len=0 for indexchar,indexword
  1557. Revision 1.35 2002/10/20 11:50:57 carl
  1558. * avoid crashes with negative len counts on fills/moves
  1559. Revision 1.34 2002/10/15 19:24:47 carl
  1560. * Replace 220 -> 219
  1561. Revision 1.33 2002/10/14 19:39:16 peter
  1562. * threads unit added for thread support
  1563. Revision 1.32 2002/10/05 14:20:16 peter
  1564. * fpc_pchar_length compilerproc and strlen alias
  1565. Revision 1.31 2002/10/02 18:21:51 peter
  1566. * Copy() changed to internal function calling compilerprocs
  1567. * FPC_SHORTSTR_COPY renamed to FPC_SHORTSTR_ASSIGN because of the
  1568. new copy functions
  1569. Revision 1.30 2002/09/07 21:33:35 carl
  1570. - removed unused defines
  1571. Revision 1.29 2002/09/07 16:01:19 peter
  1572. * old logs removed and tabs fixed
  1573. Revision 1.28 2002/09/03 15:43:36 peter
  1574. * add alias for fpc_dispose_class so it can be called from
  1575. fpc_help_fail_class
  1576. Revision 1.27 2002/08/19 19:34:02 peter
  1577. * SYSTEMINLINE define that will add inline directives for small
  1578. functions and wrappers. This will be defined automaticly when
  1579. the compiler defines the HASINLINE directive
  1580. Revision 1.26 2002/07/26 15:45:33 florian
  1581. * changed multi threading define: it's MT instead of MTRTL
  1582. Revision 1.25 2002/07/06 20:31:59 carl
  1583. + added TEST_GENERIC to test generic version
  1584. Revision 1.24 2002/06/16 08:21:26 carl
  1585. + TEST_GENERIC to test generic versions of code
  1586. Revision 1.23 2002/06/09 12:54:37 jonas
  1587. * fixed memory corruption bug in fpc_help_constructor
  1588. Revision 1.22 2002/04/21 18:56:59 peter
  1589. * fpc_freemem and fpc_getmem compilerproc
  1590. Revision 1.21 2002/04/01 14:23:17 carl
  1591. - no need for runerror 203, already fixed!
  1592. Revision 1.20 2002/03/30 14:52:04 carl
  1593. * cause runtime error 203 on failed class creation
  1594. }