i386.inc 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  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. {$asmmode ATT}
  14. {****************************************************************************
  15. Primitives
  16. ****************************************************************************}
  17. {$define FPC_SYSTEM_HAS_MOVE}
  18. procedure Move(const source;var dest;count:longint);assembler;
  19. asm
  20. movl dest,%edi
  21. movl source,%esi
  22. movl %edi,%eax
  23. movl count,%ebx
  24. { Check for back or forward }
  25. sub %esi,%eax
  26. jz .LMoveEnd { Do nothing when source=dest }
  27. jc .LFMove { Do forward, dest<source }
  28. cmp %ebx,%eax
  29. jb .LBMove { Dest is in range of move, do backward }
  30. { Forward Copy }
  31. .LFMove:
  32. cld
  33. cmpl $15,%ebx
  34. jl .LFMove1
  35. movl %edi,%ecx { Align on 32bits }
  36. negl %ecx
  37. andl $3,%ecx
  38. subl %ecx,%ebx
  39. rep
  40. movsb
  41. movl %ebx,%ecx
  42. andl $3,%ebx
  43. shrl $2,%ecx
  44. rep
  45. movsl
  46. .LFMove1:
  47. movl %ebx,%ecx
  48. rep
  49. movsb
  50. jmp .LMoveEnd
  51. { Backward Copy }
  52. .LBMove:
  53. std
  54. addl %ebx,%esi
  55. addl %ebx,%edi
  56. movl %edi,%ecx
  57. decl %esi
  58. decl %edi
  59. cmpl $15,%ebx
  60. jl .LBMove1
  61. negl %ecx { Align on 32bits }
  62. andl $3,%ecx
  63. subl %ecx,%ebx
  64. rep
  65. movsb
  66. movl %ebx,%ecx
  67. andl $3,%ebx
  68. shrl $2,%ecx
  69. subl $3,%esi
  70. subl $3,%edi
  71. rep
  72. movsl
  73. addl $3,%esi
  74. addl $3,%edi
  75. .LBMove1:
  76. movl %ebx,%ecx
  77. rep
  78. movsb
  79. cld
  80. .LMoveEnd:
  81. end ['EAX','EBX','ECX','ESI','EDI'];
  82. {$define FPC_SYSTEM_HAS_FILLCHAR}
  83. Procedure FillChar(var x;count:longint;value:byte);
  84. [public,alias: 'FPC_FILLCHAR'];assembler;
  85. asm
  86. cld
  87. movl x,%edi
  88. movb value,%al
  89. movl count,%ecx
  90. cmpl $7,%ecx
  91. jl .LFill1
  92. movb %al,%ah
  93. movl %eax,%ebx
  94. shll $16,%eax
  95. movl %ecx,%edx
  96. movw %bx,%ax
  97. movl %edi,%ecx { Align on 32bits }
  98. negl %ecx
  99. andl $3,%ecx
  100. subl %ecx,%edx
  101. rep
  102. stosb
  103. movl %edx,%ecx
  104. andl $3,%edx
  105. shrl $2,%ecx
  106. rep
  107. stosl
  108. movl %edx,%ecx
  109. .LFill1:
  110. rep
  111. stosb
  112. end;
  113. {$define FPC_SYSTEM_HAS_FILLWORD}
  114. procedure fillword(var x;count : longint;value : word);assembler;
  115. asm
  116. movl x,%edi
  117. movl count,%ecx
  118. movzwl value,%eax
  119. movl %eax,%edx
  120. shll $16,%eax
  121. orl %edx,%eax
  122. movl %ecx,%edx
  123. shrl $1,%ecx
  124. cld
  125. rep
  126. stosl
  127. movl %edx,%ecx
  128. andl $1,%ecx
  129. rep
  130. stosw
  131. end ['EAX','ECX','EDX','EDI'];
  132. {$define FPC_SYSTEM_HAS_FILLDWORD}
  133. procedure filldword(var x;count : longint;value : dword);assembler;
  134. asm
  135. movl x,%edi
  136. movl count,%ecx
  137. movl value,%eax
  138. cld
  139. rep
  140. stosl
  141. end ['EAX','ECX','EDX','EDI'];
  142. {$define FPC_SYSTEM_HAS_INDEXBYTE}
  143. function IndexByte(var buf;len:longint;b:byte):longint; assembler;
  144. asm
  145. movl Len,%ecx // Load len
  146. movl Buf,%edi // Load String
  147. testl %ecx,%ecx
  148. jz .Lready
  149. cld
  150. movl %ecx,%ebx // Copy for easy manipulation
  151. movb b,%al
  152. repne
  153. scasb
  154. jne .Lcharposnotfound
  155. incl %ecx
  156. subl %ecx,%ebx
  157. movl %ebx,%eax
  158. jmp .Lready
  159. .Lcharposnotfound:
  160. movl $-1,%eax
  161. .Lready:
  162. end ['EAX','EBX','ECX','EDI'];
  163. {$define FPC_SYSTEM_HAS_INDEXWORD}
  164. function Indexword(var buf;len:longint;b:word):longint; assembler;
  165. asm
  166. movl Len,%ecx // Load len
  167. movl Buf,%edi // Load String
  168. testl %ecx,%ecx
  169. jz .Lready
  170. cld
  171. movl %ecx,%ebx // Copy for easy manipulation
  172. movw b,%ax
  173. repne
  174. scasw
  175. jne .Lcharposnotfound
  176. incl %ecx
  177. subl %ecx,%ebx
  178. movl %ebx,%eax
  179. jmp .Lready
  180. .Lcharposnotfound:
  181. movl $-1,%eax
  182. .Lready:
  183. end ['EAX','EBX','ECX','EDI'];
  184. {$define FPC_SYSTEM_HAS_INDEXDWORD}
  185. function IndexDWord(var buf;len:longint;b:DWord):longint; assembler;
  186. asm
  187. movl Len,%ecx // Load len
  188. movl Buf,%edi // Load String
  189. testl %ecx,%ecx
  190. jz .Lready
  191. cld
  192. movl %ecx,%ebx // Copy for easy manipulation
  193. movl b,%eax
  194. repne
  195. scasl
  196. jne .Lcharposnotfound
  197. incl %ecx
  198. subl %ecx,%ebx
  199. movl %ebx,%eax
  200. jmp .Lready
  201. .Lcharposnotfound:
  202. movl $-1,%eax
  203. .Lready:
  204. end ['EAX','EBX','ECX','EDI'];
  205. {$define FPC_SYSTEM_HAS_COMPAREBYTE}
  206. function CompareByte(var buf1,buf2;len:longint):longint; assembler;
  207. asm
  208. cld
  209. movl len,%eax
  210. movl buf2,%esi { Load params}
  211. movl buf1,%edi
  212. testl %eax,%eax {We address -1(%esi), so we have to deal with len=0}
  213. je .LCmpbyteExit
  214. cmpl $7,%eax {<7 not worth aligning and go through all trouble}
  215. jl .LCmpbyte2
  216. movl %edi,%ecx { Align on 32bits }
  217. negl %ecx { calc bytes to align (%edi and 3) xor 3= -%edi and 3}
  218. andl $3,%ecx
  219. subl %ecx,%eax { Subtract from number of bytes to go}
  220. orl %ecx,%ecx
  221. rep
  222. cmpsb {The actual 32-bit Aligning}
  223. jne .LCmpbyte3
  224. movl %eax,%ecx {bytes to do, divide by 4}
  225. andl $3,%eax {remainder}
  226. shrl $2,%ecx {The actual division}
  227. orl %ecx,%ecx {Sets zero flag if ecx=0 -> no cmp}
  228. rep
  229. cmpsl
  230. je .LCmpbyte2 { All equal? then to the left over bytes}
  231. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  232. subl %eax,%esi
  233. subl %eax,%edi
  234. .LCmpbyte2:
  235. movl %eax,%ecx {bytes still to (re)scan}
  236. orl %eax,%eax {prevent disaster in case %eax=0}
  237. rep
  238. cmpsb
  239. .LCmpbyte3:
  240. movzbl -1(%esi),%ecx
  241. movzbl -1(%edi),%eax // Compare failing (or equal) position
  242. subl %ecx,%eax
  243. .LCmpbyteExit:
  244. end ['ECX','EAX','ESI','EDI'];
  245. {$define FPC_SYSTEM_HAS_COMPAREWORD}
  246. function CompareWord(var buf1,buf2;len:longint):longint; assembler;
  247. asm
  248. cld
  249. movl len,%eax
  250. movl buf2,%esi { Load params}
  251. movl buf1,%edi
  252. testl %eax,%eax {We address -2(%esi), so we have to deal with len=0}
  253. je .LCmpwordExit
  254. cmpl $5,%eax {<5 (3 bytes align + 4 bytes cmpsl = 4 words}
  255. jl .LCmpword2 { not worth aligning and go through all trouble}
  256. movl (%edi),%ebx // Compare alignment bytes.
  257. cmpl (%esi),%ebx
  258. jne .LCmpword2 // Aligning will go wrong already. Max 2 words will be scanned Branch NOW
  259. shll $1,%eax {Convert word count to bytes}
  260. movl %edi,%edx { Align comparing is already done, so simply add}
  261. negl %edx { calc bytes to align -%edi and 3}
  262. andl $3,%edx
  263. addl %edx,%esi { Skip max 3 bytes alignment}
  264. addl %edx,%edi
  265. subl %edx,%eax { Subtract from number of bytes to go}
  266. movl %eax,%ecx { Make copy of bytes to go}
  267. andl $3,%eax { Calc remainder (mod 4) }
  268. andl $1,%edx { %edx is 1 if array not 2-aligned, 0 otherwise}
  269. shrl $2,%ecx { divide bytes to go by 4, DWords to go}
  270. orl %ecx,%ecx { Sets zero flag if ecx=0 -> no cmp}
  271. rep { Compare entire DWords}
  272. cmpsl
  273. je .LCmpword2a { All equal? then to the left over bytes}
  274. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  275. subl %eax,%esi { Go back one DWord}
  276. subl %eax,%edi
  277. incl %eax {if not odd then this does nothing, else it makes
  278. sure that adding %edx increases from 2 to 3 words}
  279. .LCmpword2a:
  280. subl %edx,%esi { Subtract alignment}
  281. subl %edx,%edi
  282. addl %edx,%eax
  283. shrl $1,%eax
  284. .LCmpword2:
  285. movl %eax,%ecx {words still to (re)scan}
  286. orl %eax,%eax {prevent disaster in case %eax=0}
  287. rep
  288. cmpsw
  289. .LCmpword3:
  290. movzwl -2(%esi),%ecx
  291. movzwl -2(%edi),%eax // Compare failing (or equal) position
  292. subl %ecx,%eax // calculate end result.
  293. .LCmpwordExit:
  294. end ['EBX','EDX','ECX','EAX','ESI','EDI'];
  295. {$define FPC_SYSTEM_HAS_COMPAREDWORD}
  296. function CompareDWord(var buf1,buf2;len:longint):longint; assembler;
  297. asm
  298. cld
  299. movl len,%eax
  300. movl buf2,%esi { Load params}
  301. movl buf1,%edi
  302. testl %eax,%eax {We address -2(%esi), so we have to deal with len=0}
  303. je .LCmpDwordExit
  304. cmpl $3,%eax {<3 (3 bytes align + 4 bytes cmpsl) = 2 DWords}
  305. jl .LCmpDword2 { not worth aligning and go through all trouble}
  306. movl (%edi),%ebx // Compare alignment bytes.
  307. cmpl (%esi),%ebx
  308. jne .LCmpDword2 // Aligning will go wrong already. Max 2 words will be scanned Branch NOW
  309. shll $2,%eax {Convert word count to bytes}
  310. movl %edi,%edx { Align comparing is already done, so simply add}
  311. negl %edx { calc bytes to align -%edi and 3}
  312. andl $3,%edx
  313. addl %edx,%esi { Skip max 3 bytes alignment}
  314. addl %edx,%edi
  315. subl %edx,%eax { Subtract from number of bytes to go}
  316. movl %eax,%ecx { Make copy of bytes to go}
  317. andl $3,%eax { Calc remainder (mod 4) }
  318. shrl $2,%ecx { divide bytes to go by 4, DWords to go}
  319. orl %ecx,%ecx { Sets zero flag if ecx=0 -> no cmp}
  320. rep { Compare entire DWords}
  321. cmpsl
  322. je .LCmpDword2a { All equal? then to the left over bytes}
  323. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  324. subl %eax,%esi { Go back one DWord}
  325. subl %eax,%edi
  326. addl $3,%eax {if align<>0 this causes repcount to be 2}
  327. .LCmpDword2a:
  328. subl %edx,%esi { Subtract alignment}
  329. subl %edx,%edi
  330. addl %edx,%eax
  331. shrl $2,%eax
  332. .LCmpDword2:
  333. movl %eax,%ecx {words still to (re)scan}
  334. orl %eax,%eax {prevent disaster in case %eax=0}
  335. rep
  336. cmpsl
  337. .LCmpDword3:
  338. movzwl -4(%esi),%ecx
  339. movzwl -4(%edi),%eax // Compare failing (or equal) position
  340. subl %ecx,%eax // calculate end result.
  341. .LCmpDwordExit:
  342. end ['EBX','EDX','ECX','EAX','ESI','EDI'];
  343. {$define FPC_SYSTEM_HAS_INDEXCHAR0}
  344. function IndexChar0(var buf;len:longint;b:Char):longint; assembler;
  345. asm
  346. // Can't use scasb, or will have to do it twice, think this
  347. // is faster for small "len"
  348. movl Buf,%esi // Load address
  349. movl len,%edx // load maximal searchdistance
  350. movzbl b,%ebx // Load searchpattern
  351. testl %edx,%edx
  352. je .LFound
  353. xorl %ecx,%ecx // zero index in Buf
  354. xorl %eax,%eax // To make DWord compares possible
  355. .LLoop:
  356. movb (%esi),%al // Load byte
  357. cmpb %al,%bl
  358. je .LFound // byte the same?
  359. incl %ecx
  360. incl %esi
  361. cmpl %edx,%ecx // Maximal distance reached?
  362. je .LNotFound
  363. testl %eax,%eax // Nullchar = end of search?
  364. jne .LLoop
  365. .LNotFound:
  366. movl $-1,%ecx // Not found return -1
  367. .LFound:
  368. movl %ecx,%eax
  369. end['EAX','EBX','ECX','EDX','ESI'];
  370. {****************************************************************************
  371. Object Helpers
  372. ****************************************************************************}
  373. {$define FPC_SYSTEM_HAS_FPC_HELP_CONSTRUCTOR}
  374. procedure int_help_constructor;assembler; [public,alias:'FPC_HELP_CONSTRUCTOR'];
  375. asm
  376. { Entry without preamble, since we need the ESP of the constructor
  377. Stack (relative to %ebp):
  378. 12 Self
  379. 8 VMT-Address
  380. 4 main programm-Addr
  381. 0 %ebp
  382. edi contains the vmt position
  383. }
  384. { eax isn't touched anywhere, so it doesn't have to reloaded }
  385. movl 8(%ebp),%eax
  386. { initialise self ? }
  387. orl %esi,%esi
  388. jne .LHC_4
  389. { get memory, but save register first temporary variable }
  390. subl $4,%esp
  391. movl %esp,%esi
  392. { Save Register}
  393. pushal
  394. { Memory size }
  395. pushl (%eax)
  396. pushl %esi
  397. call AsmGetMem
  398. movl $-1,8(%ebp)
  399. popal
  400. { Memory position to %esi }
  401. movl (%esi),%esi
  402. addl $4,%esp
  403. { If no memory available : fail() }
  404. orl %esi,%esi
  405. jz .LHC_5
  406. { init self for the constructor }
  407. movl %esi,12(%ebp)
  408. { jmp not necessary anymore because next instruction is disabled (JM)
  409. jmp .LHC_6 }
  410. { Why was the VMT reset to zero here ????
  411. I need it fail to know if I should
  412. zero the VMT field in static objects PM }
  413. .LHC_4:
  414. { movl $0,8(%ebp) }
  415. .LHC_6:
  416. { is there a VMT address ? }
  417. orl %eax,%eax
  418. jnz .LHC_7
  419. { In case the constructor doesn't do anything, the Zero-Flag }
  420. { can't be put, because this calls Fail() }
  421. incl %eax
  422. ret
  423. .LHC_7:
  424. { set zero inside the object }
  425. { pushal - crashes the 386 CPU }
  426. pushl %eax
  427. pushl %edi
  428. pushl %ecx
  429. cld
  430. movl (%eax),%ecx
  431. movl %esi,%edi
  432. movl %ecx,%ebx
  433. xorl %eax,%eax
  434. shrl $2,%ecx
  435. andl $3,%ebx
  436. rep
  437. stosl
  438. movl %ebx,%ecx
  439. rep
  440. stosb
  441. popl %ecx
  442. popl %edi
  443. popl %eax
  444. { set the VMT address for the new created object }
  445. { the offset is in %edi since the calling and has not been changed !! }
  446. movl %eax,(%esi,%edi,1)
  447. testl %eax,%eax
  448. .LHC_5:
  449. end;
  450. {$define FPC_SYSTEM_HAS_FPC_HELP_FAIL}
  451. procedure int_help_fail;assembler;[public,alias:'FPC_HELP_FAIL'];
  452. { should be called with a object that needs to be
  453. freed if VMT field is at -1
  454. %edi contains VMT offset in object again }
  455. asm
  456. testl %esi,%esi
  457. je .LHF_1
  458. cmpl $-1,8(%ebp)
  459. je .LHF_2
  460. { reset vmt field to zero for static instances }
  461. cmpl $0,8(%ebp)
  462. je .LHF_3
  463. { main constructor, we can zero the VMT field now }
  464. movl $0,(%esi,%edi,1)
  465. .LHF_3:
  466. { we zero esi to indicate failure }
  467. xorl %esi,%esi
  468. jmp .LHF_1
  469. .LHF_2:
  470. { get vmt address in eax }
  471. movl (%esi,%edi,1),%eax
  472. movl %esi,12(%ebp)
  473. { push object position }
  474. leal 12(%ebp),%eax
  475. pushl %eax
  476. call AsmFreeMem
  477. { set both object places to zero }
  478. xorl %esi,%esi
  479. movl %esi,12(%ebp)
  480. .LHF_1:
  481. end;
  482. {$define FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  483. procedure int_help_destructor;assembler;[public,alias:'FPC_HELP_DESTRUCTOR'];
  484. asm
  485. { Stack (relative to %ebp):
  486. 12 Self
  487. 8 VMT-Address
  488. 4 Main program-Addr
  489. 0 %ebp
  490. edi contains the vmt position
  491. }
  492. pushal
  493. { Should the object be resolved ? }
  494. movl 8(%ebp),%eax
  495. orl %eax,%eax
  496. jz .LHD_3
  497. { Yes, get size from SELF! }
  498. movl 12(%ebp),%eax
  499. { get VMT-pointer (from Self) to %ebx }
  500. { the offset is in %edi since the calling and has not been changed !! }
  501. movl (%eax,%edi,1),%ebx
  502. { I think for precaution }
  503. { that we should clear the VMT here }
  504. movl $0,(%eax,%edi,1)
  505. { temporary Variable }
  506. subl $4,%esp
  507. movl %esp,%edi
  508. { SELF }
  509. movl %eax,(%edi)
  510. pushl %edi
  511. call AsmFreeMem
  512. addl $4,%esp
  513. .LHD_3:
  514. popal
  515. end;
  516. {$define FPC_SYSTEM_HAS_FPC_NEW_CLASS}
  517. procedure int_new_class;assembler;[public,alias:'FPC_NEW_CLASS'];
  518. asm
  519. { to be sure in the future, we save also edit }
  520. pushl %edi
  521. { create class ? }
  522. movl 8(%ebp),%edi
  523. { if we test eax later without calling newinstance }
  524. { it must have a value <>0 }
  525. movl $1,%eax
  526. testl %edi,%edi
  527. jz .LNEW_CLASS1
  528. { save registers !! }
  529. pushl %ebx
  530. pushl %ecx
  531. pushl %edx
  532. { esi contains the vmt }
  533. pushl %esi
  534. { call newinstance (class method!) }
  535. call *52{vmtNewInstance}(%esi)
  536. popl %edx
  537. popl %ecx
  538. popl %ebx
  539. { newinstance returns a pointer to the new created }
  540. { instance in eax }
  541. { load esi and insert self }
  542. movl %eax,%esi
  543. .LNEW_CLASS1:
  544. movl %esi,8(%ebp)
  545. testl %eax,%eax
  546. popl %edi
  547. end;
  548. {$define FPC_SYSTEM_HAS_FPC_DISPOSE_CLASS}
  549. procedure int_dispose_class;assembler;[public,alias:'FPC_DISPOSE_CLASS'];
  550. asm
  551. { to be sure in the future, we save also edit }
  552. pushl %edi
  553. { destroy class ? }
  554. movl 12(%ebp),%edi
  555. testl %edi,%edi
  556. jz .LDISPOSE_CLASS1
  557. { no inherited call }
  558. movl (%esi),%edi
  559. { save registers !! }
  560. pushl %eax
  561. pushl %ebx
  562. pushl %ecx
  563. pushl %edx
  564. { push self }
  565. pushl %esi
  566. { call freeinstance }
  567. call *56{vmtFreeInstance}(%edi)
  568. popl %edx
  569. popl %ecx
  570. popl %ebx
  571. popl %eax
  572. .LDISPOSE_CLASS1:
  573. popl %edi
  574. end;
  575. {$define FPC_SYSTEM_HAS_FPC_HELP_FAIL_CLASS}
  576. procedure int_help_fail_class;assembler;[public,alias:'FPC_HELP_FAIL_CLASS'];
  577. { a non zero class must allways be disposed
  578. VMT is allways at pos 0 }
  579. asm
  580. testl %esi,%esi
  581. je .LHFC_1
  582. call INT_DISPOSE_CLASS
  583. { set both object places to zero }
  584. xorl %esi,%esi
  585. movl %esi,8(%ebp)
  586. .LHFC_1:
  587. end;
  588. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  589. {$ifdef SYSTEMDEBUG}
  590. { we want the stack for debugging !! PM }
  591. procedure int_check_object(obj : pointer);[public,alias:'FPC_CHECK_OBJECT'];
  592. begin
  593. {$else not SYSTEMDEBUG}
  594. procedure int_check_object;assembler;[public,alias:'FPC_CHECK_OBJECT'];
  595. {$endif not SYSTEMDEBUG}
  596. asm
  597. pushl %edi
  598. {$ifdef SYSTEMDEBUG}
  599. movl obj,%edi
  600. {$else not SYSTEMDEBUG}
  601. movl 8(%esp),%edi
  602. {$endif not SYSTEMDEBUG}
  603. pushl %eax
  604. { Here we must check if the VMT pointer is nil before }
  605. { accessing it... }
  606. testl %edi,%edi
  607. jz .Lco_re
  608. movl (%edi),%eax
  609. addl 4(%edi),%eax
  610. jz .Lco_ok
  611. .Lco_re:
  612. pushl $210
  613. call HandleError
  614. .Lco_ok:
  615. popl %eax
  616. popl %edi
  617. { the adress is pushed : it needs to be removed from stack !! PM }
  618. {$ifdef SYSTEMDEBUG}
  619. end;{ of asm }
  620. end;
  621. {$else SYSTEMDEBUG}
  622. ret $4
  623. end;
  624. {$endif not SYSTEMDEBUG}
  625. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  626. procedure int_check_object_ext;assembler;[public,alias:'FPC_CHECK_OBJECT_EXT'];
  627. { checks for a correct vmt pointer }
  628. { deeper check to see if the current object is }
  629. { really related to the true }
  630. asm
  631. pushl %ebp
  632. movl %esp,%ebp
  633. pushl %edi
  634. movl 8(%ebp),%edi
  635. pushl %ebx
  636. movl 12(%ebp),%ebx
  637. pushl %eax
  638. { Here we must check if the VMT pointer is nil before }
  639. { accessing it... }
  640. .Lcoext_obj:
  641. testl %edi,%edi
  642. jz .Lcoext_re
  643. movl (%edi),%eax
  644. addl 4(%edi),%eax
  645. jnz .Lcoext_re
  646. cmpl %edi,%ebx
  647. je .Lcoext_ok
  648. .Lcoext_vmt:
  649. movl 8(%edi),%eax
  650. cmpl %ebx,%eax
  651. je .Lcoext_ok
  652. movl %eax,%edi
  653. jmp .Lcoext_obj
  654. .Lcoext_re:
  655. pushl $220
  656. call HandleError
  657. .Lcoext_ok:
  658. popl %eax
  659. popl %ebx
  660. popl %edi
  661. { the adress and vmt were pushed : it needs to be removed from stack !! PM }
  662. popl %ebp
  663. ret $8
  664. end;
  665. {****************************************************************************
  666. String
  667. ****************************************************************************}
  668. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COPY}
  669. procedure int_strcopy(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_COPY'];
  670. {
  671. this procedure must save all modified registers except EDI and ESI !!!
  672. }
  673. begin
  674. asm
  675. pushl %eax
  676. pushl %ecx
  677. cld
  678. movl dstr,%edi
  679. movl sstr,%esi
  680. xorl %eax,%eax
  681. movl len,%ecx
  682. lodsb
  683. cmpl %ecx,%eax
  684. jbe .LStrCopy1
  685. movl %ecx,%eax
  686. .LStrCopy1:
  687. stosb
  688. cmpl $7,%eax
  689. jl .LStrCopy2
  690. movl %edi,%ecx { Align on 32bits }
  691. negl %ecx
  692. andl $3,%ecx
  693. subl %ecx,%eax
  694. rep
  695. movsb
  696. movl %eax,%ecx
  697. andl $3,%eax
  698. shrl $2,%ecx
  699. rep
  700. movsl
  701. .LStrCopy2:
  702. movl %eax,%ecx
  703. rep
  704. movsb
  705. popl %ecx
  706. popl %eax
  707. end ['ESI','EDI'];
  708. end;
  709. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  710. procedure int_strconcat(s1,s2:pointer);
  711. [public,alias:'FPC_SHORTSTR_CONCAT'];
  712. begin
  713. asm
  714. movl s2,%edi
  715. movl s1,%esi
  716. movl %edi,%ebx
  717. movzbl (%edi),%ecx
  718. xor %eax,%eax
  719. lea 1(%edi,%ecx),%edi
  720. negl %ecx
  721. addl $0x0ff,%ecx
  722. lodsb
  723. cmpl %ecx,%eax
  724. jbe .LStrConcat1
  725. movl %ecx,%eax
  726. .LStrConcat1:
  727. addb %al,(%ebx)
  728. cmpl $7,%eax
  729. jl .LStrConcat2
  730. movl %edi,%ecx { Align on 32bits }
  731. negl %ecx
  732. andl $3,%ecx
  733. subl %ecx,%eax
  734. rep
  735. movsb
  736. movl %eax,%ecx
  737. andl $3,%eax
  738. shrl $2,%ecx
  739. rep
  740. movsl
  741. .LStrConcat2:
  742. movl %eax,%ecx
  743. rep
  744. movsb
  745. end ['EBX','ECX','EAX','ESI','EDI'];
  746. end;
  747. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  748. procedure int_strcmp(dstr,sstr:pointer);[public,alias:'FPC_SHORTSTR_COMPARE'];
  749. begin
  750. asm
  751. cld
  752. xorl %ebx,%ebx
  753. xorl %eax,%eax
  754. movl sstr,%esi
  755. movl dstr,%edi
  756. movb (%esi),%al
  757. movb (%edi),%bl
  758. movl %eax,%edx
  759. incl %esi
  760. incl %edi
  761. cmpl %ebx,%eax
  762. jbe .LStrCmp1
  763. movl %ebx,%eax
  764. .LStrCmp1:
  765. cmpl $7,%eax
  766. jl .LStrCmp2
  767. movl %edi,%ecx { Align on 32bits }
  768. negl %ecx
  769. andl $3,%ecx
  770. subl %ecx,%eax
  771. orl %ecx,%ecx
  772. rep
  773. cmpsb
  774. jne .LStrCmp3
  775. movl %eax,%ecx
  776. andl $3,%eax
  777. shrl $2,%ecx
  778. orl %ecx,%ecx
  779. rep
  780. cmpsl
  781. je .LStrCmp2
  782. movl $4,%eax
  783. sub %eax,%esi
  784. sub %eax,%edi
  785. .LStrCmp2:
  786. movl %eax,%ecx
  787. orl %eax,%eax
  788. rep
  789. cmpsb
  790. jne .LStrCmp3
  791. cmp %ebx,%edx
  792. .LStrCmp3:
  793. end ['EDX','ECX','EBX','EAX','ESI','EDI'];
  794. end;
  795. {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  796. function strpas(p:pchar):shortstring;[public,alias:'FPC_PCHAR_TO_SHORTSTR'];
  797. {$include strpas.inc}
  798. {$define FPC_SYSTEM_HAS_STRLEN}
  799. function strlen(p:pchar):longint;assembler;
  800. {$include strlen.inc}
  801. {$define FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  802. function strchararray(p:pchar; l : longint):shortstring;[public,alias:'FPC_CHARARRAY_TO_SHORTSTR'];
  803. begin
  804. asm
  805. cld
  806. movl p,%esi
  807. movl l,%ecx
  808. orl %esi,%esi
  809. jnz .LStrCharArrayNotNil
  810. movl $0,%ecx
  811. .LStrCharArrayNotNil:
  812. movl %ecx,%eax
  813. movl __RESULT,%edi
  814. stosb
  815. cmpl $7,%eax
  816. jl .LStrCharArray2
  817. movl %edi,%ecx { Align on 32bits }
  818. negl %ecx
  819. andl $3,%ecx
  820. subl %ecx,%eax
  821. rep
  822. movsb
  823. movl %eax,%ecx
  824. andl $3,%eax
  825. shrl $2,%ecx
  826. rep
  827. movsl
  828. .LStrCharArray2:
  829. movl %eax,%ecx
  830. rep
  831. movsb
  832. end ['ECX','EAX','ESI','EDI'];
  833. end;
  834. {$define FPC_SYSTEM_HAS_GET_FRAME}
  835. function get_frame:longint;assembler;
  836. asm
  837. movl %ebp,%eax
  838. end ['EAX'];
  839. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  840. function get_caller_addr(framebp:longint):longint;assembler;
  841. asm
  842. movl framebp,%eax
  843. orl %eax,%eax
  844. jz .Lg_a_null
  845. movl 4(%eax),%eax
  846. .Lg_a_null:
  847. end ['EAX'];
  848. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  849. function get_caller_frame(framebp:longint):longint;assembler;
  850. asm
  851. movl framebp,%eax
  852. orl %eax,%eax
  853. jz .Lgnf_null
  854. movl (%eax),%eax
  855. .Lgnf_null:
  856. end ['EAX'];
  857. {****************************************************************************
  858. Math
  859. ****************************************************************************}
  860. {$define FPC_SYSTEM_HAS_ABS_LONGINT}
  861. function abs(l:longint):longint; assembler;[internconst:in_const_abs];
  862. asm
  863. movl l,%eax
  864. cltd
  865. xorl %edx,%eax
  866. subl %edx,%eax
  867. end ['EAX','EDX'];
  868. {$define FPC_SYSTEM_HAS_ODD_LONGINT}
  869. function odd(l:longint):boolean;assembler;[internconst:in_const_odd];
  870. asm
  871. movl l,%eax
  872. andl $1,%eax
  873. setnz %al
  874. end ['EAX'];
  875. {$define FPC_SYSTEM_HAS_SQR_LONGINT}
  876. function sqr(l:longint):longint;assembler;[internconst:in_const_sqr];
  877. asm
  878. mov l,%eax
  879. imull %eax,%eax
  880. end ['EAX'];
  881. {$define FPC_SYSTEM_HAS_SPTR}
  882. Function Sptr : Longint;assembler;
  883. asm
  884. movl %esp,%eax
  885. end;
  886. {****************************************************************************
  887. Str()
  888. ****************************************************************************}
  889. {$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
  890. procedure int_str(l : longint;var s : string);
  891. var
  892. buffer : array[0..11] of byte;
  893. begin
  894. { Workaround: }
  895. if l=$80000000 then
  896. begin
  897. s:='-2147483648';
  898. exit;
  899. end;
  900. asm
  901. movl l,%eax // load Integer
  902. movl s,%edi // Load String address
  903. xorl %ecx,%ecx // String length=0
  904. xorl %ebx,%ebx // Buffer length=0
  905. movl $0x0a,%esi // load 10 as dividing constant.
  906. orl %eax,%eax // Sign ?
  907. jns .LM2
  908. neg %eax
  909. movb $0x2d,1(%edi) // put '-' in String
  910. incl %ecx
  911. .LM2:
  912. cltd
  913. idivl %esi
  914. addb $0x30,%dl // convert Rest to ASCII.
  915. movb %dl,-12(%ebp,%ebx)
  916. incl %ebx
  917. cmpl $0,%eax
  918. jnz .LM2
  919. { copy String }
  920. .LM3:
  921. movb -13(%ebp,%ebx),%al // -13 because EBX is decreased only later
  922. movb %al,1(%edi,%ecx)
  923. incl %ecx
  924. decl %ebx
  925. jnz .LM3
  926. movb %cl,(%edi) // Copy String length
  927. end;
  928. end;
  929. {$define FPC_SYSTEM_HAS_INT_STR_CARDINAL}
  930. procedure int_str(c : cardinal;var s : string);
  931. var
  932. buffer : array[0..14] of byte;
  933. begin
  934. asm
  935. movl c,%eax // load CARDINAL
  936. movl s,%edi // Load String address
  937. xorl %ecx,%ecx // String length=0
  938. xorl %ebx,%ebx // Buffer length=0
  939. movl $0x0a,%esi // load 10 as dividing constant.
  940. .LM4:
  941. xorl %edx,%edx
  942. divl %esi
  943. addb $0x30,%dl // convert Rest to ASCII.
  944. movb %dl,-12(%ebp,%ebx)
  945. incl %ebx
  946. cmpl $0,%eax
  947. jnz .LM4
  948. { now copy the string }
  949. .LM5:
  950. movb -13(%ebp,%ebx),%al // -13 because EBX is decreased only later
  951. movb %al,1(%edi,%ecx)
  952. incl %ecx
  953. decl %ebx
  954. jnz .LM5
  955. movb %cl,(%edi) // Copy String length
  956. end;
  957. end;
  958. {****************************************************************************
  959. Bounds Check
  960. ****************************************************************************}
  961. {$ifndef NOBOUNDCHECK}
  962. {$define FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
  963. {$ifdef SYSTEMDEBUG}
  964. { we want the stack for debugging !! PM }
  965. procedure int_boundcheck;[public,alias: 'FPC_BOUNDCHECK'];
  966. begin
  967. {$else not SYSTEMDEBUG}
  968. procedure int_boundcheck;assembler;[public,alias: 'FPC_BOUNDCHECK'];
  969. var dummy_to_force_stackframe_generation_for_trace: Longint;
  970. {$endif not SYSTEMDEBUG}
  971. {
  972. called with:
  973. %ecx - value
  974. %edi - pointer to the ranges
  975. }
  976. asm
  977. cmpl (%edi),%ecx
  978. jl .Lbc_err
  979. cmpl 4(%edi),%ecx
  980. jle .Lbc_ok
  981. .Lbc_err:
  982. pushl %ebp
  983. pushl $201
  984. call HandleErrorFrame
  985. .Lbc_ok:
  986. end;
  987. {$ifdef SYSTEMDEBUG}
  988. end;
  989. {$endif def SYSTEMDEBUG}
  990. {$endif NOBOUNDCHECK}
  991. { do a thread save inc/dec }
  992. procedure declocked(var l : longint);assembler;
  993. asm
  994. {$ifdef MTRTL}
  995. { this check should be done because a lock takes a lot }
  996. { of time! }
  997. cmpb $0,IsMultithreaded
  998. jz .Ldeclockednolock
  999. movl l,%edi
  1000. lock
  1001. decl (%edi)
  1002. jmp .Ldeclockedend
  1003. .Ldeclockednolock:
  1004. {$endif MTRTL}
  1005. movl l,%edi
  1006. decl (%edi);
  1007. .Ldeclockedend:
  1008. end ['EDI'];
  1009. procedure inclocked(var l : longint);assembler;
  1010. asm
  1011. {$ifdef MTRTL}
  1012. { this check should be done because a lock takes a lot }
  1013. { of time! }
  1014. cmpb $0,IsMultithreaded
  1015. jz .Linclockednolock
  1016. movl l,%edi
  1017. lock
  1018. incl (%edi)
  1019. jmp .Linclockedend
  1020. .Linclockednolock:
  1021. {$endif MTRTL}
  1022. movl l,%edi
  1023. incl (%edi);
  1024. .Linclockedend:
  1025. end ['EDI'];
  1026. {
  1027. $Log$
  1028. Revision 1.10 2001-04-16 11:22:53 peter
  1029. * merged popal fix
  1030. Revision 1.9 2001/04/08 13:19:28 jonas
  1031. * optimized FPC_HELP_CONSTRUCTOR a bit
  1032. Revision 1.8 2001/03/05 17:10:04 jonas
  1033. * moved implementations of strlen and strpas to separate include files
  1034. (they were duplicated in i386.inc and strings.inc/stringss.inc)
  1035. * strpas supports 'nil' pchars again (returns an empty string)
  1036. (both merged)
  1037. Revision 1.7 2001/03/04 17:31:34 jonas
  1038. * fixed all implementations of strpas
  1039. Revision 1.5 2000/11/12 23:23:34 florian
  1040. * interfaces basically running
  1041. Revision 1.4 2000/11/07 23:42:21 florian
  1042. + AfterConstruction and BeforeDestruction implemented
  1043. + TInterfacedObject implemented
  1044. Revision 1.3 2000/07/14 10:33:09 michael
  1045. + Conditionals fixed
  1046. Revision 1.2 2000/07/13 11:33:41 michael
  1047. + removed logs
  1048. }