i386.inc 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270
  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. {$ifndef TEST_GENERIC}
  376. {$define FPC_SYSTEM_HAS_FPC_HELP_CONSTRUCTOR}
  377. procedure fpc_help_constructor; assembler; [public,alias:'FPC_HELP_CONSTRUCTOR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  378. asm
  379. { Entry without preamble, since we need the ESP of the constructor
  380. Stack (relative to %ebp):
  381. 12 Self
  382. 8 VMT-Address
  383. 4 main programm-Addr
  384. 0 %ebp
  385. edi contains the vmt position
  386. }
  387. { eax isn't touched anywhere, so it doesn't have to reloaded }
  388. movl 8(%ebp),%eax
  389. { initialise self ? }
  390. orl %esi,%esi
  391. jne .LHC_4
  392. { get memory, but save register first temporary variable }
  393. subl $4,%esp
  394. movl %esp,%esi
  395. { Save Register}
  396. pushal
  397. {$ifdef valuegetmem}
  398. { esi can be destroyed in fpc_getmem!!! (JM) }
  399. pushl %esi
  400. {$endif valuegetmem}
  401. { Memory size }
  402. pushl (%eax)
  403. {$ifdef valuegetmem}
  404. call fpc_getmem
  405. popl %esi
  406. movl %eax,(%esi)
  407. {$else valuegetmem}
  408. pushl %esi
  409. call AsmGetMem
  410. {$endif valuegetmem}
  411. movl $-1,8(%ebp)
  412. popal
  413. { Avoid 80386DX bug }
  414. nop
  415. { Memory position to %esi }
  416. movl (%esi),%esi
  417. addl $4,%esp
  418. { If no memory available : fail() }
  419. orl %esi,%esi
  420. jz .LHC_5
  421. { init self for the constructor }
  422. movl %esi,12(%ebp)
  423. { jmp not necessary anymore because next instruction is disabled (JM)
  424. jmp .LHC_6 }
  425. { Why was the VMT reset to zero here ????
  426. I need it fail to know if I should
  427. zero the VMT field in static objects PM }
  428. .LHC_4:
  429. { movl $0,8(%ebp) }
  430. .LHC_6:
  431. { is there a VMT address ? }
  432. orl %eax,%eax
  433. jnz .LHC_7
  434. { In case the constructor doesn't do anything, the Zero-Flag }
  435. { can't be put, because this calls Fail() }
  436. incl %eax
  437. ret
  438. .LHC_7:
  439. { set zero inside the object }
  440. pushal
  441. cld
  442. movl (%eax),%ecx
  443. movl %esi,%edi
  444. movl %ecx,%ebx
  445. xorl %eax,%eax
  446. shrl $2,%ecx
  447. andl $3,%ebx
  448. rep
  449. stosl
  450. movl %ebx,%ecx
  451. rep
  452. stosb
  453. popal
  454. { avoid the 80386DX bug }
  455. nop
  456. { set the VMT address for the new created object }
  457. { the offset is in %edi since the calling and has not been changed !! }
  458. movl %eax,(%esi,%edi,1)
  459. testl %eax,%eax
  460. .LHC_5:
  461. end;
  462. {$define FPC_SYSTEM_HAS_FPC_HELP_FAIL}
  463. procedure fpc_help_fail;assembler;[public,alias:'FPC_HELP_FAIL']; {$ifdef hascompilerproc} compilerproc; {$endif}
  464. { should be called with a object that needs to be
  465. freed if VMT field is at -1
  466. %edi contains VMT offset in object again }
  467. asm
  468. testl %esi,%esi
  469. je .LHF_1
  470. cmpl $-1,8(%ebp)
  471. je .LHF_2
  472. { reset vmt field to zero for static instances }
  473. cmpl $0,8(%ebp)
  474. je .LHF_3
  475. { main constructor, we can zero the VMT field now }
  476. movl $0,(%esi,%edi,1)
  477. .LHF_3:
  478. { we zero esi to indicate failure }
  479. xorl %esi,%esi
  480. jmp .LHF_1
  481. .LHF_2:
  482. { get vmt address in eax }
  483. movl (%esi,%edi,1),%eax
  484. movl %esi,12(%ebp)
  485. { push object position }
  486. {$ifdef valuefreemem}
  487. pushl %esi
  488. call fpc_freemem
  489. {$else valuefreemem}
  490. leal 12(%ebp),%eax
  491. pushl %eax
  492. call AsmFreeMem
  493. {$endif valuefreemem}
  494. { set both object places to zero }
  495. xorl %esi,%esi
  496. movl %esi,12(%ebp)
  497. .LHF_1:
  498. end;
  499. {$define FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  500. procedure fpc_help_destructor;assembler;[public,alias:'FPC_HELP_DESTRUCTOR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  501. asm
  502. { Stack (relative to %ebp):
  503. 12 Self
  504. 8 VMT-Address
  505. 4 Main program-Addr
  506. 0 %ebp
  507. edi contains the vmt position
  508. }
  509. pushal
  510. { Should the object be resolved ? }
  511. movl 8(%ebp),%eax
  512. orl %eax,%eax
  513. jz .LHD_3
  514. { Yes, get size from SELF! }
  515. movl 12(%ebp),%eax
  516. { get VMT-pointer (from Self) to %ebx }
  517. { the offset is in %edi since the calling and has not been changed !! }
  518. movl (%eax,%edi,1),%ebx
  519. { I think for precaution }
  520. { that we should clear the VMT here }
  521. movl $0,(%eax,%edi,1)
  522. {$ifdef valuefreemem}
  523. { Freemem }
  524. pushl %eax
  525. call fpc_freemem
  526. {$else valuefreemem}
  527. { temporary Variable }
  528. subl $4,%esp
  529. movl %esp,%edi
  530. { SELF }
  531. movl %eax,(%edi)
  532. pushl %edi
  533. call AsmFreeMem
  534. addl $4,%esp
  535. {$endif valuefreemem}
  536. .LHD_3:
  537. popal
  538. { avoid the 80386DX bug }
  539. nop
  540. end;
  541. {$define FPC_SYSTEM_HAS_FPC_NEW_CLASS}
  542. procedure fpc_new_class;assembler;[public,alias:'FPC_NEW_CLASS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  543. asm
  544. { to be sure in the future, we save also edit }
  545. pushl %edi
  546. { create class ? }
  547. movl 8(%ebp),%edi
  548. { if we test eax later without calling newinstance }
  549. { it must have a value <>0 }
  550. movl $1,%eax
  551. testl %edi,%edi
  552. jz .LNEW_CLASS1
  553. { save registers !! }
  554. pushl %ebx
  555. pushl %ecx
  556. pushl %edx
  557. { esi contains the vmt }
  558. pushl %esi
  559. { call newinstance (class method!) }
  560. call *52{vmtNewInstance}(%esi)
  561. popl %edx
  562. popl %ecx
  563. popl %ebx
  564. { newinstance returns a pointer to the new created }
  565. { instance in eax }
  566. { load esi and insert self }
  567. movl %eax,%esi
  568. .LNEW_CLASS1:
  569. movl %esi,8(%ebp)
  570. testl %eax,%eax
  571. popl %edi
  572. end;
  573. {$define FPC_SYSTEM_HAS_FPC_DISPOSE_CLASS}
  574. procedure fpc_dispose_class;assembler;[public,alias:'FPC_DISPOSE_CLASS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  575. asm
  576. { to be sure in the future, we save also edit }
  577. pushl %edi
  578. { destroy class ? }
  579. movl 12(%ebp),%edi
  580. testl %edi,%edi
  581. jz .LDISPOSE_CLASS1
  582. { no inherited call }
  583. movl (%esi),%edi
  584. { save registers !! }
  585. pushl %eax
  586. pushl %ebx
  587. pushl %ecx
  588. pushl %edx
  589. { push self }
  590. pushl %esi
  591. { call freeinstance }
  592. call *56{vmtFreeInstance}(%edi)
  593. popl %edx
  594. popl %ecx
  595. popl %ebx
  596. popl %eax
  597. .LDISPOSE_CLASS1:
  598. popl %edi
  599. end;
  600. {$endif TEST_GENERIC}
  601. {$define FPC_SYSTEM_HAS_FPC_HELP_FAIL_CLASS}
  602. procedure fpc_help_fail_class;assembler;[public,alias:'FPC_HELP_FAIL_CLASS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  603. { a non zero class must allways be disposed
  604. VMT is allways at pos 0 }
  605. asm
  606. testl %esi,%esi
  607. je .LHFC_1
  608. call FPC_DISPOSE_CLASS
  609. { set both object places to zero }
  610. xorl %esi,%esi
  611. movl %esi,8(%ebp)
  612. .LHFC_1:
  613. end;
  614. {$ifndef TEST_GENERIC}
  615. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  616. { we want the stack for debugging !! PM }
  617. procedure fpc_check_object(obj : pointer);[public,alias:'FPC_CHECK_OBJECT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  618. begin
  619. asm
  620. pushl %edi
  621. movl obj,%edi
  622. pushl %eax
  623. { Here we must check if the VMT pointer is nil before }
  624. { accessing it... }
  625. testl %edi,%edi
  626. jz .Lco_re
  627. movl (%edi),%eax
  628. addl 4(%edi),%eax
  629. jz .Lco_ok
  630. .Lco_re:
  631. pushl $210
  632. call HandleError
  633. .Lco_ok:
  634. popl %eax
  635. popl %edi
  636. { the adress is pushed : it needs to be removed from stack !! PM }
  637. end;{ of asm }
  638. end;
  639. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  640. procedure fpc_check_object_ext;assembler;[public,alias:'FPC_CHECK_OBJECT_EXT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  641. { checks for a correct vmt pointer }
  642. { deeper check to see if the current object is }
  643. { really related to the true }
  644. asm
  645. pushl %ebp
  646. movl %esp,%ebp
  647. pushl %edi
  648. movl 8(%ebp),%edi
  649. pushl %ebx
  650. movl 12(%ebp),%ebx
  651. pushl %eax
  652. { Here we must check if the VMT pointer is nil before }
  653. { accessing it... }
  654. .Lcoext_obj:
  655. testl %edi,%edi
  656. jz .Lcoext_re
  657. movl (%edi),%eax
  658. addl 4(%edi),%eax
  659. jnz .Lcoext_re
  660. cmpl %edi,%ebx
  661. je .Lcoext_ok
  662. .Lcoext_vmt:
  663. movl 8(%edi),%eax
  664. cmpl %ebx,%eax
  665. je .Lcoext_ok
  666. movl %eax,%edi
  667. jmp .Lcoext_obj
  668. .Lcoext_re:
  669. pushl $220
  670. call HandleError
  671. .Lcoext_ok:
  672. popl %eax
  673. popl %ebx
  674. popl %edi
  675. { the adress and vmt were pushed : it needs to be removed from stack !! PM }
  676. popl %ebp
  677. ret $8
  678. end;
  679. {$endif TEST_GENERIC}
  680. {****************************************************************************
  681. String
  682. ****************************************************************************}
  683. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COPY}
  684. function fpc_shortstr_to_shortstr(len:longint; const sstr: shortstring): shortstring; [public,alias: 'FPC_SHORTSTR_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  685. begin
  686. asm
  687. cld
  688. movl __RESULT,%edi
  689. movl sstr,%esi
  690. xorl %eax,%eax
  691. movl len,%ecx
  692. lodsb
  693. cmpl %ecx,%eax
  694. jbe .LStrCopy1
  695. movl %ecx,%eax
  696. .LStrCopy1:
  697. stosb
  698. cmpl $7,%eax
  699. jl .LStrCopy2
  700. movl %edi,%ecx { Align on 32bits }
  701. negl %ecx
  702. andl $3,%ecx
  703. subl %ecx,%eax
  704. rep
  705. movsb
  706. movl %eax,%ecx
  707. andl $3,%eax
  708. shrl $2,%ecx
  709. rep
  710. movsl
  711. .LStrCopy2:
  712. movl %eax,%ecx
  713. rep
  714. movsb
  715. end ['ESI','EDI','EAX','ECX'];
  716. end;
  717. procedure fpc_shortstr_copy(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_COPY'];
  718. begin
  719. asm
  720. pushl %eax
  721. pushl %ecx
  722. cld
  723. movl dstr,%edi
  724. movl sstr,%esi
  725. xorl %eax,%eax
  726. movl len,%ecx
  727. lodsb
  728. cmpl %ecx,%eax
  729. jbe .LStrCopy1
  730. movl %ecx,%eax
  731. .LStrCopy1:
  732. stosb
  733. cmpl $7,%eax
  734. jl .LStrCopy2
  735. movl %edi,%ecx { Align on 32bits }
  736. negl %ecx
  737. andl $3,%ecx
  738. subl %ecx,%eax
  739. rep
  740. movsb
  741. movl %eax,%ecx
  742. andl $3,%eax
  743. shrl $2,%ecx
  744. rep
  745. movsl
  746. .LStrCopy2:
  747. movl %eax,%ecx
  748. rep
  749. movsb
  750. popl %ecx
  751. popl %eax
  752. end ['ESI','EDI'];
  753. end;
  754. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  755. {$ifdef hascompilerproc}
  756. { define a dummy fpc_shortstr_concat for i386. Only the next one }
  757. { is really used by the compiler, but the compilerproc forward }
  758. { definition must still be fulfilled (JM) }
  759. function fpc_shortstr_concat(const s1,s2: shortstring): shortstring; compilerproc;
  760. begin
  761. { avoid warning }
  762. fpc_shortstr_concat := '';
  763. runerror(216);
  764. end;
  765. {$endif hascompilerproc}
  766. procedure fpc_shortstr_concat_intern(const s1, s2:shortstring);
  767. [public,alias:'FPC_SHORTSTR_CONCAT'];
  768. begin
  769. asm
  770. movl s2,%edi
  771. movl s1,%esi
  772. movl %edi,%ebx
  773. movzbl (%edi),%ecx
  774. xor %eax,%eax
  775. lea 1(%edi,%ecx),%edi
  776. negl %ecx
  777. addl $0x0ff,%ecx
  778. lodsb
  779. cmpl %ecx,%eax
  780. jbe .LStrConcat1
  781. movl %ecx,%eax
  782. .LStrConcat1:
  783. addb %al,(%ebx)
  784. cmpl $7,%eax
  785. jl .LStrConcat2
  786. movl %edi,%ecx { Align on 32bits }
  787. negl %ecx
  788. andl $3,%ecx
  789. subl %ecx,%eax
  790. rep
  791. movsb
  792. movl %eax,%ecx
  793. andl $3,%eax
  794. shrl $2,%ecx
  795. rep
  796. movsl
  797. .LStrConcat2:
  798. movl %eax,%ecx
  799. rep
  800. movsb
  801. end ['EBX','ECX','EAX','ESI','EDI'];
  802. end;
  803. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  804. function fpc_shortstr_compare(const dstr,sstr:shortstring): longint; [public,alias:'FPC_SHORTSTR_COMPARE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  805. begin
  806. asm
  807. cld
  808. xorl %ebx,%ebx
  809. xorl %eax,%eax
  810. movl sstr,%esi
  811. movl dstr,%edi
  812. movb (%esi),%al
  813. movb (%edi),%bl
  814. movl %eax,%edx
  815. incl %esi
  816. incl %edi
  817. cmpl %ebx,%eax
  818. jbe .LStrCmp1
  819. movl %ebx,%eax
  820. .LStrCmp1:
  821. cmpl $7,%eax
  822. jl .LStrCmp2
  823. movl %edi,%ecx { Align on 32bits }
  824. negl %ecx
  825. andl $3,%ecx
  826. subl %ecx,%eax
  827. orl %ecx,%ecx
  828. rep
  829. cmpsb
  830. jne .LStrCmp3
  831. movl %eax,%ecx
  832. andl $3,%eax
  833. shrl $2,%ecx
  834. orl %ecx,%ecx
  835. rep
  836. cmpsl
  837. je .LStrCmp2
  838. movl $4,%eax
  839. sub %eax,%esi
  840. sub %eax,%edi
  841. .LStrCmp2:
  842. movl %eax,%ecx
  843. orl %eax,%eax
  844. rep
  845. cmpsb
  846. jne .LStrCmp3
  847. cmp %ebx,%edx
  848. .LStrCmp3:
  849. end ['EDX','ECX','EBX','EAX','ESI','EDI'];
  850. end;
  851. {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  852. function fpc_pchar_to_shortstr(p:pchar):shortstring;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  853. {$include strpas.inc}
  854. {$define FPC_SYSTEM_HAS_STRLEN}
  855. function strlen(p:pchar):longint;assembler;
  856. {$include strlen.inc}
  857. {$define FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  858. function fpc_chararray_to_shortstr(const arr: array of char):shortstring;[public,alias:'FPC_CHARARRAY_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  859. begin
  860. asm
  861. cld
  862. movl arr,%esi
  863. movl arr+4,%ecx
  864. {$ifdef hascompilerproc}
  865. { previous implementations passed length(arr), with compilerproc }
  866. { we only have high(arr), so add one (JM) }
  867. incl %ecx
  868. {$endif hascompilerproc}
  869. orl %esi,%esi
  870. jnz .LStrCharArrayNotNil
  871. movl $0,%ecx
  872. .LStrCharArrayNotNil:
  873. movl %ecx,%eax
  874. movl __RESULT,%edi
  875. stosb
  876. cmpl $7,%eax
  877. jl .LStrCharArray2
  878. movl %edi,%ecx { Align on 32bits }
  879. negl %ecx
  880. andl $3,%ecx
  881. subl %ecx,%eax
  882. rep
  883. movsb
  884. movl %eax,%ecx
  885. andl $3,%eax
  886. shrl $2,%ecx
  887. rep
  888. movsl
  889. .LStrCharArray2:
  890. movl %eax,%ecx
  891. rep
  892. movsb
  893. end ['ECX','EAX','ESI','EDI'];
  894. end;
  895. {$define FPC_SYSTEM_HAS_GET_FRAME}
  896. function get_frame:longint;assembler;
  897. asm
  898. movl %ebp,%eax
  899. end ['EAX'];
  900. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  901. function get_caller_addr(framebp:longint):longint;assembler;
  902. asm
  903. movl framebp,%eax
  904. orl %eax,%eax
  905. jz .Lg_a_null
  906. movl 4(%eax),%eax
  907. .Lg_a_null:
  908. end ['EAX'];
  909. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  910. function get_caller_frame(framebp:longint):longint;assembler;
  911. asm
  912. movl framebp,%eax
  913. orl %eax,%eax
  914. jz .Lgnf_null
  915. movl (%eax),%eax
  916. .Lgnf_null:
  917. end ['EAX'];
  918. {****************************************************************************
  919. Math
  920. ****************************************************************************}
  921. {$define FPC_SYSTEM_HAS_ABS_LONGINT}
  922. function abs(l:longint):longint; assembler;[internconst:in_const_abs];
  923. asm
  924. movl l,%eax
  925. cltd
  926. xorl %edx,%eax
  927. subl %edx,%eax
  928. end ['EAX','EDX'];
  929. {$define FPC_SYSTEM_HAS_ODD_LONGINT}
  930. function odd(l:longint):boolean;assembler;[internconst:in_const_odd];
  931. asm
  932. movl l,%eax
  933. andl $1,%eax
  934. setnz %al
  935. end ['EAX'];
  936. {$define FPC_SYSTEM_HAS_SQR_LONGINT}
  937. function sqr(l:longint):longint;assembler;[internconst:in_const_sqr];
  938. asm
  939. mov l,%eax
  940. imull %eax,%eax
  941. end ['EAX'];
  942. {$define FPC_SYSTEM_HAS_SPTR}
  943. Function Sptr : Longint;assembler;
  944. asm
  945. movl %esp,%eax
  946. end;
  947. {****************************************************************************
  948. Str()
  949. ****************************************************************************}
  950. {$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
  951. procedure int_str(l : longint;var s : string);
  952. var
  953. buffer : array[0..11] of byte;
  954. begin
  955. { Workaround: }
  956. if l=$80000000 then
  957. begin
  958. s:='-2147483648';
  959. exit;
  960. end;
  961. asm
  962. movl l,%eax // load Integer
  963. movl s,%edi // Load String address
  964. xorl %ecx,%ecx // String length=0
  965. xorl %ebx,%ebx // Buffer length=0
  966. movl $0x0a,%esi // load 10 as dividing constant.
  967. orl %eax,%eax // Sign ?
  968. jns .LM2
  969. neg %eax
  970. movb $0x2d,1(%edi) // put '-' in String
  971. incl %ecx
  972. .LM2:
  973. cltd
  974. idivl %esi
  975. addb $0x30,%dl // convert Rest to ASCII.
  976. movb %dl,-12(%ebp,%ebx)
  977. incl %ebx
  978. cmpl $0,%eax
  979. jnz .LM2
  980. { copy String }
  981. .LM3:
  982. movb -13(%ebp,%ebx),%al // -13 because EBX is decreased only later
  983. movb %al,1(%edi,%ecx)
  984. incl %ecx
  985. decl %ebx
  986. jnz .LM3
  987. movb %cl,(%edi) // Copy String length
  988. end;
  989. end;
  990. {$define FPC_SYSTEM_HAS_INT_STR_CARDINAL}
  991. procedure int_str(c : cardinal;var s : string);
  992. var
  993. buffer : array[0..14] of byte;
  994. begin
  995. asm
  996. movl c,%eax // load CARDINAL
  997. movl s,%edi // Load String address
  998. xorl %ecx,%ecx // String length=0
  999. xorl %ebx,%ebx // Buffer length=0
  1000. movl $0x0a,%esi // load 10 as dividing constant.
  1001. .LM4:
  1002. xorl %edx,%edx
  1003. divl %esi
  1004. addb $0x30,%dl // convert Rest to ASCII.
  1005. movb %dl,-12(%ebp,%ebx)
  1006. incl %ebx
  1007. cmpl $0,%eax
  1008. jnz .LM4
  1009. { now copy the string }
  1010. .LM5:
  1011. movb -13(%ebp,%ebx),%al // -13 because EBX is decreased only later
  1012. movb %al,1(%edi,%ecx)
  1013. incl %ecx
  1014. decl %ebx
  1015. jnz .LM5
  1016. movb %cl,(%edi) // Copy String length
  1017. end;
  1018. end;
  1019. {****************************************************************************
  1020. Bounds Check
  1021. ****************************************************************************}
  1022. {$ifndef NOBOUNDCHECK}
  1023. {$define FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
  1024. {$ifdef SYSTEMDEBUG}
  1025. { we want the stack for debugging !! PM }
  1026. procedure int_boundcheck;[public,alias: 'FPC_BOUNDCHECK'];
  1027. begin
  1028. {$else not SYSTEMDEBUG}
  1029. procedure int_boundcheck;assembler;[public,alias: 'FPC_BOUNDCHECK'];
  1030. var dummy_to_force_stackframe_generation_for_trace: Longint;
  1031. {$endif not SYSTEMDEBUG}
  1032. {
  1033. called with:
  1034. %ecx - value
  1035. %edi - pointer to the ranges
  1036. }
  1037. asm
  1038. cmpl (%edi),%ecx
  1039. jl .Lbc_err
  1040. cmpl 4(%edi),%ecx
  1041. jle .Lbc_ok
  1042. .Lbc_err:
  1043. pushl %ebp
  1044. pushl $201
  1045. call HandleErrorFrame
  1046. .Lbc_ok:
  1047. end;
  1048. {$ifdef SYSTEMDEBUG}
  1049. end;
  1050. {$endif def SYSTEMDEBUG}
  1051. {$endif NOBOUNDCHECK}
  1052. { do a thread save inc/dec }
  1053. function declocked(var l : longint) : boolean;assembler;
  1054. asm
  1055. movl l,%edi
  1056. {$ifdef MT}
  1057. { this check should be done because a lock takes a lot }
  1058. { of time! }
  1059. cmpb $0,IsMultithread
  1060. jz .Ldeclockednolock
  1061. lock
  1062. decl (%edi)
  1063. jmp .Ldeclockedend
  1064. .Ldeclockednolock:
  1065. {$endif MT}
  1066. decl (%edi);
  1067. .Ldeclockedend:
  1068. setzb %al
  1069. end ['EDI','EAX'];
  1070. procedure inclocked(var l : longint);assembler;
  1071. asm
  1072. movl l,%edi
  1073. {$ifdef MT}
  1074. { this check should be done because a lock takes a lot }
  1075. { of time! }
  1076. cmpb $0,IsMultithread
  1077. jz .Linclockednolock
  1078. lock
  1079. incl (%edi)
  1080. jmp .Linclockedend
  1081. .Linclockednolock:
  1082. {$endif MT}
  1083. incl (%edi)
  1084. .Linclockedend:
  1085. end ['EDI'];
  1086. {
  1087. $Log$
  1088. Revision 1.26 2002-07-26 15:45:33 florian
  1089. * changed multi threading define: it's MT instead of MTRTL
  1090. Revision 1.25 2002/07/06 20:31:59 carl
  1091. + added TEST_GENERIC to test generic version
  1092. Revision 1.24 2002/06/16 08:21:26 carl
  1093. + TEST_GENERIC to test generic versions of code
  1094. Revision 1.23 2002/06/09 12:54:37 jonas
  1095. * fixed memory corruption bug in fpc_help_constructor
  1096. Revision 1.22 2002/04/21 18:56:59 peter
  1097. * fpc_freemem and fpc_getmem compilerproc
  1098. Revision 1.21 2002/04/01 14:23:17 carl
  1099. - no need for runerror 203, already fixed!
  1100. Revision 1.20 2002/03/30 14:52:04 carl
  1101. * cause runtime error 203 on failed class creation
  1102. Revision 1.19 2001/12/03 21:39:19 peter
  1103. * freemem(var) -> freemem(value)
  1104. Revision 1.18 2001/10/09 02:43:58 carl
  1105. * bugfix #1639 (IsMultiThread varialbe setting)
  1106. Revision 1.17 2001/08/30 15:43:14 jonas
  1107. * converted adding/comparing of strings to compileproc. Note that due
  1108. to the way the shortstring helpers for i386 are written, they are
  1109. still handled by the old code (reason: fpc_shortstr_compare returns
  1110. results in the flags instead of in eax and fpc_shortstr_concat
  1111. has wierd parameter conventions). The compilerproc stuff should work
  1112. fine with the generic implementations though.
  1113. * removed some nested comments warnings
  1114. Revision 1.16 2001/08/29 19:49:04 jonas
  1115. * some fixes in compilerprocs for chararray to string conversions
  1116. * conversion from string to chararray is now also done via compilerprocs
  1117. Revision 1.15 2001/08/28 13:24:47 jonas
  1118. + compilerproc implementation of most string-related type conversions
  1119. - removed all code from the compiler which has been replaced by
  1120. compilerproc implementations (using (ifdef hascompilerproc) is not
  1121. necessary in the compiler)
  1122. Revision 1.14 2001/08/01 15:00:09 jonas
  1123. + "compproc" helpers
  1124. * renamed several helpers so that their name is the same as their
  1125. "public alias", which should facilitate the conversion of processor
  1126. specific code in the code generator to processor independent code
  1127. * some small fixes to the val_ansistring and val_widestring helpers
  1128. (always immediately exit if the source string is longer than 255
  1129. chars)
  1130. * fixed fpc_dynarray_high and fpc_dynarray_length if the dynarray is
  1131. still nil (used to crash, now return resp -1 and 0)
  1132. Revision 1.13 2001/07/08 21:00:18 peter
  1133. * various widestring updates, it works now mostly without charset
  1134. mapping supported
  1135. Revision 1.12 2001/05/31 22:42:56 florian
  1136. * some fixes for widestrings and variants
  1137. Revision 1.11 2001/04/21 12:18:09 peter
  1138. * add nop after popa (merged)
  1139. Revision 1.9 2001/04/08 13:19:28 jonas
  1140. * optimized FPC_HELP_CONSTRUCTOR a bit
  1141. Revision 1.8 2001/03/05 17:10:04 jonas
  1142. * moved implementations of strlen and strpas to separate include files
  1143. (they were duplicated in i386.inc and strings.inc/stringss.inc)
  1144. * strpas supports 'nil' pchars again (returns an empty string)
  1145. (both merged)
  1146. Revision 1.7 2001/03/04 17:31:34 jonas
  1147. * fixed all implementations of strpas
  1148. Revision 1.5 2000/11/12 23:23:34 florian
  1149. * interfaces basically running
  1150. Revision 1.4 2000/11/07 23:42:21 florian
  1151. + AfterConstruction and BeforeDestruction implemented
  1152. + TInterfacedObject implemented
  1153. Revision 1.3 2000/07/14 10:33:09 michael
  1154. + Conditionals fixed
  1155. Revision 1.2 2000/07/13 11:33:41 michael
  1156. + removed logs
  1157. }