i386.inc 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175
  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. call *52{vmtNewInstance}(%esi)
  532. popl %edx
  533. popl %ecx
  534. popl %ebx
  535. { newinstance returns a pointer to the new created }
  536. { instance in eax }
  537. { load esi and insert self }
  538. movl %eax,%esi
  539. .LNEW_CLASS1:
  540. movl %esi,8(%ebp)
  541. orl %eax,%eax
  542. popl %edi
  543. end;
  544. {$define FPC_SYSTEM_HAS_FPC_DISPOSE_CLASS}
  545. procedure int_dispose_class;assembler;[public,alias:'FPC_DISPOSE_CLASS'];
  546. asm
  547. { to be sure in the future, we save also edit }
  548. pushl %edi
  549. { destroy class ? }
  550. movl 12(%ebp),%edi
  551. orl %edi,%edi
  552. jz .LDISPOSE_CLASS1
  553. { no inherited call }
  554. movl (%esi),%edi
  555. { save registers !! }
  556. pushl %eax
  557. pushl %ebx
  558. pushl %ecx
  559. pushl %edx
  560. { push self }
  561. pushl %esi
  562. { call freeinstance }
  563. call *56{vmtFreeInstance}(%edi)
  564. popl %edx
  565. popl %ecx
  566. popl %ebx
  567. popl %eax
  568. .LDISPOSE_CLASS1:
  569. popl %edi
  570. end;
  571. {$define FPC_SYSTEM_HAS_FPC_HELP_FAIL_CLASS}
  572. procedure int_help_fail_class;assembler;[public,alias:'FPC_HELP_FAIL_CLASS'];
  573. { a non zero class must allways be disposed
  574. VMT is allways at pos 0 }
  575. asm
  576. orl %esi,%esi
  577. je .LHFC_1
  578. call INT_DISPOSE_CLASS
  579. { set both object places to zero }
  580. xorl %esi,%esi
  581. movl %esi,8(%ebp)
  582. .LHFC_1:
  583. end;
  584. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  585. {$ifdef SYSTEMDEBUG}
  586. { we want the stack for debugging !! PM }
  587. procedure int_check_object(obj : pointer);[public,alias:'FPC_CHECK_OBJECT'];
  588. begin
  589. {$else not SYSTEMDEBUG}
  590. procedure int_check_object;assembler;[public,alias:'FPC_CHECK_OBJECT'];
  591. {$endif not SYSTEMDEBUG}
  592. asm
  593. pushl %edi
  594. {$ifdef SYSTEMDEBUG}
  595. movl obj,%edi
  596. {$else not SYSTEMDEBUG}
  597. movl 8(%esp),%edi
  598. {$endif not SYSTEMDEBUG}
  599. pushl %eax
  600. { Here we must check if the VMT pointer is nil before }
  601. { accessing it... }
  602. orl %edi,%edi
  603. jz .Lco_re
  604. movl (%edi),%eax
  605. addl 4(%edi),%eax
  606. jz .Lco_ok
  607. .Lco_re:
  608. pushl $210
  609. call HandleError
  610. .Lco_ok:
  611. popl %eax
  612. popl %edi
  613. { the adress is pushed : it needs to be removed from stack !! PM }
  614. {$ifdef SYSTEMDEBUG}
  615. end;{ of asm }
  616. end;
  617. {$else SYSTEMDEBUG}
  618. ret $4
  619. end;
  620. {$endif not SYSTEMDEBUG}
  621. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  622. procedure int_check_object_ext;assembler;[public,alias:'FPC_CHECK_OBJECT_EXT'];
  623. { checks for a correct vmt pointer }
  624. { deeper check to see if the current object is }
  625. { really related to the true }
  626. asm
  627. pushl %ebp
  628. movl %esp,%ebp
  629. pushl %edi
  630. movl 8(%ebp),%edi
  631. pushl %ebx
  632. movl 12(%ebp),%ebx
  633. pushl %eax
  634. { Here we must check if the VMT pointer is nil before }
  635. { accessing it... }
  636. .Lcoext_obj:
  637. orl %edi,%edi
  638. jz .Lcoext_re
  639. movl (%edi),%eax
  640. addl 4(%edi),%eax
  641. jnz .Lcoext_re
  642. cmpl %edi,%ebx
  643. je .Lcoext_ok
  644. .Lcoext_vmt:
  645. movl 8(%edi),%eax
  646. cmpl %ebx,%eax
  647. je .Lcoext_ok
  648. movl %eax,%edi
  649. jmp .Lcoext_obj
  650. .Lcoext_re:
  651. pushl $220
  652. call HandleError
  653. .Lcoext_ok:
  654. popl %eax
  655. popl %ebx
  656. popl %edi
  657. { the adress and vmt were pushed : it needs to be removed from stack !! PM }
  658. popl %ebp
  659. ret $8
  660. end;
  661. {****************************************************************************
  662. String
  663. ****************************************************************************}
  664. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COPY}
  665. procedure int_strcopy(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_COPY'];
  666. {
  667. this procedure must save all modified registers except EDI and ESI !!!
  668. }
  669. begin
  670. asm
  671. pushl %eax
  672. pushl %ecx
  673. cld
  674. movl dstr,%edi
  675. movl sstr,%esi
  676. xorl %eax,%eax
  677. movl len,%ecx
  678. lodsb
  679. cmpl %ecx,%eax
  680. jbe .LStrCopy1
  681. movl %ecx,%eax
  682. .LStrCopy1:
  683. stosb
  684. cmpl $7,%eax
  685. jl .LStrCopy2
  686. movl %edi,%ecx { Align on 32bits }
  687. negl %ecx
  688. andl $3,%ecx
  689. subl %ecx,%eax
  690. rep
  691. movsb
  692. movl %eax,%ecx
  693. andl $3,%eax
  694. shrl $2,%ecx
  695. rep
  696. movsl
  697. .LStrCopy2:
  698. movl %eax,%ecx
  699. rep
  700. movsb
  701. popl %ecx
  702. popl %eax
  703. end ['ESI','EDI'];
  704. end;
  705. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  706. procedure int_strconcat(s1,s2:pointer);
  707. [public,alias:'FPC_SHORTSTR_CONCAT'];
  708. begin
  709. asm
  710. movl s2,%edi
  711. movl s1,%esi
  712. movl %edi,%ebx
  713. movzbl (%edi),%ecx
  714. xor %eax,%eax
  715. lea 1(%edi,%ecx),%edi
  716. negl %ecx
  717. addl $0x0ff,%ecx
  718. lodsb
  719. cmpl %ecx,%eax
  720. jbe .LStrConcat1
  721. movl %ecx,%eax
  722. .LStrConcat1:
  723. addb %al,(%ebx)
  724. cmpl $7,%eax
  725. jl .LStrConcat2
  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. .LStrConcat2:
  738. movl %eax,%ecx
  739. rep
  740. movsb
  741. end ['EBX','ECX','EAX','ESI','EDI'];
  742. end;
  743. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  744. procedure int_strcmp(dstr,sstr:pointer);[public,alias:'FPC_SHORTSTR_COMPARE'];
  745. begin
  746. asm
  747. cld
  748. xorl %ebx,%ebx
  749. xorl %eax,%eax
  750. movl sstr,%esi
  751. movl dstr,%edi
  752. movb (%esi),%al
  753. movb (%edi),%bl
  754. movl %eax,%edx
  755. incl %esi
  756. incl %edi
  757. cmpl %ebx,%eax
  758. jbe .LStrCmp1
  759. movl %ebx,%eax
  760. .LStrCmp1:
  761. cmpl $7,%eax
  762. jl .LStrCmp2
  763. movl %edi,%ecx { Align on 32bits }
  764. negl %ecx
  765. andl $3,%ecx
  766. subl %ecx,%eax
  767. orl %ecx,%ecx
  768. rep
  769. cmpsb
  770. jne .LStrCmp3
  771. movl %eax,%ecx
  772. andl $3,%eax
  773. shrl $2,%ecx
  774. orl %ecx,%ecx
  775. rep
  776. cmpsl
  777. je .LStrCmp2
  778. movl $4,%eax
  779. sub %eax,%esi
  780. sub %eax,%edi
  781. .LStrCmp2:
  782. movl %eax,%ecx
  783. orl %eax,%eax
  784. rep
  785. cmpsb
  786. jne .LStrCmp3
  787. cmp %ebx,%edx
  788. .LStrCmp3:
  789. end ['EDX','ECX','EBX','EAX','ESI','EDI'];
  790. end;
  791. {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  792. function strpas(p:pchar):shortstring;[public,alias:'FPC_PCHAR_TO_SHORTSTR'];
  793. begin
  794. asm
  795. cld
  796. movl p,%edi
  797. movl $0xff,%ecx
  798. orl %edi,%edi
  799. jnz .LStrPasNotNil
  800. decl %ecx
  801. jmp .LStrPasNil
  802. .LStrPasNotNil:
  803. xorl %eax,%eax
  804. movl %edi,%esi
  805. repne
  806. scasb
  807. .LStrPasNil:
  808. movl %ecx,%eax
  809. movl __RESULT,%edi
  810. notb %al
  811. decl %eax
  812. stosb
  813. cmpl $7,%eax
  814. jl .LStrPas2
  815. movl %edi,%ecx { Align on 32bits }
  816. negl %ecx
  817. andl $3,%ecx
  818. subl %ecx,%eax
  819. rep
  820. movsb
  821. movl %eax,%ecx
  822. andl $3,%eax
  823. shrl $2,%ecx
  824. rep
  825. movsl
  826. .LStrPas2:
  827. movl %eax,%ecx
  828. rep
  829. movsb
  830. end ['ECX','EAX','ESI','EDI'];
  831. end;
  832. {$define FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  833. function strchararray(p:pchar; l : longint):shortstring;[public,alias:'FPC_CHARARRAY_TO_SHORTSTR'];
  834. begin
  835. asm
  836. cld
  837. movl p,%esi
  838. movl l,%ecx
  839. orl %esi,%esi
  840. jnz .LStrCharArrayNotNil
  841. movl $0,%ecx
  842. .LStrCharArrayNotNil:
  843. movl %ecx,%eax
  844. movl __RESULT,%edi
  845. stosb
  846. cmpl $7,%eax
  847. jl .LStrCharArray2
  848. movl %edi,%ecx { Align on 32bits }
  849. negl %ecx
  850. andl $3,%ecx
  851. subl %ecx,%eax
  852. rep
  853. movsb
  854. movl %eax,%ecx
  855. andl $3,%eax
  856. shrl $2,%ecx
  857. rep
  858. movsl
  859. .LStrCharArray2:
  860. movl %eax,%ecx
  861. rep
  862. movsb
  863. end ['ECX','EAX','ESI','EDI'];
  864. end;
  865. {$define FPC_SYSTEM_HAS_STRLEN}
  866. function strlen(p:pchar):longint;assembler;
  867. asm
  868. movl p,%edi
  869. movl $0xffffffff,%ecx
  870. xorl %eax,%eax
  871. cld
  872. repne
  873. scasb
  874. movl $0xfffffffe,%eax
  875. subl %ecx,%eax
  876. end ['EDI','ECX','EAX'];
  877. {****************************************************************************
  878. Caller/StackFrame Helpers
  879. ****************************************************************************}
  880. {$define FPC_SYSTEM_HAS_GET_FRAME}
  881. function get_frame:longint;assembler;
  882. asm
  883. movl %ebp,%eax
  884. end ['EAX'];
  885. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  886. function get_caller_addr(framebp:longint):longint;assembler;
  887. asm
  888. movl framebp,%eax
  889. orl %eax,%eax
  890. jz .Lg_a_null
  891. movl 4(%eax),%eax
  892. .Lg_a_null:
  893. end ['EAX'];
  894. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  895. function get_caller_frame(framebp:longint):longint;assembler;
  896. asm
  897. movl framebp,%eax
  898. orl %eax,%eax
  899. jz .Lgnf_null
  900. movl (%eax),%eax
  901. .Lgnf_null:
  902. end ['EAX'];
  903. {****************************************************************************
  904. Math
  905. ****************************************************************************}
  906. {$define FPC_SYSTEM_HAS_ABS_LONGINT}
  907. function abs(l:longint):longint; assembler;[internconst:in_const_abs];
  908. asm
  909. movl l,%eax
  910. cltd
  911. xorl %edx,%eax
  912. subl %edx,%eax
  913. end ['EAX','EDX'];
  914. {$define FPC_SYSTEM_HAS_ODD_LONGINT}
  915. function odd(l:longint):boolean;assembler;[internconst:in_const_odd];
  916. asm
  917. movl l,%eax
  918. andl $1,%eax
  919. setnz %al
  920. end ['EAX'];
  921. {$define FPC_SYSTEM_HAS_SQR_LONGINT}
  922. function sqr(l:longint):longint;assembler;[internconst:in_const_sqr];
  923. asm
  924. mov l,%eax
  925. imull %eax,%eax
  926. end ['EAX'];
  927. {$define FPC_SYSTEM_HAS_SPTR}
  928. Function Sptr : Longint;assembler;
  929. asm
  930. movl %esp,%eax
  931. end;
  932. {****************************************************************************
  933. Str()
  934. ****************************************************************************}
  935. {$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
  936. procedure int_str(l : longint;var s : string);
  937. var
  938. buffer : array[0..11] of byte;
  939. begin
  940. { Workaround: }
  941. if l=$80000000 then
  942. begin
  943. s:='-2147483648';
  944. exit;
  945. end;
  946. asm
  947. movl l,%eax // load Integer
  948. movl s,%edi // Load String address
  949. xorl %ecx,%ecx // String length=0
  950. xorl %ebx,%ebx // Buffer length=0
  951. movl $0x0a,%esi // load 10 as dividing constant.
  952. orl %eax,%eax // Sign ?
  953. jns .LM2
  954. neg %eax
  955. movb $0x2d,1(%edi) // put '-' in String
  956. incl %ecx
  957. .LM2:
  958. cltd
  959. idivl %esi
  960. addb $0x30,%dl // convert Rest to ASCII.
  961. movb %dl,-12(%ebp,%ebx)
  962. incl %ebx
  963. cmpl $0,%eax
  964. jnz .LM2
  965. { copy String }
  966. .LM3:
  967. movb -13(%ebp,%ebx),%al // -13 because EBX is decreased only later
  968. movb %al,1(%edi,%ecx)
  969. incl %ecx
  970. decl %ebx
  971. jnz .LM3
  972. movb %cl,(%edi) // Copy String length
  973. end;
  974. end;
  975. {$define FPC_SYSTEM_HAS_INT_STR_CARDINAL}
  976. procedure int_str(c : cardinal;var s : string);
  977. var
  978. buffer : array[0..14] of byte;
  979. begin
  980. asm
  981. movl c,%eax // load CARDINAL
  982. movl s,%edi // Load String address
  983. xorl %ecx,%ecx // String length=0
  984. xorl %ebx,%ebx // Buffer length=0
  985. movl $0x0a,%esi // load 10 as dividing constant.
  986. .LM4:
  987. xorl %edx,%edx
  988. divl %esi
  989. addb $0x30,%dl // convert Rest to ASCII.
  990. movb %dl,-12(%ebp,%ebx)
  991. incl %ebx
  992. cmpl $0,%eax
  993. jnz .LM4
  994. { now copy the string }
  995. .LM5:
  996. movb -13(%ebp,%ebx),%al // -13 because EBX is decreased only later
  997. movb %al,1(%edi,%ecx)
  998. incl %ecx
  999. decl %ebx
  1000. jnz .LM5
  1001. movb %cl,(%edi) // Copy String length
  1002. end;
  1003. end;
  1004. {****************************************************************************
  1005. Bounds Check
  1006. ****************************************************************************}
  1007. {$define FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
  1008. {$ifdef SYSTEMDEBUG}
  1009. { we want the stack for debugging !! PM }
  1010. procedure int_boundcheck;[public,alias: 'FPC_BOUNDCHECK'];
  1011. begin
  1012. {$else not SYSTEMDEBUG}
  1013. procedure int_boundcheck;assembler;[public,alias: 'FPC_BOUNDCHECK'];
  1014. var dummy_to_force_stackframe_generation_for_trace: Longint;
  1015. {$endif not SYSTEMDEBUG}
  1016. {
  1017. called with:
  1018. %ecx - value
  1019. %edi - pointer to the ranges
  1020. }
  1021. asm
  1022. cmpl (%edi),%ecx
  1023. jl .Lbc_err
  1024. cmpl 4(%edi),%ecx
  1025. jle .Lbc_ok
  1026. .Lbc_err:
  1027. pushl %ebp
  1028. pushl $201
  1029. call HandleErrorFrame
  1030. .Lbc_ok:
  1031. end;
  1032. {$ifdef SYSTEMDEBUG}
  1033. end;
  1034. {$endif def SYSTEMDEBUG}
  1035. { do a thread save inc/dec }
  1036. procedure declocked(var l : longint);assembler;
  1037. asm
  1038. {$ifdef MTRTL}
  1039. { this check should be done because a lock takes a lot }
  1040. { of time! }
  1041. cmpb $0,IsMultithreaded
  1042. jz .Ldeclockednolock
  1043. movl l,%edi
  1044. lock
  1045. decl (%edi)
  1046. jmp .Ldeclockedend
  1047. .Ldeclockednolock:
  1048. {$endif MTRTL}
  1049. movl l,%edi
  1050. decl (%edi);
  1051. .Ldeclockedend:
  1052. end ['EDI'];
  1053. procedure inclocked(var l : longint);assembler;
  1054. asm
  1055. {$ifdef MTRTL}
  1056. { this check should be done because a lock takes a lot }
  1057. { of time! }
  1058. cmpb $0,IsMultithreaded
  1059. jz .Linclockednolock
  1060. movl l,%edi
  1061. lock
  1062. incl (%edi)
  1063. jmp .Linclockedend
  1064. .Linclockednolock:
  1065. {$endif MTRTL}
  1066. movl l,%edi
  1067. incl (%edi);
  1068. .Linclockedend:
  1069. end ['EDI'];
  1070. {
  1071. $Log$
  1072. Revision 1.5 2000-11-12 23:23:34 florian
  1073. * interfaces basically running
  1074. Revision 1.4 2000/11/07 23:42:21 florian
  1075. + AfterConstruction and BeforeDestruction implemented
  1076. + TInterfacedObject implemented
  1077. Revision 1.3 2000/07/14 10:33:09 michael
  1078. + Conditionals fixed
  1079. Revision 1.2 2000/07/13 11:33:41 michael
  1080. + removed logs
  1081. }