generic.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  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 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. var
  222. slen : byte;
  223. begin
  224. if dstr=nil then
  225. exit;
  226. if sstr=nil then
  227. begin
  228. if dstr<>nil then
  229. pstring(dstr)^[0]:=#0;
  230. exit;
  231. end;
  232. slen:=length(pstring(sstr)^);
  233. if slen<len then
  234. len:=slen;
  235. move(sstr^,dstr^,len);
  236. pstring(dstr)^[0]:=chr(len);
  237. end;
  238. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COPY}
  239. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  240. procedure int_strconcat(s1,s2:pointer);[public,alias:'FPC_SHORTSTR_CONCAT'];
  241. var
  242. s1l, s2l : byte;
  243. begin
  244. if (s1=nil) or (s2=nil) then
  245. exit;
  246. s1l:=length(pstring(s1)^);
  247. s2l:=length(pstring(s2)^);
  248. if s1l+s2l>255 then
  249. s1l:=255-s2l;
  250. move(@(pstring(s1)^[1]),@(pstring(s2)^[s2l+1]),s1l);
  251. pstring(s2)^[0]:=chr(s1l+s2l);
  252. end;
  253. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  254. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  255. function int_strcmp(dstr,sstr:pointer) : longint;[public,alias:'FPC_SHORTSTR_COMPARE'];
  256. var
  257. s1,s2,max,i : byte;
  258. d : longint;
  259. begin
  260. s1:=length(pstring(dstr)^);
  261. s2:=length(pstring(sstr)^);
  262. if s1<s2 then
  263. max:=s1
  264. else
  265. max:=s2;
  266. for i:=1 to max do
  267. begin
  268. d:=byte(pstring(dstr)^[i])-byte(pstring(sstr)^[i]);
  269. if d>0 then
  270. exit(1)
  271. else if d<0 then
  272. exit(-1);
  273. end;
  274. if s1>s2 then
  275. exit(1)
  276. else if s1<s2 then
  277. exit(-1)
  278. else
  279. exit(0);
  280. end;
  281. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  282. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  283. function strpas(p:pchar):string;[public,alias:'FPC_PCHAR_TO_SHORTSTR'];
  284. var
  285. l : longint;
  286. begin
  287. if p=nil then
  288. l:=0
  289. else
  290. l:=strlen(p);
  291. if l>255 then
  292. l:=255;
  293. if l>0 then
  294. move(p^,@(strpas[1]),l);
  295. strpas[0]:=chr(l);
  296. end;
  297. {$endif ndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  298. {$ifndef FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  299. function strchararray(p:pchar; l : longint):shortstring;[public,alias:'FPC_CHARARRAY_TO_SHORTSTR'];
  300. begin
  301. if l>=256 then
  302. l:=255
  303. else if l<0 then
  304. l:=0;
  305. move(p^,@(strchararray[1]),l);
  306. strchararray[0]:=chr(l);
  307. end;
  308. {$endif ndef FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  309. {$ifndef FPC_SYSTEM_HAS_STRLEN}
  310. function strlen(p:pchar):longint;
  311. var i : longint;
  312. begin
  313. i:=0;
  314. while p[i]<>#0 do inc(i);
  315. exit(i);
  316. end;
  317. {$endif ndef FPC_SYSTEM_HAS_STRLEN}
  318. {****************************************************************************
  319. Caller/StackFrame Helpers
  320. ****************************************************************************}
  321. {$ifndef FPC_SYSTEM_HAS_GET_FRAME}
  322. {$error Get_frame must be defined for each processor }
  323. {$endif ndef FPC_SYSTEM_HAS_GET_FRAME}
  324. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  325. {$error Get_caller_addr must be defined for each processor }
  326. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  327. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  328. {$error Get_caller_frame must be defined for each processor }
  329. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  330. {****************************************************************************
  331. Math
  332. ****************************************************************************}
  333. {$ifndef FPC_SYSTEM_HAS_ABS_LONGINT}
  334. function abs(l:longint):longint;[internconst:in_const_abs];
  335. begin
  336. if l<0 then
  337. abs:=-l
  338. else
  339. abs:=l;
  340. end;
  341. {$endif ndef FPC_SYSTEM_HAS_ABS_LONGINT}
  342. {$ifndef FPC_SYSTEM_HAS_ODD_LONGINT}
  343. function odd(l:longint):boolean;[internconst:in_const_odd];
  344. begin
  345. odd:=((l and 1)<>0);
  346. end;
  347. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGINT}
  348. {$ifndef FPC_SYSTEM_HAS_SQR_LONGINT}
  349. function sqr(l:longint):longint;[internconst:in_const_sqr];
  350. begin
  351. sqr:=l*l;
  352. end;
  353. {$endif ndef FPC_SYSTEM_HAS_SQR_LONGINT}
  354. {$ifndef FPC_SYSTEM_HAS_SPTR}
  355. {$error Sptr must be defined for each processor }
  356. {$endif ndef FPC_SYSTEM_HAS_SPTR}
  357. {****************************************************************************
  358. Str()
  359. ****************************************************************************}
  360. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  361. procedure int_str(l : longint;var s : string);
  362. var
  363. sign : boolean;
  364. begin
  365. { Workaround: }
  366. if l=$80000000 then
  367. begin
  368. s:='-2147483648';
  369. exit;
  370. end;
  371. if l<0 then
  372. begin
  373. sign:=true;
  374. l:=-l;
  375. end
  376. else
  377. sign:=false;
  378. s:='';
  379. while l>0 do
  380. begin
  381. s:=char(ord('0')+(l mod 10))+s;
  382. l:=l div 10;
  383. end;
  384. if sign then
  385. s:='-'+s;
  386. end;
  387. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  388. {$ifndef FPC_SYSTEM_HAS_INT_STR_CARDINAL}
  389. procedure int_str(l : cardinal;var s : string);
  390. begin
  391. s:='';
  392. while l>0 do
  393. begin
  394. s:=char(ord('0')+(l mod 10))+s;
  395. l:=l div 10;
  396. end;
  397. if sign then
  398. s:='-'+s;
  399. end;
  400. {$endif ndef FPC_SYSTEM_HAS_INT_STR_CARDINAL}
  401. {****************************************************************************
  402. Bounds Check
  403. ****************************************************************************}
  404. {$ifndef FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
  405. procedure int_boundcheck(l : longint; range : pointer);[public,alias: 'FPC_BOUNDCHECK'];
  406. type
  407. prange = ^trange;
  408. trange = record
  409. min,max : longint;
  410. end;
  411. begin
  412. if (l < prange(range)^.min) or
  413. (l > prange(range)^.max) then
  414. HandleError(201);
  415. end;
  416. {$endif ndef FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
  417. {****************************************************************************
  418. IoCheck
  419. ****************************************************************************}
  420. {$ifndef FPC_SYSTEM_HAS_FPC_IOCHECK}
  421. procedure int_iocheck(addr : longint);[public,alias:'FPC_IOCHECK'];
  422. var
  423. l : longint;
  424. begin
  425. if InOutRes<>0 then
  426. begin
  427. l:=InOutRes;
  428. InOutRes:=0;
  429. HandleErrorFrame(l,get_frame);
  430. end;
  431. end;
  432. {$endif ndef FPC_SYSTEM_HAS_FPC_IOCHECK}
  433. {
  434. $Log$
  435. Revision 1.5 2000-01-07 16:41:34 daniel
  436. * copyright 2000
  437. Revision 1.4 2000/01/07 16:32:24 daniel
  438. * copyright 2000 added
  439. Revision 1.3 1999/12/21 11:12:16 pierre
  440. * some assembler functions translated to pascal
  441. WARNING these are not yet TESTED !!!
  442. + FPC_CHARARRAY_TO_SHORTSTRING added
  443. Revision 1.2 1999/07/05 20:04:22 peter
  444. * removed temp defines
  445. Revision 1.1 1999/05/31 21:59:58 pierre
  446. + generic.inc added
  447. }