generic.inc 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team.
  4. Processor independent implementation for the system unit
  5. (adapted for intel i386.inc file)
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {****************************************************************************
  13. Primitives
  14. ****************************************************************************}
  15. type
  16. pstring = ^shortstring;
  17. {$ifndef FPC_SYSTEM_HAS_MOVE}
  18. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE'];
  19. var
  20. aligncount : sizeint;
  21. pdest,psrc,pend : pbyte;
  22. begin
  23. if (@dest=@source) or (count<=0) then
  24. exit;
  25. if (@dest<@source) or (@source+count<@dest) then
  26. begin
  27. { Forward Move }
  28. psrc:=@source;
  29. pdest:=@dest;
  30. if Count>4*sizeof(ptruint)-1 then
  31. begin
  32. { Align on native pointer size }
  33. aligncount:=(PtrUInt(pdest) and (sizeof(PtrUInt)-1));
  34. dec(count,aligncount);
  35. pend:=psrc+aligncount;
  36. while psrc<pend do
  37. begin
  38. pdest^:=psrc^;
  39. inc(pdest);
  40. inc(psrc);
  41. end;
  42. { use sizeuint typecast to force shr optimization }
  43. pptruint(pend):=pptruint(psrc)+(sizeuint(count) div sizeof(ptruint));
  44. while psrc<pend do
  45. begin
  46. pptruint(pdest)^:=pptruint(psrc)^;
  47. inc(pptruint(pdest));
  48. inc(pptruint(psrc));
  49. end;
  50. count:=count and (sizeof(PtrUInt)-1);
  51. end;
  52. pend:=psrc+count;
  53. while psrc<pend do
  54. begin
  55. pdest^:=psrc^;
  56. inc(pdest);
  57. inc(psrc);
  58. end;
  59. end
  60. else
  61. begin
  62. { Backward Move }
  63. psrc:=@source+count;
  64. pdest:=@dest+count;
  65. if Count>4*sizeof(ptruint)-1 then
  66. begin
  67. { Align on native pointer size }
  68. aligncount:=(PtrUInt(pdest) and (sizeof(PtrUInt)-1));
  69. dec(count,aligncount);
  70. pend:=psrc-aligncount;
  71. while psrc>pend do
  72. begin
  73. dec(pdest);
  74. dec(psrc);
  75. pdest^:=psrc^;
  76. end;
  77. { use sizeuint typecast to force shr optimization }
  78. pptruint(pend):=pptruint(psrc)-(sizeuint(count) div sizeof(ptruint));
  79. while psrc>pend do
  80. begin
  81. dec(pptruint(pdest));
  82. dec(pptruint(psrc));
  83. pptruint(pdest)^:=pptruint(psrc)^;
  84. end;
  85. count:=count and (sizeof(PtrUInt)-1);
  86. end;
  87. pend:=psrc-count;
  88. while psrc>pend do
  89. begin
  90. dec(pdest);
  91. dec(psrc);
  92. pdest^:=psrc^;
  93. end;
  94. end;
  95. end;
  96. {$endif not FPC_SYSTEM_HAS_MOVE}
  97. {$ifndef FPC_SYSTEM_HAS_FILLCHAR}
  98. Procedure FillChar(var x;count:SizeInt;value:byte);
  99. var
  100. aligncount : sizeint;
  101. pdest,pend : pbyte;
  102. v : ptruint;
  103. begin
  104. if count <= 0 then
  105. exit;
  106. pdest:=@x;
  107. if Count>4*sizeof(ptruint)-1 then
  108. begin
  109. v:=(value shl 8) or value;
  110. v:=(v shl 16) or v;
  111. if sizeof(ptruint)=8 then
  112. v:=(v shl 32) or v;
  113. { Align on native pointer size }
  114. aligncount:=(PtrUInt(pdest) and (sizeof(PtrUInt)-1));
  115. dec(count,aligncount);
  116. pend:=pdest+aligncount;
  117. while pdest<pend do
  118. begin
  119. pdest^:=value;
  120. inc(pdest);
  121. end;
  122. { use sizeuint typecast to force shr optimization }
  123. pptruint(pend):=pptruint(pdest)+(sizeuint(count) div sizeof(ptruint));
  124. while pdest<pend do
  125. begin
  126. pptruint(pdest)^:=v;
  127. inc(pptruint(pdest));
  128. end;
  129. count:=count and (sizeof(ptruint)-1);
  130. end;
  131. pend:=pdest+count;
  132. while pdest<pend do
  133. begin
  134. pdest^:=value;
  135. inc(pdest);
  136. end;
  137. end;
  138. {$endif FPC_SYSTEM_HAS_FILLCHAR}
  139. {$ifndef FPC_SYSTEM_HAS_FILLWORD}
  140. procedure fillword(var x;count : SizeInt;value : word);
  141. var
  142. aligncount : sizeint;
  143. pdest,pend : pword;
  144. v : ptruint;
  145. begin
  146. if count <= 0 then
  147. exit;
  148. pdest:=@x;
  149. if Count>4*sizeof(ptruint)-1 then
  150. begin
  151. v:=(value shl 16) or value;
  152. if sizeof(ptruint)=8 then
  153. v:=(v shl 32) or v;
  154. { Align on native pointer size }
  155. aligncount:=(PtrUInt(pdest) and (sizeof(PtrUInt)-1)) shr 1;
  156. dec(count,aligncount);
  157. pend:=pdest+aligncount;
  158. while pdest<pend do
  159. begin
  160. pdest^:=value;
  161. inc(pdest);
  162. end;
  163. { use sizeuint typecast to force shr optimization }
  164. pptruint(pend):=pptruint(pdest)+((sizeuint(count)*2) div sizeof(ptruint));
  165. while pdest<pend do
  166. begin
  167. pptruint(pdest)^:=v;
  168. inc(pptruint(pdest));
  169. end;
  170. count:=((count*2) and (sizeof(ptruint)-1)) shr 1;
  171. end;
  172. pend:=pdest+count;
  173. while pdest<pend do
  174. begin
  175. pdest^:=value;
  176. inc(pdest);
  177. end;
  178. end;
  179. {$endif not FPC_SYSTEM_HAS_FILLWORD}
  180. {$ifndef FPC_SYSTEM_HAS_FILLDWORD}
  181. procedure filldword(var x;count : SizeInt;value : dword);
  182. var
  183. aligncount : sizeint;
  184. pdest,pend : pdword;
  185. v : ptruint;
  186. begin
  187. if count <= 0 then
  188. exit;
  189. pdest:=@x;
  190. if Count>4*sizeof(ptruint)-1 then
  191. begin
  192. v:=value;
  193. if sizeof(ptruint)=8 then
  194. v:=(v shl 32) or v;
  195. { Align on native pointer size }
  196. aligncount:=(PtrUInt(pdest) and (sizeof(PtrUInt)-1)) shr 2;
  197. dec(count,aligncount);
  198. pend:=pdest+aligncount;
  199. while pdest<pend do
  200. begin
  201. pdest^:=value;
  202. inc(pdest);
  203. end;
  204. { use sizeuint typecast to force shr optimization }
  205. pptruint(pend):=pptruint(pdest)+((sizeuint(count)*4) div sizeof(ptruint));
  206. while pdest<pend do
  207. begin
  208. pptruint(pdest)^:=v;
  209. inc(pptruint(pdest));
  210. end;
  211. count:=((count*4) and (sizeof(ptruint)-1)) shr 2;
  212. end;
  213. pend:=pdest+count;
  214. while pdest<pend do
  215. begin
  216. pdest^:=value;
  217. inc(pdest);
  218. end;
  219. end;
  220. {$endif FPC_SYSTEM_HAS_FILLDWORD}
  221. {$ifndef FPC_SYSTEM_HAS_INDEXBYTE}
  222. function IndexByte(Const buf;len:SizeInt;b:byte):SizeInt;
  223. var
  224. psrc,pend : pbyte;
  225. begin
  226. psrc:=@buf;
  227. { simulate assembler implementations behaviour, which is expected }
  228. { fpc_pchar_to_ansistr in astrings.inc }
  229. if (len < 0) or
  230. (psrc+len < psrc) then
  231. pend:=pbyte(high(PtrUInt)-sizeof(byte))
  232. else
  233. pend:=psrc+len;
  234. while (psrc<pend) do
  235. begin
  236. if psrc^=b then
  237. begin
  238. result:=psrc-pbyte(@buf);
  239. exit;
  240. end;
  241. inc(psrc);
  242. end;
  243. result:=-1;
  244. end;
  245. {$endif not FPC_SYSTEM_HAS_INDEXBYTE}
  246. {$ifndef FPC_SYSTEM_HAS_INDEXWORD}
  247. function Indexword(Const buf;len:SizeInt;b:word):SizeInt;
  248. var
  249. psrc,pend : pword;
  250. begin
  251. psrc:=@buf;
  252. { simulate assembler implementations behaviour, which is expected }
  253. { fpc_pchar_to_ansistr in astrings.inc }
  254. if (len < 0) or
  255. { is this ever true? }
  256. (len > high(PtrInt)) or
  257. (psrc+len < psrc) then
  258. pend:=pword(high(PtrUInt)-sizeof(word))
  259. else
  260. pend:=psrc+len;
  261. while psrc<pend do
  262. begin
  263. if psrc^=b then
  264. begin
  265. result:=psrc-pword(@buf);
  266. exit;
  267. end;
  268. inc(psrc);
  269. end;
  270. result:=-1;
  271. end;
  272. {$endif not FPC_SYSTEM_HAS_INDEXWORD}
  273. {$ifndef FPC_SYSTEM_HAS_INDEXDWORD}
  274. function IndexDWord(Const buf;len:SizeInt;b:DWord):SizeInt;
  275. var
  276. psrc,pend : pdword;
  277. begin
  278. psrc:=@buf;
  279. { simulate assembler implementations behaviour, which is expected }
  280. { fpc_pchar_to_ansistr in astrings.inc }
  281. if (len < 0) or
  282. (len > high(PtrInt) div 2) or
  283. (psrc+len < psrc) then
  284. pend:=pdword(high(PtrUInt)-sizeof(dword))
  285. else
  286. pend:=psrc+len;
  287. while psrc<pend do
  288. begin
  289. if psrc^=b then
  290. begin
  291. result:=psrc-pdword(@buf);
  292. exit;
  293. end;
  294. inc(psrc);
  295. end;
  296. result:=-1;
  297. end;
  298. {$endif not FPC_SYSTEM_HAS_INDEXDWORD}
  299. {$ifndef FPC_SYSTEM_HAS_COMPAREBYTE}
  300. function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt;
  301. var
  302. aligncount : sizeint;
  303. psrc,pdest,pend : pbyte;
  304. b : ptrint;
  305. begin
  306. b:=0;
  307. psrc:=@buf1;
  308. pdest:=@buf2;
  309. if len>4*sizeof(ptruint)-1 then
  310. begin
  311. { Align on native pointer size }
  312. aligncount:=(PtrUInt(pdest) and (sizeof(PtrUInt)-1));
  313. dec(len,aligncount);
  314. pend:=psrc+aligncount;
  315. while psrc<pend do
  316. begin
  317. b:=(ptrint(psrc^)-ptrint(pdest^));
  318. if b<>0 then
  319. begin
  320. if b<0 then
  321. exit(-1)
  322. else
  323. exit(1);
  324. end;
  325. inc(pdest);
  326. inc(psrc);
  327. end;
  328. { use sizeuint typecast to force shr optimization }
  329. pptruint(pend):=pptruint(psrc)+(sizeuint(len) div sizeof(ptruint));
  330. len:=len and (sizeof(PtrUInt)-1);
  331. while psrc<pend do
  332. begin
  333. b:=(pptrint(psrc)^-pptrint(pdest)^);
  334. if b<>0 then
  335. begin
  336. len:=sizeof(ptruint);
  337. break;
  338. end;
  339. inc(pptruint(pdest));
  340. inc(pptruint(psrc));
  341. end;
  342. end;
  343. if (psrc+len >= psrc) then
  344. pend:=psrc+len
  345. else
  346. pend:=pbyte(high(ptruint)-1);
  347. while psrc<pend do
  348. begin
  349. b:=(ptrint(psrc^)-ptrint(pdest^));
  350. if b<>0 then
  351. begin
  352. if b<0 then
  353. exit(-1)
  354. else
  355. exit(1);
  356. end;
  357. inc(pdest);
  358. inc(psrc);
  359. end;
  360. result:=0;
  361. end;
  362. {$endif not FPC_SYSTEM_HAS_COMPAREBYTE}
  363. {$ifndef FPC_SYSTEM_HAS_COMPAREWORD}
  364. function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt;
  365. var
  366. aligncount : sizeint;
  367. psrc,pdest,pend : pword;
  368. b : ptrint;
  369. begin
  370. b:=0;
  371. psrc:=@buf1;
  372. pdest:=@buf2;
  373. if len>4*sizeof(ptruint)-1 then
  374. begin
  375. { Align on native pointer size }
  376. aligncount:=(PtrUInt(pdest) and (sizeof(PtrUInt)-1)) shr 1;
  377. dec(len,aligncount);
  378. pend:=psrc+aligncount;
  379. while psrc<pend do
  380. begin
  381. b:=(ptrint(psrc^)-ptrint(pdest^));
  382. if b<>0 then
  383. begin
  384. if b<0 then
  385. exit(-1)
  386. else
  387. exit(1);
  388. end;
  389. inc(pdest);
  390. inc(psrc);
  391. end;
  392. { use sizeuint typecast to force shr optimization }
  393. pptruint(pend):=pptruint(psrc)+(sizeuint(len)*2 div sizeof(ptruint));
  394. len:=((len*2) and (sizeof(PtrUInt)-1)) shr 1;
  395. while psrc<pend do
  396. begin
  397. b:=(pptrint(psrc)^-pptrint(pdest)^);
  398. if b<>0 then
  399. begin
  400. len:=sizeof(ptruint) shr 1;
  401. break;
  402. end;
  403. inc(pptruint(pdest));
  404. inc(pptruint(psrc));
  405. end;
  406. end;
  407. if (len <= high(ptruint) div 2) and
  408. (psrc+len >= psrc) then
  409. pend:=psrc+len
  410. else
  411. pend:=pword(high(ptruint)-2);
  412. while psrc<pend do
  413. begin
  414. b:=(ptrint(psrc^)-ptrint(pdest^));
  415. if b<>0 then
  416. begin
  417. if b<0 then
  418. exit(-1)
  419. else
  420. exit(1);
  421. end;
  422. inc(pdest);
  423. inc(psrc);
  424. end;
  425. result:=0;
  426. end;
  427. {$endif not FPC_SYSTEM_HAS_COMPAREWORD}
  428. {$ifndef FPC_SYSTEM_HAS_COMPAREDWORD}
  429. function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt;
  430. var
  431. aligncount : sizeint;
  432. psrc,pdest,pend : pdword;
  433. b : ptrint;
  434. begin
  435. b:=0;
  436. psrc:=@buf1;
  437. pdest:=@buf2;
  438. if len>4*sizeof(ptruint)-1 then
  439. begin
  440. { Align on native pointer size }
  441. aligncount:=(PtrUInt(pdest) and (sizeof(PtrUInt)-1)) shr 2;
  442. dec(len,aligncount);
  443. pend:=psrc+aligncount;
  444. while psrc<pend do
  445. begin
  446. b:=(ptrint(psrc^)-ptrint(pdest^));
  447. if b<>0 then
  448. begin
  449. if b<0 then
  450. exit(-1)
  451. else
  452. exit(1);
  453. end;
  454. inc(pdest);
  455. inc(psrc);
  456. end;
  457. { use sizeuint typecast to force shr optimization }
  458. pptruint(pend):=pptruint(psrc)+(sizeuint(len)*4 div sizeof(ptruint));
  459. len:=((len*4) and (sizeof(PtrUInt)-1)) shr 2;
  460. while psrc<pend do
  461. begin
  462. b:=(pptrint(psrc)^-pptrint(pdest)^);
  463. if b<>0 then
  464. begin
  465. len:=sizeof(ptruint) shr 2;
  466. break;
  467. end;
  468. inc(pptruint(pdest));
  469. inc(pptruint(psrc));
  470. end;
  471. end;
  472. if (len <= high(ptruint) div 4) and
  473. (psrc+len >= psrc) then
  474. pend:=psrc+len
  475. else
  476. pend:=pdword(high(ptruint)-4);
  477. while psrc<pend do
  478. begin
  479. b:=(ptrint(psrc^)-ptrint(pdest^));
  480. if b<>0 then
  481. begin
  482. if b<0 then
  483. exit(-1)
  484. else
  485. exit(1);
  486. end;
  487. inc(pdest);
  488. inc(psrc);
  489. end;
  490. result:=0;
  491. end;
  492. {$endif ndef FPC_SYSTEM_HAS_COMPAREDWORD}
  493. {$ifndef FPC_SYSTEM_HAS_MOVECHAR0}
  494. procedure MoveChar0(Const buf1;var buf2;len:SizeInt);
  495. var
  496. I : SizeInt;
  497. begin
  498. if Len = 0 then
  499. exit;
  500. I:=IndexByte(Buf1,Len,0);
  501. if I<>-1 then
  502. Move(Buf1,Buf2,I)
  503. else
  504. Move(Buf1,Buf2,len);
  505. end;
  506. {$endif ndef FPC_SYSTEM_HAS_MOVECHAR0}
  507. {$ifndef FPC_SYSTEM_HAS_INDEXCHAR0}
  508. function IndexChar0(Const buf;len:SizeInt;b:Char):SizeInt;
  509. var
  510. psrc,pend : pbyte;
  511. begin
  512. psrc:=@buf;
  513. { simulate assembler implementations behaviour, which is expected }
  514. { fpc_pchar_to_ansistr in astrings.inc }
  515. if (len < 0) then
  516. pend:=pbyte(high(PtrUInt)-sizeof(byte))
  517. else
  518. pend:=psrc+len;
  519. while (psrc<pend) and (psrc^<>0) do
  520. begin
  521. if (psrc^=byte(b)) then
  522. begin
  523. result:=psrc-pbyte(@buf);
  524. exit;
  525. end;
  526. inc(psrc);
  527. end;
  528. result:=-1;
  529. end;
  530. {$endif ndef FPC_SYSTEM_HAS_INDEXCHAR0}
  531. {$ifndef FPC_SYSTEM_HAS_COMPARECHAR0}
  532. function CompareChar0(Const buf1,buf2;len:SizeInt):SizeInt;
  533. var
  534. aligncount : sizeint;
  535. psrc,pdest,pend : pbyte;
  536. b : ptrint;
  537. begin
  538. b:=0;
  539. psrc:=@buf1;
  540. pdest:=@buf2;
  541. pend:=psrc+len;
  542. while psrc<pend do
  543. begin
  544. b:=(ptrint(psrc^)-ptrint(pdest^));
  545. if (b<>0) or (psrc^=0) or (pdest^=0) then
  546. begin
  547. if b<0 then
  548. exit(-1)
  549. else
  550. exit(1);
  551. end;
  552. inc(pdest);
  553. inc(psrc);
  554. end;
  555. result:=0;
  556. end;
  557. {$endif not FPC_SYSTEM_HAS_COMPARECHAR0}
  558. {****************************************************************************
  559. Object Helpers
  560. ****************************************************************************}
  561. {$ifdef FPC_HAS_FEATURE_OBJECTS}
  562. {$ifndef FPC_SYSTEM_HAS_FPC_HELP_CONSTRUCTOR}
  563. { Note: _vmt will be reset to -1 when memory is allocated,
  564. this is needed for fpc_help_fail }
  565. function fpc_help_constructor(_self:pointer;var _vmt:pointer;_vmt_pos:cardinal):pointer;[public,alias:'FPC_HELP_CONSTRUCTOR'];compilerproc;
  566. type
  567. ppointer = ^pointer;
  568. pvmt = ^tvmt;
  569. tvmt=packed record
  570. size,msize:ptruint;
  571. parent:pointer;
  572. end;
  573. var
  574. vmtcopy : pointer;
  575. begin
  576. { Inherited call? }
  577. if _vmt=nil then
  578. begin
  579. fpc_help_constructor:=_self;
  580. exit;
  581. end;
  582. vmtcopy:=_vmt;
  583. if (_self=nil) and
  584. (pvmt(_vmt)^.size>0) then
  585. begin
  586. getmem(_self,pvmt(_vmt)^.size);
  587. { reset vmt needed for fail }
  588. _vmt:=pointer(-1);
  589. end;
  590. if _self<>nil then
  591. begin
  592. fillchar(_self^,pvmt(vmtcopy)^.size,#0);
  593. ppointer(_self+_vmt_pos)^:=vmtcopy;
  594. end;
  595. fpc_help_constructor:=_self;
  596. end;
  597. {$endif FPC_SYSTEM_HAS_FPC_HELP_CONSTRUCTOR}
  598. {$ifndef FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  599. { Note: _self will not be reset, the compiler has to generate the reset }
  600. procedure fpc_help_destructor(_self,_vmt:pointer;vmt_pos:cardinal);[public,alias:'FPC_HELP_DESTRUCTOR']; compilerproc;
  601. type
  602. ppointer = ^pointer;
  603. pvmt = ^tvmt;
  604. tvmt = packed record
  605. size,msize : ptruint;
  606. parent : pointer;
  607. end;
  608. begin
  609. { already released? }
  610. if (_self=nil) or
  611. (_vmt=nil) or
  612. (ppointer(_self+vmt_pos)^=nil) then
  613. exit;
  614. if (pvmt(ppointer(_self+vmt_pos)^)^.size=0) or
  615. (pvmt(ppointer(_self+vmt_pos)^)^.size+pvmt(ppointer(_self+vmt_pos)^)^.msize<>0) then
  616. RunError(210);
  617. { reset vmt to nil for protection }
  618. ppointer(_self+vmt_pos)^:=nil;
  619. freemem(_self);
  620. end;
  621. {$endif FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  622. {$ifndef FPC_SYSTEM_HAS_FPC_HELP_FAIL}
  623. { Note: _self will not be reset, the compiler has to generate the reset }
  624. procedure fpc_help_fail(_self:pointer;var _vmt:pointer;vmt_pos:cardinal);[public,alias:'FPC_HELP_FAIL'];compilerproc;
  625. begin
  626. if (_self=nil) or (_vmt=nil) then
  627. exit;
  628. { vmt=$ffffffff when memory was allocated }
  629. if ptruint(_vmt)=high(ptruint) then
  630. begin
  631. if (_self=nil) or (ppointer(_self+vmt_pos)^=nil) then
  632. HandleError(210)
  633. else
  634. begin
  635. ppointer(_self+vmt_pos)^:=nil;
  636. freemem(_self);
  637. { reset _vmt to nil so it will not be freed a
  638. second time }
  639. _vmt:=nil;
  640. end;
  641. end
  642. else
  643. ppointer(_self+vmt_pos)^:=nil;
  644. end;
  645. {$endif FPC_SYSTEM_HAS_FPC_HELP_FAIL}
  646. {$ifndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  647. procedure fpc_check_object(_vmt : pointer); [public,alias:'FPC_CHECK_OBJECT']; compilerproc;
  648. type
  649. pvmt = ^tvmt;
  650. tvmt = packed record
  651. size,msize : ptruint;
  652. parent : pointer;
  653. end;
  654. begin
  655. if (_vmt=nil) or
  656. (pvmt(_vmt)^.size=0) or
  657. (pvmt(_vmt)^.size+pvmt(_vmt)^.msize<>0) then
  658. RunError(210);
  659. end;
  660. {$endif ndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  661. {$ifndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  662. { checks for a correct vmt pointer }
  663. { deeper check to see if the current object is }
  664. { really related to the true }
  665. procedure fpc_check_object_ext(vmt, expvmt : pointer); [public,alias:'FPC_CHECK_OBJECT_EXT']; compilerproc;
  666. type
  667. pvmt = ^tvmt;
  668. tvmt = packed record
  669. size,msize : ptruint;
  670. parent : pointer;
  671. end;
  672. begin
  673. if (vmt=nil) or
  674. (pvmt(vmt)^.size=0) or
  675. (pvmt(vmt)^.size+pvmt(vmt)^.msize<>0) then
  676. RunError(210);
  677. while assigned(vmt) do
  678. if vmt=expvmt then
  679. exit
  680. else
  681. vmt:=pvmt(vmt)^.parent;
  682. RunError(219);
  683. end;
  684. {$endif not FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  685. {$endif FPC_HAS_FEATURE_OBJECTS}
  686. {****************************************************************************
  687. String
  688. ****************************************************************************}
  689. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  690. function fpc_shortstr_to_shortstr(len:longint;const sstr:shortstring): shortstring;[public,alias:'FPC_SHORTSTR_TO_SHORTSTR']; compilerproc;
  691. var
  692. slen : byte;
  693. begin
  694. slen:=length(sstr);
  695. if slen<len then
  696. len:=slen;
  697. move(sstr[0],result[0],len+1);
  698. if slen>len then
  699. result[0]:=chr(len);
  700. end;
  701. procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN']; {$ifdef HAS_COMPILER_PROC} compilerproc; {$endif}
  702. var
  703. slen : byte;
  704. type
  705. pstring = ^string;
  706. begin
  707. slen:=length(pstring(sstr)^);
  708. if slen<len then
  709. len:=slen;
  710. move(sstr^,dstr^,len+1);
  711. if slen>len then
  712. pchar(dstr)^:=chr(len);
  713. end;
  714. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  715. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  716. {$ifndef STR_CONCAT_PROCS}
  717. function fpc_shortstr_concat(const s1,s2:shortstring): shortstring;[public,alias:'FPC_SHORTSTR_CONCAT']; compilerproc;
  718. var
  719. s1l, s2l : byte;
  720. begin
  721. s1l:=length(s1);
  722. s2l:=length(s2);
  723. if s1l+s2l>255 then
  724. s2l:=255-s1l;
  725. move(s1[1],fpc_shortstr_concat[1],s1l);
  726. move(s2[1],fpc_shortstr_concat[s1l+1],s2l);
  727. fpc_shortstr_concat[0]:=chr(s1l+s2l);
  728. end;
  729. {$else STR_CONCAT_PROCS}
  730. procedure fpc_shortstr_concat(var dests:shortstring;const s1,s2:shortstring);compilerproc;
  731. var
  732. s1l, s2l : longint;
  733. begin
  734. s1l:=length(s1);
  735. s2l:=length(s2);
  736. if s1l+s2l>high(dests) then
  737. s2l:=high(dests)-s1l;
  738. if @dests=@s1 then
  739. move(s2[1],dests[s1l+1],s2l)
  740. else
  741. if @dests=@s2 then
  742. begin
  743. move(dests[1],dests[s1l+1],s2l);
  744. move(s1[1],dests[1],s1l);
  745. end
  746. else
  747. begin
  748. move(s1[1],dests[1],s1l);
  749. move(s2[1],dests[s1l+1],s2l);
  750. end;
  751. dests[0]:=chr(s1l+s2l);
  752. end;
  753. procedure fpc_shortstr_concat_multi(var dests:shortstring;const sarr:array of pshortstring);compilerproc;
  754. var
  755. s2l : byte;
  756. LowStart,i,
  757. Len : longint;
  758. pc : pchar;
  759. needtemp : boolean;
  760. tmpstr : shortstring;
  761. p,pdest : pshortstring;
  762. begin
  763. if high(sarr)=0 then
  764. begin
  765. DestS:='';
  766. exit;
  767. end;
  768. lowstart:=low(sarr);
  769. if Pointer(@DestS)=Pointer(sarr[lowstart]) then
  770. inc(lowstart);
  771. { Check for another reuse, then we can't use
  772. the append optimization and need to use a temp }
  773. needtemp:=false;
  774. for i:=lowstart to high(sarr) do
  775. begin
  776. if Pointer(@DestS)=Pointer(sarr[i]) then
  777. begin
  778. needtemp:=true;
  779. break;
  780. end;
  781. end;
  782. if needtemp then
  783. begin
  784. lowstart:=low(sarr);
  785. tmpstr:='';
  786. pdest:=@tmpstr
  787. end
  788. else
  789. begin
  790. { Start with empty DestS if we start with concatting
  791. the first array element }
  792. if lowstart=low(sarr) then
  793. DestS:='';
  794. pdest:=@DestS;
  795. end;
  796. { Concat all strings, except the string we already
  797. copied in DestS }
  798. Len:=length(pdest^);
  799. pc:=@pdest^[1+Length(pdest^)];
  800. for i:=lowstart to high(sarr) do
  801. begin
  802. p:=sarr[i];
  803. if assigned(p) then
  804. begin
  805. s2l:=length(p^);
  806. if Len+s2l>high(dests) then
  807. s2l:=high(dests)-Len;
  808. Move(p^[1],pc^,s2l);
  809. inc(pc,s2l);
  810. inc(Len,s2l);
  811. end;
  812. end;
  813. pdest^[0]:=Chr(Len);
  814. if needtemp then
  815. DestS:=TmpStr;
  816. end;
  817. {$endif STR_CONCAT_PROCS}
  818. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  819. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  820. procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring);compilerproc;
  821. [public,alias:'FPC_SHORTSTR_APPEND_SHORTSTR'];
  822. var
  823. s1l, s2l : integer;
  824. begin
  825. s1l:=length(s1);
  826. s2l:=length(s2);
  827. if s1l+s2l>high(s1) then
  828. s2l:=high(s1)-s1l;
  829. move(s2[1],s1[s1l+1],s2l);
  830. s1[0]:=chr(s1l+s2l);
  831. end;
  832. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  833. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  834. function fpc_shortstr_compare(const left,right:shortstring) : longint;[public,alias:'FPC_SHORTSTR_COMPARE']; compilerproc;
  835. var
  836. s1,s2,max,i : byte;
  837. d : longint;
  838. begin
  839. s1:=length(left);
  840. s2:=length(right);
  841. if s1<s2 then
  842. max:=s1
  843. else
  844. max:=s2;
  845. for i:=1 to max do
  846. begin
  847. d:=byte(left[i])-byte(right[i]);
  848. if d>0 then
  849. exit(1)
  850. else if d<0 then
  851. exit(-1);
  852. end;
  853. if s1>s2 then
  854. exit(1)
  855. else if s1<s2 then
  856. exit(-1)
  857. else
  858. exit(0);
  859. end;
  860. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  861. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE_EQUAL}
  862. function fpc_shortstr_compare_equal(const left,right:shortstring): longint; [public,alias:'FPC_SHORTSTR_COMPARE_EQUAL']; compilerproc;
  863. begin
  864. Result := longint(left[0]) - longint(right[0]);
  865. if Result = 0 then
  866. Result := CompareByte(left[1],right[1], longint(left[0]));
  867. end;
  868. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE_EQUAL}
  869. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  870. function fpc_pchar_to_shortstr(p:pchar):shortstring;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; compilerproc;
  871. var
  872. l : longint;
  873. s: shortstring;
  874. begin
  875. if p=nil then
  876. l:=0
  877. else
  878. l:=strlen(p);
  879. if l>255 then
  880. l:=255;
  881. if l>0 then
  882. move(p^,s[1],l);
  883. s[0]:=chr(l);
  884. fpc_pchar_to_shortstr := s;
  885. end;
  886. {$endif ndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  887. {$ifndef FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  888. function fpc_chararray_to_shortstr(const arr: array of char; zerobased: boolean = true):shortstring;[public,alias:'FPC_CHARARRAY_TO_SHORTSTR']; compilerproc;
  889. var
  890. l: longint;
  891. index: longint;
  892. len: byte;
  893. begin
  894. l := high(arr)+1;
  895. if l>=256 then
  896. l:=255
  897. else if l<0 then
  898. l:=0;
  899. if (zerobased) then
  900. begin
  901. index:=IndexByte(arr[0],l,0);
  902. if (index < 0) then
  903. len := l
  904. else
  905. len := index;
  906. end
  907. else
  908. len := l;
  909. move(arr[0],fpc_chararray_to_shortstr[1],len);
  910. fpc_chararray_to_shortstr[0]:=chr(len);
  911. end;
  912. {$endif ndef FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  913. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_TO_CHARARRAY}
  914. {$ifndef FPC_STRTOCHARARRAYPROC}
  915. { inside the compiler, the resulttype is modified to that of the actual }
  916. { chararray we're converting to (JM) }
  917. function fpc_shortstr_to_chararray(arraysize: longint; const src: ShortString): fpc_big_chararray;[public,alias: 'FPC_SHORTSTR_TO_CHARARRAY']; compilerproc;
  918. var
  919. len: longint;
  920. begin
  921. len := length(src);
  922. if len > arraysize then
  923. len := arraysize;
  924. {$r-}
  925. { make sure we don't access char 1 if length is 0 (JM) }
  926. if len > 0 then
  927. move(src[1],fpc_shortstr_to_chararray[0],len);
  928. fillchar(fpc_shortstr_to_chararray[len],arraysize-len,0);
  929. {$ifdef RangeCheckWasOn}
  930. {$r+}
  931. {$endif}
  932. end;
  933. {$else ndef FPC_STRTOCHARARRAYPROC}
  934. procedure fpc_shortstr_to_chararray(out res: array of char; const src: ShortString); compilerproc;
  935. var
  936. len: longint;
  937. begin
  938. len := length(src);
  939. if len > length(res) then
  940. len := length(res);
  941. {$r-}
  942. { make sure we don't access char 1 if length is 0 (JM) }
  943. if len > 0 then
  944. move(src[1],res[0],len);
  945. fillchar(res[len],length(res)-len,0);
  946. {$ifdef RangeCheckWasOn}
  947. {$r+}
  948. {$endif}
  949. end;
  950. {$endif ndef FPC_STRTOCHARARRAYPROC}
  951. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_TO_CHARARRAY}
  952. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  953. function fpc_pchar_length(p:pchar):longint;[public,alias:'FPC_PCHAR_LENGTH']; compilerproc;
  954. var i : longint;
  955. begin
  956. i:=0;
  957. while p[i]<>#0 do inc(i);
  958. exit(i);
  959. end;
  960. {$endif ndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  961. {$ifndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  962. function fpc_pwidechar_length(p:pwidechar):longint;[public,alias:'FPC_PWIDECHAR_LENGTH']; compilerproc;
  963. var i : longint;
  964. begin
  965. i:=0;
  966. while p[i]<>#0 do inc(i);
  967. exit(i);
  968. end;
  969. {$endif ndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  970. {****************************************************************************
  971. Caller/StackFrame Helpers
  972. ****************************************************************************}
  973. {$ifndef FPC_SYSTEM_HAS_GET_FRAME}
  974. {_$error Get_frame must be defined for each processor }
  975. {$endif ndef FPC_SYSTEM_HAS_GET_FRAME}
  976. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  977. {_$error Get_caller_addr must be defined for each processor }
  978. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  979. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  980. {_$error Get_caller_frame must be defined for each processor }
  981. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  982. {****************************************************************************
  983. Math
  984. ****************************************************************************}
  985. {****************************************************************************
  986. Software longint/dword division
  987. ****************************************************************************}
  988. {$ifdef FPC_INCLUDE_SOFTWARE_MOD_DIV}
  989. function count_leading_zeros_32bit(l : longint) : longint;
  990. var
  991. i : longint;
  992. begin
  993. for i:=0 to 31 do
  994. begin
  995. if (l and (longint($80000000) shr i))<>0 then
  996. begin
  997. result:=i;
  998. exit;
  999. end;
  1000. end;
  1001. result:=i;
  1002. end;
  1003. {$ifndef FPC_SYSTEM_HAS_DIV_DWORD}
  1004. function fpc_div_dword(n,z : dword) : dword; [public,alias: 'FPC_DIV_DWORD']; compilerproc;
  1005. var
  1006. shift,lzz,lzn : longint;
  1007. begin
  1008. result:=0;
  1009. if n=0 then
  1010. HandleErrorFrame(200,get_frame);
  1011. lzz:=count_leading_zeros_32bit(z);
  1012. lzn:=count_leading_zeros_32bit(n);
  1013. { if the denominator contains less zeros
  1014. then the numerator
  1015. the d is greater than the n }
  1016. if lzn<lzz then
  1017. exit;
  1018. shift:=lzn-lzz;
  1019. n:=n shl shift;
  1020. repeat
  1021. if z>=n then
  1022. begin
  1023. z:=z-n;
  1024. result:=result+dword(1 shl shift);
  1025. end;
  1026. dec(shift);
  1027. n:=n shr 1;
  1028. until shift<0;
  1029. end;
  1030. {$endif FPC_SYSTEM_HAS_DIV_DWORD}
  1031. {$ifndef FPC_SYSTEM_HAS_MOD_DWORD}
  1032. function fpc_mod_dword(n,z : dword) : dword; [public,alias: 'FPC_MOD_DWORD']; compilerproc;
  1033. var
  1034. shift,lzz,lzn : longint;
  1035. begin
  1036. result:=0;
  1037. if n=0 then
  1038. HandleErrorFrame(200,get_frame);
  1039. lzz:=count_leading_zeros_32bit(z);
  1040. lzn:=count_leading_zeros_32bit(n);
  1041. { if the denominator contains less zeros
  1042. then the numerator
  1043. the d is greater than the n }
  1044. if lzn<lzz then
  1045. begin
  1046. result:=z;
  1047. exit;
  1048. end;
  1049. shift:=lzn-lzz;
  1050. n:=n shl shift;
  1051. repeat
  1052. if z>=n then
  1053. z:=z-n;
  1054. dec(shift);
  1055. n:=n shr 1;
  1056. until shift<0;
  1057. result:=z;
  1058. end;
  1059. {$endif FPC_SYSTEM_HAS_MOD_DWORD}
  1060. {$ifndef FPC_SYSTEM_HAS_DIV_LONGINT}
  1061. function fpc_div_longint(n,z : longint) : longint; [public,alias: 'FPC_DIV_LONGINT']; compilerproc;
  1062. var
  1063. sign : boolean;
  1064. d1,d2 : dword;
  1065. begin
  1066. if n=0 then
  1067. HandleErrorFrame(200,get_frame);
  1068. sign:=false;
  1069. if z<0 then
  1070. begin
  1071. sign:=not(sign);
  1072. d1:=dword(-z);
  1073. end
  1074. else
  1075. d1:=z;
  1076. if n<0 then
  1077. begin
  1078. sign:=not(sign);
  1079. d2:=dword(-n);
  1080. end
  1081. else
  1082. d2:=n;
  1083. { the div is coded by the compiler as call to divdword }
  1084. if sign then
  1085. result:=-(d1 div d2)
  1086. else
  1087. result:=d1 div d2;
  1088. end;
  1089. {$endif FPC_SYSTEM_HAS_DIV_LONGINT}
  1090. {$ifndef FPC_SYSTEM_HAS_MOD_LONGINT}
  1091. function fpc_mod_longint(n,z : longint) : longint; [public,alias: 'FPC_MOD_LONGINT']; compilerproc;
  1092. var
  1093. signed : boolean;
  1094. r,nq,zq : dword;
  1095. begin
  1096. if n=0 then
  1097. HandleErrorFrame(200,get_frame);
  1098. nq:=abs(n);
  1099. if z<0 then
  1100. begin
  1101. zq:=dword(-z);
  1102. signed:=true;
  1103. end
  1104. else
  1105. begin
  1106. zq:=z;
  1107. signed:=false;
  1108. end;
  1109. r:=zq mod nq;
  1110. if signed then
  1111. result:=-longint(r)
  1112. else
  1113. result:=r;
  1114. end;
  1115. {$endif FPC_SYSTEM_HAS_MOD_LONGINT}
  1116. {$endif FPC_INCLUDE_SOFTWARE_MOD_DIV}
  1117. {****************************************************************************}
  1118. {$ifndef FPC_SYSTEM_HAS_ABS_LONGINT}
  1119. function abs(l:longint):longint;{$ifdef SYSTEMINLINE}inline;{$endif}
  1120. begin
  1121. if l<0 then
  1122. abs:=-l
  1123. else
  1124. abs:=l;
  1125. end;
  1126. {$endif not FPC_SYSTEM_HAS_ABS_LONGINT}
  1127. {$ifndef FPC_SYSTEM_HAS_ODD_LONGINT}
  1128. function odd(l:longint):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  1129. begin
  1130. odd:=boolean(l and 1);
  1131. end;
  1132. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGINT}
  1133. {$ifndef FPC_SYSTEM_HAS_ODD_LONGWORD}
  1134. function odd(l:longword):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  1135. begin
  1136. odd:=boolean(l and 1);
  1137. end;
  1138. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGWORD}
  1139. {$ifndef FPC_SYSTEM_HAS_ODD_INT64}
  1140. function odd(l:int64):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  1141. begin
  1142. odd:=boolean(longint(l) and 1);
  1143. end;
  1144. {$endif ndef FPC_SYSTEM_HAS_ODD_INT64}
  1145. {$ifndef FPC_SYSTEM_HAS_ODD_QWORD}
  1146. function odd(l:qword):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  1147. begin
  1148. odd:=boolean(longint(l) and 1);
  1149. end;
  1150. {$endif ndef FPC_SYSTEM_HAS_ODD_QWORD}
  1151. {$ifndef FPC_SYSTEM_HAS_SQR_LONGINT}
  1152. function sqr(l:longint):longint;{$ifdef SYSTEMINLINE}inline;{$endif}
  1153. begin
  1154. sqr:=l*l;
  1155. end;
  1156. {$endif ndef FPC_SYSTEM_HAS_SQR_LONGINT}
  1157. {$ifndef FPC_SYSTEM_HAS_ABS_INT64}
  1158. function abs(l: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  1159. begin
  1160. if l < 0 then
  1161. abs := -l
  1162. else
  1163. abs := l;
  1164. end;
  1165. {$endif ndef FPC_SYSTEM_HAS_ABS_INT64}
  1166. {$ifndef FPC_SYSTEM_HAS_SQR_INT64}
  1167. function sqr(l: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  1168. begin
  1169. sqr := l*l;
  1170. end;
  1171. {$endif ndef FPC_SYSTEM_HAS_SQR_INT64}
  1172. {$ifndef FPC_SYSTEM_HAS_SQR_QWORD}
  1173. function sqr(l: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  1174. begin
  1175. sqr := l*l;
  1176. end;
  1177. {$endif ndef FPC_SYSTEM_HAS_SQR_INT64}
  1178. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  1179. function declocked(var l:longint):boolean;
  1180. begin
  1181. Dec(l);
  1182. declocked:=(l=0);
  1183. end;
  1184. {$endif FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  1185. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_INT64}
  1186. function declocked(var l:int64):boolean;
  1187. begin
  1188. Dec(l);
  1189. declocked:=(l=0);
  1190. end;
  1191. {$endif FPC_SYSTEM_HAS_DECLOCKED_INT64}
  1192. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  1193. procedure inclocked(var l:longint);
  1194. begin
  1195. Inc(l);
  1196. end;
  1197. {$endif FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  1198. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_INT64}
  1199. procedure inclocked(var l:int64);
  1200. begin
  1201. Inc(l);
  1202. end;
  1203. {$endif FPC_SYSTEM_HAS_INCLOCKED_INT64}
  1204. {$ifndef FPC_SYSTEM_HAS_SPTR}
  1205. {_$error Sptr must be defined for each processor }
  1206. {$endif ndef FPC_SYSTEM_HAS_SPTR}
  1207. function align(addr : PtrUInt;alignment : PtrUInt) : PtrUInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1208. begin
  1209. if addr mod alignment<>0 then
  1210. result:=addr+(alignment-(addr mod alignment))
  1211. else
  1212. result:=addr;
  1213. end;
  1214. function align(addr : Pointer;alignment : PtrUInt) : Pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
  1215. begin
  1216. if PtrUInt(addr) mod alignment<>0 then
  1217. result:=pointer(addr+(alignment-(PtrUInt(addr) mod alignment)))
  1218. else
  1219. result:=addr;
  1220. end;
  1221. {****************************************************************************
  1222. Str()
  1223. ****************************************************************************}
  1224. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  1225. procedure int_str(l:longint;out s:string);
  1226. var
  1227. m,m1 : longword;
  1228. pc,pc2 : pchar;
  1229. hs : string[32];
  1230. b : longint;
  1231. begin
  1232. pc2:=@s[1];
  1233. if (l<0) then
  1234. begin
  1235. b:=1;
  1236. pc2^:='-';
  1237. inc(pc2);
  1238. m:=longword(-l);
  1239. end
  1240. else
  1241. begin
  1242. b:=0;
  1243. m:=longword(l);
  1244. end;
  1245. pc:=@hs[0];
  1246. repeat
  1247. inc(pc);
  1248. m1:=m div 10;
  1249. pc^:=char(m-(m1*10)+byte('0'));
  1250. m:=m1;
  1251. until m=0;
  1252. while (pc>pchar(@hs[0])) and
  1253. (b<high(s)) do
  1254. begin
  1255. pc2^:=pc^;
  1256. dec(pc);
  1257. inc(pc2);
  1258. inc(b);
  1259. end;
  1260. s[0]:=chr(b);
  1261. end;
  1262. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  1263. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  1264. procedure int_str(l:longword;out s:string);
  1265. var
  1266. m1 : longword;
  1267. b: longint;
  1268. pc,pc2 : pchar;
  1269. hs : string[32];
  1270. begin
  1271. pc2:=@s[1];
  1272. pc:=@hs[0];
  1273. repeat
  1274. inc(pc);
  1275. m1:=l div 10;
  1276. pc^:=char(l-(m1*10)+byte('0'));
  1277. l:=m1;
  1278. until l=0;
  1279. b:=0;
  1280. while (pc>pchar(@hs[0])) and
  1281. (b<high(s)) do
  1282. begin
  1283. pc2^:=pc^;
  1284. dec(pc);
  1285. inc(pc2);
  1286. inc(b);
  1287. end;
  1288. s[0]:=chr(b);
  1289. end;
  1290. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  1291. {$ifndef FPC_SYSTEM_HAS_INT_STR_INT64}
  1292. procedure int_str(l:int64;out s:string);
  1293. var
  1294. m,m1 : qword;
  1295. pc,pc2 : pchar;
  1296. b: longint;
  1297. hs : string[64];
  1298. begin
  1299. pc2:=@s[1];
  1300. if (l<0) then
  1301. begin
  1302. b:=1;
  1303. pc2^:='-';
  1304. inc(pc2);
  1305. m:=qword(-l);
  1306. end
  1307. else
  1308. begin
  1309. b:=0;
  1310. m:=qword(l);
  1311. end;
  1312. pc:=@hs[0];
  1313. repeat
  1314. inc(pc);
  1315. m1:=m div 10;
  1316. pc^:=char(m-(m1*10)+byte('0'));
  1317. m:=m1;
  1318. until m=0;
  1319. while (pc>pchar(@hs[0])) and
  1320. (b < high(s)) do
  1321. begin
  1322. pc2^:=pc^;
  1323. dec(pc);
  1324. inc(pc2);
  1325. inc(b);
  1326. end;
  1327. s[0]:=chr(b);
  1328. end;
  1329. {$endif ndef FPC_SYSTEM_HAS_INT_STR_INT64}
  1330. {$ifndef FPC_SYSTEM_HAS_INT_STR_QWORD}
  1331. procedure int_str(l:qword;out s:string);
  1332. var
  1333. m1 : qword;
  1334. pc,pc2 : pchar;
  1335. b: longint;
  1336. hs : string[64];
  1337. begin
  1338. pc2:=@s[1];
  1339. pc:=@hs[0];
  1340. repeat
  1341. inc(pc);
  1342. m1:=l div 10;
  1343. pc^:=char(l-(m1*10)+byte('0'));
  1344. l:=m1;
  1345. until l=0;
  1346. b:=0;
  1347. while (pc>pchar(@hs[0])) and
  1348. (b<high(s)) do
  1349. begin
  1350. pc2^:=pc^;
  1351. dec(pc);
  1352. inc(pc2);
  1353. inc(b);
  1354. end;
  1355. s[0]:=chr(b);
  1356. end;
  1357. {$endif ndef FPC_SYSTEM_HAS_INT_STR_QWORD}
  1358. {$ifndef FPC_SYSTEM_HAS_SYSRESETFPU}
  1359. procedure SysResetFpu;{$ifdef SYSTEMINLINE}inline;{$endif}
  1360. begin
  1361. softfloat_exception_flags:=0;
  1362. softfloat_exception_mask:=float_flag_underflow or float_flag_inexact or float_flag_denormal;
  1363. end;
  1364. {$endif FPC_SYSTEM_HAS_SYSRESETFPU}
  1365. {$ifndef FPC_SYSTEM_HAS_SWAPENDIAN}
  1366. function SwapEndian(const AValue: SmallInt): SmallInt;
  1367. begin
  1368. Result := (AValue shr 8) or (AValue shl 8);
  1369. end;
  1370. function SwapEndian(const AValue: Word): Word;
  1371. begin
  1372. Result := (AValue shr 8) or (AValue shl 8);
  1373. end;
  1374. function SwapEndian(const AValue: LongInt): LongInt;
  1375. begin
  1376. Result := (AValue shl 24)
  1377. or ((AValue and $0000FF00) shl 8)
  1378. or ((AValue and $00FF0000) shr 8)
  1379. or (AValue shr 24);
  1380. end;
  1381. function SwapEndian(const AValue: DWord): DWord;
  1382. begin
  1383. Result := (AValue shl 24)
  1384. or ((AValue and $0000FF00) shl 8)
  1385. or ((AValue and $00FF0000) shr 8)
  1386. or (AValue shr 24);
  1387. end;
  1388. function SwapEndian(const AValue: Int64): Int64;
  1389. begin
  1390. Result := (AValue shl 56)
  1391. or ((AValue and $000000000000FF00) shl 40)
  1392. or ((AValue and $0000000000FF0000) shl 24)
  1393. or ((AValue and $00000000FF000000) shl 8)
  1394. or ((AValue and $000000FF00000000) shr 8)
  1395. or ((AValue and $0000FF0000000000) shr 24)
  1396. or ((AValue and $00FF000000000000) shr 40)
  1397. or (AValue shr 56);
  1398. end;
  1399. function SwapEndian(const AValue: QWord): QWord;
  1400. begin
  1401. Result := (AValue shl 56)
  1402. or ((AValue and $000000000000FF00) shl 40)
  1403. or ((AValue and $0000000000FF0000) shl 24)
  1404. or ((AValue and $00000000FF000000) shl 8)
  1405. or ((AValue and $000000FF00000000) shr 8)
  1406. or ((AValue and $0000FF0000000000) shr 24)
  1407. or ((AValue and $00FF000000000000) shr 40)
  1408. or (AValue shr 56);
  1409. end;
  1410. {$endif FPC_SYSTEM_HAS_SWAPENDIAN}
  1411. function BEtoN(const AValue: SmallInt): SmallInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1412. begin
  1413. {$IFDEF ENDIAN_BIG}
  1414. Result := AValue;
  1415. {$ELSE}
  1416. Result := SwapEndian(AValue);
  1417. {$ENDIF}
  1418. end;
  1419. function BEtoN(const AValue: Word): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  1420. begin
  1421. {$IFDEF ENDIAN_BIG}
  1422. Result := AValue;
  1423. {$ELSE}
  1424. Result := SwapEndian(AValue);
  1425. {$ENDIF}
  1426. end;
  1427. function BEtoN(const AValue: LongInt): LongInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1428. begin
  1429. {$IFDEF ENDIAN_BIG}
  1430. Result := AValue;
  1431. {$ELSE}
  1432. Result := SwapEndian(AValue);
  1433. {$ENDIF}
  1434. end;
  1435. function BEtoN(const AValue: DWord): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  1436. begin
  1437. {$IFDEF ENDIAN_BIG}
  1438. Result := AValue;
  1439. {$ELSE}
  1440. Result := SwapEndian(AValue);
  1441. {$ENDIF}
  1442. end;
  1443. function BEtoN(const AValue: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  1444. begin
  1445. {$IFDEF ENDIAN_BIG}
  1446. Result := AValue;
  1447. {$ELSE}
  1448. Result := SwapEndian(AValue);
  1449. {$ENDIF}
  1450. end;
  1451. function BEtoN(const AValue: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  1452. begin
  1453. {$IFDEF ENDIAN_BIG}
  1454. Result := AValue;
  1455. {$ELSE}
  1456. Result := SwapEndian(AValue);
  1457. {$ENDIF}
  1458. end;
  1459. function LEtoN(const AValue: SmallInt): SmallInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1460. begin
  1461. {$IFDEF ENDIAN_LITTLE}
  1462. Result := AValue;
  1463. {$ELSE}
  1464. Result := SwapEndian(AValue);
  1465. {$ENDIF}
  1466. end;
  1467. function LEtoN(const AValue: Word): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  1468. begin
  1469. {$IFDEF ENDIAN_LITTLE}
  1470. Result := AValue;
  1471. {$ELSE}
  1472. Result := SwapEndian(AValue);
  1473. {$ENDIF}
  1474. end;
  1475. function LEtoN(const AValue: LongInt): LongInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1476. begin
  1477. {$IFDEF ENDIAN_LITTLE}
  1478. Result := AValue;
  1479. {$ELSE}
  1480. Result := SwapEndian(AValue);
  1481. {$ENDIF}
  1482. end;
  1483. function LEtoN(const AValue: DWord): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  1484. begin
  1485. {$IFDEF ENDIAN_LITTLE}
  1486. Result := AValue;
  1487. {$ELSE}
  1488. Result := SwapEndian(AValue);
  1489. {$ENDIF}
  1490. end;
  1491. function LEtoN(const AValue: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  1492. begin
  1493. {$IFDEF ENDIAN_LITTLE}
  1494. Result := AValue;
  1495. {$ELSE}
  1496. Result := SwapEndian(AValue);
  1497. {$ENDIF}
  1498. end;
  1499. function LEtoN(const AValue: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  1500. begin
  1501. {$IFDEF ENDIAN_LITTLE}
  1502. Result := AValue;
  1503. {$ELSE}
  1504. Result := SwapEndian(AValue);
  1505. {$ENDIF}
  1506. end;
  1507. function NtoBE(const AValue: SmallInt): SmallInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1508. begin
  1509. {$IFDEF ENDIAN_BIG}
  1510. Result := AValue;
  1511. {$ELSE}
  1512. Result := SwapEndian(AValue);
  1513. {$ENDIF}
  1514. end;
  1515. function NtoBE(const AValue: Word): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  1516. begin
  1517. {$IFDEF ENDIAN_BIG}
  1518. Result := AValue;
  1519. {$ELSE}
  1520. Result := SwapEndian(AValue);
  1521. {$ENDIF}
  1522. end;
  1523. function NtoBE(const AValue: LongInt): LongInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1524. begin
  1525. {$IFDEF ENDIAN_BIG}
  1526. Result := AValue;
  1527. {$ELSE}
  1528. Result := SwapEndian(AValue);
  1529. {$ENDIF}
  1530. end;
  1531. function NtoBE(const AValue: DWord): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  1532. begin
  1533. {$IFDEF ENDIAN_BIG}
  1534. Result := AValue;
  1535. {$ELSE}
  1536. Result := SwapEndian(AValue);
  1537. {$ENDIF}
  1538. end;
  1539. function NtoBE(const AValue: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  1540. begin
  1541. {$IFDEF ENDIAN_BIG}
  1542. Result := AValue;
  1543. {$ELSE}
  1544. Result := SwapEndian(AValue);
  1545. {$ENDIF}
  1546. end;
  1547. function NtoBE(const AValue: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  1548. begin
  1549. {$IFDEF ENDIAN_BIG}
  1550. Result := AValue;
  1551. {$ELSE}
  1552. Result := SwapEndian(AValue);
  1553. {$ENDIF}
  1554. end;
  1555. function NtoLE(const AValue: SmallInt): SmallInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1556. begin
  1557. {$IFDEF ENDIAN_LITTLE}
  1558. Result := AValue;
  1559. {$ELSE}
  1560. Result := SwapEndian(AValue);
  1561. {$ENDIF}
  1562. end;
  1563. function NtoLE(const AValue: Word): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  1564. begin
  1565. {$IFDEF ENDIAN_LITTLE}
  1566. Result := AValue;
  1567. {$ELSE}
  1568. Result := SwapEndian(AValue);
  1569. {$ENDIF}
  1570. end;
  1571. function NtoLE(const AValue: LongInt): LongInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1572. begin
  1573. {$IFDEF ENDIAN_LITTLE}
  1574. Result := AValue;
  1575. {$ELSE}
  1576. Result := SwapEndian(AValue);
  1577. {$ENDIF}
  1578. end;
  1579. function NtoLE(const AValue: DWord): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  1580. begin
  1581. {$IFDEF ENDIAN_LITTLE}
  1582. Result := AValue;
  1583. {$ELSE}
  1584. Result := SwapEndian(AValue);
  1585. {$ENDIF}
  1586. end;
  1587. function NtoLE(const AValue: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  1588. begin
  1589. {$IFDEF ENDIAN_LITTLE}
  1590. Result := AValue;
  1591. {$ELSE}
  1592. Result := SwapEndian(AValue);
  1593. {$ENDIF}
  1594. end;
  1595. function NtoLE(const AValue: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  1596. begin
  1597. {$IFDEF ENDIAN_LITTLE}
  1598. Result := AValue;
  1599. {$ELSE}
  1600. Result := SwapEndian(AValue);
  1601. {$ENDIF}
  1602. end;
  1603. {$ifndef FPC_SYSTEM_HAS_MEM_BARRIER}
  1604. procedure ReadBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  1605. begin
  1606. end;
  1607. procedure ReadDependencyBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  1608. begin
  1609. end;
  1610. procedure ReadWriteBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  1611. begin
  1612. end;
  1613. procedure WriteBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  1614. begin
  1615. end;
  1616. {$endif}