i386.inc 33 KB

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