generic.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  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 independent implementation for the system unit
  6. (adapted for intel i386.inc file)
  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. {****************************************************************************
  14. Move / Fill
  15. ****************************************************************************}
  16. {$ifndef FPC_SYSTEM_HAS_MOVE}
  17. procedure Move(var source;var dest;count:longint);
  18. type
  19. longintarray = array [0..maxlongint] of longint;
  20. bytearray = array [0..maxlongint] of byte;
  21. var
  22. i,size : longint;
  23. begin
  24. size:=count div sizeof(longint);
  25. if (@dest)<@source) or
  26. (@dest>@source+count) then
  27. begin
  28. for i:=0 to size-1 do
  29. longintarray(dest)[i]:=longintarray(source)[i];
  30. for i:=size*sizeof(longint) to count-1 do
  31. bytearray(dest)[i]:=bytearray(source)[i];
  32. end
  33. else
  34. begin
  35. for i:=count-1 downto size*sizeof(longint) do
  36. bytearray(dest)[i]:=bytearray(source)[i];
  37. for i:=size-1 downto 0 do
  38. longintarray(dest)[i]:=longintarray(source)[i];
  39. end;
  40. end;
  41. {$endif ndef FPC_SYSTEM_HAS_MOVE}
  42. {$ifndef FPC_SYSTEM_HAS_FILLCHAR}
  43. Procedure FillChar(var x;count:longint;value:byte);
  44. type
  45. longintarray = array [0..maxlongint] of longint;
  46. bytearray = array [0..maxlongint] of byte;
  47. var i,v : longint;
  48. begin
  49. v:=value*256+value;
  50. v:=v*$10000+v;
  51. for i:=0 to (count div 4) -1 do
  52. longintarray(x)[i]:=v;
  53. for i:=(count div 4)*4 to count-1 do
  54. bytearray(x)[i]:=value;
  55. end;
  56. {$endif ndef FPC_SYSTEM_HAS_FILLCHAR}
  57. {$ifndef FPC_SYSTEM_HAS_FILLWORD}
  58. procedure fillword(var x;count : longint;value : word);
  59. type
  60. longintarray = array [0..maxlongint] of longint;
  61. wordarray = array [0..maxlongint] of word;
  62. var i,v : longint;
  63. begin
  64. v:=value*$10000+value;
  65. for i:=0 to (count div 2) -1 do
  66. longintarray(x)[i]:=v;
  67. for i:=(count div 2)*2 to count-1 do
  68. wordarray(x)[i]:=value;
  69. end;
  70. {$endif ndef FPC_SYSTEM_HAS_FILLWORD}
  71. {****************************************************************************
  72. Object Helpers
  73. ****************************************************************************}
  74. {$ifndef FPC_SYSTEM_HAS_FPC_HELP_CONSTRUCTOR}
  75. { Generic code does not set the register used for self !
  76. So this needs to be done by the compiler after calling
  77. FPC_HELP_CONSTRUCTOR : generic allways means aa little less efficient (PM) }
  78. procedure int_help_constructor(var _self : pointer; vmt : pointer; vmt_pos : cardinal); [public,alias:'FPC_HELP_CONSTRUCTOR'];
  79. type
  80. ppointer = ^pointer;
  81. pvmt = ^tvmt;
  82. tvmt = record
  83. size,msize : longint;
  84. parent : pointer;
  85. end;
  86. var
  87. objectsize : longint;
  88. begin
  89. objectsize:=pvmt(vmt)^.size;
  90. getmem(_self,objectsize);
  91. fillchar(_self,objectsize,#0);
  92. ppointer(_self+vmt_pos)^:=vmt;
  93. end;
  94. {$endif ndef FPC_SYSTEM_HAS_FPC_HELP_CONSTRUCTOR}
  95. {$ifndef FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  96. procedure int_help_destructor(var _self : pointer; vmt : pointer; vmt_pos : cardinal);[public,alias:'FPC_HELP_DESTRUCTOR'];
  97. type
  98. ppointer = ^pointer;
  99. pvmt = ^tvmt;
  100. tvmt = record
  101. size,msize : longint;
  102. parent : pointer;
  103. end;
  104. var
  105. objectsize : longint;
  106. begin
  107. if (_self=nil) then
  108. exit;
  109. if (pvmt(ppointer(_self+vmt_pos)^)^.size=0) or
  110. (pvmt(ppointer(_self+vmt_pos)^)^.size+pvmt(ppointer(_self+vmt_pos)^)^.msize<>0) then
  111. RunError(210);
  112. objectsize:=pvmt(vmt)^.size;
  113. { reset vmt to nil for protection }
  114. ppointer(_self+vmt_pos)^:=nil;
  115. freemem(_self,objectsize);
  116. _self:=nil;
  117. end;
  118. {$endif ndef FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  119. {$ifndef FPC_SYSTEM_HAS_FPC_NEW_CLASS}
  120. procedure int_new_class;assembler;[public,alias:'FPC_NEW_CLASS'];
  121. asm
  122. { to be sure in the future, we save also edit }
  123. pushl %edi
  124. { create class ? }
  125. movl 8(%ebp),%edi
  126. orl %edi,%edi
  127. jz .LNEW_CLASS1
  128. { save registers !! }
  129. pushl %ebx
  130. pushl %ecx
  131. pushl %edx
  132. { esi contains the vmt }
  133. pushl %esi
  134. { call newinstance (class method!) }
  135. call *16(%esi)
  136. popl %edx
  137. popl %ecx
  138. popl %ebx
  139. { newinstance returns a pointer to the new created }
  140. { instance in eax }
  141. { load esi and insert self }
  142. movl %eax,%esi
  143. .LNEW_CLASS1:
  144. movl %esi,8(%ebp)
  145. orl %eax,%eax
  146. popl %edi
  147. end;
  148. {$endif ndef FPC_SYSTEM_HAS_FPC_NEW_CLASS}
  149. {$ifndef FPC_SYSTEM_HAS_FPC_DISPOSE_CLASS}
  150. procedure int_dispose_class;assembler;[public,alias:'FPC_DISPOSE_CLASS'];
  151. asm
  152. { to be sure in the future, we save also edit }
  153. pushl %edi
  154. { destroy class ? }
  155. movl 12(%ebp),%edi
  156. orl %edi,%edi
  157. jz .LDISPOSE_CLASS1
  158. { no inherited call }
  159. movl (%esi),%edi
  160. { save registers !! }
  161. pushl %eax
  162. pushl %ebx
  163. pushl %ecx
  164. pushl %edx
  165. { push self }
  166. pushl %esi
  167. { call freeinstance }
  168. call *20(%edi)
  169. popl %edx
  170. popl %ecx
  171. popl %ebx
  172. popl %eax
  173. .LDISPOSE_CLASS1:
  174. popl %edi
  175. end;
  176. {$endif ndef FPC_SYSTEM_HAS_FPC_DISPOSE_CLASS}
  177. {$ifndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  178. procedure int_check_object(vmt : pointer);[public,alias:'FPC_CHECK_OBJECT'];
  179. type
  180. pvmt = ^tvmt;
  181. tvmt = record
  182. size,msize : longint;
  183. parent : pointer;
  184. end;
  185. begin
  186. if (vmt=nil) or
  187. (pvmt(vmt)^.size=0) or
  188. (pvmt(vmt)^.size+pvmt(vmt)^.msize<>0) then
  189. RunError(210);
  190. end;
  191. {$endif ndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  192. {$ifdef FPC_TESTOBJEXT}
  193. { checks for a correct vmt pointer }
  194. { deeper check to see if the current object is }
  195. { really related to the true }
  196. {$ifndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  197. procedure int_check_object_ext(vmt, expvmt : pointer);[public,alias:'FPC_CHECK_OBJECT_EXT'];
  198. type
  199. pvmt = ^tvmt;
  200. tvmt = record
  201. size,msize : longint;
  202. parent : pointer;
  203. end;
  204. begin
  205. if (vmt=nil) or
  206. (pvmt(vmt)^.size=0) or
  207. (pvmt(vmt)^.size+pvmt(vmt)^.msize<>0) then
  208. RunError(210);
  209. while assigned(vmt) do
  210. if vmt=expvmt then
  211. exit
  212. else
  213. vmt:=pvmt(vmt)^.parent;
  214. RunError(220);
  215. end;
  216. {$endif ndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  217. {$endif FPC_TESTOBJEXT}
  218. {****************************************************************************
  219. String
  220. ****************************************************************************}
  221. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COPY}
  222. procedure int_strcopy(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_COPY'];
  223. {
  224. this procedure must save all modified registers except EDI and ESI !!!
  225. }
  226. begin
  227. asm
  228. pushl %eax
  229. pushl %ecx
  230. cld
  231. movl 16(%ebp),%edi
  232. movl 12(%ebp),%esi
  233. xorl %eax,%eax
  234. movl 8(%ebp),%ecx
  235. lodsb
  236. cmpl %ecx,%eax
  237. jbe .LStrCopy1
  238. movl %ecx,%eax
  239. .LStrCopy1:
  240. stosb
  241. cmpl $7,%eax
  242. jl .LStrCopy2
  243. movl %edi,%ecx { Align on 32bits }
  244. negl %ecx
  245. andl $3,%ecx
  246. subl %ecx,%eax
  247. rep
  248. movsb
  249. movl %eax,%ecx
  250. andl $3,%eax
  251. shrl $2,%ecx
  252. rep
  253. movsl
  254. .LStrCopy2:
  255. movl %eax,%ecx
  256. rep
  257. movsb
  258. popl %ecx
  259. popl %eax
  260. end ['ESI','EDI'];
  261. end;
  262. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COPY}
  263. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  264. procedure int_strconcat(s1,s2:pointer);[public,alias:'FPC_SHORTSTR_CONCAT'];
  265. begin
  266. asm
  267. xorl %ecx,%ecx
  268. movl 12(%ebp),%edi
  269. movl 8(%ebp),%esi
  270. movl %edi,%ebx
  271. movb (%edi),%cl
  272. lea 1(%edi,%ecx),%edi
  273. negl %ecx
  274. xor %eax,%eax
  275. addl $0xff,%ecx
  276. lodsb
  277. cmpl %ecx,%eax
  278. jbe .LStrConcat1
  279. movl %ecx,%eax
  280. .LStrConcat1:
  281. addb %al,(%ebx)
  282. cmpl $7,%eax
  283. jl .LStrConcat2
  284. movl %edi,%ecx { Align on 32bits }
  285. negl %ecx
  286. andl $3,%ecx
  287. subl %ecx,%eax
  288. rep
  289. movsb
  290. movl %eax,%ecx
  291. andl $3,%eax
  292. shrl $2,%ecx
  293. rep
  294. movsl
  295. .LStrConcat2:
  296. movl %eax,%ecx
  297. rep
  298. movsb
  299. end ['EBX','ECX','EAX','ESI','EDI'];
  300. end;
  301. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  302. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  303. procedure int_strcmp(dstr,sstr:pointer);[public,alias:'FPC_SHORTSTR_COMPARE'];
  304. begin
  305. asm
  306. cld
  307. xorl %ebx,%ebx
  308. xorl %eax,%eax
  309. movl 12(%ebp),%esi
  310. movl 8(%ebp),%edi
  311. movb (%esi),%al
  312. movb (%edi),%bl
  313. movl %eax,%edx
  314. incl %esi
  315. incl %edi
  316. cmpl %ebx,%eax
  317. jbe .LStrCmp1
  318. movl %ebx,%eax
  319. .LStrCmp1:
  320. cmpl $7,%eax
  321. jl .LStrCmp2
  322. movl %edi,%ecx { Align on 32bits }
  323. negl %ecx
  324. andl $3,%ecx
  325. subl %ecx,%eax
  326. orl %ecx,%ecx
  327. rep
  328. cmpsb
  329. jne .LStrCmp3
  330. movl %eax,%ecx
  331. andl $3,%eax
  332. shrl $2,%ecx
  333. orl %ecx,%ecx
  334. rep
  335. cmpsl
  336. je .LStrCmp2
  337. movl $4,%eax
  338. sub %eax,%esi
  339. sub %eax,%edi
  340. .LStrCmp2:
  341. movl %eax,%ecx
  342. orl %eax,%eax
  343. rep
  344. cmpsb
  345. jne .LStrCmp3
  346. cmp %ebx,%edx
  347. .LStrCmp3:
  348. end ['EDX','ECX','EBX','EAX','ESI','EDI'];
  349. end;
  350. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  351. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  352. function strpas(p:pchar):string;[public,alias:'FPC_PCHAR_TO_SHORTSTR'];
  353. begin
  354. {$ifndef NEWATT}
  355. { remove warning }
  356. strpas:='';
  357. {$endif}
  358. asm
  359. cld
  360. movl p,%edi
  361. movl $0xff,%ecx
  362. orl %edi,%edi
  363. jnz .LStrPasNotNil
  364. decl %ecx
  365. jmp .LStrPasNil
  366. .LStrPasNotNil:
  367. xorl %eax,%eax
  368. movl %edi,%esi
  369. repne
  370. scasb
  371. .LStrPasNil:
  372. movl %ecx,%eax
  373. {$ifdef NEWATT}
  374. movl __RESULT,%edi
  375. {$else}
  376. movl 8(%ebp),%edi
  377. {$endif}
  378. notb %al
  379. decl %eax
  380. stosb
  381. cmpl $7,%eax
  382. jl .LStrPas2
  383. movl %edi,%ecx { Align on 32bits }
  384. negl %ecx
  385. andl $3,%ecx
  386. subl %ecx,%eax
  387. rep
  388. movsb
  389. movl %eax,%ecx
  390. andl $3,%eax
  391. shrl $2,%ecx
  392. rep
  393. movsl
  394. .LStrPas2:
  395. movl %eax,%ecx
  396. rep
  397. movsb
  398. end ['ECX','EAX','ESI','EDI'];
  399. end;
  400. {$endif ndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  401. {$ifndef FPC_SYSTEM_HAS_STRLEN}
  402. function strlen(p:pchar):longint;assembler;
  403. asm
  404. movl p,%edi
  405. movl $0xffffffff,%ecx
  406. xorl %eax,%eax
  407. cld
  408. repne
  409. scasb
  410. movl $0xfffffffe,%eax
  411. subl %ecx,%eax
  412. end ['EDI','ECX','EAX'];
  413. {$endif ndef FPC_SYSTEM_HAS_STRLEN}
  414. {****************************************************************************
  415. Caller/StackFrame Helpers
  416. ****************************************************************************}
  417. {$ifndef FPC_SYSTEM_HAS_GET_FRAME}
  418. {$error Get_frame must be defined for each processor }
  419. {$endif ndef FPC_SYSTEM_HAS_GET_FRAME}
  420. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  421. {$error Get_caller_addr must be defined for each processor }
  422. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  423. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  424. {$error Get_caller_frame must be defined for each processor }
  425. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  426. {****************************************************************************
  427. Math
  428. ****************************************************************************}
  429. {$ifndef FPC_SYSTEM_HAS_ABS_LONGINT}
  430. function abs(l:longint):longint;[internconst:in_const_abs];
  431. begin
  432. if l<0 then
  433. abs:=-l
  434. else
  435. abs:=l;
  436. end;
  437. {$endif ndef FPC_SYSTEM_HAS_ABS_LONGINT}
  438. {$ifndef FPC_SYSTEM_HAS_ODD_LONGINT}
  439. function odd(l:longint):boolean;[internconst:in_const_odd];
  440. begin
  441. odd:=((l and 1)<>0);
  442. end;
  443. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGINT}
  444. {$ifndef FPC_SYSTEM_HAS_SQR_LONGINT}
  445. function sqr(l:longint):longint;[internconst:in_const_sqr];
  446. begin
  447. sqr:=l*l;
  448. end;
  449. {$endif ndef FPC_SYSTEM_HAS_SQR_LONGINT}
  450. {$ifndef FPC_SYSTEM_HAS_SPTR}
  451. {$error Sptr must be defined for each processor }
  452. {$endif ndef FPC_SYSTEM_HAS_SPTR}
  453. {****************************************************************************
  454. Str()
  455. ****************************************************************************}
  456. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  457. procedure int_str(l : longint;var s : string);
  458. var
  459. sign : boolean;
  460. begin
  461. { Workaround: }
  462. if l=$80000000 then
  463. begin
  464. s:='-2147483648';
  465. exit;
  466. end;
  467. if l<0 then
  468. begin
  469. sign:=true;
  470. l:=-l;
  471. end
  472. else
  473. sign:=false;
  474. s:='';
  475. while l>0 do
  476. begin
  477. s:=char(ord('0')+(l mod 10))+s;
  478. l:=l div 10;
  479. end;
  480. if sign then
  481. s:='-'+s;
  482. end;
  483. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  484. {$ifndef FPC_SYSTEM_HAS_INT_STR_CARDINAL}
  485. procedure int_str(l : cardinal;var s : string);
  486. begin
  487. s:='';
  488. while l>0 do
  489. begin
  490. s:=char(ord('0')+(l mod 10))+s;
  491. l:=l div 10;
  492. end;
  493. if sign then
  494. s:='-'+s;
  495. end;
  496. {$endif ndef FPC_SYSTEM_HAS_INT_STR_CARDINAL}
  497. {****************************************************************************
  498. Bounds Check
  499. ****************************************************************************}
  500. {$ifndef FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
  501. procedure int_boundcheck(l : longint; range : pointer);[public,alias: 'FPC_BOUNDCHECK'];
  502. type
  503. prange = ^trange;
  504. trange = record
  505. min,max : longint;
  506. end;
  507. begin
  508. if (l < prange(range)^.min) or
  509. (l > prange(range)^.max) then
  510. HandleError(201);
  511. end;
  512. {$endif ndef FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
  513. {****************************************************************************
  514. IoCheck
  515. ****************************************************************************}
  516. {$ifndef FPC_SYSTEM_HAS_FPC_IOCHECK}
  517. procedure int_iocheck(addr : longint);[public,alias:'FPC_IOCHECK'];
  518. var
  519. l : longint;
  520. begin
  521. if InOutRes<>0 then
  522. begin
  523. l:=InOutRes;
  524. InOutRes:=0;
  525. HandleErrorFrame(l,get_frame);
  526. end;
  527. end;
  528. {$endif ndef FPC_SYSTEM_HAS_FPC_IOCHECK}
  529. {
  530. $Log$
  531. Revision 1.1 1999-05-31 21:59:58 pierre
  532. + generic.inc added
  533. }