i386.inc 42 KB

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