i386.inc 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542
  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. function geteipasebx : pointer;assembler;[public,alias:'FPC_GETEIPINEBX'];
  18. asm
  19. movl (%esp),%ebx
  20. ret
  21. end;
  22. {$define FPC_SYSTEM_HAS_MOVE}
  23. procedure Move(const source;var dest;count:longint);assembler;
  24. var
  25. saveesi,saveedi : longint;
  26. asm
  27. movl %edi,saveedi
  28. movl %esi,saveesi
  29. {$ifdef REGCALL}
  30. movl %eax,%esi
  31. movl %edx,%edi
  32. movl %ecx,%edx
  33. {$else}
  34. movl dest,%edi
  35. movl source,%esi
  36. movl count,%edx
  37. {$endif}
  38. movl %edi,%eax
  39. { check for zero or negative count }
  40. cmpl $0,%edx
  41. jle .LMoveEnd
  42. { Check for back or forward }
  43. sub %esi,%eax
  44. jz .LMoveEnd { Do nothing when source=dest }
  45. jc .LFMove { Do forward, dest<source }
  46. cmp %edx,%eax
  47. jb .LBMove { Dest is in range of move, do backward }
  48. { Forward Copy }
  49. .LFMove:
  50. cld
  51. cmpl $15,%edx
  52. jl .LFMove1
  53. movl %edi,%ecx { Align on 32bits }
  54. negl %ecx
  55. andl $3,%ecx
  56. subl %ecx,%edx
  57. rep
  58. movsb
  59. movl %edx,%ecx
  60. andl $3,%edx
  61. shrl $2,%ecx
  62. rep
  63. movsl
  64. .LFMove1:
  65. movl %edx,%ecx
  66. rep
  67. movsb
  68. jmp .LMoveEnd
  69. { Backward Copy }
  70. .LBMove:
  71. std
  72. addl %edx,%esi
  73. addl %edx,%edi
  74. movl %edi,%ecx
  75. decl %esi
  76. decl %edi
  77. cmpl $15,%edx
  78. jl .LBMove1
  79. negl %ecx { Align on 32bits }
  80. andl $3,%ecx
  81. subl %ecx,%edx
  82. rep
  83. movsb
  84. movl %edx,%ecx
  85. andl $3,%edx
  86. shrl $2,%ecx
  87. subl $3,%esi
  88. subl $3,%edi
  89. rep
  90. movsl
  91. addl $3,%esi
  92. addl $3,%edi
  93. .LBMove1:
  94. movl %edx,%ecx
  95. rep
  96. movsb
  97. cld
  98. .LMoveEnd:
  99. movl saveedi,%edi
  100. movl saveesi,%esi
  101. end;
  102. {$define FPC_SYSTEM_HAS_FILLCHAR}
  103. Procedure FillChar(var x;count:longint;value:byte);assembler;
  104. var
  105. saveedi : longint;
  106. asm
  107. movl %edi,saveedi
  108. cld
  109. {$ifdef REGCALL}
  110. movl %eax,%edi
  111. movb %cl,%al
  112. movl %edx,%ecx
  113. {$else}
  114. movl x,%edi
  115. movb value,%al
  116. movl count,%ecx
  117. {$endif}
  118. { check for zero or negative count }
  119. cmpl $0,%ecx
  120. jle .LFillEnd
  121. cmpl $7,%ecx
  122. jl .LFill1
  123. movb %al,%ah
  124. movl %eax,%edx
  125. shll $16,%eax
  126. movw %dx,%ax
  127. movl %ecx,%edx
  128. movl %edi,%ecx { Align on 32bits }
  129. negl %ecx
  130. andl $3,%ecx
  131. subl %ecx,%edx
  132. rep
  133. stosb
  134. movl %edx,%ecx
  135. andl $3,%edx
  136. shrl $2,%ecx
  137. rep
  138. stosl
  139. movl %edx,%ecx
  140. .LFill1:
  141. rep
  142. stosb
  143. .LFillEnd:
  144. movl saveedi,%edi
  145. end;
  146. {$define FPC_SYSTEM_HAS_FILLWORD}
  147. procedure fillword(var x;count : longint;value : word);assembler;
  148. var
  149. saveedi : longint;
  150. asm
  151. movl %edi,saveedi
  152. {$ifdef REGCALL}
  153. movl %eax,%edi
  154. movzwl %cx,%eax
  155. movl %edx,%ecx
  156. {$else}
  157. movl x,%edi
  158. movl count,%ecx
  159. movzwl value,%eax
  160. {$endif}
  161. { check for zero or negative count }
  162. cmpl $0,%ecx
  163. jle .LFillWordEnd
  164. movl %eax,%edx
  165. shll $16,%eax
  166. orl %edx,%eax
  167. movl %ecx,%edx
  168. shrl $1,%ecx
  169. cld
  170. rep
  171. stosl
  172. movl %edx,%ecx
  173. andl $1,%ecx
  174. rep
  175. stosw
  176. .LFillWordEnd:
  177. movl saveedi,%edi
  178. end;
  179. {$define FPC_SYSTEM_HAS_FILLDWORD}
  180. procedure filldword(var x;count : longint;value : dword);assembler;
  181. var
  182. saveedi : longint;
  183. asm
  184. movl %edi,saveedi
  185. {$ifdef REGCALL}
  186. movl %eax,%edi
  187. movl %ecx,%eax
  188. movl %edx,%ecx
  189. {$else}
  190. movl x,%edi
  191. movl count,%ecx
  192. movl value,%eax
  193. {$endif}
  194. { check for zero or negative count }
  195. cmpl $0,%ecx
  196. jle .LFillDWordEnd
  197. cld
  198. rep
  199. stosl
  200. .LFillDWordEnd:
  201. movl saveedi,%edi
  202. end;
  203. {$define FPC_SYSTEM_HAS_INDEXBYTE}
  204. function IndexByte(Const buf;len:longint;b:byte):longint; assembler;
  205. var
  206. saveedi,saveebx : longint;
  207. asm
  208. movl %edi,saveedi
  209. movl %ebx,saveebx
  210. movl buf,%edi // Load String
  211. movb b,%bl
  212. movl len,%ecx // Load len
  213. xorl %eax,%eax
  214. testl %ecx,%ecx
  215. jz .Lready
  216. cld
  217. movl %ecx,%edx // Copy for easy manipulation
  218. movb %bl,%al
  219. repne
  220. scasb
  221. jne .Lcharposnotfound
  222. incl %ecx
  223. subl %ecx,%edx
  224. movl %edx,%eax
  225. jmp .Lready
  226. .Lcharposnotfound:
  227. movl $-1,%eax
  228. .Lready:
  229. movl saveedi,%edi
  230. movl saveebx,%ebx
  231. end;
  232. {$define FPC_SYSTEM_HAS_INDEXWORD}
  233. function Indexword(Const buf;len:longint;b:word):longint; assembler;
  234. var
  235. saveedi,saveebx : longint;
  236. asm
  237. movl %edi,saveedi
  238. movl %ebx,saveebx
  239. movl Buf,%edi // Load String
  240. movw b,%bx
  241. movl Len,%ecx // Load len
  242. xorl %eax,%eax
  243. testl %ecx,%ecx
  244. jz .Lready
  245. cld
  246. movl %ecx,%edx // Copy for easy manipulation
  247. movw %bx,%ax
  248. repne
  249. scasw
  250. jne .Lcharposnotfound
  251. incl %ecx
  252. subl %ecx,%edx
  253. movl %edx,%eax
  254. jmp .Lready
  255. .Lcharposnotfound:
  256. movl $-1,%eax
  257. .Lready:
  258. movl saveedi,%edi
  259. movl saveebx,%ebx
  260. end;
  261. {$define FPC_SYSTEM_HAS_INDEXDWORD}
  262. function IndexDWord(Const buf;len:longint;b:DWord):longint; assembler;
  263. var
  264. saveedi,saveebx : longint;
  265. asm
  266. movl %edi,saveedi
  267. movl %ebx,saveebx
  268. {$ifdef REGCALL}
  269. movl %eax,%edi
  270. movl %ecx,%ebx
  271. movl %edx,%ecx
  272. {$else}
  273. movl Len,%ecx // Load len
  274. movl Buf,%edi // Load String
  275. movl b,%ebx
  276. {$endif}
  277. xorl %eax,%eax
  278. testl %ecx,%ecx
  279. jz .Lready
  280. cld
  281. movl %ecx,%edx // Copy for easy manipulation
  282. movl %ebx,%eax
  283. repne
  284. scasl
  285. jne .Lcharposnotfound
  286. incl %ecx
  287. subl %ecx,%edx
  288. movl %edx,%eax
  289. jmp .Lready
  290. .Lcharposnotfound:
  291. movl $-1,%eax
  292. .Lready:
  293. movl saveedi,%edi
  294. movl saveebx,%ebx
  295. end;
  296. {$define FPC_SYSTEM_HAS_COMPAREBYTE}
  297. function CompareByte(Const buf1,buf2;len:longint):longint; assembler;
  298. var
  299. saveesi,saveedi : longint;
  300. asm
  301. movl %edi,saveedi
  302. movl %esi,saveesi
  303. cld
  304. {$ifdef REGCALL}
  305. movl %eax,%edi
  306. movl %edx,%esi
  307. movl %ecx,%eax
  308. {$else}
  309. movl len,%eax
  310. movl buf2,%esi { Load params}
  311. movl buf1,%edi
  312. {$endif}
  313. testl %eax,%eax {We address -1(%esi), so we have to deal with len=0}
  314. je .LCmpbyteExit
  315. cmpl $7,%eax {<7 not worth aligning and go through all trouble}
  316. jl .LCmpbyte2
  317. movl %edi,%ecx { Align on 32bits }
  318. negl %ecx { calc bytes to align (%edi and 3) xor 3= -%edi and 3}
  319. andl $3,%ecx
  320. subl %ecx,%eax { Subtract from number of bytes to go}
  321. orl %ecx,%ecx
  322. rep
  323. cmpsb {The actual 32-bit Aligning}
  324. jne .LCmpbyte3
  325. movl %eax,%ecx {bytes to do, divide by 4}
  326. andl $3,%eax {remainder}
  327. shrl $2,%ecx {The actual division}
  328. orl %ecx,%ecx {Sets zero flag if ecx=0 -> no cmp}
  329. rep
  330. cmpsl
  331. je .LCmpbyte2 { All equal? then to the left over bytes}
  332. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  333. subl %eax,%esi
  334. subl %eax,%edi
  335. .LCmpbyte2:
  336. movl %eax,%ecx {bytes still to (re)scan}
  337. orl %eax,%eax {prevent disaster in case %eax=0}
  338. rep
  339. cmpsb
  340. .LCmpbyte3:
  341. movzbl -1(%esi),%ecx
  342. movzbl -1(%edi),%eax // Compare failing (or equal) position
  343. subl %ecx,%eax
  344. .LCmpbyteExit:
  345. movl saveedi,%edi
  346. movl saveesi,%esi
  347. end;
  348. {$define FPC_SYSTEM_HAS_COMPAREWORD}
  349. function CompareWord(Const buf1,buf2;len:longint):longint; assembler;
  350. var
  351. saveesi,saveedi,saveebx : longint;
  352. asm
  353. movl %edi,saveedi
  354. movl %esi,saveesi
  355. movl %ebx,saveebx
  356. cld
  357. {$ifdef REGCALL}
  358. movl %eax,%edi
  359. movl %edx,%esi
  360. movl %ecx,%eax
  361. {$else}
  362. movl len,%eax
  363. movl buf2,%esi { Load params}
  364. movl buf1,%edi
  365. {$endif}
  366. testl %eax,%eax {We address -2(%esi), so we have to deal with len=0}
  367. je .LCmpwordExit
  368. cmpl $5,%eax {<5 (3 bytes align + 4 bytes cmpsl = 4 words}
  369. jl .LCmpword2 { not worth aligning and go through all trouble}
  370. movl (%edi),%ebx // Compare alignment bytes.
  371. cmpl (%esi),%ebx
  372. jne .LCmpword2 // Aligning will go wrong already. Max 2 words will be scanned Branch NOW
  373. shll $1,%eax {Convert word count to bytes}
  374. movl %edi,%edx { Align comparing is already done, so simply add}
  375. negl %edx { calc bytes to align -%edi and 3}
  376. andl $3,%edx
  377. addl %edx,%esi { Skip max 3 bytes alignment}
  378. addl %edx,%edi
  379. subl %edx,%eax { Subtract from number of bytes to go}
  380. movl %eax,%ecx { Make copy of bytes to go}
  381. andl $3,%eax { Calc remainder (mod 4) }
  382. andl $1,%edx { %edx is 1 if array not 2-aligned, 0 otherwise}
  383. shrl $2,%ecx { divide bytes to go by 4, DWords to go}
  384. orl %ecx,%ecx { Sets zero flag if ecx=0 -> no cmp}
  385. rep { Compare entire DWords}
  386. cmpsl
  387. je .LCmpword2a { All equal? then to the left over bytes}
  388. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  389. subl %eax,%esi { Go back one DWord}
  390. subl %eax,%edi
  391. incl %eax {if not odd then this does nothing, else it makes
  392. sure that adding %edx increases from 2 to 3 words}
  393. .LCmpword2a:
  394. subl %edx,%esi { Subtract alignment}
  395. subl %edx,%edi
  396. addl %edx,%eax
  397. shrl $1,%eax
  398. .LCmpword2:
  399. movl %eax,%ecx {words still to (re)scan}
  400. orl %eax,%eax {prevent disaster in case %eax=0}
  401. rep
  402. cmpsw
  403. .LCmpword3:
  404. movzwl -2(%esi),%ecx
  405. movzwl -2(%edi),%eax // Compare failing (or equal) position
  406. subl %ecx,%eax // calculate end result.
  407. .LCmpwordExit:
  408. movl saveedi,%edi
  409. movl saveesi,%esi
  410. movl saveebx,%ebx
  411. end;
  412. {$define FPC_SYSTEM_HAS_COMPAREDWORD}
  413. function CompareDWord(Const buf1,buf2;len:longint):longint; assembler;
  414. var
  415. saveesi,saveedi,saveebx : longint;
  416. asm
  417. movl %edi,saveedi
  418. movl %esi,saveesi
  419. movl %ebx,saveebx
  420. cld
  421. {$ifdef REGCALL}
  422. movl %eax,%edi
  423. movl %edx,%esi
  424. movl %ecx,%eax
  425. {$else}
  426. movl len,%eax
  427. movl buf2,%esi { Load params}
  428. movl buf1,%edi
  429. {$endif}
  430. testl %eax,%eax {We address -2(%esi), so we have to deal with len=0}
  431. je .LCmpDwordExit
  432. cmpl $3,%eax {<3 (3 bytes align + 4 bytes cmpsl) = 2 DWords}
  433. jl .LCmpDword2 { not worth aligning and go through all trouble}
  434. movl (%edi),%ebx // Compare alignment bytes.
  435. cmpl (%esi),%ebx
  436. jne .LCmpDword2 // Aligning will go wrong already. Max 2 words will be scanned Branch NOW
  437. shll $2,%eax {Convert word count to bytes}
  438. movl %edi,%edx { Align comparing is already done, so simply add}
  439. negl %edx { calc bytes to align -%edi and 3}
  440. andl $3,%edx
  441. addl %edx,%esi { Skip max 3 bytes alignment}
  442. addl %edx,%edi
  443. subl %edx,%eax { Subtract from number of bytes to go}
  444. movl %eax,%ecx { Make copy of bytes to go}
  445. andl $3,%eax { Calc remainder (mod 4) }
  446. shrl $2,%ecx { divide bytes to go by 4, DWords to go}
  447. orl %ecx,%ecx { Sets zero flag if ecx=0 -> no cmp}
  448. rep { Compare entire DWords}
  449. cmpsl
  450. je .LCmpDword2a { All equal? then to the left over bytes}
  451. movl $4,%eax { Not equal. Rescan the last 4 bytes bytewise}
  452. subl %eax,%esi { Go back one DWord}
  453. subl %eax,%edi
  454. addl $3,%eax {if align<>0 this causes repcount to be 2}
  455. .LCmpDword2a:
  456. subl %edx,%esi { Subtract alignment}
  457. subl %edx,%edi
  458. addl %edx,%eax
  459. shrl $2,%eax
  460. .LCmpDword2:
  461. movl %eax,%ecx {words still to (re)scan}
  462. orl %eax,%eax {prevent disaster in case %eax=0}
  463. rep
  464. cmpsl
  465. .LCmpDword3:
  466. movzwl -4(%esi),%ecx
  467. movzwl -4(%edi),%eax // Compare failing (or equal) position
  468. subl %ecx,%eax // calculate end result.
  469. .LCmpDwordExit:
  470. movl saveedi,%edi
  471. movl saveesi,%esi
  472. movl saveebx,%ebx
  473. end;
  474. {$define FPC_SYSTEM_HAS_INDEXCHAR0}
  475. function IndexChar0(Const buf;len:longint;b:Char):longint; assembler;
  476. var
  477. saveesi,saveebx : longint;
  478. asm
  479. movl %esi,saveesi
  480. movl %ebx,saveebx
  481. // Can't use scasb, or will have to do it twice, think this
  482. // is faster for small "len"
  483. {$ifdef REGCALL}
  484. movl %eax,%esi // Load address
  485. movzbl %cl,%ebx // Load searchpattern
  486. {$else}
  487. movl Buf,%esi // Load address
  488. movl len,%edx // load maximal searchdistance
  489. movzbl b,%ebx // Load searchpattern
  490. {$endif}
  491. testl %edx,%edx
  492. je .LFound
  493. xorl %ecx,%ecx // zero index in Buf
  494. xorl %eax,%eax // To make DWord compares possible
  495. .LLoop:
  496. movb (%esi),%al // Load byte
  497. cmpb %al,%bl
  498. je .LFound // byte the same?
  499. incl %ecx
  500. incl %esi
  501. cmpl %edx,%ecx // Maximal distance reached?
  502. je .LNotFound
  503. testl %eax,%eax // Nullchar = end of search?
  504. jne .LLoop
  505. .LNotFound:
  506. movl $-1,%ecx // Not found return -1
  507. .LFound:
  508. movl %ecx,%eax
  509. movl saveesi,%esi
  510. movl saveebx,%ebx
  511. end;
  512. {****************************************************************************
  513. Object Helpers
  514. ****************************************************************************}
  515. {$ifndef HAS_GENERICCONSTRUCTOR}
  516. {$define FPC_SYSTEM_HAS_FPC_HELP_CONSTRUCTOR}
  517. procedure fpc_help_constructor; assembler; [public,alias:'FPC_HELP_CONSTRUCTOR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  518. asm
  519. { Entry without preamble, since we need the ESP of the constructor
  520. Stack (relative to %ebp):
  521. 12 Self
  522. 8 VMT-Address
  523. 4 main programm-Addr
  524. 0 %ebp
  525. edi contains the vmt position
  526. }
  527. { eax isn't touched anywhere, so it doesn't have to reloaded }
  528. movl 8(%ebp),%eax
  529. { initialise self ? }
  530. orl %esi,%esi
  531. jne .LHC_4
  532. { get memory, but save register first temporary variable }
  533. subl $4,%esp
  534. movl %esp,%esi
  535. { Save Register}
  536. pushal
  537. {$ifdef valuegetmem}
  538. { esi can be destroyed in fpc_getmem!!! (JM) }
  539. pushl %esi
  540. {$endif valuegetmem}
  541. { Memory size }
  542. pushl (%eax)
  543. {$ifdef valuegetmem}
  544. call fpc_getmem
  545. popl %esi
  546. movl %eax,(%esi)
  547. {$else valuegetmem}
  548. pushl %esi
  549. call AsmGetMem
  550. {$endif valuegetmem}
  551. movl $-1,8(%ebp)
  552. popal
  553. { Avoid 80386DX bug }
  554. nop
  555. { Memory position to %esi }
  556. movl (%esi),%esi
  557. addl $4,%esp
  558. { If no memory available : fail() }
  559. orl %esi,%esi
  560. jz .LHC_5
  561. { init self for the constructor }
  562. movl %esi,12(%ebp)
  563. { jmp not necessary anymore because next instruction is disabled (JM)
  564. jmp .LHC_6 }
  565. { Why was the VMT reset to zero here ????
  566. I need it fail to know if I should
  567. zero the VMT field in static objects PM }
  568. .LHC_4:
  569. { movl $0,8(%ebp) }
  570. .LHC_6:
  571. { is there a VMT address ? }
  572. orl %eax,%eax
  573. jnz .LHC_7
  574. { In case the constructor doesn't do anything, the Zero-Flag }
  575. { can't be put, because this calls Fail() }
  576. incl %eax
  577. ret
  578. .LHC_7:
  579. { set zero inside the object }
  580. pushal
  581. cld
  582. movl (%eax),%ecx
  583. movl %esi,%edi
  584. movl %ecx,%ebx
  585. xorl %eax,%eax
  586. shrl $2,%ecx
  587. andl $3,%ebx
  588. rep
  589. stosl
  590. movl %ebx,%ecx
  591. rep
  592. stosb
  593. popal
  594. { avoid the 80386DX bug }
  595. nop
  596. { set the VMT address for the new created object }
  597. { the offset is in %edi since the calling and has not been changed !! }
  598. movl %eax,(%esi,%edi,1)
  599. testl %eax,%eax
  600. .LHC_5:
  601. end;
  602. {$define FPC_SYSTEM_HAS_FPC_HELP_FAIL}
  603. procedure fpc_help_fail;assembler;[public,alias:'FPC_HELP_FAIL']; {$ifdef hascompilerproc} compilerproc; {$endif}
  604. { should be called with a object that needs to be
  605. freed if VMT field is at -1
  606. %edi contains VMT offset in object again }
  607. asm
  608. testl %esi,%esi
  609. je .LHF_1
  610. cmpl $-1,8(%ebp)
  611. je .LHF_2
  612. { reset vmt field to zero for static instances }
  613. cmpl $0,8(%ebp)
  614. je .LHF_3
  615. { main constructor, we can zero the VMT field now }
  616. movl $0,(%esi,%edi,1)
  617. .LHF_3:
  618. { we zero esi to indicate failure }
  619. xorl %esi,%esi
  620. jmp .LHF_1
  621. .LHF_2:
  622. { get vmt address in eax }
  623. movl (%esi,%edi,1),%eax
  624. movl %esi,12(%ebp)
  625. { push object position }
  626. {$ifdef valuefreemem}
  627. pushl %esi
  628. call fpc_freemem
  629. {$else valuefreemem}
  630. leal 12(%ebp),%eax
  631. pushl %eax
  632. call AsmFreeMem
  633. {$endif valuefreemem}
  634. { set both object places to zero }
  635. xorl %esi,%esi
  636. movl %esi,12(%ebp)
  637. .LHF_1:
  638. end;
  639. {$define FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  640. procedure fpc_help_destructor;assembler;[public,alias:'FPC_HELP_DESTRUCTOR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  641. asm
  642. { Stack (relative to %ebp):
  643. 12 Self
  644. 8 VMT-Address
  645. 4 Main program-Addr
  646. 0 %ebp
  647. edi contains the vmt position
  648. }
  649. pushal
  650. { Should the object be resolved ? }
  651. movl 8(%ebp),%eax
  652. orl %eax,%eax
  653. jz .LHD_3
  654. { Yes, get size from SELF! }
  655. movl 12(%ebp),%eax
  656. { get VMT-pointer (from Self) to %ebx }
  657. { the offset is in %edi since the calling and has not been changed !! }
  658. movl (%eax,%edi,1),%ebx
  659. { I think for precaution }
  660. { that we should clear the VMT here }
  661. movl $0,(%eax,%edi,1)
  662. {$ifdef valuefreemem}
  663. { Freemem }
  664. pushl %eax
  665. call fpc_freemem
  666. {$else valuefreemem}
  667. { temporary Variable }
  668. subl $4,%esp
  669. movl %esp,%edi
  670. { SELF }
  671. movl %eax,(%edi)
  672. pushl %edi
  673. call AsmFreeMem
  674. addl $4,%esp
  675. {$endif valuefreemem}
  676. .LHD_3:
  677. popal
  678. { avoid the 80386DX bug }
  679. nop
  680. end;
  681. {$define FPC_SYSTEM_HAS_FPC_NEW_CLASS}
  682. procedure fpc_new_class;assembler;[public,alias:'FPC_NEW_CLASS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  683. asm
  684. { to be sure in the future, we save also edit }
  685. pushl %edi
  686. { create class ? }
  687. movl 8(%ebp),%edi
  688. { if we test eax later without calling newinstance }
  689. { it must have a value <>0 }
  690. movl $1,%eax
  691. testl %edi,%edi
  692. jz .LNEW_CLASS1
  693. { save registers !! }
  694. pushl %ebx
  695. pushl %ecx
  696. pushl %edx
  697. { esi contains the vmt }
  698. pushl %esi
  699. { call newinstance (class method!) }
  700. call *52{vmtNewInstance}(%esi)
  701. popl %edx
  702. popl %ecx
  703. popl %ebx
  704. { newinstance returns a pointer to the new created }
  705. { instance in eax }
  706. { load esi and insert self }
  707. movl %eax,%esi
  708. .LNEW_CLASS1:
  709. movl %esi,8(%ebp)
  710. testl %eax,%eax
  711. popl %edi
  712. end;
  713. { Internal alias that can be reference from asm code }
  714. procedure int_dispose_class;external name 'FPC_DISPOSE_CLASS';
  715. {$define FPC_SYSTEM_HAS_FPC_DISPOSE_CLASS}
  716. procedure fpc_dispose_class;assembler;[public,alias:'FPC_DISPOSE_CLASS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  717. asm
  718. { to be sure in the future, we save also edit }
  719. pushl %edi
  720. { destroy class ? }
  721. movl 12(%ebp),%edi
  722. testl %edi,%edi
  723. jz .LDISPOSE_CLASS1
  724. { no inherited call }
  725. movl (%esi),%edi
  726. { save registers !! }
  727. pushl %eax
  728. pushl %ebx
  729. pushl %ecx
  730. pushl %edx
  731. { push self }
  732. pushl %esi
  733. { call freeinstance }
  734. call *56{vmtFreeInstance}(%edi)
  735. popl %edx
  736. popl %ecx
  737. popl %ebx
  738. popl %eax
  739. .LDISPOSE_CLASS1:
  740. popl %edi
  741. end;
  742. {$define FPC_SYSTEM_HAS_FPC_HELP_FAIL_CLASS}
  743. procedure fpc_help_fail_class;assembler;[public,alias:'FPC_HELP_FAIL_CLASS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  744. { a non zero class must allways be disposed
  745. VMT is allways at pos 0 }
  746. asm
  747. testl %esi,%esi
  748. je .LHFC_1
  749. { can't use the compilerproc version as that will generate a
  750. reference instead of a symbol }
  751. call int_dispose_class
  752. { set both object places to zero }
  753. xorl %esi,%esi
  754. movl %esi,8(%ebp)
  755. .LHFC_1:
  756. end;
  757. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  758. { we want the stack for debugging !! PM }
  759. procedure fpc_check_object(obj : pointer);[public,alias:'FPC_CHECK_OBJECT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  760. begin
  761. asm
  762. pushl %edi
  763. movl obj,%edi
  764. pushl %eax
  765. { Here we must check if the VMT pointer is nil before }
  766. { accessing it... }
  767. testl %edi,%edi
  768. jz .Lco_re
  769. movl (%edi),%eax
  770. addl 4(%edi),%eax
  771. jz .Lco_ok
  772. .Lco_re:
  773. pushl $210
  774. call HandleError
  775. .Lco_ok:
  776. popl %eax
  777. popl %edi
  778. { the adress is pushed : it needs to be removed from stack !! PM }
  779. end;{ of asm }
  780. end;
  781. {$define FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  782. procedure fpc_check_object_ext;assembler;[public,alias:'FPC_CHECK_OBJECT_EXT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  783. { checks for a correct vmt pointer }
  784. { deeper check to see if the current object is }
  785. { really related to the true }
  786. asm
  787. pushl %ebp
  788. movl %esp,%ebp
  789. pushl %edi
  790. movl 8(%ebp),%edi
  791. pushl %ebx
  792. movl 12(%ebp),%ebx
  793. pushl %eax
  794. { Here we must check if the VMT pointer is nil before }
  795. { accessing it... }
  796. .Lcoext_obj:
  797. testl %edi,%edi
  798. jz .Lcoext_re
  799. movl (%edi),%eax
  800. addl 4(%edi),%eax
  801. jnz .Lcoext_re
  802. cmpl %edi,%ebx
  803. je .Lcoext_ok
  804. .Lcoext_vmt:
  805. movl 8(%edi),%eax
  806. cmpl %ebx,%eax
  807. je .Lcoext_ok
  808. movl %eax,%edi
  809. jmp .Lcoext_obj
  810. .Lcoext_re:
  811. pushl $219
  812. call HandleError
  813. .Lcoext_ok:
  814. popl %eax
  815. popl %ebx
  816. popl %edi
  817. { the adress and vmt were pushed : it needs to be removed from stack !! PM }
  818. popl %ebp
  819. ret $8
  820. end;
  821. {$endif HAS_GENERICCONSTRUCTOR}
  822. {****************************************************************************
  823. String
  824. ****************************************************************************}
  825. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  826. function fpc_shortstr_to_shortstr(len:longint; const sstr: shortstring): shortstring; [public,alias: 'FPC_SHORTSTR_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  827. begin
  828. asm
  829. cld
  830. movl __RESULT,%edi
  831. movl sstr,%esi
  832. xorl %eax,%eax
  833. movl len,%ecx
  834. lodsb
  835. cmpl %ecx,%eax
  836. jbe .LStrCopy1
  837. movl %ecx,%eax
  838. .LStrCopy1:
  839. stosb
  840. cmpl $7,%eax
  841. jl .LStrCopy2
  842. movl %edi,%ecx { Align on 32bits }
  843. negl %ecx
  844. andl $3,%ecx
  845. subl %ecx,%eax
  846. rep
  847. movsb
  848. movl %eax,%ecx
  849. andl $3,%eax
  850. shrl $2,%ecx
  851. rep
  852. movsl
  853. .LStrCopy2:
  854. movl %eax,%ecx
  855. rep
  856. movsb
  857. end ['ESI','EDI','EAX','ECX'];
  858. end;
  859. {$ifdef interncopy}
  860. procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN'];
  861. {$else}
  862. procedure fpc_shortstr_copy(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_COPY'];
  863. {$endif}
  864. begin
  865. asm
  866. pushl %eax
  867. pushl %ecx
  868. cld
  869. movl dstr,%edi
  870. movl sstr,%esi
  871. xorl %eax,%eax
  872. movl len,%ecx
  873. lodsb
  874. cmpl %ecx,%eax
  875. jbe .LStrCopy1
  876. movl %ecx,%eax
  877. .LStrCopy1:
  878. stosb
  879. cmpl $7,%eax
  880. jl .LStrCopy2
  881. movl %edi,%ecx { Align on 32bits }
  882. negl %ecx
  883. andl $3,%ecx
  884. subl %ecx,%eax
  885. rep
  886. movsb
  887. movl %eax,%ecx
  888. andl $3,%eax
  889. shrl $2,%ecx
  890. rep
  891. movsl
  892. .LStrCopy2:
  893. movl %eax,%ecx
  894. rep
  895. movsb
  896. popl %ecx
  897. popl %eax
  898. end ['ESI','EDI'];
  899. end;
  900. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  901. function fpc_shortstr_concat(const s1,s2:shortstring):shortstring;{$ifdef hascompilerproc}compilerproc;{$endif}
  902. begin
  903. asm
  904. movl __RESULT,%edi
  905. movl %edi,%ebx
  906. movl s1,%esi { first string }
  907. lodsb
  908. andl $0x0ff,%eax
  909. stosb
  910. cmpl $7,%eax
  911. jl .LStrConcat1
  912. movl %edi,%ecx { Align on 32bits }
  913. negl %ecx
  914. andl $3,%ecx
  915. subl %ecx,%eax
  916. rep
  917. movsb
  918. movl %eax,%ecx
  919. andl $3,%eax
  920. shrl $2,%ecx
  921. rep
  922. movsl
  923. .LStrConcat1:
  924. movl %eax,%ecx
  925. rep
  926. movsb
  927. movl s2,%esi { second string }
  928. movzbl (%ebx),%ecx
  929. negl %ecx
  930. addl $0x0ff,%ecx
  931. lodsb
  932. cmpl %ecx,%eax
  933. jbe .LStrConcat2
  934. movl %ecx,%eax
  935. .LStrConcat2:
  936. addb %al,(%ebx)
  937. cmpl $7,%eax
  938. jl .LStrConcat3
  939. movl %edi,%ecx { Align on 32bits }
  940. negl %ecx
  941. andl $3,%ecx
  942. subl %ecx,%eax
  943. rep
  944. movsb
  945. movl %eax,%ecx
  946. andl $3,%eax
  947. shrl $2,%ecx
  948. rep
  949. movsl
  950. .LStrConcat3:
  951. movl %eax,%ecx
  952. rep
  953. movsb
  954. end ['EBX','ECX','EAX','ESI','EDI'];
  955. end;
  956. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  957. {$ifdef hascompilerproc}
  958. procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring);compilerproc;
  959. [public,alias:'FPC_SHORTSTR_APPEND_SHORTSTR'];
  960. begin
  961. asm
  962. movl s1,%edi
  963. movl s2,%esi
  964. movl %edi,%ebx
  965. movzbl (%edi),%ecx
  966. movl __HIGH(s1),%eax
  967. lea 1(%edi,%ecx),%edi
  968. negl %ecx
  969. addl %eax,%ecx
  970. // no need to zero eax, high(s1) <= 255
  971. lodsb
  972. cmpl %ecx,%eax
  973. jbe .LStrConcat1
  974. movl %ecx,%eax
  975. .LStrConcat1:
  976. addb %al,(%ebx)
  977. cmpl $7,%eax
  978. jl .LStrConcat2
  979. movl %edi,%ecx { Align on 32bits }
  980. negl %ecx
  981. andl $3,%ecx
  982. subl %ecx,%eax
  983. rep
  984. movsb
  985. movl %eax,%ecx
  986. andl $3,%eax
  987. shrl $2,%ecx
  988. rep
  989. movsl
  990. .LStrConcat2:
  991. movl %eax,%ecx
  992. rep
  993. movsb
  994. end ['EBX','ECX','EAX','ESI','EDI'];
  995. end;
  996. {$else hascompilerproc}
  997. procedure fpc_shortstr_concat_int(const s1,s2:shortstring);[public,alias:'FPC_SHORTSTR_CONCAT'];
  998. begin
  999. asm
  1000. movl s1,%esi
  1001. movl s2,%edi
  1002. movl %edi,%ebx
  1003. movzbl (%edi),%ecx
  1004. xor %eax,%eax
  1005. lea 1(%edi,%ecx),%edi
  1006. negl %ecx
  1007. addl $0x0ff,%ecx
  1008. lodsb
  1009. cmpl %ecx,%eax
  1010. jbe .LStrConcat1
  1011. movl %ecx,%eax
  1012. .LStrConcat1:
  1013. addb %al,(%ebx)
  1014. cmpl $7,%eax
  1015. jl .LStrConcat2
  1016. movl %edi,%ecx { Align on 32bits }
  1017. negl %ecx
  1018. andl $3,%ecx
  1019. subl %ecx,%eax
  1020. rep
  1021. movsb
  1022. movl %eax,%ecx
  1023. andl $3,%eax
  1024. shrl $2,%ecx
  1025. rep
  1026. movsl
  1027. .LStrConcat2:
  1028. movl %eax,%ecx
  1029. rep
  1030. movsb
  1031. end ['EBX','ECX','EAX','ESI','EDI'];
  1032. end;
  1033. {$endif hascompilerproc}
  1034. {$define FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  1035. function fpc_shortstr_compare(const left,right:shortstring): longint; [public,alias:'FPC_SHORTSTR_COMPARE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  1036. begin
  1037. asm
  1038. cld
  1039. xorl %ebx,%ebx
  1040. xorl %eax,%eax
  1041. movl right,%esi
  1042. movl left,%edi
  1043. movb (%esi),%al
  1044. movb (%edi),%bl
  1045. movl %eax,%edx
  1046. incl %esi
  1047. incl %edi
  1048. cmpl %ebx,%eax
  1049. jbe .LStrCmp1
  1050. movl %ebx,%eax
  1051. .LStrCmp1:
  1052. cmpl $7,%eax
  1053. jl .LStrCmp2
  1054. movl %edi,%ecx { Align on 32bits }
  1055. negl %ecx
  1056. andl $3,%ecx
  1057. subl %ecx,%eax
  1058. orl %ecx,%ecx
  1059. rep
  1060. cmpsb
  1061. jne .LStrCmp3
  1062. movl %eax,%ecx
  1063. andl $3,%eax
  1064. shrl $2,%ecx
  1065. orl %ecx,%ecx
  1066. rep
  1067. cmpsl
  1068. je .LStrCmp2
  1069. movl $4,%eax
  1070. sub %eax,%esi
  1071. sub %eax,%edi
  1072. .LStrCmp2:
  1073. movl %eax,%ecx
  1074. orl %eax,%eax
  1075. rep
  1076. cmpsb
  1077. jne .LStrCmp3
  1078. cmp %ebx,%edx
  1079. .LStrCmp3:
  1080. end ['EDX','ECX','EBX','EAX','ESI','EDI'];
  1081. end;
  1082. {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  1083. function fpc_pchar_to_shortstr(p:pchar):shortstring;assembler;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  1084. {$include strpas.inc}
  1085. {$define FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  1086. function fpc_pchar_length(p:pchar):longint;assembler;[public,alias:'FPC_PCHAR_LENGTH']; {$ifdef hascompilerproc} compilerproc; {$endif}
  1087. {$include strlen.inc}
  1088. {$define FPC_SYSTEM_HAS_GET_FRAME}
  1089. function get_frame:pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  1090. asm
  1091. movl %ebp,%eax
  1092. end ['EAX'];
  1093. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  1094. function get_caller_addr(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  1095. asm
  1096. {$ifndef REGCALL}
  1097. movl framebp,%eax
  1098. {$endif}
  1099. orl %eax,%eax
  1100. jz .Lg_a_null
  1101. movl 4(%eax),%eax
  1102. .Lg_a_null:
  1103. end ['EAX'];
  1104. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  1105. function get_caller_frame(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  1106. asm
  1107. {$ifndef REGCALL}
  1108. movl framebp,%eax
  1109. {$endif}
  1110. orl %eax,%eax
  1111. jz .Lgnf_null
  1112. movl (%eax),%eax
  1113. .Lgnf_null:
  1114. end ['EAX'];
  1115. {****************************************************************************
  1116. Math
  1117. ****************************************************************************}
  1118. {$define FPC_SYSTEM_HAS_ABS_LONGINT}
  1119. function abs(l:longint):longint; assembler;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_abs];
  1120. asm
  1121. {$ifndef REGCALL}
  1122. movl l,%eax
  1123. {$endif}
  1124. cltd
  1125. xorl %edx,%eax
  1126. subl %edx,%eax
  1127. end ['EAX','EDX'];
  1128. {$define FPC_SYSTEM_HAS_ODD_LONGINT}
  1129. function odd(l:longint):boolean;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_odd];
  1130. asm
  1131. {$ifdef SYSTEMINLINE}
  1132. movl l,%eax
  1133. {$else}
  1134. {$ifndef REGCALL}
  1135. movl l,%eax
  1136. {$endif}
  1137. {$endif}
  1138. andl $1,%eax
  1139. setnz %al
  1140. end ['EAX'];
  1141. {$define FPC_SYSTEM_HAS_SQR_LONGINT}
  1142. function sqr(l:longint):longint;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_sqr];
  1143. asm
  1144. {$ifdef SYSTEMINLINE}
  1145. movl l,%eax
  1146. {$else}
  1147. {$ifndef REGCALL}
  1148. movl l,%eax
  1149. {$endif}
  1150. {$endif}
  1151. imull %eax,%eax
  1152. end ['EAX'];
  1153. {$define FPC_SYSTEM_HAS_SPTR}
  1154. Function Sptr : Pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  1155. asm
  1156. movl %esp,%eax
  1157. end;
  1158. {****************************************************************************
  1159. Str()
  1160. ****************************************************************************}
  1161. {$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
  1162. procedure int_str(l : longint;var s : string);
  1163. var
  1164. buffer : array[0..15] of byte;
  1165. isneg : byte;
  1166. begin
  1167. { Workaround: }
  1168. if l=longint($80000000) then
  1169. begin
  1170. s:='-2147483648';
  1171. exit;
  1172. end;
  1173. asm
  1174. movl l,%eax // load Integer
  1175. xorl %ecx,%ecx // String length=0
  1176. leal buffer,%ebx
  1177. movl $0x0a,%esi // load 10 as dividing constant.
  1178. movb $0,isneg
  1179. orl %eax,%eax // Sign ?
  1180. jns .LM2
  1181. movb $1,isneg
  1182. negl %eax
  1183. .LM2:
  1184. cltd
  1185. idivl %esi
  1186. addb $0x30,%dl // convert Rest to ASCII.
  1187. movb %dl,(%ebx)
  1188. incl %ecx
  1189. incl %ebx
  1190. cmpl $0,%eax
  1191. jnz .LM2
  1192. { now copy the string }
  1193. movl s,%edi // Load String address
  1194. cmpb $0,isneg
  1195. je .LM3
  1196. movb $0x2d,(%ebx)
  1197. incl %ecx
  1198. incl %ebx
  1199. .LM3:
  1200. movb %cl,(%edi) // Copy String length
  1201. incl %edi
  1202. .LM4:
  1203. decl %ebx
  1204. movb (%ebx),%al
  1205. stosb
  1206. decl %ecx
  1207. jnz .LM4
  1208. end ['eax','ecx','edx','ebx','esi','edi'];
  1209. end;
  1210. {$define FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  1211. procedure int_str(c : longword;var s : string);
  1212. var
  1213. buffer : array[0..15] of byte;
  1214. begin
  1215. asm
  1216. movl c,%eax // load CARDINAL
  1217. xorl %ecx,%ecx // String length=0
  1218. leal buffer,%ebx
  1219. movl $0x0a,%esi // load 10 as dividing constant.
  1220. .LM4:
  1221. xorl %edx,%edx
  1222. divl %esi
  1223. addb $0x30,%dl // convert Rest to ASCII.
  1224. movb %dl,(%ebx)
  1225. incl %ecx
  1226. incl %ebx
  1227. cmpl $0,%eax
  1228. jnz .LM4
  1229. { now copy the string }
  1230. movl s,%edi // Load String address
  1231. movb %cl,(%edi) // Copy String length
  1232. incl %edi
  1233. .LM5:
  1234. decl %ebx
  1235. movb (%ebx),%al
  1236. stosb
  1237. decl %ecx
  1238. jnz .LM5
  1239. end ['eax','ecx','edx','ebx','esi','edi'];
  1240. end;
  1241. {****************************************************************************
  1242. Bounds Check
  1243. ****************************************************************************}
  1244. {$ifndef NOBOUNDCHECK}
  1245. procedure int_boundcheck;assembler;[public,alias: 'FPC_BOUNDCHECK'];
  1246. var dummy_to_force_stackframe_generation_for_trace: Longint;
  1247. {
  1248. called with:
  1249. %ecx - value
  1250. %edi - pointer to the ranges
  1251. }
  1252. asm
  1253. cmpl (%edi),%ecx
  1254. jl .Lbc_err
  1255. cmpl 4(%edi),%ecx
  1256. jle .Lbc_ok
  1257. .Lbc_err:
  1258. pushl %ebp
  1259. pushl $201
  1260. call HandleErrorFrame
  1261. .Lbc_ok:
  1262. end;
  1263. {$endif NOBOUNDCHECK}
  1264. { do a thread save inc/dec }
  1265. {$define FPC_SYSTEM_HAS_DECLOCKED}
  1266. function declocked(var l : longint) : boolean;assembler;
  1267. asm
  1268. {$ifndef REGCALL}
  1269. movl l,%eax
  1270. {$endif}
  1271. { this check should be done because a lock takes a lot }
  1272. { of time! }
  1273. cmpb $0,IsMultithread
  1274. jz .Ldeclockednolock
  1275. lock
  1276. decl (%eax)
  1277. jmp .Ldeclockedend
  1278. .Ldeclockednolock:
  1279. decl (%eax);
  1280. .Ldeclockedend:
  1281. setzb %al
  1282. end;
  1283. {$define FPC_SYSTEM_HAS_INCLOCKED}
  1284. procedure inclocked(var l : longint);assembler;
  1285. asm
  1286. {$ifndef REGCALL}
  1287. movl l,%eax
  1288. {$endif}
  1289. { this check should be done because a lock takes a lot }
  1290. { of time! }
  1291. cmpb $0,IsMultithread
  1292. jz .Linclockednolock
  1293. lock
  1294. incl (%eax)
  1295. jmp .Linclockedend
  1296. .Linclockednolock:
  1297. incl (%eax)
  1298. .Linclockedend:
  1299. end;
  1300. {****************************************************************************
  1301. FPU
  1302. ****************************************************************************}
  1303. const
  1304. fpucw : word = $1332;
  1305. { Internal constants for use in system unit }
  1306. FPU_Invalid = 1;
  1307. FPU_Denormal = 2;
  1308. FPU_DivisionByZero = 4;
  1309. FPU_Overflow = 8;
  1310. FPU_Underflow = $10;
  1311. FPU_StackUnderflow = $20;
  1312. FPU_StackOverflow = $40;
  1313. FPU_ExceptionMask = $ff;
  1314. {$define FPC_SYSTEM_HAS_SYSRESETFPU}
  1315. Procedure SysResetFPU;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
  1316. asm
  1317. fninit
  1318. fldcw fpucw
  1319. end;
  1320. {
  1321. $Log$
  1322. Revision 1.56 2003-12-24 23:07:28 peter
  1323. * fixed indexbyte for regcall
  1324. Revision 1.55 2003/12/04 21:44:39 peter
  1325. * fix warning in gas
  1326. Revision 1.54 2003/11/19 16:58:44 peter
  1327. * make strpas assembler function
  1328. Revision 1.53 2003/11/11 21:08:17 peter
  1329. * REGCALL define added
  1330. Revision 1.52 2003/11/03 09:42:27 marco
  1331. * Peter's Cardinal<->Longint fixes patch
  1332. Revision 1.51 2003/10/27 09:16:57 marco
  1333. * fix from peter i386.inc to circumvent ebx destroying
  1334. Revision 1.50 2003/10/23 17:01:27 peter
  1335. * save edi,ebx,esi in int_str
  1336. Revision 1.49 2003/10/16 21:28:40 peter
  1337. * use __HIGH()
  1338. Revision 1.48 2003/10/14 00:57:48 florian
  1339. + some code for PIC support added
  1340. Revision 1.47 2003/09/14 11:34:13 peter
  1341. * moved int64 asm code to int64p.inc
  1342. * save ebx,esi
  1343. Revision 1.46 2003/09/08 18:21:37 peter
  1344. * save edi,esi,ebx
  1345. Revision 1.45 2003/06/01 14:50:17 jonas
  1346. * fpc_shortstr_append_shortstr has to use high(s1) instead of 255 as
  1347. maxlen
  1348. + ppc version of fpc_shortstr_append_shortstr
  1349. Revision 1.44 2003/05/26 21:18:13 peter
  1350. * FPC_SHORTSTR_APPEND_SHORTSTR public added
  1351. Revision 1.43 2003/05/26 19:36:46 peter
  1352. * fpc_shortstr_concat is now the same for all targets
  1353. * fpc_shortstr_append_shortstr added for optimized code generation
  1354. Revision 1.42 2003/05/16 22:40:11 florian
  1355. * fixed generic shortstr_compare
  1356. Revision 1.41 2003/03/26 00:19:10 peter
  1357. * ifdef HAS_GENERICCONSTRUCTOR
  1358. Revision 1.40 2003/03/17 14:30:11 peter
  1359. * changed address parameter/return values to pointer instead
  1360. of longint
  1361. Revision 1.39 2003/02/18 17:56:06 jonas
  1362. - removed buggy i386-specific FPC_CHARARRAY_TO_SHORTSTR
  1363. * fixed generic FPC_CHARARRAY_TO_SHORTSTR (web bug 2382)
  1364. * fixed some potential range errors in indexchar/word/dword
  1365. Revision 1.38 2003/01/06 23:03:13 mazen
  1366. + defining FPC_SYSTEM_HAS_DECLOCKED and FPC_SYSTEM_HAS_INCLOCKED to avoid
  1367. compilation error on generic.inc
  1368. Revision 1.37 2003/01/03 17:14:54 peter
  1369. * fix possible overflow when array len > 255 when converting to
  1370. shortstring
  1371. Revision 1.36 2002/12/15 22:32:25 peter
  1372. * fixed return value when len=0 for indexchar,indexword
  1373. Revision 1.35 2002/10/20 11:50:57 carl
  1374. * avoid crashes with negative len counts on fills/moves
  1375. Revision 1.34 2002/10/15 19:24:47 carl
  1376. * Replace 220 -> 219
  1377. Revision 1.33 2002/10/14 19:39:16 peter
  1378. * threads unit added for thread support
  1379. Revision 1.32 2002/10/05 14:20:16 peter
  1380. * fpc_pchar_length compilerproc and strlen alias
  1381. Revision 1.31 2002/10/02 18:21:51 peter
  1382. * Copy() changed to internal function calling compilerprocs
  1383. * FPC_SHORTSTR_COPY renamed to FPC_SHORTSTR_ASSIGN because of the
  1384. new copy functions
  1385. Revision 1.30 2002/09/07 21:33:35 carl
  1386. - removed unused defines
  1387. Revision 1.29 2002/09/07 16:01:19 peter
  1388. * old logs removed and tabs fixed
  1389. Revision 1.28 2002/09/03 15:43:36 peter
  1390. * add alias for fpc_dispose_class so it can be called from
  1391. fpc_help_fail_class
  1392. Revision 1.27 2002/08/19 19:34:02 peter
  1393. * SYSTEMINLINE define that will add inline directives for small
  1394. functions and wrappers. This will be defined automaticly when
  1395. the compiler defines the HASINLINE directive
  1396. Revision 1.26 2002/07/26 15:45:33 florian
  1397. * changed multi threading define: it's MT instead of MTRTL
  1398. Revision 1.25 2002/07/06 20:31:59 carl
  1399. + added TEST_GENERIC to test generic version
  1400. Revision 1.24 2002/06/16 08:21:26 carl
  1401. + TEST_GENERIC to test generic versions of code
  1402. Revision 1.23 2002/06/09 12:54:37 jonas
  1403. * fixed memory corruption bug in fpc_help_constructor
  1404. Revision 1.22 2002/04/21 18:56:59 peter
  1405. * fpc_freemem and fpc_getmem compilerproc
  1406. Revision 1.21 2002/04/01 14:23:17 carl
  1407. - no need for runerror 203, already fixed!
  1408. Revision 1.20 2002/03/30 14:52:04 carl
  1409. * cause runtime error 203 on failed class creation
  1410. }