generic.inc 44 KB

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