i386.inc 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246
  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 .LHC_6
  409. { Why was the VMT reset to zero here ????
  410. I need it fail to know if I should
  411. zero the VMT field in static objects PM }
  412. .LHC_4:
  413. { movl $0,8(%ebp) }
  414. .LHC_6:
  415. { is there a VMT address ? }
  416. orl %eax,%eax
  417. jnz .LHC_7
  418. { In case the constructor doesn't do anything, the Zero-Flag }
  419. { can't be put, because this calls Fail() }
  420. incl %eax
  421. ret
  422. .LHC_7:
  423. { set zero inside the object }
  424. pushal
  425. cld
  426. movl (%eax),%ecx
  427. movl %esi,%edi
  428. xorl %eax,%eax
  429. shrl $1,%ecx
  430. jnc .LHCFill1
  431. stosb
  432. .LHCFill1:
  433. shrl $1,%ecx
  434. jnc .LHCFill2
  435. stosw
  436. .LHCFill2:
  437. rep
  438. stosl
  439. popal
  440. { set the VMT address for the new created object }
  441. { the offset is in %edi since the calling and has not been changed !! }
  442. movl %eax,(%esi,%edi,1)
  443. orl %eax,%eax
  444. .LHC_5:
  445. end;
  446. {$define FPC_SYSTEM_HAS_FPC_HELP_FAIL}
  447. procedure int_help_fail;assembler;[public,alias:'FPC_HELP_FAIL'];
  448. { should be called with a object that needs to be
  449. freed if VMT field is at -1
  450. %edi contains VMT offset in object again }
  451. asm
  452. orl %esi,%esi
  453. je .LHF_1
  454. cmpl $-1,8(%ebp)
  455. je .LHF_2
  456. { reset vmt field to zero for static instances }
  457. cmpl $0,8(%ebp)
  458. je .LHF_3
  459. { main constructor, we can zero the VMT field now }
  460. movl $0,(%esi,%edi,1)
  461. .LHF_3:
  462. { we zero esi to indicate failure }
  463. xorl %esi,%esi
  464. jmp .LHF_1
  465. .LHF_2:
  466. { get vmt address in eax }
  467. movl (%esi,%edi,1),%eax
  468. movl %esi,12(%ebp)
  469. { push object position }
  470. leal 12(%ebp),%eax
  471. pushl %eax
  472. call AsmFreeMem
  473. { set both object places to zero }
  474. xorl %esi,%esi
  475. movl %esi,12(%ebp)
  476. .LHF_1:
  477. end;
  478. {$define FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  479. procedure int_help_destructor;assembler;[public,alias:'FPC_HELP_DESTRUCTOR'];
  480. asm
  481. { Stack (relative to %ebp):
  482. 12 Self
  483. 8 VMT-Address
  484. 4 Main program-Addr
  485. 0 %ebp
  486. edi contains the vmt position
  487. }
  488. pushal
  489. { Should the object be resolved ? }
  490. movl 8(%ebp),%eax
  491. orl %eax,%eax
  492. jz .LHD_3
  493. { Yes, get size from SELF! }
  494. movl 12(%ebp),%eax
  495. { get VMT-pointer (from Self) to %ebx }
  496. { the offset is in %edi since the calling and has not been changed !! }
  497. movl (%eax,%edi,1),%ebx
  498. { I think for precaution }
  499. { that we should clear the VMT here }
  500. movl $0,(%eax,%edi,1)
  501. { temporary Variable }
  502. subl $4,%esp
  503. movl %esp,%edi
  504. { SELF }
  505. movl %eax,(%edi)
  506. pushl %edi
  507. call AsmFreeMem
  508. addl $4,%esp
  509. .LHD_3:
  510. popal
  511. end;
  512. {$define FPC_SYSTEM_HAS_FPC_NEW_CLASS}
  513. procedure int_new_class;assembler;[public,alias:'FPC_NEW_CLASS'];
  514. asm
  515. { to be sure in the future, we save also edit }
  516. pushl %edi
  517. { create class ? }
  518. movl 8(%ebp),%edi
  519. { if we test eax later without calling newinstance }
  520. { it must have a value <>0 }
  521. movl $1,%eax
  522. orl %edi,%edi
  523. jz .LNEW_CLASS1
  524. { save registers !! }
  525. pushl %ebx
  526. pushl %ecx
  527. pushl %edx
  528. { esi contains the vmt }
  529. pushl %esi
  530. { call newinstance (class method!) }
  531. {$ifdef NEWVMTOFFSET}
  532. call *52{vmtNewInstance}(%esi)
  533. {$else}
  534. call *16(%esi)
  535. {$endif}
  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. orl %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. orl %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. {$ifdef NEWVMTOFFSET}
  568. call *56{vmtFreeInstance}(%edi)
  569. {$else}
  570. call *20(%edi)
  571. {$endif}
  572. popl %edx
  573. popl %ecx
  574. popl %ebx
  575. popl %eax
  576. .LDISPOSE_CLASS1:
  577. popl %edi
  578. end;
  579. {$define FPC_SYSTEM_HAS_FPC_HELP_FAIL_CLASS}
  580. procedure int_help_fail_class;assembler;[public,alias:'FPC_HELP_FAIL_CLASS'];
  581. { a non zero class must allways be disposed
  582. VMT is allways at pos 0 }
  583. asm
  584. orl %esi,%esi
  585. je .LHFC_1
  586. call INT_DISPOSE_CLASS
  587. { set both object places to zero }
  588. xorl %esi,%esi
  589. movl %esi,8(%ebp)
  590. .LHFC_1:
  591. end;
  592. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  593. {$ifdef SYSTEMDEBUG}
  594. { we want the stack for debugging !! PM }
  595. procedure int_check_object(obj : pointer);[public,alias:'FPC_CHECK_OBJECT'];
  596. begin
  597. {$else not SYSTEMDEBUG}
  598. procedure int_check_object;assembler;[public,alias:'FPC_CHECK_OBJECT'];
  599. {$endif not SYSTEMDEBUG}
  600. asm
  601. pushl %edi
  602. {$ifdef SYSTEMDEBUG}
  603. movl obj,%edi
  604. {$else not SYSTEMDEBUG}
  605. movl 8(%esp),%edi
  606. {$endif not SYSTEMDEBUG}
  607. pushl %eax
  608. { Here we must check if the VMT pointer is nil before }
  609. { accessing it... }
  610. orl %edi,%edi
  611. jz .Lco_re
  612. movl (%edi),%eax
  613. addl 4(%edi),%eax
  614. jz .Lco_ok
  615. .Lco_re:
  616. pushl $210
  617. call HandleError
  618. .Lco_ok:
  619. popl %eax
  620. popl %edi
  621. { the adress is pushed : it needs to be removed from stack !! PM }
  622. {$ifdef SYSTEMDEBUG}
  623. end;{ of asm }
  624. end;
  625. {$else SYSTEMDEBUG}
  626. ret $4
  627. end;
  628. {$endif not SYSTEMDEBUG}
  629. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  630. procedure int_check_object_ext;assembler;[public,alias:'FPC_CHECK_OBJECT_EXT'];
  631. { checks for a correct vmt pointer }
  632. { deeper check to see if the current object is }
  633. { really related to the true }
  634. asm
  635. pushl %ebp
  636. movl %esp,%ebp
  637. pushl %edi
  638. movl 8(%ebp),%edi
  639. pushl %ebx
  640. movl 12(%ebp),%ebx
  641. pushl %eax
  642. { Here we must check if the VMT pointer is nil before }
  643. { accessing it... }
  644. .Lcoext_obj:
  645. orl %edi,%edi
  646. jz .Lcoext_re
  647. movl (%edi),%eax
  648. addl 4(%edi),%eax
  649. jnz .Lcoext_re
  650. cmpl %edi,%ebx
  651. je .Lcoext_ok
  652. .Lcoext_vmt:
  653. movl 8(%edi),%eax
  654. cmpl %ebx,%eax
  655. je .Lcoext_ok
  656. movl %eax,%edi
  657. jmp .Lcoext_obj
  658. .Lcoext_re:
  659. pushl $220
  660. call HandleError
  661. .Lcoext_ok:
  662. popl %eax
  663. popl %ebx
  664. popl %edi
  665. { the adress and vmt were pushed : it needs to be removed from stack !! PM }
  666. popl %ebp
  667. ret $8
  668. end;
  669. {****************************************************************************
  670. String
  671. ****************************************************************************}
  672. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COPY}
  673. procedure int_strcopy(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_COPY'];
  674. {
  675. this procedure must save all modified registers except EDI and ESI !!!
  676. }
  677. begin
  678. asm
  679. pushl %eax
  680. pushl %ecx
  681. cld
  682. movl dstr,%edi
  683. movl sstr,%esi
  684. xorl %eax,%eax
  685. movl len,%ecx
  686. lodsb
  687. cmpl %ecx,%eax
  688. jbe .LStrCopy1
  689. movl %ecx,%eax
  690. .LStrCopy1:
  691. stosb
  692. cmpl $7,%eax
  693. jl .LStrCopy2
  694. movl %edi,%ecx { Align on 32bits }
  695. negl %ecx
  696. andl $3,%ecx
  697. subl %ecx,%eax
  698. rep
  699. movsb
  700. movl %eax,%ecx
  701. andl $3,%eax
  702. shrl $2,%ecx
  703. rep
  704. movsl
  705. .LStrCopy2:
  706. movl %eax,%ecx
  707. rep
  708. movsb
  709. popl %ecx
  710. popl %eax
  711. end ['ESI','EDI'];
  712. end;
  713. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  714. procedure int_strconcat(s1,s2:pointer);
  715. [public,alias:'FPC_SHORTSTR_CONCAT'];
  716. begin
  717. asm
  718. movl s2,%edi
  719. movl s1,%esi
  720. movl %edi,%ebx
  721. movzbl (%edi),%ecx
  722. xor %eax,%eax
  723. lea 1(%edi,%ecx),%edi
  724. negl %ecx
  725. addl $0x0ff,%ecx
  726. lodsb
  727. cmpl %ecx,%eax
  728. jbe .LStrConcat1
  729. movl %ecx,%eax
  730. .LStrConcat1:
  731. addb %al,(%ebx)
  732. cmpl $7,%eax
  733. jl .LStrConcat2
  734. movl %edi,%ecx { Align on 32bits }
  735. negl %ecx
  736. andl $3,%ecx
  737. subl %ecx,%eax
  738. rep
  739. movsb
  740. movl %eax,%ecx
  741. andl $3,%eax
  742. shrl $2,%ecx
  743. rep
  744. movsl
  745. .LStrConcat2:
  746. movl %eax,%ecx
  747. rep
  748. movsb
  749. end ['EBX','ECX','EAX','ESI','EDI'];
  750. end;
  751. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  752. procedure int_strcmp(dstr,sstr:pointer);[public,alias:'FPC_SHORTSTR_COMPARE'];
  753. begin
  754. asm
  755. cld
  756. xorl %ebx,%ebx
  757. xorl %eax,%eax
  758. movl sstr,%esi
  759. movl dstr,%edi
  760. movb (%esi),%al
  761. movb (%edi),%bl
  762. movl %eax,%edx
  763. incl %esi
  764. incl %edi
  765. cmpl %ebx,%eax
  766. jbe .LStrCmp1
  767. movl %ebx,%eax
  768. .LStrCmp1:
  769. cmpl $7,%eax
  770. jl .LStrCmp2
  771. movl %edi,%ecx { Align on 32bits }
  772. negl %ecx
  773. andl $3,%ecx
  774. subl %ecx,%eax
  775. orl %ecx,%ecx
  776. rep
  777. cmpsb
  778. jne .LStrCmp3
  779. movl %eax,%ecx
  780. andl $3,%eax
  781. shrl $2,%ecx
  782. orl %ecx,%ecx
  783. rep
  784. cmpsl
  785. je .LStrCmp2
  786. movl $4,%eax
  787. sub %eax,%esi
  788. sub %eax,%edi
  789. .LStrCmp2:
  790. movl %eax,%ecx
  791. orl %eax,%eax
  792. rep
  793. cmpsb
  794. jne .LStrCmp3
  795. cmp %ebx,%edx
  796. .LStrCmp3:
  797. end ['EDX','ECX','EBX','EAX','ESI','EDI'];
  798. end;
  799. {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  800. function strpas(p:pchar):shortstring;[public,alias:'FPC_PCHAR_TO_SHORTSTR'];
  801. begin
  802. asm
  803. cld
  804. movl p,%edi
  805. movl $0xff,%ecx
  806. orl %edi,%edi
  807. jnz .LStrPasNotNil
  808. decl %ecx
  809. jmp .LStrPasNil
  810. .LStrPasNotNil:
  811. xorl %eax,%eax
  812. movl %edi,%esi
  813. repne
  814. scasb
  815. .LStrPasNil:
  816. movl %ecx,%eax
  817. movl __RESULT,%edi
  818. notb %al
  819. decl %eax
  820. stosb
  821. cmpl $7,%eax
  822. jl .LStrPas2
  823. movl %edi,%ecx { Align on 32bits }
  824. negl %ecx
  825. andl $3,%ecx
  826. subl %ecx,%eax
  827. rep
  828. movsb
  829. movl %eax,%ecx
  830. andl $3,%eax
  831. shrl $2,%ecx
  832. rep
  833. movsl
  834. .LStrPas2:
  835. movl %eax,%ecx
  836. rep
  837. movsb
  838. end ['ECX','EAX','ESI','EDI'];
  839. end;
  840. {$define FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  841. function strchararray(p:pchar; l : longint):shortstring;[public,alias:'FPC_CHARARRAY_TO_SHORTSTR'];
  842. begin
  843. asm
  844. cld
  845. movl p,%esi
  846. movl l,%ecx
  847. orl %esi,%esi
  848. jnz .LStrCharArrayNotNil
  849. movl $0,%ecx
  850. .LStrCharArrayNotNil:
  851. movl %ecx,%eax
  852. movl __RESULT,%edi
  853. stosb
  854. cmpl $7,%eax
  855. jl .LStrCharArray2
  856. movl %edi,%ecx { Align on 32bits }
  857. negl %ecx
  858. andl $3,%ecx
  859. subl %ecx,%eax
  860. rep
  861. movsb
  862. movl %eax,%ecx
  863. andl $3,%eax
  864. shrl $2,%ecx
  865. rep
  866. movsl
  867. .LStrCharArray2:
  868. movl %eax,%ecx
  869. rep
  870. movsb
  871. end ['ECX','EAX','ESI','EDI'];
  872. end;
  873. {$define FPC_SYSTEM_HAS_STRLEN}
  874. function strlen(p:pchar):longint;assembler;
  875. asm
  876. movl p,%edi
  877. movl $0xffffffff,%ecx
  878. xorl %eax,%eax
  879. cld
  880. repne
  881. scasb
  882. movl $0xfffffffe,%eax
  883. subl %ecx,%eax
  884. end ['EDI','ECX','EAX'];
  885. {****************************************************************************
  886. Caller/StackFrame Helpers
  887. ****************************************************************************}
  888. {$define FPC_SYSTEM_HAS_GET_FRAME}
  889. function get_frame:longint;assembler;
  890. asm
  891. movl %ebp,%eax
  892. end ['EAX'];
  893. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  894. function get_caller_addr(framebp:longint):longint;assembler;
  895. asm
  896. movl framebp,%eax
  897. orl %eax,%eax
  898. jz .Lg_a_null
  899. movl 4(%eax),%eax
  900. .Lg_a_null:
  901. end ['EAX'];
  902. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  903. function get_caller_frame(framebp:longint):longint;assembler;
  904. asm
  905. movl framebp,%eax
  906. orl %eax,%eax
  907. jz .Lgnf_null
  908. movl (%eax),%eax
  909. .Lgnf_null:
  910. end ['EAX'];
  911. {****************************************************************************
  912. Math
  913. ****************************************************************************}
  914. {$define FPC_SYSTEM_HAS_ABS_LONGINT}
  915. function abs(l:longint):longint; assembler;[internconst:in_const_abs];
  916. asm
  917. movl l,%eax
  918. cltd
  919. xorl %edx,%eax
  920. subl %edx,%eax
  921. end ['EAX','EDX'];
  922. {$define FPC_SYSTEM_HAS_ODD_LONGINT}
  923. function odd(l:longint):boolean;assembler;[internconst:in_const_odd];
  924. asm
  925. movl l,%eax
  926. andl $1,%eax
  927. setnz %al
  928. end ['EAX'];
  929. {$define FPC_SYSTEM_HAS_SQR_LONGINT}
  930. function sqr(l:longint):longint;assembler;[internconst:in_const_sqr];
  931. asm
  932. mov l,%eax
  933. imull %eax,%eax
  934. end ['EAX'];
  935. {$define FPC_SYSTEM_HAS_SPTR}
  936. Function Sptr : Longint;assembler;
  937. asm
  938. movl %esp,%eax
  939. end;
  940. {****************************************************************************
  941. Str()
  942. ****************************************************************************}
  943. {$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
  944. procedure int_str(l : longint;var s : string);
  945. var
  946. buffer : array[0..11] of byte;
  947. begin
  948. { Workaround: }
  949. if l=$80000000 then
  950. begin
  951. s:='-2147483648';
  952. exit;
  953. end;
  954. asm
  955. movl l,%eax // load Integer
  956. movl s,%edi // Load String address
  957. xorl %ecx,%ecx // String length=0
  958. xorl %ebx,%ebx // Buffer length=0
  959. movl $0x0a,%esi // load 10 as dividing constant.
  960. orl %eax,%eax // Sign ?
  961. jns .LM2
  962. neg %eax
  963. movb $0x2d,1(%edi) // put '-' in String
  964. incl %ecx
  965. .LM2:
  966. cltd
  967. idivl %esi
  968. addb $0x30,%dl // convert Rest to ASCII.
  969. movb %dl,-12(%ebp,%ebx)
  970. incl %ebx
  971. cmpl $0,%eax
  972. jnz .LM2
  973. { copy String }
  974. .LM3:
  975. movb -13(%ebp,%ebx),%al // -13 because EBX is decreased only later
  976. movb %al,1(%edi,%ecx)
  977. incl %ecx
  978. decl %ebx
  979. jnz .LM3
  980. movb %cl,(%edi) // Copy String length
  981. end;
  982. end;
  983. {$define FPC_SYSTEM_HAS_INT_STR_CARDINAL}
  984. procedure int_str(c : cardinal;var s : string);
  985. var
  986. buffer : array[0..14] of byte;
  987. begin
  988. asm
  989. movl c,%eax // load CARDINAL
  990. movl s,%edi // Load String address
  991. xorl %ecx,%ecx // String length=0
  992. xorl %ebx,%ebx // Buffer length=0
  993. movl $0x0a,%esi // load 10 as dividing constant.
  994. .LM4:
  995. xorl %edx,%edx
  996. divl %esi
  997. addb $0x30,%dl // convert Rest to ASCII.
  998. movb %dl,-12(%ebp,%ebx)
  999. incl %ebx
  1000. cmpl $0,%eax
  1001. jnz .LM4
  1002. { now copy the string }
  1003. .LM5:
  1004. movb -13(%ebp,%ebx),%al // -13 because EBX is decreased only later
  1005. movb %al,1(%edi,%ecx)
  1006. incl %ecx
  1007. decl %ebx
  1008. jnz .LM5
  1009. movb %cl,(%edi) // Copy String length
  1010. end;
  1011. end;
  1012. {****************************************************************************
  1013. Bounds Check
  1014. ****************************************************************************}
  1015. {$define FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
  1016. {$ifdef SYSTEMDEBUG}
  1017. { we want the stack for debugging !! PM }
  1018. procedure int_boundcheck;[public,alias: 'FPC_BOUNDCHECK'];
  1019. begin
  1020. {$else not SYSTEMDEBUG}
  1021. procedure int_boundcheck;assembler;[public,alias: 'FPC_BOUNDCHECK'];
  1022. var dummy_to_force_stackframe_generation_for_trace: Longint;
  1023. {$endif not SYSTEMDEBUG}
  1024. {
  1025. called with:
  1026. %ecx - value
  1027. %edi - pointer to the ranges
  1028. }
  1029. asm
  1030. cmpl (%edi),%ecx
  1031. jl .Lbc_err
  1032. cmpl 4(%edi),%ecx
  1033. jle .Lbc_ok
  1034. .Lbc_err:
  1035. pushl %ebp
  1036. pushl $201
  1037. call HandleErrorFrame
  1038. .Lbc_ok:
  1039. end;
  1040. {$ifdef SYSTEMDEBUG}
  1041. end;
  1042. {$endif def SYSTEMDEBUG}
  1043. {$ifndef HASSAVEREGISTERS}
  1044. {****************************************************************************
  1045. IoCheck
  1046. ****************************************************************************}
  1047. {$define FPC_SYSTEM_HAS_FPC_IOCHECK}
  1048. procedure int_iocheck(addr : longint);[public,alias:'FPC_IOCHECK'];
  1049. var
  1050. l : longint;
  1051. begin
  1052. asm
  1053. pushal
  1054. end;
  1055. if InOutRes<>0 then
  1056. begin
  1057. l:=InOutRes;
  1058. InOutRes:=0;
  1059. HandleErrorFrame(l,get_frame);
  1060. end;
  1061. asm
  1062. popal
  1063. end;
  1064. end;
  1065. {$endif not HASSAVEREGISTERS}
  1066. {
  1067. $Log$
  1068. Revision 1.1 2000-07-13 06:30:41 michael
  1069. + Initial import
  1070. Revision 1.75 2000/07/08 09:09:35 jonas
  1071. - removed fpc_strconcat_len for -dnewoptimizations since it's not
  1072. used anymore (because the strconcat optimizations have been
  1073. disabled quite a while ago)
  1074. Revision 1.74 2000/07/07 18:23:41 marco
  1075. * Changed move (var source;var dest) to move (const source;var dest)
  1076. Revision 1.73 2000/05/09 06:21:58 pierre
  1077. * fix ingnored assembler error in IndexDWord
  1078. Revision 1.72 2000/04/23 09:26:51 jonas
  1079. + FPC_SHORTSTR_CONCAT_LEN (temporary, for -dnewoptimizations)
  1080. Revision 1.71 2000/04/10 09:47:15 jonas
  1081. + added destroyed registers list for move procedure (it doesn't destroy
  1082. edx)
  1083. Revision 1.70 2000/04/06 08:39:22 florian
  1084. * the bounds check error gets now a correct stack frame
  1085. Revision 1.69 2000/02/09 16:59:29 peter
  1086. * truncated log
  1087. Revision 1.68 2000/01/13 13:06:03 jonas
  1088. * fixed warning
  1089. Revision 1.67 2000/01/11 21:11:04 marco
  1090. * Changed some direct asm params to real params
  1091. Revision 1.66 2000/01/10 09:54:30 peter
  1092. * primitives added
  1093. Revision 1.65 2000/01/07 16:41:32 daniel
  1094. * copyright 2000
  1095. Revision 1.64 2000/01/07 16:32:24 daniel
  1096. * copyright 2000 added
  1097. Revision 1.63 1999/12/21 11:48:09 pierre
  1098. * typo error if previous commit
  1099. Revision 1.62 1999/12/21 11:13:34 pierre
  1100. + FPC_CHARARRAY_TO_SHORTSTRING added
  1101. Revision 1.61 1999/12/11 18:59:44 jonas
  1102. * faster abs() function (no jump anymore)
  1103. Revision 1.60 1999/11/20 12:48:09 jonas
  1104. * reinstated old random generator, but modified it so the integer
  1105. one now has a much longer period
  1106. Revision 1.59 1999/11/09 20:14:12 daniel
  1107. * Committed new random generator.
  1108. Revision 1.58 1999/10/30 17:39:05 peter
  1109. * memorymanager expanded with allocmem/reallocmem
  1110. Revision 1.57 1999/10/08 14:40:54 pierre
  1111. * fix for FPC_HELP_FAIL_CLASS
  1112. Revision 1.56 1999/10/05 20:50:06 pierre
  1113. + code for fail for class
  1114. Revision 1.55 1999/09/17 17:14:11 peter
  1115. + new heap manager supporting delphi freemem(pointer)
  1116. Revision 1.54 1999/09/15 13:04:04 jonas
  1117. * added dummy local var to boundcheck to force stackframe generation
  1118. Revision 1.53 1999/08/19 12:50:08 pierre
  1119. * changes for fail support
  1120. Revision 1.52 1999/08/18 10:43:31 pierre
  1121. + VMT reset to -1 if getmem called, neede for fail
  1122. Revision 1.51 1999/08/09 22:20:02 peter
  1123. * classes vmt changed to only positive addresses
  1124. * sharedlib creation is working
  1125. Revision 1.50 1999/08/05 23:45:12 peter
  1126. * saveregister is now working and used for assert and iocheck (which has
  1127. been moved to system.inc because it's now system independent)
  1128. }