cgai386.pas 145 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. Helper routines for the i386 code generator
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************}
  17. unit cgai386;
  18. interface
  19. uses
  20. cobjects,tree,
  21. i386base,i386asm,
  22. {$ifdef dummy}
  23. end { to get correct syntax highlighting }
  24. {$endif dummy}
  25. aasm,symtable,win_targ;
  26. {$define TESTGETTEMP to store const that
  27. are written into temps for later release PM }
  28. function def_opsize(p1:pdef):topsize;
  29. function def2def_opsize(p1,p2:pdef):topsize;
  30. function def_getreg(p1:pdef):tregister;
  31. function makereg8(r:tregister):tregister;
  32. function makereg16(r:tregister):tregister;
  33. function makereg32(r:tregister):tregister;
  34. procedure emitlab(var l : pasmlabel);
  35. procedure emitjmp(c : tasmcond;var l : pasmlabel);
  36. procedure emit_flag2reg(flag:tresflags;hregister:tregister);
  37. procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
  38. procedure emitcall(const routine:string);
  39. procedure emit_mov_loc_ref(const t:tlocation;const ref:treference);
  40. procedure emit_mov_loc_reg(const t:tlocation;reg:tregister);
  41. procedure emit_push_loc(const t:tlocation);
  42. { pushes qword location to the stack }
  43. procedure emit_pushq_loc(const t : tlocation);
  44. procedure release_qword_loc(const t : tlocation);
  45. { releases the registers of a location }
  46. procedure release_loc(const t : tlocation);
  47. procedure emit_pushw_loc(const t:tlocation);
  48. procedure emit_lea_loc_ref(const t:tlocation;const ref:treference);
  49. procedure emit_push_lea_loc(const t:tlocation);
  50. procedure emit_to_reference(var p:ptree);
  51. procedure emit_to_reg16(var hr:tregister);
  52. procedure emit_to_reg32(var hr:tregister);
  53. procedure emit_mov_reg_loc(reg: TRegister; const t:tlocation);
  54. procedure emit_movq_reg_loc(reghigh,reglow: TRegister;t:tlocation);
  55. procedure copyshortstring(const dref,sref : treference;len : byte;loadref:boolean);
  56. procedure loadansistring(p : ptree);
  57. procedure finalize(t : pdef;const ref : treference;is_already_ref : boolean);
  58. procedure decrstringref(t : pdef;const ref : treference);
  59. function maybe_push(needed : byte;p : ptree;isint64 : boolean) : boolean;
  60. procedure push_int(l : longint);
  61. procedure emit_push_mem(const ref : treference);
  62. procedure emitpushreferenceaddr(const ref : treference);
  63. procedure pushsetelement(p : ptree);
  64. procedure restore(p : ptree;isint64 : boolean);
  65. procedure push_value_para(p:ptree;inlined:boolean;para_offset:longint;alignment : longint);
  66. {$ifdef TEMPS_NOT_PUSH}
  67. { does the same as restore/maybe_push, but uses temp. space instead of pushing }
  68. function maybe_push(needed : byte;p : ptree;isint64 : boolean) : boolean;
  69. procedure restorefromtemp(p : ptree;isint64 : boolean);
  70. {$endif TEMPS_NOT_PUSH}
  71. procedure floatload(t : tfloattype;const ref : treference);
  72. procedure floatstore(t : tfloattype;const ref : treference);
  73. procedure floatloadops(t : tfloattype;var op : tasmop;var s : topsize);
  74. procedure floatstoreops(t : tfloattype;var op : tasmop;var s : topsize);
  75. procedure maybe_loadesi;
  76. procedure maketojumpbool(p : ptree);
  77. procedure emitloadord2reg(const location:Tlocation;orddef:Porddef;destreg:Tregister;delloc:boolean);
  78. procedure emitoverflowcheck(p:ptree);
  79. procedure emitrangecheck(p:ptree;todef:pdef);
  80. procedure concatcopy(source,dest : treference;size : longint;delsource : boolean;loadref:boolean);
  81. procedure firstcomplex(p : ptree);
  82. procedure genentrycode(alist : paasmoutput;const proc_names:Tstringcontainer;make_global:boolean;
  83. stackframe:longint;
  84. var parasize:longint;var nostackframe:boolean;
  85. inlined : boolean);
  86. procedure genexitcode(alist : paasmoutput;parasize:longint;
  87. nostackframe,inlined:boolean);
  88. {$ifdef test_dest_loc}
  89. const
  90. { used to avoid temporary assignments }
  91. dest_loc_known : boolean = false;
  92. in_dest_loc : boolean = false;
  93. dest_loc_tree : ptree = nil;
  94. var
  95. dest_loc : tlocation;
  96. procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
  97. {$endif test_dest_loc}
  98. implementation
  99. uses
  100. strings,globtype,systems,globals,verbose,files,types,pbase,
  101. tgeni386,temp_gen,hcodegen,ppu
  102. {$ifdef GDB}
  103. ,gdb
  104. {$endif}
  105. ;
  106. {*****************************************************************************
  107. Helpers
  108. *****************************************************************************}
  109. function def_opsize(p1:pdef):topsize;
  110. begin
  111. case p1^.size of
  112. 1 : def_opsize:=S_B;
  113. 2 : def_opsize:=S_W;
  114. 4 : def_opsize:=S_L;
  115. else
  116. internalerror(78);
  117. end;
  118. end;
  119. function def2def_opsize(p1,p2:pdef):topsize;
  120. var
  121. o1 : topsize;
  122. begin
  123. case p1^.size of
  124. 1 : o1:=S_B;
  125. 2 : o1:=S_W;
  126. 4 : o1:=S_L;
  127. { I don't know if we need it (FK) }
  128. 8 : o1:=S_L;
  129. else
  130. internalerror(78);
  131. end;
  132. if assigned(p2) then
  133. begin
  134. case p2^.size of
  135. 1 : o1:=S_B;
  136. 2 : begin
  137. if o1=S_B then
  138. o1:=S_BW
  139. else
  140. o1:=S_W;
  141. end;
  142. 4,8:
  143. begin
  144. case o1 of
  145. S_B : o1:=S_BL;
  146. S_W : o1:=S_WL;
  147. end;
  148. end;
  149. end;
  150. end;
  151. def2def_opsize:=o1;
  152. end;
  153. function def_getreg(p1:pdef):tregister;
  154. begin
  155. case p1^.size of
  156. 1 : def_getreg:=reg32toreg8(getregister32);
  157. 2 : def_getreg:=reg32toreg16(getregister32);
  158. 4 : def_getreg:=getregister32;
  159. else
  160. internalerror(78);
  161. end;
  162. end;
  163. function makereg8(r:tregister):tregister;
  164. begin
  165. case r of
  166. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  167. makereg8:=reg32toreg8(r);
  168. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  169. makereg8:=reg16toreg8(r);
  170. R_AL,R_BL,R_CL,R_DL :
  171. makereg8:=r;
  172. end;
  173. end;
  174. function makereg16(r:tregister):tregister;
  175. begin
  176. case r of
  177. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  178. makereg16:=reg32toreg16(r);
  179. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  180. makereg16:=r;
  181. R_AL,R_BL,R_CL,R_DL :
  182. makereg16:=reg8toreg16(r);
  183. end;
  184. end;
  185. function makereg32(r:tregister):tregister;
  186. begin
  187. case r of
  188. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  189. makereg32:=r;
  190. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  191. makereg32:=reg16toreg32(r);
  192. R_AL,R_BL,R_CL,R_DL :
  193. makereg32:=reg8toreg32(r);
  194. end;
  195. end;
  196. {*****************************************************************************
  197. Emit Assembler
  198. *****************************************************************************}
  199. procedure emitlab(var l : pasmlabel);
  200. begin
  201. if not l^.is_set then
  202. exprasmlist^.concat(new(pai_label,init(l)))
  203. else
  204. internalerror(7453984);
  205. end;
  206. {$ifdef nojmpfix}
  207. procedure emitjmp(c : tasmcond;var l : pasmlabel);
  208. var
  209. ai : Pai386;
  210. begin
  211. if c=C_None then
  212. exprasmlist^.concat(new(pai386,op_sym(A_JMP,S_NO,l)))
  213. else
  214. begin
  215. ai:=new(pai386,op_sym(A_Jcc,S_NO,l));
  216. ai^.SetCondition(c);
  217. ai^.is_jmp:=true;
  218. exprasmlist^.concat(ai);
  219. end;
  220. end;
  221. {$else nojmpfix}
  222. procedure emitjmp(c : tasmcond;var l : pasmlabel);
  223. var
  224. ai : Pai386;
  225. begin
  226. if c=C_None then
  227. ai := new(pai386,op_sym(A_JMP,S_NO,l))
  228. else
  229. begin
  230. ai:=new(pai386,op_sym(A_Jcc,S_NO,l));
  231. ai^.SetCondition(c);
  232. end;
  233. ai^.is_jmp:=true;
  234. exprasmlist^.concat(ai);
  235. end;
  236. {$endif nojmpfix}
  237. procedure emit_flag2reg(flag:tresflags;hregister:tregister);
  238. var
  239. ai : pai386;
  240. hreg : tregister;
  241. begin
  242. hreg:=makereg8(hregister);
  243. ai:=new(pai386,op_reg(A_Setcc,S_B,hreg));
  244. ai^.SetCondition(flag_2_cond[flag]);
  245. exprasmlist^.concat(ai);
  246. if hreg<>hregister then
  247. begin
  248. if hregister in regset16bit then
  249. emit_to_reg16(hreg)
  250. else
  251. emit_to_reg32(hreg);
  252. end;
  253. end;
  254. procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
  255. begin
  256. if (reg1<>reg2) or (i<>A_MOV) then
  257. exprasmlist^.concat(new(pai386,op_reg_reg(i,s,reg1,reg2)));
  258. end;
  259. procedure emitcall(const routine:string);
  260. begin
  261. exprasmlist^.concat(new(pai386,op_sym(A_CALL,S_NO,newasmsymbol(routine))));
  262. end;
  263. procedure emit_mov_loc_ref(const t:tlocation;const ref:treference);
  264. begin
  265. case t.loc of
  266. LOC_REGISTER,
  267. LOC_CREGISTER : begin
  268. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  269. t.register,newreference(ref))));
  270. ungetregister32(t.register); { the register is not needed anymore }
  271. end;
  272. LOC_MEM,
  273. LOC_REFERENCE : begin
  274. if t.reference.is_immediate then
  275. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_L,
  276. t.reference.offset,newreference(ref))))
  277. else
  278. begin
  279. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  280. newreference(t.reference),R_EDI)));
  281. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  282. R_EDI,newreference(ref))));
  283. { we can release the registers }
  284. { but only AFTER the MOV! Important for the optimizer!
  285. (JM)}
  286. del_reference(ref);
  287. end;
  288. ungetiftemp(t.reference);
  289. end;
  290. else
  291. internalerror(330);
  292. end;
  293. end;
  294. procedure emit_mov_loc_reg(const t:tlocation;reg:tregister);
  295. begin
  296. case t.loc of
  297. LOC_REGISTER,
  298. LOC_CREGISTER : begin
  299. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,
  300. t.register,reg)));
  301. ungetregister32(t.register); { the register is not needed anymore }
  302. end;
  303. LOC_MEM,
  304. LOC_REFERENCE : begin
  305. if t.reference.is_immediate then
  306. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,S_L,
  307. t.reference.offset,reg)))
  308. else
  309. begin
  310. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  311. newreference(t.reference),reg)));
  312. end;
  313. ungetiftemp(t.reference);
  314. end;
  315. else
  316. internalerror(330);
  317. end;
  318. end;
  319. procedure emit_mov_reg_loc(reg: TRegister; const t:tlocation);
  320. begin
  321. case t.loc of
  322. LOC_REGISTER,
  323. LOC_CREGISTER : begin
  324. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,RegSize(Reg),
  325. reg,t.register)));
  326. end;
  327. LOC_MEM,
  328. LOC_REFERENCE : begin
  329. if t.reference.is_immediate then
  330. internalerror(334)
  331. else
  332. begin
  333. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,RegSize(Reg),
  334. Reg,newreference(t.reference))));
  335. end;
  336. end;
  337. else
  338. internalerror(330);
  339. end;
  340. end;
  341. procedure emit_movq_reg_loc(reghigh,reglow: TRegister;t:tlocation);
  342. begin
  343. case t.loc of
  344. LOC_REGISTER,
  345. LOC_CREGISTER : begin
  346. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,
  347. reglow,t.registerlow)));
  348. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,
  349. reghigh,t.registerhigh)));
  350. end;
  351. LOC_MEM,
  352. LOC_REFERENCE : begin
  353. if t.reference.is_immediate then
  354. internalerror(334)
  355. else
  356. begin
  357. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  358. Reglow,newreference(t.reference))));
  359. inc(t.reference.offset,4);
  360. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  361. Reghigh,newreference(t.reference))));
  362. end;
  363. end;
  364. else
  365. internalerror(330);
  366. end;
  367. end;
  368. procedure emit_pushq_loc(const t : tlocation);
  369. var
  370. hr : preference;
  371. begin
  372. case t.loc of
  373. LOC_REGISTER,
  374. LOC_CREGISTER:
  375. begin
  376. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,
  377. t.registerhigh)));
  378. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,
  379. t.registerlow)));
  380. end;
  381. LOC_MEM,
  382. LOC_REFERENCE:
  383. begin
  384. hr:=newreference(t.reference);
  385. inc(hr^.offset,4);
  386. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_L,
  387. hr)));
  388. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_L,
  389. newreference(t.reference))));
  390. ungetiftemp(t.reference);
  391. end;
  392. else internalerror(331);
  393. end;
  394. end;
  395. procedure release_loc(const t : tlocation);
  396. begin
  397. case t.loc of
  398. LOC_REGISTER,
  399. LOC_CREGISTER:
  400. begin
  401. ungetregister32(t.register);
  402. end;
  403. LOC_MEM,
  404. LOC_REFERENCE:
  405. del_reference(t.reference);
  406. else internalerror(332);
  407. end;
  408. end;
  409. procedure release_qword_loc(const t : tlocation);
  410. begin
  411. case t.loc of
  412. LOC_REGISTER,
  413. LOC_CREGISTER:
  414. begin
  415. ungetregister32(t.registerhigh);
  416. ungetregister32(t.registerlow);
  417. end;
  418. LOC_MEM,
  419. LOC_REFERENCE:
  420. del_reference(t.reference);
  421. else internalerror(331);
  422. end;
  423. end;
  424. procedure emit_push_loc(const t:tlocation);
  425. begin
  426. case t.loc of
  427. LOC_REGISTER,
  428. LOC_CREGISTER : begin
  429. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,makereg32(t.register))));
  430. ungetregister(t.register); { the register is not needed anymore }
  431. end;
  432. LOC_MEM,
  433. LOC_REFERENCE : begin
  434. if t.reference.is_immediate then
  435. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,t.reference.offset)))
  436. else
  437. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_L,newreference(t.reference))));
  438. del_reference(t.reference);
  439. ungetiftemp(t.reference);
  440. end;
  441. else
  442. internalerror(330);
  443. end;
  444. end;
  445. procedure emit_pushw_loc(const t:tlocation);
  446. var
  447. opsize : topsize;
  448. begin
  449. case t.loc of
  450. LOC_REGISTER,
  451. LOC_CREGISTER : begin
  452. if target_os.stackalignment=4 then
  453. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,makereg32(t.register))))
  454. else
  455. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_W,makereg16(t.register))));
  456. ungetregister(t.register); { the register is not needed anymore }
  457. end;
  458. LOC_MEM,
  459. LOC_REFERENCE : begin
  460. if target_os.stackalignment=4 then
  461. opsize:=S_L
  462. else
  463. opsize:=S_W;
  464. if t.reference.is_immediate then
  465. exprasmlist^.concat(new(pai386,op_const(A_PUSH,opsize,t.reference.offset)))
  466. else
  467. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,opsize,newreference(t.reference))));
  468. del_reference(t.reference);
  469. ungetiftemp(t.reference);
  470. end;
  471. else
  472. internalerror(330);
  473. end;
  474. end;
  475. procedure emit_lea_loc_ref(const t:tlocation;const ref:treference);
  476. begin
  477. case t.loc of
  478. LOC_MEM,
  479. LOC_REFERENCE : begin
  480. if t.reference.is_immediate then
  481. internalerror(331)
  482. else
  483. begin
  484. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  485. newreference(t.reference),R_EDI)));
  486. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  487. R_EDI,newreference(ref))));
  488. end;
  489. ungetiftemp(t.reference);
  490. end;
  491. else
  492. internalerror(332);
  493. end;
  494. end;
  495. procedure emit_push_lea_loc(const t:tlocation);
  496. begin
  497. case t.loc of
  498. LOC_MEM,
  499. LOC_REFERENCE : begin
  500. if t.reference.is_immediate then
  501. internalerror(331)
  502. else
  503. begin
  504. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  505. newreference(t.reference),R_EDI)));
  506. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EDI)));
  507. end;
  508. { Wrong !!
  509. ungetiftemp(t.reference);}
  510. end;
  511. else
  512. internalerror(332);
  513. end;
  514. end;
  515. procedure emit_to_reference(var p:ptree);
  516. begin
  517. case p^.location.loc of
  518. LOC_FPU : begin
  519. reset_reference(p^.location.reference);
  520. gettempofsizereference(10,p^.location.reference);
  521. floatstore(pfloatdef(p^.resulttype)^.typ,p^.location.reference);
  522. p^.location.loc:=LOC_REFERENCE;
  523. end;
  524. LOC_MEM,
  525. LOC_REFERENCE : ;
  526. else
  527. internalerror(333);
  528. end;
  529. end;
  530. procedure emit_to_reg16(var hr:tregister);
  531. begin
  532. { ranges are a little bit bug sensitive ! }
  533. case hr of
  534. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP,R_EBP:
  535. begin
  536. hr:=reg32toreg16(hr);
  537. end;
  538. R_AL,R_BL,R_CL,R_DL:
  539. begin
  540. hr:=reg8toreg16(hr);
  541. exprasmlist^.concat(new(pai386,op_const_reg(A_AND,S_W,$ff,hr)));
  542. end;
  543. R_AH,R_BH,R_CH,R_DH:
  544. begin
  545. hr:=reg8toreg16(hr);
  546. exprasmlist^.concat(new(pai386,op_const_reg(A_AND,S_W,$ff00,hr)));
  547. end;
  548. end;
  549. end;
  550. procedure emit_to_reg32(var hr:tregister);
  551. begin
  552. { ranges are a little bit bug sensitive ! }
  553. case hr of
  554. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP,R_BP:
  555. begin
  556. hr:=reg16toreg32(hr);
  557. exprasmlist^.concat(new(pai386,op_const_reg(A_AND,S_L,$ffff,hr)));
  558. end;
  559. R_AL,R_BL,R_CL,R_DL:
  560. begin
  561. hr:=reg8toreg32(hr);
  562. exprasmlist^.concat(new(pai386,op_const_reg(A_AND,S_L,$ff,hr)));
  563. end;
  564. R_AH,R_BH,R_CH,R_DH:
  565. begin
  566. hr:=reg8toreg32(hr);
  567. exprasmlist^.concat(new(pai386,op_const_reg(A_AND,S_L,$ff00,hr)));
  568. end;
  569. end;
  570. end;
  571. {*****************************************************************************
  572. Emit String Functions
  573. *****************************************************************************}
  574. procedure copyshortstring(const dref,sref : treference;len : byte;loadref:boolean);
  575. begin
  576. emitpushreferenceaddr(dref);
  577. if loadref then
  578. emit_push_mem(sref)
  579. else
  580. emitpushreferenceaddr(sref);
  581. push_int(len);
  582. emitcall('FPC_SHORTSTR_COPY');
  583. maybe_loadesi;
  584. end;
  585. procedure copylongstring(const dref,sref : treference;len : longint;loadref:boolean);
  586. begin
  587. emitpushreferenceaddr(dref);
  588. if loadref then
  589. emit_push_mem(sref)
  590. else
  591. emitpushreferenceaddr(sref);
  592. push_int(len);
  593. emitcall('FPC_LONGSTR_COPY');
  594. maybe_loadesi;
  595. end;
  596. procedure decrstringref(t : pdef;const ref : treference);
  597. var
  598. pushedregs : tpushed;
  599. begin
  600. pushusedregisters(pushedregs,$ff);
  601. emitpushreferenceaddr(ref);
  602. if is_ansistring(t) then
  603. begin
  604. exprasmlist^.concat(new(pai386,
  605. op_sym(A_CALL,S_NO,newasmsymbol('FPC_ANSISTR_DECR_REF'))));
  606. end
  607. else if is_widestring(t) then
  608. begin
  609. exprasmlist^.concat(new(pai386,
  610. op_sym(A_CALL,S_NO,newasmsymbol('FPC_WIDESTR_DECR_REF'))));
  611. end
  612. else internalerror(1859);
  613. popusedregisters(pushedregs);
  614. end;
  615. procedure loadansistring(p : ptree);
  616. {
  617. copies an ansistring from p^.right to p^.left, we
  618. assume, that both sides are ansistring, firstassignement have
  619. to take care of that, an ansistring can't be a register variable
  620. }
  621. var
  622. pushed : tpushed;
  623. ungettemp : boolean;
  624. begin
  625. { before pushing any parameter, we have to save all used }
  626. { registers, but before that we have to release the }
  627. { registers of that node to save uneccessary pushed }
  628. { so be careful, if you think you can optimize that code (FK) }
  629. { nevertheless, this has to be changed, because otherwise the }
  630. { register is released before it's contents are pushed -> }
  631. { problems with the optimizer (JM) }
  632. del_reference(p^.left^.location.reference);
  633. ungettemp:=false;
  634. case p^.right^.location.loc of
  635. LOC_REGISTER,LOC_CREGISTER:
  636. begin
  637. {$IfNDef regallocfix}
  638. ungetregister32(p^.right^.location.register);
  639. pushusedregisters(pushed,$ff);
  640. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.right^.location.register)));
  641. {$Else regallocfix}
  642. pushusedregisters(pushed, $ff xor ($80 shr byte(p^.right^.location.register)));
  643. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.right^.location.register)));
  644. ungetregister32(p^.right^.location.register);
  645. {$EndIf regallocfix}
  646. end;
  647. LOC_REFERENCE,LOC_MEM:
  648. begin
  649. {$IfNDef regallocfix}
  650. del_reference(p^.right^.location.reference);
  651. pushusedregisters(pushed,$ff);
  652. emit_push_mem(p^.right^.location.reference);
  653. {$Else regallocfix}
  654. pushusedregisters(pushed,$ff
  655. xor ($80 shr byte(p^.right^.location.reference.base))
  656. xor ($80 shr byte(p^.right^.location.reference.index)));
  657. emit_push_mem(p^.right^.location.reference);
  658. del_reference(p^.right^.location.reference);
  659. {$EndIf regallocfix}
  660. ungettemp:=true;
  661. end;
  662. end;
  663. emitpushreferenceaddr(p^.left^.location.reference);
  664. del_reference(p^.left^.location.reference);
  665. emitcall('FPC_ANSISTR_ASSIGN');
  666. maybe_loadesi;
  667. popusedregisters(pushed);
  668. if ungettemp then
  669. ungetiftemp(p^.right^.location.reference);
  670. end;
  671. {*****************************************************************************
  672. Emit Push Functions
  673. *****************************************************************************}
  674. function maybe_push(needed : byte;p : ptree;isint64 : boolean) : boolean;
  675. var
  676. pushed : boolean;
  677. {hregister : tregister; }
  678. {$ifdef TEMPS_NOT_PUSH}
  679. href : treference;
  680. {$endif TEMPS_NOT_PUSH}
  681. begin
  682. if needed>usablereg32 then
  683. begin
  684. if (p^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  685. begin
  686. if isint64 then
  687. begin
  688. {$ifdef TEMPS_NOT_PUSH}
  689. gettempofsizereference(href,8);
  690. p^.temp_offset:=href.offset;
  691. href.offset:=href.offset+4;
  692. exprasmlist^.concat(new(pai386,op_reg(A_MOV,S_L,p^.location.registerhigh,href)));
  693. href.offset:=href.offset-4;
  694. {$else TEMPS_NOT_PUSH}
  695. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.location.registerhigh)));
  696. {$endif TEMPS_NOT_PUSH}
  697. ungetregister32(p^.location.registerhigh);
  698. end
  699. {$ifdef TEMPS_NOT_PUSH}
  700. else
  701. begin
  702. gettempofsizereference(href,4);
  703. p^.temp_offset:=href.offset;
  704. end
  705. {$endif TEMPS_NOT_PUSH}
  706. ;
  707. pushed:=true;
  708. {$ifdef TEMPS_NOT_PUSH}
  709. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,p^.location.register,href)));
  710. {$else TEMPS_NOT_PUSH}
  711. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.location.register)));
  712. {$endif TEMPS_NOT_PUSH}
  713. ungetregister32(p^.location.register);
  714. end
  715. else if (p^.location.loc in [LOC_MEM,LOC_REFERENCE]) and
  716. ((p^.location.reference.base<>R_NO) or
  717. (p^.location.reference.index<>R_NO)
  718. ) then
  719. begin
  720. del_reference(p^.location.reference);
  721. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(p^.location.reference),
  722. R_EDI)));
  723. {$ifdef TEMPS_NOT_PUSH}
  724. gettempofsizereference(href,4);
  725. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,href)));
  726. p^.temp_offset:=href.offset;
  727. {$else TEMPS_NOT_PUSH}
  728. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EDI)));
  729. {$endif TEMPS_NOT_PUSH}
  730. pushed:=true;
  731. end
  732. else pushed:=false;
  733. end
  734. else pushed:=false;
  735. maybe_push:=pushed;
  736. end;
  737. {$ifdef TEMPS_NOT_PUSH}
  738. function maybe_savetotemp(needed : byte;p : ptree;isint64 : boolean) : boolean;
  739. var
  740. pushed : boolean;
  741. href : treference;
  742. begin
  743. if needed>usablereg32 then
  744. begin
  745. if (p^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  746. begin
  747. if isint64(p^.resulttype) then
  748. begin
  749. gettempofsizereference(href,8);
  750. p^.temp_offset:=href.offset;
  751. href.offset:=href.offset+4;
  752. exprasmlist^.concat(new(pai386,op_reg(A_MOV,S_L,p^.location.registerhigh,href)));
  753. href.offset:=href.offset-4;
  754. ungetregister32(p^.location.registerhigh);
  755. end
  756. else
  757. begin
  758. gettempofsizereference(href,4);
  759. p^.temp_offset:=href.offset;
  760. end;
  761. pushed:=true;
  762. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,p^.location.register,href)));
  763. ungetregister32(p^.location.register);
  764. end
  765. else if (p^.location.loc in [LOC_MEM,LOC_REFERENCE]) and
  766. ((p^.location.reference.base<>R_NO) or
  767. (p^.location.reference.index<>R_NO)
  768. ) then
  769. begin
  770. del_reference(p^.location.reference);
  771. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(p^.location.reference),
  772. R_EDI)));
  773. gettempofsizereference(href,4);
  774. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,href)));
  775. p^.temp_offset:=href.offset;
  776. pushed:=true;
  777. end
  778. else pushed:=false;
  779. end
  780. else pushed:=false;
  781. maybe_push:=pushed;
  782. end;
  783. {$endif TEMPS_NOT_PUSH}
  784. procedure push_int(l : longint);
  785. begin
  786. if (l = 0) and
  787. not(aktoptprocessor in [Class386, ClassP6]) and
  788. not(cs_littlesize in aktglobalswitches)
  789. Then
  790. begin
  791. exprasmlist^.concat(new(pai386,op_reg_reg(A_XOR,S_L,R_EDI,R_EDI)));
  792. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EDI)));
  793. end
  794. else
  795. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,l)));
  796. end;
  797. procedure emit_push_mem(const ref : treference);
  798. begin
  799. if ref.is_immediate then
  800. push_int(ref.offset)
  801. else
  802. begin
  803. if not(aktoptprocessor in [Class386, ClassP6]) and
  804. not(cs_littlesize in aktglobalswitches)
  805. then
  806. begin
  807. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(ref),R_EDI)));
  808. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EDI)));
  809. end
  810. else exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_L,newreference(ref))));
  811. end;
  812. end;
  813. procedure emitpushreferenceaddr(const ref : treference);
  814. var
  815. href : treference;
  816. begin
  817. { this will fail for references to other segments !!! }
  818. if ref.is_immediate then
  819. { is this right ? }
  820. begin
  821. { push_int(ref.offset)}
  822. gettempofsizereference(4,href);
  823. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_L,ref.offset,newreference(href))));
  824. emitpushreferenceaddr(href);
  825. del_reference(href);
  826. end
  827. else
  828. begin
  829. if ref.segment<>R_NO then
  830. CGMessage(cg_e_cant_use_far_pointer_there);
  831. if (ref.base=R_NO) and (ref.index=R_NO) then
  832. exprasmlist^.concat(new(pai386,op_sym_ofs(A_PUSH,S_L,ref.symbol,ref.offset)))
  833. else if (ref.base=R_NO) and (ref.index<>R_NO) and
  834. (ref.offset=0) and (ref.scalefactor=0) and (ref.symbol=nil) then
  835. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,ref.index)))
  836. else if (ref.base<>R_NO) and (ref.index=R_NO) and
  837. (ref.offset=0) and (ref.symbol=nil) then
  838. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,ref.base)))
  839. else
  840. begin
  841. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(ref),R_EDI)));
  842. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EDI)));
  843. end;
  844. end;
  845. end;
  846. procedure pushsetelement(p : ptree);
  847. {
  848. copies p a set element on the stack
  849. }
  850. var
  851. hr,hr16,hr32 : tregister;
  852. begin
  853. { copy the element on the stack, slightly complicated }
  854. if p^.treetype=ordconstn then
  855. begin
  856. if target_os.stackalignment=4 then
  857. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,p^.value)))
  858. else
  859. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_W,p^.value)));
  860. end
  861. else
  862. begin
  863. case p^.location.loc of
  864. LOC_REGISTER,
  865. LOC_CREGISTER :
  866. begin
  867. hr:=p^.location.register;
  868. case hr of
  869. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  870. begin
  871. hr16:=reg32toreg16(hr);
  872. hr32:=hr;
  873. end;
  874. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  875. begin
  876. hr16:=hr;
  877. hr32:=reg16toreg32(hr);
  878. end;
  879. R_AL,R_BL,R_CL,R_DL :
  880. begin
  881. hr16:=reg8toreg16(hr);
  882. hr32:=reg8toreg32(hr);
  883. end;
  884. end;
  885. if target_os.stackalignment=4 then
  886. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,hr32)))
  887. else
  888. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_W,hr16)));
  889. ungetregister32(hr32);
  890. end;
  891. else
  892. begin
  893. if target_os.stackalignment=4 then
  894. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_L,newreference(p^.location.reference))))
  895. else
  896. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_W,newreference(p^.location.reference))));
  897. del_reference(p^.location.reference);
  898. end;
  899. end;
  900. end;
  901. end;
  902. procedure restore(p : ptree;isint64 : boolean);
  903. var
  904. hregister : tregister;
  905. {$ifdef TEMPS_NOT_PUSH}
  906. href : treference;
  907. {$endif TEMPS_NOT_PUSH}
  908. begin
  909. hregister:=getregister32;
  910. {$ifdef TEMPS_NOT_PUSH}
  911. reset_reference(href);
  912. href.base:=procinfo.frame_pointer;
  913. href.offset:=p^.temp_offset;
  914. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,href,hregister)));
  915. {$else TEMPS_NOT_PUSH}
  916. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,hregister)));
  917. {$endif TEMPS_NOT_PUSH}
  918. if (p^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  919. begin
  920. p^.location.register:=hregister;
  921. if isint64 then
  922. begin
  923. p^.location.registerhigh:=getregister32;
  924. {$ifdef TEMPS_NOT_PUSH}
  925. href.offset:=p^.temp_offset+4;
  926. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,p^.location.registerhigh)));
  927. { set correctly for release ! }
  928. href.offset:=p^.temp_offset;
  929. {$else TEMPS_NOT_PUSH}
  930. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,p^.location.registerhigh)));
  931. {$endif TEMPS_NOT_PUSH}
  932. end;
  933. end
  934. else
  935. begin
  936. reset_reference(p^.location.reference);
  937. p^.location.reference.index:=hregister;
  938. set_location(p^.left^.location,p^.location);
  939. end;
  940. {$ifdef TEMPS_NOT_PUSH}
  941. ungetiftemp(href);
  942. {$endif TEMPS_NOT_PUSH}
  943. end;
  944. {$ifdef TEMPS_NOT_PUSH}
  945. procedure restorefromtemp(p : ptree;isint64 : boolean);
  946. var
  947. hregister : tregister;
  948. href : treference;
  949. begin
  950. hregister:=getregister32;
  951. reset_reference(href);
  952. href.base:=procinfo.frame_pointer;
  953. href.offset:=p^.temp_offset;
  954. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,href,hregister)));
  955. if (p^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  956. begin
  957. p^.location.register:=hregister;
  958. if isint64 then
  959. begin
  960. p^.location.registerhigh:=getregister32;
  961. href.offset:=p^.temp_offset+4;
  962. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,p^.location.registerhigh)));
  963. { set correctly for release ! }
  964. href.offset:=p^.temp_offset;
  965. end;
  966. end
  967. else
  968. begin
  969. reset_reference(p^.location.reference);
  970. p^.location.reference.index:=hregister;
  971. set_location(p^.left^.location,p^.location);
  972. end;
  973. ungetiftemp(href);
  974. end;
  975. {$endif TEMPS_NOT_PUSH}
  976. procedure push_value_para(p:ptree;inlined:boolean;para_offset:longint;alignment : longint);
  977. var
  978. tempreference : treference;
  979. r : preference;
  980. opsize : topsize;
  981. op : tasmop;
  982. hreg : tregister;
  983. size : longint;
  984. hlabel : pasmlabel;
  985. begin
  986. case p^.location.loc of
  987. LOC_REGISTER,
  988. LOC_CREGISTER:
  989. begin
  990. case p^.location.register of
  991. R_EAX,R_EBX,R_ECX,R_EDX,R_ESI,
  992. R_EDI,R_ESP,R_EBP :
  993. begin
  994. if p^.resulttype^.size=8 then
  995. begin
  996. inc(pushedparasize,8);
  997. if inlined then
  998. begin
  999. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1000. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  1001. p^.location.registerlow,r)));
  1002. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize+4);
  1003. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  1004. p^.location.registerhigh,r)));
  1005. end
  1006. else
  1007. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.location.registerhigh)));
  1008. ungetregister32(p^.location.registerhigh);
  1009. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.location.registerlow)));
  1010. ungetregister32(p^.location.registerlow);
  1011. end
  1012. else
  1013. begin
  1014. inc(pushedparasize,4);
  1015. if inlined then
  1016. begin
  1017. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1018. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  1019. p^.location.register,r)));
  1020. end
  1021. else
  1022. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.location.register)));
  1023. ungetregister32(p^.location.register);
  1024. end;
  1025. end;
  1026. R_AX,R_BX,R_CX,R_DX,R_SI,R_DI:
  1027. begin
  1028. if alignment=4 then
  1029. begin
  1030. opsize:=S_L;
  1031. hreg:=reg16toreg32(p^.location.register);
  1032. inc(pushedparasize,4);
  1033. end
  1034. else
  1035. begin
  1036. opsize:=S_W;
  1037. hreg:=p^.location.register;
  1038. inc(pushedparasize,2);
  1039. end;
  1040. if inlined then
  1041. begin
  1042. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1043. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,hreg,r)));
  1044. end
  1045. else
  1046. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,opsize,hreg)));
  1047. ungetregister32(reg16toreg32(p^.location.register));
  1048. end;
  1049. R_AL,R_BL,R_CL,R_DL:
  1050. begin
  1051. if alignment=4 then
  1052. begin
  1053. opsize:=S_L;
  1054. hreg:=reg8toreg32(p^.location.register);
  1055. inc(pushedparasize,4);
  1056. end
  1057. else
  1058. begin
  1059. opsize:=S_W;
  1060. hreg:=reg8toreg16(p^.location.register);
  1061. inc(pushedparasize,2);
  1062. end;
  1063. { we must push always 16 bit }
  1064. if inlined then
  1065. begin
  1066. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1067. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,hreg,r)));
  1068. end
  1069. else
  1070. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,opsize,hreg)));
  1071. ungetregister32(reg8toreg32(p^.location.register));
  1072. end;
  1073. else internalerror(1899);
  1074. end;
  1075. end;
  1076. LOC_FPU:
  1077. begin
  1078. size:=align(pfloatdef(p^.resulttype)^.size,alignment);
  1079. inc(pushedparasize,size);
  1080. if not inlined then
  1081. exprasmlist^.concat(new(pai386,op_const_reg(A_SUB,S_L,size,R_ESP)));
  1082. {$ifdef GDB}
  1083. if (cs_debuginfo in aktmoduleswitches) and
  1084. (exprasmlist^.first=exprasmlist^.last) then
  1085. exprasmlist^.concat(new(pai_force_line,init));
  1086. {$endif GDB}
  1087. r:=new_reference(R_ESP,0);
  1088. floatstoreops(pfloatdef(p^.resulttype)^.typ,op,opsize);
  1089. { this is the easiest case for inlined !! }
  1090. if inlined then
  1091. begin
  1092. r^.base:=procinfo.framepointer;
  1093. r^.offset:=para_offset-pushedparasize;
  1094. end;
  1095. exprasmlist^.concat(new(pai386,op_ref(op,opsize,r)));
  1096. end;
  1097. LOC_REFERENCE,LOC_MEM:
  1098. begin
  1099. tempreference:=p^.location.reference;
  1100. del_reference(p^.location.reference);
  1101. case p^.resulttype^.deftype of
  1102. enumdef,
  1103. orddef :
  1104. begin
  1105. case p^.resulttype^.size of
  1106. 8 : begin
  1107. inc(pushedparasize,8);
  1108. if inlined then
  1109. begin
  1110. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  1111. newreference(tempreference),R_EDI)));
  1112. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1113. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1114. inc(tempreference.offset,4);
  1115. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  1116. newreference(tempreference),R_EDI)));
  1117. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize+4);
  1118. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1119. end
  1120. else
  1121. begin
  1122. inc(tempreference.offset,4);
  1123. emit_push_mem(tempreference);
  1124. dec(tempreference.offset,4);
  1125. emit_push_mem(tempreference);
  1126. end;
  1127. end;
  1128. 4 : begin
  1129. inc(pushedparasize,4);
  1130. if inlined then
  1131. begin
  1132. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  1133. newreference(tempreference),R_EDI)));
  1134. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1135. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1136. end
  1137. else
  1138. emit_push_mem(tempreference);
  1139. end;
  1140. 1,2 : begin
  1141. if alignment=4 then
  1142. begin
  1143. opsize:=S_L;
  1144. hreg:=R_EDI;
  1145. inc(pushedparasize,4);
  1146. end
  1147. else
  1148. begin
  1149. opsize:=S_W;
  1150. hreg:=R_DI;
  1151. inc(pushedparasize,2);
  1152. end;
  1153. if inlined then
  1154. begin
  1155. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  1156. newreference(tempreference),hreg)));
  1157. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1158. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,hreg,r)));
  1159. end
  1160. else
  1161. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,opsize,
  1162. newreference(tempreference))));
  1163. end;
  1164. else
  1165. internalerror(234231);
  1166. end;
  1167. end;
  1168. floatdef :
  1169. begin
  1170. case pfloatdef(p^.resulttype)^.typ of
  1171. f32bit,
  1172. s32real :
  1173. begin
  1174. inc(pushedparasize,4);
  1175. if inlined then
  1176. begin
  1177. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  1178. newreference(tempreference),R_EDI)));
  1179. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1180. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1181. end
  1182. else
  1183. emit_push_mem(tempreference);
  1184. end;
  1185. s64real,
  1186. s64comp :
  1187. begin
  1188. inc(pushedparasize,4);
  1189. inc(tempreference.offset,4);
  1190. if inlined then
  1191. begin
  1192. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  1193. newreference(tempreference),R_EDI)));
  1194. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1195. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1196. end
  1197. else
  1198. emit_push_mem(tempreference);
  1199. inc(pushedparasize,4);
  1200. dec(tempreference.offset,4);
  1201. if inlined then
  1202. begin
  1203. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  1204. newreference(tempreference),R_EDI)));
  1205. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1206. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1207. end
  1208. else
  1209. emit_push_mem(tempreference);
  1210. end;
  1211. s80real :
  1212. begin
  1213. inc(pushedparasize,4);
  1214. if alignment=4 then
  1215. inc(tempreference.offset,8)
  1216. else
  1217. inc(tempreference.offset,6);
  1218. if inlined then
  1219. begin
  1220. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  1221. newreference(tempreference),R_EDI)));
  1222. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1223. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1224. end
  1225. else
  1226. emit_push_mem(tempreference);
  1227. dec(tempreference.offset,4);
  1228. inc(pushedparasize,4);
  1229. if inlined then
  1230. begin
  1231. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  1232. newreference(tempreference),R_EDI)));
  1233. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1234. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1235. end
  1236. else
  1237. emit_push_mem(tempreference);
  1238. if alignment=4 then
  1239. begin
  1240. opsize:=S_L;
  1241. hreg:=R_EDI;
  1242. inc(pushedparasize,4);
  1243. dec(tempreference.offset,4);
  1244. end
  1245. else
  1246. begin
  1247. opsize:=S_W;
  1248. hreg:=R_DI;
  1249. inc(pushedparasize,2);
  1250. dec(tempreference.offset,2);
  1251. end;
  1252. if inlined then
  1253. begin
  1254. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  1255. newreference(tempreference),hreg)));
  1256. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1257. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,hreg,r)));
  1258. end
  1259. else
  1260. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,opsize,
  1261. newreference(tempreference))));
  1262. end;
  1263. end;
  1264. end;
  1265. pointerdef,
  1266. procvardef,
  1267. classrefdef:
  1268. begin
  1269. inc(pushedparasize,4);
  1270. if inlined then
  1271. begin
  1272. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  1273. newreference(tempreference),R_EDI)));
  1274. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1275. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1276. end
  1277. else
  1278. emit_push_mem(tempreference);
  1279. end;
  1280. arraydef,
  1281. recorddef,
  1282. stringdef,
  1283. setdef,
  1284. objectdef :
  1285. begin
  1286. { even some structured types are 32 bit }
  1287. if is_widestring(p^.resulttype) or
  1288. is_ansistring(p^.resulttype) or
  1289. is_smallset(p^.resulttype) or
  1290. ((p^.resulttype^.deftype in [recorddef,arraydef]) and (p^.resulttype^.size<=4)
  1291. and ((p^.resulttype^.deftype<>arraydef) or not
  1292. (parraydef(p^.resulttype)^.IsConstructor or
  1293. parraydef(p^.resulttype)^.isArrayOfConst or
  1294. is_open_array(p^.resulttype)))
  1295. ) or
  1296. ((p^.resulttype^.deftype=objectdef) and
  1297. pobjectdef(p^.resulttype)^.isclass) then
  1298. begin
  1299. inc(pushedparasize,4);
  1300. if inlined then
  1301. begin
  1302. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1303. concatcopy(tempreference,r^,4,false,false);
  1304. end
  1305. else
  1306. emit_push_mem(tempreference);
  1307. end
  1308. { call by value open array ? }
  1309. else
  1310. internalerror(8954);
  1311. end;
  1312. else
  1313. CGMessage(cg_e_illegal_expression);
  1314. end;
  1315. end;
  1316. LOC_JUMP:
  1317. begin
  1318. getlabel(hlabel);
  1319. if alignment=4 then
  1320. begin
  1321. opsize:=S_L;
  1322. inc(pushedparasize,4);
  1323. end
  1324. else
  1325. begin
  1326. opsize:=S_W;
  1327. inc(pushedparasize,2);
  1328. end;
  1329. emitlab(truelabel);
  1330. if inlined then
  1331. begin
  1332. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1333. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,opsize,1,r)));
  1334. end
  1335. else
  1336. exprasmlist^.concat(new(pai386,op_const(A_PUSH,opsize,1)));
  1337. emitjmp(C_None,hlabel);
  1338. emitlab(falselabel);
  1339. if inlined then
  1340. begin
  1341. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1342. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,opsize,0,r)));
  1343. end
  1344. else
  1345. exprasmlist^.concat(new(pai386,op_const(A_PUSH,opsize,0)));
  1346. emitlab(hlabel);
  1347. end;
  1348. LOC_FLAGS:
  1349. begin
  1350. if not(R_EAX in unused) then
  1351. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,R_EAX,R_EDI)));
  1352. emit_flag2reg(p^.location.resflags,R_AL);
  1353. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BW,R_AL,R_AX)));
  1354. if alignment=4 then
  1355. begin
  1356. opsize:=S_L;
  1357. hreg:=R_EAX;
  1358. inc(pushedparasize,4);
  1359. end
  1360. else
  1361. begin
  1362. opsize:=S_W;
  1363. hreg:=R_AX;
  1364. inc(pushedparasize,2);
  1365. end;
  1366. if inlined then
  1367. begin
  1368. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1369. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,hreg,r)));
  1370. end
  1371. else
  1372. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,opsize,hreg)));
  1373. if not(R_EAX in unused) then
  1374. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,R_EDI,R_EAX)));
  1375. end;
  1376. {$ifdef SUPPORT_MMX}
  1377. LOC_MMXREGISTER,
  1378. LOC_CMMXREGISTER:
  1379. begin
  1380. inc(pushedparasize,8); { was missing !!! (PM) }
  1381. exprasmlist^.concat(new(pai386,op_const_reg(
  1382. A_SUB,S_L,8,R_ESP)));
  1383. {$ifdef GDB}
  1384. if (cs_debuginfo in aktmoduleswitches) and
  1385. (exprasmlist^.first=exprasmlist^.last) then
  1386. exprasmlist^.concat(new(pai_force_line,init));
  1387. {$endif GDB}
  1388. if inlined then
  1389. begin
  1390. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  1391. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOVQ,S_NO,
  1392. p^.location.register,r)));
  1393. end
  1394. else
  1395. begin
  1396. r:=new_reference(R_ESP,0);
  1397. exprasmlist^.concat(new(pai386,op_reg_ref(
  1398. A_MOVQ,S_NO,p^.location.register,r)));
  1399. end;
  1400. end;
  1401. {$endif SUPPORT_MMX}
  1402. end;
  1403. end;
  1404. {*****************************************************************************
  1405. Emit Float Functions
  1406. *****************************************************************************}
  1407. procedure floatloadops(t : tfloattype;var op : tasmop;var s : topsize);
  1408. begin
  1409. case t of
  1410. s32real : begin
  1411. op:=A_FLD;
  1412. s:=S_FS;
  1413. end;
  1414. s64real : begin
  1415. op:=A_FLD;
  1416. { ???? }
  1417. s:=S_FL;
  1418. end;
  1419. s80real : begin
  1420. op:=A_FLD;
  1421. s:=S_FX;
  1422. end;
  1423. s64comp : begin
  1424. op:=A_FILD;
  1425. s:=S_IQ;
  1426. end;
  1427. else internalerror(17);
  1428. end;
  1429. end;
  1430. procedure floatload(t : tfloattype;const ref : treference);
  1431. var
  1432. op : tasmop;
  1433. s : topsize;
  1434. begin
  1435. floatloadops(t,op,s);
  1436. exprasmlist^.concat(new(pai386,op_ref(op,s,
  1437. newreference(ref))));
  1438. end;
  1439. procedure floatstoreops(t : tfloattype;var op : tasmop;var s : topsize);
  1440. begin
  1441. case t of
  1442. s32real : begin
  1443. op:=A_FSTP;
  1444. s:=S_FS;
  1445. end;
  1446. s64real : begin
  1447. op:=A_FSTP;
  1448. s:=S_FL;
  1449. end;
  1450. s80real : begin
  1451. op:=A_FSTP;
  1452. s:=S_FX;
  1453. end;
  1454. s64comp : begin
  1455. op:=A_FISTP;
  1456. s:=S_IQ;
  1457. end;
  1458. else
  1459. internalerror(17);
  1460. end;
  1461. end;
  1462. procedure floatstore(t : tfloattype;const ref : treference);
  1463. var
  1464. op : tasmop;
  1465. s : topsize;
  1466. begin
  1467. floatstoreops(t,op,s);
  1468. exprasmlist^.concat(new(pai386,op_ref(op,s,
  1469. newreference(ref))));
  1470. end;
  1471. {*****************************************************************************
  1472. Emit Functions
  1473. *****************************************************************************}
  1474. procedure maketojumpbool(p : ptree);
  1475. {
  1476. produces jumps to true respectively false labels using boolean expressions
  1477. }
  1478. var
  1479. opsize : topsize;
  1480. storepos : tfileposinfo;
  1481. begin
  1482. if p^.error then
  1483. exit;
  1484. storepos:=aktfilepos;
  1485. aktfilepos:=p^.fileinfo;
  1486. if is_boolean(p^.resulttype) then
  1487. begin
  1488. if is_constboolnode(p) then
  1489. begin
  1490. if p^.value<>0 then
  1491. emitjmp(C_None,truelabel)
  1492. else
  1493. emitjmp(C_None,falselabel);
  1494. end
  1495. else
  1496. begin
  1497. opsize:=def_opsize(p^.resulttype);
  1498. case p^.location.loc of
  1499. LOC_CREGISTER,LOC_REGISTER : begin
  1500. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,opsize,p^.location.register,
  1501. p^.location.register)));
  1502. ungetregister(p^.location.register);
  1503. emitjmp(C_NZ,truelabel);
  1504. emitjmp(C_None,falselabel);
  1505. end;
  1506. LOC_MEM,LOC_REFERENCE : begin
  1507. exprasmlist^.concat(new(pai386,op_const_ref(
  1508. A_CMP,opsize,0,newreference(p^.location.reference))));
  1509. del_reference(p^.location.reference);
  1510. emitjmp(C_NZ,truelabel);
  1511. emitjmp(C_None,falselabel);
  1512. end;
  1513. LOC_FLAGS : begin
  1514. emitjmp(flag_2_cond[p^.location.resflags],truelabel);
  1515. emitjmp(C_None,falselabel);
  1516. end;
  1517. end;
  1518. end;
  1519. end
  1520. else
  1521. CGMessage(type_e_mismatch);
  1522. aktfilepos:=storepos;
  1523. end;
  1524. { produces if necessary overflowcode }
  1525. procedure emitoverflowcheck(p:ptree);
  1526. var
  1527. hl : pasmlabel;
  1528. begin
  1529. if not(cs_check_overflow in aktlocalswitches) then
  1530. exit;
  1531. getlabel(hl);
  1532. if not ((p^.resulttype^.deftype=pointerdef) or
  1533. ((p^.resulttype^.deftype=orddef) and
  1534. (porddef(p^.resulttype)^.typ in [u64bit,u16bit,u32bit,u8bit,uchar,
  1535. bool8bit,bool16bit,bool32bit]))) then
  1536. emitjmp(C_NO,hl)
  1537. else
  1538. emitjmp(C_NB,hl);
  1539. emitcall('FPC_OVERFLOW');
  1540. emitlab(hl);
  1541. end;
  1542. { produces range check code, while one of the operands is a 64 bit
  1543. integer }
  1544. procedure emitrangecheck64(p : ptree;todef : pdef);
  1545. begin
  1546. internalerror(28699);
  1547. end;
  1548. { produces if necessary rangecheckcode }
  1549. procedure emitrangecheck(p:ptree;todef:pdef);
  1550. {
  1551. generate range checking code for the value at location t. The
  1552. type used is the checked against todefs ranges. fromdef (p.resulttype)
  1553. is the original type used at that location, when both defs are
  1554. equal the check is also insert (needed for succ,pref,inc,dec)
  1555. }
  1556. var
  1557. neglabel,
  1558. poslabel : pasmlabel;
  1559. href : treference;
  1560. rstr : string;
  1561. hreg : tregister;
  1562. opsize : topsize;
  1563. op : tasmop;
  1564. fromdef : pdef;
  1565. lto,hto,
  1566. lfrom,hfrom : longint;
  1567. doublebound,
  1568. is_reg,
  1569. popecx : boolean;
  1570. begin
  1571. { range checking on and range checkable value? }
  1572. if not(cs_check_range in aktlocalswitches) or
  1573. not(todef^.deftype in [orddef,enumdef,arraydef]) then
  1574. exit;
  1575. { only check when assigning to scalar, subranges are different,
  1576. when todef=fromdef then the check is always generated }
  1577. fromdef:=p^.resulttype;
  1578. if is_64bitint(fromdef) or is_64bitint(todef) then
  1579. begin
  1580. emitrangecheck64(p,todef);
  1581. exit;
  1582. end;
  1583. {we also need lto and hto when checking if we need to use doublebound!
  1584. (JM)}
  1585. getrange(todef,lto,hto);
  1586. if todef<>fromdef then
  1587. begin
  1588. getrange(p^.resulttype,lfrom,hfrom);
  1589. { first check for not being u32bit, then if the to is bigger than
  1590. from }
  1591. if (lto<hto) and (lfrom<hfrom) and
  1592. (lto<=lfrom) and (hto>=hfrom) then
  1593. exit;
  1594. end;
  1595. { generate the rangecheck code for the def where we are going to
  1596. store the result }
  1597. doublebound:=false;
  1598. case todef^.deftype of
  1599. orddef :
  1600. begin
  1601. porddef(todef)^.genrangecheck;
  1602. rstr:=porddef(todef)^.getrangecheckstring;
  1603. doublebound:=(porddef(todef)^.typ=u32bit) and (lto>hto);
  1604. end;
  1605. enumdef :
  1606. begin
  1607. penumdef(todef)^.genrangecheck;
  1608. rstr:=penumdef(todef)^.getrangecheckstring;
  1609. end;
  1610. arraydef :
  1611. begin
  1612. parraydef(todef)^.genrangecheck;
  1613. rstr:=parraydef(todef)^.getrangecheckstring;
  1614. end;
  1615. end;
  1616. { get op and opsize }
  1617. opsize:=def2def_opsize(fromdef,u32bitdef);
  1618. if opsize in [S_B,S_W,S_L] then
  1619. op:=A_MOV
  1620. else
  1621. if is_signed(fromdef) then
  1622. op:=A_MOVSX
  1623. else
  1624. op:=A_MOVZX;
  1625. is_reg:=(p^.location.loc in [LOC_REGISTER,LOC_CREGISTER]);
  1626. if is_reg then
  1627. hreg:=p^.location.register;
  1628. if not target_os.use_bound_instruction then
  1629. begin
  1630. { FPC_BOUNDCHECK needs to be called with
  1631. %ecx - value
  1632. %edi - pointer to the ranges }
  1633. popecx:=false;
  1634. if not(is_reg) or
  1635. (p^.location.register<>R_ECX) then
  1636. begin
  1637. if not(R_ECX in unused) then
  1638. begin
  1639. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ECX)));
  1640. popecx:=true;
  1641. end;
  1642. if is_reg then
  1643. exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,p^.location.register,R_ECX)))
  1644. else
  1645. exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,newreference(p^.location.reference),R_ECX)));
  1646. end;
  1647. if doublebound then
  1648. begin
  1649. getlabel(neglabel);
  1650. getlabel(poslabel);
  1651. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,R_ECX,R_ECX)));
  1652. emitjmp(C_L,neglabel);
  1653. end;
  1654. { insert bound instruction only }
  1655. exprasmlist^.concat(new(pai386,op_sym_ofs_reg(A_MOV,S_L,newasmsymbol(rstr),0,R_EDI)));
  1656. emitcall('FPC_BOUNDCHECK');
  1657. { u32bit needs 2 checks }
  1658. if doublebound then
  1659. begin
  1660. emitjmp(C_None,poslabel);
  1661. emitlab(neglabel);
  1662. exprasmlist^.concat(new(pai386,op_sym_ofs_reg(A_MOV,S_L,newasmsymbol(rstr),8,R_EDI)));
  1663. emitcall('FPC_BOUNDCHECK');
  1664. emitlab(poslabel);
  1665. end;
  1666. if popecx then
  1667. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_ECX)));
  1668. end
  1669. else
  1670. begin
  1671. reset_reference(href);
  1672. href.symbol:=newasmsymbol(rstr);
  1673. { load the value in a register }
  1674. if is_reg then
  1675. begin
  1676. { be sure that hreg is a 32 bit reg, if not load it in %edi }
  1677. if p^.location.register in [R_EAX..R_EDI] then
  1678. hreg:=p^.location.register
  1679. else
  1680. begin
  1681. exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,p^.location.register,R_EDI)));
  1682. hreg:=R_EDI;
  1683. end;
  1684. end
  1685. else
  1686. begin
  1687. exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,newreference(p^.location.reference),R_EDI)));
  1688. hreg:=R_EDI;
  1689. end;
  1690. if doublebound then
  1691. begin
  1692. getlabel(neglabel);
  1693. getlabel(poslabel);
  1694. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,hreg,hreg)));
  1695. emitjmp(C_L,neglabel);
  1696. end;
  1697. { insert bound instruction only }
  1698. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,hreg,newreference(href))));
  1699. { u32bit needs 2 checks }
  1700. if doublebound then
  1701. begin
  1702. href.offset:=8;
  1703. emitjmp(C_None,poslabel);
  1704. emitlab(neglabel);
  1705. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,hreg,newreference(href))));
  1706. emitlab(poslabel);
  1707. end;
  1708. end;
  1709. end;
  1710. procedure concatcopy(source,dest : treference;size : longint;delsource,loadref : boolean);
  1711. const
  1712. isizes : array[0..3] of topsize=(S_L,S_B,S_W,S_B);
  1713. ishr : array[0..3] of byte=(2,0,1,0);
  1714. var
  1715. ecxpushed : boolean;
  1716. helpsize : longint;
  1717. i : byte;
  1718. reg8,reg32 : tregister;
  1719. swap : boolean;
  1720. procedure maybepushecx;
  1721. begin
  1722. if not(R_ECX in unused) then
  1723. begin
  1724. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ECX)));
  1725. ecxpushed:=true;
  1726. end;
  1727. end;
  1728. begin
  1729. {$IfNDef regallocfix}
  1730. If delsource then
  1731. del_reference(source);
  1732. {$EndIf regallocfix}
  1733. if (not loadref) and
  1734. ((size<=8) or
  1735. (not(cs_littlesize in aktglobalswitches ) and (size<=12))) then
  1736. begin
  1737. helpsize:=size shr 2;
  1738. for i:=1 to helpsize do
  1739. begin
  1740. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(source),R_EDI)));
  1741. {$ifdef regallocfix}
  1742. If (size = 4) and delsource then
  1743. del_reference(source);
  1744. {$endif regallocfix}
  1745. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,newreference(dest))));
  1746. inc(source.offset,4);
  1747. inc(dest.offset,4);
  1748. dec(size,4);
  1749. end;
  1750. if size>1 then
  1751. begin
  1752. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_W,newreference(source),R_DI)));
  1753. {$ifdef regallocfix}
  1754. If (size = 2) and delsource then
  1755. del_reference(source);
  1756. {$endif regallocfix}
  1757. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_W,R_DI,newreference(dest))));
  1758. inc(source.offset,2);
  1759. inc(dest.offset,2);
  1760. dec(size,2);
  1761. end;
  1762. if size>0 then
  1763. begin
  1764. { and now look for an 8 bit register }
  1765. swap:=false;
  1766. if R_EAX in unused then reg8:=R_AL
  1767. else if R_EBX in unused then reg8:=R_BL
  1768. else if R_ECX in unused then reg8:=R_CL
  1769. else if R_EDX in unused then reg8:=R_DL
  1770. else
  1771. begin
  1772. swap:=true;
  1773. { we need only to check 3 registers, because }
  1774. { one is always not index or base }
  1775. if (dest.base<>R_EAX) and (dest.index<>R_EAX) then
  1776. begin
  1777. reg8:=R_AL;
  1778. reg32:=R_EAX;
  1779. end
  1780. else if (dest.base<>R_EBX) and (dest.index<>R_EBX) then
  1781. begin
  1782. reg8:=R_BL;
  1783. reg32:=R_EBX;
  1784. end
  1785. else if (dest.base<>R_ECX) and (dest.index<>R_ECX) then
  1786. begin
  1787. reg8:=R_CL;
  1788. reg32:=R_ECX;
  1789. end;
  1790. end;
  1791. if swap then
  1792. { was earlier XCHG, of course nonsense }
  1793. emit_reg_reg(A_MOV,S_L,reg32,R_EDI);
  1794. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_B,newreference(source),reg8)));
  1795. {$ifdef regallocfix}
  1796. If delsource then
  1797. del_reference(source);
  1798. {$endif regallocfix}
  1799. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_B,reg8,newreference(dest))));
  1800. if swap then
  1801. emit_reg_reg(A_MOV,S_L,R_EDI,reg32);
  1802. end;
  1803. end
  1804. else
  1805. begin
  1806. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(dest),R_EDI)));
  1807. {$ifdef regallocfix}
  1808. {is this ok?? (JM)}
  1809. del_reference(dest);
  1810. {$endif regallocfix}
  1811. if loadref then
  1812. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(source),R_ESI)))
  1813. else
  1814. begin
  1815. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(source),R_ESI)));
  1816. {$ifdef regallocfix}
  1817. if delsource then
  1818. del_reference(source);
  1819. {$endif regallocfix}
  1820. end;
  1821. exprasmlist^.concat(new(pai386,op_none(A_CLD,S_NO)));
  1822. ecxpushed:=false;
  1823. if cs_littlesize in aktglobalswitches then
  1824. begin
  1825. maybepushecx;
  1826. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,S_L,size,R_ECX)));
  1827. exprasmlist^.concat(new(pai386,op_none(A_REP,S_NO)));
  1828. exprasmlist^.concat(new(pai386,op_none(A_MOVSB,S_NO)));
  1829. end
  1830. else
  1831. begin
  1832. helpsize:=size shr 2;
  1833. size:=size and 3;
  1834. if helpsize>1 then
  1835. begin
  1836. maybepushecx;
  1837. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,S_L,helpsize,R_ECX)));
  1838. exprasmlist^.concat(new(pai386,op_none(A_REP,S_NO)));
  1839. end;
  1840. if helpsize>0 then
  1841. exprasmlist^.concat(new(pai386,op_none(A_MOVSD,S_NO)));
  1842. if size>1 then
  1843. begin
  1844. dec(size,2);
  1845. exprasmlist^.concat(new(pai386,op_none(A_MOVSW,S_NO)));
  1846. end;
  1847. if size=1 then
  1848. exprasmlist^.concat(new(pai386,op_none(A_MOVSB,S_NO)));
  1849. end;
  1850. if ecxpushed then
  1851. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_ECX)));
  1852. { loading SELF-reference again }
  1853. maybe_loadesi;
  1854. end;
  1855. if delsource then
  1856. ungetiftemp(source);
  1857. end;
  1858. procedure emitloadord2reg(const location:Tlocation;orddef:Porddef;
  1859. destreg:Tregister;delloc:boolean);
  1860. {A lot smaller and less bug sensitive than the original unfolded loads.}
  1861. var tai:Pai386;
  1862. r:Preference;
  1863. begin
  1864. case location.loc of
  1865. LOC_REGISTER,LOC_CREGISTER:
  1866. begin
  1867. case orddef^.typ of
  1868. u8bit:
  1869. tai:=new(pai386,op_reg_reg(A_MOVZX,S_BL,location.register,destreg));
  1870. s8bit:
  1871. tai:=new(pai386,op_reg_reg(A_MOVSX,S_BL,location.register,destreg));
  1872. u16bit:
  1873. tai:=new(pai386,op_reg_reg(A_MOVZX,S_WL,location.register,destreg));
  1874. s16bit:
  1875. tai:=new(pai386,op_reg_reg(A_MOVSX,S_WL,location.register,destreg));
  1876. u32bit:
  1877. tai:=new(pai386,op_reg_reg(A_MOV,S_L,location.register,destreg));
  1878. s32bit:
  1879. tai:=new(pai386,op_reg_reg(A_MOV,S_L,location.register,destreg));
  1880. end;
  1881. if delloc then
  1882. ungetregister(location.register);
  1883. end;
  1884. LOC_MEM,
  1885. LOC_REFERENCE:
  1886. begin
  1887. if location.reference.is_immediate then
  1888. tai:=new(pai386,op_const_reg(A_MOV,S_L,location.reference.offset,destreg))
  1889. else
  1890. begin
  1891. r:=newreference(location.reference);
  1892. case orddef^.typ of
  1893. u8bit:
  1894. tai:=new(pai386,op_ref_reg(A_MOVZX,S_BL,r,destreg));
  1895. s8bit:
  1896. tai:=new(pai386,op_ref_reg(A_MOVSX,S_BL,r,destreg));
  1897. u16bit:
  1898. tai:=new(pai386,op_ref_reg(A_MOVZX,S_WL,r,destreg));
  1899. s16bit:
  1900. tai:=new(pai386,op_ref_reg(A_MOVSX,S_WL,r,destreg));
  1901. u32bit:
  1902. tai:=new(pai386,op_ref_reg(A_MOV,S_L,r,destreg));
  1903. s32bit:
  1904. tai:=new(pai386,op_ref_reg(A_MOV,S_L,r,destreg));
  1905. end;
  1906. end;
  1907. if delloc then
  1908. del_reference(location.reference);
  1909. end
  1910. else
  1911. internalerror(6);
  1912. end;
  1913. exprasmlist^.concat(tai);
  1914. end;
  1915. { if necessary ESI is reloaded after a call}
  1916. procedure maybe_loadesi;
  1917. var
  1918. hp : preference;
  1919. p : pprocinfo;
  1920. i : longint;
  1921. begin
  1922. if assigned(procinfo._class) then
  1923. begin
  1924. if lexlevel>normal_function_level then
  1925. begin
  1926. new(hp);
  1927. reset_reference(hp^);
  1928. hp^.offset:=procinfo.framepointer_offset;
  1929. hp^.base:=procinfo.framepointer;
  1930. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,R_ESI)));
  1931. p:=procinfo.parent;
  1932. for i:=3 to lexlevel-1 do
  1933. begin
  1934. new(hp);
  1935. reset_reference(hp^);
  1936. hp^.offset:=p^.framepointer_offset;
  1937. hp^.base:=R_ESI;
  1938. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,R_ESI)));
  1939. p:=p^.parent;
  1940. end;
  1941. new(hp);
  1942. reset_reference(hp^);
  1943. hp^.offset:=p^.ESI_offset;
  1944. hp^.base:=R_ESI;
  1945. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,R_ESI)));
  1946. end
  1947. else
  1948. begin
  1949. new(hp);
  1950. reset_reference(hp^);
  1951. hp^.offset:=procinfo.ESI_offset;
  1952. hp^.base:=procinfo.framepointer;
  1953. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,R_ESI)));
  1954. end;
  1955. end;
  1956. end;
  1957. procedure firstcomplex(p : ptree);
  1958. var
  1959. hp : ptree;
  1960. begin
  1961. { always calculate boolean AND and OR from left to right }
  1962. if (p^.treetype in [orn,andn]) and
  1963. (p^.left^.resulttype^.deftype=orddef) and
  1964. (porddef(p^.left^.resulttype)^.typ in [bool8bit,bool16bit,bool32bit]) then
  1965. p^.swaped:=false
  1966. else
  1967. if (p^.left^.registers32<p^.right^.registers32) and
  1968. { the following check is appropriate, because all }
  1969. { 4 registers are rarely used and it is thereby }
  1970. { achieved that the extra code is being dropped }
  1971. { by exchanging not commutative operators }
  1972. (p^.right^.registers32<=4) then
  1973. begin
  1974. hp:=p^.left;
  1975. p^.left:=p^.right;
  1976. p^.right:=hp;
  1977. p^.swaped:=true;
  1978. end
  1979. else
  1980. p^.swaped:=false;
  1981. end;
  1982. {*****************************************************************************
  1983. Entry/Exit Code Functions
  1984. *****************************************************************************}
  1985. procedure genprofilecode;
  1986. var
  1987. pl : pasmlabel;
  1988. begin
  1989. if (aktprocsym^.definition^.options and poassembler)<>0 then
  1990. exit;
  1991. case target_info.target of
  1992. target_i386_linux:
  1993. begin
  1994. getlabel(pl);
  1995. emitcall('mcount');
  1996. exprasmlist^.insert(new(pai386,op_sym_ofs_reg(A_MOV,S_L,pl,0,R_EDX)));
  1997. exprasmlist^.insert(new(pai_section,init(sec_code)));
  1998. exprasmlist^.insert(new(pai_const,init_32bit(0)));
  1999. exprasmlist^.insert(new(pai_label,init(pl)));
  2000. exprasmlist^.insert(new(pai_align,init(4)));
  2001. exprasmlist^.insert(new(pai_section,init(sec_data)));
  2002. end;
  2003. target_i386_go32v2:
  2004. begin
  2005. exprasmlist^.insert(new(pai386,op_sym(A_CALL,S_NO,newasmsymbol('MCOUNT'))));
  2006. end;
  2007. end;
  2008. end;
  2009. procedure generate_interrupt_stackframe_entry;
  2010. begin
  2011. { save the registers of an interrupt procedure }
  2012. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_L,R_EAX)));
  2013. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_L,R_EBX)));
  2014. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_L,R_ECX)));
  2015. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_L,R_EDX)));
  2016. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_L,R_ESI)));
  2017. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_L,R_EDI)));
  2018. { .... also the segment registers }
  2019. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_W,R_DS)));
  2020. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_W,R_ES)));
  2021. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_W,R_FS)));
  2022. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_W,R_GS)));
  2023. end;
  2024. procedure generate_interrupt_stackframe_exit;
  2025. begin
  2026. { restore the registers of an interrupt procedure }
  2027. { this was all with entrycode instead of exitcode !!}
  2028. procinfo.aktexitcode^.concat(new(pai386,op_reg(A_POP,S_L,R_EAX)));
  2029. procinfo.aktexitcode^.concat(new(pai386,op_reg(A_POP,S_L,R_EBX)));
  2030. procinfo.aktexitcode^.concat(new(pai386,op_reg(A_POP,S_L,R_ECX)));
  2031. procinfo.aktexitcode^.concat(new(pai386,op_reg(A_POP,S_L,R_EDX)));
  2032. procinfo.aktexitcode^.concat(new(pai386,op_reg(A_POP,S_L,R_ESI)));
  2033. procinfo.aktexitcode^.concat(new(pai386,op_reg(A_POP,S_L,R_EDI)));
  2034. { .... also the segment registers }
  2035. procinfo.aktexitcode^.concat(new(pai386,op_reg(A_POP,S_W,R_DS)));
  2036. procinfo.aktexitcode^.concat(new(pai386,op_reg(A_POP,S_W,R_ES)));
  2037. procinfo.aktexitcode^.concat(new(pai386,op_reg(A_POP,S_W,R_FS)));
  2038. procinfo.aktexitcode^.concat(new(pai386,op_reg(A_POP,S_W,R_GS)));
  2039. { this restores the flags }
  2040. procinfo.aktexitcode^.concat(new(pai386,op_none(A_IRET,S_NO)));
  2041. end;
  2042. { generates the code for threadvar initialisation }
  2043. procedure initialize_threadvar(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  2044. var
  2045. hr : treference;
  2046. begin
  2047. if (psym(p)^.typ=varsym) and
  2048. ((pvarsym(p)^.var_options and vo_is_thread_var)<>0) then
  2049. begin
  2050. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,pvarsym(p)^.getsize)));
  2051. reset_reference(hr);
  2052. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  2053. emitpushreferenceaddr(hr);
  2054. exprasmlist^.concat(new(pai386,
  2055. op_sym(A_CALL,S_NO,newasmsymbol('FPC_INIT_THREADVAR'))));
  2056. end;
  2057. end;
  2058. { initilizes data of type t }
  2059. { if is_already_ref is true then the routines assumes }
  2060. { that r points to the data to initialize }
  2061. procedure initialize(t : pdef;const ref : treference;is_already_ref : boolean);
  2062. var
  2063. hr : treference;
  2064. begin
  2065. if is_ansistring(t) or
  2066. is_widestring(t) then
  2067. begin
  2068. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_L,0,
  2069. newreference(ref))));
  2070. end
  2071. else
  2072. begin
  2073. reset_reference(hr);
  2074. hr.symbol:=t^.get_inittable_label;
  2075. emitpushreferenceaddr(hr);
  2076. if is_already_ref then
  2077. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_L,
  2078. newreference(ref))))
  2079. else
  2080. emitpushreferenceaddr(ref);
  2081. exprasmlist^.concat(new(pai386,
  2082. op_sym(A_CALL,S_NO,newasmsymbol('FPC_INITIALIZE'))));
  2083. end;
  2084. end;
  2085. { finalizes data of type t }
  2086. { if is_already_ref is true then the routines assumes }
  2087. { that r points to the data to finalizes }
  2088. procedure finalize(t : pdef;const ref : treference;is_already_ref : boolean);
  2089. var
  2090. r : treference;
  2091. begin
  2092. if is_ansistring(t) or
  2093. is_widestring(t) then
  2094. begin
  2095. decrstringref(t,ref);
  2096. end
  2097. else
  2098. begin
  2099. reset_reference(r);
  2100. r.symbol:=t^.get_inittable_label;
  2101. emitpushreferenceaddr(r);
  2102. if is_already_ref then
  2103. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_L,
  2104. newreference(ref))))
  2105. else
  2106. emitpushreferenceaddr(ref);
  2107. emitcall('FPC_FINALIZE');
  2108. end;
  2109. end;
  2110. { generates the code for initialisation of local data }
  2111. procedure initialize_data(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  2112. var
  2113. hr : treference;
  2114. begin
  2115. if (psym(p)^.typ=varsym) and
  2116. assigned(pvarsym(p)^.definition) and
  2117. not((pvarsym(p)^.definition^.deftype=objectdef) and
  2118. pobjectdef(pvarsym(p)^.definition)^.isclass) and
  2119. pvarsym(p)^.definition^.needs_inittable then
  2120. begin
  2121. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  2122. reset_reference(hr);
  2123. if psym(p)^.owner^.symtabletype=localsymtable then
  2124. begin
  2125. hr.base:=procinfo.framepointer;
  2126. hr.offset:=-pvarsym(p)^.address;
  2127. end
  2128. else
  2129. begin
  2130. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  2131. end;
  2132. initialize(pvarsym(p)^.definition,hr,false);
  2133. end;
  2134. end;
  2135. { generates the code for incrementing the reference count of parameters }
  2136. procedure incr_data(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  2137. var
  2138. hr : treference;
  2139. begin
  2140. if (psym(p)^.typ=varsym) and
  2141. not((pvarsym(p)^.definition^.deftype=objectdef) and
  2142. pobjectdef(pvarsym(p)^.definition)^.isclass) and
  2143. pvarsym(p)^.definition^.needs_inittable and
  2144. ((pvarsym(p)^.varspez=vs_value) {or
  2145. (pvarsym(p)^.varspez=vs_const) and
  2146. not(dont_copy_const_param(pvarsym(p)^.definition))}) then
  2147. begin
  2148. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  2149. reset_reference(hr);
  2150. hr.symbol:=pvarsym(p)^.definition^.get_inittable_label;
  2151. emitpushreferenceaddr(hr);
  2152. reset_reference(hr);
  2153. hr.base:=procinfo.framepointer;
  2154. hr.offset:=pvarsym(p)^.address+procinfo.call_offset;
  2155. emitpushreferenceaddr(hr);
  2156. reset_reference(hr);
  2157. exprasmlist^.concat(new(pai386,
  2158. op_sym(A_CALL,S_NO,newasmsymbol('FPC_ADDREF'))));
  2159. end;
  2160. end;
  2161. { generates the code for finalisation of local data }
  2162. procedure finalize_data(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  2163. var
  2164. hr : treference;
  2165. begin
  2166. if (psym(p)^.typ=varsym) and
  2167. assigned(pvarsym(p)^.definition) and
  2168. not((pvarsym(p)^.definition^.deftype=objectdef) and
  2169. pobjectdef(pvarsym(p)^.definition)^.isclass) and
  2170. pvarsym(p)^.definition^.needs_inittable then
  2171. begin
  2172. { not all kind of parameters need to be finalized }
  2173. if (psym(p)^.owner^.symtabletype=parasymtable) and
  2174. ((pvarsym(p)^.varspez=vs_var) or
  2175. (pvarsym(p)^.varspez=vs_const) { and
  2176. (dont_copy_const_param(pvarsym(p)^.definition)) } ) then
  2177. exit;
  2178. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  2179. reset_reference(hr);
  2180. case psym(p)^.owner^.symtabletype of
  2181. localsymtable:
  2182. begin
  2183. hr.base:=procinfo.framepointer;
  2184. hr.offset:=-pvarsym(p)^.address;
  2185. end;
  2186. parasymtable:
  2187. begin
  2188. hr.base:=procinfo.framepointer;
  2189. hr.offset:=pvarsym(p)^.address+procinfo.call_offset;
  2190. end;
  2191. else
  2192. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  2193. end;
  2194. finalize(pvarsym(p)^.definition,hr,false);
  2195. end;
  2196. end;
  2197. { generates the code to make local copies of the value parameters }
  2198. procedure copyvalueparas(p : pnamedindexobject);{$ifndef fpc}far;{$endif}
  2199. var
  2200. href1,href2 : treference;
  2201. r : preference;
  2202. len : longint;
  2203. opsize : topsize;
  2204. again,ok : pasmlabel;
  2205. begin
  2206. if (psym(p)^.typ=varsym) and
  2207. (pvarsym(p)^.varspez=vs_value) and
  2208. (push_addr_param(pvarsym(p)^.definition)) then
  2209. begin
  2210. if is_open_array(pvarsym(p)^.definition) or
  2211. is_array_of_const(pvarsym(p)^.definition) then
  2212. begin
  2213. { get stack space }
  2214. new(r);
  2215. reset_reference(r^);
  2216. r^.base:=procinfo.framepointer;
  2217. r^.offset:=pvarsym(p)^.address+4+procinfo.call_offset;
  2218. exprasmlist^.concat(new(pai386,
  2219. op_ref_reg(A_MOV,S_L,r,R_EDI)));
  2220. exprasmlist^.concat(new(pai386,
  2221. op_reg(A_INC,S_L,R_EDI)));
  2222. exprasmlist^.concat(new(pai386,
  2223. op_const_reg(A_IMUL,S_L,
  2224. parraydef(pvarsym(p)^.definition)^.definition^.size,R_EDI)));
  2225. { windows guards only a few pages for stack growing, }
  2226. { so we have to access every page first }
  2227. if target_os.id=os_i386_win32 then
  2228. begin
  2229. getlabel(again);
  2230. getlabel(ok);
  2231. emitlab(again);
  2232. exprasmlist^.concat(new(pai386,
  2233. op_const_reg(A_CMP,S_L,winstackpagesize,R_EDI)));
  2234. emitjmp(C_C,ok);
  2235. exprasmlist^.concat(new(pai386,
  2236. op_const_reg(A_SUB,S_L,winstackpagesize-4,R_ESP)));
  2237. exprasmlist^.concat(new(pai386,
  2238. op_reg(A_PUSH,S_L,R_EAX)));
  2239. exprasmlist^.concat(new(pai386,
  2240. op_const_reg(A_SUB,S_L,winstackpagesize,R_EDI)));
  2241. emitjmp(C_None,again);
  2242. emitlab(ok);
  2243. exprasmlist^.concat(new(pai386,
  2244. op_reg_reg(A_SUB,S_L,R_EDI,R_ESP)));
  2245. { now reload EDI }
  2246. new(r);
  2247. reset_reference(r^);
  2248. r^.base:=procinfo.framepointer;
  2249. r^.offset:=pvarsym(p)^.address+4+procinfo.call_offset;
  2250. exprasmlist^.concat(new(pai386,
  2251. op_ref_reg(A_MOV,S_L,r,R_EDI)));
  2252. exprasmlist^.concat(new(pai386,
  2253. op_reg(A_INC,S_L,R_EDI)));
  2254. exprasmlist^.concat(new(pai386,
  2255. op_const_reg(A_IMUL,S_L,
  2256. parraydef(pvarsym(p)^.definition)^.definition^.size,R_EDI)));
  2257. end
  2258. else
  2259. begin
  2260. exprasmlist^.concat(new(pai386,
  2261. op_reg_reg(A_SUB,S_L,R_EDI,R_ESP)));
  2262. { load destination }
  2263. exprasmlist^.concat(new(pai386,
  2264. op_reg_reg(A_MOV,S_L,R_ESP,R_EDI)));
  2265. end;
  2266. { don't destroy the registers! }
  2267. exprasmlist^.concat(new(pai386,
  2268. op_reg(A_PUSH,S_L,R_ECX)));
  2269. exprasmlist^.concat(new(pai386,
  2270. op_reg(A_PUSH,S_L,R_ESI)));
  2271. { load count }
  2272. new(r);
  2273. reset_reference(r^);
  2274. r^.base:=procinfo.framepointer;
  2275. r^.offset:=pvarsym(p)^.address+4+procinfo.call_offset;
  2276. exprasmlist^.concat(new(pai386,
  2277. op_ref_reg(A_MOV,S_L,r,R_ECX)));
  2278. { load source }
  2279. new(r);
  2280. reset_reference(r^);
  2281. r^.base:=procinfo.framepointer;
  2282. r^.offset:=pvarsym(p)^.address+procinfo.call_offset;
  2283. exprasmlist^.concat(new(pai386,
  2284. op_ref_reg(A_MOV,S_L,r,R_ESI)));
  2285. { scheduled .... }
  2286. exprasmlist^.concat(new(pai386,
  2287. op_reg(A_INC,S_L,R_ECX)));
  2288. { calculate size }
  2289. len:=parraydef(pvarsym(p)^.definition)^.definition^.size;
  2290. opsize:=S_B;
  2291. if (len and 3)=0 then
  2292. begin
  2293. opsize:=S_L;
  2294. len:=len shr 2;
  2295. end
  2296. else
  2297. if (len and 1)=0 then
  2298. begin
  2299. opsize:=S_W;
  2300. len:=len shr 1;
  2301. end;
  2302. exprasmlist^.concat(new(pai386,
  2303. op_const_reg(A_IMUL,S_L,len,R_ECX)));
  2304. exprasmlist^.concat(new(pai386,
  2305. op_none(A_REP,S_NO)));
  2306. case opsize of
  2307. S_B : exprasmlist^.concat(new(pai386,op_none(A_MOVSB,S_NO)));
  2308. S_W : exprasmlist^.concat(new(pai386,op_none(A_MOVSW,S_NO)));
  2309. S_L : exprasmlist^.concat(new(pai386,op_none(A_MOVSD,S_NO)));
  2310. end;
  2311. exprasmlist^.concat(new(pai386,
  2312. op_reg(A_POP,S_L,R_ESI)));
  2313. exprasmlist^.concat(new(pai386,
  2314. op_reg(A_POP,S_L,R_ECX)));
  2315. { patch the new address }
  2316. new(r);
  2317. reset_reference(r^);
  2318. r^.base:=procinfo.framepointer;
  2319. r^.offset:=pvarsym(p)^.address+procinfo.call_offset;
  2320. exprasmlist^.concat(new(pai386,
  2321. op_reg_ref(A_MOV,S_L,R_ESP,r)));
  2322. end
  2323. else
  2324. if is_shortstring(pvarsym(p)^.definition) then
  2325. begin
  2326. reset_reference(href1);
  2327. href1.base:=procinfo.framepointer;
  2328. href1.offset:=pvarsym(p)^.address+procinfo.call_offset;
  2329. reset_reference(href2);
  2330. href2.base:=procinfo.framepointer;
  2331. href2.offset:=-pvarsym(p)^.localvarsym^.address;
  2332. copyshortstring(href2,href1,pstringdef(pvarsym(p)^.definition)^.len,true);
  2333. end
  2334. else
  2335. begin
  2336. reset_reference(href1);
  2337. href1.base:=procinfo.framepointer;
  2338. href1.offset:=pvarsym(p)^.address+procinfo.call_offset;
  2339. reset_reference(href2);
  2340. href2.base:=procinfo.framepointer;
  2341. href2.offset:=-pvarsym(p)^.localvarsym^.address;
  2342. concatcopy(href1,href2,pvarsym(p)^.definition^.size,true,true);
  2343. end;
  2344. end;
  2345. end;
  2346. procedure inittempansistrings;
  2347. var
  2348. hp : ptemprecord;
  2349. r : preference;
  2350. begin
  2351. hp:=templist;
  2352. while assigned(hp) do
  2353. begin
  2354. if hp^.temptype in [tt_ansistring,tt_freeansistring] then
  2355. begin
  2356. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  2357. new(r);
  2358. reset_reference(r^);
  2359. r^.base:=procinfo.framepointer;
  2360. r^.offset:=hp^.pos;
  2361. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_L,0,r)));
  2362. end;
  2363. hp:=hp^.next;
  2364. end;
  2365. end;
  2366. procedure finalizetempansistrings;
  2367. var
  2368. hp : ptemprecord;
  2369. hr : treference;
  2370. begin
  2371. hp:=templist;
  2372. while assigned(hp) do
  2373. begin
  2374. if hp^.temptype in [tt_ansistring,tt_freeansistring] then
  2375. begin
  2376. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  2377. reset_reference(hr);
  2378. hr.base:=procinfo.framepointer;
  2379. hr.offset:=hp^.pos;
  2380. emitpushreferenceaddr(hr);
  2381. exprasmlist^.concat(new(pai386,
  2382. op_sym(A_CALL,S_NO,newasmsymbol('FPC_ANSISTR_DECR_REF'))));
  2383. end;
  2384. hp:=hp^.next;
  2385. end;
  2386. end;
  2387. procedure genentrycode(alist : paasmoutput;const proc_names:Tstringcontainer;make_global:boolean;
  2388. stackframe:longint;
  2389. var parasize:longint;var nostackframe:boolean;
  2390. inlined : boolean);
  2391. {
  2392. Generates the entry code for a procedure
  2393. }
  2394. var
  2395. hs : string;
  2396. {$ifdef GDB}
  2397. stab_function_name : Pai_stab_function_name;
  2398. {$endif GDB}
  2399. hr : preference;
  2400. p : psymtable;
  2401. r : treference;
  2402. oldlist,
  2403. oldexprasmlist : paasmoutput;
  2404. again : pasmlabel;
  2405. i : longint;
  2406. begin
  2407. oldexprasmlist:=exprasmlist;
  2408. exprasmlist:=alist;
  2409. if (not inlined) and ((aktprocsym^.definition^.options and poproginit)<>0) then
  2410. begin
  2411. exprasmlist^.insert(new(pai386,
  2412. op_sym(A_CALL,S_NO,newasmsymbol('FPC_INITIALIZEUNITS'))));
  2413. if target_info.target=target_I386_WIN32 then
  2414. begin
  2415. new(hr);
  2416. reset_reference(hr^);
  2417. hr^.symbol:=newasmsymbol('U_SYSWIN32_ISCONSOLE');
  2418. if apptype=at_cui then
  2419. exprasmlist^.insert(new(pai386,op_const_ref(A_MOV,S_B,
  2420. 1,hr)))
  2421. else
  2422. exprasmlist^.insert(new(pai386,op_const_ref(A_MOV,S_B,
  2423. 0,hr)));
  2424. end;
  2425. oldlist:=exprasmlist;
  2426. exprasmlist:=new(paasmoutput,init);
  2427. p:=symtablestack;
  2428. while assigned(p) do
  2429. begin
  2430. p^.foreach({$ifndef TP}@{$endif}initialize_threadvar);
  2431. p:=p^.next;
  2432. end;
  2433. oldlist^.insertlist(exprasmlist);
  2434. dispose(exprasmlist,done);
  2435. exprasmlist:=oldlist;
  2436. end;
  2437. { a constructor needs a help procedure }
  2438. if (aktprocsym^.definition^.options and poconstructor)<>0 then
  2439. begin
  2440. if procinfo._class^.isclass then
  2441. begin
  2442. exprasmlist^.insert(new(pai386,op_cond_sym(A_Jcc,C_Z,S_NO,quickexitlabel)));
  2443. exprasmlist^.insert(new(pai386,op_sym(A_CALL,S_NO,newasmsymbol('FPC_NEW_CLASS'))));
  2444. end
  2445. else
  2446. begin
  2447. exprasmlist^.insert(new(pai386,op_cond_sym(A_Jcc,C_Z,S_NO,quickexitlabel)));
  2448. exprasmlist^.insert(new(pai386,op_sym(A_CALL,S_NO,newasmsymbol('FPC_HELP_CONSTRUCTOR'))));
  2449. exprasmlist^.insert(new(pai386,op_const_reg(A_MOV,S_L,procinfo._class^.vmt_offset,R_EDI)));
  2450. end;
  2451. end;
  2452. { don't load ESI, does the caller }
  2453. { When message method contains self as a parameter,
  2454. we must load it into ESI }
  2455. If ((aktprocsym^.definition^.options and pocontainsself)<>0) then
  2456. begin
  2457. new(hr);
  2458. reset_reference(hr^);
  2459. hr^.offset:=procinfo.ESI_offset;
  2460. hr^.base:=procinfo.framepointer;
  2461. exprasmlist^.insert(new(pai386,op_ref_reg(A_MOV,S_L,hr,R_ESI)));
  2462. end;
  2463. { should we save edi ? }
  2464. if ((aktprocsym^.definition^.options and posavestdregs)<>0) then
  2465. begin
  2466. if (aktprocsym^.definition^.usedregisters and ($80 shr byte(R_EBX)))<>0 then
  2467. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_L,R_EBX)));
  2468. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_L,R_ESI)));
  2469. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_L,R_EDI)));
  2470. end;
  2471. { omit stack frame ? }
  2472. if not inlined then
  2473. if procinfo.framepointer=stack_pointer then
  2474. begin
  2475. CGMessage(cg_d_stackframe_omited);
  2476. nostackframe:=true;
  2477. if (aktprocsym^.definition^.options and (pounitinit or poproginit or pounitfinalize)<>0) then
  2478. parasize:=0
  2479. else
  2480. parasize:=aktprocsym^.definition^.parast^.datasize+procinfo.call_offset-4;
  2481. end
  2482. else
  2483. begin
  2484. if (aktprocsym^.definition^.options and (pounitinit or poproginit or pounitfinalize)<>0) then
  2485. parasize:=0
  2486. else
  2487. parasize:=aktprocsym^.definition^.parast^.datasize+procinfo.call_offset-8;
  2488. nostackframe:=false;
  2489. if stackframe<>0 then
  2490. begin
  2491. {$ifdef unused}
  2492. if (cs_littlesize in aktglobalswitches) and (stackframe<=65535) then
  2493. begin
  2494. if (cs_check_stack in aktlocalswitches) and
  2495. not(target_info.target in [target_i386_linux,target_i386_win32]) then
  2496. begin
  2497. exprasmlist^.insert(new(pai386,
  2498. op_sym(A_CALL,S_NO,newasmsymbol('FPC_STACKCHECK'))));
  2499. exprasmlist^.insert(new(pai386,op_const(A_PUSH,S_L,stackframe)));
  2500. end;
  2501. if cs_profile in aktmoduleswitches then
  2502. genprofilecode;
  2503. { %edi is already saved when pocdecl is used
  2504. if (target_info.target=target_linux) and
  2505. ((aktprocsym^.definition^.options and poexports)<>0) then
  2506. exprasmlist^.insert(new(Pai386,op_reg(A_PUSH,S_L,R_EDI))); }
  2507. exprasmlist^.insert(new(pai386,op_const_const(A_ENTER,S_NO,stackframe,0)))
  2508. end
  2509. else
  2510. {$endif unused}
  2511. begin
  2512. { windows guards only a few pages for stack growing, }
  2513. { so we have to access every page first }
  2514. if (target_os.id=os_i386_win32) and
  2515. (stackframe>=winstackpagesize) then
  2516. begin
  2517. if stackframe div winstackpagesize<=5 then
  2518. begin
  2519. exprasmlist^.insert(new(pai386,op_const_reg(A_SUB,S_L,stackframe-4,R_ESP)));
  2520. for i:=1 to stackframe div winstackpagesize do
  2521. begin
  2522. hr:=new_reference(R_ESP,stackframe-i*winstackpagesize);
  2523. exprasmlist^.concat(new(pai386,
  2524. op_const_ref(A_MOV,S_L,0,hr)));
  2525. end;
  2526. exprasmlist^.concat(new(pai386,
  2527. op_reg(A_PUSH,S_L,R_EAX)));
  2528. end
  2529. else
  2530. begin
  2531. getlabel(again);
  2532. exprasmlist^.concat(new(pai386,
  2533. op_const_reg(A_MOV,S_L,stackframe div winstackpagesize,R_EDI)));
  2534. emitlab(again);
  2535. exprasmlist^.concat(new(pai386,
  2536. op_const_reg(A_SUB,S_L,winstackpagesize-4,R_ESP)));
  2537. exprasmlist^.concat(new(pai386,
  2538. op_reg(A_PUSH,S_L,R_EAX)));
  2539. exprasmlist^.concat(new(pai386,
  2540. op_reg(A_DEC,S_L,R_EDI)));
  2541. emitjmp(C_NZ,again);
  2542. exprasmlist^.concat(new(pai386,
  2543. op_const_reg(A_SUB,S_L,stackframe mod winstackpagesize,R_ESP)));
  2544. end
  2545. end
  2546. else
  2547. exprasmlist^.insert(new(pai386,op_const_reg(A_SUB,S_L,stackframe,R_ESP)));
  2548. if (cs_check_stack in aktlocalswitches) and
  2549. not(target_info.target in [target_i386_linux,target_i386_win32]) then
  2550. begin
  2551. exprasmlist^.insert(new(pai386,op_sym(A_CALL,S_NO,newasmsymbol('FPC_STACKCHECK'))));
  2552. exprasmlist^.insert(new(pai386,op_const(A_PUSH,S_L,stackframe)));
  2553. end;
  2554. if cs_profile in aktmoduleswitches then
  2555. genprofilecode;
  2556. exprasmlist^.insert(new(pai386,op_reg_reg(A_MOV,S_L,R_ESP,R_EBP)));
  2557. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_L,R_EBP)));
  2558. end;
  2559. end { endif stackframe <> 0 }
  2560. else
  2561. begin
  2562. if cs_profile in aktmoduleswitches then
  2563. genprofilecode;
  2564. exprasmlist^.insert(new(pai386,op_reg_reg(A_MOV,S_L,R_ESP,R_EBP)));
  2565. exprasmlist^.insert(new(pai386,op_reg(A_PUSH,S_L,R_EBP)));
  2566. end;
  2567. end;
  2568. if (aktprocsym^.definition^.options and pointerrupt)<>0 then
  2569. generate_interrupt_stackframe_entry;
  2570. { initialize return value }
  2571. if (procinfo.retdef<>pdef(voiddef)) and
  2572. (procinfo.retdef^.needs_inittable) and
  2573. ((procinfo.retdef^.deftype<>objectdef) or
  2574. not(pobjectdef(procinfo.retdef)^.isclass)) then
  2575. begin
  2576. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  2577. reset_reference(r);
  2578. r.offset:=procinfo.retoffset;
  2579. r.base:=procinfo.framepointer;
  2580. initialize(procinfo.retdef,r,ret_in_param(procinfo.retdef));
  2581. end;
  2582. { generate copies of call by value parameters }
  2583. if (aktprocsym^.definition^.options and poassembler=0) then
  2584. aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}copyvalueparas);
  2585. { initialisizes local data }
  2586. aktprocsym^.definition^.localst^.foreach({$ifndef TP}@{$endif}initialize_data);
  2587. { add a reference to all call by value/const parameters }
  2588. aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}incr_data);
  2589. { initilisizes temp. ansi/wide string data }
  2590. inittempansistrings;
  2591. { do we need an exception frame because of ansi/widestrings ? }
  2592. if (procinfo.flags and pi_needs_implicit_finally)<>0 then
  2593. begin
  2594. usedinproc:=usedinproc or ($80 shr byte(R_EAX));
  2595. { Type of stack-frame must be pushed}
  2596. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,1)));
  2597. emitcall('FPC_PUSHEXCEPTADDR');
  2598. exprasmlist^.concat(new(pai386,
  2599. op_reg(A_PUSH,S_L,R_EAX)));
  2600. emitcall('FPC_SETJMP');
  2601. exprasmlist^.concat(new(pai386,
  2602. op_reg(A_PUSH,S_L,R_EAX)));
  2603. exprasmlist^.concat(new(pai386,
  2604. op_reg_reg(A_TEST,S_L,R_EAX,R_EAX)));
  2605. emitjmp(C_NE,aktexitlabel);
  2606. end;
  2607. if (cs_profile in aktmoduleswitches) or
  2608. (aktprocsym^.definition^.owner^.symtabletype=globalsymtable) or
  2609. (assigned(procinfo._class) and (procinfo._class^.owner^.symtabletype=globalsymtable)) then
  2610. make_global:=true;
  2611. if not inlined then
  2612. begin
  2613. hs:=proc_names.get;
  2614. {$ifdef GDB}
  2615. if (cs_debuginfo in aktmoduleswitches) then
  2616. exprasmlist^.insert(new(pai_force_line,init));
  2617. if (cs_debuginfo in aktmoduleswitches) and target_os.use_function_relative_addresses then
  2618. stab_function_name := new(pai_stab_function_name,init(strpnew(hs)));
  2619. {$EndIf GDB}
  2620. while hs<>'' do
  2621. begin
  2622. if make_global then
  2623. exprasmlist^.insert(new(pai_symbol,initname_global(hs,0)))
  2624. else
  2625. exprasmlist^.insert(new(pai_symbol,initname(hs,0)));
  2626. {$ifdef GDB}
  2627. if (cs_debuginfo in aktmoduleswitches) and
  2628. target_os.use_function_relative_addresses then
  2629. exprasmlist^.insert(new(pai_stab_function_name,init(strpnew(hs))));
  2630. {$endif GDB}
  2631. hs:=proc_names.get;
  2632. end;
  2633. end;
  2634. {$ifdef GDB}
  2635. if (not inlined) and (cs_debuginfo in aktmoduleswitches) then
  2636. begin
  2637. if target_os.use_function_relative_addresses then
  2638. exprasmlist^.insert(stab_function_name);
  2639. if make_global or ((procinfo.flags and pi_is_global) <> 0) then
  2640. aktprocsym^.is_global := True;
  2641. exprasmlist^.insert(new(pai_stabs,init(aktprocsym^.stabstring)));
  2642. aktprocsym^.isstabwritten:=true;
  2643. end;
  2644. {$endif GDB}
  2645. { Align }
  2646. if (not inlined) then
  2647. begin
  2648. { gprof uses 16 byte granularity !! }
  2649. if (cs_profile in aktmoduleswitches) then
  2650. exprasmlist^.insert(new(pai_align,init_op(16,$90)))
  2651. else
  2652. if not(cs_littlesize in aktglobalswitches) then
  2653. exprasmlist^.insert(new(pai_align,init(4)));
  2654. end;
  2655. exprasmlist:=oldexprasmlist;
  2656. end;
  2657. procedure handle_return_value(inlined : boolean);
  2658. var
  2659. hr : preference;
  2660. op : Tasmop;
  2661. s : Topsize;
  2662. begin
  2663. if procinfo.retdef<>pdef(voiddef) then
  2664. begin
  2665. if ((procinfo.flags and pi_operator)<>0) and
  2666. assigned(opsym) then
  2667. procinfo.funcret_is_valid:=
  2668. procinfo.funcret_is_valid or (opsym^.refs>0);
  2669. if not(procinfo.funcret_is_valid) and not inlined { and
  2670. ((procinfo.flags and pi_uses_asm)=0)} then
  2671. CGMessage(sym_w_function_result_not_set);
  2672. hr:=new_reference(procinfo.framepointer,procinfo.retoffset);
  2673. if (procinfo.retdef^.deftype in [orddef,enumdef]) then
  2674. begin
  2675. case procinfo.retdef^.size of
  2676. 8:
  2677. begin
  2678. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hr,R_EAX)));
  2679. hr:=new_reference(procinfo.framepointer,procinfo.retoffset+4);
  2680. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hr,R_EDX)));
  2681. end;
  2682. 4:
  2683. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hr,R_EAX)));
  2684. 2:
  2685. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_W,hr,R_AX)));
  2686. 1:
  2687. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_B,hr,R_AL)));
  2688. end;
  2689. end
  2690. else
  2691. if ret_in_acc(procinfo.retdef) then
  2692. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hr,R_EAX)))
  2693. else
  2694. if (procinfo.retdef^.deftype=floatdef) then
  2695. begin
  2696. floatloadops(pfloatdef(procinfo.retdef)^.typ,op,s);
  2697. exprasmlist^.concat(new(pai386,op_ref(op,s,hr)))
  2698. end
  2699. else
  2700. dispose(hr);
  2701. end
  2702. end;
  2703. procedure genexitcode(alist : paasmoutput;parasize:longint;nostackframe,inlined:boolean);
  2704. var
  2705. {$ifdef GDB}
  2706. mangled_length : longint;
  2707. p : pchar;
  2708. {$endif GDB}
  2709. noreraiselabel : pasmlabel;
  2710. hr : treference;
  2711. oldexprasmlist : paasmoutput;
  2712. begin
  2713. oldexprasmlist:=exprasmlist;
  2714. exprasmlist:=alist;
  2715. if aktexitlabel^.is_used then
  2716. exprasmlist^.insert(new(pai_label,init(aktexitlabel)));
  2717. { call the destructor help procedure }
  2718. if (aktprocsym^.definition^.options and podestructor)<>0 then
  2719. begin
  2720. if procinfo._class^.isclass then
  2721. begin
  2722. exprasmlist^.insert(new(pai386,op_sym(A_CALL,S_NO,
  2723. newasmsymbol('FPC_DISPOSE_CLASS'))));
  2724. end
  2725. else
  2726. begin
  2727. exprasmlist^.insert(new(pai386,op_sym(A_CALL,S_NO,
  2728. newasmsymbol('FPC_HELP_DESTRUCTOR'))));
  2729. exprasmlist^.insert(new(pai386,op_const_reg(A_MOV,S_L,procinfo._class^.vmt_offset,R_EDI)));
  2730. end;
  2731. end;
  2732. { finalize temporary data }
  2733. finalizetempansistrings;
  2734. { finalize local data }
  2735. aktprocsym^.definition^.localst^.foreach({$ifndef TP}@{$endif}finalize_data);
  2736. { finalize paras data }
  2737. if assigned(aktprocsym^.definition^.parast) then
  2738. aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}finalize_data);
  2739. { do we need to handle exceptions because of ansi/widestrings ? }
  2740. if (procinfo.flags and pi_needs_implicit_finally)<>0 then
  2741. begin
  2742. getlabel(noreraiselabel);
  2743. exprasmlist^.concat(new(pai386,
  2744. op_sym(A_CALL,S_NO,newasmsymbol('FPC_POPADDRSTACK'))));
  2745. exprasmlist^.concat(new(pai386,
  2746. op_reg(A_POP,S_L,R_EAX)));
  2747. exprasmlist^.concat(new(pai386,
  2748. op_reg_reg(A_TEST,S_L,R_EAX,R_EAX)));
  2749. emitjmp(C_E,noreraiselabel);
  2750. { must be the return value finalized before reraising the exception? }
  2751. if (procinfo.retdef<>pdef(voiddef)) and
  2752. (procinfo.retdef^.needs_inittable) and
  2753. ((procinfo.retdef^.deftype<>objectdef) or
  2754. not(pobjectdef(procinfo.retdef)^.isclass)) then
  2755. begin
  2756. reset_reference(hr);
  2757. hr.offset:=procinfo.retoffset;
  2758. hr.base:=procinfo.framepointer;
  2759. finalize(procinfo.retdef,hr,ret_in_param(procinfo.retdef));
  2760. end;
  2761. exprasmlist^.concat(new(pai386,
  2762. op_sym(A_CALL,S_NO,newasmsymbol('FPC_RERAISE'))));
  2763. exprasmlist^.concat(new(pai_label,init(noreraiselabel)));
  2764. end;
  2765. { call __EXIT for main program }
  2766. if (not DLLsource) and (not inlined) and ((aktprocsym^.definition^.options and poproginit)<>0) then
  2767. begin
  2768. exprasmlist^.concat(new(pai386,op_sym(A_CALL,S_NO,newasmsymbol('FPC_DO_EXIT'))));
  2769. end;
  2770. { handle return value }
  2771. if (aktprocsym^.definition^.options and poassembler)=0 then
  2772. if (aktprocsym^.definition^.options and poconstructor)=0 then
  2773. handle_return_value(inlined)
  2774. else
  2775. begin
  2776. { successful constructor deletes the zero flag }
  2777. { and returns self in eax }
  2778. exprasmlist^.concat(new(pai_label,init(quickexitlabel)));
  2779. { eax must be set to zero if the allocation failed !!! }
  2780. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,R_ESI,R_EAX)));
  2781. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,R_EAX,R_EAX)));
  2782. end;
  2783. { stabs uses the label also ! }
  2784. if aktexit2label^.is_used or
  2785. ((cs_debuginfo in aktmoduleswitches) and not inlined) then
  2786. exprasmlist^.concat(new(pai_label,init(aktexit2label)));
  2787. { gives problems for long mangled names }
  2788. {list^.concat(new(pai_symbol,init(aktprocsym^.definition^.mangledname+'_end')));}
  2789. { should we restore edi ? }
  2790. { for all i386 gcc implementations }
  2791. if ((aktprocsym^.definition^.options and posavestdregs)<>0) then
  2792. begin
  2793. if (aktprocsym^.definition^.usedregisters and ($80 shr byte(R_EBX)))<>0 then
  2794. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EBX)));
  2795. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_ESI)));
  2796. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDI)));
  2797. { here we could reset R_EBX
  2798. but that is risky because it only works
  2799. if genexitcode is called after genentrycode
  2800. so lets skip this for the moment PM
  2801. aktprocsym^.definition^.usedregisters:=
  2802. aktprocsym^.definition^.usedregisters or not ($80 shr byte(R_EBX));
  2803. }
  2804. end;
  2805. if not(nostackframe) and not inlined then
  2806. exprasmlist^.concat(new(pai386,op_none(A_LEAVE,S_NO)));
  2807. { parameters are limited to 65535 bytes because }
  2808. { ret allows only imm16 }
  2809. if (parasize>65535) and not(aktprocsym^.definition^.options and poclearstack<>0) then
  2810. CGMessage(cg_e_parasize_too_big);
  2811. { at last, the return is generated }
  2812. if not inlined then
  2813. if (aktprocsym^.definition^.options and pointerrupt)<>0 then
  2814. generate_interrupt_stackframe_exit
  2815. else
  2816. begin
  2817. {Routines with the poclearstack flag set use only a ret.}
  2818. { also routines with parasize=0 }
  2819. if (parasize=0) or (aktprocsym^.definition^.options and poclearstack<>0) then
  2820. exprasmlist^.concat(new(pai386,op_none(A_RET,S_NO)))
  2821. else
  2822. exprasmlist^.concat(new(pai386,op_const(A_RET,S_NO,parasize)));
  2823. end;
  2824. exprasmlist^.concat(new(pai_symbol_end,initname(aktprocsym^.definition^.mangledname)));
  2825. {$ifdef GDB}
  2826. if (cs_debuginfo in aktmoduleswitches) and not inlined then
  2827. begin
  2828. aktprocsym^.concatstabto(exprasmlist);
  2829. if assigned(procinfo._class) then
  2830. if (not assigned(procinfo.parent) or
  2831. not assigned(procinfo.parent^._class)) then
  2832. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  2833. '"$t:v'+procinfo._class^.numberstring+'",'+
  2834. tostr(N_PSYM)+',0,0,'+tostr(procinfo.esi_offset)))))
  2835. else
  2836. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  2837. '"$t:r'+procinfo._class^.numberstring+'",'+
  2838. tostr(N_RSYM)+',0,0,'+tostr(GDB_i386index[R_ESI])))));
  2839. if (pdef(aktprocsym^.definition^.retdef) <> pdef(voiddef)) then
  2840. if ret_in_param(aktprocsym^.definition^.retdef) then
  2841. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  2842. '"'+aktprocsym^.name+':X*'+aktprocsym^.definition^.retdef^.numberstring+'",'+
  2843. tostr(N_PSYM)+',0,0,'+tostr(procinfo.retoffset)))))
  2844. else
  2845. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  2846. '"'+aktprocsym^.name+':X'+aktprocsym^.definition^.retdef^.numberstring+'",'+
  2847. tostr(N_PSYM)+',0,0,'+tostr(procinfo.retoffset)))));
  2848. mangled_length:=length(aktprocsym^.definition^.mangledname);
  2849. getmem(p,mangled_length+50);
  2850. strpcopy(p,'192,0,0,');
  2851. strpcopy(strend(p),aktprocsym^.definition^.mangledname);
  2852. exprasmlist^.concat(new(pai_stabn,init(strnew(p))));
  2853. {list^.concat(new(pai_stabn,init(strpnew('192,0,0,'
  2854. +aktprocsym^.definition^.mangledname))));
  2855. p[0]:='2';p[1]:='2';p[2]:='4';
  2856. strpcopy(strend(p),'_end');}
  2857. freemem(p,mangled_length+50);
  2858. exprasmlist^.concat(new(pai_stabn,init(
  2859. strpnew('224,0,0,'+aktexit2label^.name))));
  2860. { strpnew('224,0,0,'
  2861. +aktprocsym^.definition^.mangledname+'_end'))));}
  2862. end;
  2863. {$endif GDB}
  2864. exprasmlist:=oldexprasmlist;
  2865. end;
  2866. {$ifdef test_dest_loc}
  2867. procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
  2868. begin
  2869. if (dest_loc.loc=LOC_CREGISTER) or (dest_loc.loc=LOC_REGISTER) then
  2870. begin
  2871. emit_reg_reg(A_MOV,s,reg,dest_loc.register);
  2872. set_location(p^.location,dest_loc);
  2873. in_dest_loc:=true;
  2874. end
  2875. else
  2876. if (dest_loc.loc=LOC_REFERENCE) or (dest_loc.loc=LOC_MEM) then
  2877. begin
  2878. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,s,reg,newreference(dest_loc.reference))));
  2879. set_location(p^.location,dest_loc);
  2880. in_dest_loc:=true;
  2881. end
  2882. else
  2883. internalerror(20080);
  2884. end;
  2885. {$endif test_dest_loc}
  2886. end.
  2887. {
  2888. $Log$
  2889. Revision 1.22 1999-08-01 23:36:39 florian
  2890. * some changes to compile the new code generator
  2891. Revision 1.21 1999/08/01 17:32:31 florian
  2892. * more fixes for inittable call
  2893. Revision 1.20 1999/08/01 17:17:37 florian
  2894. * tried to fix a bug with init table
  2895. Revision 1.19 1999/07/29 20:53:58 peter
  2896. * write .size also
  2897. Revision 1.18 1999/07/26 12:13:46 florian
  2898. * exit in try..finally blocks needed a second fix
  2899. * a raise in a try..finally lead into a endless loop, fixed
  2900. Revision 1.17 1999/07/22 09:37:38 florian
  2901. + resourcestring implemented
  2902. + start of longstring support
  2903. Revision 1.16 1999/07/18 10:41:59 florian
  2904. * fix of my previous commit nevertheless it doesn't work completly
  2905. Revision 1.15 1999/07/18 10:19:44 florian
  2906. * made it compilable with Dlephi 4 again
  2907. + fixed problem with large stack allocations on win32
  2908. Revision 1.14 1999/07/06 21:48:11 florian
  2909. * a lot bug fixes:
  2910. - po_external isn't any longer necessary for procedure compatibility
  2911. - m_tp_procvar is in -Sd now available
  2912. - error messages of procedure variables improved
  2913. - return values with init./finalization fixed
  2914. - data types with init./finalization aren't any longer allowed in variant
  2915. record
  2916. Revision 1.13 1999/07/05 20:25:22 peter
  2917. * merged
  2918. Revision 1.12 1999/07/05 20:13:13 peter
  2919. * removed temp defines
  2920. Revision 1.11 1999/07/05 11:56:56 jonas
  2921. * merged
  2922. Revision 1.5.2.5 1999/07/05 20:03:31 peter
  2923. * removed warning/notes
  2924. Revision 1.5.2.3 1999/07/04 21:50:17 jonas
  2925. * everything between $ifdef jmpfix:
  2926. * when a jxx instruction is disposed, decrease the refcount of the label
  2927. it referenced
  2928. * for jmp instructions to a label, set is_jmp also to true (was only done
  2929. for Jcc instructions)
  2930. Revision 1.9 1999/07/01 15:49:11 florian
  2931. * int64/qword type release
  2932. + lo/hi for int64/qword
  2933. Revision 1.8 1999/06/28 22:29:15 florian
  2934. * qword division fixed
  2935. + code for qword/int64 type casting added:
  2936. range checking isn't implemented yet
  2937. Revision 1.7 1999/06/17 13:19:50 pierre
  2938. * merged from 0_99_12 branch
  2939. Revision 1.5.2.2 1999/06/17 12:38:39 pierre
  2940. * wrong warning for operators removed
  2941. Revision 1.6 1999/06/14 17:47:48 peter
  2942. * merged
  2943. Revision 1.5.2.1 1999/06/14 17:27:08 peter
  2944. * fixed posavestd regs which popped at the wrong place
  2945. Revision 1.5 1999/06/03 16:21:15 pierre
  2946. * fixes a bug due to int64 code in maybe_savetotemp
  2947. Revision 1.4 1999/06/02 22:44:06 pierre
  2948. * previous wrong log corrected
  2949. Revision 1.3 1999/06/02 22:25:29 pierre
  2950. * changed $ifdef FPC @ into $ifndef TP
  2951. Revision 1.2 1999/06/02 10:11:49 florian
  2952. * make cycle fixed i.e. compilation with 0.99.10
  2953. * some fixes for qword
  2954. * start of register calling conventions
  2955. Revision 1.1 1999/06/01 19:33:18 peter
  2956. * reinserted
  2957. Revision 1.158 1999/06/01 14:45:46 peter
  2958. * @procvar is now always needed for FPC
  2959. Revision 1.157 1999/05/27 19:44:20 peter
  2960. * removed oldasm
  2961. * plabel -> pasmlabel
  2962. * -a switches to source writing automaticly
  2963. * assembler readers OOPed
  2964. * asmsymbol automaticly external
  2965. * jumptables and other label fixes for asm readers
  2966. Revision 1.156 1999/05/24 08:55:24 florian
  2967. * non working safecall directiv implemented, I don't know if we
  2968. need it
  2969. Revision 1.155 1999/05/23 19:55:14 florian
  2970. * qword/int64 multiplication fixed
  2971. + qword/int64 subtraction
  2972. Revision 1.154 1999/05/23 18:42:05 florian
  2973. * better error recovering in typed constants
  2974. * some problems with arrays of const fixed, some problems
  2975. due my previous
  2976. - the location type of array constructor is now LOC_MEM
  2977. - the pushing of high fixed
  2978. - parameter copying fixed
  2979. - zero temp. allocation removed
  2980. * small problem in the assembler writers fixed:
  2981. ref to nil wasn't written correctly
  2982. Revision 1.153 1999/05/21 13:54:55 peter
  2983. * NEWLAB for label as symbol
  2984. Revision 1.152 1999/05/19 22:00:45 florian
  2985. * some new routines for register management:
  2986. maybe_savetotemp,restorefromtemp, saveusedregisters,
  2987. restoreusedregisters
  2988. Revision 1.151 1999/05/19 20:40:11 florian
  2989. * fixed a couple of array related bugs:
  2990. - var a : array[0..1] of char; p : pchar; p:=a+123; works now
  2991. - open arrays with an odd size doesn't work: movsb wasn't generated
  2992. - introduced some new array type helper routines (is_special_array) etc.
  2993. - made the array type checking in isconvertable more strict, often
  2994. open array can be used where is wasn't allowed etc...
  2995. Revision 1.150 1999/05/19 15:26:30 florian
  2996. * if a non local variables isn't initialized the compiler doesn't write
  2997. any longer "local var. seems not to be ..."
  2998. Revision 1.149 1999/05/19 13:59:07 jonas
  2999. * no more "enter" generated when -Og is used (caused sometimes crashes under
  3000. Linux, don't know why)
  3001. Revision 1.148 1999/05/18 21:58:30 florian
  3002. * fixed some bugs related to temp. ansistrings and functions results
  3003. which return records/objects/arrays which need init/final.
  3004. Revision 1.147 1999/05/18 14:15:28 peter
  3005. * containsself fixes
  3006. * checktypes()
  3007. Revision 1.146 1999/05/17 22:42:26 florian
  3008. * FPC_ANSISTR_DECR_REF needs a reference!
  3009. Revision 1.145 1999/05/17 21:57:06 florian
  3010. * new temporary ansistring handling
  3011. Revision 1.144 1999/05/15 21:33:18 peter
  3012. * redesigned temp_gen temp allocation so temp allocation for
  3013. ansistring works correct. It also does a best fit instead of first fit
  3014. Revision 1.143 1999/05/13 21:59:22 peter
  3015. * removed oldppu code
  3016. * warning if objpas is loaded from uses
  3017. * first things for new deref writing
  3018. Revision 1.142 1999/05/12 00:19:46 peter
  3019. * removed R_DEFAULT_SEG
  3020. * uniform float names
  3021. Revision 1.141 1999/05/07 00:33:44 pierre
  3022. explicit type conv to pobject checked with cond TESTOBJEXT2
  3023. Revision 1.140 1999/05/06 09:05:17 peter
  3024. * generic write_float and str_float
  3025. * fixed constant float conversions
  3026. Revision 1.139 1999/05/04 21:44:35 florian
  3027. * changes to compile it with Delphi 4.0
  3028. Revision 1.138 1999/05/02 09:35:36 florian
  3029. + method message handlers which contain an explicit self can't be called
  3030. directly anymore
  3031. + self is now loaded at the start of the an message handler with an explicit
  3032. self
  3033. + $useoverlay fixed: i386 was renamed to i386base
  3034. Revision 1.137 1999/05/01 13:24:16 peter
  3035. * merged nasm compiler
  3036. * old asm moved to oldasm/
  3037. Revision 1.136 1999/04/28 06:01:56 florian
  3038. * changes of Bruessel:
  3039. + message handler can now take an explicit self
  3040. * typinfo fixed: sometimes the type names weren't written
  3041. * the type checking for pointer comparisations and subtraction
  3042. and are now more strict (was also buggy)
  3043. * small bug fix to link.pas to support compiling on another
  3044. drive
  3045. * probable bug in popt386 fixed: call/jmp => push/jmp
  3046. transformation didn't count correctly the jmp references
  3047. + threadvar support
  3048. * warning if ln/sqrt gets an invalid constant argument
  3049. Revision 1.135 1999/04/26 13:31:26 peter
  3050. * release storenumber,double_checksum
  3051. Revision 1.134 1999/04/21 21:53:08 pierre
  3052. * previous log corrected
  3053. Revision 1.133 1999/04/21 16:31:38 pierre
  3054. + TEMPS_NOT_PUSH conditionnal code :
  3055. put needed registers into temp space instead of pushing them
  3056. Revision 1.132 1999/04/21 09:43:30 peter
  3057. * storenumber works
  3058. * fixed some typos in double_checksum
  3059. + incompatible types type1 and type2 message (with storenumber)
  3060. Revision 1.131 1999/04/19 09:45:49 pierre
  3061. + cdecl or stdcall push all args with longint size
  3062. * tempansi stuff cleaned up
  3063. Revision 1.130 1999/04/17 13:14:50 peter
  3064. * concat_external added for new init/final
  3065. Revision 1.129 1999/04/16 20:44:35 florian
  3066. * the boolean operators =;<>;xor with LOC_JUMP and LOC_FLAGS
  3067. operands fixed, small things for new ansistring management
  3068. Revision 1.128 1999/04/16 13:42:31 jonas
  3069. * more regalloc fixes (still not complete)
  3070. Revision 1.127 1999/04/16 10:28:23 pierre
  3071. + added posavestdregs used for cdecl AND stdcall functions
  3072. (saves ESI EDI and EBX for i386)
  3073. Revision 1.126 1999/04/16 09:56:06 pierre
  3074. * unused local var commented
  3075. Revision 1.125 1999/04/15 13:08:30 pierre
  3076. * misplaced statement in concatcopy corrected
  3077. Revision 1.124 1999/04/15 12:19:55 peter
  3078. + finalization support
  3079. Revision 1.123 1999/04/09 00:00:52 pierre
  3080. + uses ungetiftempansi
  3081. Revision 1.122 1999/04/08 15:57:47 peter
  3082. + subrange checking for readln()
  3083. Revision 1.121 1999/03/31 13:55:08 peter
  3084. * assembler inlining working for ag386bin
  3085. Revision 1.120 1999/03/26 00:05:27 peter
  3086. * released valintern
  3087. + deffile is now removed when compiling is finished
  3088. * ^( compiles now correct
  3089. + static directive
  3090. * shrd fixed
  3091. Revision 1.119 1999/03/24 23:16:55 peter
  3092. * fixed bugs 212,222,225,227,229,231,233
  3093. Revision 1.118 1999/03/16 17:52:49 jonas
  3094. * changes for internal Val code (do a "make cycle OPT=-dvalintern" to test)
  3095. * in cgi386inl: also range checking for subrange types (compile with "-dreadrangecheck")
  3096. * in cgai386: also small fixes to emitrangecheck
  3097. Revision 1.117 1999/03/09 19:29:12 peter
  3098. * ecxpushed was not reset in concatcopy
  3099. Revision 1.116 1999/03/09 11:45:40 pierre
  3100. * small arrays and records (size <=4) are copied directly
  3101. Revision 1.115 1999/03/03 12:15:13 pierre
  3102. * U_SYSWIN32_ISCONSOLE adde to external list
  3103. Revision 1.114 1999/03/02 18:21:33 peter
  3104. + flags support for add and case
  3105. Revision 1.113 1999/03/01 15:46:19 peter
  3106. * ag386bin finally make cycles correct
  3107. * prefixes are now also normal opcodes
  3108. Revision 1.112 1999/03/01 13:39:44 pierre
  3109. * temp for int_value const parameters
  3110. Revision 1.111 1999/02/25 21:02:32 peter
  3111. * ag386bin updates
  3112. + coff writer
  3113. Revision 1.110 1999/02/22 02:15:17 peter
  3114. * updates for ag386bin
  3115. Revision 1.109 1999/02/16 00:46:09 peter
  3116. * optimized concatcopy with ecx=1 and ecx=0
  3117. Revision 1.108 1999/02/15 13:13:14 pierre
  3118. * fix for bug0216
  3119. Revision 1.107 1999/02/12 10:43:58 florian
  3120. * internal error 10 with ansistrings fixed
  3121. Revision 1.106 1999/02/03 09:50:22 pierre
  3122. * conditionnal code to try to release temp for consts that are not in memory
  3123. Revision 1.105 1999/02/02 11:47:56 peter
  3124. * fixed ansi2short
  3125. Revision 1.104 1999/01/25 09:29:36 florian
  3126. * very rare problem with in-operator fixed, mainly it was a problem of
  3127. emit_to_reg32 (typo in case ranges)
  3128. Revision 1.103 1999/01/21 22:10:42 peter
  3129. * fixed array of const
  3130. * generic platform independent high() support
  3131. Revision 1.102 1999/01/19 10:19:00 florian
  3132. * bug with mul. of dwords fixed, reported by Alexander Stohr
  3133. * some changes to compile with TP
  3134. + small enhancements for the new code generator
  3135. Revision 1.101 1999/01/15 11:36:48 pierre
  3136. * double temp disallocation on ansistring removed
  3137. Revision 1.100 1998/12/30 13:41:08 peter
  3138. * released valuepara
  3139. Revision 1.99 1998/12/22 13:11:00 florian
  3140. * memory leaks for ansistring type casts fixed
  3141. Revision 1.98 1998/12/19 00:23:46 florian
  3142. * ansistring memory leaks fixed
  3143. Revision 1.97 1998/12/11 16:10:08 florian
  3144. + shifting for 64 bit ints added
  3145. * bug in getexplicitregister32 fixed: usableregs wasn't decremented !!
  3146. Revision 1.96 1998/12/11 00:03:11 peter
  3147. + globtype,tokens,version unit splitted from globals
  3148. Revision 1.95 1998/12/10 09:47:19 florian
  3149. + basic operations with int64/qord (compiler with -dint64)
  3150. + rtti of enumerations extended: names are now written
  3151. Revision 1.94 1998/12/03 10:17:27 peter
  3152. * target_os.use_bound_instruction boolean
  3153. Revision 1.93 1998/11/30 19:48:56 peter
  3154. * some more rangecheck fixes
  3155. Revision 1.92 1998/11/30 16:34:44 pierre
  3156. * corrected problems with rangecheck
  3157. + added needed code for no rangecheck in CRC32 functions in ppu unit
  3158. * enumdef lso need its rangenr reset to zero
  3159. when calling reset_global_defs
  3160. Revision 1.91 1998/11/30 09:43:07 pierre
  3161. * some range check bugs fixed (still not working !)
  3162. + added DLL writing support for win32 (also accepts variables)
  3163. + TempAnsi for code that could be used for Temporary ansi strings
  3164. handling
  3165. Revision 1.90 1998/11/29 12:43:45 peter
  3166. * commented the fpc_init_stack_check becuase it is not in the RTL
  3167. Revision 1.89 1998/11/27 14:50:34 peter
  3168. + open strings, $P switch support
  3169. Revision 1.88 1998/11/26 21:33:07 peter
  3170. * rangecheck updates
  3171. Revision 1.87 1998/11/26 13:10:41 peter
  3172. * new int - int conversion -dNEWCNV
  3173. * some function renamings
  3174. Revision 1.86 1998/11/26 09:53:37 florian
  3175. * for classes no init/final. code is necessary, fixed
  3176. Revision 1.85 1998/11/20 15:35:56 florian
  3177. * problems with rtti fixed, hope it works
  3178. Revision 1.84 1998/11/18 17:45:25 peter
  3179. * fixes for VALUEPARA
  3180. Revision 1.83 1998/11/18 15:44:12 peter
  3181. * VALUEPARA for tp7 compatible value parameters
  3182. Revision 1.82 1998/11/17 00:36:41 peter
  3183. * more ansistring fixes
  3184. Revision 1.81 1998/11/16 19:23:33 florian
  3185. * isconsole is now set by win32 applications
  3186. Revision 1.80 1998/11/16 15:35:40 peter
  3187. * rename laod/copystring -> load/copyshortstring
  3188. * fixed int-bool cnv bug
  3189. + char-ansistring conversion
  3190. Revision 1.79 1998/11/16 11:28:56 pierre
  3191. * stackcheck removed for i386_win32
  3192. * exportlist does not crash at least !!
  3193. (was need for tests dir !)z
  3194. Revision 1.78 1998/11/15 16:32:34 florian
  3195. * some stuff of Pavel implement (win32 dll creation)
  3196. * bug with ansistring function results fixed
  3197. Revision 1.77 1998/11/13 15:40:17 pierre
  3198. + added -Se in Makefile cvstest target
  3199. + lexlevel cleanup
  3200. normal_function_level main_program_level and unit_init_level defined
  3201. * tins_cache grown to A_EMMS (gave range check error in asm readers)
  3202. (test added in code !)
  3203. * -Un option was wrong
  3204. * _FAIL and _SELF only keyword inside
  3205. constructors and methods respectively
  3206. Revision 1.76 1998/11/12 16:43:33 florian
  3207. * functions with ansi strings as result didn't work, solved
  3208. Revision 1.75 1998/11/12 11:19:44 pierre
  3209. * fix for first line of function break
  3210. Revision 1.74 1998/11/12 09:46:18 pierre
  3211. + break main stops before calls to unit inits
  3212. + break at constructors stops before call to FPC_NEW_CLASS
  3213. or FPC_HELP_CONSTRUCTOR
  3214. Revision 1.73 1998/11/10 10:50:55 pierre
  3215. * temporary fix for long mangled procsym names
  3216. Revision 1.72 1998/11/05 12:02:40 peter
  3217. * released useansistring
  3218. * removed -Sv, its now available in fpc modes
  3219. Revision 1.71 1998/10/29 15:42:45 florian
  3220. + partial disposing of temp. ansistrings
  3221. Revision 1.70 1998/10/25 23:32:49 peter
  3222. * fixed unsigned mul
  3223. Revision 1.69 1998/10/20 13:11:33 peter
  3224. + def_getreg to get a register with the same size as definition
  3225. Revision 1.68 1998/10/20 08:06:48 pierre
  3226. * several memory corruptions due to double freemem solved
  3227. => never use p^.loc.location:=p^.left^.loc.location;
  3228. + finally I added now by default
  3229. that ra386dir translates global and unit symbols
  3230. + added a first field in tsymtable and
  3231. a nextsym field in tsym
  3232. (this allows to obtain ordered type info for
  3233. records and objects in gdb !)
  3234. Revision 1.67 1998/10/16 13:12:50 pierre
  3235. * added vmt_offsets in destructors code also !!!
  3236. * vmt_offset code for m68k
  3237. Revision 1.66 1998/10/16 08:48:40 peter
  3238. * fixed some misplaced $endif GDB
  3239. Revision 1.65 1998/10/15 12:37:40 pierre
  3240. + passes vmt offset to HELP_CONSTRUCTOR for objects
  3241. Revision 1.64 1998/10/13 16:50:13 pierre
  3242. * undid some changes of Peter that made the compiler wrong
  3243. for m68k (I had to reinsert some ifdefs)
  3244. * removed several memory leaks under m68k
  3245. * removed the meory leaks for assembler readers
  3246. * cross compiling shoud work again better
  3247. ( crosscompiling sysamiga works
  3248. but as68k still complain about some code !)
  3249. Revision 1.63 1998/10/13 13:10:13 peter
  3250. * new style for m68k/i386 infos and enums
  3251. Revision 1.62 1998/10/08 17:17:17 pierre
  3252. * current_module old scanner tagged as invalid if unit is recompiled
  3253. + added ppheap for better info on tracegetmem of heaptrc
  3254. (adds line column and file index)
  3255. * several memory leaks removed ith help of heaptrc !!
  3256. Revision 1.61 1998/10/08 13:48:41 peter
  3257. * fixed memory leaks for do nothing source
  3258. * fixed unit interdependency
  3259. Revision 1.60 1998/10/07 10:37:43 peter
  3260. * fixed stabs
  3261. Revision 1.59 1998/10/06 17:16:45 pierre
  3262. * some memory leaks fixed (thanks to Peter for heaptrc !)
  3263. Revision 1.58 1998/10/05 21:33:16 peter
  3264. * fixed 161,165,166,167,168
  3265. Revision 1.57 1998/10/01 09:22:54 peter
  3266. * fixed value openarray
  3267. * ungettemp of arrayconstruct
  3268. Revision 1.56 1998/09/28 16:57:19 pierre
  3269. * changed all length(p^.value_str^) into str_length(p)
  3270. to get it work with and without ansistrings
  3271. * changed sourcefiles field of tmodule to a pointer
  3272. Revision 1.55 1998/09/28 16:18:15 florian
  3273. * two fixes to get ansi strings work
  3274. Revision 1.54 1998/09/20 17:46:49 florian
  3275. * some things regarding ansistrings fixed
  3276. Revision 1.53 1998/09/20 09:38:44 florian
  3277. * hasharray for defs fixed
  3278. * ansistring code generation corrected (init/final, assignement)
  3279. Revision 1.52 1998/09/17 09:42:31 peter
  3280. + pass_2 for cg386
  3281. * Message() -> CGMessage() for pass_1/pass_2
  3282. Revision 1.51 1998/09/14 10:44:05 peter
  3283. * all internal RTL functions start with FPC_
  3284. Revision 1.50 1998/09/07 18:46:01 peter
  3285. * update smartlinking, uses getdatalabel
  3286. * renamed ptree.value vars to value_str,value_real,value_set
  3287. Revision 1.49 1998/09/05 22:10:52 florian
  3288. + switch -vb
  3289. * while/repeat loops accept now also word/longbool conditions
  3290. * makebooltojump did an invalid ungetregister32, fixed
  3291. Revision 1.48 1998/09/04 08:41:52 peter
  3292. * updated some error CGMessages
  3293. Revision 1.47 1998/09/03 17:08:41 pierre
  3294. * better lines for stabs
  3295. (no scroll back to if before else part
  3296. no return to case line at jump outside case)
  3297. + source lines also if not in order
  3298. Revision 1.46 1998/09/03 16:03:16 florian
  3299. + rtti generation
  3300. * init table generation changed
  3301. Revision 1.45 1998/09/01 12:48:03 peter
  3302. * use pdef^.size instead of orddef^.typ
  3303. Revision 1.44 1998/09/01 09:07:11 peter
  3304. * m68k fixes, splitted cg68k like cgi386
  3305. Revision 1.43 1998/08/21 08:40:52 pierre
  3306. * EBX,EDI,ESI saved for CDECL on all i386 targets
  3307. Revision 1.42 1998/08/19 16:07:41 jonas
  3308. * changed optimizer switches + cleanup of DestroyRefs in daopt386.pas
  3309. Revision 1.41 1998/08/19 00:40:43 peter
  3310. * small crash prevention
  3311. Revision 1.40 1998/08/17 10:10:06 peter
  3312. - removed OLDPPU
  3313. Revision 1.39 1998/08/15 16:51:39 peter
  3314. * save also esi,ebx for cdecl procedures
  3315. Revision 1.38 1998/08/14 18:18:42 peter
  3316. + dynamic set contruction
  3317. * smallsets are now working (always longint size)
  3318. Revision 1.37 1998/08/11 00:00:30 peter
  3319. * fixed dup log
  3320. Revision 1.36 1998/08/10 14:49:52 peter
  3321. + localswitches, moduleswitches, globalswitches splitting
  3322. Revision 1.35 1998/08/05 16:00:11 florian
  3323. * some fixes for ansi strings
  3324. Revision 1.34 1998/07/30 11:18:14 florian
  3325. + first implementation of try ... except on .. do end;
  3326. * limitiation of 65535 bytes parameters for cdecl removed
  3327. Revision 1.33 1998/07/27 21:57:12 florian
  3328. * fix to allow tv like stream registration:
  3329. @tmenu.load doesn't work if load had parameters or if load was only
  3330. declared in an anchestor class of tmenu
  3331. Revision 1.32 1998/07/27 11:23:40 florian
  3332. + procedures with the directive cdecl and with target linux save now
  3333. the register EDI (like GCC procedures).
  3334. Revision 1.31 1998/07/20 18:40:11 florian
  3335. * handling of ansi string constants should now work
  3336. Revision 1.30 1998/07/18 22:54:26 florian
  3337. * some ansi/wide/longstring support fixed:
  3338. o parameter passing
  3339. o returning as result from functions
  3340. Revision 1.29 1998/07/06 13:21:13 michael
  3341. + Fixed Initialization/Finalizarion calls
  3342. Revision 1.28 1998/06/25 08:48:11 florian
  3343. * first version of rtti support
  3344. Revision 1.27 1998/06/24 14:48:32 peter
  3345. * ifdef newppu -> ifndef oldppu
  3346. Revision 1.26 1998/06/16 08:56:19 peter
  3347. + targetcpu
  3348. * cleaner pmodules for newppu
  3349. Revision 1.25 1998/06/08 13:13:40 pierre
  3350. + temporary variables now in temp_gen.pas unit
  3351. because it is processor independent
  3352. * mppc68k.bat modified to undefine i386 and support_mmx
  3353. (which are defaults for i386)
  3354. Revision 1.24 1998/06/07 15:30:23 florian
  3355. + first working rtti
  3356. + data init/final. for local variables
  3357. Revision 1.23 1998/06/05 17:49:53 peter
  3358. * cleanup of cgai386
  3359. Revision 1.22 1998/06/04 09:55:34 pierre
  3360. * demangled name of procsym reworked to become
  3361. independant of the mangling scheme
  3362. Revision 1.21 1998/06/03 22:48:51 peter
  3363. + wordbool,longbool
  3364. * rename bis,von -> high,low
  3365. * moved some systemunit loading/creating to psystem.pas
  3366. Revision 1.20 1998/05/30 14:31:03 peter
  3367. + $ASMMODE
  3368. Revision 1.19 1998/05/23 01:21:02 peter
  3369. + aktasmmode, aktoptprocessor, aktoutputformat
  3370. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  3371. + $LIBNAME to set the library name where the unit will be put in
  3372. * splitted cgi386 a bit (codeseg to large for bp7)
  3373. * nasm, tasm works again. nasm moved to ag386nsm.pas
  3374. Revision 1.18 1998/05/20 09:42:32 pierre
  3375. + UseTokenInfo now default
  3376. * unit in interface uses and implementation uses gives error now
  3377. * only one error for unknown symbol (uses lastsymknown boolean)
  3378. the problem came from the label code !
  3379. + first inlined procedures and function work
  3380. (warning there might be allowed cases were the result is still wrong !!)
  3381. * UseBrower updated gives a global list of all position of all used symbols
  3382. with switch -gb
  3383. Revision 1.17 1998/05/11 13:07:53 peter
  3384. + $ifdef NEWPPU for the new ppuformat
  3385. + $define GDB not longer required
  3386. * removed all warnings and stripped some log comments
  3387. * no findfirst/findnext anymore to remove smartlink *.o files
  3388. Revision 1.16 1998/05/07 00:17:00 peter
  3389. * smartlinking for sets
  3390. + consts labels are now concated/generated in hcodegen
  3391. * moved some cpu code to cga and some none cpu depended code from cga
  3392. to tree and hcodegen and cleanup of hcodegen
  3393. * assembling .. output reduced for smartlinking ;)
  3394. Revision 1.15 1998/05/06 08:38:35 pierre
  3395. * better position info with UseTokenInfo
  3396. UseTokenInfo greatly simplified
  3397. + added check for changed tree after first time firstpass
  3398. (if we could remove all the cases were it happen
  3399. we could skip all firstpass if firstpasscount > 1)
  3400. Only with ExtDebug
  3401. Revision 1.14 1998/05/04 17:54:24 peter
  3402. + smartlinking works (only case jumptable left todo)
  3403. * redesign of systems.pas to support assemblers and linkers
  3404. + Unitname is now also in the PPU-file, increased version to 14
  3405. Revision 1.13 1998/05/01 16:38:43 florian
  3406. * handling of private and protected fixed
  3407. + change_keywords_to_tp implemented to remove
  3408. keywords which aren't supported by tp
  3409. * break and continue are now symbols of the system unit
  3410. + widestring, longstring and ansistring type released
  3411. Revision 1.12 1998/05/01 07:43:52 florian
  3412. + basics for rtti implemented
  3413. + switch $m (generate rtti for published sections)
  3414. Revision 1.11 1998/04/29 13:41:17 peter
  3415. + assembler functions are not profiled
  3416. Revision 1.10 1998/04/29 10:33:47 pierre
  3417. + added some code for ansistring (not complete nor working yet)
  3418. * corrected operator overloading
  3419. * corrected nasm output
  3420. + started inline procedures
  3421. + added starstarn : use ** for exponentiation (^ gave problems)
  3422. + started UseTokenInfo cond to get accurate positions
  3423. Revision 1.9 1998/04/21 10:16:46 peter
  3424. * patches from strasbourg
  3425. * objects is not used anymore in the fpc compiled version
  3426. Revision 1.8 1998/04/13 08:42:50 florian
  3427. * call by reference and call by value open arrays fixed
  3428. Revision 1.7 1998/04/09 23:27:26 peter
  3429. * fixed profiling results
  3430. Revision 1.6 1998/04/09 14:28:03 jonas
  3431. + basic k6 and 6x86 optimizing support (-O7 and -O8)
  3432. Revision 1.5 1998/04/08 16:58:01 pierre
  3433. * several bugfixes
  3434. ADD ADC and AND are also sign extended
  3435. nasm output OK (program still crashes at end
  3436. and creates wrong assembler files !!)
  3437. procsym types sym in tdef removed !!
  3438. }