i386.inc 44 KB

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