i386.inc 36 KB

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