i386.inc 47 KB

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