generic.inc 88 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357
  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. function align(addr : PtrUInt;alignment : PtrUInt) : PtrUInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  13. var
  14. tmp,am1 : PtrUInt;
  15. begin
  16. am1:=alignment-1;
  17. tmp:=addr+am1;
  18. if alignment and am1=0 then
  19. { Alignment is a power of two. In practice alignments are powers of two 100% of the time. }
  20. result:=tmp and not am1
  21. else
  22. result:=tmp-(tmp mod alignment);
  23. end;
  24. {$ifndef cpujvm}
  25. function align(addr : Pointer;alignment : PtrUInt) : Pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
  26. var
  27. tmp,am1 : PtrUInt;
  28. begin
  29. am1:=alignment-1;
  30. tmp:=PtrUint(addr)+am1;
  31. if alignment and am1=0 then
  32. result:=pointer(tmp and not am1)
  33. else
  34. result:=pointer(ptruint(tmp-(tmp mod alignment)));
  35. end;
  36. {$endif}
  37. {****************************************************************************
  38. Primitives
  39. ****************************************************************************}
  40. type
  41. pstring = ^shortstring;
  42. {$ifndef FPC_HAS_SHORTSTR_SHORTSTR_INTERN_CHARMOVE}
  43. {$define FPC_HAS_SHORTSTR_SHORTSTR_INTERN_CHARMOVE}
  44. procedure fpc_shortstr_shortstr_intern_charmove(const src: shortstring; const srcindex: byte; var dst: shortstring; const dstindex, len: byte); {$ifdef SYSTEMINLINE}inline;{$endif}
  45. begin
  46. move(src[srcindex],dst[dstindex],len);
  47. end;
  48. {$endif FPC_HAS_SHORTSTR_SHORTSTR_INTERN_CHARMOVE}
  49. {$ifndef FPC_HAS_SHORTSTR_CHARARRAY_INTERN_CHARMOVE}
  50. {$define FPC_HAS_SHORTSTR_CHARARRAY_INTERN_CHARMOVE}
  51. procedure fpc_shortstr_chararray_intern_charmove(const src: shortstring; out dst: array of char; const len: sizeint);
  52. begin
  53. move(src[1],pchar(@dst)^,len);
  54. end;
  55. {$endif FPC_HAS_SHORTSTR_CHARARRAY_INTERN_CHARMOVE}
  56. {$ifndef FPC_SYSTEM_HAS_MOVE}
  57. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE'];
  58. var
  59. aligncount : sizeint;
  60. pdest,psrc,pend : pbyte;
  61. begin
  62. if (@dest=@source) or (count<=0) then
  63. exit;
  64. if (@dest<@source) or (@source+count<@dest) then
  65. begin
  66. { Forward Move }
  67. psrc:=@source;
  68. pdest:=@dest;
  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:=(sizeof(PtrUInt)-PtrInt(pdest)) and (sizeof(PtrUInt)-1);
  77. dec(count,aligncount);
  78. pend:=psrc+aligncount;
  79. while psrc<pend do
  80. begin
  81. pdest^:=psrc^;
  82. inc(pdest);
  83. inc(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. pptruint(pdest)^:=pptruint(psrc)^;
  90. inc(pptruint(pdest));
  91. inc(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. pdest^:=psrc^;
  99. inc(pdest);
  100. inc(psrc);
  101. end;
  102. end
  103. else
  104. begin
  105. { Backward Move }
  106. psrc:=@source+count;
  107. pdest:=@dest+count;
  108. if (Count>4*sizeof(ptruint)-11)
  109. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  110. and ((PtrUInt(pdest) and (sizeof(PtrUInt)-1))=(PtrUInt(psrc) and (sizeof(PtrUInt)-1)))
  111. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  112. then
  113. begin
  114. { Align on native pointer size }
  115. aligncount:=(PtrUInt(pdest) and (sizeof(PtrUInt)-1));
  116. dec(count,aligncount);
  117. pend:=psrc-aligncount;
  118. while psrc>pend do
  119. begin
  120. dec(pdest);
  121. dec(psrc);
  122. pdest^:=psrc^;
  123. end;
  124. { use sizeuint typecast to force shr optimization }
  125. pptruint(pend):=pptruint(psrc)-(sizeuint(count) div sizeof(ptruint));
  126. while psrc>pend do
  127. begin
  128. dec(pptruint(pdest));
  129. dec(pptruint(psrc));
  130. pptruint(pdest)^:=pptruint(psrc)^;
  131. end;
  132. count:=count and (sizeof(PtrUInt)-1);
  133. end;
  134. pend:=psrc-count;
  135. while psrc>pend do
  136. begin
  137. dec(pdest);
  138. dec(psrc);
  139. pdest^:=psrc^;
  140. end;
  141. end;
  142. end;
  143. {$endif not FPC_SYSTEM_HAS_MOVE}
  144. {$ifndef FPC_SYSTEM_HAS_FILLCHAR}
  145. Procedure FillChar(var x;count:SizeInt;value:byte);
  146. var
  147. pdest,pend : pbyte;
  148. v : ALUUInt;
  149. begin
  150. if count <= 0 then
  151. exit;
  152. pdest:=@x;
  153. if Count>4*sizeof(ptruint)-1 then
  154. begin
  155. {$if sizeof(v)>=2}
  156. v:=(value shl 8) or value;
  157. {$endif sizeof(v)>=2}
  158. {$if sizeof(v)>=4}
  159. v:=(v shl 16) or v;
  160. {$endif sizeof(v)>=4}
  161. {$if sizeof(v)=8}
  162. v:=(v shl 32) or v;
  163. {$endif sizeof(v)=8}
  164. { Align on native pointer size }
  165. pend:=pbyte(align(pdest,sizeof(PtrUInt)));
  166. dec(count,pend-pdest);
  167. while pdest<pend do
  168. begin
  169. pdest^:=value;
  170. inc(pdest);
  171. end;
  172. { use sizeuint typecast to force shr optimization }
  173. pptruint(pend):=pptruint(pdest)+(sizeuint(count) div sizeof(ptruint));
  174. while pdest<pend do
  175. begin
  176. pptruint(pdest)^:=v;
  177. inc(pptruint(pdest));
  178. end;
  179. count:=count and (sizeof(ptruint)-1);
  180. end;
  181. pend:=pdest+count;
  182. while pdest<pend do
  183. begin
  184. pdest^:=value;
  185. inc(pdest);
  186. end;
  187. end;
  188. {$endif FPC_SYSTEM_HAS_FILLCHAR}
  189. {$ifndef FPC_SYSTEM_HAS_FILLWORD}
  190. procedure fillword(var x;count : SizeInt;value : word);
  191. var
  192. aligncount : sizeint;
  193. pdest,pend : pword;
  194. v : ALUUInt;
  195. begin
  196. if count <= 0 then
  197. exit;
  198. pdest:=@x;
  199. if Count>4*sizeof(ptruint)-1 then
  200. begin
  201. {$if sizeof(v)>=4}
  202. v:=(value shl 16) or value;
  203. {$endif sizeof(v)>=4}
  204. {$if sizeof(v)=8}
  205. v:=(v shl 32) or v;
  206. {$endif sizeof(v)=8}
  207. { Align on native pointer size }
  208. aligncount:=(PtrUInt(pdest) and (sizeof(PtrUInt)-1)) shr 1;
  209. dec(count,aligncount);
  210. pend:=pdest+aligncount;
  211. while pdest<pend do
  212. begin
  213. pdest^:=value;
  214. inc(pdest);
  215. end;
  216. { use sizeuint typecast to force shr optimization }
  217. pptruint(pend):=pptruint(pdest)+((sizeuint(count)*2) div sizeof(ptruint));
  218. while pdest<pend do
  219. begin
  220. pptruint(pdest)^:=v;
  221. inc(pptruint(pdest));
  222. end;
  223. count:=((count*2) and (sizeof(ptruint)-1)) shr 1;
  224. end;
  225. pend:=pdest+count;
  226. while pdest<pend do
  227. begin
  228. pdest^:=value;
  229. inc(pdest);
  230. end;
  231. end;
  232. {$endif not FPC_SYSTEM_HAS_FILLWORD}
  233. {$ifndef FPC_SYSTEM_HAS_FILLDWORD}
  234. procedure filldword(var x;count : SizeInt;value : dword);
  235. var
  236. aligncount : sizeint;
  237. pdest,pend : pdword;
  238. v : ALUUInt;
  239. begin
  240. if count <= 0 then
  241. exit;
  242. pdest:=@x;
  243. if Count>4*sizeof(ptruint)-1 then
  244. begin
  245. v:=value;
  246. {$if sizeof(v)=8}
  247. v:=(v shl 32) or v;
  248. {$endif sizeof(v)=8}
  249. { Align on native pointer size }
  250. aligncount:=(PtrUInt(pdest) and (sizeof(PtrUInt)-1)) shr 2;
  251. dec(count,aligncount);
  252. pend:=pdest+aligncount;
  253. while pdest<pend do
  254. begin
  255. pdest^:=value;
  256. inc(pdest);
  257. end;
  258. { use sizeuint typecast to force shr optimization }
  259. pptruint(pend):=pptruint(pdest)+((sizeuint(count)*4) div sizeof(ptruint));
  260. while pdest<pend do
  261. begin
  262. pptruint(pdest)^:=v;
  263. inc(pptruint(pdest));
  264. end;
  265. count:=((count*4) and (sizeof(ptruint)-1)) shr 2;
  266. end;
  267. pend:=pdest+count;
  268. while pdest<pend do
  269. begin
  270. pdest^:=value;
  271. inc(pdest);
  272. end;
  273. end;
  274. {$endif FPC_SYSTEM_HAS_FILLDWORD}
  275. {$ifndef FPC_SYSTEM_HAS_FILLQWORD}
  276. procedure fillqword(var x;count : SizeInt;value : qword);
  277. var
  278. pdest,pend : pqword;
  279. begin
  280. if count <= 0 then
  281. exit;
  282. pdest:=@x;
  283. pend:=pdest+count;
  284. while pdest<pend do
  285. begin
  286. pdest^:=value;
  287. inc(pdest);
  288. end;
  289. end;
  290. {$endif FPC_SYSTEM_HAS_FILLQWORD}
  291. {$ifndef FPC_SYSTEM_HAS_INDEXBYTE}
  292. function IndexByte(Const buf;len:SizeInt;b:byte):SizeInt;
  293. var
  294. psrc,pend : pbyte;
  295. begin
  296. psrc:=@buf;
  297. { simulate assembler implementations behaviour, which is expected }
  298. { fpc_pchar_to_ansistr in astrings.inc }
  299. if (len < 0) or
  300. (psrc+len < psrc) then
  301. pend:=pbyte(high(PtrUInt)-sizeof(byte))
  302. else
  303. pend:=psrc+len;
  304. while (psrc<pend) do
  305. begin
  306. if psrc^=b then
  307. begin
  308. result:=psrc-pbyte(@buf);
  309. exit;
  310. end;
  311. inc(psrc);
  312. end;
  313. result:=-1;
  314. end;
  315. {$endif not FPC_SYSTEM_HAS_INDEXBYTE}
  316. {$ifndef FPC_SYSTEM_HAS_INDEXWORD}
  317. function Indexword(Const buf;len:SizeInt;b:word):SizeInt;
  318. var
  319. psrc,pend : pword;
  320. begin
  321. psrc:=@buf;
  322. { simulate assembler implementations behaviour, which is expected }
  323. { fpc_pchar_to_ansistr in astrings.inc }
  324. if (len < 0) or
  325. { is this ever true? }
  326. (len > high(PtrInt)) or
  327. (psrc+len < psrc) then
  328. pend:=pword(high(PtrUInt)-sizeof(word))
  329. else
  330. pend:=psrc+len;
  331. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  332. if (ptruint(psrc) mod 2)<>0 then
  333. while psrc<pend do
  334. begin
  335. if unaligned(psrc^)=b then
  336. begin
  337. result:=psrc-pword(@buf);
  338. exit;
  339. end;
  340. inc(psrc);
  341. end
  342. else
  343. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  344. while psrc<pend do
  345. begin
  346. if psrc^=b then
  347. begin
  348. result:=psrc-pword(@buf);
  349. exit;
  350. end;
  351. inc(psrc);
  352. end;
  353. result:=-1;
  354. end;
  355. {$endif not FPC_SYSTEM_HAS_INDEXWORD}
  356. {$ifndef FPC_SYSTEM_HAS_INDEXDWORD}
  357. function IndexDWord(Const buf;len:SizeInt;b:DWord):SizeInt;
  358. var
  359. psrc,pend : pdword;
  360. begin
  361. psrc:=@buf;
  362. { simulate assembler implementations behaviour, which is expected }
  363. { fpc_pchar_to_ansistr in astrings.inc }
  364. if (len < 0) or
  365. (len > high(PtrInt) div 2) or
  366. (psrc+len < psrc) then
  367. pend:=pdword(high(PtrUInt)-PtrUInt(sizeof(dword)))
  368. else
  369. pend:=psrc+len;
  370. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  371. if (ptruint(psrc) mod 4)<>0 then
  372. while psrc<pend do
  373. begin
  374. if unaligned(psrc^)=b then
  375. begin
  376. result:=psrc-pdword(@buf);
  377. exit;
  378. end;
  379. inc(psrc);
  380. end
  381. else
  382. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  383. while psrc<pend do
  384. begin
  385. if psrc^=b then
  386. begin
  387. result:=psrc-pdword(@buf);
  388. exit;
  389. end;
  390. inc(psrc);
  391. end;
  392. result:=-1;
  393. end;
  394. {$endif not FPC_SYSTEM_HAS_INDEXDWORD}
  395. {$ifndef FPC_SYSTEM_HAS_INDEXQWORD}
  396. function IndexQWord(Const buf;len:SizeInt;b:QWord):SizeInt;
  397. var
  398. psrc,pend : pqword;
  399. begin
  400. psrc:=@buf;
  401. { simulate assembler implementations behaviour, which is expected }
  402. { fpc_pchar_to_ansistr in astrings.inc }
  403. if (len < 0) or
  404. (len > high(PtrInt) div 4) or
  405. (psrc+len < psrc) then
  406. pend:=pqword(high(PtrUInt)-PtrUInt(sizeof(qword)))
  407. else
  408. pend:=psrc+len;
  409. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  410. if (ptruint(psrc) mod 8)<>0 then
  411. while psrc<pend do
  412. begin
  413. if unaligned(psrc^)=b then
  414. begin
  415. result:=psrc-pqword(@buf);
  416. exit;
  417. end;
  418. inc(psrc);
  419. end
  420. else
  421. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  422. while psrc<pend do
  423. begin
  424. if psrc^=b then
  425. begin
  426. result:=psrc-pqword(@buf);
  427. exit;
  428. end;
  429. inc(psrc);
  430. end;
  431. result:=-1;
  432. end;
  433. {$endif not FPC_SYSTEM_HAS_INDEXQWORD}
  434. {$ifndef FPC_SYSTEM_HAS_COMPAREBYTE}
  435. function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt;
  436. var
  437. aligncount : sizeint;
  438. psrc,pdest,pend : pbyte;
  439. b : ptrint;
  440. begin
  441. b:=0;
  442. psrc:=@buf1;
  443. pdest:=@buf2;
  444. if (len>4*sizeof(ptruint)-1)
  445. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  446. and ((PtrUInt(pdest) and (sizeof(PtrUInt)-1))=(PtrUInt(psrc) and (sizeof(PtrUInt)-1)))
  447. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  448. then
  449. begin
  450. { Align on native pointer size }
  451. aligncount:=(sizeof(PtrUInt)-(PtrUInt(pdest) and (sizeof(PtrUInt)-1))) and (sizeof(PtrUInt)-1);
  452. dec(len,aligncount);
  453. pend:=psrc+aligncount;
  454. while psrc<pend do
  455. begin
  456. b:=(ptrint(psrc^)-ptrint(pdest^));
  457. if b<>0 then
  458. begin
  459. if b<0 then
  460. exit(-1)
  461. else
  462. exit(1);
  463. end;
  464. inc(pdest);
  465. inc(psrc);
  466. end;
  467. { use sizeuint typecast to force shr optimization }
  468. pptruint(pend):=pptruint(psrc)+(sizeuint(len) div sizeof(ptruint));
  469. len:=len and (sizeof(PtrUInt)-1);
  470. while psrc<pend do
  471. begin
  472. b:=(pptrint(psrc)^-pptrint(pdest)^);
  473. if b<>0 then
  474. begin
  475. len:=sizeof(ptruint);
  476. break;
  477. end;
  478. inc(pptruint(pdest));
  479. inc(pptruint(psrc));
  480. end;
  481. end;
  482. if (psrc+len >= psrc) then
  483. pend:=psrc+len
  484. else
  485. pend:=pbyte(high(ptruint)-1);
  486. while psrc<pend do
  487. begin
  488. b:=(ptrint(psrc^)-ptrint(pdest^));
  489. if b<>0 then
  490. begin
  491. if b<0 then
  492. exit(-1)
  493. else
  494. exit(1);
  495. end;
  496. inc(pdest);
  497. inc(psrc);
  498. end;
  499. result:=0;
  500. end;
  501. {$endif not FPC_SYSTEM_HAS_COMPAREBYTE}
  502. {$ifndef FPC_SYSTEM_HAS_COMPAREWORD}
  503. function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt;
  504. var
  505. aligncount : sizeint;
  506. psrc,pdest,pend : pword;
  507. b : ptrint;
  508. begin
  509. b:=0;
  510. psrc:=@buf1;
  511. pdest:=@buf2;
  512. if (len>4*sizeof(ptruint)-1)
  513. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  514. and ((PtrUInt(pdest) and (sizeof(PtrUInt)-1))=(PtrUInt(psrc) and (sizeof(PtrUInt)-1)))
  515. and (((PtrUInt(pdest) and 1) or (PtrUInt(psrc) and 1))=0)
  516. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  517. then
  518. begin
  519. { Align on native pointer size }
  520. aligncount:=((sizeof(PtrUInt)-(PtrUInt(pdest) and (sizeof(PtrUInt)-1))) and (sizeof(PtrUInt)-1)) shr 1;
  521. dec(len,aligncount);
  522. pend:=psrc+aligncount;
  523. while psrc<pend do
  524. begin
  525. b:=(ptrint(psrc^)-ptrint(pdest^));
  526. if b<>0 then
  527. begin
  528. if b<0 then
  529. exit(-1)
  530. else
  531. exit(1);
  532. end;
  533. inc(pdest);
  534. inc(psrc);
  535. end;
  536. { use sizeuint typecast to force shr optimization }
  537. pptruint(pend):=pptruint(psrc)+(sizeuint(len)*2 div sizeof(ptruint));
  538. len:=((len*2) and (sizeof(PtrUInt)-1)) shr 1;
  539. while psrc<pend do
  540. begin
  541. b:=(pptrint(psrc)^-pptrint(pdest)^);
  542. if b<>0 then
  543. begin
  544. len:=sizeof(ptruint) shr 1;
  545. break;
  546. end;
  547. inc(pptruint(pdest));
  548. inc(pptruint(psrc));
  549. end;
  550. end;
  551. if (psrc+len >= psrc) then
  552. pend:=psrc+len
  553. else
  554. pend:=pword(high(ptruint)-2);
  555. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  556. if ((PtrUInt(pdest) and 1) or (PtrUInt(psrc) and 1))<>0 then
  557. while psrc<pend do
  558. begin
  559. b:=(ptrint(unaligned(psrc^))-ptrint(unaligned(pdest^)));
  560. if b<>0 then
  561. begin
  562. if b<0 then
  563. exit(-1)
  564. else
  565. exit(1);
  566. end;
  567. inc(pdest);
  568. inc(psrc);
  569. end
  570. else
  571. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  572. while psrc<pend do
  573. begin
  574. b:=(ptrint(psrc^)-ptrint(pdest^));
  575. if b<>0 then
  576. begin
  577. if b<0 then
  578. exit(-1)
  579. else
  580. exit(1);
  581. end;
  582. inc(pdest);
  583. inc(psrc);
  584. end;
  585. result:=0;
  586. end;
  587. {$endif not FPC_SYSTEM_HAS_COMPAREWORD}
  588. {$ifndef FPC_SYSTEM_HAS_COMPAREDWORD}
  589. function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt;
  590. var
  591. aligncount : sizeint;
  592. psrc,pdest,pend : pdword;
  593. begin
  594. psrc:=@buf1;
  595. pdest:=@buf2;
  596. if (len>4*sizeof(ptruint)-11)
  597. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  598. and ((PtrUInt(pdest) and (sizeof(PtrUInt)-1))=(PtrUInt(psrc) and (sizeof(PtrUInt)-1)))
  599. and (((PtrUInt(pdest) and 3) or (PtrUInt(psrc) and 3))=0)
  600. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  601. then
  602. begin
  603. { Align on native pointer size }
  604. aligncount:=((sizeof(PtrUInt)-(PtrUInt(pdest) and (sizeof(PtrUInt)-1))) and (sizeof(PtrUInt)-1)) shr 2;
  605. dec(len,aligncount);
  606. pend:=psrc+aligncount;
  607. while psrc<pend do
  608. begin
  609. if psrc^<>pdest^ then
  610. if psrc^>pdest^ then
  611. exit(1)
  612. else
  613. exit(-1);
  614. inc(pdest);
  615. inc(psrc);
  616. end;
  617. { use sizeuint typecast to force shr optimization }
  618. pptruint(pend):=pptruint(psrc)+(sizeuint(len)*4 div sizeof(ptruint));
  619. len:=((len*4) and (sizeof(PtrUInt)-1)) shr 2;
  620. while psrc<pend do
  621. begin
  622. if pptrint(psrc)^<>pptrint(pdest)^ then
  623. begin
  624. len:=sizeof(ptruint) shr 2;
  625. break;
  626. end;
  627. inc(pptruint(pdest));
  628. inc(pptruint(psrc));
  629. end;
  630. end;
  631. if (len <= high(ptrint) div 2) and
  632. (psrc+len >= psrc) then
  633. pend:=psrc+len
  634. else
  635. pend:=pdword(high(ptruint)-4);
  636. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  637. if ((PtrUInt(pdest) and 3) or (PtrUInt(psrc) and 3))<>0 then
  638. while psrc<pend do
  639. begin
  640. if unaligned(psrc^)<>unaligned(pdest^) then
  641. if unaligned(psrc^)>unaligned(pdest^) then
  642. exit(1)
  643. else
  644. exit(-1);
  645. inc(pdest);
  646. inc(psrc);
  647. end
  648. else
  649. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  650. while psrc<pend do
  651. begin
  652. if psrc^<>pdest^ then
  653. if psrc^>pdest^ then
  654. exit(1)
  655. else
  656. exit(-1);
  657. inc(pdest);
  658. inc(psrc);
  659. end;
  660. result:=0;
  661. end;
  662. {$endif ndef FPC_SYSTEM_HAS_COMPAREDWORD}
  663. {$ifndef FPC_SYSTEM_HAS_MOVECHAR0}
  664. procedure MoveChar0(Const buf1;var buf2;len:SizeInt);
  665. var
  666. I : SizeInt;
  667. begin
  668. if Len = 0 then
  669. exit;
  670. I:=IndexByte(Buf1,Len,0);
  671. if I<>-1 then
  672. Move(Buf1,Buf2,I)
  673. else
  674. Move(Buf1,Buf2,len);
  675. end;
  676. {$endif ndef FPC_SYSTEM_HAS_MOVECHAR0}
  677. {$ifndef FPC_SYSTEM_HAS_INDEXCHAR0}
  678. function IndexChar0(Const buf;len:SizeInt;b:Char):SizeInt;
  679. var
  680. psrc,pend : pbyte;
  681. begin
  682. psrc:=@buf;
  683. { simulate assembler implementations behaviour, which is expected }
  684. { fpc_pchar_to_ansistr in astrings.inc }
  685. if (len < 0) then
  686. pend:=pbyte(high(PtrUInt)-PtrUInt(sizeof(byte)))
  687. else
  688. pend:=psrc+len;
  689. while (psrc<pend) and (psrc^<>0) do
  690. begin
  691. if (psrc^=byte(b)) then
  692. begin
  693. result:=psrc-pbyte(@buf);
  694. exit;
  695. end;
  696. inc(psrc);
  697. end;
  698. result:=-1;
  699. end;
  700. {$endif ndef FPC_SYSTEM_HAS_INDEXCHAR0}
  701. {$ifndef FPC_SYSTEM_HAS_COMPARECHAR0}
  702. function CompareChar0(Const buf1,buf2;len:SizeInt):SizeInt;
  703. var
  704. psrc,pdest,pend : pbyte;
  705. b : ptrint;
  706. begin
  707. b:=0;
  708. psrc:=@buf1;
  709. pdest:=@buf2;
  710. pend:=psrc+len;
  711. while psrc<pend do
  712. begin
  713. b:=(ptrint(psrc^)-ptrint(pdest^));
  714. if b<0 then
  715. exit(-1)
  716. else if b>0 then
  717. exit(1);
  718. if (psrc^=0) or (pdest^=0) then
  719. exit(0);
  720. inc(pdest);
  721. inc(psrc);
  722. end;
  723. result:=0;
  724. end;
  725. {$endif not FPC_SYSTEM_HAS_COMPARECHAR0}
  726. {****************************************************************************
  727. Object Helpers
  728. ****************************************************************************}
  729. {$ifdef FPC_HAS_FEATURE_OBJECTS}
  730. type
  731. pobjectvmt=^tobjectvmt;
  732. tobjectvmt=record
  733. size,msize:sizeuint;
  734. parent:{$ifdef VER3_0}pointer{$else}ppointer{$endif};
  735. end;
  736. {$ifndef FPC_SYSTEM_HAS_FPC_HELP_CONSTRUCTOR}
  737. { Note: _vmt will be reset to -1 when memory is allocated,
  738. this is needed for fpc_help_fail }
  739. function fpc_help_constructor(_self:pointer;var _vmt:pointer;_vmt_pos:cardinal):pointer;[public,alias:'FPC_HELP_CONSTRUCTOR'];compilerproc;
  740. var
  741. vmtcopy : pobjectvmt;
  742. begin
  743. vmtcopy:=pobjectvmt(_vmt);
  744. { Inherited call? }
  745. if vmtcopy=nil then
  746. begin
  747. fpc_help_constructor:=_self;
  748. exit;
  749. end;
  750. if (_self=nil) and
  751. (vmtcopy^.size>0) then
  752. begin
  753. getmem(_self,vmtcopy^.size);
  754. { reset vmt needed for fail }
  755. _vmt:=pointer(-1);
  756. end;
  757. if _self<>nil then
  758. begin
  759. fillchar(_self^,vmtcopy^.size,0);
  760. ppointer(_self+_vmt_pos)^:=vmtcopy;
  761. end;
  762. fpc_help_constructor:=_self;
  763. end;
  764. {$endif FPC_SYSTEM_HAS_FPC_HELP_CONSTRUCTOR}
  765. {$ifndef FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  766. { Note: _self will not be reset, the compiler has to generate the reset }
  767. procedure fpc_help_destructor(_self,_vmt:pointer;vmt_pos:cardinal);[public,alias:'FPC_HELP_DESTRUCTOR']; compilerproc;
  768. begin
  769. { already released? }
  770. if (_self=nil) or
  771. (_vmt<>pointer(-1)) or
  772. (ppointer(_self+vmt_pos)^=nil) then
  773. exit;
  774. if (pobjectvmt(ppointer(_self+vmt_pos)^)^.size=0) or
  775. (pobjectvmt(ppointer(_self+vmt_pos)^)^.size+pobjectvmt(ppointer(_self+vmt_pos)^)^.msize<>0) then
  776. HandleErrorAddrFrameInd(210,get_pc_addr,get_frame);
  777. { reset vmt to nil for protection }
  778. ppointer(_self+vmt_pos)^:=nil;
  779. freemem(_self);
  780. end;
  781. {$endif FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  782. {$ifndef FPC_SYSTEM_HAS_FPC_HELP_FAIL}
  783. { Note: _self will not be reset, the compiler has to generate the reset }
  784. procedure fpc_help_fail(_self:pointer;var _vmt:pointer;vmt_pos:cardinal);[public,alias:'FPC_HELP_FAIL'];compilerproc;
  785. begin
  786. if (_self=nil) or (_vmt=nil) then
  787. exit;
  788. { vmt=$ffffffff when memory was allocated }
  789. if ptruint(_vmt)=high(ptruint) then
  790. begin
  791. if (_self=nil) or (ppointer(_self+vmt_pos)^=nil) then
  792. HandleError(210)
  793. else
  794. begin
  795. ppointer(_self+vmt_pos)^:=nil;
  796. freemem(_self);
  797. { reset _vmt to nil so it will not be freed a
  798. second time }
  799. _vmt:=nil;
  800. end;
  801. end
  802. else
  803. ppointer(_self+vmt_pos)^:=nil;
  804. end;
  805. {$endif FPC_SYSTEM_HAS_FPC_HELP_FAIL}
  806. {$ifndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  807. procedure fpc_check_object(_vmt : pointer); [public,alias:'FPC_CHECK_OBJECT']; compilerproc;
  808. begin
  809. if (_vmt=nil) or
  810. (pobjectvmt(_vmt)^.size=0) or
  811. (pobjectvmt(_vmt)^.size+pobjectvmt(_vmt)^.msize<>0) then
  812. HandleErrorAddrFrameInd(210,get_pc_addr,get_frame);
  813. end;
  814. {$endif ndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  815. {$ifndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  816. { checks for a correct vmt pointer }
  817. { deeper check to see if the current object is }
  818. { really related to the true }
  819. procedure fpc_check_object_ext(vmt, expvmt : pointer); [public,alias:'FPC_CHECK_OBJECT_EXT']; compilerproc;
  820. begin
  821. if (vmt=nil) or
  822. (pobjectvmt(vmt)^.size=0) or
  823. (pobjectvmt(vmt)^.size+pobjectvmt(vmt)^.msize<>0) then
  824. HandleErrorAddrFrameInd(210,get_pc_addr,get_frame);
  825. while assigned(vmt) do
  826. if vmt=expvmt then
  827. exit
  828. else
  829. {$ifdef VER3_0}
  830. vmt:=pobjectvmt(vmt)^.parent;
  831. {$else VER3_0}
  832. if assigned(pobjectvmt(vmt)^.parent) then
  833. vmt:=pobjectvmt(vmt)^.parent^
  834. else
  835. vmt:=nil;
  836. {$endif}
  837. HandleErrorAddrFrameInd(219,get_pc_addr,get_frame);
  838. end;
  839. {$endif not FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  840. {$endif FPC_HAS_FEATURE_OBJECTS}
  841. {****************************************************************************
  842. String
  843. ****************************************************************************}
  844. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  845. procedure fpc_shortstr_to_shortstr(out res:shortstring; const sstr: shortstring);[public,alias:'FPC_SHORTSTR_TO_SHORTSTR']; compilerproc;
  846. var
  847. slen : byte;
  848. begin
  849. slen:=length(sstr);
  850. if slen>high(res) then
  851. slen:=high(res);
  852. move(sstr[0],res[0],slen+1);
  853. res[0]:=chr(slen);
  854. end;
  855. procedure fpc_shortstr_assign(len:{$ifdef cpu16}smallint{$else}longint{$endif};sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN']; compilerproc;
  856. var
  857. slen : byte;
  858. begin
  859. slen:=length(pshortstring(sstr)^);
  860. if slen<len then
  861. len:=slen;
  862. move(sstr^,dstr^,len+1);
  863. if slen>len then
  864. pchar(dstr)^:=chr(len);
  865. end;
  866. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  867. {$push}
  868. { ensure that comparing addresses of openshortstrings with regular shortstrings
  869. doesn't cause errors }
  870. {$t-}
  871. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  872. procedure fpc_shortstr_concat(var dests:shortstring;const s1,s2:shortstring);compilerproc;
  873. var
  874. s1l, s2l : ObjpasInt;
  875. begin
  876. s1l:=length(s1);
  877. s2l:=length(s2);
  878. if s1l+s2l>high(dests) then
  879. begin
  880. if s1l>high(dests) then
  881. s1l:=high(dests);
  882. s2l:=high(dests)-s1l;
  883. end;
  884. if @dests=@s1 then
  885. fpc_shortstr_shortstr_intern_charmove(s2,1,dests,s1l+1,s2l)
  886. else
  887. if @dests=@s2 then
  888. begin
  889. fpc_shortstr_shortstr_intern_charmove(dests,1,dests,s1l+1,s2l);
  890. fpc_shortstr_shortstr_intern_charmove(s1,1,dests,1,s1l);
  891. end
  892. else
  893. begin
  894. fpc_shortstr_shortstr_intern_charmove(s1,1,dests,1,s1l);
  895. fpc_shortstr_shortstr_intern_charmove(s2,1,dests,s1l+1,s2l);
  896. end;
  897. dests[0]:=chr(s1l+s2l);
  898. end;
  899. procedure fpc_shortstr_concat_multi(var dests:shortstring;const sarr:array of pshortstring);compilerproc;
  900. var
  901. s2l : byte;
  902. LowStart,i,
  903. Len : ObjpasInt;
  904. needtemp : boolean;
  905. tmpstr : shortstring;
  906. p,pdest : pshortstring;
  907. begin
  908. if high(sarr)=0 then
  909. begin
  910. DestS:='';
  911. exit;
  912. end;
  913. lowstart:=low(sarr);
  914. if Pointer(@DestS)=Pointer(sarr[lowstart]) then
  915. inc(lowstart);
  916. { Check for another reuse, then we can't use
  917. the append optimization and need to use a temp }
  918. needtemp:=false;
  919. for i:=lowstart to high(sarr) do
  920. begin
  921. if Pointer(@DestS)=Pointer(sarr[i]) then
  922. begin
  923. needtemp:=true;
  924. break;
  925. end;
  926. end;
  927. if needtemp then
  928. begin
  929. lowstart:=low(sarr);
  930. tmpstr:='';
  931. pdest:=@tmpstr
  932. end
  933. else
  934. begin
  935. { Start with empty DestS if we start with concatting
  936. the first array element }
  937. if lowstart=low(sarr) then
  938. DestS:='';
  939. pdest:=@DestS;
  940. end;
  941. { Concat all strings, except the string we already
  942. copied in DestS }
  943. Len:=length(pdest^);
  944. for i:=lowstart to high(sarr) do
  945. begin
  946. p:=sarr[i];
  947. if assigned(p) then
  948. begin
  949. s2l:=length(p^);
  950. if Len+s2l>high(dests) then
  951. s2l:=high(dests)-Len;
  952. fpc_shortstr_shortstr_intern_charmove(p^,1,pdest^,Len+1,s2l);
  953. inc(Len,s2l);
  954. end;
  955. end;
  956. pdest^[0]:=Chr(Len);
  957. if needtemp then
  958. DestS:=TmpStr;
  959. end;
  960. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  961. {$pop}
  962. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  963. procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring);compilerproc;
  964. [public,alias:'FPC_SHORTSTR_APPEND_SHORTSTR'];
  965. var
  966. s1l, s2l : sizeint;
  967. begin
  968. s1l:=length(s1);
  969. s2l:=length(s2);
  970. if s1l+s2l>high(s1) then
  971. s2l:=high(s1)-s1l;
  972. move(s2[1],s1[s1l+1],s2l);
  973. s1[0]:=chr(s1l+s2l);
  974. end;
  975. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  976. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  977. function fpc_shortstr_compare(const left,right:shortstring) : longint;[public,alias:'FPC_SHORTSTR_COMPARE']; compilerproc;
  978. var
  979. s1,s2,max,i : byte;
  980. d : ObjpasInt;
  981. begin
  982. s1:=length(left);
  983. s2:=length(right);
  984. if s1<s2 then
  985. max:=s1
  986. else
  987. max:=s2;
  988. for i:=1 to max do
  989. begin
  990. d:=byte(left[i])-byte(right[i]);
  991. if d>0 then
  992. exit(1)
  993. else if d<0 then
  994. exit(-1);
  995. end;
  996. if s1>s2 then
  997. exit(1)
  998. else if s1<s2 then
  999. exit(-1)
  1000. else
  1001. exit(0);
  1002. end;
  1003. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  1004. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE_EQUAL}
  1005. function fpc_shortstr_compare_equal(const left,right:shortstring): longint; [public,alias:'FPC_SHORTSTR_COMPARE_EQUAL']; compilerproc;
  1006. begin
  1007. Result := ObjpasInt(left[0]) - ObjpasInt(right[0]);
  1008. if Result = 0 then
  1009. Result := CompareByte(left[1],right[1], ObjpasInt(left[0]));
  1010. end;
  1011. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE_EQUAL}
  1012. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  1013. procedure fpc_pchar_to_shortstr(out res : shortstring;p:pchar);[public,alias:'FPC_PCHAR_TO_SHORTSTR']; compilerproc;
  1014. var
  1015. l : ObjpasInt;
  1016. s: shortstring;
  1017. begin
  1018. if p=nil then
  1019. l:=0
  1020. else
  1021. l:=strlen(p);
  1022. if l>high(res) then
  1023. l:=high(res);
  1024. if l>0 then
  1025. move(p^,s[1],l);
  1026. s[0]:=chr(l);
  1027. res:=s;
  1028. end;
  1029. {$endif ndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  1030. {$ifndef cpujvm}
  1031. { also define alias which can be used inside the system unit }
  1032. procedure fpc_pchar_to_shortstr(out res : shortstring;p:pchar);[external name 'FPC_PCHAR_TO_SHORTSTR'];
  1033. function strpas(p:pchar):shortstring;{$ifdef SYSTEMINLINE}inline;{$endif}
  1034. begin
  1035. fpc_pchar_to_shortstr(result,p);
  1036. end;
  1037. {$endif not cpujvm}
  1038. function Utf8CodePointLen(P: PAnsiChar; MaxLookAhead: SizeInt; IncludeCombiningDiacriticalMarks: Boolean): SizeInt;
  1039. var
  1040. bytes: sizeint;
  1041. firstzerobit: byte;
  1042. begin
  1043. { see https://en.wikipedia.org/wiki/UTF-8#Description for details }
  1044. if maxlookahead<=0 then
  1045. begin
  1046. { incomplete }
  1047. result:=0;
  1048. exit;
  1049. end;
  1050. { include the first byte }
  1051. result:=1;
  1052. { multiple byte utf-8 code point? }
  1053. if p[0]>#127 then
  1054. begin
  1055. { bsr searches for the leftmost 1 bit. We are interested in the
  1056. leftmost 0 bit, so first invert the value
  1057. }
  1058. firstzerobit:=bsrbyte(not(byte(p[0])));
  1059. { if there is no zero bit or the first zero bit is the rightmost bit
  1060. (bit 0), this is an invalid UTF-8 byte ($ff cannot appear in an
  1061. UTF-8-encoded string, and in the worst case bit 1 has to be zero)
  1062. Additionally, 5-byte UTF-8 sequences don't exist either, so bit 1
  1063. cannot be the first zero-bit either. And bits 6 and 7 can't be 0
  1064. either in the first byte.
  1065. }
  1066. if (firstzerobit<=1) or (firstzerobit>=6) then
  1067. begin
  1068. result:=-result;
  1069. exit;
  1070. end;
  1071. { the number of bytes belonging to this code point is
  1072. 7-(pos first 0-bit). Subtract 1 since we're already at the first
  1073. byte. All subsequent bytes of the same sequence must have their
  1074. highest bit set and the next one unset. We stop when we detect an
  1075. invalid sequence.
  1076. }
  1077. bytes:=6-firstzerobit;
  1078. while (result<maxlookahead) and
  1079. (bytes>0) and
  1080. ((ord(p[result]) and %11000000)=%10000000) do
  1081. begin
  1082. inc(result);
  1083. dec(bytes);
  1084. end;
  1085. { stopped because of invalid/incomplete sequence -> exit }
  1086. if bytes<>0 then
  1087. begin
  1088. if result>=maxlookahead then
  1089. result:=0
  1090. else
  1091. result:=-result;
  1092. exit;
  1093. end;
  1094. end;
  1095. if includecombiningdiacriticalmarks then
  1096. begin
  1097. { combining diacritical marks?
  1098. 1) U+0300 - U+036F in UTF-8 = %11001100 10000000 - %11001101 10101111
  1099. 2) U+1AB0 - U+1AFF in UTF-8 = %11100001 10101010 10110000 - %11100001 10101011 10111111
  1100. 3) U+1DC0 - U+1DFF in UTF-8 = %11100001 10110111 10000000 - %11100001 10110111 10111111
  1101. 4) U+20D0 - U+20FF in UTF-8 = %11100010 10000011 10010000 - %11100010 10000011 10111111
  1102. 5) U+FE20 - U+FE2F in UTF-8 = %11101111 10111000 10100000 - %11101111 10111000 10101111
  1103. }
  1104. repeat
  1105. bytes:=result;
  1106. if result+1<maxlookahead then
  1107. begin
  1108. { case 1) }
  1109. if ((ord(p[result]) and %11001100=%11001100)) and
  1110. (ord(p[result+1])>=%10000000) and
  1111. (ord(p[result+1])<=%10101111) then
  1112. inc(result,2)
  1113. { case 2), 3), 4), 5) }
  1114. else if (result+2<maxlookahead) and
  1115. (ord(p[result])>=%11100001) then
  1116. begin
  1117. { case 2) }
  1118. if ((ord(p[result])=%11100001) and
  1119. (ord(p[result+1])=%10101010) and
  1120. (ord(p[result+2])>=%10110000) and
  1121. (ord(p[result+2])<=%10111111)) or
  1122. { case 3) }
  1123. ((ord(p[result])=%11100001) and
  1124. (ord(p[result+1])=%10110111) and
  1125. (ord(p[result+2])>=%10000000) and
  1126. (ord(p[result+2])<=%10111111)) or
  1127. { case 4) }
  1128. ((ord(p[result])=%11100010) and
  1129. (ord(p[result+1])=%10000011) and
  1130. (ord(p[result+2])>=%10010000) and
  1131. (ord(p[result+2])<=%10111111)) or
  1132. { case 5) }
  1133. ((ord(p[result])=%11101111) and
  1134. (ord(p[result+1])=%10111000) and
  1135. (ord(p[result+2])>=%10100000) and
  1136. (ord(p[result+2])<=%10101111)) then
  1137. inc(result,3);
  1138. end;
  1139. end;
  1140. until bytes=result;
  1141. { is there an incomplete diacritical mark? (invalid makes little sense:
  1142. either a sequence is a combining diacritical mark, or it's not ; if
  1143. it's invalid, it may also not have been a combining diacritical mark)
  1144. }
  1145. if result<maxlookahead then
  1146. begin
  1147. { case 1) }
  1148. if (((ord(p[result]) and %11001100=%11001100)) and
  1149. (result+1>=maxlookahead)) or
  1150. { case 2) and 3)}
  1151. ((ord(p[result])=%11100001) and
  1152. ((result+1>=maxlookahead) or
  1153. (((ord(p[result+1])=%10101010) or
  1154. (ord(p[result+1])=%10110111)) and
  1155. (result+2>=maxlookahead)))) or
  1156. { case 4 }
  1157. ((ord(p[result])=%11100010) and
  1158. ((result+1>=maxlookahead) or
  1159. ((ord(p[result+1])=%10000011) and
  1160. (result+2>=maxlookahead)))) or
  1161. { case 5 }
  1162. ((ord(p[result])=%11101111) and
  1163. ((result+1>=maxlookahead) or
  1164. ((ord(p[result+1])=%10111000) and
  1165. (result+2>=maxlookahead)))) then
  1166. begin
  1167. result:=0;
  1168. exit;
  1169. end;
  1170. end;
  1171. end;
  1172. end;
  1173. {$ifndef FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  1174. procedure fpc_chararray_to_shortstr(out res : shortstring;const arr: array of char; zerobased: boolean = true);[public,alias:'FPC_CHARARRAY_TO_SHORTSTR']; compilerproc;
  1175. var
  1176. l: ObjpasInt;
  1177. index: ObjpasInt;
  1178. len: byte;
  1179. begin
  1180. l:=high(arr)+1;
  1181. if l>=high(res)+1 then
  1182. l:=high(res)
  1183. else if l<0 then
  1184. l:=0;
  1185. if zerobased then
  1186. begin
  1187. index:=IndexByte(arr[0],l,0);
  1188. if index<0 then
  1189. len:=l
  1190. else
  1191. len:=index;
  1192. end
  1193. else
  1194. len:=l;
  1195. move(arr[0],res[1],len);
  1196. res[0]:=chr(len);
  1197. end;
  1198. {$endif ndef FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  1199. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_TO_CHARARRAY}
  1200. procedure fpc_shortstr_to_chararray(out res: array of char; const src: ShortString); compilerproc;
  1201. var
  1202. len: ObjpasInt;
  1203. begin
  1204. len := length(src);
  1205. if len > length(res) then
  1206. len := length(res);
  1207. {$push}{$r-}
  1208. { make sure we don't access char 1 if length is 0 (JM) }
  1209. if len > 0 then
  1210. move(src[1],res[0],len);
  1211. fillchar(res[len],length(res)-len,0);
  1212. {$pop}
  1213. end;
  1214. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_TO_CHARARRAY}
  1215. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  1216. function fpc_pchar_length(p:pchar):sizeint;[public,alias:'FPC_PCHAR_LENGTH']; compilerproc;
  1217. begin
  1218. if assigned(p) then
  1219. Result:=IndexByte(p^,high(Result),0)
  1220. else
  1221. Result:=0;
  1222. end;
  1223. {$endif ndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  1224. {$ifndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  1225. function fpc_pwidechar_length(p:pwidechar):sizeint;[public,alias:'FPC_PWIDECHAR_LENGTH']; compilerproc;
  1226. var i : sizeint;
  1227. begin
  1228. i:=0;
  1229. if assigned(p) then
  1230. while p[i]<>#0 do
  1231. inc(i);
  1232. exit(i);
  1233. end;
  1234. {$endif ndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  1235. {****************************************************************************
  1236. Caller/StackFrame Helpers
  1237. ****************************************************************************}
  1238. {$ifndef FPC_SYSTEM_HAS_GET_FRAME}
  1239. {_$error Get_frame must be defined for each processor }
  1240. {$endif ndef FPC_SYSTEM_HAS_GET_FRAME}
  1241. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  1242. {_$error Get_caller_addr must be defined for each processor }
  1243. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  1244. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  1245. {_$error Get_caller_frame must be defined for each processor }
  1246. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  1247. {****************************************************************************
  1248. Math
  1249. ****************************************************************************}
  1250. {****************************************************************************
  1251. Software multiplication
  1252. ****************************************************************************}
  1253. {$ifdef FPC_INCLUDE_SOFTWARE_MUL}
  1254. {$ifdef VER3_0}
  1255. {$ifndef FPC_SYSTEM_HAS_MUL_INTEGER}
  1256. function fpc_mul_integer(f1,f2 : integer;checkoverflow : boolean) : integer;[public,alias: 'FPC_MUL_INTEGER']; compilerproc;
  1257. var
  1258. sign : boolean;
  1259. q1,q2,q3 : word;
  1260. begin
  1261. { there's no difference between signed and unsigned multiplication,
  1262. when the destination size is equal to the source size and overflow
  1263. checking is off }
  1264. if not checkoverflow then
  1265. { word(f1)*word(f2) is coded as a call to mulword }
  1266. fpc_mul_integer:=integer(word(f1)*word(f2))
  1267. else
  1268. begin
  1269. sign:=false;
  1270. if f1<0 then
  1271. begin
  1272. sign:=not(sign);
  1273. q1:=word(-f1);
  1274. end
  1275. else
  1276. q1:=f1;
  1277. if f2<0 then
  1278. begin
  1279. sign:=not(sign);
  1280. q2:=word(-f2);
  1281. end
  1282. else
  1283. q2:=f2;
  1284. { the q1*q2 is coded as call to mulword }
  1285. q3:=q1*q2;
  1286. if (q1 <> 0) and (q2 <>0) and
  1287. ((q1>q3) or (q2>q3) or
  1288. { the bit 63 can be only set if we have $8000 }
  1289. { and sign is true }
  1290. (q3 shr 15<>0) and
  1291. ((q3<>word(word(1) shl 15)) or not(sign))
  1292. ) then
  1293. HandleErrorAddrFrameInd(215,get_pc_addr,get_frame);
  1294. if sign then
  1295. fpc_mul_integer:=-q3
  1296. else
  1297. fpc_mul_integer:=q3;
  1298. end;
  1299. end;
  1300. {$endif FPC_SYSTEM_HAS_MUL_INTEGER}
  1301. {$ifndef FPC_SYSTEM_HAS_MUL_WORD}
  1302. function fpc_mul_word(f1,f2 : word;checkoverflow : boolean) : word;[public,alias: 'FPC_MUL_WORD']; compilerproc;
  1303. var
  1304. _f1,bitpos : word;
  1305. f1overflowed : boolean;
  1306. begin
  1307. fpc_mul_word:=0;
  1308. bitpos:=1;
  1309. f1overflowed:=false;
  1310. while f1<>0 do
  1311. begin
  1312. if (f2 and bitpos)<>0 then
  1313. begin
  1314. _f1:=fpc_mul_word;
  1315. fpc_mul_word:=fpc_mul_word+f1;
  1316. { if one of the operands is greater than the result an
  1317. overflow occurs }
  1318. if checkoverflow and (f1overflowed or ((_f1<>0) and (f1<>0) and
  1319. ((_f1>fpc_mul_word) or (f1>fpc_mul_word)))) then
  1320. HandleErrorAddrFrameInd(215,get_pc_addr,get_frame);
  1321. end;
  1322. { when bootstrapping, we forget about overflow checking for qword :) }
  1323. f1overflowed:=f1overflowed or ((f1 and (1 shl 15))<>0);
  1324. f1:=f1 shl 1;
  1325. bitpos:=bitpos shl 1;
  1326. end;
  1327. end;
  1328. {$endif FPC_SYSTEM_HAS_MUL_WORD}
  1329. {$ifndef FPC_SYSTEM_HAS_MUL_LONGINT}
  1330. function fpc_mul_longint(f1,f2 : longint;checkoverflow : boolean) : longint;[public,alias: 'FPC_MUL_LONGINT']; compilerproc;
  1331. var
  1332. sign : boolean;
  1333. q1,q2,q3 : dword;
  1334. begin
  1335. { there's no difference between signed and unsigned multiplication,
  1336. when the destination size is equal to the source size and overflow
  1337. checking is off }
  1338. if not checkoverflow then
  1339. { dword(f1)*dword(f2) is coded as a call to muldword }
  1340. fpc_mul_longint:=longint(dword(f1)*dword(f2))
  1341. else
  1342. begin
  1343. sign:=false;
  1344. if f1<0 then
  1345. begin
  1346. sign:=not(sign);
  1347. q1:=dword(-f1);
  1348. end
  1349. else
  1350. q1:=f1;
  1351. if f2<0 then
  1352. begin
  1353. sign:=not(sign);
  1354. q2:=dword(-f2);
  1355. end
  1356. else
  1357. q2:=f2;
  1358. { the q1*q2 is coded as call to muldword }
  1359. q3:=q1*q2;
  1360. if (q1 <> 0) and (q2 <>0) and
  1361. ((q1>q3) or (q2>q3) or
  1362. { the bit 31 can be only set if we have $8000 0000 }
  1363. { and sign is true }
  1364. (q3 shr 15<>0) and
  1365. ((q3<>dword(dword(1) shl 31)) or not(sign))
  1366. ) then
  1367. HandleErrorAddrFrameInd(215,get_pc_addr,get_frame);
  1368. if sign then
  1369. fpc_mul_longint:=-q3
  1370. else
  1371. fpc_mul_longint:=q3;
  1372. end;
  1373. end;
  1374. {$endif FPC_SYSTEM_HAS_MUL_INTEGER}
  1375. {$ifndef FPC_SYSTEM_HAS_MUL_DWORD}
  1376. { multiplies two dwords
  1377. the longbool for checkoverflow avoids a misaligned stack
  1378. }
  1379. function fpc_mul_dword(f1,f2 : dword;checkoverflow : boolean) : dword;[public,alias: 'FPC_MUL_DWORD']; compilerproc;
  1380. var
  1381. _f1,bitpos : dword;
  1382. f1overflowed : boolean;
  1383. begin
  1384. fpc_mul_dword:=0;
  1385. bitpos:=1;
  1386. f1overflowed:=false;
  1387. while f1<>0 do
  1388. begin
  1389. if (f2 and bitpos)<>0 then
  1390. begin
  1391. _f1:=fpc_mul_dword;
  1392. fpc_mul_dword:=fpc_mul_dword+f1;
  1393. { if one of the operands is greater than the result an
  1394. overflow occurs }
  1395. if checkoverflow and (f1overflowed or ((_f1<>0) and (f1<>0) and
  1396. ((_f1>fpc_mul_dword) or (f1>fpc_mul_dword)))) then
  1397. HandleErrorAddrFrameInd(215,get_pc_addr,get_frame);
  1398. end;
  1399. { when bootstrapping, we forget about overflow checking for qword :) }
  1400. f1overflowed:=f1overflowed or ((f1 and (dword(1) shl 31))<>0);
  1401. f1:=f1 shl 1;
  1402. bitpos:=bitpos shl 1;
  1403. end;
  1404. end;
  1405. {$endif FPC_SYSTEM_HAS_MUL_DWORD}
  1406. {$else VER3_0}
  1407. {$ifndef FPC_SYSTEM_HAS_MUL_SHORTINT}
  1408. function fpc_mul_shortint(f1,f2 : shortint) : shortint;[public,alias: 'FPC_MUL_SHORTINT']; compilerproc;
  1409. begin
  1410. { there's no difference between signed and unsigned multiplication,
  1411. when the destination size is equal to the source size and overflow
  1412. checking is off }
  1413. { byte(f1) * byte(f2) is coded as a call to mul_byte }
  1414. fpc_mul_shortint := shortint(byte(f1) * byte(f2));
  1415. end;
  1416. function fpc_mul_shortint_checkoverflow(f1,f2 : shortint) : shortint;[public,alias: 'FPC_MUL_SHORTINT_CHECKOVERFLOW']; compilerproc;
  1417. var
  1418. sign : boolean;
  1419. q1,q2,q3 : byte;
  1420. begin
  1421. sign:=false;
  1422. if f1 < 0 then
  1423. begin
  1424. sign := not(sign);
  1425. q1 := byte(-f1);
  1426. end
  1427. else
  1428. q1 := f1;
  1429. if f2 < 0 then
  1430. begin
  1431. sign := not(sign);
  1432. q2 := byte(-f2);
  1433. end
  1434. else
  1435. q2 := f2;
  1436. { the q1*q2 is coded as call to mul_byte }
  1437. {$push}
  1438. {$Q+}
  1439. q3 := q1 * q2;
  1440. {$pop}
  1441. if (q1 <> 0) and (q2 <> 0) and
  1442. ((q1 > q3) or (q2 > q3) or
  1443. { the bit 7 can be only set if we have $80 }
  1444. { and sign is true }
  1445. (q3 shr 7 <> 0) and
  1446. ((q3 <> byte(byte(1) shl 7)) or not(sign))
  1447. ) then
  1448. FPC_Overflow();
  1449. if sign then
  1450. fpc_mul_shortint_checkoverflow := -q3
  1451. else
  1452. fpc_mul_shortint_checkoverflow := q3;
  1453. end;
  1454. {$endif FPC_SYSTEM_HAS_MUL_SHORTINT}
  1455. {$ifndef FPC_SYSTEM_HAS_MUL_BYTE}
  1456. function fpc_mul_byte(f1,f2 : byte) : byte;[public,alias: 'FPC_MUL_BYTE']; compilerproc;
  1457. var
  1458. v1,v2,res: byte;
  1459. begin
  1460. if f1<f2 then
  1461. begin
  1462. v1:=f1;
  1463. v2:=f2;
  1464. end
  1465. else
  1466. begin
  1467. v1:=f2;
  1468. v2:=f1;
  1469. end;
  1470. res:=0;
  1471. while v1<>0 do
  1472. begin
  1473. if v1 and 1<>0 then
  1474. inc(res,v2);
  1475. v2:=v2 shl 1;
  1476. v1:=v1 shr 1;
  1477. end;
  1478. fpc_mul_byte:=res;
  1479. end;
  1480. function fpc_mul_byte_checkoverflow(f1,f2 : byte) : byte;[public,alias: 'FPC_MUL_BYTE_CHECKOVERFLOW']; compilerproc;
  1481. var
  1482. _f1, bitpos : byte;
  1483. f1overflowed : boolean;
  1484. begin
  1485. fpc_mul_byte_checkoverflow := 0;
  1486. bitpos := 1;
  1487. f1overflowed := false;
  1488. while f1<>0 do
  1489. begin
  1490. if (f2 and bitpos) <> 0 then
  1491. begin
  1492. _f1 := fpc_mul_byte_checkoverflow;
  1493. fpc_mul_byte_checkoverflow := fpc_mul_byte_checkoverflow + f1;
  1494. { if one of the operands is greater than the result an
  1495. overflow occurs }
  1496. if f1overflowed or ((_f1 <> 0) and (f1 <> 0) and
  1497. ((_f1 > fpc_mul_byte_checkoverflow) or (f1 > fpc_mul_byte_checkoverflow))) then
  1498. FPC_Overflow();
  1499. end;
  1500. { when bootstrapping, we forget about overflow checking for qword :) }
  1501. f1overflowed := f1overflowed or ((f1 and (1 shl 7)) <> 0);
  1502. f1 := f1 shl 1;
  1503. bitpos := bitpos shl 1;
  1504. end;
  1505. end;
  1506. {$endif FPC_SYSTEM_HAS_MUL_BYTE}
  1507. {$ifndef FPC_SYSTEM_HAS_MUL_INTEGER}
  1508. function fpc_mul_integer(f1,f2 : integer) : integer;[public,alias: 'FPC_MUL_INTEGER']; compilerproc;
  1509. begin
  1510. { there's no difference between signed and unsigned multiplication,
  1511. when the destination size is equal to the source size and overflow
  1512. checking is off }
  1513. { word(f1)*word(f2) is coded as a call to mulword }
  1514. fpc_mul_integer:=integer(word(f1)*word(f2));
  1515. end;
  1516. function fpc_mul_integer_checkoverflow(f1,f2 : integer) : integer;[public,alias: 'FPC_MUL_INTEGER_CHECKOVERFLOW']; compilerproc;
  1517. var
  1518. sign : boolean;
  1519. q1,q2,q3 : word;
  1520. begin
  1521. sign:=false;
  1522. if f1<0 then
  1523. begin
  1524. sign:=not(sign);
  1525. q1:=word(-f1);
  1526. end
  1527. else
  1528. q1:=f1;
  1529. if f2<0 then
  1530. begin
  1531. sign:=not(sign);
  1532. q2:=word(-f2);
  1533. end
  1534. else
  1535. q2:=f2;
  1536. { the q1*q2 is coded as call to mulword }
  1537. {$push}
  1538. {$Q+}
  1539. q3:=q1*q2;
  1540. {$pop}
  1541. if (q1 <> 0) and (q2 <>0) and
  1542. ((q1>q3) or (q2>q3) or
  1543. { the bit 63 can be only set if we have $8000 }
  1544. { and sign is true }
  1545. (q3 shr 15<>0) and
  1546. ((q3<>word(word(1) shl 15)) or not(sign))
  1547. ) then
  1548. FPC_Overflow();
  1549. if sign then
  1550. fpc_mul_integer_checkoverflow:=-q3
  1551. else
  1552. fpc_mul_integer_checkoverflow:=q3;
  1553. end;
  1554. {$endif FPC_SYSTEM_HAS_MUL_INTEGER}
  1555. {$ifndef FPC_SYSTEM_HAS_MUL_WORD}
  1556. function fpc_mul_word(f1,f2 : word) : word;[public,alias: 'FPC_MUL_WORD']; compilerproc;
  1557. var
  1558. v1,v2,res: word;
  1559. begin
  1560. if f1<f2 then
  1561. begin
  1562. v1:=f1;
  1563. v2:=f2;
  1564. end
  1565. else
  1566. begin
  1567. v1:=f2;
  1568. v2:=f1;
  1569. end;
  1570. res:=0;
  1571. while v1<>0 do
  1572. begin
  1573. if ALUUInt(v1) and 1<>0 then
  1574. inc(res,v2);
  1575. v2:=v2 shl 1;
  1576. v1:=v1 shr 1;
  1577. end;
  1578. fpc_mul_word:=res;
  1579. end;
  1580. function fpc_mul_word_checkoverflow(f1,f2 : word) : word;[public,alias: 'FPC_MUL_WORD_CHECKOVERFLOW']; compilerproc;
  1581. var
  1582. _f1,bitpos : word;
  1583. f1overflowed : boolean;
  1584. begin
  1585. fpc_mul_word_checkoverflow:=0;
  1586. bitpos:=1;
  1587. f1overflowed:=false;
  1588. while f1<>0 do
  1589. begin
  1590. if (f2 and bitpos)<>0 then
  1591. begin
  1592. _f1:=fpc_mul_word_checkoverflow;
  1593. fpc_mul_word_checkoverflow:=fpc_mul_word_checkoverflow+f1;
  1594. { if one of the operands is greater than the result an
  1595. overflow occurs }
  1596. if f1overflowed or ((_f1<>0) and (f1<>0) and
  1597. ((_f1>fpc_mul_word_checkoverflow) or (f1>fpc_mul_word_checkoverflow))) then
  1598. FPC_Overflow();
  1599. end;
  1600. { when bootstrapping, we forget about overflow checking for qword :) }
  1601. f1overflowed:=f1overflowed or ((f1 and (1 shl 15))<>0);
  1602. f1:=f1 shl 1;
  1603. bitpos:=bitpos shl 1;
  1604. end;
  1605. end;
  1606. {$endif FPC_SYSTEM_HAS_MUL_WORD}
  1607. {$ifndef FPC_SYSTEM_HAS_MUL_LONGINT}
  1608. function fpc_mul_longint(f1,f2 : longint) : longint;[public,alias: 'FPC_MUL_LONGINT']; compilerproc;
  1609. begin
  1610. { there's no difference between signed and unsigned multiplication,
  1611. when the destination size is equal to the source size and overflow
  1612. checking is off }
  1613. { dword(f1)*dword(f2) is coded as a call to muldword }
  1614. fpc_mul_longint:=longint(dword(f1)*dword(f2));
  1615. end;
  1616. function fpc_mul_longint_checkoverflow(f1,f2 : longint) : longint;[public,alias: 'FPC_MUL_LONGINT_CHECKOVERFLOW']; compilerproc;
  1617. var
  1618. sign : boolean;
  1619. q1,q2,q3 : dword;
  1620. begin
  1621. sign:=false;
  1622. if f1<0 then
  1623. begin
  1624. sign:=not(sign);
  1625. q1:=dword(-f1);
  1626. end
  1627. else
  1628. q1:=f1;
  1629. if f2<0 then
  1630. begin
  1631. sign:=not(sign);
  1632. q2:=dword(-f2);
  1633. end
  1634. else
  1635. q2:=f2;
  1636. { the q1*q2 is coded as call to muldword }
  1637. {$push}
  1638. {$Q+}
  1639. q3:=q1*q2;
  1640. {$pop}
  1641. if (q1 <> 0) and (q2 <>0) and
  1642. ((q1>q3) or (q2>q3) or
  1643. { the bit 31 can be only set if we have $8000 0000 }
  1644. { and sign is true }
  1645. (q3 shr 31<>0) and
  1646. ((q3<>dword(dword(1) shl 31)) or not(sign))
  1647. ) then
  1648. FPC_Overflow();
  1649. if sign then
  1650. fpc_mul_longint_checkoverflow:=-q3
  1651. else
  1652. fpc_mul_longint_checkoverflow:=q3;
  1653. end;
  1654. {$endif FPC_SYSTEM_HAS_MUL_INTEGER}
  1655. {$ifndef FPC_SYSTEM_HAS_MUL_DWORD}
  1656. function fpc_mul_dword(f1,f2 : dword) : dword;[public,alias: 'FPC_MUL_DWORD']; compilerproc;
  1657. var
  1658. v1,v2,res: dword;
  1659. begin
  1660. if f1<f2 then
  1661. begin
  1662. v1:=f1;
  1663. v2:=f2;
  1664. end
  1665. else
  1666. begin
  1667. v1:=f2;
  1668. v2:=f1;
  1669. end;
  1670. res:=0;
  1671. while v1<>0 do
  1672. begin
  1673. if ALUUInt(v1) and 1<>0 then
  1674. inc(res,v2);
  1675. v2:=v2 shl 1;
  1676. v1:=v1 shr 1;
  1677. end;
  1678. fpc_mul_dword:=res;
  1679. end;
  1680. function fpc_mul_dword_checkoverflow(f1,f2 : dword) : dword;[public,alias: 'FPC_MUL_DWORD_CHECKOVERFLOW']; compilerproc;
  1681. var
  1682. _f1,bitpos : dword;
  1683. f1overflowed : boolean;
  1684. begin
  1685. fpc_mul_dword_checkoverflow:=0;
  1686. bitpos:=1;
  1687. f1overflowed:=false;
  1688. while f1<>0 do
  1689. begin
  1690. if (f2 and bitpos)<>0 then
  1691. begin
  1692. _f1:=fpc_mul_dword_checkoverflow;
  1693. fpc_mul_dword_checkoverflow:=fpc_mul_dword_checkoverflow+f1;
  1694. { if one of the operands is greater than the result an
  1695. overflow occurs }
  1696. if f1overflowed or ((_f1<>0) and (f1<>0) and
  1697. ((_f1>fpc_mul_dword_checkoverflow) or (f1>fpc_mul_dword_checkoverflow))) then
  1698. FPC_Overflow();
  1699. end;
  1700. { when bootstrapping, we forget about overflow checking for qword :) }
  1701. f1overflowed:=f1overflowed or ((f1 and (dword(1) shl 31))<>0);
  1702. f1:=f1 shl 1;
  1703. bitpos:=bitpos shl 1;
  1704. end;
  1705. end;
  1706. {$endif FPC_SYSTEM_HAS_MUL_DWORD}
  1707. {$endif VER3_0}
  1708. {$endif FPC_INCLUDE_SOFTWARE_MUL}
  1709. {****************************************************************************
  1710. Software longint/dword division
  1711. ****************************************************************************}
  1712. {$ifdef FPC_INCLUDE_SOFTWARE_MOD_DIV}
  1713. {$ifndef FPC_SYSTEM_HAS_DIV_DWORD}
  1714. function fpc_div_dword(n,z : dword) : dword; [public,alias: 'FPC_DIV_DWORD']; compilerproc;
  1715. var
  1716. shift,lzz,lzn : ObjpasInt;
  1717. begin
  1718. result:=0;
  1719. if n=0 then
  1720. HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
  1721. if z=0 then
  1722. exit;
  1723. lzz:=BsrDWord(z);
  1724. lzn:=BsrDWord(n);
  1725. { if the denominator contains less zeros
  1726. then the numerator
  1727. then d is greater than the n }
  1728. if lzn>lzz then
  1729. exit;
  1730. shift:=lzz-lzn;
  1731. n:=n shl shift;
  1732. for shift:=shift downto 0 do
  1733. begin
  1734. if z>=n then
  1735. begin
  1736. z:=z-n;
  1737. result:=result+dword(dword(1) shl shift);
  1738. end;
  1739. n:=n shr 1;
  1740. end;
  1741. end;
  1742. {$endif FPC_SYSTEM_HAS_DIV_DWORD}
  1743. {$ifndef FPC_SYSTEM_HAS_MOD_DWORD}
  1744. function fpc_mod_dword(n,z : dword) : dword; [public,alias: 'FPC_MOD_DWORD']; compilerproc;
  1745. var
  1746. shift,lzz,lzn : ObjpasInt;
  1747. begin
  1748. result:=0;
  1749. if n=0 then
  1750. HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
  1751. if z=0 then
  1752. exit;
  1753. lzz:=BsrDWord(z);
  1754. lzn:=BsrDWord(n);
  1755. { if the denominator contains less zeros
  1756. then the numerator
  1757. then d is greater than the n }
  1758. if lzn>lzz then
  1759. begin
  1760. result:=z;
  1761. exit;
  1762. end;
  1763. shift:=lzz-lzn;
  1764. n:=n shl shift;
  1765. for shift:=shift downto 0 do
  1766. begin
  1767. if z>=n then
  1768. z:=z-n;
  1769. n:=n shr 1;
  1770. end;
  1771. result:=z;
  1772. end;
  1773. {$endif FPC_SYSTEM_HAS_MOD_DWORD}
  1774. {$ifndef FPC_SYSTEM_HAS_DIV_WORD}
  1775. function fpc_div_word(n,z : word) : word; [public,alias: 'FPC_DIV_WORD']; compilerproc;
  1776. var
  1777. shift,lzz,lzn : Byte;
  1778. begin
  1779. result:=0;
  1780. if n=0 then
  1781. HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
  1782. if z=0 then
  1783. exit;
  1784. lzz:=BsrWord(z);
  1785. lzn:=BsrWord(n);
  1786. { if the denominator contains less zeros
  1787. then the numerator
  1788. then d is greater than the n }
  1789. if lzn>lzz then
  1790. exit;
  1791. shift:=lzz-lzn;
  1792. n:=n shl shift;
  1793. for shift:=shift downto 0 do
  1794. begin
  1795. if z>=n then
  1796. begin
  1797. z:=z-n;
  1798. result:=result+word(word(1) shl shift);
  1799. end;
  1800. n:=n shr 1;
  1801. end;
  1802. end;
  1803. {$endif FPC_SYSTEM_HAS_DIV_WORD}
  1804. {$ifndef FPC_SYSTEM_HAS_MOD_WORD}
  1805. function fpc_mod_word(n,z : word) : word; [public,alias: 'FPC_MOD_WORD']; compilerproc;
  1806. var
  1807. shift,lzz,lzn : Byte;
  1808. begin
  1809. result:=0;
  1810. if n=0 then
  1811. HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
  1812. if z=0 then
  1813. exit;
  1814. lzz:=BsrWord(z);
  1815. lzn:=BsrWord(n);
  1816. { if the denominator contains less zeros
  1817. then the numerator
  1818. then d is greater than the n }
  1819. if lzn>lzz then
  1820. begin
  1821. result:=z;
  1822. exit;
  1823. end;
  1824. shift:=lzz-lzn;
  1825. n:=n shl shift;
  1826. for shift:=shift downto 0 do
  1827. begin
  1828. if z>=n then
  1829. z:=z-n;
  1830. n:=n shr 1;
  1831. end;
  1832. result:=z;
  1833. end;
  1834. {$endif FPC_SYSTEM_HAS_MOD_WORD}
  1835. {$ifndef FPC_SYSTEM_HAS_DIV_BYTE}
  1836. function fpc_div_byte(n,z : byte) : byte; [public,alias: 'FPC_DIV_BYTE']; compilerproc;
  1837. var
  1838. shift,lzz,lzn : Byte;
  1839. begin
  1840. result:=0;
  1841. if n=0 then
  1842. HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
  1843. if z=0 then
  1844. exit;
  1845. lzz:=BsrByte(z);
  1846. lzn:=BsrByte(n);
  1847. { if the denominator contains less zeros
  1848. then the numerator
  1849. then d is greater than the n }
  1850. if lzn>lzz then
  1851. exit;
  1852. shift:=lzz-lzn;
  1853. n:=n shl shift;
  1854. for shift:=shift downto 0 do
  1855. begin
  1856. if z>=n then
  1857. begin
  1858. z:=z-n;
  1859. result:=result+byte(byte(1) shl shift);
  1860. end;
  1861. n:=n shr 1;
  1862. end;
  1863. end;
  1864. {$endif FPC_SYSTEM_HAS_DIV_BYTE}
  1865. {$ifndef FPC_SYSTEM_HAS_MOD_BYTE}
  1866. function fpc_mod_byte(n,z : byte) : byte; [public,alias: 'FPC_MOD_BYTE']; compilerproc;
  1867. var
  1868. shift,lzz,lzn : Byte;
  1869. begin
  1870. result:=0;
  1871. if n=0 then
  1872. HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
  1873. if z=0 then
  1874. exit;
  1875. lzz:=BsrByte(z);
  1876. lzn:=BsrByte(n);
  1877. { if the denominator contains less zeros
  1878. then the numerator
  1879. then d is greater than the n }
  1880. if lzn>lzz then
  1881. begin
  1882. result:=z;
  1883. exit;
  1884. end;
  1885. shift:=lzz-lzn;
  1886. n:=n shl shift;
  1887. for shift:=shift downto 0 do
  1888. begin
  1889. if z>=n then
  1890. z:=z-n;
  1891. n:=n shr 1;
  1892. end;
  1893. result:=z;
  1894. end;
  1895. {$endif FPC_SYSTEM_HAS_MOD_BYTE}
  1896. {$ifndef FPC_SYSTEM_HAS_DIV_LONGINT}
  1897. function fpc_div_longint(n,z : longint) : longint; [public,alias: 'FPC_DIV_LONGINT']; compilerproc;
  1898. var
  1899. sign : boolean;
  1900. d1,d2 : dword;
  1901. begin
  1902. if n=0 then
  1903. HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
  1904. sign:=false;
  1905. if z<0 then
  1906. begin
  1907. sign:=not(sign);
  1908. d1:=dword(-z);
  1909. end
  1910. else
  1911. d1:=z;
  1912. if n<0 then
  1913. begin
  1914. sign:=not(sign);
  1915. d2:=dword(-n);
  1916. end
  1917. else
  1918. d2:=n;
  1919. { the div is coded by the compiler as call to divdword }
  1920. if sign then
  1921. result:=-(d1 div d2)
  1922. else
  1923. result:=d1 div d2;
  1924. end;
  1925. {$endif FPC_SYSTEM_HAS_DIV_LONGINT}
  1926. {$ifndef FPC_SYSTEM_HAS_MOD_LONGINT}
  1927. function fpc_mod_longint(n,z : longint) : longint; [public,alias: 'FPC_MOD_LONGINT']; compilerproc;
  1928. var
  1929. signed : boolean;
  1930. r,nq,zq : dword;
  1931. begin
  1932. if n=0 then
  1933. HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
  1934. nq:=abs(n);
  1935. if z<0 then
  1936. begin
  1937. zq:=dword(-z);
  1938. signed:=true;
  1939. end
  1940. else
  1941. begin
  1942. zq:=z;
  1943. signed:=false;
  1944. end;
  1945. r:=zq mod nq;
  1946. if signed then
  1947. result:=-longint(r)
  1948. else
  1949. result:=r;
  1950. end;
  1951. {$endif FPC_SYSTEM_HAS_MOD_LONGINT}
  1952. {$ifndef FPC_SYSTEM_HAS_DIV_SMALLINT}
  1953. function fpc_div_smallint(n,z : smallint) : smallint; [public,alias: 'FPC_DIV_SMALLINT']; compilerproc;
  1954. var
  1955. sign : boolean;
  1956. w1,w2 : word;
  1957. begin
  1958. if n=0 then
  1959. HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
  1960. sign:=false;
  1961. if z<0 then
  1962. begin
  1963. sign:=not(sign);
  1964. w1:=word(-z);
  1965. end
  1966. else
  1967. w1:=z;
  1968. if n<0 then
  1969. begin
  1970. sign:=not(sign);
  1971. w2:=word(-n);
  1972. end
  1973. else
  1974. w2:=n;
  1975. { the div is coded by the compiler as call to divdword }
  1976. if sign then
  1977. result:=-(w1 div w2)
  1978. else
  1979. result:=w1 div w2;
  1980. end;
  1981. {$endif FPC_SYSTEM_HAS_DIV_SMALLINT}
  1982. {$ifndef FPC_SYSTEM_HAS_MOD_SMALLINT}
  1983. function fpc_mod_smallint(n,z : smallint) : smallint; [public,alias: 'FPC_MOD_SMALLINT']; compilerproc;
  1984. var
  1985. signed : boolean;
  1986. r,nq,zq : word;
  1987. begin
  1988. if n=0 then
  1989. HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
  1990. nq:=abs(n);
  1991. if z<0 then
  1992. begin
  1993. zq:=word(-z);
  1994. signed:=true;
  1995. end
  1996. else
  1997. begin
  1998. zq:=z;
  1999. signed:=false;
  2000. end;
  2001. r:=zq mod nq;
  2002. if signed then
  2003. result:=-smallint(r)
  2004. else
  2005. result:=r;
  2006. end;
  2007. {$endif FPC_SYSTEM_HAS_MOD_SMALLINT}
  2008. {$ifndef FPC_SYSTEM_HAS_DIV_SHORTINT}
  2009. function fpc_div_shortint(n,z : shortint) : shortint; [public,alias: 'FPC_DIV_SHORTINT']; compilerproc;
  2010. var
  2011. sign : boolean;
  2012. b1,b2 : byte;
  2013. begin
  2014. if n=0 then
  2015. HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
  2016. sign:=false;
  2017. if z<0 then
  2018. begin
  2019. sign:=not(sign);
  2020. b1:=byte(-z);
  2021. end
  2022. else
  2023. b1:=z;
  2024. if n<0 then
  2025. begin
  2026. sign:=not(sign);
  2027. b2:=byte(-n);
  2028. end
  2029. else
  2030. b2:=n;
  2031. { the div is coded by the compiler as call to divdword }
  2032. if sign then
  2033. result:=-(b1 div b2)
  2034. else
  2035. result:=b1 div b2;
  2036. end;
  2037. {$endif FPC_SYSTEM_HAS_DIV_SHORTINT}
  2038. {$ifndef FPC_SYSTEM_HAS_MOD_SHORTINT}
  2039. function fpc_mod_shortint(n,z : shortint) : shortint; [public,alias: 'FPC_MOD_SHORTINT']; compilerproc;
  2040. var
  2041. signed : boolean;
  2042. r,nq,zq : byte;
  2043. begin
  2044. if n=0 then
  2045. HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
  2046. nq:=abs(n);
  2047. if z<0 then
  2048. begin
  2049. zq:=byte(-z);
  2050. signed:=true;
  2051. end
  2052. else
  2053. begin
  2054. zq:=z;
  2055. signed:=false;
  2056. end;
  2057. r:=zq mod nq;
  2058. if signed then
  2059. result:=-shortint(r)
  2060. else
  2061. result:=r;
  2062. end;
  2063. {$endif FPC_SYSTEM_HAS_MOD_SHORTINT}
  2064. {$endif FPC_INCLUDE_SOFTWARE_MOD_DIV}
  2065. {****************************************************************************}
  2066. {$if defined(CPUINT8)}
  2067. {$ifndef FPC_SYSTEM_HAS_ABS_SHORTINT}
  2068. function abs(l:shortint):shortint;{$ifdef SYSTEMINLINE}inline;{$endif}
  2069. begin
  2070. if l<0 then
  2071. abs:=-l
  2072. else
  2073. abs:=l;
  2074. end;
  2075. {$endif not FPC_SYSTEM_HAS_ABS_SMALLINT}
  2076. {$endif CPUINT8}
  2077. {$if defined(CPUINT16) or defined(CPUINT8)}
  2078. {$ifndef FPC_SYSTEM_HAS_ABS_SMALLINT}
  2079. function abs(l:smallint):smallint;{$ifdef SYSTEMINLINE}inline;{$endif}
  2080. begin
  2081. if l<0 then
  2082. abs:=-l
  2083. else
  2084. abs:=l;
  2085. end;
  2086. {$endif not FPC_SYSTEM_HAS_ABS_SMALLINT}
  2087. {$endif CPUINT16 or CPUINT8}
  2088. {$ifndef FPC_SYSTEM_HAS_ABS_LONGINT}
  2089. { This is only needed to bootstrap on SPARC targets
  2090. (MIPS and m68k too, but they have no releases, so bootstrapping is not an issue) }
  2091. function abs(l:longint):longint;{$ifdef SYSTEMINLINE}inline;{$endif}
  2092. begin
  2093. if l<0 then
  2094. abs:=-l
  2095. else
  2096. abs:=l;
  2097. end;
  2098. {$endif not FPC_SYSTEM_HAS_ABS_LONGINT}
  2099. {$if defined(CPUINT8)}
  2100. {$ifndef FPC_SYSTEM_HAS_ODD_SHORTINT}
  2101. function odd(l:shortint):Boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  2102. begin
  2103. odd:=boolean(l and 1);
  2104. end;
  2105. {$endif ndef FPC_SYSTEM_HAS_ODD_SHORTINT}
  2106. {$ifndef FPC_SYSTEM_HAS_ODD_BYTE}
  2107. function odd(l:byte):Boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  2108. begin
  2109. odd:=boolean(l and 1);
  2110. end;
  2111. {$endif ndef FPC_SYSTEM_HAS_ODD_BYTE}
  2112. {$endif CPUINT8}
  2113. {$if defined(CPUINT16) or defined(CPUINT8)}
  2114. {$ifndef FPC_SYSTEM_HAS_ODD_SMALLINT}
  2115. function odd(l:smallint):Boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  2116. begin
  2117. odd:=boolean(l and 1);
  2118. end;
  2119. {$endif ndef FPC_SYSTEM_HAS_ODD_SMALLINT}
  2120. {$ifndef FPC_SYSTEM_HAS_ODD_WORD}
  2121. function odd(l:word):Boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  2122. begin
  2123. odd:=boolean(l and 1);
  2124. end;
  2125. {$endif ndef FPC_SYSTEM_HAS_ODD_WORD}
  2126. {$endif CPUINT16 or CPUINT8}
  2127. {$ifndef FPC_SYSTEM_HAS_ODD_LONGINT}
  2128. function odd(l:longint):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  2129. begin
  2130. odd:=boolean(l and 1);
  2131. end;
  2132. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGINT}
  2133. {$ifndef FPC_SYSTEM_HAS_ODD_LONGWORD}
  2134. function odd(l:longword):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  2135. begin
  2136. odd:=boolean(l and 1);
  2137. end;
  2138. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGWORD}
  2139. {$ifndef FPC_SYSTEM_HAS_ODD_INT64}
  2140. function odd(l:int64):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  2141. begin
  2142. odd:=boolean(longint(l) and 1);
  2143. end;
  2144. {$endif ndef FPC_SYSTEM_HAS_ODD_INT64}
  2145. {$ifndef FPC_SYSTEM_HAS_ODD_QWORD}
  2146. function odd(l:qword):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  2147. begin
  2148. odd:=boolean(longint(l) and 1);
  2149. end;
  2150. {$endif ndef FPC_SYSTEM_HAS_ODD_QWORD}
  2151. {$if defined(CPUINT8)}
  2152. {$ifndef FPC_SYSTEM_HAS_SQR_SHORTINT}
  2153. function sqr(l:shortint):shortint;{$ifdef SYSTEMINLINE}inline;{$endif}
  2154. begin
  2155. sqr:=l*l;
  2156. end;
  2157. {$endif ndef FPC_SYSTEM_HAS_SQR_SHORTINT}
  2158. {$endif CPUINT8}
  2159. {$if defined(CPUINT16) or defined(CPUINT8)}
  2160. {$ifndef FPC_SYSTEM_HAS_SQR_SMALLINT}
  2161. function sqr(l:smallint):smallint;{$ifdef SYSTEMINLINE}inline;{$endif}
  2162. begin
  2163. sqr:=l*l;
  2164. end;
  2165. {$endif ndef FPC_SYSTEM_HAS_SQR_SMALLINT}
  2166. {$endif CPUINT16 or CPUINT8}
  2167. {$ifndef FPC_SYSTEM_HAS_SQR_LONGINT}
  2168. function sqr(l:longint):longint;{$ifdef SYSTEMINLINE}inline;{$endif}
  2169. begin
  2170. sqr:=l*l;
  2171. end;
  2172. {$endif ndef FPC_SYSTEM_HAS_SQR_LONGINT}
  2173. {$ifndef FPC_SYSTEM_HAS_ABS_INT64}
  2174. function abs(l: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  2175. begin
  2176. if l < 0 then
  2177. abs := -l
  2178. else
  2179. abs := l;
  2180. end;
  2181. {$endif ndef FPC_SYSTEM_HAS_ABS_INT64}
  2182. {$ifndef FPC_SYSTEM_HAS_SQR_INT64}
  2183. function sqr(l: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  2184. begin
  2185. sqr := l*l;
  2186. end;
  2187. {$endif ndef FPC_SYSTEM_HAS_SQR_INT64}
  2188. {$ifndef FPC_SYSTEM_HAS_SQR_QWORD}
  2189. function sqr(l: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2190. begin
  2191. sqr := l*l;
  2192. end;
  2193. {$endif ndef FPC_SYSTEM_HAS_SQR_INT64}
  2194. {$ifdef CPU16}
  2195. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_SMALLINT}
  2196. function declocked(var l:smallint):boolean;
  2197. begin
  2198. Dec(l);
  2199. declocked:=(l=0);
  2200. end;
  2201. {$endif FPC_SYSTEM_HAS_DECLOCKED_SMALLINT}
  2202. {$endif CPU16}
  2203. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  2204. function declocked(var l:longint):boolean;
  2205. begin
  2206. Dec(l);
  2207. declocked:=(l=0);
  2208. end;
  2209. {$endif FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  2210. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_INT64}
  2211. function declocked(var l:int64):boolean;
  2212. begin
  2213. Dec(l);
  2214. declocked:=(l=0);
  2215. end;
  2216. {$endif FPC_SYSTEM_HAS_DECLOCKED_INT64}
  2217. {$ifdef CPU16}
  2218. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_SMALLINT}
  2219. procedure inclocked(var l:smallint);
  2220. begin
  2221. Inc(l);
  2222. end;
  2223. {$endif FPC_SYSTEM_HAS_INCLOCKED_SMALLINT}
  2224. {$endif CPU16}
  2225. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  2226. procedure inclocked(var l:longint);
  2227. begin
  2228. Inc(l);
  2229. end;
  2230. {$endif FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  2231. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_INT64}
  2232. procedure inclocked(var l:int64);
  2233. begin
  2234. Inc(l);
  2235. end;
  2236. {$endif FPC_SYSTEM_HAS_INCLOCKED_INT64}
  2237. {$ifndef FPC_SYSTEM_HAS_SPTR}
  2238. {_$error Sptr must be defined for each processor }
  2239. {$endif ndef FPC_SYSTEM_HAS_SPTR}
  2240. {****************************************************************************
  2241. Str()
  2242. ****************************************************************************}
  2243. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  2244. procedure int_str(l:longint;out s:shortstring);
  2245. var
  2246. m,m1 : longword;
  2247. pcstart,
  2248. pc2start,
  2249. pc,pc2 : pchar;
  2250. hs : string[32];
  2251. overflow : longint;
  2252. begin
  2253. pc2start:=@s[1];
  2254. pc2:=pc2start;
  2255. if (l<0) then
  2256. begin
  2257. pc2^:='-';
  2258. inc(pc2);
  2259. m:=longword(-l);
  2260. end
  2261. else
  2262. m:=longword(l);
  2263. pcstart:=pchar(@hs[0]);
  2264. pc:=pcstart;
  2265. repeat
  2266. m1:=m div 10;
  2267. inc(pc);
  2268. pc^:=char(m-(m1*10)+byte('0'));
  2269. m:=m1;
  2270. until m=0;
  2271. overflow:=(pc-pcstart)+(pc2-pc2start)-high(s);
  2272. if overflow>0 then
  2273. inc(pcstart,overflow);
  2274. while (pc>pcstart) do
  2275. begin
  2276. pc2^:=pc^;
  2277. inc(pc2);
  2278. dec(pc);
  2279. end;
  2280. s[0]:=char(pc2-pc2start);
  2281. end;
  2282. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  2283. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  2284. procedure int_str_unsigned(l:longword;out s:shortstring);
  2285. var
  2286. m1 : longword;
  2287. pcstart,
  2288. pc2start,
  2289. pc,pc2 : pchar;
  2290. hs : string[32];
  2291. overflow : longint;
  2292. begin
  2293. pc2start:=@s[1];
  2294. pc2:=pc2start;
  2295. pcstart:=pchar(@hs[0]);
  2296. pc:=pcstart;
  2297. repeat
  2298. inc(pc);
  2299. m1:=l div 10;
  2300. pc^:=char(l-(m1*10)+byte('0'));
  2301. l:=m1;
  2302. until l=0;
  2303. overflow:=(pc-pcstart)-high(s);
  2304. if overflow>0 then
  2305. inc(pcstart,overflow);
  2306. while (pc>pcstart) do
  2307. begin
  2308. pc2^:=pc^;
  2309. inc(pc2);
  2310. dec(pc);
  2311. end;
  2312. s[0]:=char(pc2-pc2start);
  2313. end;
  2314. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  2315. {$ifndef FPC_SYSTEM_HAS_INT_STR_INT64}
  2316. procedure int_str(l:int64;out s:shortstring);
  2317. {$ifdef EXCLUDE_COMPLEX_PROCS}
  2318. begin
  2319. runerror(217);
  2320. end;
  2321. {$else EXCLUDE_COMPLEX_PROCS}
  2322. var
  2323. m,m1 : qword;
  2324. pcstart,
  2325. pc2start,
  2326. pc,pc2 : pchar;
  2327. hs : string[32];
  2328. overflow : longint;
  2329. begin
  2330. pc2start:=@s[1];
  2331. pc2:=pc2start;
  2332. if (l<0) then
  2333. begin
  2334. pc2^:='-';
  2335. inc(pc2);
  2336. m:=qword(-l);
  2337. end
  2338. else
  2339. m:=qword(l);
  2340. pcstart:=pchar(@hs[0]);
  2341. pc:=pcstart;
  2342. repeat
  2343. m1:=m div 10;
  2344. inc(pc);
  2345. pc^:=char(m-(m1*10)+byte('0'));
  2346. m:=m1;
  2347. until m=0;
  2348. overflow:=(pc-pcstart)+(pc2-pc2start)-high(s);
  2349. if overflow>0 then
  2350. inc(pcstart,overflow);
  2351. while (pc>pcstart) do
  2352. begin
  2353. pc2^:=pc^;
  2354. inc(pc2);
  2355. dec(pc);
  2356. end;
  2357. s[0]:=char(pc2-pc2start);
  2358. end;
  2359. {$endif EXCLUDE_COMPLEX_PROCS}
  2360. {$endif ndef FPC_SYSTEM_HAS_INT_STR_INT64}
  2361. {$ifndef FPC_SYSTEM_HAS_INT_STR_QWORD}
  2362. procedure int_str_unsigned(l:qword;out s:shortstring);
  2363. {$ifdef EXCLUDE_COMPLEX_PROCS}
  2364. begin
  2365. runerror(217);
  2366. end;
  2367. {$else EXCLUDE_COMPLEX_PROCS}
  2368. var
  2369. m1 : qword;
  2370. pcstart,
  2371. pc2start,
  2372. pc,pc2 : pchar;
  2373. hs : string[64];
  2374. overflow : longint;
  2375. begin
  2376. pc2start:=@s[1];
  2377. pc2:=pc2start;
  2378. pcstart:=pchar(@hs[0]);
  2379. pc:=pcstart;
  2380. repeat
  2381. inc(pc);
  2382. m1:=l div 10;
  2383. pc^:=char(l-(m1*10)+byte('0'));
  2384. l:=m1;
  2385. until l=0;
  2386. overflow:=(pc-pcstart)-high(s);
  2387. if overflow>0 then
  2388. inc(pcstart,overflow);
  2389. while (pc>pcstart) do
  2390. begin
  2391. pc2^:=pc^;
  2392. inc(pc2);
  2393. dec(pc);
  2394. end;
  2395. s[0]:=char(pc2-pc2start);
  2396. end;
  2397. {$endif EXCLUDE_COMPLEX_PROCS}
  2398. {$endif ndef FPC_SYSTEM_HAS_INT_STR_QWORD}
  2399. {$ifndef FPUNONE}
  2400. {$ifndef FPC_SYSTEM_HAS_SYSRESETFPU}
  2401. procedure SysResetFpu;{$ifdef SYSTEMINLINE}inline;{$endif}
  2402. begin
  2403. softfloat_exception_flags:=[];
  2404. end;
  2405. {$endif FPC_SYSTEM_HAS_SYSRESETFPU}
  2406. {$ifndef FPC_SYSTEM_HAS_SYSINITFPU}
  2407. procedure SysInitFpu;{$ifdef SYSTEMINLINE}inline;{$endif}
  2408. begin
  2409. softfloat_exception_mask:=[float_flag_underflow,float_flag_inexact,float_flag_denormal];
  2410. end;
  2411. {$endif FPC_SYSTEM_HAS_SYSINITFPU}
  2412. {$endif}
  2413. {$ifndef FPC_SYSTEM_HAS_SWAPENDIAN}
  2414. function SwapEndian(const AValue: SmallInt): SmallInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  2415. begin
  2416. { the extra Word type cast is necessary because the "AValue shr 8" }
  2417. { is turned into "longint(AValue) shr 8", so if AValue < 0 then }
  2418. { the sign bits from the upper 16 bits are shifted in rather than }
  2419. { zeroes. }
  2420. Result := SmallInt(((Word(AValue) shr 8) or (Word(AValue) shl 8)) and $ffff);
  2421. end;
  2422. {$ifndef cpujvm}
  2423. function SwapEndian(const AValue: Word): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  2424. begin
  2425. Result := ((AValue shr 8) or (AValue shl 8)) and $ffff;
  2426. end;
  2427. {$endif}
  2428. function SwapEndian(const AValue: LongInt): LongInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  2429. begin
  2430. Result := ((AValue shl 8) and $FF00FF00) or ((AValue shr 8) and $00FF00FF);
  2431. Result := (Result shl 16) or (Result shr 16);
  2432. end;
  2433. {$ifndef cpujvm}
  2434. function SwapEndian(const AValue: DWord): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2435. begin
  2436. Result := ((AValue shl 8) and $FF00FF00) or ((AValue shr 8) and $00FF00FF);
  2437. Result := (Result shl 16) or (Result shr 16);
  2438. end;
  2439. {$endif}
  2440. function SwapEndian(const AValue: Int64): Int64;
  2441. begin
  2442. Result := ((AValue shl 8) and $FF00FF00FF00FF00) or
  2443. ((AValue shr 8) and $00FF00FF00FF00FF);
  2444. Result := ((Result shl 16) and $FFFF0000FFFF0000) or
  2445. ((Result shr 16) and $0000FFFF0000FFFF);
  2446. Result := (Result shl 32) or ((Result shr 32));
  2447. end;
  2448. {$ifndef cpujvm}
  2449. function SwapEndian(const AValue: QWord): QWord;
  2450. begin
  2451. Result := ((AValue shl 8) and $FF00FF00FF00FF00) or
  2452. ((AValue shr 8) and $00FF00FF00FF00FF);
  2453. Result := ((Result shl 16) and $FFFF0000FFFF0000) or
  2454. ((Result shr 16) and $0000FFFF0000FFFF);
  2455. Result := (Result shl 32) or ((Result shr 32));
  2456. end;
  2457. {$endif}
  2458. {$endif FPC_SYSTEM_HAS_SWAPENDIAN}
  2459. function BEtoN(const AValue: SmallInt): SmallInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  2460. begin
  2461. {$IFDEF ENDIAN_BIG}
  2462. Result := AValue;
  2463. {$ELSE}
  2464. Result := SwapEndian(AValue);
  2465. {$ENDIF}
  2466. end;
  2467. {$ifndef cpujvm}
  2468. function BEtoN(const AValue: Word): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  2469. begin
  2470. {$IFDEF ENDIAN_BIG}
  2471. Result := AValue;
  2472. {$ELSE}
  2473. Result := SwapEndian(AValue);
  2474. {$ENDIF}
  2475. end;
  2476. {$endif not cpujvm}
  2477. function BEtoN(const AValue: LongInt): LongInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  2478. begin
  2479. {$IFDEF ENDIAN_BIG}
  2480. Result := AValue;
  2481. {$ELSE}
  2482. Result := SwapEndian(AValue);
  2483. {$ENDIF}
  2484. end;
  2485. {$ifndef cpujvm}
  2486. function BEtoN(const AValue: DWord): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2487. begin
  2488. {$IFDEF ENDIAN_BIG}
  2489. Result := AValue;
  2490. {$ELSE}
  2491. Result := SwapEndian(AValue);
  2492. {$ENDIF}
  2493. end;
  2494. {$endif not cpujvm}
  2495. function BEtoN(const AValue: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  2496. begin
  2497. {$IFDEF ENDIAN_BIG}
  2498. Result := AValue;
  2499. {$ELSE}
  2500. Result := SwapEndian(AValue);
  2501. {$ENDIF}
  2502. end;
  2503. {$ifndef cpujvm}
  2504. function BEtoN(const AValue: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2505. begin
  2506. {$IFDEF ENDIAN_BIG}
  2507. Result := AValue;
  2508. {$ELSE}
  2509. Result := SwapEndian(AValue);
  2510. {$ENDIF}
  2511. end;
  2512. {$endif not cpujvm}
  2513. function LEtoN(const AValue: SmallInt): SmallInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  2514. begin
  2515. {$IFDEF ENDIAN_LITTLE}
  2516. Result := AValue;
  2517. {$ELSE}
  2518. Result := SwapEndian(AValue);
  2519. {$ENDIF}
  2520. end;
  2521. {$ifndef cpujvm}
  2522. function LEtoN(const AValue: Word): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  2523. begin
  2524. {$IFDEF ENDIAN_LITTLE}
  2525. Result := AValue;
  2526. {$ELSE}
  2527. Result := SwapEndian(AValue);
  2528. {$ENDIF}
  2529. end;
  2530. {$endif not cpujvm}
  2531. function LEtoN(const AValue: LongInt): LongInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  2532. begin
  2533. {$IFDEF ENDIAN_LITTLE}
  2534. Result := AValue;
  2535. {$ELSE}
  2536. Result := SwapEndian(AValue);
  2537. {$ENDIF}
  2538. end;
  2539. {$ifndef cpujvm}
  2540. function LEtoN(const AValue: DWord): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2541. begin
  2542. {$IFDEF ENDIAN_LITTLE}
  2543. Result := AValue;
  2544. {$ELSE}
  2545. Result := SwapEndian(AValue);
  2546. {$ENDIF}
  2547. end;
  2548. {$endif not cpujvm}
  2549. function LEtoN(const AValue: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  2550. begin
  2551. {$IFDEF ENDIAN_LITTLE}
  2552. Result := AValue;
  2553. {$ELSE}
  2554. Result := SwapEndian(AValue);
  2555. {$ENDIF}
  2556. end;
  2557. {$ifndef cpujvm}
  2558. function LEtoN(const AValue: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2559. begin
  2560. {$IFDEF ENDIAN_LITTLE}
  2561. Result := AValue;
  2562. {$ELSE}
  2563. Result := SwapEndian(AValue);
  2564. {$ENDIF}
  2565. end;
  2566. {$endif not cpujvm}
  2567. function NtoBE(const AValue: SmallInt): SmallInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  2568. begin
  2569. {$IFDEF ENDIAN_BIG}
  2570. Result := AValue;
  2571. {$ELSE}
  2572. Result := SwapEndian(AValue);
  2573. {$ENDIF}
  2574. end;
  2575. {$ifndef cpujvm}
  2576. function NtoBE(const AValue: Word): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  2577. begin
  2578. {$IFDEF ENDIAN_BIG}
  2579. Result := AValue;
  2580. {$ELSE}
  2581. Result := SwapEndian(AValue);
  2582. {$ENDIF}
  2583. end;
  2584. {$endif not cpujvm}
  2585. function NtoBE(const AValue: LongInt): LongInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  2586. begin
  2587. {$IFDEF ENDIAN_BIG}
  2588. Result := AValue;
  2589. {$ELSE}
  2590. Result := SwapEndian(AValue);
  2591. {$ENDIF}
  2592. end;
  2593. {$ifndef cpujvm}
  2594. function NtoBE(const AValue: DWord): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2595. begin
  2596. {$IFDEF ENDIAN_BIG}
  2597. Result := AValue;
  2598. {$ELSE}
  2599. Result := SwapEndian(AValue);
  2600. {$ENDIF}
  2601. end;
  2602. {$endif not cpujvm}
  2603. function NtoBE(const AValue: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  2604. begin
  2605. {$IFDEF ENDIAN_BIG}
  2606. Result := AValue;
  2607. {$ELSE}
  2608. Result := SwapEndian(AValue);
  2609. {$ENDIF}
  2610. end;
  2611. {$ifndef cpujvm}
  2612. function NtoBE(const AValue: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2613. begin
  2614. {$IFDEF ENDIAN_BIG}
  2615. Result := AValue;
  2616. {$ELSE}
  2617. Result := SwapEndian(AValue);
  2618. {$ENDIF}
  2619. end;
  2620. {$endif not cpujvm}
  2621. function NtoLE(const AValue: SmallInt): SmallInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  2622. begin
  2623. {$IFDEF ENDIAN_LITTLE}
  2624. Result := AValue;
  2625. {$ELSE}
  2626. Result := SwapEndian(AValue);
  2627. {$ENDIF}
  2628. end;
  2629. {$ifndef cpujvm}
  2630. function NtoLE(const AValue: Word): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  2631. begin
  2632. {$IFDEF ENDIAN_LITTLE}
  2633. Result := AValue;
  2634. {$ELSE}
  2635. Result := SwapEndian(AValue);
  2636. {$ENDIF}
  2637. end;
  2638. {$endif not cpujvm}
  2639. function NtoLE(const AValue: LongInt): LongInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  2640. begin
  2641. {$IFDEF ENDIAN_LITTLE}
  2642. Result := AValue;
  2643. {$ELSE}
  2644. Result := SwapEndian(AValue);
  2645. {$ENDIF}
  2646. end;
  2647. {$ifndef cpujvm}
  2648. function NtoLE(const AValue: DWord): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2649. begin
  2650. {$IFDEF ENDIAN_LITTLE}
  2651. Result := AValue;
  2652. {$ELSE}
  2653. Result := SwapEndian(AValue);
  2654. {$ENDIF}
  2655. end;
  2656. {$endif not cpujvm}
  2657. function NtoLE(const AValue: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  2658. begin
  2659. {$IFDEF ENDIAN_LITTLE}
  2660. Result := AValue;
  2661. {$ELSE}
  2662. Result := SwapEndian(AValue);
  2663. {$ENDIF}
  2664. end;
  2665. {$ifndef cpujvm}
  2666. function NtoLE(const AValue: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2667. begin
  2668. {$IFDEF ENDIAN_LITTLE}
  2669. Result := AValue;
  2670. {$ELSE}
  2671. Result := SwapEndian(AValue);
  2672. {$ENDIF}
  2673. end;
  2674. {$endif not cpujvm}
  2675. {$ifndef FPC_SYSTEM_HAS_MEM_BARRIER}
  2676. procedure ReadBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  2677. begin
  2678. end;
  2679. procedure ReadDependencyBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  2680. begin
  2681. end;
  2682. procedure ReadWriteBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  2683. begin
  2684. end;
  2685. procedure WriteBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  2686. begin
  2687. end;
  2688. {$endif FPC_SYSTEM_HAS_MEM_BARRIER}
  2689. {$ifndef FPC_HAS_INTERNAL_ROX_BYTE}
  2690. {$ifndef FPC_SYSTEM_HAS_ROX_BYTE}
  2691. function RorByte(Const AValue : Byte): Byte;{$ifdef SYSTEMINLINE}inline;{$endif}
  2692. begin
  2693. Result:=(AValue shr 1) or (AValue shl 7);
  2694. end;
  2695. function RorByte(Const AValue : Byte;const Dist : Byte): Byte;{$ifdef SYSTEMINLINE}inline;{$endif}
  2696. begin
  2697. Result:=(AValue shr (Dist and 7)) or (AValue shl (8-(Dist and 7)));
  2698. end;
  2699. function RolByte(Const AValue : Byte): Byte;{$ifdef SYSTEMINLINE}inline;{$endif}
  2700. begin
  2701. Result:=(AValue shl 1) or (AValue shr 7);
  2702. end;
  2703. function RolByte(Const AValue : Byte;const Dist : Byte): Byte;{$ifdef SYSTEMINLINE}inline;{$endif}
  2704. begin
  2705. Result:=(AValue shl (Dist and 7)) or (AValue shr (8-(Dist and 7)));
  2706. end;
  2707. {$endif FPC_SYSTEM_HAS_ROX_BYTE}
  2708. {$endif FPC_HAS_INTERNAL_ROX_BYTE}
  2709. {$ifndef FPC_HAS_INTERNAL_ROX_WORD}
  2710. {$ifndef FPC_SYSTEM_HAS_ROX_WORD}
  2711. function RorWord(Const AValue : Word): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  2712. begin
  2713. Result:=(AValue shr 1) or (AValue shl 15);
  2714. end;
  2715. function RorWord(Const AValue : Word;const Dist : Byte): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  2716. begin
  2717. Result:=(AValue shr (Dist and 15)) or (AValue shl (16-(Dist and 15)));
  2718. end;
  2719. function RolWord(Const AValue : Word): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  2720. begin
  2721. Result:=(AValue shl 1) or (AValue shr 15);
  2722. end;
  2723. function RolWord(Const AValue : Word;const Dist : Byte): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  2724. begin
  2725. Result:=(AValue shl (Dist and 15)) or (AValue shr (16-(Dist and 15)));
  2726. end;
  2727. {$endif FPC_SYSTEM_HAS_ROX_WORD}
  2728. {$endif FPC_HAS_INTERNAL_ROX_WORD}
  2729. {$ifndef FPC_HAS_INTERNAL_ROX_DWORD}
  2730. {$ifndef FPC_SYSTEM_HAS_ROX_DWORD}
  2731. function RorDWord(Const AValue : DWord): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2732. begin
  2733. Result:=(AValue shr 1) or (AValue shl 31);
  2734. end;
  2735. function RorDWord(Const AValue : DWord;const Dist : Byte): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2736. begin
  2737. Result:=(AValue shr (Dist and 31)) or (AValue shl (32-(Dist and 31)));
  2738. end;
  2739. function RolDWord(Const AValue : DWord): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2740. begin
  2741. Result:=(AValue shl 1) or (AValue shr 31);
  2742. end;
  2743. function RolDWord(Const AValue : DWord;const Dist : Byte): DWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2744. begin
  2745. Result:=(AValue shl (Dist and 31)) or (AValue shr (32-(Dist and 31)));
  2746. end;
  2747. {$endif FPC_SYSTEM_HAS_ROX_DWORD}
  2748. {$endif FPC_HAS_INTERNAL_ROX_DWORD}
  2749. {$ifndef FPC_HAS_INTERNAL_ROX_QWORD}
  2750. {$ifndef FPC_SYSTEM_HAS_ROX_QWORD}
  2751. function RorQWord(Const AValue : QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2752. begin
  2753. Result:=(AValue shr 1) or (AValue shl 63);
  2754. end;
  2755. function RorQWord(Const AValue : QWord;const Dist : Byte): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2756. begin
  2757. Result:=(AValue shr (Dist and 63)) or (AValue shl (64-(Dist and 63)));
  2758. end;
  2759. function RolQWord(Const AValue : QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2760. begin
  2761. Result:=(AValue shl 1) or (AValue shr 63);
  2762. end;
  2763. function RolQWord(Const AValue : QWord;const Dist : Byte): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  2764. begin
  2765. Result:=(AValue shl (Dist and 63)) or (AValue shr (64-(Dist and 63)));
  2766. end;
  2767. {$endif FPC_SYSTEM_HAS_ROX_QWORD}
  2768. {$endif FPC_HAS_INTERNAL_ROX_QWORD}
  2769. {$ifndef FPC_HAS_INTERNAL_ROX_ASSIGN_QWORD}
  2770. {$ifndef FPC_SYSTEM_HAS_ROX_ASSIGN_QWORD}
  2771. procedure fpc_ror_assign_int64(var AValue : int64;const Dist : Byte); [Public,Alias:'FPC_ROR_ASSIGN_INT64']; compilerproc;
  2772. begin
  2773. AValue:=(AValue shr (Dist and 63)) or (AValue shl (64-(Dist and 63)));
  2774. end;
  2775. procedure fpc_ror_assign_qword(var AValue : QWord;const Dist : Byte); [Public,Alias:'FPC_ROR_ASSIGN_QWORD']; compilerproc;
  2776. begin
  2777. AValue:=(AValue shr (Dist and 63)) or (AValue shl (64-(Dist and 63)));
  2778. end;
  2779. procedure fpc_rol_assign_int64(var AValue : int64;const Dist : Byte); [Public,Alias:'FPC_ROL_ASSIGN_INT64']; compilerproc;
  2780. begin
  2781. AValue:=(AValue shl (Dist and 63)) or (AValue shr (64-(Dist and 63)));
  2782. end;
  2783. procedure fpc_rol_assign_qword(var AValue : QWord;const Dist : Byte); [Public,Alias:'FPC_ROL_ASSIGN_QWORD']; compilerproc;
  2784. begin
  2785. AValue:=(AValue shl (Dist and 63)) or (AValue shr (64-(Dist and 63)));
  2786. end;
  2787. {$endif FPC_SYSTEM_HAS_ROX_ASSIGN_QWORD}
  2788. {$endif FPC_HAS_INTERNAL_ROX_ASSIGN_QWORD}
  2789. {$ifndef FPC_HAS_INTERNAL_SAR_BYTE}
  2790. {$ifndef FPC_SYSTEM_HAS_SAR_BYTE}
  2791. function SarShortint(Const AValue : Shortint;const Shift : Byte): Shortint;
  2792. begin
  2793. Result:=shortint(byte(byte(byte(AValue) shr (Shift and 7)) or (byte(shortint(byte(0-byte(byte(AValue) shr 7)) and byte(shortint(0-(ord((Shift and 7)<>0){ and 1}))))) shl (8-(Shift and 7)))));
  2794. end;
  2795. {$endif FPC_HAS_INTERNAL_SAR_BYTE}
  2796. {$endif FPC_SYSTEM_HAS_SAR_BYTE}
  2797. {$ifndef FPC_HAS_INTERNAL_SAR_WORD}
  2798. {$ifndef FPC_SYSTEM_HAS_SAR_WORD}
  2799. function SarSmallint(Const AValue : Smallint;const Shift : Byte): Smallint;
  2800. begin
  2801. Result:=smallint(word(word(word(AValue) shr (Shift and 15)) or (word(smallint(word(0-word(word(AValue) shr 15)) and word(smallint(0-(ord((Shift and 15)<>0){ and 1}))))) shl (16-(Shift and 15)))));
  2802. end;
  2803. {$endif FPC_HAS_INTERNAL_SAR_WORD}
  2804. {$endif FPC_SYSTEM_HAS_SAR_WORD}
  2805. {$ifndef FPC_HAS_INTERNAL_SAR_DWORD}
  2806. {$ifndef FPC_SYSTEM_HAS_SAR_DWORD}
  2807. function SarLongint(Const AValue : Longint;const Shift : Byte): Longint;
  2808. begin
  2809. Result:=longint(dword(dword(dword(AValue) shr (Shift and 31)) or (dword(longint(dword(0-dword(dword(AValue) shr 31)) and dword(longint(0-(ord((Shift and 31)<>0){ and 1}))))) shl (32-(Shift and 31)))));
  2810. end;
  2811. {$endif FPC_HAS_INTERNAL_SAR_DWORD}
  2812. {$endif FPC_SYSTEM_HAS_SAR_DWORD}
  2813. {$ifndef FPC_HAS_INTERNAL_SAR_QWORD}
  2814. {$ifndef FPC_SYSTEM_HAS_SAR_QWORD}
  2815. function fpc_SarInt64(Const AValue : Int64;const Shift : Byte): Int64; [Public,Alias:'FPC_SARINT64']; compilerproc;
  2816. begin
  2817. Result:=int64(qword(qword(qword(AValue) shr (Shift and 63)) or (qword(int64(qword(0-qword(qword(AValue) shr 63)) and qword(int64(0-(ord((Shift and 63)<>0){ and 1}))))) shl (64-(Shift and 63)))));
  2818. end;
  2819. {$endif FPC_HAS_INTERNAL_SAR_QWORD}
  2820. {$endif FPC_SYSTEM_HAS_SAR_QWORD}
  2821. {$ifndef FPC_HAS_INTERNAL_SAR_ASSIGN_QWORD}
  2822. {$ifndef FPC_SYSTEM_HAS_SAR_ASSIGN_QWORD}
  2823. procedure fpc_sar_assign_int64(var AValue : Int64;const Shift : Byte); [Public,Alias:'FPC_SAR_ASSIGN_INT64']; compilerproc;
  2824. begin
  2825. AValue:=int64(qword(qword(qword(AValue) shr (Shift and 63)) or (qword(int64(qword(0-qword(qword(AValue) shr 63)) and qword(int64(0-(ord((Shift and 63)<>0){ and 1}))))) shl (64-(Shift and 63)))));
  2826. end;
  2827. procedure fpc_sar_assign_qword(var AValue : QWord;const Shift : Byte); [Public,Alias:'FPC_SAR_ASSIGN_QWORD']; compilerproc;
  2828. begin
  2829. AValue:=qword(qword(qword(qword(AValue) shr (Shift and 63)) or (qword(int64(qword(0-qword(qword(AValue) shr 63)) and qword(int64(0-(ord((Shift and 63)<>0){ and 1}))))) shl (64-(Shift and 63)))));
  2830. end;
  2831. {$endif FPC_HAS_INTERNAL_SAR_ASSIGN_QWORD}
  2832. {$endif FPC_SYSTEM_HAS_SAR_ASSIGN_QWORD}
  2833. {$ifndef FPC_HAS_INTERNAL_BSF_BYTE}
  2834. {$ifndef FPC_SYSTEM_HAS_BSF_BYTE}
  2835. function BsfByte(Const AValue: Byte): Byte;
  2836. const bsf8bit: array [Byte] of Byte = (
  2837. $ff,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  2838. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  2839. 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  2840. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  2841. 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  2842. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  2843. 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  2844. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
  2845. );
  2846. begin
  2847. result:=bsf8bit[AValue];
  2848. end;
  2849. {$endif}
  2850. {$endif}
  2851. {$ifndef FPC_HAS_INTERNAL_BSR_BYTE}
  2852. {$ifndef FPC_SYSTEM_HAS_BSR_BYTE}
  2853. function BsrByte(Const AValue: Byte): Byte;
  2854. const bsr8bit: array [Byte] of Byte = (
  2855. $ff,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  2856. 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
  2857. 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  2858. 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  2859. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  2860. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  2861. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  2862. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
  2863. );
  2864. begin
  2865. result:=bsr8bit[AValue];
  2866. end;
  2867. {$endif}
  2868. {$endif}
  2869. {$ifndef FPC_SYSTEM_HAS_BSF_WORD}
  2870. {$ifndef FPC_HAS_INTERNAL_BSF_WORD}
  2871. function BsfWord(Const AValue: Word): {$ifdef CPU16}byte{$else}cardinal{$endif};
  2872. begin
  2873. result:=ord(lo(AValue)=0)*8;
  2874. result:=result or BsfByte(byte(AValue shr result));
  2875. end;
  2876. {$endif}
  2877. {$endif}
  2878. {$ifndef FPC_SYSTEM_HAS_BSR_WORD}
  2879. {$ifndef FPC_HAS_INTERNAL_BSR_WORD}
  2880. function BsrWord(Const AValue: Word): {$ifdef CPU16}byte{$else}cardinal{$endif};
  2881. begin
  2882. result:=ord(AValue>255)*8;
  2883. result:=result or BsrByte(byte(AValue shr result));
  2884. end;
  2885. {$endif}
  2886. {$endif}
  2887. {$ifndef FPC_HAS_INTERNAL_BSF_DWORD}
  2888. {$ifndef FPC_SYSTEM_HAS_BSF_DWORD}
  2889. function BsfDWord(Const AValue : DWord): {$ifdef CPU16}byte{$else}cardinal{$endif};
  2890. var
  2891. tmp: DWord;
  2892. begin
  2893. result:=ord(lo(AValue)=0)*16;
  2894. tmp:=AValue shr result;
  2895. result:=result or (ord((tmp and $FF)=0)*8);
  2896. tmp:=tmp shr (result and 8);
  2897. result:=result or BsfByte(byte(tmp));
  2898. end;
  2899. {$endif}
  2900. {$endif}
  2901. {$ifndef FPC_HAS_INTERNAL_BSR_DWORD}
  2902. {$ifndef FPC_SYSTEM_HAS_BSR_DWORD}
  2903. function BsrDWord(Const AValue : DWord): {$ifdef CPU16}byte{$else}cardinal{$endif};
  2904. var
  2905. tmp: DWord;
  2906. begin
  2907. result:=ord(AValue>$FFFF)*16;
  2908. tmp:=AValue shr result;
  2909. result:=result or (ord(tmp>$FF)*8);
  2910. tmp:=tmp shr (result and 8);
  2911. result:=result or BsrByte(byte(tmp));
  2912. end;
  2913. {$endif}
  2914. {$endif}
  2915. {$ifndef FPC_HAS_INTERNAL_BSF_QWORD}
  2916. {$ifndef FPC_SYSTEM_HAS_BSF_QWORD}
  2917. function BsfQWord(Const AValue : QWord): {$ifdef CPU16}byte{$else}cardinal{$endif};
  2918. var
  2919. tmp: DWord;
  2920. begin
  2921. result:=0;
  2922. tmp:=lo(AValue);
  2923. if (tmp=0) then
  2924. begin
  2925. tmp:=hi(AValue);
  2926. result:=32;
  2927. end;
  2928. result:=result or BsfDword(tmp);
  2929. end;
  2930. {$endif}
  2931. {$endif}
  2932. {$ifndef FPC_HAS_INTERNAL_BSR_QWORD}
  2933. {$ifndef FPC_SYSTEM_HAS_BSR_QWORD}
  2934. function BsrQWord(Const AValue : QWord): {$ifdef CPU16}byte{$else}cardinal{$endif};
  2935. var
  2936. tmp: DWord;
  2937. begin
  2938. result:=32;
  2939. tmp:=hi(AValue);
  2940. if (tmp=0) then
  2941. begin
  2942. tmp:=lo(AValue);
  2943. result:=0;
  2944. end;
  2945. result:=result or BsrDword(tmp);
  2946. end;
  2947. {$endif}
  2948. {$endif}
  2949. const
  2950. PopCntData : array[0..15] of byte = (0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4);
  2951. function fpc_PopCnt_byte(AValue : Byte): Byte;[Public,Alias:'FPC_POPCNT_BYTE'];compilerproc;
  2952. begin
  2953. Result:=PopCntData[AValue and $f]+PopCntData[(AValue shr 4) and $f];
  2954. end;
  2955. function fpc_PopCnt_word(AValue : Word): Word;[Public,Alias:'FPC_POPCNT_WORD'];compilerproc;
  2956. var
  2957. i : SizeInt;
  2958. begin
  2959. Result:=0;
  2960. for i:=0 to 3 do
  2961. begin
  2962. inc(Result,PopCntData[AValue and $f]);
  2963. AValue:=AValue shr 4;
  2964. end;
  2965. end;
  2966. function fpc_PopCnt_dword(AValue : DWord): DWord;[Public,Alias:'FPC_POPCNT_DWORD'];compilerproc;
  2967. var
  2968. i : SizeInt;
  2969. begin
  2970. Result:=0;
  2971. for i:=0 to 7 do
  2972. begin
  2973. inc(Result,PopCntData[AValue and $f]);
  2974. AValue:=AValue shr 4;
  2975. end;
  2976. end;
  2977. {$ifndef FPC_SYSTEM_HAS_POPCNT_QWORD}
  2978. function fpc_PopCnt_qword(AValue : QWord): QWord;[Public,Alias:'FPC_POPCNT_QWORD'];compilerproc;
  2979. begin
  2980. Result:=PopCnt(lo(AValue))+PopCnt(hi(AValue))
  2981. end;
  2982. {$endif}