i386.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 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. Move / Fill
  16. ****************************************************************************}
  17. procedure Move(var source;var dest;count:longint);
  18. begin
  19. asm
  20. movl dest,%edi
  21. movl source,%esi
  22. movl %edi,%eax
  23. movl count,%ebx
  24. { Check for back or forward }
  25. sub %esi,%eax
  26. jz .LMoveEnd { Do nothing when source=dest }
  27. jc .LFMove { Do forward, dest<source }
  28. cmp %ebx,%eax
  29. jb .LBMove { Dest is in range of move, do backward }
  30. { Forward Copy }
  31. .LFMove:
  32. cld
  33. cmpl $15,%ebx
  34. jl .LFMove1
  35. movl %edi,%ecx { Align on 32bits }
  36. negl %ecx
  37. andl $3,%ecx
  38. subl %ecx,%ebx
  39. rep
  40. movsb
  41. movl %ebx,%ecx
  42. andl $3,%ebx
  43. shrl $2,%ecx
  44. rep
  45. movsl
  46. .LFMove1:
  47. movl %ebx,%ecx
  48. rep
  49. movsb
  50. jmp .LMoveEnd
  51. { Backward Copy }
  52. .LBMove:
  53. std
  54. addl %ebx,%esi
  55. addl %ebx,%edi
  56. movl %edi,%ecx
  57. decl %esi
  58. decl %edi
  59. cmpl $15,%ebx
  60. jl .LBMove1
  61. negl %ecx { Align on 32bits }
  62. andl $3,%ecx
  63. subl %ecx,%ebx
  64. rep
  65. movsb
  66. movl %ebx,%ecx
  67. andl $3,%ebx
  68. shrl $2,%ecx
  69. subl $3,%esi
  70. subl $3,%edi
  71. rep
  72. movsl
  73. addl $3,%esi
  74. addl $3,%edi
  75. .LBMove1:
  76. movl %ebx,%ecx
  77. rep
  78. movsb
  79. cld
  80. .LMoveEnd:
  81. end;
  82. end;
  83. Procedure FillChar(var x;count:longint;value:byte);[alias: 'FPC_FILL_OBJECT'];
  84. begin
  85. asm
  86. cld
  87. movl x,%edi
  88. movl value,%eax { Only lower 8 bits will be used }
  89. movl count,%ecx
  90. cmpl $7,%ecx
  91. jl .LFill1
  92. movb %al,%ah
  93. movl %eax,%ebx
  94. shll $16,%eax
  95. movl %ecx,%edx
  96. movw %bx,%ax
  97. movl %edi,%ecx { Align on 32bits }
  98. negl %ecx
  99. andl $3,%ecx
  100. subl %ecx,%edx
  101. rep
  102. stosb
  103. movl %edx,%ecx
  104. andl $3,%edx
  105. shrl $2,%ecx
  106. rep
  107. stosl
  108. movl %edx,%ecx
  109. .LFill1:
  110. rep
  111. stosb
  112. end;
  113. end;
  114. procedure fillword(var x;count : longint;value : word);
  115. begin
  116. asm
  117. movl 8(%ebp),%edi
  118. movl 12(%ebp),%ecx
  119. movl 16(%ebp),%eax
  120. movl %eax,%edx
  121. shll $16,%eax
  122. movw %dx,%ax
  123. movl %ecx,%edx
  124. shrl $1,%ecx
  125. cld
  126. rep
  127. stosl
  128. movl %edx,%ecx
  129. andl $1,%ecx
  130. rep
  131. stosw
  132. end ['EAX','ECX','EDX','EDI'];
  133. end;
  134. {****************************************************************************
  135. Object Helpers
  136. ****************************************************************************}
  137. {$ASMMODE DIRECT}
  138. procedure int_help_constructor;assembler; [public,alias:{$ifdef FPCNAMES}'FPC_'+{$endif}'HELP_CONSTRUCTOR'];
  139. asm
  140. { Entry without preamble, since we need the ESP of the constructor
  141. Stack (relative to %ebp):
  142. 12 Self
  143. 8 VMT-Address
  144. 4 main programm-Addr
  145. 0 %ebp
  146. }
  147. { eax isn't touched anywhere, so it doesn't have to reloaded }
  148. movl 8(%ebp),%eax
  149. { initialise self ? }
  150. orl %esi,%esi
  151. jne .LHC_4
  152. { get memory, but save register first temporary variable }
  153. subl $4,%esp
  154. movl %esp,%esi
  155. { Save Register}
  156. pushal
  157. { Memory size }
  158. pushl (%eax)
  159. pushl %esi
  160. {$ifdef FPCNAMES}
  161. call FPC_GETMEM
  162. {$else}
  163. call GETMEM
  164. {$endif}
  165. popal
  166. { Memory size to %esi }
  167. movl (%esi),%esi
  168. addl $4,%esp
  169. { If no memory available : fail() }
  170. orl %esi,%esi
  171. jz .LHC_5
  172. { init self for the constructor }
  173. movl %esi,12(%ebp)
  174. .LHC_4:
  175. { is there a VMT address ? }
  176. orl %eax,%eax
  177. jnz .LHC_7
  178. { In case the constructor doesn't do anything, the Zero-Flag }
  179. { can't be put, because this calls Fail() }
  180. incl %eax
  181. ret
  182. .LHC_7:
  183. { set zero inside the object }
  184. pushal
  185. pushw $0
  186. pushl (%eax)
  187. pushl %esi
  188. call FPC_FILL_OBJECT
  189. popal
  190. { set the VMT address for the new created object }
  191. movl %eax,(%esi)
  192. orl %eax,%eax
  193. .LHC_5:
  194. end;
  195. procedure help_fail;assembler;
  196. asm
  197. end;
  198. procedure int_new_class;assembler;[public,alias:{$ifdef FPCNAMES}'FPC_'+{$endif}'NEW_CLASS'];
  199. asm
  200. { create class ? }
  201. movl 8(%ebp),%edi
  202. orl %edi,%edi
  203. jz .LNEW_CLASS1
  204. { esi contains the vmt }
  205. pushl %esi
  206. { call newinstance (class method!) }
  207. call *16(%esi)
  208. { newinstance returns a pointer to the new created }
  209. { instance in eax }
  210. { load esi and insert self }
  211. movl %eax,8(%ebp)
  212. movl %eax,%esi
  213. orl %eax,%eax
  214. ret
  215. .LNEW_CLASS1:
  216. movl %esi,8(%ebp)
  217. orl %eax,%eax
  218. end;
  219. procedure int_dispose_class;assembler;[public,alias:{$ifdef FPCNAMES}'FPC_'+{$endif}'DISPOSE_CLASS'];
  220. asm
  221. { destroy class ? }
  222. movl 8(%ebp),%edi
  223. { save self }
  224. movl %esi,8(%ebp)
  225. orl %edi,%edi
  226. jz .LDISPOSE_CLASS1
  227. { no inherited call }
  228. movl (%esi),%edi
  229. { push self }
  230. pushl %esi
  231. { call freeinstance }
  232. call *20(%edi)
  233. .LDISPOSE_CLASS1:
  234. { load self }
  235. movl 8(%ebp),%esi
  236. end;
  237. { checks for a correct vmt pointer }
  238. procedure int_check_object;assembler;[public,alias:{$ifdef FPCNAMES}'FPC_'+{$endif}'CHECK_OBJECT'];
  239. asm
  240. pushl %edi
  241. movl 8(%esp),%edi
  242. pushl %eax
  243. { Here we must check if the VMT pointer is nil before }
  244. { accessing it... }
  245. { WARNING: Will only probably work with GAS, as fields }
  246. { are ZEROED automatically in BSS, which might not be }
  247. { the case with other linkers/assemblers... }
  248. orl %edi,%edi
  249. jz .Lco_re
  250. movl (%edi),%eax
  251. addl 4(%edi),%eax
  252. jnz .Lco_re
  253. popl %eax
  254. popl %edi
  255. ret $4
  256. .Lco_re:
  257. pushl $210
  258. call FPC_HANDLEERROR
  259. end;
  260. procedure int_help_destructor;assembler;[public,alias:{$ifdef FPCNAMES}'FPC_'+{$endif}'HELP_DESTRUCTOR'];
  261. asm
  262. { Stack (relative to %ebp):
  263. 12 Self
  264. 8 VMT-Address
  265. 4 Main program-Addr
  266. 0 %ebp
  267. }
  268. { temporary Variable }
  269. subl $4,%esp
  270. movl %esp,%edi
  271. pushal
  272. { Should the object be resolved ? }
  273. movl 8(%ebp),%eax
  274. orl %eax,%eax
  275. jz .LHD_3
  276. { Yes, get size from SELF! }
  277. movl 12(%ebp),%eax
  278. { get VMT-pointer (from Self) to %ebx }
  279. movl (%eax),%ebx
  280. { And put size on the Stack }
  281. pushl (%ebx)
  282. { SELF }
  283. { I think for precaution }
  284. { that we should clear the VMT here }
  285. movl $0,(%eax)
  286. movl %eax,(%edi)
  287. pushl %edi
  288. {$ifdef FPCNAMES}
  289. call FPC_FREEMEM
  290. {$else}
  291. call FREEMEM
  292. {$endif}
  293. .LHD_3:
  294. popal
  295. addl $4,%esp
  296. end;
  297. {$ASMMODE ATT}
  298. {****************************************************************************
  299. String
  300. ****************************************************************************}
  301. procedure strcopy(dstr,sstr:pointer;len:longint);[public,alias:{$ifdef FPCNAMES}'FPC_'+{$endif}'STRCOPY'];
  302. {
  303. this procedure must save all modified registers except EDI and ESI !!!
  304. }
  305. begin
  306. asm
  307. pushl %eax
  308. pushl %ecx
  309. cld
  310. movl 16(%ebp),%edi
  311. movl 12(%ebp),%esi
  312. xorl %eax,%eax
  313. movl 8(%ebp),%ecx
  314. lodsb
  315. cmpl %ecx,%eax
  316. jbe .LStrCopy1
  317. movl %ecx,%eax
  318. .LStrCopy1:
  319. stosb
  320. cmpl $7,%eax
  321. jl .LStrCopy2
  322. movl %edi,%ecx { Align on 32bits }
  323. negl %ecx
  324. andl $3,%ecx
  325. subl %ecx,%eax
  326. rep
  327. movsb
  328. movl %eax,%ecx
  329. andl $3,%eax
  330. shrl $2,%ecx
  331. rep
  332. movsl
  333. .LStrCopy2:
  334. movl %eax,%ecx
  335. rep
  336. movsb
  337. popl %ecx
  338. popl %eax
  339. end ['ECX','EAX','ESI','EDI'];
  340. end;
  341. procedure strconcat(s1,s2 : pointer);[public,alias: {$ifdef FPCNAMES}'FPC_'+{$endif}'STRCONCAT'];
  342. begin
  343. asm
  344. xorl %ecx,%ecx
  345. movl 12(%ebp),%edi
  346. movl 8(%ebp),%esi
  347. movl %edi,%ebx
  348. movb (%edi),%cl
  349. lea 1(%edi,%ecx),%edi
  350. negl %ecx
  351. xor %eax,%eax
  352. addl $0xff,%ecx
  353. lodsb
  354. cmpl %ecx,%eax
  355. jbe .LStrConcat1
  356. movl %ecx,%eax
  357. .LStrConcat1:
  358. addb %al,(%ebx)
  359. cmpl $7,%eax
  360. jl .LStrConcat2
  361. movl %edi,%ecx { Align on 32bits }
  362. negl %ecx
  363. andl $3,%ecx
  364. subl %ecx,%eax
  365. rep
  366. movsb
  367. movl %eax,%ecx
  368. andl $3,%eax
  369. shrl $2,%ecx
  370. rep
  371. movsl
  372. .LStrConcat2:
  373. movl %eax,%ecx
  374. rep
  375. movsb
  376. end ['EBX','ECX','EAX','ESI','EDI'];
  377. end;
  378. procedure strcmp(dstr,sstr : pointer);[public,alias: {$ifdef FPCNAMES}'FPC_'+{$endif}'STRCMP'];
  379. begin
  380. asm
  381. cld
  382. xorl %ebx,%ebx
  383. xorl %eax,%eax
  384. movl 12(%ebp),%esi
  385. movl 8(%ebp),%edi
  386. movb (%esi),%al
  387. movb (%edi),%bl
  388. movl %eax,%edx
  389. incl %esi
  390. incl %edi
  391. cmpl %ebx,%eax
  392. jbe .LStrCmp1
  393. movl %ebx,%eax
  394. .LStrCmp1:
  395. cmpl $7,%eax
  396. jl .LStrCmp2
  397. movl %edi,%ecx { Align on 32bits }
  398. negl %ecx
  399. andl $3,%ecx
  400. subl %ecx,%eax
  401. orl %ecx,%ecx
  402. rep
  403. cmpsb
  404. jne .LStrCmp3
  405. movl %eax,%ecx
  406. andl $3,%eax
  407. shrl $2,%ecx
  408. orl %ecx,%ecx
  409. rep
  410. cmpsl
  411. je .LStrCmp2
  412. movl $4,%eax
  413. sub %eax,%esi
  414. sub %eax,%edi
  415. .LStrCmp2:
  416. movl %eax,%ecx
  417. orl %eax,%eax
  418. rep
  419. cmpsb
  420. jne .LStrCmp3
  421. cmp %ebx,%edx
  422. .LStrCmp3:
  423. end ['EDX','ECX','EBX','EAX','ESI','EDI'];
  424. end;
  425. {$ASMMODE DIRECT}
  426. function strpas(p:pchar):string;[public,alias:'FPC_PCHAR_TO_STR'];
  427. begin
  428. asm
  429. cld
  430. movl 12(%ebp),%edi
  431. movl $0xff,%ecx
  432. xorl %eax,%eax
  433. movl %edi,%esi
  434. repne
  435. scasb
  436. movl %ecx,%eax
  437. movl 8(%ebp),%edi
  438. notb %al
  439. decl %eax
  440. stosb
  441. cmpl $7,%eax
  442. jl .LStrPas2
  443. movl %edi,%ecx { Align on 32bits }
  444. negl %ecx
  445. andl $3,%ecx
  446. subl %ecx,%eax
  447. rep
  448. movsb
  449. movl %eax,%ecx
  450. andl $3,%eax
  451. shrl $2,%ecx
  452. rep
  453. movsl
  454. .LStrPas2:
  455. movl %eax,%ecx
  456. rep
  457. movsb
  458. end ['ECX','EAX','ESI','EDI'];
  459. end;
  460. {$ASMMODE ATT}
  461. function strlen(p:pchar):longint;assembler;
  462. asm
  463. movl p,%edi
  464. movl $0xffffffff,%ecx
  465. xorl %eax,%eax
  466. cld
  467. repne
  468. scasb
  469. movl $0xfffffffe,%eax
  470. subl %ecx,%eax
  471. end ['EDI','ECX','EAX'];
  472. {****************************************************************************
  473. Caller/StackFrame Helpers
  474. ****************************************************************************}
  475. function get_frame:longint;assembler;
  476. asm
  477. movl %ebp,%eax
  478. end ['EAX'];
  479. function get_caller_addr(framebp:longint):longint;assembler;
  480. asm
  481. movl framebp,%eax
  482. orl %eax,%eax
  483. jz .Lg_a_null
  484. movl 4(%eax),%eax
  485. .Lg_a_null:
  486. end ['EAX'];
  487. function get_caller_frame(framebp:longint):longint;assembler;
  488. asm
  489. movl framebp,%eax
  490. orl %eax,%eax
  491. jz .Lgnf_null
  492. movl (%eax),%eax
  493. .Lgnf_null:
  494. end ['EAX'];
  495. {****************************************************************************
  496. Math
  497. ****************************************************************************}
  498. function abs(l:longint):longint;assembler;{$ifdef INTERNCONST}[internconst:in_const_abs];{$endif}
  499. asm
  500. movl l,%eax
  501. orl %eax,%eax
  502. jns .LMABS1
  503. negl %eax
  504. .LMABS1:
  505. end ['EAX'];
  506. function odd(l:longint):boolean;assembler;{$ifdef INTERNCONST}[internconst:in_const_odd];{$endif}
  507. asm
  508. movl l,%eax
  509. andl $1,%eax
  510. setnz %al
  511. end ['EAX'];
  512. function sqr(l:longint):longint;assembler;{$ifdef INTERNCONST}[internconst:in_const_sqr];{$endif}
  513. asm
  514. mov l,%eax
  515. imull %eax,%eax
  516. end ['EAX'];
  517. Function Sptr : Longint;
  518. begin
  519. asm
  520. movl %esp,%eax
  521. addl $8,%eax
  522. movl %eax,-4(%ebp)
  523. end ['EAX'];
  524. end;
  525. {****************************************************************************
  526. Str()
  527. ****************************************************************************}
  528. procedure int_str(l : longint;var s : string);
  529. var
  530. buffer : array[0..11] of byte;
  531. begin
  532. { Workaround: }
  533. if l=$80000000 then
  534. begin
  535. s:='-2147483648';
  536. exit;
  537. end;
  538. asm
  539. movl 8(%ebp),%eax // load Integer
  540. movl 12(%ebp),%edi // Load String address
  541. xorl %ecx,%ecx // String length=0
  542. xorl %ebx,%ebx // Buffer length=0
  543. movl $0x0a,%esi // load 10 as dividing constant.
  544. or %eax,%eax // Sign ?
  545. jns .LM2
  546. neg %eax
  547. movb $0x2d,1(%edi) // put '-' in String
  548. incl %ecx
  549. .LM2:
  550. cdq
  551. idivl %esi,%eax
  552. addb $0x30,%dl // convert Rest to ASCII.
  553. movb %dl,-12(%ebp,%ebx)
  554. incl %ebx
  555. cmpl $0,%eax
  556. jnz .LM2
  557. // copy String
  558. .LM3:
  559. movb -13(%ebp,%ebx),%al // -13 because EBX is decreased only
  560. // later.
  561. movb %al,1(%edi,%ecx)
  562. incl %ecx
  563. decl %ebx
  564. jnz .LM3
  565. movb %cl,(%edi) // Copy String length
  566. end;
  567. end;
  568. procedure int_str(c : cardinal;var s : string);
  569. var
  570. buffer : array[0..14] of byte;
  571. begin
  572. asm
  573. movl 8(%ebp),%eax // load CARDINAL
  574. movl 12(%ebp),%edi // Load String address
  575. xorl %ecx,%ecx // String length=0
  576. xorl %ebx,%ebx // Buffer length=0
  577. movl $0x0a,%esi // load 10 as dividing constant.
  578. .LM4:
  579. xorl %edx,%edx
  580. divl %esi,%eax
  581. addb $0x30,%dl // convert Rest to ASCII.
  582. movb %dl,-12(%ebp,%ebx)
  583. incl %ebx
  584. cmpl $0,%eax
  585. jnz .LM4
  586. { now copy the string }
  587. .LM5:
  588. movb -13(%ebp,%ebx),%al // -13 because EBX is decreased only
  589. // later.
  590. movb %al,1(%edi,%ecx)
  591. incl %ecx
  592. decl %ebx
  593. jnz .LM5
  594. movb %cl,(%edi) // Copy String length
  595. end;
  596. end;
  597. {****************************************************************************
  598. IoCheck
  599. ****************************************************************************}
  600. procedure int_iocheck(addr : longint);[public,alias: {$ifdef FPCNAMES}'FPC_'+{$endif}'IOCHECK'];
  601. var
  602. l : longint;
  603. begin
  604. asm
  605. pushal
  606. end;
  607. if InOutRes<>0 then
  608. begin
  609. l:=InOutRes;
  610. InOutRes:=0;
  611. If ErrorProc<>Nil then
  612. TErrorProc(Errorproc)(l,pointer(addr));
  613. {$ifndef RTLLITE}
  614. writeln('IO-Error ',l,' at 0x',HexStr(addr,8));
  615. {$endif}
  616. Halt(byte(l));
  617. end;
  618. asm
  619. popal
  620. end;
  621. end;
  622. {
  623. $Log$
  624. Revision 1.25 1998-09-28 11:02:34 peter
  625. * added some more $ifdef FPCNAMES
  626. Revision 1.24 1998/09/28 10:23:43 florian
  627. * FPC_NEW_CLASS optimized: addl $0,%eax => orl %eax,%eax
  628. Revision 1.23 1998/09/28 08:40:47 michael
  629. + Bugreport from Gertjan Schouten
  630. Revision 1.22 1998/09/22 15:32:00 peter
  631. + fpc_pchar_to_str alias for strpas
  632. Revision 1.21 1998/09/14 10:48:08 peter
  633. * FPC_ names
  634. * Heap manager is now system independent
  635. Revision 1.20 1998/09/11 17:38:48 pierre
  636. merge for fixes branch
  637. Revision 1.19.2.1 1998/09/11 17:37:24 pierre
  638. * correction respective to stricter as v2.9.1 syntax
  639. Revision 1.19 1998/09/01 17:36:17 peter
  640. + internconst
  641. Revision 1.18 1998/08/11 00:04:47 peter
  642. * $ifdef ver0_99_5 updates
  643. Revision 1.17 1998/07/30 13:26:20 michael
  644. + Added support for ErrorProc variable. All internal functions are required
  645. to call HandleError instead of runerror from now on.
  646. This is necessary for exception support.
  647. Revision 1.16 1998/07/02 12:55:04 carl
  648. * Put back DoError, DO NOT TOUCH!
  649. Revision 1.15 1998/07/02 12:19:32 carl
  650. + IO-Error and Overflow now print address in hex
  651. Revision 1.14 1998/07/01 15:29:58 peter
  652. * better readln/writeln
  653. Revision 1.13 1998/06/26 08:20:57 daniel
  654. - Doerror removed.
  655. Revision 1.12 1998/05/31 14:15:47 peter
  656. * force to use ATT or direct parsing
  657. Revision 1.11 1998/05/30 14:30:21 peter
  658. * force att reading
  659. Revision 1.10 1998/05/25 10:40:49 peter
  660. * remake3 works again on tflily
  661. Revision 1.5 1998/04/29 13:28:19 peter
  662. * some cleanup and i386_att usage
  663. Revision 1.4 1998/04/10 15:41:54 florian
  664. + some small comments added
  665. Revision 1.3 1998/04/10 15:25:23 michael
  666. - Removed so-called better random function
  667. Revision 1.2 1998/04/08 07:53:31 michael
  668. + Changed Random() function. Moved from system to processor dependent files (from Pedro Gimeno)
  669. }