generic.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  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. { checks for a correct vmt pointer }
  193. { deeper check to see if the current object is }
  194. { really related to the true }
  195. {$ifndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  196. procedure int_check_object_ext(vmt, expvmt : pointer);[public,alias:'FPC_CHECK_OBJECT_EXT'];
  197. type
  198. pvmt = ^tvmt;
  199. tvmt = record
  200. size,msize : longint;
  201. parent : pointer;
  202. end;
  203. begin
  204. if (vmt=nil) or
  205. (pvmt(vmt)^.size=0) or
  206. (pvmt(vmt)^.size+pvmt(vmt)^.msize<>0) then
  207. RunError(210);
  208. while assigned(vmt) do
  209. if vmt=expvmt then
  210. exit
  211. else
  212. vmt:=pvmt(vmt)^.parent;
  213. RunError(220);
  214. end;
  215. {$endif ndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  216. {****************************************************************************
  217. String
  218. ****************************************************************************}
  219. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COPY}
  220. procedure int_strcopy(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_COPY'];
  221. {
  222. this procedure must save all modified registers except EDI and ESI !!!
  223. }
  224. begin
  225. asm
  226. pushl %eax
  227. pushl %ecx
  228. cld
  229. movl 16(%ebp),%edi
  230. movl 12(%ebp),%esi
  231. xorl %eax,%eax
  232. movl 8(%ebp),%ecx
  233. lodsb
  234. cmpl %ecx,%eax
  235. jbe .LStrCopy1
  236. movl %ecx,%eax
  237. .LStrCopy1:
  238. stosb
  239. cmpl $7,%eax
  240. jl .LStrCopy2
  241. movl %edi,%ecx { Align on 32bits }
  242. negl %ecx
  243. andl $3,%ecx
  244. subl %ecx,%eax
  245. rep
  246. movsb
  247. movl %eax,%ecx
  248. andl $3,%eax
  249. shrl $2,%ecx
  250. rep
  251. movsl
  252. .LStrCopy2:
  253. movl %eax,%ecx
  254. rep
  255. movsb
  256. popl %ecx
  257. popl %eax
  258. end ['ESI','EDI'];
  259. end;
  260. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COPY}
  261. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  262. procedure int_strconcat(s1,s2:pointer);[public,alias:'FPC_SHORTSTR_CONCAT'];
  263. begin
  264. asm
  265. xorl %ecx,%ecx
  266. movl 12(%ebp),%edi
  267. movl 8(%ebp),%esi
  268. movl %edi,%ebx
  269. movb (%edi),%cl
  270. lea 1(%edi,%ecx),%edi
  271. negl %ecx
  272. xor %eax,%eax
  273. addl $0xff,%ecx
  274. lodsb
  275. cmpl %ecx,%eax
  276. jbe .LStrConcat1
  277. movl %ecx,%eax
  278. .LStrConcat1:
  279. addb %al,(%ebx)
  280. cmpl $7,%eax
  281. jl .LStrConcat2
  282. movl %edi,%ecx { Align on 32bits }
  283. negl %ecx
  284. andl $3,%ecx
  285. subl %ecx,%eax
  286. rep
  287. movsb
  288. movl %eax,%ecx
  289. andl $3,%eax
  290. shrl $2,%ecx
  291. rep
  292. movsl
  293. .LStrConcat2:
  294. movl %eax,%ecx
  295. rep
  296. movsb
  297. end ['EBX','ECX','EAX','ESI','EDI'];
  298. end;
  299. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  300. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  301. procedure int_strcmp(dstr,sstr:pointer);[public,alias:'FPC_SHORTSTR_COMPARE'];
  302. begin
  303. asm
  304. cld
  305. xorl %ebx,%ebx
  306. xorl %eax,%eax
  307. movl 12(%ebp),%esi
  308. movl 8(%ebp),%edi
  309. movb (%esi),%al
  310. movb (%edi),%bl
  311. movl %eax,%edx
  312. incl %esi
  313. incl %edi
  314. cmpl %ebx,%eax
  315. jbe .LStrCmp1
  316. movl %ebx,%eax
  317. .LStrCmp1:
  318. cmpl $7,%eax
  319. jl .LStrCmp2
  320. movl %edi,%ecx { Align on 32bits }
  321. negl %ecx
  322. andl $3,%ecx
  323. subl %ecx,%eax
  324. orl %ecx,%ecx
  325. rep
  326. cmpsb
  327. jne .LStrCmp3
  328. movl %eax,%ecx
  329. andl $3,%eax
  330. shrl $2,%ecx
  331. orl %ecx,%ecx
  332. rep
  333. cmpsl
  334. je .LStrCmp2
  335. movl $4,%eax
  336. sub %eax,%esi
  337. sub %eax,%edi
  338. .LStrCmp2:
  339. movl %eax,%ecx
  340. orl %eax,%eax
  341. rep
  342. cmpsb
  343. jne .LStrCmp3
  344. cmp %ebx,%edx
  345. .LStrCmp3:
  346. end ['EDX','ECX','EBX','EAX','ESI','EDI'];
  347. end;
  348. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  349. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  350. function strpas(p:pchar):string;[public,alias:'FPC_PCHAR_TO_SHORTSTR'];
  351. begin
  352. asm
  353. cld
  354. movl p,%edi
  355. movl $0xff,%ecx
  356. orl %edi,%edi
  357. jnz .LStrPasNotNil
  358. decl %ecx
  359. jmp .LStrPasNil
  360. .LStrPasNotNil:
  361. xorl %eax,%eax
  362. movl %edi,%esi
  363. repne
  364. scasb
  365. .LStrPasNil:
  366. movl %ecx,%eax
  367. movl __RESULT,%edi
  368. notb %al
  369. decl %eax
  370. stosb
  371. cmpl $7,%eax
  372. jl .LStrPas2
  373. movl %edi,%ecx { Align on 32bits }
  374. negl %ecx
  375. andl $3,%ecx
  376. subl %ecx,%eax
  377. rep
  378. movsb
  379. movl %eax,%ecx
  380. andl $3,%eax
  381. shrl $2,%ecx
  382. rep
  383. movsl
  384. .LStrPas2:
  385. movl %eax,%ecx
  386. rep
  387. movsb
  388. end ['ECX','EAX','ESI','EDI'];
  389. end;
  390. {$endif ndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  391. {$ifndef FPC_SYSTEM_HAS_STRLEN}
  392. function strlen(p:pchar):longint;assembler;
  393. asm
  394. movl p,%edi
  395. movl $0xffffffff,%ecx
  396. xorl %eax,%eax
  397. cld
  398. repne
  399. scasb
  400. movl $0xfffffffe,%eax
  401. subl %ecx,%eax
  402. end ['EDI','ECX','EAX'];
  403. {$endif ndef FPC_SYSTEM_HAS_STRLEN}
  404. {****************************************************************************
  405. Caller/StackFrame Helpers
  406. ****************************************************************************}
  407. {$ifndef FPC_SYSTEM_HAS_GET_FRAME}
  408. {$error Get_frame must be defined for each processor }
  409. {$endif ndef FPC_SYSTEM_HAS_GET_FRAME}
  410. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  411. {$error Get_caller_addr must be defined for each processor }
  412. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  413. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  414. {$error Get_caller_frame must be defined for each processor }
  415. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  416. {****************************************************************************
  417. Math
  418. ****************************************************************************}
  419. {$ifndef FPC_SYSTEM_HAS_ABS_LONGINT}
  420. function abs(l:longint):longint;[internconst:in_const_abs];
  421. begin
  422. if l<0 then
  423. abs:=-l
  424. else
  425. abs:=l;
  426. end;
  427. {$endif ndef FPC_SYSTEM_HAS_ABS_LONGINT}
  428. {$ifndef FPC_SYSTEM_HAS_ODD_LONGINT}
  429. function odd(l:longint):boolean;[internconst:in_const_odd];
  430. begin
  431. odd:=((l and 1)<>0);
  432. end;
  433. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGINT}
  434. {$ifndef FPC_SYSTEM_HAS_SQR_LONGINT}
  435. function sqr(l:longint):longint;[internconst:in_const_sqr];
  436. begin
  437. sqr:=l*l;
  438. end;
  439. {$endif ndef FPC_SYSTEM_HAS_SQR_LONGINT}
  440. {$ifndef FPC_SYSTEM_HAS_SPTR}
  441. {$error Sptr must be defined for each processor }
  442. {$endif ndef FPC_SYSTEM_HAS_SPTR}
  443. {****************************************************************************
  444. Str()
  445. ****************************************************************************}
  446. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  447. procedure int_str(l : longint;var s : string);
  448. var
  449. sign : boolean;
  450. begin
  451. { Workaround: }
  452. if l=$80000000 then
  453. begin
  454. s:='-2147483648';
  455. exit;
  456. end;
  457. if l<0 then
  458. begin
  459. sign:=true;
  460. l:=-l;
  461. end
  462. else
  463. sign:=false;
  464. s:='';
  465. while l>0 do
  466. begin
  467. s:=char(ord('0')+(l mod 10))+s;
  468. l:=l div 10;
  469. end;
  470. if sign then
  471. s:='-'+s;
  472. end;
  473. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  474. {$ifndef FPC_SYSTEM_HAS_INT_STR_CARDINAL}
  475. procedure int_str(l : cardinal;var s : string);
  476. begin
  477. s:='';
  478. while l>0 do
  479. begin
  480. s:=char(ord('0')+(l mod 10))+s;
  481. l:=l div 10;
  482. end;
  483. if sign then
  484. s:='-'+s;
  485. end;
  486. {$endif ndef FPC_SYSTEM_HAS_INT_STR_CARDINAL}
  487. {****************************************************************************
  488. Bounds Check
  489. ****************************************************************************}
  490. {$ifndef FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
  491. procedure int_boundcheck(l : longint; range : pointer);[public,alias: 'FPC_BOUNDCHECK'];
  492. type
  493. prange = ^trange;
  494. trange = record
  495. min,max : longint;
  496. end;
  497. begin
  498. if (l < prange(range)^.min) or
  499. (l > prange(range)^.max) then
  500. HandleError(201);
  501. end;
  502. {$endif ndef FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
  503. {****************************************************************************
  504. IoCheck
  505. ****************************************************************************}
  506. {$ifndef FPC_SYSTEM_HAS_FPC_IOCHECK}
  507. procedure int_iocheck(addr : longint);[public,alias:'FPC_IOCHECK'];
  508. var
  509. l : longint;
  510. begin
  511. if InOutRes<>0 then
  512. begin
  513. l:=InOutRes;
  514. InOutRes:=0;
  515. HandleErrorFrame(l,get_frame);
  516. end;
  517. end;
  518. {$endif ndef FPC_SYSTEM_HAS_FPC_IOCHECK}
  519. {
  520. $Log$
  521. Revision 1.2 1999-07-05 20:04:22 peter
  522. * removed temp defines
  523. Revision 1.1 1999/05/31 21:59:58 pierre
  524. + generic.inc added
  525. }