i386.inc 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248
  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. { Internal alias that can be reference from asm code }
  574. procedure int_dispose_class;external name 'FPC_DISPOSE_CLASS';
  575. {$define FPC_SYSTEM_HAS_FPC_DISPOSE_CLASS}
  576. procedure fpc_dispose_class;assembler;[public,alias:'FPC_DISPOSE_CLASS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  577. asm
  578. { to be sure in the future, we save also edit }
  579. pushl %edi
  580. { destroy class ? }
  581. movl 12(%ebp),%edi
  582. testl %edi,%edi
  583. jz .LDISPOSE_CLASS1
  584. { no inherited call }
  585. movl (%esi),%edi
  586. { save registers !! }
  587. pushl %eax
  588. pushl %ebx
  589. pushl %ecx
  590. pushl %edx
  591. { push self }
  592. pushl %esi
  593. { call freeinstance }
  594. call *56{vmtFreeInstance}(%edi)
  595. popl %edx
  596. popl %ecx
  597. popl %ebx
  598. popl %eax
  599. .LDISPOSE_CLASS1:
  600. popl %edi
  601. end;
  602. {$endif TEST_GENERIC}
  603. {$define FPC_SYSTEM_HAS_FPC_HELP_FAIL_CLASS}
  604. procedure fpc_help_fail_class;assembler;[public,alias:'FPC_HELP_FAIL_CLASS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  605. { a non zero class must allways be disposed
  606. VMT is allways at pos 0 }
  607. asm
  608. testl %esi,%esi
  609. je .LHFC_1
  610. { can't use the compilerproc version as that will generate a
  611. reference instead of a symbol }
  612. call int_dispose_class
  613. { set both object places to zero }
  614. xorl %esi,%esi
  615. movl %esi,8(%ebp)
  616. .LHFC_1:
  617. end;
  618. {$ifndef TEST_GENERIC}
  619. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  620. { we want the stack for debugging !! PM }
  621. procedure fpc_check_object(obj : pointer);[public,alias:'FPC_CHECK_OBJECT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  622. begin
  623. asm
  624. pushl %edi
  625. movl obj,%edi
  626. pushl %eax
  627. { Here we must check if the VMT pointer is nil before }
  628. { accessing it... }
  629. testl %edi,%edi
  630. jz .Lco_re
  631. movl (%edi),%eax
  632. addl 4(%edi),%eax
  633. jz .Lco_ok
  634. .Lco_re:
  635. pushl $210
  636. call HandleError
  637. .Lco_ok:
  638. popl %eax
  639. popl %edi
  640. { the adress is pushed : it needs to be removed from stack !! PM }
  641. end;{ of asm }
  642. end;
  643. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  644. procedure fpc_check_object_ext;assembler;[public,alias:'FPC_CHECK_OBJECT_EXT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  645. { checks for a correct vmt pointer }
  646. { deeper check to see if the current object is }
  647. { really related to the true }
  648. asm
  649. pushl %ebp
  650. movl %esp,%ebp
  651. pushl %edi
  652. movl 8(%ebp),%edi
  653. pushl %ebx
  654. movl 12(%ebp),%ebx
  655. pushl %eax
  656. { Here we must check if the VMT pointer is nil before }
  657. { accessing it... }
  658. .Lcoext_obj:
  659. testl %edi,%edi
  660. jz .Lcoext_re
  661. movl (%edi),%eax
  662. addl 4(%edi),%eax
  663. jnz .Lcoext_re
  664. cmpl %edi,%ebx
  665. je .Lcoext_ok
  666. .Lcoext_vmt:
  667. movl 8(%edi),%eax
  668. cmpl %ebx,%eax
  669. je .Lcoext_ok
  670. movl %eax,%edi
  671. jmp .Lcoext_obj
  672. .Lcoext_re:
  673. pushl $219
  674. call HandleError
  675. .Lcoext_ok:
  676. popl %eax
  677. popl %ebx
  678. popl %edi
  679. { the adress and vmt were pushed : it needs to be removed from stack !! PM }
  680. popl %ebp
  681. ret $8
  682. end;
  683. {$endif TEST_GENERIC}
  684. {****************************************************************************
  685. String
  686. ****************************************************************************}
  687. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  688. function fpc_shortstr_to_shortstr(len:longint; const sstr: shortstring): shortstring; [public,alias: 'FPC_SHORTSTR_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  689. begin
  690. asm
  691. cld
  692. movl __RESULT,%edi
  693. movl sstr,%esi
  694. xorl %eax,%eax
  695. movl len,%ecx
  696. lodsb
  697. cmpl %ecx,%eax
  698. jbe .LStrCopy1
  699. movl %ecx,%eax
  700. .LStrCopy1:
  701. stosb
  702. cmpl $7,%eax
  703. jl .LStrCopy2
  704. movl %edi,%ecx { Align on 32bits }
  705. negl %ecx
  706. andl $3,%ecx
  707. subl %ecx,%eax
  708. rep
  709. movsb
  710. movl %eax,%ecx
  711. andl $3,%eax
  712. shrl $2,%ecx
  713. rep
  714. movsl
  715. .LStrCopy2:
  716. movl %eax,%ecx
  717. rep
  718. movsb
  719. end ['ESI','EDI','EAX','ECX'];
  720. end;
  721. {$ifdef interncopy}
  722. procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN'];
  723. {$else}
  724. procedure fpc_shortstr_copy(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_COPY'];
  725. {$endif}
  726. begin
  727. asm
  728. pushl %eax
  729. pushl %ecx
  730. cld
  731. movl dstr,%edi
  732. movl sstr,%esi
  733. xorl %eax,%eax
  734. movl len,%ecx
  735. lodsb
  736. cmpl %ecx,%eax
  737. jbe .LStrCopy1
  738. movl %ecx,%eax
  739. .LStrCopy1:
  740. stosb
  741. cmpl $7,%eax
  742. jl .LStrCopy2
  743. movl %edi,%ecx { Align on 32bits }
  744. negl %ecx
  745. andl $3,%ecx
  746. subl %ecx,%eax
  747. rep
  748. movsb
  749. movl %eax,%ecx
  750. andl $3,%eax
  751. shrl $2,%ecx
  752. rep
  753. movsl
  754. .LStrCopy2:
  755. movl %eax,%ecx
  756. rep
  757. movsb
  758. popl %ecx
  759. popl %eax
  760. end ['ESI','EDI'];
  761. end;
  762. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  763. {$ifdef hascompilerproc}
  764. { define a dummy fpc_shortstr_concat for i386. Only the next one }
  765. { is really used by the compiler, but the compilerproc forward }
  766. { definition must still be fulfilled (JM) }
  767. function fpc_shortstr_concat(const s1,s2: shortstring): shortstring; compilerproc;
  768. begin
  769. { avoid warning }
  770. fpc_shortstr_concat := '';
  771. runerror(216);
  772. end;
  773. {$endif hascompilerproc}
  774. procedure fpc_shortstr_concat_intern(const s1, s2:shortstring);
  775. [public,alias:'FPC_SHORTSTR_CONCAT'];
  776. begin
  777. asm
  778. movl s2,%edi
  779. movl s1,%esi
  780. movl %edi,%ebx
  781. movzbl (%edi),%ecx
  782. xor %eax,%eax
  783. lea 1(%edi,%ecx),%edi
  784. negl %ecx
  785. addl $0x0ff,%ecx
  786. lodsb
  787. cmpl %ecx,%eax
  788. jbe .LStrConcat1
  789. movl %ecx,%eax
  790. .LStrConcat1:
  791. addb %al,(%ebx)
  792. cmpl $7,%eax
  793. jl .LStrConcat2
  794. movl %edi,%ecx { Align on 32bits }
  795. negl %ecx
  796. andl $3,%ecx
  797. subl %ecx,%eax
  798. rep
  799. movsb
  800. movl %eax,%ecx
  801. andl $3,%eax
  802. shrl $2,%ecx
  803. rep
  804. movsl
  805. .LStrConcat2:
  806. movl %eax,%ecx
  807. rep
  808. movsb
  809. end ['EBX','ECX','EAX','ESI','EDI'];
  810. end;
  811. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  812. function fpc_shortstr_compare(const dstr,sstr:shortstring): longint; [public,alias:'FPC_SHORTSTR_COMPARE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  813. begin
  814. asm
  815. cld
  816. xorl %ebx,%ebx
  817. xorl %eax,%eax
  818. movl sstr,%esi
  819. movl dstr,%edi
  820. movb (%esi),%al
  821. movb (%edi),%bl
  822. movl %eax,%edx
  823. incl %esi
  824. incl %edi
  825. cmpl %ebx,%eax
  826. jbe .LStrCmp1
  827. movl %ebx,%eax
  828. .LStrCmp1:
  829. cmpl $7,%eax
  830. jl .LStrCmp2
  831. movl %edi,%ecx { Align on 32bits }
  832. negl %ecx
  833. andl $3,%ecx
  834. subl %ecx,%eax
  835. orl %ecx,%ecx
  836. rep
  837. cmpsb
  838. jne .LStrCmp3
  839. movl %eax,%ecx
  840. andl $3,%eax
  841. shrl $2,%ecx
  842. orl %ecx,%ecx
  843. rep
  844. cmpsl
  845. je .LStrCmp2
  846. movl $4,%eax
  847. sub %eax,%esi
  848. sub %eax,%edi
  849. .LStrCmp2:
  850. movl %eax,%ecx
  851. orl %eax,%eax
  852. rep
  853. cmpsb
  854. jne .LStrCmp3
  855. cmp %ebx,%edx
  856. .LStrCmp3:
  857. end ['EDX','ECX','EBX','EAX','ESI','EDI'];
  858. end;
  859. {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  860. function fpc_pchar_to_shortstr(p:pchar):shortstring;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  861. {$include strpas.inc}
  862. {$define FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  863. function fpc_pchar_length(p:pchar):longint;assembler;[public,alias:'FPC_PCHAR_LENGTH']; {$ifdef hascompilerproc} compilerproc; {$endif}
  864. {$include strlen.inc}
  865. {$define FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  866. function fpc_chararray_to_shortstr(const arr: array of char):shortstring;[public,alias:'FPC_CHARARRAY_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  867. begin
  868. asm
  869. cld
  870. movl arr,%esi
  871. movl arr+4,%ecx
  872. {$ifdef hascompilerproc}
  873. { previous implementations passed length(arr), with compilerproc }
  874. { we only have high(arr), so add one (JM) }
  875. incl %ecx
  876. {$endif hascompilerproc}
  877. orl %esi,%esi
  878. jnz .LStrCharArrayNotNil
  879. movl $0,%ecx
  880. .LStrCharArrayNotNil:
  881. movl %ecx,%eax
  882. movl __RESULT,%edi
  883. stosb
  884. cmpl $7,%eax
  885. jl .LStrCharArray2
  886. movl %edi,%ecx { Align on 32bits }
  887. negl %ecx
  888. andl $3,%ecx
  889. subl %ecx,%eax
  890. rep
  891. movsb
  892. movl %eax,%ecx
  893. andl $3,%eax
  894. shrl $2,%ecx
  895. rep
  896. movsl
  897. .LStrCharArray2:
  898. movl %eax,%ecx
  899. rep
  900. movsb
  901. end ['ECX','EAX','ESI','EDI'];
  902. end;
  903. {$define FPC_SYSTEM_HAS_GET_FRAME}
  904. function get_frame:longint;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  905. asm
  906. movl %ebp,%eax
  907. end ['EAX'];
  908. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  909. function get_caller_addr(framebp:longint):longint;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  910. asm
  911. movl framebp,%eax
  912. orl %eax,%eax
  913. jz .Lg_a_null
  914. movl 4(%eax),%eax
  915. .Lg_a_null:
  916. end ['EAX'];
  917. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  918. function get_caller_frame(framebp:longint):longint;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  919. asm
  920. movl framebp,%eax
  921. orl %eax,%eax
  922. jz .Lgnf_null
  923. movl (%eax),%eax
  924. .Lgnf_null:
  925. end ['EAX'];
  926. {****************************************************************************
  927. Math
  928. ****************************************************************************}
  929. {$define FPC_SYSTEM_HAS_ABS_LONGINT}
  930. function abs(l:longint):longint; assembler;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_abs];
  931. asm
  932. movl l,%eax
  933. cltd
  934. xorl %edx,%eax
  935. subl %edx,%eax
  936. end ['EAX','EDX'];
  937. {$define FPC_SYSTEM_HAS_ODD_LONGINT}
  938. function odd(l:longint):boolean;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_odd];
  939. asm
  940. movl l,%eax
  941. andl $1,%eax
  942. setnz %al
  943. end ['EAX'];
  944. {$define FPC_SYSTEM_HAS_SQR_LONGINT}
  945. function sqr(l:longint):longint;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_sqr];
  946. asm
  947. mov l,%eax
  948. imull %eax,%eax
  949. end ['EAX'];
  950. {$define FPC_SYSTEM_HAS_SPTR}
  951. Function Sptr : Longint;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  952. asm
  953. movl %esp,%eax
  954. end;
  955. {****************************************************************************
  956. Str()
  957. ****************************************************************************}
  958. {$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
  959. procedure int_str(l : longint;var s : string);
  960. var
  961. buffer : array[0..11] of byte;
  962. begin
  963. { Workaround: }
  964. if l=$80000000 then
  965. begin
  966. s:='-2147483648';
  967. exit;
  968. end;
  969. asm
  970. movl l,%eax // load Integer
  971. movl s,%edi // Load String address
  972. xorl %ecx,%ecx // String length=0
  973. xorl %ebx,%ebx // Buffer length=0
  974. movl $0x0a,%esi // load 10 as dividing constant.
  975. orl %eax,%eax // Sign ?
  976. jns .LM2
  977. neg %eax
  978. movb $0x2d,1(%edi) // put '-' in String
  979. incl %ecx
  980. .LM2:
  981. cltd
  982. idivl %esi
  983. addb $0x30,%dl // convert Rest to ASCII.
  984. movb %dl,-12(%ebp,%ebx)
  985. incl %ebx
  986. cmpl $0,%eax
  987. jnz .LM2
  988. { copy String }
  989. .LM3:
  990. movb -13(%ebp,%ebx),%al // -13 because EBX is decreased only later
  991. movb %al,1(%edi,%ecx)
  992. incl %ecx
  993. decl %ebx
  994. jnz .LM3
  995. movb %cl,(%edi) // Copy String length
  996. end;
  997. end;
  998. {$define FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  999. procedure int_str(c : longword;var s : string);
  1000. var
  1001. buffer : array[0..14] of byte;
  1002. begin
  1003. asm
  1004. movl c,%eax // load CARDINAL
  1005. movl s,%edi // Load String address
  1006. xorl %ecx,%ecx // String length=0
  1007. xorl %ebx,%ebx // Buffer length=0
  1008. movl $0x0a,%esi // load 10 as dividing constant.
  1009. .LM4:
  1010. xorl %edx,%edx
  1011. divl %esi
  1012. addb $0x30,%dl // convert Rest to ASCII.
  1013. movb %dl,-12(%ebp,%ebx)
  1014. incl %ebx
  1015. cmpl $0,%eax
  1016. jnz .LM4
  1017. { now copy the string }
  1018. .LM5:
  1019. movb -13(%ebp,%ebx),%al // -13 because EBX is decreased only later
  1020. movb %al,1(%edi,%ecx)
  1021. incl %ecx
  1022. decl %ebx
  1023. jnz .LM5
  1024. movb %cl,(%edi) // Copy String length
  1025. end;
  1026. end;
  1027. {****************************************************************************
  1028. Bounds Check
  1029. ****************************************************************************}
  1030. {$ifndef NOBOUNDCHECK}
  1031. procedure int_boundcheck;assembler;[public,alias: 'FPC_BOUNDCHECK'];
  1032. var dummy_to_force_stackframe_generation_for_trace: Longint;
  1033. {
  1034. called with:
  1035. %ecx - value
  1036. %edi - pointer to the ranges
  1037. }
  1038. asm
  1039. cmpl (%edi),%ecx
  1040. jl .Lbc_err
  1041. cmpl 4(%edi),%ecx
  1042. jle .Lbc_ok
  1043. .Lbc_err:
  1044. pushl %ebp
  1045. pushl $201
  1046. call HandleErrorFrame
  1047. .Lbc_ok:
  1048. end;
  1049. {$endif NOBOUNDCHECK}
  1050. { do a thread save inc/dec }
  1051. function declocked(var l : longint) : boolean;assembler;
  1052. asm
  1053. movl l,%edi
  1054. { this check should be done because a lock takes a lot }
  1055. { of time! }
  1056. cmpb $0,IsMultithread
  1057. jz .Ldeclockednolock
  1058. lock
  1059. decl (%edi)
  1060. jmp .Ldeclockedend
  1061. .Ldeclockednolock:
  1062. decl (%edi);
  1063. .Ldeclockedend:
  1064. setzb %al
  1065. end ['EDI','EAX'];
  1066. procedure inclocked(var l : longint);assembler;
  1067. asm
  1068. movl l,%edi
  1069. { this check should be done because a lock takes a lot }
  1070. { of time! }
  1071. cmpb $0,IsMultithread
  1072. jz .Linclockednolock
  1073. lock
  1074. incl (%edi)
  1075. jmp .Linclockedend
  1076. .Linclockednolock:
  1077. incl (%edi)
  1078. .Linclockedend:
  1079. end ['EDI'];
  1080. {****************************************************************************
  1081. FPU
  1082. ****************************************************************************}
  1083. const
  1084. fpucw : word = $1332;
  1085. { Internal constants for use in system unit }
  1086. FPU_Invalid = 1;
  1087. FPU_Denormal = 2;
  1088. FPU_DivisionByZero = 4;
  1089. FPU_Overflow = 8;
  1090. FPU_Underflow = $10;
  1091. FPU_StackUnderflow = $20;
  1092. FPU_StackOverflow = $40;
  1093. FPU_ExceptionMask = $ff;
  1094. {$define FPC_SYSTEM_HAS_SYSRESETFPU}
  1095. Procedure SysResetFPU;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  1096. asm
  1097. fninit
  1098. fldcw fpucw
  1099. end;
  1100. {
  1101. $Log$
  1102. Revision 1.34 2002-10-15 19:24:47 carl
  1103. * Replace 220 -> 219
  1104. Revision 1.33 2002/10/14 19:39:16 peter
  1105. * threads unit added for thread support
  1106. Revision 1.32 2002/10/05 14:20:16 peter
  1107. * fpc_pchar_length compilerproc and strlen alias
  1108. Revision 1.31 2002/10/02 18:21:51 peter
  1109. * Copy() changed to internal function calling compilerprocs
  1110. * FPC_SHORTSTR_COPY renamed to FPC_SHORTSTR_ASSIGN because of the
  1111. new copy functions
  1112. Revision 1.30 2002/09/07 21:33:35 carl
  1113. - removed unused defines
  1114. Revision 1.29 2002/09/07 16:01:19 peter
  1115. * old logs removed and tabs fixed
  1116. Revision 1.28 2002/09/03 15:43:36 peter
  1117. * add alias for fpc_dispose_class so it can be called from
  1118. fpc_help_fail_class
  1119. Revision 1.27 2002/08/19 19:34:02 peter
  1120. * SYSTEMINLINE define that will add inline directives for small
  1121. functions and wrappers. This will be defined automaticly when
  1122. the compiler defines the HASINLINE directive
  1123. Revision 1.26 2002/07/26 15:45:33 florian
  1124. * changed multi threading define: it's MT instead of MTRTL
  1125. Revision 1.25 2002/07/06 20:31:59 carl
  1126. + added TEST_GENERIC to test generic version
  1127. Revision 1.24 2002/06/16 08:21:26 carl
  1128. + TEST_GENERIC to test generic versions of code
  1129. Revision 1.23 2002/06/09 12:54:37 jonas
  1130. * fixed memory corruption bug in fpc_help_constructor
  1131. Revision 1.22 2002/04/21 18:56:59 peter
  1132. * fpc_freemem and fpc_getmem compilerproc
  1133. Revision 1.21 2002/04/01 14:23:17 carl
  1134. - no need for runerror 203, already fixed!
  1135. Revision 1.20 2002/03/30 14:52:04 carl
  1136. * cause runtime error 203 on failed class creation
  1137. }